From 4abbf8879f44d80f106cdf6c4fde5edda6488077 Mon Sep 17 00:00:00 2001 From: Cyd Date: Tue, 30 Jun 2026 07:59:51 -0500 Subject: [PATCH] Initial import of Red Planet v4.10 Win32 source Imports the current Win32 source for the pod-racing game 'Red Planet', built on the MUNGA engine and its L4 (Win32/DirectX) platform layer: - MUNGA / MUNGA_L4: cross-platform engine core and Win32 backend - RP / RP_L4: Red Planet game logic and Win32 application - DivLoader, Setup1: asset loader and installer project - lib, MUNGA_L4/openal, MUNGA_L4/sos: third-party audio dependencies Removed stale Subversion metadata and added .gitignore/.gitattributes. Co-Authored-By: Claude Opus 4.8 --- .gitattributes | 30 + .gitignore | 48 + DPLSTUB.h | 40 + DivLoader/DivLoader.vcproj | 172 + DivLoader/VGCDivLoader.cpp | 1387 +++ DivLoader/VGCDivLoader.h | 240 + DivLoader/tagIdents.h | 89 + LOGGER.cpp | 25 + LOGGER.h | 13 + MUNGA/AFFNMTRX.cpp | 785 ++ MUNGA/AFFNMTRX.h | 145 + MUNGA/ANGLE.cpp | 167 + MUNGA/ANGLE.h | 228 + MUNGA/ANIMTOOL.cpp | 1088 ++ MUNGA/APP.cpp | 1777 +++ MUNGA/APP.h | 764 ++ MUNGA/APPMGR.cpp | 219 + MUNGA/APPMGR.h | 34 + MUNGA/APPMSG.cpp | 46 + MUNGA/APPMSG.h | 223 + MUNGA/APPTASK.cpp | 185 + MUNGA/APPTASK.h | 153 + MUNGA/AUDCMP.cpp | 1523 +++ MUNGA/AUDCMP.h | 720 ++ MUNGA/AUDENT.cpp | 177 + MUNGA/AUDENT.h | 72 + MUNGA/AUDIO.cpp | 474 + MUNGA/AUDIO.h | 655 ++ MUNGA/AUDLOC.cpp | 508 + MUNGA/AUDLOC.h | 202 + MUNGA/AUDLVL.cpp | 450 + MUNGA/AUDLVL.h | 247 + MUNGA/AUDMIDI.cpp | 690 ++ MUNGA/AUDMIDI.h | 147 + MUNGA/AUDREND.cpp | 513 + MUNGA/AUDREND.h | 250 + MUNGA/AUDSEQ.cpp | 868 ++ MUNGA/AUDSEQ.h | 244 + MUNGA/AUDSRC.cpp | 817 ++ MUNGA/AUDSRC.h | 664 ++ MUNGA/AUDTIME.cpp | 54 + MUNGA/AUDTIME.h | 258 + MUNGA/AUDTOOLS.cpp | 102 + MUNGA/AUDTOOLS.h | 19 + MUNGA/AUDWGT.cpp | 12 + MUNGA/AUDWGT.h | 128 + MUNGA/AUDWTHR.cpp | 1048 ++ MUNGA/AUDWTHR.h | 1557 +++ MUNGA/AVERAGE.cpp | 4 + MUNGA/AVERAGE.h | 298 + MUNGA/BNDGBOX.cpp | 435 + MUNGA/BNDGBOX.h | 195 + MUNGA/BOXCONE.cpp | 464 + MUNGA/BOXDISKS.cpp | 1773 +++ MUNGA/BOXIRAMP.cpp | 911 ++ MUNGA/BOXLIST.cpp | 311 + MUNGA/BOXLIST.h | 147 + MUNGA/BOXRAMP.cpp | 924 ++ MUNGA/BOXSOLID.cpp | 1406 +++ MUNGA/BOXSOLID.h | 976 ++ MUNGA/BOXSORT.cpp | 474 + MUNGA/BOXSPHR.cpp | 235 + MUNGA/BOXTILE.cpp | 641 ++ MUNGA/BOXTREE.cpp | 1340 +++ MUNGA/BOXTREE.h | 208 + MUNGA/BOXWEDGE.cpp | 872 ++ MUNGA/CAMINST.cpp | 567 + MUNGA/CAMINST.h | 173 + MUNGA/CAMMGR.cpp | 748 ++ MUNGA/CAMMGR.h | 106 + MUNGA/CAMMPPR.cpp | 244 + MUNGA/CAMMPPR.h | 110 + MUNGA/CAMSHIP.cpp | 732 ++ MUNGA/CAMSHIP.h | 202 + MUNGA/CHAIN.cpp | 451 + MUNGA/CHAIN.h | 157 + MUNGA/CMPNNT.cpp | 59 + MUNGA/CMPNNT.h | 22 + MUNGA/COLLASST.cpp | 367 + MUNGA/COLLASST.h | 180 + MUNGA/COLLORGN.cpp | 144 + MUNGA/COLLORGN.h | 50 + MUNGA/COLOR.cpp | 68 + MUNGA/COLOR.h | 92 + MUNGA/CONFIG.h | 151 + MUNGA/CONSOLE.cpp | 85 + MUNGA/CONSOLE.h | 281 + MUNGA/CONTROLS.cpp | 660 ++ MUNGA/CONTROLS.h | 910 ++ MUNGA/CSTR.cpp | 444 + MUNGA/CSTR.h | 644 ++ MUNGA/CULTURAL.cpp | 1073 ++ MUNGA/DAMAGE.cpp | 800 ++ MUNGA/DAMAGE.h | 384 + MUNGA/DEBUG1ON.h | 134 + MUNGA/DEBUGOFF.h | 63 + MUNGA/DIRECTOR.cpp | 309 + MUNGA/DIRECTOR.h | 157 + MUNGA/DOOR.cpp | 537 + MUNGA/DOOR.h | 164 + MUNGA/DOORFRAM.cpp | 278 + MUNGA/DOORFRAM.h | 52 + MUNGA/DROPZONE.cpp | 447 + MUNGA/DROPZONE.h | 152 + MUNGA/ENTITY.cpp | 1571 +++ MUNGA/ENTITY.h | 621 + MUNGA/ENTITY2.cpp | 80 + MUNGA/ENTITY2.h | 118 + MUNGA/ENTITY3.h | 324 + MUNGA/ENTITYID.cpp | 209 + MUNGA/ENTITYID.h | 61 + MUNGA/ENVIRNMT.cpp | 97 + MUNGA/ENVIRNMT.h | 76 + MUNGA/EVENT.cpp | 1079 ++ MUNGA/EVENT.h | 342 + MUNGA/EVTSTAT.cpp | 143 + MUNGA/EVTSTAT.h | 58 + MUNGA/EXPLODE.cpp | 773 ++ MUNGA/EXPLODE.h | 187 + MUNGA/EXPTBL.cpp | 605 + MUNGA/EXPTBL.h | 209 + MUNGA/EXTNTBOX.cpp | 251 + MUNGA/EXTNTBOX.h | 60 + MUNGA/EYECANDY.cpp | 236 + MUNGA/EYECANDY.h | 102 + MUNGA/FILESTRM.cpp | 122 + MUNGA/FILESTRM.h | 44 + MUNGA/FILESTUB.cpp | 80 + MUNGA/FILEUTIL.cpp | 825 ++ MUNGA/FILEUTIL.h | 76 + MUNGA/GAUGALRM.cpp | 406 + MUNGA/GAUGALRM.h | 58 + MUNGA/GAUGE.cpp | 779 ++ MUNGA/GAUGE.h | 403 + MUNGA/GAUGMAP.cpp | 736 ++ MUNGA/GAUGMAP.h | 137 + MUNGA/GAUGREND.cpp | 4196 +++++++ MUNGA/GAUGREND.h | 710 ++ MUNGA/GRAPH2D.cpp | 3103 +++++ MUNGA/GRAPH2D.h | 772 ++ MUNGA/HASH.cpp | 531 + MUNGA/HASH.h | 132 + MUNGA/HOST.cpp | 139 + MUNGA/HOST.h | 186 + MUNGA/HOSTID.h | 9 + MUNGA/HOSTMGR.cpp | 697 ++ MUNGA/HOSTMGR.h | 367 + MUNGA/ICOM.cpp | 475 + MUNGA/ICOM.h | 179 + MUNGA/INTEREST.cpp | 2587 +++++ MUNGA/INTEREST.h | 571 + MUNGA/INTORGN.cpp | 151 + MUNGA/INTORGN.h | 176 + MUNGA/ITERATOR.cpp | 154 + MUNGA/ITERATOR.h | 64 + MUNGA/JMOVER.cpp | 2044 ++++ MUNGA/JMOVER.h | 245 + MUNGA/JOINT.cpp | 513 + MUNGA/JOINT.h | 271 + MUNGA/LAMP.cpp | 363 + MUNGA/LAMP.h | 172 + MUNGA/LATTICE.cpp | 692 ++ MUNGA/LATTICE.h | 480 + MUNGA/LINE.cpp | 72 + MUNGA/LINE.h | 33 + MUNGA/LINK.cpp | 89 + MUNGA/LINK.h | 34 + MUNGA/LINMTRX.cpp | 138 + MUNGA/LINMTRX.h | 119 + MUNGA/MAPTOOL.cpp | 987 ++ MUNGA/MATRIX.cpp | 711 ++ MUNGA/MATRIX.h | 180 + MUNGA/MEMBLOCK.cpp | 658 ++ MUNGA/MEMBLOCK.h | 108 + MUNGA/MEMREG.cpp | 654 ++ MUNGA/MEMREG.h | 76 + MUNGA/MEMSTRM.CPP | 180 + MUNGA/MEMSTRM.H | 141 + MUNGA/MISSION.cpp | 623 + MUNGA/MISSION.h | 274 + MUNGA/MODE.cpp | 59 + MUNGA/MODE.h | 66 + MUNGA/MODTOOL.cpp | 637 ++ MUNGA/MOTION.cpp | 78 + MUNGA/MOTION.h | 53 + MUNGA/MOVER.cpp | 2084 ++++ MUNGA/MOVER.h | 463 + MUNGA/MTRXSTK.cpp | 42 + MUNGA/MTRXSTK.h | 123 + MUNGA/MUNGA.h | 50 + MUNGA/NAMELIST.cpp | 448 + MUNGA/NAMELIST.h | 165 + MUNGA/NETWORK.cpp | 440 + MUNGA/NETWORK.h | 281 + MUNGA/NODE.cpp | 22 + MUNGA/NODE.h | 17 + MUNGA/NORMAL.cpp | 41 + MUNGA/NORMAL.h | 72 + MUNGA/NOTATION.cpp | 2110 ++++ MUNGA/NOTATION.h | 194 + MUNGA/NTTMGR.cpp | 216 + MUNGA/NTTMGR.h | 107 + MUNGA/OBJSTRM.cpp | 1203 ++ MUNGA/OBJSTRM.h | 333 + MUNGA/ORIGIN.cpp | 116 + MUNGA/ORIGIN.h | 80 + MUNGA/PLANE.cpp | 192 + MUNGA/PLANE.h | 76 + MUNGA/PLAYER.cpp | 876 ++ MUNGA/PLAYER.h | 461 + MUNGA/PLUG.cpp | 490 + MUNGA/PLUG.h | 144 + MUNGA/POINT3D.cpp | 56 + MUNGA/POINT3D.h | 126 + MUNGA/RANDOM.cpp | 176 + MUNGA/RANDOM.h | 53 + MUNGA/RAY.cpp | 168 + MUNGA/RAY.h | 48 + MUNGA/RECEIVER.cpp | 645 ++ MUNGA/RECEIVER.h | 546 + MUNGA/RECT2D.cpp | 138 + MUNGA/RECT2D.h | 49 + MUNGA/REGISTRY.cpp | 679 ++ MUNGA/REGISTRY.h | 163 + MUNGA/RENDERER.cpp | 1031 ++ MUNGA/RENDERER.h | 740 ++ MUNGA/RESOURCE.cpp | 911 ++ MUNGA/RESOURCE.h | 409 + MUNGA/RESVER.h | 3 + MUNGA/RETICLE.cpp | 104 + MUNGA/RETICLE.h | 64 + MUNGA/RNDORGN.cpp | 187 + MUNGA/RNDORGN.h | 96 + MUNGA/ROTATION.cpp | 1338 +++ MUNGA/ROTATION.h | 307 + MUNGA/SCALAR.cpp | 167 + MUNGA/SCALAR.h | 31 + MUNGA/SCHAIN.cpp | 483 + MUNGA/SCHAIN.h | 129 + MUNGA/SCNROLE.cpp | 235 + MUNGA/SCNROLE.h | 116 + MUNGA/SEGMENT.cpp | 273 + MUNGA/SEGMENT.h | 239 + MUNGA/SET.cpp | 144 + MUNGA/SET.h | 261 + MUNGA/SFESKT.cpp | 150 + MUNGA/SFESKT.h | 49 + MUNGA/SIMULATE.cpp | 715 ++ MUNGA/SIMULATE.h | 387 + MUNGA/SLOT.cpp | 167 + MUNGA/SLOT.h | 65 + MUNGA/SOCKET.cpp | 256 + MUNGA/SOCKET.h | 67 + MUNGA/SPHERE.cpp | 40 + MUNGA/SPHERE.h | 25 + MUNGA/SPLINE.cpp | 114 + MUNGA/SPLINE.h | 31 + MUNGA/SPOOLER.cpp | 311 + MUNGA/SPOOLER.h | 66 + MUNGA/SRTSKT.cpp | 44 + MUNGA/SRTSKT.h | 39 + MUNGA/STATE.h | 62 + MUNGA/STYLE.H | 139 + MUNGA/SUBSYSTM.cpp | 291 + MUNGA/SUBSYSTM.h | 179 + MUNGA/TABLE.cpp | 791 ++ MUNGA/TABLE.h | 273 + MUNGA/TEAM.cpp | 203 + MUNGA/TEAM.h | 178 + MUNGA/TERRAIN.cpp | 303 + MUNGA/TERRAIN.h | 164 + MUNGA/TESTALL.cpp | 166 + MUNGA/TIME.cpp | 117 + MUNGA/TIME.h | 170 + MUNGA/TIMESTUB.cpp | 44 + MUNGA/TOOL.cpp | 862 ++ MUNGA/TOOL.h | 224 + MUNGA/TRACE.cpp | 566 + MUNGA/TRACE.h | 297 + MUNGA/TRACSTUB.cpp | 22 + MUNGA/TREE.cpp | 845 ++ MUNGA/TREE.h | 262 + MUNGA/UNITVEC.cpp | 36 + MUNGA/UNITVEC.h | 64 + MUNGA/UPDATE.cpp | 242 + MUNGA/UPDATE.h | 64 + MUNGA/VCHAIN.cpp | 631 + MUNGA/VCHAIN.h | 295 + MUNGA/VDATA.cpp | 97 + MUNGA/VDATA.h | 303 + MUNGA/VECTOR2D.h | 286 + MUNGA/VECTOR3D.cpp | 326 + MUNGA/VECTOR3D.h | 267 + MUNGA/VECTOR4D.cpp | 365 + MUNGA/VECTOR4D.h | 204 + MUNGA/VERIFY.cpp | 198 + MUNGA/VERIFY.h | 41 + MUNGA/VIDREND.cpp | 261 + MUNGA/VIDREND.h | 108 + MUNGA/WATCHER.cpp | 192 + MUNGA/WATCHER.h | 311 + MUNGA/WRHOUS.cpp | 167 + MUNGA/WRHOUS.h | 452 + MUNGA/cultural.h | 352 + MUNGA_L4/DXUtils.cpp | 33 + MUNGA_L4/DXUtils.h | 45 + MUNGA_L4/JOYSTICK.asm | 147 + MUNGA_L4/L4APP.H | 232 + MUNGA_L4/L4APP.cpp | 904 ++ MUNGA_L4/L4AUDHDW.cpp | 990 ++ MUNGA_L4/L4AUDHDW.h | 530 + MUNGA_L4/L4AUDIO.cpp | 2190 ++++ MUNGA_L4/L4AUDIO.h | 801 ++ MUNGA_L4/L4AUDLVL.cpp | 312 + MUNGA_L4/L4AUDLVL.h | 169 + MUNGA_L4/L4AUDRES.cpp | 1115 ++ MUNGA_L4/L4AUDRES.h | 163 + MUNGA_L4/L4AUDRND.cpp | 1417 +++ MUNGA_L4/L4AUDRND.h | 207 + MUNGA_L4/L4AUDTUL.cpp | 59 + MUNGA_L4/L4AUDWTR.cpp | 187 + MUNGA_L4/L4AUDWTR.h | 87 + MUNGA_L4/L4CTLTUL.cpp | 10 + MUNGA_L4/L4CTRL.cpp | 2592 +++++ MUNGA_L4/L4CTRL.h | 668 ++ MUNGA_L4/L4D3D.cpp | 464 + MUNGA_L4/L4D3D.h | 151 + MUNGA_L4/L4DINPUT.cpp | 194 + MUNGA_L4/L4DINPUT.h | 29 + MUNGA_L4/L4DPLMEM.cpp | 48 + MUNGA_L4/L4GAUGE.cpp | 5161 +++++++++ MUNGA_L4/L4GAUGE.h | 1162 ++ MUNGA_L4/L4GAUIMA.cpp | 1665 +++ MUNGA_L4/L4GAUIMA.h | 249 + MUNGA_L4/L4GAUTUL.cpp | 99 + MUNGA_L4/L4GREND.cpp | 836 ++ MUNGA_L4/L4GREND.h | 150 + MUNGA_L4/L4HOST.H | 112 + MUNGA_L4/L4HOST.cpp | 31 + MUNGA_L4/L4ICOM.cpp | 1026 ++ MUNGA_L4/L4ICOM.h | 169 + MUNGA_L4/L4JOYSTK.h | 97 + MUNGA_L4/L4KEYBD.cpp | 24 + MUNGA_L4/L4KEYBD.h | 138 + MUNGA_L4/L4LAMP.cpp | 389 + MUNGA_L4/L4LAMP.h | 147 + MUNGA_L4/L4MOUSE.cpp | 191 + MUNGA_L4/L4MOUSE.h | 17 + MUNGA_L4/L4MPPR.cpp | 369 + MUNGA_L4/L4MPPR.h | 151 + MUNGA_L4/L4NET.CPP | 3446 ++++++ MUNGA_L4/L4NET.H | 424 + MUNGA_L4/L4PARTICLES.cpp | 528 + MUNGA_L4/L4PARTICLES.h | 159 + MUNGA_L4/L4PCSPAK.cpp | 950 ++ MUNGA_L4/L4PCSPAK.h | 293 + MUNGA_L4/L4PLASMA.cpp | 363 + MUNGA_L4/L4PLASMA.h | 51 + MUNGA_L4/L4RIO.cpp | 1674 +++ MUNGA_L4/L4RIO.h | 320 + MUNGA_L4/L4SERIAL.H | 164 + MUNGA_L4/L4SERIAL.cpp | 287 + MUNGA_L4/L4SPLR.cpp | 741 ++ MUNGA_L4/L4SPLR.h | 204 + MUNGA_L4/L4TIME.cpp | 162 + MUNGA_L4/L4TIME.h | 6 + MUNGA_L4/L4TOOL.h | 68 + MUNGA_L4/L4TRACE.cpp | 127 + MUNGA_L4/L4TSTALL.cpp | 129 + MUNGA_L4/L4VB16.cpp | 5935 ++++++++++ MUNGA_L4/L4VB16.h | 508 + MUNGA_L4/L4VB8.cpp | 3010 +++++ MUNGA_L4/L4VB8.h | 260 + MUNGA_L4/L4VIDEO.cpp | 7419 ++++++++++++ MUNGA_L4/L4VIDEO.h | 577 + MUNGA_L4/L4VIDPER.cpp | 477 + MUNGA_L4/L4VIDPER.h | 117 + MUNGA_L4/L4VIDRND.cpp | 7317 ++++++++++++ MUNGA_L4/L4VIDRND.h | 2385 ++++ MUNGA_L4/L4VIDTUL.cpp | 10 + MUNGA_L4/L4WRHOUS.cpp | 40 + MUNGA_L4/L4WRHOUS.h | 18 + MUNGA_L4/MUNGAL4.H | 16 + MUNGA_L4/Munga_L4 VS2008.vcproj | 1695 +++ MUNGA_L4/Munga_L4.vcproj | 1763 +++ MUNGA_L4/WTPresets.cpp | 47 + MUNGA_L4/libDPL/dpl/DPLUTILS.H | 408 + MUNGA_L4/libDPL/dpl/DPL_2D.H | 123 + MUNGA_L4/libDPL/dpl/DPL_PRIV.H | 531 + MUNGA_L4/libDPL/dpl/DPL_VPX.H | 220 + MUNGA_L4/libDPL/dpl/MATRIX.H | 47 + MUNGA_L4/libDPL/dpl/dpl.h | 590 + MUNGA_L4/libDPL/dpl/dpltypes.h | 387 + MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H | 33 + MUNGA_L4/libDPL/dpl/vpx/DPL_2D.H | 123 + MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H | 24 + MUNGA_L4/libDPL/dpl/vpx/DPL_PRIV.H | 531 + MUNGA_L4/libDPL/dpl/vpx/DPL_VPX.H | 220 + MUNGA_L4/libDPL/dpl/vpx/MATRIX.H | 47 + MUNGA_L4/libDPL/dpl/vpx/TRICODER.H | 35 + MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H | 95 + MUNGA_L4/libDPL/dsys/DIVTYPES.DEF | 75 + MUNGA_L4/libDPL/dsys/DIVTYPES.H | 73 + MUNGA_L4/libDPL/dsys/DIVVERS.H | 54 + MUNGA_L4/libDPL/dsys/DLINK.H | 258 + MUNGA_L4/libDPL/dsys/DM.H | 635 ++ MUNGA_L4/libDPL/dsys/DP.H | 47 + MUNGA_L4/libDPL/dsys/DS.H | 48 + MUNGA_L4/libDPL/dsys/DTCP.H | 165 + MUNGA_L4/libDPL/dsys/DU.H | 214 + MUNGA_L4/libDPL/dsys/FILELIB.H | 315 + MUNGA_L4/libDPL/dsys/GETPARAM.H | 73 + MUNGA_L4/libDPL/dsys/MAPFILE.H | 99 + MUNGA_L4/libDPL/dsys/PARSER.H | 122 + MUNGA_L4/libDPL/dsys/PFBIZTAG.H | 197 + MUNGA_L4/libDPL/dsys/PFILE.H | 1166 ++ MUNGA_L4/libDPL/dsys/PFPARSER.H | 97 + MUNGA_L4/libDPL/dsys/PGENERAL.H | 183 + MUNGA_L4/libDPL/dsys/PIMAGE.H | 199 + MUNGA_L4/libDPL/dsys/PTOOL.H | 666 ++ MUNGA_L4/libDPL/dsys/VDIFILE.H | 229 + MUNGA_L4/libDPL/dsys/__PFILE.H | 603 + MUNGA_L4/libDPL/dsys/__PTOOL.H | 84 + MUNGA_L4/libDPL/dvs/DM.H | 29 + MUNGA_L4/libDPL/dvs/DMELEM.H | 132 + MUNGA_L4/libDPL/dvs/VC.H | 818 ++ MUNGA_L4/libDPL/dvs/VCBODAPP.H | 47 + MUNGA_L4/libDPL/dvs/VCDATA.H | 60 + MUNGA_L4/libDPL/dvs/VCDEFS.H | 597 + MUNGA_L4/libDPL/dvs/VCDTYPES.H | 394 + MUNGA_L4/libDPL/dvs/VCDYNAM.H | 538 + MUNGA_L4/libDPL/dvs/VCELEMEN.H | 840 ++ MUNGA_L4/libDPL/dvs/VCELTYPE.H | 629 + MUNGA_L4/libDPL/dvs/VCERROR.H | 33 + MUNGA_L4/libDPL/dvs/VCINPDEF.H | 71 + MUNGA_L4/libDPL/dvs/VCMACROS.H | 33 + MUNGA_L4/libDPL/dvs/VCOBJECT.H | 686 ++ MUNGA_L4/libDPL/dvs/VCSTRUCT.H | 215 + MUNGA_L4/libDPL/dvs/VCTYPES.H | 178 + MUNGA_L4/libDPL/dvs/VCVBOSE.H | 100 + MUNGA_L4/libDPL/dvs/VL.H | 476 + MUNGA_L4/libDPL/dvs/VLTYPES.H | 161 + MUNGA_L4/libDPL/dvs/_VCSTRUC.H | 569 + MUNGA_L4/libDPL/dvs/_VCTYPES.H | 10 + MUNGA_L4/openal/EFX-Util.h | 422 + MUNGA_L4/openal/al.h | 732 ++ MUNGA_L4/openal/alc.h | 273 + MUNGA_L4/openal/efx-creative.h | 151 + MUNGA_L4/openal/efx.h | 737 ++ MUNGA_L4/openal/xram.h | 94 + MUNGA_L4/sndfile.h | 554 + MUNGA_L4/sos/SOSMAWE.C | 443 + MUNGA_L4/sos/bc4/SOS.H | 554 + MUNGA_L4/sos/bc4/SOS.INC | 192 + MUNGA_L4/sos/bc4/SOSDATA.H | 112 + MUNGA_L4/sos/bc4/SOSDEFS.H | 65 + MUNGA_L4/sos/bc4/SOSFNCT.H | 209 + MUNGA_L4/sos/bc4/SOSM.H | 450 + MUNGA_L4/sos/bc4/SOSMAWE.H | 16 + MUNGA_L4/sos/bc4/SOSMDATA.H | 125 + MUNGA_L4/sos/bc4/SOSMFNCT.H | 190 + MUNGA_L4/sos/bc4/SOSRES.H | 110 + MUNGA_L4/sos/wc/SOS.H | 553 + MUNGA_L4/sos/wc/SOSDATA.H | 110 + MUNGA_L4/sos/wc/SOSFNCT.H | 208 + MUNGA_L4/sos/wc/SOSMDATA.H | 125 + MUNGA_L4/sos/wc/SOSMFNCT.H | 175 + MUNGA_L4/sos/wc/SOSRES.H | 110 + MUNGA_L4/sos/wc/sosdefs.h | 65 + MUNGA_L4/sos/wc/sosm.h | 451 + MUNGA_L4/tagIdents.h | 89 + MUNGA_L4/temp.cpp | 1 + RP/BLOCKER.cpp | 271 + RP/BLOCKER.h | 72 + RP/BOOSTER.cpp | 487 + RP/BOOSTER.h | 156 + RP/CHUTE.cpp | 638 ++ RP/CHUTE.h | 230 + RP/CRUSHER.cpp | 433 + RP/CRUSHER.h | 81 + RP/DEMOPACK.cpp | 581 + RP/DEMOPACK.h | 121 + RP/RIVET.cpp | 503 + RP/RIVET.h | 178 + RP/RP.h | 9 + RP/RPCNSL.cpp | 81 + RP/RPCNSL.h | 280 + RP/RPDIRECT.cpp | 197 + RP/RPDIRECT.h | 60 + RP/RPMSSN.cpp | 28 + RP/RPMSSN.h | 26 + RP/RPPLAYER.cpp | 1381 +++ RP/RPPLAYER.h | 417 + RP/RPREG.cpp | 186 + RP/RPREG.h | 51 + RP/RPTOOL.cpp | 180 + RP/RPTOOL.h | 20 + RP/RUNNER.cpp | 281 + RP/RUNNER.h | 61 + RP/SCORZONE.cpp | 577 + RP/SCORZONE.h | 271 + RP/THRUSTER.cpp | 401 + RP/THRUSTER.h | 143 + RP/VTV.cpp | 3199 ++++++ RP/VTV.h | 524 + RP/VTVMPPR.cpp | 958 ++ RP/VTVMPPR.h | 245 + RP/VTVPWR.cpp | 134 + RP/VTVPWR.h | 100 + RP/VTVSUB.cpp | 153 + RP/VTVSUB.h | 61 + RP/WEAPSYS.cpp | 1523 +++ RP/WEAPSYS.h | 548 + RP_L4/JOYSTICK.INI | 12 + RP_L4/RPL4.CPP | 284 + RP_L4/RPL4.HPP | 12 + RP_L4/RPL4.RES | Bin 0 -> 819872 bytes RP_L4/RPL4.h | 2 + RP_L4/RPL4APP.cpp | 382 + RP_L4/RPL4APP.h | 29 + RP_L4/RPL4ARND.cpp | 22 + RP_L4/RPL4ARND.h | 17 + RP_L4/RPL4GAUG.cpp | 3823 +++++++ RP_L4/RPL4GAUG.h | 571 + RP_L4/RPL4GRND.cpp | 270 + RP_L4/RPL4GRND.h | 36 + RP_L4/RPL4MODE.cpp | 60 + RP_L4/RPL4MODE.h | 76 + RP_L4/RPL4MPPR.cpp | 2056 ++++ RP_L4/RPL4MPPR.h | 316 + RP_L4/RPL4MSSN.cpp | 306 + RP_L4/RPL4MSSN.h | 18 + RP_L4/RPL4PB.cpp | 566 + RP_L4/RPL4PB.h | 121 + RP_L4/RPL4TOOL VS2008.vcproj | 363 + RP_L4/RPL4TOOL.cpp | 78 + RP_L4/RPL4TOOL.vcproj | 372 + RP_L4/RPL4VER.h | 5 + RP_L4/RPL4VID.cpp | 1713 +++ RP_L4/RPL4VID.h | 67 + RP_L4/RP_L4 VS2008.vcproj | 579 + RP_L4/RP_L4.vcproj | 589 + RP_L4/TEST.EGG | 243 + RP_L4/WTPresets.cpp | 2812 +++++ RP_L4/WTPresets.h | 1 + RP_L4/last.egg | 224 + Setup1/Setup1.vdproj | 16493 +++++++++++++++++++++++++++ WinTesla.sln | 141 + docs/audionotes.rtf | 94 + lib/OpenAL32.lib | Bin 0 -> 20552 bytes lib/libsndfile-1.lib | Bin 0 -> 8180 bytes 551 files changed, 254956 insertions(+) create mode 100644 .gitattributes create mode 100644 .gitignore create mode 100644 DPLSTUB.h create mode 100644 DivLoader/DivLoader.vcproj create mode 100644 DivLoader/VGCDivLoader.cpp create mode 100644 DivLoader/VGCDivLoader.h create mode 100644 DivLoader/tagIdents.h create mode 100644 LOGGER.cpp create mode 100644 LOGGER.h create mode 100644 MUNGA/AFFNMTRX.cpp create mode 100644 MUNGA/AFFNMTRX.h create mode 100644 MUNGA/ANGLE.cpp create mode 100644 MUNGA/ANGLE.h create mode 100644 MUNGA/ANIMTOOL.cpp create mode 100644 MUNGA/APP.cpp create mode 100644 MUNGA/APP.h create mode 100644 MUNGA/APPMGR.cpp create mode 100644 MUNGA/APPMGR.h create mode 100644 MUNGA/APPMSG.cpp create mode 100644 MUNGA/APPMSG.h create mode 100644 MUNGA/APPTASK.cpp create mode 100644 MUNGA/APPTASK.h create mode 100644 MUNGA/AUDCMP.cpp create mode 100644 MUNGA/AUDCMP.h create mode 100644 MUNGA/AUDENT.cpp create mode 100644 MUNGA/AUDENT.h create mode 100644 MUNGA/AUDIO.cpp create mode 100644 MUNGA/AUDIO.h create mode 100644 MUNGA/AUDLOC.cpp create mode 100644 MUNGA/AUDLOC.h create mode 100644 MUNGA/AUDLVL.cpp create mode 100644 MUNGA/AUDLVL.h create mode 100644 MUNGA/AUDMIDI.cpp create mode 100644 MUNGA/AUDMIDI.h create mode 100644 MUNGA/AUDREND.cpp create mode 100644 MUNGA/AUDREND.h create mode 100644 MUNGA/AUDSEQ.cpp create mode 100644 MUNGA/AUDSEQ.h create mode 100644 MUNGA/AUDSRC.cpp create mode 100644 MUNGA/AUDSRC.h create mode 100644 MUNGA/AUDTIME.cpp create mode 100644 MUNGA/AUDTIME.h create mode 100644 MUNGA/AUDTOOLS.cpp create mode 100644 MUNGA/AUDTOOLS.h create mode 100644 MUNGA/AUDWGT.cpp create mode 100644 MUNGA/AUDWGT.h create mode 100644 MUNGA/AUDWTHR.cpp create mode 100644 MUNGA/AUDWTHR.h create mode 100644 MUNGA/AVERAGE.cpp create mode 100644 MUNGA/AVERAGE.h create mode 100644 MUNGA/BNDGBOX.cpp create mode 100644 MUNGA/BNDGBOX.h create mode 100644 MUNGA/BOXCONE.cpp create mode 100644 MUNGA/BOXDISKS.cpp create mode 100644 MUNGA/BOXIRAMP.cpp create mode 100644 MUNGA/BOXLIST.cpp create mode 100644 MUNGA/BOXLIST.h create mode 100644 MUNGA/BOXRAMP.cpp create mode 100644 MUNGA/BOXSOLID.cpp create mode 100644 MUNGA/BOXSOLID.h create mode 100644 MUNGA/BOXSORT.cpp create mode 100644 MUNGA/BOXSPHR.cpp create mode 100644 MUNGA/BOXTILE.cpp create mode 100644 MUNGA/BOXTREE.cpp create mode 100644 MUNGA/BOXTREE.h create mode 100644 MUNGA/BOXWEDGE.cpp create mode 100644 MUNGA/CAMINST.cpp create mode 100644 MUNGA/CAMINST.h create mode 100644 MUNGA/CAMMGR.cpp create mode 100644 MUNGA/CAMMGR.h create mode 100644 MUNGA/CAMMPPR.cpp create mode 100644 MUNGA/CAMMPPR.h create mode 100644 MUNGA/CAMSHIP.cpp create mode 100644 MUNGA/CAMSHIP.h create mode 100644 MUNGA/CHAIN.cpp create mode 100644 MUNGA/CHAIN.h create mode 100644 MUNGA/CMPNNT.cpp create mode 100644 MUNGA/CMPNNT.h create mode 100644 MUNGA/COLLASST.cpp create mode 100644 MUNGA/COLLASST.h create mode 100644 MUNGA/COLLORGN.cpp create mode 100644 MUNGA/COLLORGN.h create mode 100644 MUNGA/COLOR.cpp create mode 100644 MUNGA/COLOR.h create mode 100644 MUNGA/CONFIG.h create mode 100644 MUNGA/CONSOLE.cpp create mode 100644 MUNGA/CONSOLE.h create mode 100644 MUNGA/CONTROLS.cpp create mode 100644 MUNGA/CONTROLS.h create mode 100644 MUNGA/CSTR.cpp create mode 100644 MUNGA/CSTR.h create mode 100644 MUNGA/CULTURAL.cpp create mode 100644 MUNGA/DAMAGE.cpp create mode 100644 MUNGA/DAMAGE.h create mode 100644 MUNGA/DEBUG1ON.h create mode 100644 MUNGA/DEBUGOFF.h create mode 100644 MUNGA/DIRECTOR.cpp create mode 100644 MUNGA/DIRECTOR.h create mode 100644 MUNGA/DOOR.cpp create mode 100644 MUNGA/DOOR.h create mode 100644 MUNGA/DOORFRAM.cpp create mode 100644 MUNGA/DOORFRAM.h create mode 100644 MUNGA/DROPZONE.cpp create mode 100644 MUNGA/DROPZONE.h create mode 100644 MUNGA/ENTITY.cpp create mode 100644 MUNGA/ENTITY.h create mode 100644 MUNGA/ENTITY2.cpp create mode 100644 MUNGA/ENTITY2.h create mode 100644 MUNGA/ENTITY3.h create mode 100644 MUNGA/ENTITYID.cpp create mode 100644 MUNGA/ENTITYID.h create mode 100644 MUNGA/ENVIRNMT.cpp create mode 100644 MUNGA/ENVIRNMT.h create mode 100644 MUNGA/EVENT.cpp create mode 100644 MUNGA/EVENT.h create mode 100644 MUNGA/EVTSTAT.cpp create mode 100644 MUNGA/EVTSTAT.h create mode 100644 MUNGA/EXPLODE.cpp create mode 100644 MUNGA/EXPLODE.h create mode 100644 MUNGA/EXPTBL.cpp create mode 100644 MUNGA/EXPTBL.h create mode 100644 MUNGA/EXTNTBOX.cpp create mode 100644 MUNGA/EXTNTBOX.h create mode 100644 MUNGA/EYECANDY.cpp create mode 100644 MUNGA/EYECANDY.h create mode 100644 MUNGA/FILESTRM.cpp create mode 100644 MUNGA/FILESTRM.h create mode 100644 MUNGA/FILESTUB.cpp create mode 100644 MUNGA/FILEUTIL.cpp create mode 100644 MUNGA/FILEUTIL.h create mode 100644 MUNGA/GAUGALRM.cpp create mode 100644 MUNGA/GAUGALRM.h create mode 100644 MUNGA/GAUGE.cpp create mode 100644 MUNGA/GAUGE.h create mode 100644 MUNGA/GAUGMAP.cpp create mode 100644 MUNGA/GAUGMAP.h create mode 100644 MUNGA/GAUGREND.cpp create mode 100644 MUNGA/GAUGREND.h create mode 100644 MUNGA/GRAPH2D.cpp create mode 100644 MUNGA/GRAPH2D.h create mode 100644 MUNGA/HASH.cpp create mode 100644 MUNGA/HASH.h create mode 100644 MUNGA/HOST.cpp create mode 100644 MUNGA/HOST.h create mode 100644 MUNGA/HOSTID.h create mode 100644 MUNGA/HOSTMGR.cpp create mode 100644 MUNGA/HOSTMGR.h create mode 100644 MUNGA/ICOM.cpp create mode 100644 MUNGA/ICOM.h create mode 100644 MUNGA/INTEREST.cpp create mode 100644 MUNGA/INTEREST.h create mode 100644 MUNGA/INTORGN.cpp create mode 100644 MUNGA/INTORGN.h create mode 100644 MUNGA/ITERATOR.cpp create mode 100644 MUNGA/ITERATOR.h create mode 100644 MUNGA/JMOVER.cpp create mode 100644 MUNGA/JMOVER.h create mode 100644 MUNGA/JOINT.cpp create mode 100644 MUNGA/JOINT.h create mode 100644 MUNGA/LAMP.cpp create mode 100644 MUNGA/LAMP.h create mode 100644 MUNGA/LATTICE.cpp create mode 100644 MUNGA/LATTICE.h create mode 100644 MUNGA/LINE.cpp create mode 100644 MUNGA/LINE.h create mode 100644 MUNGA/LINK.cpp create mode 100644 MUNGA/LINK.h create mode 100644 MUNGA/LINMTRX.cpp create mode 100644 MUNGA/LINMTRX.h create mode 100644 MUNGA/MAPTOOL.cpp create mode 100644 MUNGA/MATRIX.cpp create mode 100644 MUNGA/MATRIX.h create mode 100644 MUNGA/MEMBLOCK.cpp create mode 100644 MUNGA/MEMBLOCK.h create mode 100644 MUNGA/MEMREG.cpp create mode 100644 MUNGA/MEMREG.h create mode 100644 MUNGA/MEMSTRM.CPP create mode 100644 MUNGA/MEMSTRM.H create mode 100644 MUNGA/MISSION.cpp create mode 100644 MUNGA/MISSION.h create mode 100644 MUNGA/MODE.cpp create mode 100644 MUNGA/MODE.h create mode 100644 MUNGA/MODTOOL.cpp create mode 100644 MUNGA/MOTION.cpp create mode 100644 MUNGA/MOTION.h create mode 100644 MUNGA/MOVER.cpp create mode 100644 MUNGA/MOVER.h create mode 100644 MUNGA/MTRXSTK.cpp create mode 100644 MUNGA/MTRXSTK.h create mode 100644 MUNGA/MUNGA.h create mode 100644 MUNGA/NAMELIST.cpp create mode 100644 MUNGA/NAMELIST.h create mode 100644 MUNGA/NETWORK.cpp create mode 100644 MUNGA/NETWORK.h create mode 100644 MUNGA/NODE.cpp create mode 100644 MUNGA/NODE.h create mode 100644 MUNGA/NORMAL.cpp create mode 100644 MUNGA/NORMAL.h create mode 100644 MUNGA/NOTATION.cpp create mode 100644 MUNGA/NOTATION.h create mode 100644 MUNGA/NTTMGR.cpp create mode 100644 MUNGA/NTTMGR.h create mode 100644 MUNGA/OBJSTRM.cpp create mode 100644 MUNGA/OBJSTRM.h create mode 100644 MUNGA/ORIGIN.cpp create mode 100644 MUNGA/ORIGIN.h create mode 100644 MUNGA/PLANE.cpp create mode 100644 MUNGA/PLANE.h create mode 100644 MUNGA/PLAYER.cpp create mode 100644 MUNGA/PLAYER.h create mode 100644 MUNGA/PLUG.cpp create mode 100644 MUNGA/PLUG.h create mode 100644 MUNGA/POINT3D.cpp create mode 100644 MUNGA/POINT3D.h create mode 100644 MUNGA/RANDOM.cpp create mode 100644 MUNGA/RANDOM.h create mode 100644 MUNGA/RAY.cpp create mode 100644 MUNGA/RAY.h create mode 100644 MUNGA/RECEIVER.cpp create mode 100644 MUNGA/RECEIVER.h create mode 100644 MUNGA/RECT2D.cpp create mode 100644 MUNGA/RECT2D.h create mode 100644 MUNGA/REGISTRY.cpp create mode 100644 MUNGA/REGISTRY.h create mode 100644 MUNGA/RENDERER.cpp create mode 100644 MUNGA/RENDERER.h create mode 100644 MUNGA/RESOURCE.cpp create mode 100644 MUNGA/RESOURCE.h create mode 100644 MUNGA/RESVER.h create mode 100644 MUNGA/RETICLE.cpp create mode 100644 MUNGA/RETICLE.h create mode 100644 MUNGA/RNDORGN.cpp create mode 100644 MUNGA/RNDORGN.h create mode 100644 MUNGA/ROTATION.cpp create mode 100644 MUNGA/ROTATION.h create mode 100644 MUNGA/SCALAR.cpp create mode 100644 MUNGA/SCALAR.h create mode 100644 MUNGA/SCHAIN.cpp create mode 100644 MUNGA/SCHAIN.h create mode 100644 MUNGA/SCNROLE.cpp create mode 100644 MUNGA/SCNROLE.h create mode 100644 MUNGA/SEGMENT.cpp create mode 100644 MUNGA/SEGMENT.h create mode 100644 MUNGA/SET.cpp create mode 100644 MUNGA/SET.h create mode 100644 MUNGA/SFESKT.cpp create mode 100644 MUNGA/SFESKT.h create mode 100644 MUNGA/SIMULATE.cpp create mode 100644 MUNGA/SIMULATE.h create mode 100644 MUNGA/SLOT.cpp create mode 100644 MUNGA/SLOT.h create mode 100644 MUNGA/SOCKET.cpp create mode 100644 MUNGA/SOCKET.h create mode 100644 MUNGA/SPHERE.cpp create mode 100644 MUNGA/SPHERE.h create mode 100644 MUNGA/SPLINE.cpp create mode 100644 MUNGA/SPLINE.h create mode 100644 MUNGA/SPOOLER.cpp create mode 100644 MUNGA/SPOOLER.h create mode 100644 MUNGA/SRTSKT.cpp create mode 100644 MUNGA/SRTSKT.h create mode 100644 MUNGA/STATE.h create mode 100644 MUNGA/STYLE.H create mode 100644 MUNGA/SUBSYSTM.cpp create mode 100644 MUNGA/SUBSYSTM.h create mode 100644 MUNGA/TABLE.cpp create mode 100644 MUNGA/TABLE.h create mode 100644 MUNGA/TEAM.cpp create mode 100644 MUNGA/TEAM.h create mode 100644 MUNGA/TERRAIN.cpp create mode 100644 MUNGA/TERRAIN.h create mode 100644 MUNGA/TESTALL.cpp create mode 100644 MUNGA/TIME.cpp create mode 100644 MUNGA/TIME.h create mode 100644 MUNGA/TIMESTUB.cpp create mode 100644 MUNGA/TOOL.cpp create mode 100644 MUNGA/TOOL.h create mode 100644 MUNGA/TRACE.cpp create mode 100644 MUNGA/TRACE.h create mode 100644 MUNGA/TRACSTUB.cpp create mode 100644 MUNGA/TREE.cpp create mode 100644 MUNGA/TREE.h create mode 100644 MUNGA/UNITVEC.cpp create mode 100644 MUNGA/UNITVEC.h create mode 100644 MUNGA/UPDATE.cpp create mode 100644 MUNGA/UPDATE.h create mode 100644 MUNGA/VCHAIN.cpp create mode 100644 MUNGA/VCHAIN.h create mode 100644 MUNGA/VDATA.cpp create mode 100644 MUNGA/VDATA.h create mode 100644 MUNGA/VECTOR2D.h create mode 100644 MUNGA/VECTOR3D.cpp create mode 100644 MUNGA/VECTOR3D.h create mode 100644 MUNGA/VECTOR4D.cpp create mode 100644 MUNGA/VECTOR4D.h create mode 100644 MUNGA/VERIFY.cpp create mode 100644 MUNGA/VERIFY.h create mode 100644 MUNGA/VIDREND.cpp create mode 100644 MUNGA/VIDREND.h create mode 100644 MUNGA/WATCHER.cpp create mode 100644 MUNGA/WATCHER.h create mode 100644 MUNGA/WRHOUS.cpp create mode 100644 MUNGA/WRHOUS.h create mode 100644 MUNGA/cultural.h create mode 100644 MUNGA_L4/DXUtils.cpp create mode 100644 MUNGA_L4/DXUtils.h create mode 100644 MUNGA_L4/JOYSTICK.asm create mode 100644 MUNGA_L4/L4APP.H create mode 100644 MUNGA_L4/L4APP.cpp create mode 100644 MUNGA_L4/L4AUDHDW.cpp create mode 100644 MUNGA_L4/L4AUDHDW.h create mode 100644 MUNGA_L4/L4AUDIO.cpp create mode 100644 MUNGA_L4/L4AUDIO.h create mode 100644 MUNGA_L4/L4AUDLVL.cpp create mode 100644 MUNGA_L4/L4AUDLVL.h create mode 100644 MUNGA_L4/L4AUDRES.cpp create mode 100644 MUNGA_L4/L4AUDRES.h create mode 100644 MUNGA_L4/L4AUDRND.cpp create mode 100644 MUNGA_L4/L4AUDRND.h create mode 100644 MUNGA_L4/L4AUDTUL.cpp create mode 100644 MUNGA_L4/L4AUDWTR.cpp create mode 100644 MUNGA_L4/L4AUDWTR.h create mode 100644 MUNGA_L4/L4CTLTUL.cpp create mode 100644 MUNGA_L4/L4CTRL.cpp create mode 100644 MUNGA_L4/L4CTRL.h create mode 100644 MUNGA_L4/L4D3D.cpp create mode 100644 MUNGA_L4/L4D3D.h create mode 100644 MUNGA_L4/L4DINPUT.cpp create mode 100644 MUNGA_L4/L4DINPUT.h create mode 100644 MUNGA_L4/L4DPLMEM.cpp create mode 100644 MUNGA_L4/L4GAUGE.cpp create mode 100644 MUNGA_L4/L4GAUGE.h create mode 100644 MUNGA_L4/L4GAUIMA.cpp create mode 100644 MUNGA_L4/L4GAUIMA.h create mode 100644 MUNGA_L4/L4GAUTUL.cpp create mode 100644 MUNGA_L4/L4GREND.cpp create mode 100644 MUNGA_L4/L4GREND.h create mode 100644 MUNGA_L4/L4HOST.H create mode 100644 MUNGA_L4/L4HOST.cpp create mode 100644 MUNGA_L4/L4ICOM.cpp create mode 100644 MUNGA_L4/L4ICOM.h create mode 100644 MUNGA_L4/L4JOYSTK.h create mode 100644 MUNGA_L4/L4KEYBD.cpp create mode 100644 MUNGA_L4/L4KEYBD.h create mode 100644 MUNGA_L4/L4LAMP.cpp create mode 100644 MUNGA_L4/L4LAMP.h create mode 100644 MUNGA_L4/L4MOUSE.cpp create mode 100644 MUNGA_L4/L4MOUSE.h create mode 100644 MUNGA_L4/L4MPPR.cpp create mode 100644 MUNGA_L4/L4MPPR.h create mode 100644 MUNGA_L4/L4NET.CPP create mode 100644 MUNGA_L4/L4NET.H create mode 100644 MUNGA_L4/L4PARTICLES.cpp create mode 100644 MUNGA_L4/L4PARTICLES.h create mode 100644 MUNGA_L4/L4PCSPAK.cpp create mode 100644 MUNGA_L4/L4PCSPAK.h create mode 100644 MUNGA_L4/L4PLASMA.cpp create mode 100644 MUNGA_L4/L4PLASMA.h create mode 100644 MUNGA_L4/L4RIO.cpp create mode 100644 MUNGA_L4/L4RIO.h create mode 100644 MUNGA_L4/L4SERIAL.H create mode 100644 MUNGA_L4/L4SERIAL.cpp create mode 100644 MUNGA_L4/L4SPLR.cpp create mode 100644 MUNGA_L4/L4SPLR.h create mode 100644 MUNGA_L4/L4TIME.cpp create mode 100644 MUNGA_L4/L4TIME.h create mode 100644 MUNGA_L4/L4TOOL.h create mode 100644 MUNGA_L4/L4TRACE.cpp create mode 100644 MUNGA_L4/L4TSTALL.cpp create mode 100644 MUNGA_L4/L4VB16.cpp create mode 100644 MUNGA_L4/L4VB16.h create mode 100644 MUNGA_L4/L4VB8.cpp create mode 100644 MUNGA_L4/L4VB8.h create mode 100644 MUNGA_L4/L4VIDEO.cpp create mode 100644 MUNGA_L4/L4VIDEO.h create mode 100644 MUNGA_L4/L4VIDPER.cpp create mode 100644 MUNGA_L4/L4VIDPER.h create mode 100644 MUNGA_L4/L4VIDRND.cpp create mode 100644 MUNGA_L4/L4VIDRND.h create mode 100644 MUNGA_L4/L4VIDTUL.cpp create mode 100644 MUNGA_L4/L4WRHOUS.cpp create mode 100644 MUNGA_L4/L4WRHOUS.h create mode 100644 MUNGA_L4/MUNGAL4.H create mode 100644 MUNGA_L4/Munga_L4 VS2008.vcproj create mode 100644 MUNGA_L4/Munga_L4.vcproj create mode 100644 MUNGA_L4/WTPresets.cpp create mode 100644 MUNGA_L4/libDPL/dpl/DPLUTILS.H create mode 100644 MUNGA_L4/libDPL/dpl/DPL_2D.H create mode 100644 MUNGA_L4/libDPL/dpl/DPL_PRIV.H create mode 100644 MUNGA_L4/libDPL/dpl/DPL_VPX.H create mode 100644 MUNGA_L4/libDPL/dpl/MATRIX.H create mode 100644 MUNGA_L4/libDPL/dpl/dpl.h create mode 100644 MUNGA_L4/libDPL/dpl/dpltypes.h create mode 100644 MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H create mode 100644 MUNGA_L4/libDPL/dpl/vpx/DPL_2D.H create mode 100644 MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H create mode 100644 MUNGA_L4/libDPL/dpl/vpx/DPL_PRIV.H create mode 100644 MUNGA_L4/libDPL/dpl/vpx/DPL_VPX.H create mode 100644 MUNGA_L4/libDPL/dpl/vpx/MATRIX.H create mode 100644 MUNGA_L4/libDPL/dpl/vpx/TRICODER.H create mode 100644 MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H create mode 100644 MUNGA_L4/libDPL/dsys/DIVTYPES.DEF create mode 100644 MUNGA_L4/libDPL/dsys/DIVTYPES.H create mode 100644 MUNGA_L4/libDPL/dsys/DIVVERS.H create mode 100644 MUNGA_L4/libDPL/dsys/DLINK.H create mode 100644 MUNGA_L4/libDPL/dsys/DM.H create mode 100644 MUNGA_L4/libDPL/dsys/DP.H create mode 100644 MUNGA_L4/libDPL/dsys/DS.H create mode 100644 MUNGA_L4/libDPL/dsys/DTCP.H create mode 100644 MUNGA_L4/libDPL/dsys/DU.H create mode 100644 MUNGA_L4/libDPL/dsys/FILELIB.H create mode 100644 MUNGA_L4/libDPL/dsys/GETPARAM.H create mode 100644 MUNGA_L4/libDPL/dsys/MAPFILE.H create mode 100644 MUNGA_L4/libDPL/dsys/PARSER.H create mode 100644 MUNGA_L4/libDPL/dsys/PFBIZTAG.H create mode 100644 MUNGA_L4/libDPL/dsys/PFILE.H create mode 100644 MUNGA_L4/libDPL/dsys/PFPARSER.H create mode 100644 MUNGA_L4/libDPL/dsys/PGENERAL.H create mode 100644 MUNGA_L4/libDPL/dsys/PIMAGE.H create mode 100644 MUNGA_L4/libDPL/dsys/PTOOL.H create mode 100644 MUNGA_L4/libDPL/dsys/VDIFILE.H create mode 100644 MUNGA_L4/libDPL/dsys/__PFILE.H create mode 100644 MUNGA_L4/libDPL/dsys/__PTOOL.H create mode 100644 MUNGA_L4/libDPL/dvs/DM.H create mode 100644 MUNGA_L4/libDPL/dvs/DMELEM.H create mode 100644 MUNGA_L4/libDPL/dvs/VC.H create mode 100644 MUNGA_L4/libDPL/dvs/VCBODAPP.H create mode 100644 MUNGA_L4/libDPL/dvs/VCDATA.H create mode 100644 MUNGA_L4/libDPL/dvs/VCDEFS.H create mode 100644 MUNGA_L4/libDPL/dvs/VCDTYPES.H create mode 100644 MUNGA_L4/libDPL/dvs/VCDYNAM.H create mode 100644 MUNGA_L4/libDPL/dvs/VCELEMEN.H create mode 100644 MUNGA_L4/libDPL/dvs/VCELTYPE.H create mode 100644 MUNGA_L4/libDPL/dvs/VCERROR.H create mode 100644 MUNGA_L4/libDPL/dvs/VCINPDEF.H create mode 100644 MUNGA_L4/libDPL/dvs/VCMACROS.H create mode 100644 MUNGA_L4/libDPL/dvs/VCOBJECT.H create mode 100644 MUNGA_L4/libDPL/dvs/VCSTRUCT.H create mode 100644 MUNGA_L4/libDPL/dvs/VCTYPES.H create mode 100644 MUNGA_L4/libDPL/dvs/VCVBOSE.H create mode 100644 MUNGA_L4/libDPL/dvs/VL.H create mode 100644 MUNGA_L4/libDPL/dvs/VLTYPES.H create mode 100644 MUNGA_L4/libDPL/dvs/_VCSTRUC.H create mode 100644 MUNGA_L4/libDPL/dvs/_VCTYPES.H create mode 100644 MUNGA_L4/openal/EFX-Util.h create mode 100644 MUNGA_L4/openal/al.h create mode 100644 MUNGA_L4/openal/alc.h create mode 100644 MUNGA_L4/openal/efx-creative.h create mode 100644 MUNGA_L4/openal/efx.h create mode 100644 MUNGA_L4/openal/xram.h create mode 100644 MUNGA_L4/sndfile.h create mode 100644 MUNGA_L4/sos/SOSMAWE.C create mode 100644 MUNGA_L4/sos/bc4/SOS.H create mode 100644 MUNGA_L4/sos/bc4/SOS.INC create mode 100644 MUNGA_L4/sos/bc4/SOSDATA.H create mode 100644 MUNGA_L4/sos/bc4/SOSDEFS.H create mode 100644 MUNGA_L4/sos/bc4/SOSFNCT.H create mode 100644 MUNGA_L4/sos/bc4/SOSM.H create mode 100644 MUNGA_L4/sos/bc4/SOSMAWE.H create mode 100644 MUNGA_L4/sos/bc4/SOSMDATA.H create mode 100644 MUNGA_L4/sos/bc4/SOSMFNCT.H create mode 100644 MUNGA_L4/sos/bc4/SOSRES.H create mode 100644 MUNGA_L4/sos/wc/SOS.H create mode 100644 MUNGA_L4/sos/wc/SOSDATA.H create mode 100644 MUNGA_L4/sos/wc/SOSFNCT.H create mode 100644 MUNGA_L4/sos/wc/SOSMDATA.H create mode 100644 MUNGA_L4/sos/wc/SOSMFNCT.H create mode 100644 MUNGA_L4/sos/wc/SOSRES.H create mode 100644 MUNGA_L4/sos/wc/sosdefs.h create mode 100644 MUNGA_L4/sos/wc/sosm.h create mode 100644 MUNGA_L4/tagIdents.h create mode 100644 MUNGA_L4/temp.cpp create mode 100644 RP/BLOCKER.cpp create mode 100644 RP/BLOCKER.h create mode 100644 RP/BOOSTER.cpp create mode 100644 RP/BOOSTER.h create mode 100644 RP/CHUTE.cpp create mode 100644 RP/CHUTE.h create mode 100644 RP/CRUSHER.cpp create mode 100644 RP/CRUSHER.h create mode 100644 RP/DEMOPACK.cpp create mode 100644 RP/DEMOPACK.h create mode 100644 RP/RIVET.cpp create mode 100644 RP/RIVET.h create mode 100644 RP/RP.h create mode 100644 RP/RPCNSL.cpp create mode 100644 RP/RPCNSL.h create mode 100644 RP/RPDIRECT.cpp create mode 100644 RP/RPDIRECT.h create mode 100644 RP/RPMSSN.cpp create mode 100644 RP/RPMSSN.h create mode 100644 RP/RPPLAYER.cpp create mode 100644 RP/RPPLAYER.h create mode 100644 RP/RPREG.cpp create mode 100644 RP/RPREG.h create mode 100644 RP/RPTOOL.cpp create mode 100644 RP/RPTOOL.h create mode 100644 RP/RUNNER.cpp create mode 100644 RP/RUNNER.h create mode 100644 RP/SCORZONE.cpp create mode 100644 RP/SCORZONE.h create mode 100644 RP/THRUSTER.cpp create mode 100644 RP/THRUSTER.h create mode 100644 RP/VTV.cpp create mode 100644 RP/VTV.h create mode 100644 RP/VTVMPPR.cpp create mode 100644 RP/VTVMPPR.h create mode 100644 RP/VTVPWR.cpp create mode 100644 RP/VTVPWR.h create mode 100644 RP/VTVSUB.cpp create mode 100644 RP/VTVSUB.h create mode 100644 RP/WEAPSYS.cpp create mode 100644 RP/WEAPSYS.h create mode 100644 RP_L4/JOYSTICK.INI create mode 100644 RP_L4/RPL4.CPP create mode 100644 RP_L4/RPL4.HPP create mode 100644 RP_L4/RPL4.RES create mode 100644 RP_L4/RPL4.h create mode 100644 RP_L4/RPL4APP.cpp create mode 100644 RP_L4/RPL4APP.h create mode 100644 RP_L4/RPL4ARND.cpp create mode 100644 RP_L4/RPL4ARND.h create mode 100644 RP_L4/RPL4GAUG.cpp create mode 100644 RP_L4/RPL4GAUG.h create mode 100644 RP_L4/RPL4GRND.cpp create mode 100644 RP_L4/RPL4GRND.h create mode 100644 RP_L4/RPL4MODE.cpp create mode 100644 RP_L4/RPL4MODE.h create mode 100644 RP_L4/RPL4MPPR.cpp create mode 100644 RP_L4/RPL4MPPR.h create mode 100644 RP_L4/RPL4MSSN.cpp create mode 100644 RP_L4/RPL4MSSN.h create mode 100644 RP_L4/RPL4PB.cpp create mode 100644 RP_L4/RPL4PB.h create mode 100644 RP_L4/RPL4TOOL VS2008.vcproj create mode 100644 RP_L4/RPL4TOOL.cpp create mode 100644 RP_L4/RPL4TOOL.vcproj create mode 100644 RP_L4/RPL4VER.h create mode 100644 RP_L4/RPL4VID.cpp create mode 100644 RP_L4/RPL4VID.h create mode 100644 RP_L4/RP_L4 VS2008.vcproj create mode 100644 RP_L4/RP_L4.vcproj create mode 100644 RP_L4/TEST.EGG create mode 100644 RP_L4/WTPresets.cpp create mode 100644 RP_L4/WTPresets.h create mode 100644 RP_L4/last.egg create mode 100644 Setup1/Setup1.vdproj create mode 100644 WinTesla.sln create mode 100644 docs/audionotes.rtf create mode 100644 lib/OpenAL32.lib create mode 100644 lib/libsndfile-1.lib diff --git a/.gitattributes b/.gitattributes new file mode 100644 index 0000000..c6aaf9a --- /dev/null +++ b/.gitattributes @@ -0,0 +1,30 @@ +# Normalize line endings; let Git auto-detect text vs binary +* text=auto + +# Win32 C/C++ source — keep CRLF in the working tree on checkout +*.c text eol=crlf +*.cpp text eol=crlf +*.C text eol=crlf +*.CPP text eol=crlf +*.h text eol=crlf +*.H text eol=crlf +*.hpp text eol=crlf +*.HPP text eol=crlf +*.inc text eol=crlf +*.INC text eol=crlf +*.asm text eol=crlf +*.def text eol=crlf +*.DEF text eol=crlf +*.sln text eol=crlf +*.vcproj text eol=crlf +*.vdproj text eol=crlf +*.ini text eol=crlf +*.INI text eol=crlf + +# Binary assets — never normalize +*.lib binary +*.res binary +*.RES binary +*.egg binary +*.EGG binary +*.rtf binary diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..a76d193 --- /dev/null +++ b/.gitignore @@ -0,0 +1,48 @@ +# Visual Studio build artifacts +[Dd]ebug/ +[Rr]elease/ +[Dd]ebug*/ +[Rr]elease*/ +x64/ +x86/ +[Bb]in/ +[Oo]bj/ +ipch/ +*.aps +*.ncb +*.opensdf +*.sdf +*.suo +*.user +*.cachefile +*.vspscc +*.vssscc +*.pch +*.ilk +*.tlog +*.lastbuildstate +*.idb +*.pdb +*.obj +*.o +*.exe +*.dll +*.exp +*.map + +# Visual Studio per-user / IDE state +.vs/ +*.VC.db +*.VC.opendb + +# Runtime / generated output +*.log +rpl4.log + +# Stale Subversion metadata +.svn/ + +# OS cruft +Thumbs.db +desktop.ini +.DS_Store diff --git a/DPLSTUB.h b/DPLSTUB.h new file mode 100644 index 0000000..5b06c3a --- /dev/null +++ b/DPLSTUB.h @@ -0,0 +1,40 @@ +#pragma once + +enum dpl_TYPE +{ + dpl_type_error, + dpl_type_scene, + dpl_type_zones, + dpl_type_view, + dpl_type_instance, + dpl_type_dcs, + dpl_type_light, + dpl_type_object, + dpl_type_lod, + dpl_type_geogroup, + dpl_type_geometry, + dpl_type_material, + dpl_type_texture, + dpl_type_texmap, + dpl_type_ramp +}; + +class dpl_OBJECT {}; +class dpl_DCS {}; +class dpl_ZONE {}; +class dpl_PARTICLESTART_EFFECT_INFO {}; +class dpl_VIEW {}; +class dpl_INSTANCE {}; +class dpl_GEOGROUP {}; +class dpl_GEOMETRY {}; +class dpl_LIGHT {}; +class dpl_LIGHT_TYPE {}; +class dpl_LOAD_MODE {}; +class dpl_ISECT_MODE {}; +class dpl_TEXTURE {}; +class dpl_MATERIAL {}; +class dpl_TEXMAP {}; +class dpl_EXPLOSION_EFFECT_INFO {}; +class dpl2d_DISPLAY {}; +class dpl2d_MATRIX {}; + diff --git a/DivLoader/DivLoader.vcproj b/DivLoader/DivLoader.vcproj new file mode 100644 index 0000000..7131b30 --- /dev/null +++ b/DivLoader/DivLoader.vcproj @@ -0,0 +1,172 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/DivLoader/VGCDivLoader.cpp b/DivLoader/VGCDivLoader.cpp new file mode 100644 index 0000000..f304e24 --- /dev/null +++ b/DivLoader/VGCDivLoader.cpp @@ -0,0 +1,1387 @@ +class DPLRenderer; +#include +#include "VGCDivLoader.h" + +using namespace std; + +hash_map VGCDivLoader::mMaterials; +hash_map VGCDivLoader::mTextures; +hash_map VGCDivLoader::mRamps; +hash_map VGCDivLoader::mObjects; + +VGCDivLoader::VGCDivLoader() +{ + //Initialize header to defaults + mHeaderInfo.precision = PRECISION_32BIT; + mHeaderInfo.scale = 1; + mHeaderInfo.type = TYPE_GEOMETRY; + mHeaderInfo.unit = UNIT_INCHES; + + //Initialize surface props to defaults + mMasterProps.b_material_type = 2; + mMasterProps.b_material_name = 0; + mMasterProps.decal_offset = 0; + mMasterProps.drawmode = 0; + mMasterProps.drawmode_width = 1; + mMasterProps.f_material_type = 2; + mMasterProps.f_material_name = 0; + mMasterProps.faceted = 0; + mMasterProps.locks = 0; + mMasterProps.name = 0; + mMasterProps.plane = 0; + mMasterProps.specialInst = 0; + mMasterProps.vertex_mask = 0; + mMasterProps.isImmune = false; + mMasterProps.drawSpheres = false; + + if (mTextures.find("NULL") == mTextures.end()) + { + DivTexture *tex = new DivTexture; + memset(tex,0,sizeof(DivTexture)); + tex->name = new char[5]; + strcpy_s(tex->name,5,"NULL"); + tex->texBuffer = new TexBuffer; + tex->texBuffer->height = 1; + tex->texBuffer->width = 1; + tex->texBuffer->m_buffer = new RGBA*[1]; + tex->texBuffer->m_buffer[0] = new RGBA; + tex->texBuffer->m_buffer[0]->r = 255; + tex->texBuffer->m_buffer[0]->g = 255; + tex->texBuffer->m_buffer[0]->b = 255; + tex->texBuffer->m_buffer[0]->a = 255; + mTextures.insert(std::pair(string("NULL"),tex)); + } +} + +VGCDivLoader::~VGCDivLoader() +{ + delete[] mMasterProps.b_material_name; + delete[] mMasterProps.name; + delete[] mMasterProps.f_material_name; +} + +void VGCDivLoader::parse(LPDIRECT3DDEVICE9 device, char *fileName) +{ + const char BIZ_IDSTR[] = "DIV-BIZ2"; + const char VTX_IDSTR[] = "DIV-VTX2"; + FILE file; + FILE *mFile = &file; + if (fopen_s(&mFile, fileName, "rb") != 0) + return; + + char id[8]; + + fread(&id, 8, 1, mFile); + + //Compare first 8 bits to make sure it's a biz2 file + if (strncmp(id,"DIV-BIZ2",8) != 0) + { + fclose(mFile); + return; + } + + BIZ_IDENTITIES ident; + unsigned int len; + while(!feof(mFile)) + { + //Retrieve ID and length of upcoming block + getBlock(mFile, ident, len); + + switch(ident) + { + case HEADER: + parseHeader(mFile, len); + break; + case TRAILER: + //Output code here + fclose(mFile); + return; + case TEXTURE: + //This should be a geometry file + fseek(mFile,len,SEEK_CUR); + break; + case MATERIAL: + //This should be a geometry file + fseek(mFile,len,SEEK_CUR); + break; + case RAMP: + //This should be a geometry file + fseek(mFile,len,SEEK_CUR); + break; + case OBJECT: + parseObject(mFile, len, fileName); + break; + default: + //Unknown! Skip it + if (!feof(mFile)) + { + fseek(mFile,len,SEEK_CUR); + } + break; + } + } + + fclose(mFile); +} + +void VGCDivLoader::parseHeader(FILE *file, unsigned int len) +{ + //Set identifiable header props + BIZ_IDENTITIES ident; + unsigned int nlen; + + while(len > 0) + { + len -= getBlock(file, ident,nlen); + len -= nlen; + + switch(ident) + { + case HDR_VERSION: + fread(&mHeaderInfo.verMajor,1,1,file); + fread(&mHeaderInfo.verMinor,1,1,file); + break; + case HDR_DATE: + fread(&mHeaderInfo.dateDay,1,1,file); + fread(&mHeaderInfo.dateMon,1,1,file); + fread(&mHeaderInfo.dateYear,1,1,file); + break; + case HDR_TIME: + fread(&mHeaderInfo.timeHour,1,1,file); + fread(&mHeaderInfo.timeMin,1,1,file); + break; + case HDR_SCALE: + fread(&mHeaderInfo.scale,floatSize(),1,file); + break; + case HDR_PRECISION: + char precision; + fread(&precision,1,1,file); + mHeaderInfo.precision = (FloatPrecision)precision; + + if (mHeaderInfo.precision == PRECISION_64BIT) + { + //Don't believe we have any 64 bit files, so fuck it + MessageBox(NULL,_T("PANIC 64 BIT"),_T("OH NOES"),MB_OK); + std::cout << "PANIC: 64 BIT PRECISION." << std::endl; + std::cin.get(); + exit(1); + } + break; + case HDR_FILETYPE: + char type; + fread(&type,1,1,file); + mHeaderInfo.type = (FileType)type; + break; + case HDR_UNIT: + char unit; + fread(&unit,1,1,file); + mHeaderInfo.unit = (Unit)unit; + break; + default: + cout << "UNKNOWN HEADER ENTRY " << ident << endl; + } + } +} + +TexBuffer *VGCDivLoader::LoadVTXFile(char *fileName, DivTexture *tex) +{ + int len = strlen(fileName) + 5; + char *fullFileName = new char[len]; + strcpy_s(fullFileName, len, fileName); + strcat_s(fullFileName, len, ".VTX"); + + FILE *texFile; + if (fopen_s(&texFile, fullFileName, "rb") != 0) + { + delete [] fullFileName; + return NULL; + } + + delete [] fullFileName; + char id[8]; + fread(id, 1, 8, texFile); + + if (strncmp(id, "DIV-VTX2", 8) != 0) + { + fclose(texFile); + return NULL; + } + + unsigned int blen; + BIZ_IDENTITIES ident; + while(!feof(texFile)) + { + //Retrieve ID and length of upcoming block + getBlock(texFile, ident, blen); + + switch(ident) + { + case HEADER: + fseek(texFile, blen, SEEK_CUR); + break; + case VTX_TEX: + tex->texBuffer = new TexBuffer; + unsigned int nlen; + while(blen > 0) + { + blen -= getBlock(texFile, ident, nlen); + blen -= nlen; + + unsigned char pixelWidth; + unsigned char colorSettings; + + switch(ident) + { + case VTX_COLOR: + fread(&colorSettings, 1, 1, texFile); + break; + case VTX_SIZE: + fread(&pixelWidth, 1, 1, texFile); + break; + case VTX_DIMENSIONS: + fread(&tex->texBuffer->width, 4, 1, texFile); + fread(&tex->texBuffer->height, 4, 1, texFile); + break; + default: + if (ident >= 0x68 && ident == 0x68 + colorSettings) + { + int dataPoints = 1; + if (colorSettings & 0x01) + { + dataPoints++; + } + if (colorSettings & 0x02) + { + dataPoints += 2; + } + + int sampleSize = 1; + if (pixelWidth != 0x01) + { + MessageBox(NULL, _T("PANIC: UNEXPECTED SAMPLE SIZE FOR TEX"), _T("PROBLEM"), MB_OK); + } + + int tLen = nlen / (dataPoints * sampleSize); + tex->texBuffer->m_buffer = new RGBA*[tex->texBuffer->height]; + + for (int i=0; i < tex->texBuffer->height; i++) + { + tex->texBuffer->m_buffer[i] = new RGBA[tex->texBuffer->width]; + + for (int j=0; j< tex->texBuffer->width; j++) + { + fread(&tex->texBuffer->m_buffer[i][j].r, 1, 1, texFile); + + if (colorSettings & 0x02) + { + fread(&tex->texBuffer->m_buffer[i][j].g, 1, 1, texFile); + fread(&tex->texBuffer->m_buffer[i][j].b, 1, 1, texFile); + } else + { + tex->texBuffer->m_buffer[i][j].g = tex->texBuffer->m_buffer[i][i].r; + tex->texBuffer->m_buffer[i][j].b = tex->texBuffer->m_buffer[i][i].r; + } + + if (colorSettings & 0x01) + { + fread(&tex->texBuffer->m_buffer[i][j].a, 1, 1, texFile); + } else + { + tex->texBuffer->m_buffer[i][j].a = 255; + } + } + } + } else + { + if (ident >= 0x68) + { + MessageBox(NULL, _T("BAD TEX INFO"), _T("PROBLEMS"), MB_OK); + } else + { + MessageBox(NULL, _T("UNKNOWN TAG IN VTX"), _T("PROBLEM"), MB_OK); + } + fseek(texFile, nlen, SEEK_CUR); + } + } + } + break; + case TRAILER: + fclose(texFile); + return tex->texBuffer; + break; + default: + MessageBox(NULL, _T("UNKNOWN VTX INFO"), _T("PROBLEM"), MB_OK); + fseek(texFile, blen, SEEK_CUR); + break; + } + } + + fclose(texFile); + return tex->texBuffer;; +} + +unsigned char getBSLData(int channel, int value) +{ + int shift = (channel + (((channel + 1) % 2) * 2)) * 4; + int mask = 0xF0 << shift; + return (unsigned char)((value & mask) >> shift); +} + +TexBuffer *VGCDivLoader::LoadBSLFile(char *fileName, char channelIndex, DivTexture *tex) +{ + int len = strlen(fileName) + 5; + char *fullFileName = new char[len]; + strcpy_s(fullFileName, len, fileName); + strcat_s(fullFileName, len, ".BSL"); + + FILE *texFile; + if (fopen_s(&texFile, fullFileName, "rb") != 0) + { + delete [] fullFileName; + return NULL; + } + + char id[8]; + fread(id, 1, 8, texFile); + + delete [] fullFileName; + if (strncmp(id, "DIV-BSL2", 8) != 0) + { + fclose(texFile); + return NULL; + } + + int width, height, depth, nTextures; + + fread(&width, 4, 1, texFile); + fread(&height, 4, 1, texFile); + fread(&depth, 4, 1, texFile); + fseek(texFile, 4, SEEK_CUR); + fread(&nTextures, 4, 1, texFile); + + int usefulChannel = channelIndex; + + for (int i=0; i < nTextures; i++) + { + int header, channel; + fread(&header, 4, 1, texFile); + fread(&channel, 4, 1, texFile); + + char *chanName = new char[header-4]; + fread(chanName, 1, header - 4, texFile); + + delete [] chanName; + } + + tex->texBuffer = new TexBuffer; + tex->texBuffer->height = height; + tex->texBuffer->width = width; + tex->texBuffer->m_buffer = new RGBA*[height]; + for (int i=0; i texBuffer->m_buffer[i] = new RGBA[width]; + for (int j=0; j < width; j++) + { + int val; + fread(&val, 4, 1, texFile); + if (usefulChannel < 6) + { + unsigned char color = getBSLData(usefulChannel,val); + tex->texBuffer->m_buffer[i][j].a = 255; + tex->texBuffer->m_buffer[i][j].r = color; + tex->texBuffer->m_buffer[i][j].g = color; + tex->texBuffer->m_buffer[i][j].b = color; + } else + { + if (usefulChannel == 8) + { + tex->texBuffer->m_buffer[i][j].a = getBSLData(2, val); + } else + { + tex->texBuffer->m_buffer[i][j].a = 255; + } + tex->texBuffer->m_buffer[i][j].r = getBSLData(5, val); + tex->texBuffer->m_buffer[i][j].g = getBSLData(4, val); + tex->texBuffer->m_buffer[i][j].b = getBSLData(3, val); + } + } + } + return tex->texBuffer; +} + +void VGCDivLoader::parseTexture(FILE *file, unsigned int len) +{ + BIZ_IDENTITIES ident; + unsigned int nlen; + + DivTexture *texture = new DivTexture; + memset(texture,0,sizeof(DivTexture)); + texture->alpha = 255; + + char *texMapName = NULL; + char channelIndex = 0; + + while(len > 0) + { + len -= getBlock(file, ident,nlen); + len -= nlen; + + char *fileName; //Name of tex raster file + char *ran; //Temp place for strings + + switch(ident) + { + case GEN_NAME: + { + texture->name = new char[nlen]; + fread(texture->name, 1, nlen, file); + break; + } + case GEN_SCOPE: + fseek(file,1,SEEK_CUR); + break; + case TEX_MAP: + texMapName = new char[nlen]; + fread(texMapName,1,nlen,file); + + break; + case TEX_MINIFY: + fread(&texture->minify,1,1,file); + break; + case TEX_MAGNIFY: + fread(&texture->magnify,1,1,file); + break; + case TEX_ALPHA: + fread(&texture->alpha,1,1,file); + break; + case TEX_WRAP_U: + fread(&texture->wrap_u,1,1,file); + break; + case TEX_WRAP_V: + fread(&texture->wrap_v, 1, 1, file); + break; + case TEX_DETAIL: + fread(&texture->detail_type, 1, 1, file); + if (nlen > 1) + { + texture->detail_name = new char[nlen - 1]; + fread(texture->detail_name, 1, nlen - 1, file); + } + break; + case TEX_BSL_CHANNEL: + //This is the channel index being loaded for a BSL file + fread(&channelIndex, 1, 1, file); + break; + case SRF_SPECIAL: + { + char *pos; + //Awesome + ran = new char[nlen]; + fread(ran,1,nlen,file); + + if ((pos = strstr(ran,"SCROLL")) != NULL) + { + float startu,startv,endu,endv; + sscanf(pos, "SCROLL %f %f %f %f",&startu, &startv, &endu, &endv); + texture->doScroll = true; + texture->scrollU = endu; + texture->scrollV = endv; + } + delete [] ran; + break; + } + default: + MessageBox(NULL,_T("UNKNOWN TEXTURE ENTRY"),_T("PROBLEM"),MB_OK); + if (!feof(file)) + { + fseek(file, nlen, SEEK_CUR); + } + } + } + + //Load up the texture buffer + //Try to load as a BSL first + if ((texture->texBuffer = LoadBSLFile(texMapName, channelIndex, texture)) == NULL) + { + //If that didn't work, do VTX + texture->texBuffer = LoadVTXFile(texMapName, texture); + } + + delete [] texMapName; + + if (texture->name == NULL) + { + delete [] texture->name; + if (texture->detail_name != NULL) + { + delete [] texture->detail_name; + } + if (texture->texBuffer != NULL) + { + delete texture->texBuffer; + } + delete texture; + fseek(file,len,SEEK_CUR); + } else + { + //Add material + mTextures.insert(pair(string(texture->name),texture)); + } +} + +bool VGCDivLoader::parseMaterial(FILE *file, unsigned int len, char *filename) +{ + BIZ_IDENTITIES ident; + unsigned int nlen; + + DivMaterial *material = new DivMaterial; + memset(material,0,sizeof(DivMaterial)); + material->amb_b = 1; + material->amb_g = 1; + material->amb_r = 1; + material->dif_b = 1; + material->dif_g = 1; + material->dif_r = 1; + material->emi_b = 0; + material->emi_g = 0; + material->emi_r = 0; + material->spe_b = 0; + material->spe_g = 0; + material->spe_p = 1; + material->spe_r = 0; + material->opa_b = 1; + material->opa_g = 1; + material->opa_r = 1; + material->isImmune = false; + + while(len > 0) + { + len -= getBlock(file, ident, nlen); + len -= nlen; + + char *ran; //Temp place for strings + + switch(ident) + { + case GEN_NAME: + material->name = new char[nlen]; + fread(material->name, 1, nlen, file); + break; + case GEN_SCOPE: + fseek(file,1,SEEK_CUR); + break; + case MAT_TEXTURE: + fread(&material->tex_type, 1, 1, file); + if (nlen > 1) + { + material->tex_name = new char[nlen - 1]; + fread(material->tex_name, 1, nlen - 1, file); + } + + //Precaching textures moves the file offset, so: + /*loc = ftell(file); + precacheTexture(material->tex_name,file); + fseek(file,loc,SEEK_SET);*/ + //We don't precache textures anymore- they should be local, so screw it + break; + case MAT_ENVIRONMENT: + //Anyone know what this is for? + fread(&material->env_type, 1, 1, file); + material->env_name = new char[nlen - 1]; + fread(material->env_name, 1, nlen - 1, file); + break; + case MAT_AMBIENT: + fread(&material->amb_r, floatSize(), 1, file); + fread(&material->amb_g, floatSize(), 1, file); + fread(&material->amb_b, floatSize(), 1, file); + break; + case MAT_DIFFUSE: + fread(&material->dif_r, floatSize(), 1, file); + fread(&material->dif_g, floatSize(), 1, file); + fread(&material->dif_b, floatSize(), 1, file); + break; + case MAT_SPECULAR: + fread(&material->spe_r, floatSize(), 1, file); + fread(&material->spe_g, floatSize(), 1, file); + fread(&material->spe_b, floatSize(), 1, file); + fread(&material->spe_p, floatSize(), 1, file); + break; + case MAT_EMISSIVE: + fread(&material->emi_r, floatSize(), 1, file); + fread(&material->emi_g, floatSize(), 1, file); + fread(&material->emi_b, floatSize(), 1, file); + break; + case MAT_OPACITY: + fread(&material->opa_r, floatSize(), 1, file); + fread(&material->opa_g, floatSize(), 1, file); + fread(&material->opa_b, floatSize(), 1, file); + break; + case MAT_RAMP: + material->ramp_name = new char[nlen]; + fread(material->ramp_name, 1, nlen, file); + break; + case SRF_SPECIAL: + { + //Awesome! + ran = new char[nlen]; + fread(ran,1,nlen,file); + char *immuneParam = strstr(ran, "IMMUNE"); + if (immuneParam != NULL) + { + material->isImmune = true; + } + delete [] ran; + break; + } + default: + MessageBox(NULL,_T("UNKNOWN MATERIAL ENTRY"),_T("PROBLEM"),MB_OK); + if (!feof(file)) + { + fseek(file, nlen, SEEK_CUR); + } + } + } + + if (material->name == NULL) + { + //This material is nameless? + if (material->env_name) + { + delete [] material->env_name; + } + + if (material->tex_name) + { + delete [] material->tex_name; + } + + if (material->ramp_name) + { + delete [] material->ramp_name; + } + + delete material; + return false; + } else + { + //If there's no material, set it to null. + if (material->tex_type != 2) + { + if (material->tex_name != NULL) + { + delete [] material->tex_name; + } + material->tex_type = 2; + material->tex_name = new char[5]; + strcpy_s(material->tex_name, 5, "NULL"); + } + //Add material + string fullMatName = string(filename); + fullMatName += string(":"); + fullMatName += string(material->name); + mMaterials.insert(pair(fullMatName,material)); + return true; + } +} + +void VGCDivLoader::precacheMaterial(char *name) +{ + FILE *matFile = NULL; + + //Get material file name + char *colon = strstr(name, ":"); + int len = colon - name; + char *fname = new char[(len + 5)]; + char *matFileName = new char[len + 1]; + strncpy(matFileName,name,len); + matFileName[len] = 0; + strncpy(fname, name, len); + fname[len] = 0; + strcat_s(fname,len + 5, ".BMF"); + + //Get actual material name + int matNameLen = strlen(name) - len; + char *mname = new char[matNameLen]; + strcpy_s(mname, matNameLen, colon + 1); + + if (mMaterials.find(string(name)) != mMaterials.end()) + { + //Already precached + return; + } + + //Open the BMF file + int fullDirLen = strlen(fname) + 1; + char *fulldir = new char[fullDirLen]; + strcpy_s(fulldir, fullDirLen, fname); + delete [] fname; + + if (fopen_s(&matFile,fulldir,"rb") != 0) + { + MessageBox(NULL,_T("PANIC MAT FILE FAILED TO OPEN"),_T("SHIT"),MB_OK); + } + + delete [] fulldir; + + //Parse the file + char id[8]; + + fread(&id, 8, 1, matFile); + + //Compare first 8 bits to make sure it's a biz2 file + if (strncmp(id,"DIV-BIZ2",8) != 0) + { + fclose(matFile); + MessageBox(NULL, _T("PANIC MAT FILE WAS NOT MAT FILE"),_T("Oh no"),MB_OK); + } + + unsigned int blen; + BIZ_IDENTITIES ident; + bool done = false; + while(!feof(matFile)) + { + //Retrieve ID and length of upcoming block + getBlock(matFile, ident, blen); + + switch(ident) + { + case MATERIAL: + //This is the only relevant thing right now + parseMaterial(matFile, blen,matFileName); + break; + case RAMP: + parseRamp(matFile,blen); + break; + case TEXTURE: + parseTexture(matFile, blen); + break; + default: + if (!feof(matFile)) + { + fseek(matFile,blen,SEEK_CUR); + } + } + } + delete [] mname; + delete [] matFileName; +} + +void VGCDivLoader::parseRamp(FILE *file, unsigned int len) +{ + BIZ_IDENTITIES ident; + unsigned int nlen; + + DivRamp *ramp = new DivRamp; + memset(ramp, 0, sizeof(DivRamp)); + + char *name; + + while(len > 0) + { + len -= getBlock(file, ident, nlen); + len -= nlen; + + switch(ident) + { + case GEN_NAME: + name = new char[nlen]; + fread(name, 1, nlen, file); + + if (mRamps.find(string(name)) != mRamps.end()) + { + delete [] name; + delete ramp; + fseek(file,len,SEEK_CUR); + return; + } + break; + case GEN_SCOPE: + if (nlen > 0) + { + fseek(file, nlen, SEEK_CUR); + } + break; + case RMP_DATA: + fread(&ramp->r1, floatSize(), 1, file); + fread(&ramp->g1, floatSize(), 1, file); + fread(&ramp->b1, floatSize(), 1, file); + fread(&ramp->r2, floatSize(), 1, file); + fread(&ramp->g2, floatSize(), 1, file); + fread(&ramp->b2, floatSize(), 1, file); + break; + default: + MessageBox(NULL, _T("UNRECOGNIZED RAMP BLOCK"), _T("PROBLEM"), MB_OK); + if (nlen > 0) + { + fseek(file, nlen, SEEK_CUR); + } + break; + } + } + + mRamps[string(name)] = ramp; + delete [] name; +} + +void VGCDivLoader::parseObject(FILE *file, unsigned int len, char *fileName) +{ + BIZ_IDENTITIES ident; + unsigned int nlen; + + DivObject *obj = new DivObject; + obj->objName = new char[strlen(fileName) + 1]; + strcpy_s(obj->objName, strlen(fileName) + 1, fileName); + + while(len > 0) + { + len -= getBlock(file, ident,nlen); + len -= nlen; + + switch(ident) + { + //Set the master set of surface props + case GEN_NAME: + case SRF_F_MATERIAL: + case SRF_B_MATERIAL: + case SRF_PLANE: + case SRF_DRAWMODE: + case SRF_DECAL: + case SRF_FACETED: + case SRF_VERTEX: + case SRF_SPECIAL: + case SRF_LOCK: + parseSurface(file, ident,nlen,mMasterProps); + break; + case LOD: + parseLOD(obj, file, nlen); + break; + case PATCH: + parsePatch(obj, file, nlen); + break; + } + } + + VGCDivLoader::mObjects.insert(std::pair(string(obj->objName), obj)); + +} + +void VGCDivLoader::parseLOD(DivObject *obj, FILE *file, unsigned int len) +{ + //LOD's are only relevant if it's the closest LOD level, + //and the only relevant part are the patches + BIZ_IDENTITIES ident; + unsigned int nlen; + bool parse = false; + + while(len > 0) + { + len -= getBlock(file, ident,nlen); + len -= nlen; + + switch(ident) + { + case LOD_DISTANCE: + float in, out; + fread(&in,floatSize(),1,file); + fread(&out,floatSize(),1,file); + + if (in < 5.0f) + { + //Don't even bother if this isn't a seriously close-up LOD + parse = true; + } + break; + case PATCH: + if (parse) + { + //If this is the right LOD, parse patches + parsePatch(obj, file, nlen); + } else + { + fseek(file,nlen,SEEK_CUR); + } + break; + default: + fseek(file,nlen,SEEK_CUR); + } + } +} + +void VGCDivLoader::parsePatch(DivObject *obj, FILE *file, unsigned int len) +{ + BIZ_IDENTITIES ident; + unsigned int nlen; + bool parse = false; + + DivPatch *patch = new DivPatch; + patch->surface = mMasterProps; + + int *indices; + DivVertex *verts; + + while(len > 0) + { + len -= getBlock(file, ident,nlen); + len -= nlen; + + int n; + + switch(ident) + { + case GEN_NAME: + case SRF_F_MATERIAL: + case SRF_B_MATERIAL: + case SRF_PLANE: + case SRF_DRAWMODE: + case SRF_DECAL: + case SRF_FACETED: + case SRF_VERTEX: + case SRF_SPECIAL: + case SRF_LOCK: + //Edit our patch's surface props + parseSurface(file, ident,nlen,patch->surface); + break; + case POLYGON: + case POLYSTRIP: + //Polystrip is a tri fan. Incidentally, we're treating + //>3 sided polys like tri fans + nlen = 0; + while (!(ident & 0x80)) + { + //Poly lists are the only relevant blocks + if (nlen > 0) + { + fseek(file,nlen,SEEK_CUR); + } + getBlock(file, ident,nlen); + } + + //Parse list of polys + verts = parseVList(file, nlen,(unsigned char)(ident & 0x7F),n); + + indices = new int[n]; + for (int i=0; i 0) + { + fseek(file,nlen,SEEK_CUR); + } + getBlock(file, ident,nlen); + } + + verts = parseVList(file, nlen,(unsigned char)(ident & 0x7F),n); + + indices = new int[n]; + for (int i=0; isurface.drawSpheres = true; + vector verts; + + while (nlen > 0) + { + nlen -= getBlock(file, inident, inlen); + nlen -= inlen; + if (inident == SPHERE) + { + for (int i=0; i < (inlen/(floatSize()*4)); i++) + { + float x,y,z,radius; + fread(&x,floatSize(),1,file); + fread(&y,floatSize(),1,file); + fread(&z,floatSize(),1,file); + fread(&radius,floatSize(),1,file); + DivVertex vert; + vert.x = x * this->mHeaderInfo.scale; + vert.y = y * this->mHeaderInfo.scale; + vert.z = z * this->mHeaderInfo.scale; + vert.mask = 0; + verts.insert(verts.end(),vert); + } + } else if (inlen > 0) + { + fseek(file,nlen,SEEK_CUR); + } + } + + for (int i=0; i < verts.size(); i++) + { + getVertex(verts[i], obj); + } + //setupDrawOps(props); + break; + } + case LINE_LIST: + //Ignore these + fseek(file,nlen,SEEK_CUR); + break; + case TEXT: + //Ignore these + fseek(file,nlen,SEEK_CUR); + break; + default: + cout << "UNKNOWN PATCH VAR " << ident << endl; + } + } + + obj->patches.insert(obj->patches.end(), patch); + +} + +void VGCDivLoader::parseSurface(FILE *file, BIZ_IDENTITIES ident, unsigned int len, SurfaceProps &props) +{ + //These are really straightforward- just move the value + //from the file to the SurfaceProps struct + switch(ident) + { + case GEN_NAME: + props.name = new char[len]; + fread(props.name,1,len,file); + break; + case SRF_F_MATERIAL: + fread(&props.f_material_type,1,1,file); + props.faceted |= 0x02; + if (len > 1) + { + props.f_material_name = new char[len-1]; + fread(props.f_material_name,1,len-1,file); + precacheMaterial(props.f_material_name); + } + break; + case SRF_B_MATERIAL: + fread(&props.b_material_type,1,1,file); + props.faceted |= 0x01; + if (len > 1) + { + props.b_material_name = new char[len-1]; + fread(props.b_material_name,1,len-1,file); + precacheMaterial(props.b_material_name); + } + break; + case SRF_PLANE: + fread(&props.plane,1,1,file); + break; + case SRF_DRAWMODE: + fread(&props.drawmode,1,1,file); + fread(&props.drawmode_width,1,1,file); + break; + case SRF_DECAL: + fread(&props.decal_offset,4,1,file); + break; + case SRF_FACETED: + fread(&props.faceted,1,1,file); + break; + case SRF_VERTEX: + fread(&props.vertex_mask,1,1,file); + break; + case SRF_SPECIAL: + props.specialInst = new char[len]; + fread(props.specialInst,1,len,file); + + break; + case SRF_LOCK: + fread(&props.locks,1,1,file); + break; + default: + cout << "UNKNOWN SURFACE VAR " << ident << endl; + } +} + +void VGCDivLoader::parsePMesh(FILE *file, unsigned int len, DivPatch *patch, DivObject *obj) +{ + //PMeshes are a list of vertices, and a list of vertex indices + //The pmeshes default to 3 side per poly, but can be set different + BIZ_IDENTITIES ident; + unsigned int nlen; + bool parse = false; + + std::vector conLists; + DivVertex *vertList; + + while(len > 0) + { + len -= getBlock(file, ident,nlen); + len -= nlen; + + ConList *list; + + switch(ident) + { + case PMESH_CONLIST: + //old conlists are tris only + list = new ConList; + list->sideCount = 3; + list->numIndices = nlen / 4; + list->indices = new int[list->numIndices]; + fread(list->indices,4,list->numIndices,file); + conLists.insert(conLists.begin(),list); + break; + case PMESH_CONLIST_NEW: + //Newer ones specify the sideage of the polys + list = new ConList; + fread(&list->sideCount,1,1,file); + list->numIndices = (nlen-1) / 4; + list->indices = new int[list->numIndices]; + fread(list->indices,4,list->numIndices,file); + conLists.insert(conLists.begin(),list); + break; + default: + if (ident & 0x80) + { + //Read in verts like normal + int n; + vertList = parseVList(file, nlen,(unsigned char)(ident & 0x7F), n); + } else + { + cout << "UNKNOWN PMESH VAR " << ident << endl; + fseek(file,nlen,SEEK_CUR); + } + } + } + + while(!conLists.empty()) + { + //For each connection list, add polygons from the conlist + //and destroy the connection list + + ConList *list = *conLists.begin(); + + //Replace local vertex indexes with global ones + for (int i=0; i < list->numIndices; i++) + { + list->indices[i] = getVertex(vertList[list->indices[i]], obj); + } + + //Add the individual polygons + for (int i=0; i < list->numIndices; i += list->sideCount) + { + addPolygon(list->indices + i,list->sideCount, patch); + } + + delete [] list->indices; + delete list; + conLists.erase(conLists.begin()); + } + delete [] vertList; +} + +DivVertex *VGCDivLoader::parseVList(FILE *file, unsigned int len, unsigned char mask, int &n) +{ + //The passed-in mask is the format of the vertices, and + //determines the in-file structure + + //Figure out the size-per-vertex + int size = floatSize() * 3; + + if (mask & 0x01) + { + //Normals + size += floatSize() * 3; + } + + if (mask & 0x02) + { + //RGB + size += floatSize() * 4; + } else if (mask & 0x04) + { + //Luminance + size += floatSize() * 2; + } + + if (mask & 0x08) + { + //2D Tex + size += floatSize() * 2; + } else if (mask & 0x10) + { + //3D Tex + size += floatSize() * 3; + } + + //Use the size-per-vertex to derive the number of vertices + n = len / size; + + DivVertex *buffer = new DivVertex[n]; + + //Read in each vertex + for (int i=0; i < n; i++) + { + buffer[i].mask = mask; + fread(&buffer[i].x,floatSize(),1,file); + fread(&buffer[i].y,floatSize(),1,file); + fread(&buffer[i].z,floatSize(),1,file); + //buffer[i].z = -buffer[i].z; + + buffer[i].x *= this->mHeaderInfo.scale; + buffer[i].y *= this->mHeaderInfo.scale; + buffer[i].z *= this->mHeaderInfo.scale; + if (mask & 0x01) + { + //Normals + fread(&buffer[i].Nx,floatSize(),1,file); + fread(&buffer[i].Ny,floatSize(),1,file); + fread(&buffer[i].Nz,floatSize(),1,file); + } else + { + buffer[i].Nx = 0; + buffer[i].Ny = 0; + buffer[i].Nz = 0; + } + + if (mask & 0x02) + { + //RGB + fread(&buffer[i].r,floatSize(),1,file); + fread(&buffer[i].g,floatSize(),1,file); + fread(&buffer[i].b,floatSize(),1,file); + } + + if (mask & 0x04) + { + //Luminance + fread(&buffer[i].l,floatSize(),1,file); + } + + if (mask & 0x06) + { + //RGB or Luminance + fread(&buffer[i].a,floatSize(),1,file); + } + + if (mask & 0x18) + { + //2D or 3D texture + fread(&buffer[i].u,floatSize(),1,file); + //buffer[i].u = 1.0f - buffer[i].u; + fread(&buffer[i].v,floatSize(),1,file); + } + + if (mask & 0x10) + { + //3D texture + fread(&buffer[i].w,floatSize(),1,file); + } + } + + return buffer; +} + +int VGCDivLoader::getBlock(FILE *file, BIZ_IDENTITIES &id, unsigned int &len) +{ + //BIZ_IDENTTAG is ryan's structure that mimics the in-file structure + //of the first two bytes of a block + BIZ_IDENTTAG ident; + + fread(&ident,sizeof(BIZ_IDENTTAG),1,file); + + //Get ID value + int idVal = ident.identity; + idVal = (ident.configBit)?(idVal+2000):idVal; + id = (BIZ_IDENTITIES)idVal; + + //Get File Length + if (ident.headerSize == 2) + { + fread(&len,4,1,file); + return 6; + } else if (ident.headerSize == 1) + { + unsigned short size; + fread(&size,2,1,file); + len = size; + return 4; + } else + { + unsigned char size; + fread(&size,1,1,file); + len = size; + return 3; + } +} + +int VGCDivLoader::floatSize() +{ + return 4; +} + +int VGCDivLoader::getVertex(DivVertex vert, DivObject *obj) +{ + //Try and find vertices, if the vertex doesn't exist, add it + std::vector::iterator it = obj->vertices.begin(); + int i=0; + + while(it != obj->vertices.end() && memcmp(&(*it),&vert,sizeof(DivVertex)) != 0) {++it; ++i;} + + if (it == obj->vertices.end()) + { + obj->vertices.insert(obj->vertices.end(),vert); + } + + //Return the vertex's index in the VGCDivLoader's vertex list + return i; +} + +void VGCDivLoader::addPolygon(int *indices, int numIndices, DivPatch *patch) +{ + //Break the polygon down into a triangle fan and add it to the tris + char facets = patch->surface.faceted; + + for (int i=0; i < numIndices - 2; i++) + { + if (facets & 0x02) + { + Triangle tri; + tri.indices[2] = indices[0]; + tri.indices[1] = indices[i+1]; + tri.indices[0] = indices[i+2]; + patch->frontTriangles.insert(patch->frontTriangles.end(),tri); + } + + if (facets & 0x01) + { + Triangle tri; + tri.indices[0] = indices[0]; + tri.indices[1] = indices[i+1]; + tri.indices[2] = indices[i+2]; + patch->backTriangles.insert(patch->backTriangles.end(),tri); + } + } +} + diff --git a/DivLoader/VGCDivLoader.h b/DivLoader/VGCDivLoader.h new file mode 100644 index 0000000..f3ef054 --- /dev/null +++ b/DivLoader/VGCDivLoader.h @@ -0,0 +1,240 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "tagIdents.h" + +using namespace std; +using namespace stdext; + +enum FloatPrecision +{ + PRECISION_32BIT, + PRECISION_64BIT +}; + +enum FileType +{ + TYPE_GEOMETRY, + TYPE_MATERIAL, + TYPE_TEXTURE +}; + +enum Unit +{ + UNIT_INCHES, + UNIT_MILLIMETERS +}; + +struct BIZ_IDENTTAG +{ + unsigned short identity : 12; + unsigned short RESERVED : 1; + unsigned short configBit : 1; + unsigned short headerSize : 2; +}; + +struct HeaderInfo +{ + char verMajor; + char verMinor; + + char dateDay; + char dateMon; + char dateYear; + + char timeHour; + char timeMin; + + float scale; + + FloatPrecision precision; + + FileType type; + + Unit unit; +}; + +struct DivVertex +{ + char mask; + float x,y,z; + + float Nx,Ny,Nz; + + float r,g,b; + float l; + float a; + + float u,v; + float w; +}; + +struct ConList +{ + unsigned char sideCount; + int numIndices; + int *indices; +}; + +struct Triangle +{ + int indices[3]; +}; + +struct SurfaceProps +{ + char *name; + + char f_material_type; + char *f_material_name; + + char b_material_type;//Slinky has too much comments + char *b_material_name; + + char plane; + + char drawmode; + char drawmode_width; + + int decal_offset; + + char faceted; + + char vertex_mask; + + char *specialInst; + + char locks; + + bool isImmune; + + bool drawSpheres; +}; + +struct DivPatch +{ + vector frontTriangles; + vector backTriangles; + SurfaceProps surface; +}; + +struct DivObject +{ + char *objName; + + vector vertices; + vector patches; +}; + +struct DivMaterial +{ + char *name; + + unsigned char tex_type; + char *tex_name; + + unsigned char env_type; + char *env_name; + + float amb_r, amb_g, amb_b; //Ambient + float dif_r, dif_g, dif_b; //Diffuse + float spe_r, spe_g, spe_b, spe_p; //Specular + float emi_r, emi_g, emi_b; //Emissive + float opa_r, opa_g, opa_b; //Opacity + + char *ramp_name; + + bool isImmune; +}; + +struct RGBA +{ + unsigned char r, g, b, a; +}; + +struct TexBuffer +{ + int height, width; + RGBA **m_buffer; +}; + +struct DivTexture +{ + char *name; + + TexBuffer *texBuffer; + + unsigned char minify; + unsigned char magnify; + unsigned char alpha; + unsigned char wrap_u; + unsigned char wrap_v; + + unsigned char detail_type; + char *detail_name; + + bool doScroll; + float scrollU; + float scrollV; +}; + +struct DivRamp +{ + float r1, g1, b1; + float r2, g2, b2; +}; + +class VGCDivLoader +{ +public: + VGCDivLoader(); + ~VGCDivLoader(); + + static void FindObject(hyper hashValue); + + void parse(LPDIRECT3DDEVICE9 device, char *fileName); + + static hash_map< string , DivMaterial* > mMaterials; + static hash_map< string , DivTexture* > mTextures; + static hash_map< string , DivRamp* > mRamps; + static hash_map< string, DivObject*> mObjects; + +protected: + HeaderInfo mHeaderInfo; + + void precacheMaterial(char *name); + //void precacheTexture(char *name, FILE *matFile); + TexBuffer *LoadVTXFile(char *fileName, DivTexture *tex); + TexBuffer *LoadBSLFile(char *fileName, char channelIndex, DivTexture *tex); + + void parseHeader(FILE *file, unsigned int len); + void parseTexture(FILE *file, unsigned int len); + bool parseMaterial(FILE *file, unsigned int len, char *filename); + void parseRamp(FILE *file, unsigned int len); + void parseObject(FILE *file, unsigned int len, char *fileName); + + void parseLOD(DivObject *obj, FILE *file, unsigned int len); + void parsePatch(DivObject *obj, FILE *file, unsigned int len); + void parseSurface(FILE *file, BIZ_IDENTITIES ident, unsigned int len, SurfaceProps &props); + + void parsePMesh(FILE *file, unsigned int len, DivPatch *patch, DivObject *obj); + DivVertex *parseVList(FILE *file, unsigned int len, unsigned char vertTypeMask, int &n); + + int getVertex(DivVertex vert, DivObject *obj); + void addPolygon(int *indices, int numIndices, DivPatch *patch); + + int floatSize(); + + int getBlock(FILE *file, BIZ_IDENTITIES &id, unsigned int &length); + + SurfaceProps mMasterProps; + std::vector mVertices; +}; \ No newline at end of file diff --git a/DivLoader/tagIdents.h b/DivLoader/tagIdents.h new file mode 100644 index 0000000..48f6ecc --- /dev/null +++ b/DivLoader/tagIdents.h @@ -0,0 +1,89 @@ +#pragma once + +enum BIZ_IDENTITIES +{ + COMMENT, + REF_COMMENT, + COMMENT_DICT, + + HEADER, + OLD_COMMENT, + TRAILER, + + TEXTURE = 16, + TEX_MAP, + TEX_MINIFY, + TEX_MAGNIFY, + TEX_ALPHA, + TEX_WRAP_U, + TEX_WRAP_V, + TEX_DETAIL, + TEX_BSL_CHANNEL, + + MATERIAL = 32, + MAT_TEXTURE, + MAT_ENVIRONMENT, + MAT_AMBIENT, + MAT_DIFFUSE, + MAT_SPECULAR, + MAT_EMISSIVE, + MAT_OPACITY, + MAT_RAMP, + + RAMP = 48, + RMP_DATA, + + OBJECT = 64, + LOD, + PATCH, + POLYGON, + TRISTRIP, + POLYSTRIP, + PMESH, + PMESH_CONLIST, + SPHERE_LIST, + SPHERE, + LINE_LIST, + TEXT, + TEXT_VAL, + PMESH_CONLIST_NEW, + + VTX_TEX = 96, + + LINE = 128, + + HDR_VERSION = 2002, + HDR_DATE, + HDR_TIME, + HDR_SCALE, + HDR_PRECISION, + HDR_FILETYPE, + GEN_NAME, + HDR_UNIT, + GEN_SCOPE, + + SRF_F_MATERIAL = 2048, + SRF_B_MATERIAL, + SRF_PLANE, + SRF_DRAWMODE, + SRF_DECAL, + SRF_FACETED, + SRF_VERTEX, + SRF_SPECIAL, + SRF_LOCK, + + SPHERE_DICE_V = 2064, + SPHERE_DICE_U, + LINE_THICKNESS, + TEXT_FONT, + TEXT_SCALE, + TEXT_ORIENTATION, + + LOD_DISTANCE = 2070, + LOD_REFERENCE, + LOD_TRANSITION, + + VTX_COLOR = 2096, + VTX_SIZE, + VTX_DIMENSIONS +}; \ No newline at end of file diff --git a/LOGGER.cpp b/LOGGER.cpp new file mode 100644 index 0000000..5df00b2 --- /dev/null +++ b/LOGGER.cpp @@ -0,0 +1,25 @@ +#include +#include "logger.h" + +FILE *Logger::mLogFile = NULL; + +bool Logger::Init(const char *filename) +{ + if (Logger::mLogFile) + fclose(mLogFile); + + Logger::mLogFile = fopen(filename, "w"); + + return (Logger::mLogFile != NULL); +} + +int Logger::Printf(const char *format, ...) +{ + if (!Logger::mLogFile) + return 0; + + va_list argptr; + va_start(argptr, format); + + return vfprintf_s(mLogFile, format, argptr); +} \ No newline at end of file diff --git a/LOGGER.h b/LOGGER.h new file mode 100644 index 0000000..5cf0c90 --- /dev/null +++ b/LOGGER.h @@ -0,0 +1,13 @@ +#pragma once + +#include + +class Logger +{ +public: + static bool Init(const char *filename); + static int Printf(const char *format, ...); + +private: + static FILE *mLogFile; +}; \ No newline at end of file diff --git a/MUNGA/AFFNMTRX.cpp b/MUNGA/AFFNMTRX.cpp new file mode 100644 index 0000000..66053f7 --- /dev/null +++ b/MUNGA/AFFNMTRX.cpp @@ -0,0 +1,785 @@ +#include "munga.h" +#pragma hdrstop + +#include "affnmtrx.h" +#include "matrix.h" +#include "linmtrx.h" +#include "origin.h" + +const AffineMatrix AffineMatrix::Identity(true); + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const volatile AffineMatrix *) + { + return false; + } +#endif + +AffineMatrix& AffineMatrix::BuildIdentity() +{ + Check_Pointer(this); + + entries[0] = 1.0f; + entries[1] = 0.0f; + entries[2] = 0.0f; + entries[3] = 0.0f; + + entries[4] = 0.0f; + entries[5] = 1.0f; + entries[6] = 0.0f; + entries[7] = 0.0f; + + entries[8] = 0.0f; + entries[9] = 0.0f; + entries[10] = 1.0f; + entries[11] = 0.0f; + return *this; +} + +AffineMatrix& AffineMatrix::operator=(const AffineMatrix& m) +{ + Check_Pointer(this); + Check(&m); + + //#if sizeof(entries) > sizeof(m.entries) + //# error memcpy mismatch + //#endif + + memcpy(entries, m.entries, sizeof(m.entries)); + return *this; +} + +AffineMatrix& AffineMatrix::operator=(const Origin& p) +{ + Check_Pointer(this); + Check(&p); + + *this = p.angularPosition; + *this = p.linearPosition; + return *this; +} + +AffineMatrix& AffineMatrix::operator=(const Hinge &hinge) +{ + Check_Pointer(this); + Check(&hinge); + SinCosPair x,y,z; + + switch (hinge.axisNumber) + { + case X_Axis: + x = hinge.rotationAmount; + (*this)(0,0) = 1.0f; + (*this)(0,1) = 0.0f; + (*this)(0,2) = 0.0f; + + (*this)(1,0) = 0.0f; + (*this)(1,1) = x.cosine; + (*this)(1,2) = -x.sine; + + (*this)(2,0) = 0.0f; + (*this)(2,1) = x.sine; + (*this)(2,2) = x.cosine; + + break; + case Y_Axis: + y = hinge.rotationAmount; + (*this)(0,0) = y.cosine; + (*this)(0,1) = 0.0f; + (*this)(0,2) = y.sine; + + (*this)(1,0) = 0.0f; + (*this)(1,1) = 1.0f; + (*this)(1,2) = 0.0f; + + (*this)(2,0) = -y.sine; + (*this)(2,1) = 0.0f; + (*this)(2,2) = y.cosine; + break; + case Z_Axis: + z = hinge.rotationAmount; + (*this)(0,0) = z.cosine; + (*this)(0,1) = -z.sine; + (*this)(0,2) = 0.0f; + + (*this)(1,0) = z.sine; + (*this)(1,1) = z.cosine; + (*this)(1,2) = 0.0f; + + (*this)(2,0) = 0.0f; + (*this)(2,1) = 0.0f; + (*this)(2,2) = 1.0f; + break; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +AffineMatrix& + AffineMatrix::operator=(const EulerAngles &angles) +{ + Check_Pointer(this); + Check(&angles); + + SinCosPair + x, + y, + z; + + x = angles.pitch; + y = angles.yaw; + z = angles.roll; + + (*this)(0,0) = y.cosine*z.cosine; + (*this)(0,1) = y.cosine*z.sine; + (*this)(0,2) = -y.sine; + + (*this)(1,0) = x.sine*y.sine*z.cosine - x.cosine*z.sine; + (*this)(1,1) = x.sine*y.sine*z.sine + x.cosine*z.cosine; + (*this)(1,2) = x.sine*y.cosine; + + (*this)(2,0) = x.cosine*y.sine*z.cosine + x.sine*z.sine; + (*this)(2,1) = x.cosine*y.sine*z.sine - x.sine*z.cosine; + (*this)(2,2) = x.cosine*y.cosine; + + Check(this); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +AffineMatrix& + AffineMatrix::operator=(const YawPitchRoll &angles) +{ + Check_Pointer(this); + Check(&angles); + + SinCosPair + x, + y, + z; + + x = angles.pitch; + y = angles.yaw; + z = angles.roll; + + (*this)(0,0) = y.cosine*z.cosine + x.sine*y.sine*z.sine; + (*this)(0,1) = x.cosine*z.sine; + (*this)(0,2) = x.sine*y.cosine*z.sine - y.sine*z.cosine; + + (*this)(1,0) = x.sine*y.sine*z.cosine - y.cosine*z.sine; + (*this)(1,1) = x.cosine*z.cosine; + (*this)(1,2) = y.sine*z.sine + x.sine*y.cosine*z.cosine; + + (*this)(2,0) = x.cosine*y.sine; + (*this)(2,1) = -x.sine; + (*this)(2,2) = x.cosine*y.cosine; + + Check(this); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const Quaternion &q) +{ + Check_Pointer(this); + Check(&q); + + Scalar + a = q.x*q.y, + b = q.y*q.z, + c = q.z*q.x, + d = q.w*q.x, + e = q.w*q.y, + f = q.w*q.z, + g = q.w*q.w, + h = q.x*q.x, + i = q.y*q.y, + j = q.z*q.z; + + (*this)(0,0) = g + h - i - j; + (*this)(1,0) = 2.0f*(a - f); + (*this)(2,0) = 2.0f*(c + e); + + (*this)(0,1) = 2.0f*(f + a); + (*this)(1,1) = g - h + i - j; + (*this)(2,1) = 2.0f*(b - d); + + (*this)(0,2) = 2.0f*(c - e); + (*this)(1,2) = 2.0f*(b + d); + (*this)(2,2) = g - h - i + j; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const Matrix4x4 &m) +{ + Check_Pointer(this); + Check(&m); + Warn(!Small_Enough(m(0,3))); + Warn(!Small_Enough(m(1,3))); + Warn(!Small_Enough(m(2,3))); + Warn(!Close_Enough(m(3,3),1.0f)); + + (*this)(0,0) = m(0,0); + (*this)(0,1) = m(0,1); + (*this)(0,2) = m(0,2); + + (*this)(1,0) = m(1,0); + (*this)(1,1) = m(1,1); + (*this)(1,2) = m(1,2); + + (*this)(2,0) = m(2,0); + (*this)(2,1) = m(2,1); + (*this)(2,2) = m(2,2); + + (*this)(3,0) = m(3,0); + (*this)(3,1) = m(3,1); + (*this)(3,2) = m(3,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::operator=(const TransposedMatrix &m) +{ + Check_Pointer(this); + Check(&m); + Warn(!Small_Enough(m(3,0))); + Warn(!Small_Enough(m(3,1))); + Warn(!Small_Enough(m(3,2))); + Warn(!Close_Enough(m(3,3),1.0f)); + + (*this)(0,0) = m(0,0); + (*this)(0,1) = m(1,0); + (*this)(0,2) = m(2,0); + + (*this)(1,0) = m(0,1); + (*this)(1,1) = m(1,1); + (*this)(1,2) = m(2,1); + + (*this)(2,0) = m(0,2); + (*this)(2,1) = m(1,2); + (*this)(2,2) = m(2,2); + + (*this)(3,0) = m(0,3); + (*this)(3,1) = m(1,3); + (*this)(3,2) = m(2,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + AffineMatrix::operator==(const AffineMatrix& m) const +{ + Check(this); + Check(&m); + + for (size_t i=0; iW_Axis); + + v->x = (*this)(index,X_Axis); + v->y = (*this)(index,Y_Axis); + v->z = (*this)(index,Z_Axis); +} + +// +//########################################################################### +//########################################################################### +// +void + AffineMatrix::GetToAxis( + size_t index, + Vector3D *v + ) const +{ + Check(this); + Check_Pointer(v); + Warn(index>Z_Axis); + + v->x = (*this)(X_Axis,index); + v->y = (*this)(Y_Axis,index); + v->z = (*this)(Z_Axis,index); +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::SetFromAxis( + size_t index, + const Vector3D &v + ) +{ + Check_Pointer(this); + Check(&v); + Warn(index>W_Axis); + + (*this)(index,X_Axis) = v.x; + (*this)(index,Y_Axis) = v.y; + (*this)(index,Z_Axis) = v.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::SetToAxis( + size_t index, + const Vector3D &v + ) +{ + Check_Pointer(this); + Check(&v); + Warn(index>Z_Axis); + + (*this)(X_Axis,index) = v.x; + (*this)(Y_Axis,index) = v.y; + (*this)(Z_Axis,index) = v.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply( + const AffineMatrix& Source1, + const AffineMatrix& Source2 + ) +{ + Check_Pointer(this); + Check(&Source1); + Check(&Source2); + + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source2(3,2); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Invert(const AffineMatrix& Source) +{ + Check_Pointer(this); + Check(&Source); + + (*this)(0,0) = Source(1,1)*Source(2,2) - Source(1,2)*Source(2,1); + (*this)(1,0) = Source(1,2)*Source(2,0) - Source(1,0)*Source(2,2); + (*this)(2,0) = Source(1,0)*Source(2,1) - Source(1,1)*Source(2,0); + + Scalar det = + (*this)(0,0)*Source(0,0) + + (*this)(1,0)*Source(0,1) + + (*this)(2,0)*Source(0,2); + Verify(!Small_Enough(det)); + + (*this)(3,0) = + -Source(3,0)*(*this)(0,0) + - Source(3,1)*(*this)(1,0) + - Source(3,2)*(*this)(2,0); + + (*this)(0,1) = Source(0,2)*Source(2,1) - Source(0,1)*Source(2,2); + (*this)(1,1) = Source(0,0)*Source(2,2) - Source(0,2)*Source(2,0); + (*this)(2,1) = Source(0,1)*Source(2,0) - Source(0,0)*Source(2,1); + (*this)(3,1) = + -Source(3,0)*(*this)(0,1) + - Source(3,1)*(*this)(1,1) + - Source(3,2)*(*this)(2,1); + + (*this)(0,2) = Source(0,1)*Source(1,2) - Source(0,2)*Source(1,1); + (*this)(1,2) = Source(1,0)*Source(0,2) - Source(0,0)*Source(1,2); + (*this)(2,2) = Source(0,0)*Source(1,1) - Source(0,1)*Source(1,0); + (*this)(3,2) = + -Source(3,0)*(*this)(0,2) + - Source(3,1)*(*this)(1,2) + - Source(3,2)*(*this)(2,2); + + det = 1.0f/det; + for (int i=0; i<12; ++i) + { + entries[i] *= det; + } + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply(const AffineMatrix &m,const Vector3D &v) +{ + Check_Pointer(this); + Check(&m); + Check(&v); + + (*this)(0,0) = m(0,0)*v.x; + (*this)(1,0) = m(1,0)*v.x; + (*this)(2,0) = m(2,0)*v.x; + (*this)(3,0) = m(3,0)*v.x; + + (*this)(0,1) = m(0,1)*v.y; + (*this)(1,1) = m(1,1)*v.y; + (*this)(2,1) = m(2,1)*v.y; + (*this)(3,1) = m(3,1)*v.y; + + (*this)(0,2) = m(0,2)*v.z; + (*this)(1,2) = m(1,2)*v.z; + (*this)(2,2) = m(2,2)*v.z; + (*this)(3,2) = m(3,2)*v.z; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply(const AffineMatrix& m,const Quaternion &q) +{ + Check_Pointer(this); + Check(&m); + Check(&q); + + LinearMatrix t(LinearMatrix::Identity); + t = q; + return Multiply(m,t); +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Multiply(const AffineMatrix &m,const Point3D& p) +{ + Check_Pointer(this); + Check(&m); + Check(&p); + + (*this)(3,0) = m(3,0) + p.x; + (*this)(3,1) = m(3,1) + p.y; + (*this)(3,2) = m(3,2) + p.z; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Scalar + AffineMatrix::Determinant() const +{ + Check(this); + + return + (*this)(0,0)*((*this)(1,1)*(*this)(2,2) - (*this)(1,2)*(*this)(2,1)) + + (*this)(0,1)*((*this)(1,2)*(*this)(2,0) - (*this)(1,0)*(*this)(2,2)) + + (*this)(0,2)*((*this)(1,0)*(*this)(2,1) - (*this)(1,1)*(*this)(2,0)); +} + +// +//########################################################################### +//########################################################################### +// +AffineMatrix& + AffineMatrix::Solve() +{ + Check(this); + + int column; + Scalar temp; + + // + //------------------------------------------------------------------ + // Make sure that we get a decent value into the first diagonal spot + //------------------------------------------------------------------ + // + if (!(*this)(0,0)) + { + for (column=0; column<3; ++column) + if ((*this)(0,column)) + break; + Verify(column != 3); + + // + //-------------- + // Swap the columns + //-------------- + // + temp = (*this)(0,0); + (*this)(0,0) = (*this)(0,column); + (*this)(0,column) = temp; + + temp = (*this)(1,0); + (*this)(1,0) = (*this)(1,column); + (*this)(1,column) = temp; + + temp = (*this)(2,0); + (*this)(2,0) = (*this)(2,column); + (*this)(2,column) = temp; + + temp = (*this)(3,0); + (*this)(3,0) = (*this)(3,column); + (*this)(3,column) = temp; + } + + // + //------------------------------------ + // Make sure the diagonal entry is 1.0 + //------------------------------------ + // + temp = (*this)(0,0); + (*this)(0,0) = 1.0f; + (*this)(1,0) /= temp; + (*this)(2,0) /= temp; + (*this)(3,0) /= temp; + + // + //------------------------ + // Make the first row zero + //------------------------ + // + temp = (*this)(0,1); + (*this)(0,1) = 0.0f; + (*this)(1,1) -= temp * (*this)(1,0); + (*this)(2,1) -= temp * (*this)(2,0); + (*this)(3,1) -= temp * (*this)(3,0); + + temp = (*this)(0,2); + (*this)(0,2) = 0.0f; + (*this)(1,2) -= temp * (*this)(1,0); + (*this)(2,2) -= temp * (*this)(2,0); + (*this)(3,2) -= temp * (*this)(3,0); + + // + //------------------------------------------------------------------- + // Make sure that we get a decent value into the second diagonal spot + //------------------------------------------------------------------- + // + if (!(*this)(1,1)) + { + Verify(!(*this)(2,2)); + + // + //--------------------- + // Swap the (*this) columns + //--------------------- + // + temp = (*this)(1,1); + (*this)(1,1) = (*this)(1,2); + (*this)(1,2) = temp; + + temp = (*this)(2,1); + (*this)(2,1) = (*this)(2,2); + (*this)(2,2) = temp; + + temp = (*this)(3,1); + (*this)(3,1) = (*this)(3,2); + (*this)(3,2) = temp; + } + + // + //----------------------------------- + // Make the second diaginal entry 1.0 + //----------------------------------- + // + temp = (*this)(1,1); + (*this)(1,1) = 1.0f; + (*this)(2,1) /= temp; + (*this)(3,1) /= temp; + + // + //------------------------------------ + // Make the second row zeros otherwise + //------------------------------------ + // + temp = (*this)(1,0); + (*this)(1,0) = 0.0f; + (*this)(2,0) -= temp * (*this)(2,1); + (*this)(3,0) -= temp * (*this)(3,1); + + temp = (*this)(1,2); + (*this)(1,2) = 0.0f; + (*this)(2,2) -= temp * (*this)(2,1); + (*this)(3,2) -= temp * (*this)(3,1); + + // + //--------------------------- + // Make the last diagonal 1.0 + //--------------------------- + // + Verify((*this)(2,2)); + temp = (*this)(2,2); + (*this)(2,2) = 1.0f; + (*this)(3,2) /= temp; + + // + //------------------------------------ + // Make the third row zeros otherwise + //------------------------------------ + // + temp = (*this)(2,0); + (*this)(2,0) = 0.0f; + (*this)(3,0) -= temp * (*this)(3,2); + + temp = (*this)(2,1); + (*this)(2,1) = 0.0f; + (*this)(3,1) -= temp * (*this)(3,2); + + // + //------------------------- + // Return the reduced array + //------------------------- + // + return *this; +} + +// +//########################################################################### +//########################################################################### +// +std::ostream& operator <<(std::ostream& Stream, const AffineMatrix& M) +{ + Check(&M); + return Stream << std::setprecision(4) << "\n\t| " << std::setw(9) << M(0,0) << ", " + << std::setw(9) << M(0,1) << ", " << std::setw(9) << M(0,2) << ", 0 |\n\t| " + << std::setw(9) << M(1,0) << ", " << std::setw(9) << M(1,1) << ", " << std::setw(9) + << M(1,2) << ", 0 |\n\t| " << std::setw(9) << M(2,0) << ", " << std::setw(9) + << M(2,1) << ", " << std::setw(9) << M(2,2) << ", 0 |\n\t| " << std::setw(9) + << M(3,0) << ", " << std::setw(9) << M(3,1) << ", " << std::setw(9) << M(3,2) + << ", 1 |"; +} + +// +//########################################################################### +//########################################################################### +// +Logical AffineMatrix::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) + #include "affnmtrx.tcp" +#endif \ No newline at end of file diff --git a/MUNGA/AFFNMTRX.h b/MUNGA/AFFNMTRX.h new file mode 100644 index 0000000..263f5ae --- /dev/null +++ b/MUNGA/AFFNMTRX.h @@ -0,0 +1,145 @@ +#pragma once + +#include "point3d.h" + +class Origin; +class TransposedMatrix; +class Hinge; +class EulerAngles; +class Quaternion; +class YawPitchRoll; + +class AffineMatrix +{ +public: + static const AffineMatrix Identity; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile AffineMatrix *); + #endif + + Scalar entries[12]; + + // + // Constructors + // + AffineMatrix() {} + AffineMatrix& BuildIdentity(); + AffineMatrix(int) { BuildIdentity(); } + + // + // Assignment Operators + // + AffineMatrix& operator=(const AffineMatrix &m); + AffineMatrix& operator=(const Origin &p); + AffineMatrix& operator=(const Hinge &hinge); + AffineMatrix& operator=(const EulerAngles &angles); + AffineMatrix& operator=(const YawPitchRoll &angles); + AffineMatrix& operator=(const Quaternion &q); + AffineMatrix& operator=(const Point3D &p) { return SetFromAxis(W_Axis, p); } + AffineMatrix& operator=(const Matrix4x4 &m); + AffineMatrix& operator=(const TransposedMatrix &m); + + // + // Comparison operators + // + Logical operator==(const AffineMatrix& m) const; + Logical operator!=(const AffineMatrix& m) const; + + // + // Index operators + // + Scalar& operator()(size_t row, size_t column) + { + Check_Pointer(this); + Warn(row>3); + Warn(column>2); + return entries[(column<<2)+row]; + } + const Scalar& operator()(size_t row, size_t column) const + { + Check_Pointer(this); + Warn(row>3); + Warn(column>2); + return entries[(column<<2)+row]; + } + + // + // Axis Manipulation functions + // + void GetFromAxis(size_t index, Vector3D *v) const; + void GetToAxis(size_t index, Vector3D *v) const; + + AffineMatrix& SetFromAxis(size_t index, const Vector3D &v); + AffineMatrix& SetToAxis(size_t index, const Vector3D &v); + + // + // Matrix Multiplication + // + AffineMatrix& Multiply(const AffineMatrix& m1, const AffineMatrix& m2); + AffineMatrix& operator*=(const AffineMatrix& m) + { + AffineMatrix temp(*this); + return Multiply(temp,m); + } + + // + // Matrix Inversion + // + AffineMatrix& Invert(const AffineMatrix& Source); + AffineMatrix& Invert() + { + AffineMatrix src(*this); + return Invert(src); + } + + // + // Scaling, Rotation and Translation + // + AffineMatrix& Multiply(const AffineMatrix &m,const Vector3D &v); + AffineMatrix& operator*=(const Vector3D &v) + { + AffineMatrix m(*this); + return Multiply(m,v); + } + AffineMatrix& Multiply(const AffineMatrix &m,const Quaternion &q); + AffineMatrix& operator*=(const Quaternion &q) + { + AffineMatrix m(*this); + return Multiply(m,q); + } + AffineMatrix& Multiply(const AffineMatrix &m,const Point3D &p); + AffineMatrix& operator*=(const Point3D& p) + { + AffineMatrix m(*this); + return Multiply(m,p); + } + + // + // Miscellaneous Functions + // + Scalar Determinant() const; + AffineMatrix& Solve(); + + // + // Support functions + // + friend std::ostream& operator <<(std::ostream& stream, const AffineMatrix& m); + Logical TestInstance() const; + static Logical TestClass(); +}; + +inline Point3D& Point3D::operator=(const AffineMatrix& m) +{ + m.GetFromAxis(W_Axis,this); + return *this; +} + +inline MemoryStream& MemoryStream_Read(MemoryStream *stream, AffineMatrix *output) +{ + return stream->ReadBytes(output, sizeof(*output)); +} +inline MemoryStream& MemoryStream_Write(MemoryStream *stream, const AffineMatrix *input) +{ + return stream->WriteBytes(input, sizeof(*input)); +} diff --git a/MUNGA/ANGLE.cpp b/MUNGA/ANGLE.cpp new file mode 100644 index 0000000..24781be --- /dev/null +++ b/MUNGA/ANGLE.cpp @@ -0,0 +1,167 @@ +#include "munga.h" +#pragma hdrstop + +#include "angle.h" + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const volatile Radian *) + { + return false; + } +#endif + +Scalar Radian::Normalize(Scalar Value) +{ + Scalar temp; + + temp = fmod(Value,TWO_PI); + if (temp > PI) { + temp -= TWO_PI; + } + else if (temp < -PI) { + temp += TWO_PI; + } + return temp; +} + +// +//############################################################################# +//############################################################################# +// +Radian& + Radian::Normalize() +{ + Check(this); + angle = fmod(angle,TWO_PI); + if (angle > PI) { + angle -= TWO_PI; + } + else if (angle < -PI) { + angle += TWO_PI; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Radian& + Radian::Lerp(const Radian &a,const Radian &b,Scalar t) +{ + Scalar a1,a2; + + Check_Pointer(this); + Check(&a); + Check(&b); + a1 = Radian::Normalize(a.angle); + a2 = Radian::Normalize(b.angle); + if (a2-a1 > PI) { + a2 -= TWO_PI; + } + else if (a2-a1 < -PI) { + a2 += TWO_PI; + } + angle = ::Lerp(a1, a2, t); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator<<(std::ostream& stream, const Radian& radian) +{ + return stream << radian.angle << " rad"; +} + +// +//############################################################################# +//############################################################################# +// +Logical Radian::TestInstance() const +{ + return angle >= -100.0f && angle <= 100.0f; +} + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const volatile Degree *) + { + return false; + } +#endif + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator<<(std::ostream& stream, const Degree& degree) +{ + return stream << degree.angle << " deg"; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Degree::TestInstance() const +{ + return True; +} + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile SinCosPair *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +SinCosPair& + SinCosPair::operator=(const Radian &radian) +{ + Check_Pointer(this); + Check(&radian); + + cosine = cos(radian); + sine = sin(radian); + #if defined(__BCPLUSPLUS__) + cosine = cos(radian); // STUPID FUCKING BORLAND LIBRARY HACK!!!!! + #endif + Check(this); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator<<(std::ostream& stream, const SinCosPair& pair) +{ + return stream << '{' << pair.cosine << ',' << pair.sine << '}'; +} + +// +//############################################################################# +//############################################################################# +// +Logical SinCosPair::TestInstance() const +{ + Scalar t = sine*sine + cosine*cosine; + if (!Close_Enough(t,1.0f,0.001f)) + { + Dump(*this); + Dump(t); + return False; + } + return True; +} + +#if defined(TEST_CLASS) +# include "angle.tcp" +#endif \ No newline at end of file diff --git a/MUNGA/ANGLE.h b/MUNGA/ANGLE.h new file mode 100644 index 0000000..8812552 --- /dev/null +++ b/MUNGA/ANGLE.h @@ -0,0 +1,228 @@ +#pragma once + +#include "scalar.h" + +class Degree; +class SinCosPair; + +class Radian +{ +public: + Scalar angle; + +#if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Radian *); +#endif + + Radian() {} + Radian(Scalar angle) { this->angle = angle; } + + Radian& operator=(Scalar angle) + { + Check_Pointer(this); + this->angle = angle; + return *this; + } + Radian& operator=(const Radian &radian) + { + Check_Pointer(this); + Check(&radian); + angle = radian.angle; + return *this; + } + Radian& operator=(const Degree °ree); + Radian& operator=(const SinCosPair &pair); + + operator Scalar() const + { + Check(this); + return angle; + } + + // + // These comparator functions are not designed to make exact comparisons + // of Scalaring point numbers, but rather to compare them to within some + // specified error threshold + // + Logical operator!() const { return Small_Enough(angle); } + Logical operator==(const Radian &r) const { return Close_Enough(angle, r.angle); } + Logical operator==(float r) const { return Close_Enough(angle, r); } + Logical operator!=(const Radian &r) const { return !Close_Enough(angle, r.angle); } + Logical operator!=(float r) const { return !Close_Enough(angle, r); } + + Radian& Negate(Scalar r) + { + Check_Pointer(this); + angle = -r; + return *this; + } + + Radian& Add(Scalar r1, Scalar r2) + { + Check_Pointer(this); + angle = r1 + r2; + return *this; + } + Radian& operator+=(Scalar r) + { + Check(this); + angle += r; + return *this; + } + + Radian& Subtract(Scalar r1, Scalar r2) + { + Check_Pointer(this); + angle = r1 - r2; + return *this; + } + Radian& operator-=(Scalar r) + { + Check(this); + angle -= r; + return *this; + } + + Radian& Multiply(Scalar r1, Scalar r2) + { + Check_Pointer(this); + angle = r1 * r2; + return *this; + } + Radian& operator*=(Scalar r) + { + Check(this); + angle *= r; + return *this; + } + + Radian& Divide(Scalar r1, Scalar r2) + { + Check_Pointer(this); + Verify(!Small_Enough(r2)); + angle = r1 / r2; + return *this; + } + Radian& operator/=(Scalar r) + { + Check(this); + Verify(!Small_Enough(r)); + angle /= r; + return *this; + } + + Radian& Lerp(const Radian &a, const Radian &b, Scalar t); + + static Scalar Normalize(Scalar value); + Radian& Normalize(); + + friend std::ostream& operator<<(std::ostream& stream, const Radian &radian); + Logical TestInstance() const; + static Logical TestClass(); +}; + +class Degree +{ +public: + Scalar angle; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Degree *); + #endif + + // + // constructors + // + Degree() {} + Degree(Scalar angle) { this->angle = angle; } + + // + // Assignment operators + // + Degree& operator=(const Degree °ree) + { + Check(this); + Check(°ree); + angle = degree.angle; + return *this; + } + Degree& operator=(Scalar angle) + { + Check(this); + this->angle = angle; + return *this; + } + Degree& operator=(const Radian &radian) + { + Check(this); + Check(&radian); + angle = radian.angle * DEG_PER_RAD; + return *this; + } + + // + // Support functions + // + friend std::ostream& operator<<(std::ostream& stream, const Degree &angle); + Logical TestInstance() const; + static Logical TestClass(); +}; + +inline Radian& Radian::operator=(const Degree& degree) +{ + Check_Pointer(this); + Check(°ree); + angle = degree.angle * RAD_PER_DEG; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SinCosPair ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class SinCosPair +{ + public: + Scalar sine, cosine; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile SinCosPair *); + #endif + + // + // Constructors + // + SinCosPair() {} + SinCosPair(Scalar sin, Scalar cos) + { + Check_Pointer(this); + sine = sin; + cosine = cos; + Check(this); + } + + // + // Assignment operators + // + SinCosPair& operator=(const SinCosPair &pair) + { + Check_Pointer(this); + Check(&pair); + sine = pair.sine; cosine = pair.cosine; + return *this; + } + SinCosPair& operator=(const Radian &radian); + + // + // Support functions + // + friend std::ostream& operator<<(std::ostream& stream, const SinCosPair &pair); + Logical TestInstance() const; + static Logical TestClass(); +}; + +inline Radian& Radian::operator=(const SinCosPair& pair) +{ + Check_Pointer(this); + Check(&pair); + angle = Arctan(pair.sine, pair.cosine); + return *this; +} diff --git a/MUNGA/ANIMTOOL.cpp b/MUNGA/ANIMTOOL.cpp new file mode 100644 index 0000000..27c0c20 --- /dev/null +++ b/MUNGA/ANIMTOOL.cpp @@ -0,0 +1,1088 @@ +#include "munga.h" +#pragma hdrstop + +#include "tool.h" +#include "fileutil.h" +#include "joint.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ApplicationTool::WriteAnimationCycle( + NotationFile *animation_file, + StreamableResourceFile *file, + const char *animation_name + ) +{ + int frame_count; + int joint_count; + int i; + + if (!animation_file->GetEntry("HEADER", "framecount", &frame_count)) + { + std::cout << "No framecount in HEADER for animation " << animation_name << std::endl; + return False; + } + + if (!animation_file->GetEntry("HEADER", "jointcount", &joint_count)) + { + std::cout << "No jointcount in HEADER for animation " << animation_name << std::endl; + return False; + } + + char **joint_indices = new char *[joint_count]; + int *joint_indices_numbers = new int[joint_count]; + Register_Pointer(joint_indices_numbers); + Register_Pointer(joint_indices); + + NameList *joint_list = animation_file->MakeEntryList("JointIndices"); + Register_Object(joint_list); + NameList::Entry *entry = joint_list->GetFirstEntry(); + + i = 0; + while (entry != NULL) + { + if (entry->GetData()) + { + joint_indices_numbers[i] = entry->GetAtoi(); + //Dump(entry->GetName()); + joint_indices[i] = new char[strlen(entry->GetName()) +2 ]; + Register_Pointer(joint_indices[i]); + strcpy(joint_indices[i], entry->GetName()); + ++i; + } + entry = entry->GetNextEntry(); + } + + + Unregister_Object(joint_list); + delete joint_list; + + + Scalar *frame_time = new Scalar[frame_count]; + Register_Pointer(frame_time); + + NameList *frame_list = animation_file->MakeEntryList("Time", "frame"); + Register_Object(frame_list); + entry = frame_list->GetFirstEntry(); + + i = 0; + + + while (entry != NULL) + { + if (entry->GetData()) + { + frame_time[i] = entry->GetAtof(); + ++i; + } + entry = entry->GetNextEntry(); + } + + + + Unregister_Object(frame_list); + delete frame_list; + + + + char temp[100]; + const char *euler_txt; + char page_name[100]; + + NameList *page_list = animation_file->MakePageList("frame"); + Register_Object(page_list); + entry = page_list->GetFirstEntry(); + + EulerAngles *keyframe = new EulerAngles[joint_count*frame_count]; + Register_Pointer(keyframe); + + int keycounter = 0; + + + while (entry != NULL) + { + if (entry->GetData()) + { + strcpy(page_name, entry->GetName()); + + for (int j = 0; j < joint_count; ++j) + { + if (!animation_file->GetEntry(page_name, joint_indices[j], &euler_txt)) + { + std::cout << "No page for joint " << j << "in page " << page_name + << " - joint " << joint_indices[j] << std::endl; + Unregister_Object(page_list); + delete page_list; + + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + + strcpy(temp, euler_txt); + strtok(temp,White_Space); + + + keyframe[keycounter].pitch = atof(temp); + keyframe[keycounter].yaw = atof(NextToken()) ; + keyframe[keycounter].roll = atof(NextToken()); + ++keycounter; + } + } + entry = entry->GetNextEntry(); + + } + Unregister_Object(page_list); + delete page_list; + + + NameList *root_list = animation_file->MakeEntryList("RootTranslation", "frame"); + Register_Object(root_list); + entry = root_list->GetFirstEntry(); + + Vector3D *root_trans = new Vector3D[frame_count]; + Register_Pointer(root_trans); + + i = 0; + + while (entry != NULL) + { + if (entry->GetData()) + { + char *root_txt = entry->GetChar(); + + strcpy(temp, root_txt); + strtok(temp,White_Space); + + root_trans[i].x = atof(temp); + root_trans[i].y = atof(NextToken()); + root_trans[i].z = atof(NextToken()); + + ++i; + } + entry = entry->GetNextEntry(); + } + + Unregister_Object(root_list); + delete root_list; + + + NameList *keyjoint_list = animation_file->MakeEntryList("KeyJointPos", "frame"); + Vector3D *keyjoint_trans; + + Logical key_used = False; + + if (keyjoint_list) + { + key_used = True; + Register_Object(keyjoint_list); + entry = keyjoint_list->GetFirstEntry(); + + keyjoint_trans = new Vector3D[frame_count]; + Register_Pointer(keyjoint_trans); + + i = 0; + + + while (entry != NULL) + { + if (entry->GetData()) + { + char *keyjoint_txt = entry->GetChar(); + + strcpy(temp, keyjoint_txt); + strtok(temp,White_Space); + + keyjoint_trans[i].x = atof(temp); + keyjoint_trans[i].y = atof(NextToken()); + keyjoint_trans[i].z = atof(NextToken()); + + ++i; + } + entry = entry->GetNextEntry(); + } + + Unregister_Object(keyjoint_list); + delete keyjoint_list; + + } + + // + // Take bottom 5% of scaling for foot_step + // + + float foot_step = 0.0f; + + if (key_used) + { + float min_step = keyjoint_trans[0].y; + float max_step = keyjoint_trans[0].y; + + for (i = 0; i < frame_count; ++i) + { + if (keyjoint_trans[i].y < min_step) + { + min_step = keyjoint_trans[i].y; + } + if (keyjoint_trans[i].y > max_step) + { + max_step = keyjoint_trans[i].y; + } + } + + if (min_step == max_step) + { + foot_step = min_step; + } + else + { + float diffrence = (float)max_step - (float)min_step; + float percent = (float)diffrence * 0.20f; + foot_step = (float)min_step + (float)percent; + } + } + + NameList *jointtype_list = animation_file->MakeEntryList("JointType"); + Register_Object(jointtype_list); + entry = jointtype_list->GetFirstEntry(); + + Joint::JointType *joint_type = new Joint::JointType[joint_count]; + Register_Pointer(joint_type); + + i = 0; + + + while (entry != NULL) + { + if (entry->GetData()) + { + char *keyjoint_txt = entry->GetChar(); + + if (!stricmp(keyjoint_txt, "ball")) + { + joint_type[i] = Joint::BallJointType; + } + else if (!stricmp(keyjoint_txt, "hingex")) + { + joint_type[i] = Joint::HingeXJointType; + } + else if (!stricmp(keyjoint_txt, "hingey")) + { + joint_type[i] = Joint::HingeYJointType; + } + else if (!stricmp(keyjoint_txt, "hingez")) + { + joint_type[i] = Joint::HingeZJointType; + } + else if (!stricmp(keyjoint_txt, "balltranslate")) + { + joint_type[i] = Joint::BallTranslationJointType; + } + else if (!stricmp(keyjoint_txt, "static")) + { + std::cout << "No static joints allowed!" << std::endl; + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + else + { + Dump(keyjoint_txt); + std::cout << "Unrecognized Joint Type" << std::endl; + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + + ++i; + } + entry = entry->GetNextEntry(); + } + + Unregister_Object(jointtype_list); + delete(jointtype_list); + + + //############################################################ + // Write Resource + //############################################################ + + + int huge_honkin_array_size = sizeof(frame_count) + sizeof(joint_count); + huge_honkin_array_size += sizeof(float); + huge_honkin_array_size += (joint_count * sizeof(int)); + huge_honkin_array_size += (frame_count * sizeof(Scalar)); + + // Change size for ball or hinge + // or for ball translation + + + //huge_honkin_array_size += joint_count * frame_count * sizeof(EulerAngles); + + + for (i = 0; i < joint_count; ++i) + { +// Dump(i); + if (joint_type[i] == Joint::BallJointType) + { + huge_honkin_array_size += (sizeof(EulerAngles) * frame_count); + } + else if (joint_type[i] == Joint::HingeXJointType) + { + huge_honkin_array_size += (sizeof(Hinge) * frame_count); + } + else if (joint_type[i] == Joint::HingeYJointType) + { + huge_honkin_array_size += (sizeof(Hinge) * frame_count); + } + else if (joint_type[i] == Joint::HingeZJointType) + { + huge_honkin_array_size += (sizeof(Hinge) * frame_count); + } + else if (joint_type[i] == Joint::BallTranslationJointType) + { + huge_honkin_array_size += (sizeof(EulerAngles) * frame_count); + huge_honkin_array_size += (sizeof(Vector3D) * frame_count); + } + else + { + Dump(joint_type[i]); + std::cout << "Unknown Joint type" << std::endl; + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + } + + huge_honkin_array_size += (frame_count * sizeof(Vector3D)); + + // adjust for long's instead of chars + + huge_honkin_array_size += 3; + size_t long_array_size = huge_honkin_array_size >> 2; + + long *huge_honkin_array = new long[long_array_size]; + Register_Pointer(huge_honkin_array); + #if DEBUG_LEVEL>0 + long *end_of_array = huge_honkin_array + long_array_size; + #endif + EulerAngles *p = (EulerAngles *)huge_honkin_array; + + + + + *(int*)p = frame_count; + p = (EulerAngles *)((char *)p+sizeof(frame_count)); + + *(int*)p = joint_count; + p = (EulerAngles *)((char *)p+sizeof(joint_count)); + + *(float*)p = foot_step; + p = (EulerAngles *)((char *)p+sizeof(foot_step)); + + for (i = 0; i < joint_count; ++i) + { + *(int*)p = joint_indices_numbers[i]; + p = (EulerAngles *)((char *)p+sizeof(joint_indices_numbers[i])); + } + + for (i = 0; i < frame_count; ++i) + { + *(Scalar*)p = frame_time[i]; + p = (EulerAngles *)((char *)p+sizeof(frame_time[i])); + } + +//######################################################################## +// THIS MUST CHANGE TO USE DIFFRENT JOINT TYPES +// + + + keycounter = 0; + for (i = 0; i < frame_count; ++i) + { + for (int j = 0; j < joint_count; ++j) + { + if (joint_type[j] == Joint::BallJointType) + { + *(EulerAngles*)p = keyframe[keycounter]; + p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter])); + } + else if (joint_type[j] == Joint::HingeXJointType) + { + Hinge hinge(X_Axis, keyframe[keycounter].pitch); + *(Hinge*)p = hinge; + p = (EulerAngles *)((char *)p+sizeof(hinge)); + } + else if (joint_type[j] == Joint::HingeYJointType) + { + Hinge hinge(Y_Axis, keyframe[keycounter].yaw); + *(Hinge*)p = hinge; + p = (EulerAngles *)((char *)p+sizeof(hinge)); + } + else if (joint_type[j] == Joint::HingeZJointType) + { + Hinge hinge(Z_Axis, keyframe[keycounter].roll); + *(Hinge*)p = hinge; + p = (EulerAngles *)((char *)p+sizeof(hinge)); + } + else if (joint_type[j] == Joint::BallTranslationJointType) + { + *(EulerAngles*)p = keyframe[keycounter]; + p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter])); + *(Vector3D*)p = keyjoint_trans[i]; + p = (EulerAngles *)((char *)p+sizeof(keyjoint_trans[i])); + } + + ++keycounter; + } + } + +// +// +//######################################################################### + + + for (i = 0; i < frame_count; ++i) + { + *(Vector3D*)p = root_trans[i]; + p = (EulerAngles *)((char *)p+sizeof(root_trans[i])); + } + + Verify((void*)p == (void*)end_of_array); + + file->AddResource( + animation_name, + ResourceDescription::AnimationResourceType, + 1, + ResourceDescription::Preload, + huge_honkin_array, + long_array_size * sizeof(long) + ); + + //--------------------- + // Delete everything + //--------------------- + + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + + Unregister_Pointer(joint_type); + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + Unregister_Pointer(root_trans); + Unregister_Pointer(huge_honkin_array); + delete[] joint_type; + delete[] huge_honkin_array; + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + delete[] root_trans; + + if (key_used) + { + Unregister_Pointer(keyjoint_trans); + delete[] keyjoint_trans; + } + return True; +} + + +//##################################################################### + +// +// This doesn't have the last frame... +// + +Logical + ApplicationTool::WriteAnimationTransition( + NotationFile *animation_file, + StreamableResourceFile *file, + const char *animation_name + ) +{ + + int frame_count; + int joint_count; + int i; + + if (!animation_file->GetEntry("HEADER", "framecount", &frame_count)) + { + std::cout << "No framecount in HEADER for animation " << animation_name << std::endl; + return False; + } + + //animation_file->GetEntry("HEADER", "framerate", &frame_rate); + + if (!animation_file->GetEntry("HEADER", "jointcount", &joint_count)) + { + std::cout << "No jointcount in HEADER for animation " << animation_name << std::endl; + return False; + } + + + + //animation_file->GetEntry("HEADER", "skeletonfile", &skeleton_file_name); + + + + + char **joint_indices = new char *[joint_count]; + int *joint_indices_numbers = new int[joint_count]; + Register_Pointer(joint_indices_numbers); + Register_Pointer(joint_indices); + + + + NameList *joint_list = animation_file->MakeEntryList("JointIndices"); + Register_Object(joint_list); + NameList::Entry *entry = joint_list->GetFirstEntry(); + + i = 0; + while (entry != NULL) + { + if (entry->GetData()) + { + joint_indices_numbers[i] = entry->GetAtoi(); + //Dump(entry->GetName()); + joint_indices[i] = new char[strlen(entry->GetName()) +2 ]; + Register_Pointer(joint_indices[i]); + strcpy(joint_indices[i], entry->GetName()); + ++i; + } + entry = entry->GetNextEntry(); + } + + + Unregister_Object(joint_list); + delete joint_list; + + + Scalar *frame_time = new Scalar[frame_count]; + Register_Pointer(frame_time); + + NameList *frame_list = animation_file->MakeEntryList("Time", "frame"); + Register_Object(frame_list); + entry = frame_list->GetFirstEntry(); + + i = 0; + + while (entry != NULL) + { + if (entry->GetData()) + { + frame_time[i] = entry->GetAtof(); + ++i; + } + entry = entry->GetNextEntry(); + } + + + + Unregister_Object(frame_list); + delete frame_list; + + + + char temp[100]; + const char *euler_txt; + char page_name[100]; + + NameList *page_list = animation_file->MakePageList("frame"); + Register_Object(page_list); + entry = page_list->GetFirstEntry(); + + EulerAngles *keyframe = new EulerAngles[joint_count*frame_count]; + Register_Pointer(keyframe); + + int keycounter = 0; + + while (entry != NULL) + { + if (entry->GetData()) + { + strcpy(page_name, entry->GetName()); + + for (int j = 0; j < joint_count; ++j) + { + if (!animation_file->GetEntry(page_name, joint_indices[j], &euler_txt)) + { + std::cout << "No page for joint " << j << "in page " << page_name + << " - joint " << joint_indices[j] << std::endl; + Unregister_Object(page_list); + delete page_list; + + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + + Verify(keycounter < joint_count*frame_count); + + strcpy(temp, euler_txt); + strtok(temp,White_Space); + + + keyframe[keycounter].pitch = atof(temp); + keyframe[keycounter].yaw = atof(NextToken()) ; + keyframe[keycounter].roll = atof(NextToken()); + ++keycounter; + } + } + entry = entry->GetNextEntry(); + + } + Unregister_Object(page_list); + delete page_list; + + + NameList *root_list = animation_file->MakeEntryList("RootTranslation", "frame"); + Register_Object(root_list); + entry = root_list->GetFirstEntry(); + + Vector3D *root_trans = new Vector3D[frame_count]; + Register_Pointer(root_trans); + + i = 0; + + while (entry != NULL) + { + if (entry->GetData()) + { + char *root_txt = entry->GetChar(); + + strcpy(temp, root_txt); + strtok(temp,White_Space); + + root_trans[i].x = atof(temp); + root_trans[i].y = atof(NextToken()); + root_trans[i].z = atof(NextToken()); + + ++i; + } + entry = entry->GetNextEntry(); + } + + Unregister_Object(root_list); + delete root_list; + + + + + NameList *keyjoint_list = animation_file->MakeEntryList("KeyJointPos", "frame"); + Vector3D *keyjoint_trans; + Logical key_used = False; + + if (keyjoint_list) + { + key_used = True; + Register_Object(keyjoint_list); + entry = keyjoint_list->GetFirstEntry(); + + keyjoint_trans = new Vector3D[frame_count]; + Register_Pointer(keyjoint_trans); + + i = 0; + + while (entry != NULL) + { + if (entry->GetData()) + { + char *keyjoint_txt = entry->GetChar(); + + strcpy(temp, keyjoint_txt); + strtok(temp,White_Space); + + keyjoint_trans[i].x = atof(temp); + keyjoint_trans[i].y = atof(NextToken()); + keyjoint_trans[i].z = atof(NextToken()); + + ++i; + } + entry = entry->GetNextEntry(); + } + + Unregister_Object(keyjoint_list); + delete keyjoint_list; + } + + // + // Take bottom 5% of scaling for foot_step + // + + float foot_step = 0.0f; + + if (key_used) + { + float min_step = keyjoint_trans[0].y; + float max_step = keyjoint_trans[0].y; + + for (i = 0; i < frame_count; ++i) + { + if (keyjoint_trans[i].y < min_step) + { + min_step = keyjoint_trans[i].y; + } + if (keyjoint_trans[i].y > max_step) + { + max_step = keyjoint_trans[i].y; + } + } + + if (min_step == max_step) + { + foot_step = min_step; + } + else + { + float diffrence = (float)max_step - (float)min_step; + float percent = (float)diffrence * 0.20f; + foot_step = (float)min_step + (float)percent; + } + } + + NameList *jointtype_list = animation_file->MakeEntryList("JointType"); + Register_Object(jointtype_list); + entry = jointtype_list->GetFirstEntry(); + + Joint::JointType *joint_type = new Joint::JointType[joint_count]; + Register_Pointer(joint_type); + + i = 0; + + + while (entry != NULL) + { + if (entry->GetData()) + { + char *keyjoint_txt = entry->GetChar(); + + if (!stricmp(keyjoint_txt, "ball")) + { + joint_type[i] = Joint::BallJointType; + } + else if (!stricmp(keyjoint_txt, "hingex")) + { + joint_type[i] = Joint::HingeXJointType; + } + else if (!stricmp(keyjoint_txt, "hingey")) + { + joint_type[i] = Joint::HingeYJointType; + } + else if (!stricmp(keyjoint_txt, "hingez")) + { + joint_type[i] = Joint::HingeZJointType; + } + else if (!stricmp(keyjoint_txt, "balltranslate")) + { + joint_type[i] = Joint::BallTranslationJointType; + } + else if (!stricmp(keyjoint_txt, "static")) + { + std::cout << "No static joints allowed!" << std::endl; + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + else + { + Dump(keyjoint_txt); + std::cout << "Unrecognized Joint Type" << std::endl; + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + + ++i; + } + entry = entry->GetNextEntry(); + } + + Unregister_Object(jointtype_list); + delete(jointtype_list); + + + // + // Adjust the frame_count down 1 so it won't write.. + // + + frame_count -= 1; + + + int huge_honkin_array_size = sizeof(frame_count) + sizeof(joint_count); + huge_honkin_array_size += sizeof(foot_step); + huge_honkin_array_size += joint_count * sizeof(int); + huge_honkin_array_size += frame_count * sizeof(Scalar); + + // Change size for ball or hinge + // Don't need to change for ball translation since that + // is already done + + //huge_honkin_array_size += joint_count * frame_count * sizeof(EulerAngles); + + for (i = 0; i < joint_count; ++i) + { +// Dump(i); + if (joint_type[i] == Joint::BallJointType) + { + huge_honkin_array_size += sizeof(EulerAngles) * frame_count; + } + else if (joint_type[i] == Joint::HingeXJointType) + { + huge_honkin_array_size += sizeof(Hinge) * frame_count; + } + else if (joint_type[i] == Joint::HingeYJointType) + { + huge_honkin_array_size += sizeof(Hinge) * frame_count; + } + else if (joint_type[i] == Joint::HingeZJointType) + { + huge_honkin_array_size += sizeof(Hinge) * frame_count; + } + else if (joint_type[i] == Joint::BallTranslationJointType) + { + huge_honkin_array_size += sizeof(EulerAngles) * frame_count; + huge_honkin_array_size += sizeof(Vector3D) * frame_count; + } + else + { + Dump(joint_type[i]); + std::cout << "Unknown Joint type" << std::endl; + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + + return False; + } + } + + huge_honkin_array_size += (frame_count+1) * sizeof(Vector3D); + // the plus one is so this DOES have last frame + + // adjust for long's instead of chars + + huge_honkin_array_size += 3; + size_t long_array_size = huge_honkin_array_size >> 2; + + long *huge_honkin_array = new long[long_array_size]; + Register_Pointer(huge_honkin_array); + #if DEBUG_LEVEL>0 + long *end_of_array = huge_honkin_array + long_array_size; + #endif + EulerAngles *p = (EulerAngles *)huge_honkin_array; + + *(int*)p = frame_count; + p = (EulerAngles *)((char *)p+sizeof(frame_count)); + + *(int*)p = joint_count; + p = (EulerAngles *)((char *)p+sizeof(joint_count)); + + *(float*)p = foot_step; + p = (EulerAngles *)((char *)p+sizeof(foot_step)); + + for (i = 0; i < joint_count; ++i) + { + *(int*)p = joint_indices_numbers[i]; + p = (EulerAngles *)((char *)p+sizeof(joint_indices_numbers[i])); + } + + for (i = 0; i < frame_count; ++i) + { + *(Scalar*)p = frame_time[i]; + p = (EulerAngles *)((char *)p+sizeof(frame_time[i])); + } + + + keycounter = 0; + for (i = 0; i < frame_count; ++i) + { + for (int j = 0; j < joint_count; ++j) + { + if (joint_type[j] == Joint::BallJointType) + { + *(EulerAngles*)p = keyframe[keycounter]; + p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter])); + } + else if (joint_type[j] == Joint::HingeXJointType) + { + Hinge hinge(X_Axis, keyframe[keycounter].pitch); + *(Hinge*)p = hinge; + p = (EulerAngles *)((char *)p+sizeof(hinge)); + } + else if (joint_type[j] == Joint::HingeYJointType) + { + Hinge hinge(Y_Axis, keyframe[keycounter].yaw); + *(Hinge*)p = hinge; + p = (EulerAngles *)((char *)p+sizeof(hinge)); + } + else if (joint_type[j] == Joint::HingeZJointType) + { + Hinge hinge(Z_Axis, keyframe[keycounter].roll); + *(Hinge*)p = hinge; + p = (EulerAngles *)((char *)p+sizeof(hinge)); + } + else if (joint_type[j] == Joint::BallTranslationJointType) + { + *(EulerAngles*)p = keyframe[keycounter]; + p = (EulerAngles *)((char *)p+sizeof(keyframe[keycounter])); + *(Vector3D*)p = keyjoint_trans[i]; + p = (EulerAngles *)((char *)p+sizeof(keyjoint_trans[i])); + } + + ++keycounter; + } + } + + for (i = 0; i < (frame_count + 1); ++i) + { + *(Vector3D*)p = root_trans[i]; + p = (EulerAngles *)((char *)p+sizeof(root_trans[i])); + } + + + + Verify((void*)p == (void*)end_of_array); + + + file->AddResource( + animation_name, + ResourceDescription::AnimationResourceType, + 1, + ResourceDescription::Preload, + huge_honkin_array, + long_array_size * sizeof(long) + ); + + //--------------------- + // Delete everything + //--------------------- + + for (i = 0; i < joint_count; ++i) + { + Unregister_Pointer(joint_indices[i]); + delete[] joint_indices[i]; + } + Unregister_Pointer(joint_type); + Unregister_Pointer(joint_indices_numbers); + Unregister_Pointer(joint_indices); + Unregister_Pointer(keyframe); + Unregister_Pointer(frame_time); + Unregister_Pointer(root_trans); + Unregister_Pointer(huge_honkin_array); + delete[] joint_type; + delete[] huge_honkin_array; + delete[] joint_indices; + delete[] joint_indices_numbers; + delete[] keyframe; + delete[] frame_time; + delete[] root_trans; + + if (key_used) + { + Unregister_Pointer(keyjoint_trans); + delete[] keyjoint_trans; + } + + return True; +} diff --git a/MUNGA/APP.cpp b/MUNGA/APP.cpp new file mode 100644 index 0000000..e6eb8f1 --- /dev/null +++ b/MUNGA/APP.cpp @@ -0,0 +1,1777 @@ +#include "registry.h" +#include "renderer.h" +#include "controls.h" +#include "update.h" +#include "mission.h" +#include "player.h" +#include "director.h" +#include "appmgr.h" +#include "audrend.h" +#include "vidrend.h" +#include "gaugrend.h" +#include "hostmgr.h" +#include "interest.h" +#include "nttmgr.h" +#include "apptask.h" +#include "console.h" +#include "appmsg.h" +#include "evtstat.h" + +#if defined(TRACE_FOREGROUND_PROCESSING) + BitTrace Foreground_Processing("Foreground Processing"); +#endif + +#if defined(TRACE_UPDATE_MANAGER) + BitTrace Update_Manager("Update Manager"); +#endif + +#if defined(TRACE_RENDERER_MANAGER) + BitTrace Renderer_Manager("Renderer Manager"); +#endif + +Application *application = NULL; +int Exit_Code = 0; +Logical Application::suppressGauges = False; + +//############################################################################# +//########################### Application ############################### +//############################################################################# + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Application::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Application, StateQuery), + MESSAGE_ENTRY(Application, CheckLoad), + MESSAGE_ENTRY(Application, RunMission), + MESSAGE_ENTRY(Application, StopMission), + MESSAGE_ENTRY(Application, ResumeMission), + MESSAGE_ENTRY(Application, SuspendMission), + MESSAGE_ENTRY(Application, KeyCommand), + MESSAGE_ENTRY(Application, LoadMission), + MESSAGE_ENTRY(Application, AbortMission) +}; + +Application::MessageHandlerSet& Application::GetMessageHandlers() +{ + static Application::MessageHandlerSet messageHandlers(ELEMENTS(Application::MessageHandlerEntries), Application::MessageHandlerEntries, NetworkClient::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Virtual Data support +// +Derivation* Application::GetClassDerivations() +{ + static Derivation classDerivations(NetworkClient::GetClassDerivations(), "Application"); + return &classDerivations; +} + +Application::SharedData + Application::DefaultData( + Application::GetClassDerivations(), + Application::GetMessageHandlers() + ); + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Application::TestInstance() const +{ + if (!IsDerivedFrom(*GetClassDerivations())) + { + return False; + } + Check(&applicationState); + if (eventQueue) + { + Check(eventQueue); + } + if (networkManager) + { + Check(networkManager); + } + if (entityManager) + { + Check(entityManager); + } + if (registry) + { + Check(registry); + } + if (hostManager) + { + Check(hostManager); + } + if (interestManager) + { + Check(interestManager); + } + if (updateManager) + { + Check(updateManager); + } + if (rendererManager) + { + Check(rendererManager); + } + if (controlsManager) + { + Check(controlsManager); + } + if (intercomManager) + { + Check(intercomManager); + } + if (resourceFile) + { + Check(resourceFile); + } + if (viewpointEntity) + { + Check(viewpointEntity); + } + if (currentMission) + { + Check(currentMission); + } + if (backgroundTasks) + { + Check(backgroundTasks); + } + if (audioRenderer) + { + Check(audioRenderer); + } + if (videoRenderer) + { + Check(videoRenderer); + } + if (gaugeRenderer) + { + Check(gaugeRenderer); + } + return True; +} + +// +//############################################################################# +// Application +//############################################################################# +// +Application::Application( + ResourceFile *resource_file, + ApplicationID application_ID, + ClassID class_ID, + SharedData &shared_data +): + NetworkClient(class_ID, shared_data, ApplicationClientID), + applicationState(ApplicationStateCount) +{ + Check(&shared_data); + Check(resource_file); + + applicationID = application_ID; + + // + // Create the event queue + // + eventQueue = GeneralEventQueue::Make( + EVENT_PRIORITIES_COUNT, + "MUNGA Event Count" + ); + Check(eventQueue); + + // + // Remember the resource file + // + resourceFile = resource_file; + missionPlayer = NULL; + + // + // NULL managers not yet created + // + networkManager = NULL; + registry = NULL; + controlsManager = NULL; + intercomManager = NULL; + backgroundTasks = NULL; + interestManager = NULL; + audioRenderer = NULL; + videoRenderer = NULL; + gaugeRenderer = NULL; + + // + // NULL pointers to other objects not yet created + // + viewpointEntity = NULL; + currentMission = NULL; + + // + // Create base level managers + // + entityManager = new EntityManager; + Register_Object(entityManager); + hostManager = new HostManager; + Register_Object(hostManager); + updateManager = new UpdateManager; + Register_Object(updateManager); + rendererManager = new RendererManager; + Register_Object(rendererManager); + backgroundTasks = new BackgroundTasks; + Register_Object(backgroundTasks); + + // + // Set up game state + // + executeFrames = False; + applicationState.SetState(InitializingState); + currentMission = NULL; + secondsRemainingInGame = 0.0f; + spoolFile = NULL; + routePacketFinished = False; + lastCreationMessage = Now(); + + // + // HACK - Init analysis bits + // + #if defined(TRACE_ON) + trace_manager.ResetTraces(); + #endif +} + +// +//############################################################################# +// GetApplicationManager +//############################################################################# +// +ApplicationManager* + Application::GetApplicationManager() +{ + PlugIteratorOf manager_link(this); + ApplicationManager *mgr; + while ((mgr = manager_link.ReadAndNext()) != NULL) + { + if (mgr->GetClassID() == ApplicationManagerClassID) + { + return mgr; + } + } + return NULL; +} + +Scalar + Application::GetApplicationLoopFrameRate() +{ + ApplicationManager *mgr = GetApplicationManager(); + Check(mgr); + return mgr->GetFrameRate(); +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + Application::Initialize() +{ + Check(this); + + // + //---------------------------- + // Create the interest Manager + //---------------------------- + // + interestManager = MakeInterestManager(); + Register_Object(interestManager); + + // + //-------------------------------------------------------------------------- + // Create the network manager + //-------------------------------------------------------------------------- + // + networkManager = MakeNetworkManager(); + Register_Object(networkManager); + + // + //-------------------------------------------------------------------------- + // Create the registry, load static object streams + //-------------------------------------------------------------------------- + // + registry = MakeRegistry(); + if (registry) + { + Register_Object(registry); + registry->LoadStaticObjectStreamResource(); + } + + // + //-------------------------------------------------------------------------- + // Create the mode manager + //-------------------------------------------------------------------------- + // + modeManager = MakeModeManager(); + Register_Object(modeManager); + + // + //-------------------------------------------------------------------------- + // Create the controls manager + //-------------------------------------------------------------------------- + // + controlsManager = MakeControlsManager(); + Register_Object(controlsManager); + + // + //-------------------------------------------------------------------------- + // Create the intercom manager + //-------------------------------------------------------------------------- + // + intercomManager = MakeIntercomManager(); + Register_Object(intercomManager); + + // + //-------------------------------------------------------------------------- + // Add background tasks + //-------------------------------------------------------------------------- + // + LoadBackgroundTasks(); + executeFrames = True; + applicationState.SetState(WaitingForEgg); + + // + //-------------------------------------------------------------------------- + // Create the audio renderer + //-------------------------------------------------------------------------- + // + Verify(audioRenderer == NULL); + if ((audioRenderer = MakeAudioRenderer()) != NULL) + { + Register_Object(audioRenderer); + audioRenderer->Initialize(); + } + + // + //-------------------------------------------------------------------------- + // Create the video renderer + //-------------------------------------------------------------------------- + // + Verify(videoRenderer == NULL); + if ((videoRenderer = MakeVideoRenderer()) != NULL) + { + Register_Object(videoRenderer); + } + + // + //-------------------------------------------------------------------------- + // Create the gauge renderer + //-------------------------------------------------------------------------- + // + Verify(gaugeRenderer == NULL); + + if (Application::GetVideoRenderer() != NULL) + { + int *secondaryIndex = Application::GetVideoRenderer()->GetSecondaryIndex(); + int *aux1Index = Application::GetVideoRenderer()->GetAux1Index(); + int *aux2Index = Application::GetVideoRenderer()->GetAux2Index(); + if ((gaugeRenderer = MakeGaugeRenderer(secondaryIndex, aux1Index, aux2Index)) != NULL) + { + Register_Object(gaugeRenderer); + } + } +} + +// +//############################################################################# +// LoadBackgroundTasks +//############################################################################# +// +void + Application::LoadBackgroundTasks() +{ + Check(this); + + ApplicationTask *application_task; + + application_task = new RoutePacketTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new ProcessEventTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new AudioRendererTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new GaugeRendererTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new NetworkManagerTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new CompleteCyclesTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new FryDeathRowTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); +} + +// +//############################################################################# +// MakeInterestManager +//############################################################################# +// +InterestManager* + Application::MakeInterestManager() +{ + return new InterestManager; +} + +// +//############################################################################# +// MakeNetworkManager +//############################################################################# +// +NetworkManager* + Application::MakeNetworkManager() +{ + return new NetworkManager(NetworkManager::DefaultData); +} + +// +//############################################################################# +// MakeRegistry +//############################################################################# +// +Registry* + Application::MakeRegistry() +{ + Fail("Application::MakeRegistry - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// MakeModeManager +//############################################################################# +// +ModeManager* + Application::MakeModeManager() +{ + Fail("Application::MakeModeManager - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// MakeControlsManager +//############################################################################# +// +ControlsManager* + Application::MakeControlsManager() +{ + Fail("Application::MakeControlsManager - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// MakeIntercomManager +//############################################################################# +// +IcomManager* + Application::MakeIntercomManager() +{ + Fail("Application::MakeIntercomManager - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// ExecuteForeground +//############################################################################# +// +Logical + Application::ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ) +{ + SET_FOREGROUND_PROCESSING(); + + Check(this); + Verify(application == this); + + if (!executeFrames) + { + CLEAR_FOREGROUND_PROCESSING(); + return executeFrames; + } + + Time + frame_ticks; + frame_ticks = frame_duration; + + // + //-------------------------------------------------------------------------- + // Controls Manager + // + // Poll all devices, update all control variables. + // + // This is executed before the update manager so that the + // models have valid control values. It is not necessary for + // the controls to operate at the frame rate of this loop. If + // the controls manager can run run at a lower rate it can + // throttle itself internally. + //-------------------------------------------------------------------------- + // + Check(controlsManager); +Time startControls = Now(); + controlsManager->Execute(); +Time endControls = Now(); + + if (GetApplicationState() == WaitingForEgg) + { + // since we're idling, let the renderers clear the screens + videoRenderer->ExecuteIdle(); + CLEAR_FOREGROUND_PROCESSING(); + return executeFrames; + } + + // + //-------------------------------------------------------------------------- + // Update Manager + // + // Execute replicants. + // Execute master entities if they are interesting here or + // elsewhere. + // Inform interest manager of possible interest zone change. + // If the master entity has provided and update message then + // send it to replicants. + // + // This is executed before the interest manager so that the + // interest manager can merge all interest zone changes before + // broadcasting interest arena deltas and building interesting + // entity lists. + // + // This is executed before the renderers so that the watchers + // have executed on the model and are ready for use by the + // renderers. + //-------------------------------------------------------------------------- + // + SET_UPDATE_MANAGER(); + +Time startUpdate = Now(); + Check(updateManager); + updateManager->Execute(start_of_frame); +Time endUpdate = Now(); + + CLEAR_UPDATE_MANAGER(); + + // + //-------------------------------------------------------------------------- + // Interest Manager + // + // Update the net interest arena. + // Calculate which interest zones should be released and which + // interest zones should be loaded + // Send a becoming uninteresting and becoming interesting + // message to the entity. + // Broadcast the interest arena change + // + // The renderer manager call, update interest origins will + // update only those interest origins required by the renderers + // executing this frame. + // + // This is executed before the renderer manager so that when + // the renderers execute they execute upon interest lists that + // are valid as of the end of a model/update frame. + // + // In theory the interest manager does not have to run every + // frame. If throttled less, this would cause fuzz at interest + // zone borders, which may or may not be acceptable depending + // on the size of the interest arena. + //-------------------------------------------------------------------------- + // +Time startInterest = Now(); + Check(rendererManager); + rendererManager->UpdateInterestOrigins(start_of_frame); + Check(interestManager); + interestManager->Execute(); +Time endInterest = Now(); + + // + //-------------------------------------------------------------------------- + // Renderer Manager + // + // Execute renderers. + // Get interest list from interest manager. + // Poll watchers. + // + // It is not necessary for all renderers to operate at the frame + // rate of this loop. If a renderer can run at a lower rate it + // does so via the renderer manager which will govern if a + // renderer executes this frame. + //-------------------------------------------------------------------------- + // + SET_RENDERER_MANAGER(); +Time startRender = Now(); + Check(rendererManager); + rendererManager->Execute(start_of_frame, frame_ticks, frame_ticks); +Time endRender = Now(); + CLEAR_RENDERER_MANAGER(); + + // + //-------------------------------------------------------------------------- + // Intercom Manager + //-------------------------------------------------------------------------- + // +Time startIntercom = Now(); + Check(intercomManager); + intercomManager->Execute(); +Time endIntercom = Now(); + + // + //-------------------------------------------------------------------------- + // Execution statistics + //-------------------------------------------------------------------------- + // + if (GetApplicationState() == RunningMission) + { + secondsRemainingInGame = + currentMission->GetGameLength() - (Now() - gameStarted); + } + routePacketFinished = False; + + CLEAR_FOREGROUND_PROCESSING(); + + return executeFrames && !Exit_Code; +} + +// +//############################################################################# +// ExecuteBackgroundTask +//############################################################################# +// +#define QUIET_TIME_OUT 3.0f +void + Application::ExecuteBackgroundTask() +{ + Check(this); + + // + //------------------------------------------------------------------------ + // If we are processing the map's creation messages, don't allow any other + // processing to happen until nothing appears for the timeout period + //------------------------------------------------------------------------ + // + if (GetApplicationState() == CreatingMission) + { + Check(networkManager); + + if (networkManager->RoutePacket()) + { + return; + } + + if (ProcessOneEvent(DefaultEventPriority)) + { + return; + } + + if (ProcessOneEvent(LowEventPriority)) + { + lastCreationMessage = Now(); + } + else + { + Scalar wait = Now() - lastCreationMessage; + if (wait > QUIET_TIME_OUT) + { + applicationState.SetState(LoadingMission); + networkManager->Marker("MUNGA MARKER - Starting renderer load...\n"); + networkManager->Mode(NetworkManager::UnreliableMode); + #if defined(LAB_ONLY) + DEBUG_STREAM << "Starting renderer load...\n" << std::flush; + #endif + } + } + return; + } + + // + // If there exists a high priority event, execute it + // + if (ProcessOneEvent(HighEventPriority)) + { + return; + } + + // + // if + // we are not finished routing packets this frames or + // we are not running the game + // then + // attempt to route a network packet + // we are finished routing packets for this frame + // + if ( + !routePacketFinished || + applicationState.GetState() != RunningMission + ) + { + Check(networkManager); + if (networkManager->RoutePacket()) + { + return; + } + } + routePacketFinished = True; + + // + // Execute lower priority tasks + // + Check(backgroundTasks); + backgroundTasks->Execute(); +} + +// +//############################################################################# +// Stop +//############################################################################# +// +void + Application::Stop() +{ + Check(this); + + // + // Dump analysis sample + // + #if defined(USE_TIME_ANALYSIS) + DEBUG_STREAM << "\nGame timing statistics:\n" << std::flush; + trace_manager.SnapshotTimingAnalysis(True); + #endif + #if defined(USE_TRACE_LOG) + trace_manager.SaveTraceLog("trace.log"); + #endif + #if defined(USE_EVENT_STATISTICS) + event_statistics_manager.Report(); + #endif + + // + // Set state variables to end game status + // + executeFrames = False; + DEBUG_STREAM << std::flush << std::flush; + applicationState.SetState(StoppingMission); +} + +// +//############################################################################# +// Shutdown +//############################################################################# +// +Logical + Application::Shutdown(int remainingApps) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Shutdown gauge renderer + //-------------------------------------------------------------------------- + // + if (gaugeRenderer != NULL) + { + Check(gaugeRenderer); + gaugeRenderer->Shutdown(); + gaugeRenderer->UnlinkFromEntity(); + } + // + //-------------------------------------------------------------------------- + // Shutdown video renderer + //-------------------------------------------------------------------------- + // + if (videoRenderer != NULL) + { + Check(videoRenderer); + videoRenderer->Shutdown(); + videoRenderer->UnlinkFromEntity(); + } + // + //-------------------------------------------------------------------------- + // Shutdown audio renderer + //-------------------------------------------------------------------------- + // + if (audioRenderer != NULL) + { + Check(audioRenderer); + audioRenderer->Shutdown(); + audioRenderer->UnlinkFromEntity(); + } + + // + //-------------------------------------------------------------------------- + // Delete the viewpoint entity + //-------------------------------------------------------------------------- + // + if (viewpointEntity != NULL) + { + Unregister_Object(viewpointEntity); + delete viewpointEntity; + viewpointEntity = NULL; + } + + // + //-------------------------------------------------------------------------- + // Shutdown the interest manager + //-------------------------------------------------------------------------- + // + Check(interestManager); + interestManager->Shutdown(); + + // + //-------------------------------------------------------------------------- + // Shutdown the host manager + //-------------------------------------------------------------------------- + // + Check(hostManager); + hostManager->Shutdown(); + + // + //-------------------------------------------------------------------------- + // Shutdown the network manager + //-------------------------------------------------------------------------- + // + Check(networkManager); + networkManager->Shutdown(); + + // + //-------------------------------------------------- + // Delete the current mission if it has been created + //-------------------------------------------------- + // + if (currentMission) + { + Unregister_Object(currentMission); + delete currentMission; + currentMission = NULL; + } + + // + //--------------------------------- + // Allow the process to start again + //--------------------------------- + // + executeFrames = True; + applicationState.SetState(WaitingForEgg); +#if 0 + return !Exit_Code; +#else + return False; +#endif +} + +// +//############################################################################# +// Terminate +//############################################################################# +// +void + Application::Terminate() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Delete the gauge renderer + //-------------------------------------------------------------------------- + // + if (gaugeRenderer != NULL) + { + Unregister_Object(gaugeRenderer); + delete gaugeRenderer; + gaugeRenderer = NULL; + } + + // + //-------------------------------------------------------------------------- + // Delete the video renderer + //-------------------------------------------------------------------------- + // + if (videoRenderer != NULL) + { + Unregister_Object(videoRenderer); + delete videoRenderer; + videoRenderer = NULL; + } + + // + //-------------------------------------------------------------------------- + // Delete the audio renderer + //-------------------------------------------------------------------------- + // + if (audioRenderer != NULL) + { + Unregister_Object(audioRenderer); + delete audioRenderer; + audioRenderer = NULL; + } + + // + //----------------------------------------------------------------------- + // Delete the intercom manager + //----------------------------------------------------------------------- + // + if (intercomManager != NULL) + { + Unregister_Object(intercomManager); + delete intercomManager; + intercomManager = NULL; + } + + // + //----------------------------------------------------------------------- + // Delete the controls manager + //----------------------------------------------------------------------- + // + if (controlsManager != NULL) + { + Unregister_Object(controlsManager); + delete controlsManager; + controlsManager = NULL; + } + + // + //------------------------ + // Delete the mode manager + //------------------------ + // + if (modeManager) + { + Unregister_Object(modeManager); + delete modeManager; + modeManager = NULL; + } + + // + //----------------------------------------------------------------------- + // Delete the registry + //----------------------------------------------------------------------- + // + if (registry != NULL) + { + Unregister_Object(registry); + delete registry; + registry = NULL; + } + + // + //----------------------------------------------------------------------- + // Delete the network manager + //----------------------------------------------------------------------- + // + if (networkManager != NULL) + { + Unregister_Object(networkManager); + delete networkManager; + networkManager = NULL; + } + + // + //---------------------------- + // Delete the interest manager + //---------------------------- + // + if (interestManager != NULL) + { + Unregister_Object(interestManager); + delete interestManager; + interestManager = NULL; + } +} + +// +//############################################################################# +// ~Application +//############################################################################# +// +Application::~Application() +{ + // + // Verify that these managers have been deleted + // + Verify(interestManager == NULL); + Verify(networkManager == NULL); + Verify(registry == NULL); + Verify(controlsManager == NULL); + Verify(intercomManager == NULL); + Verify(audioRenderer == NULL); + Verify(videoRenderer == NULL); + Verify(gaugeRenderer == NULL); + + // + // Verify that the mission has been deleted + // + Verify(currentMission == NULL); + + // + // Verify that the viewpoint entity has been deleted + // + Verify(viewpointEntity == NULL); + + // + // Destroy these managers + // + Unregister_Object(backgroundTasks); + delete backgroundTasks; + backgroundTasks = NULL; + + Unregister_Object(rendererManager); + delete rendererManager; + rendererManager = NULL; + + Unregister_Object(updateManager); + delete updateManager; + updateManager = NULL; + + Unregister_Object(hostManager); + delete hostManager; + hostManager = NULL; + + Unregister_Object(entityManager); + delete entityManager; + entityManager = NULL; + + resourceFile = NULL; + + // + // Destroy the event queue + // HACK - the event queue is transparently created as an array, + // therefore must be deleted as one + // + Unregister_Object(eventQueue); + delete[] eventQueue; + eventQueue = NULL; +} + +// +//############################################################################# +// StateQueryMessageHandler +//############################################################################# +// +void + Application::StateQueryMessageHandler( +#if DEBUG_LEVEL>0 + StateQueryMessage *message +#else + StateQueryMessage * +#endif + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StateQueryMessageID); + + // + //-------------------------------------------------------------------------- + // Send the console our application state + //-------------------------------------------------------------------------- + // + Host *console_host; + + Check(GetHostManager()); + if ((console_host = GetHostManager()->GetConsoleHost()) != NULL) + { + Check(console_host); + + unsigned int appState = applicationState.GetState(); + + ConsoleApplicationStateResponseMessage + response_message( + 0, // GetHostManager()->GetLocalHostID(), + applicationState.GetState(), + GetApplicationID() + ); + + SendMessage( + console_host->GetHostID(), + ConsoleClientID, + &response_message + ); + } +} + +// +//############################################################################# +// CreateMission +//############################################################################# +// +void + Application::CreateMission(NotationFile *egg_notation_file) +{ + Check(this); + Check(egg_notation_file); + + // + //-------------------------------------------------------------------------- + // Create mission from egg notation file + //-------------------------------------------------------------------------- + // + currentMission = MakeMission(egg_notation_file, resourceFile); + Register_Object(currentMission); + secondsRemainingInGame = currentMission->GetGameLength(); + + // + //---------------------------------------------------------------------- + // Now, start up the network connect process. The network must have at + // least established the local host before returning, so that the player + // data load can work + //---------------------------------------------------------------------- + // + NetworkManager *net_mgr = GetNetworkManager(); + Check(net_mgr); + net_mgr->StartConnecting(currentMission); + currentMission->SetPlayerData(egg_notation_file); + + InterestManager *interest_mgr = GetInterestManager(); + Check(interest_mgr); + interest_mgr->LoadInterestArenas(currentMission); +} + +// +//############################################################################# +// MakeMission +//############################################################################# +// +Mission* + Application::MakeMission( + NotationFile*, + ResourceFile* + ) +{ + Fail("Application::MakeMisson - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// LoadMissionMessageHandler +//############################################################################# +// +void + Application::LoadMissionMessageHandler(Message *) +{ + Check(this); + // + //-------------------------------------------------------------------------- + // Load the interest manager + //-------------------------------------------------------------------------- + // + #ifdef USE_TIME_ANALYSIS + trace_manager.StartTimingAnalysis(); + #endif + Check(interestManager); + interestManager->LoadMission(currentMission); + + // + //-------------------------------------------------------------------------- + // Make the player + //-------------------------------------------------------------------------- + // + Registry* registry = GetRegistry(); + Check(registry); + missionPlayer = registry->MakePlayer(currentMission); + Register_Object(missionPlayer); + + // + //-------------------------------------------------------------------------- + // Set application state to loading + //-------------------------------------------------------------------------- + // + applicationState.SetState(CreatingMission); + #if defined(LAB_ONLY) + DEBUG_STREAM << "Starting entity creation...\n" << std::flush; + #endif +} + +// +//############################################################################# +// MakeAndLinkViewpointEntity +//############################################################################# +// +Entity* + Application::MakeAndLinkViewpointEntity(Entity::MakeMessage* message) +{ + Check(this); + Check(message); + + // + //-------------------------------------------------------------------------- + // Create the viewpoint entity + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + HostManager *host = GetHostManager(); + Check(host); + Verify(message->entityID.GetHostID() == host->GetLocalHostID()); + #endif + + Verify(viewpointEntity == NULL); + viewpointEntity = MakeViewpointEntity(message); + + // + //-------------------------------------------------------------------------- + // Post a message to check the status of the load + //-------------------------------------------------------------------------- + // + CheckLoadMessage check_load_message; + Post(DefaultEventPriority, this, &check_load_message); + + // + //-------------------------------------------------------------------------- + // Load audio renderer + //-------------------------------------------------------------------------- + // + if (audioRenderer != NULL) + { + Check(audioRenderer); + audioRenderer->LinkToEntity(viewpointEntity); + audioRenderer->LoadMission(GetCurrentMission()); + audioRenderer->SetRendererStatusToRunning(); + } + + // + //-------------------------------------------------------------------------- + // Load video renderer + //-------------------------------------------------------------------------- + // + if (videoRenderer != NULL) + { + Check(videoRenderer); + videoRenderer->LinkToEntity(viewpointEntity); + videoRenderer->LoadMission(GetCurrentMission()); + videoRenderer->SetRendererStatusToRunning(); + } + + // + //-------------------------------------------------------------------------- + // Load gauge renderer + //-------------------------------------------------------------------------- + // + if (gaugeRenderer != NULL) + { + Check(gaugeRenderer); + gaugeRenderer->LinkToEntity(viewpointEntity); + gaugeRenderer->LoadMission(GetCurrentMission()); + gaugeRenderer->SetRendererStatusToRunning(); + } + + return viewpointEntity; +} + +// +//############################################################################# +// MakeViewpointEntity +//############################################################################# +// +Entity* + Application::MakeViewpointEntity(Entity::MakeMessage*) +{ + Fail("Application::MakeViewpointEntity - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// MakeAudioRenderer +//############################################################################# +// +AudioRenderer* + Application::MakeAudioRenderer() +{ + Fail("Application::MakeAudioRenderer - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// MakeVideoRenderer +//############################################################################# +// +VideoRenderer* + Application::MakeVideoRenderer() +{ + Fail("Application::MakeVideoRenderer - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// MakeGaugeRenderer +//############################################################################# +// +GaugeRenderer* + Application::MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index) +{ + Fail("Application::MakeGaugeRenderer - Should never reach here"); + return NULL; +} + +// +//############################################################################# +// CheckLoadMessageHandler +//############################################################################# +// +void + Application::CheckLoadMessageHandler( + CheckLoadMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == CheckLoadMessageID); + + // + //-------------------------------------------------------------------------- + // If the application is already running then ignore this message + //-------------------------------------------------------------------------- + // + switch (applicationState.GetState()) + { + case CreatingMission: + case LoadingMission: + case WaitingForLaunch: + if (eventQueue->IsPriorityEmpty(MinEventPriority)) + { + Host *console_host; + + if (applicationState.GetState() == LoadingMission) + { + ResourceFile *res_file = GetResourceFile(); + Check(res_file); + res_file->ReleaseUnlockedResources(); + #if defined(LAB_ONLY) + DEBUG_STREAM << "Waiting for translocation!\n" << std::flush; + #endif + #if defined(USE_TIME_ANALYSIS) + DEBUG_STREAM << "Loading time usage:\n" << std::flush; + trace_manager.SnapshotTimingAnalysis(True); + #endif + } + applicationState.SetState(WaitingForLaunch); + Check(GetHostManager()); + + static bool hasConsolidated = false; + + if (!hasConsolidated) + { + //Consolidate level geometry here + VideoRenderer *renderer = Application::GetVideoRenderer(); + renderer->ConsolidateStaticObjects(); + hasConsolidated = true; + } + + console_host = GetHostManager()->GetConsoleHost(); + if ( + (console_host == NULL) || + ( + console_host != NULL && + console_host->GetConnectStatus() != Host::OnLineConnectionStatus + ) + ) + { + // + // In the absence of the console just post the message to run + // + RunMissionMessage run_mission_message; + Post(DefaultEventPriority, this, &run_mission_message); + Tell("Sent ready message to ourselves\n"); + } + } + + // + //----------------------------------------------------------------------- + // Post this message again until the application is running + //----------------------------------------------------------------------- + // + Time post_time; + + post_time = Now(); + #if DEBUG_LEVEL<3 + post_time += 1.0f; + #else + post_time += 5.0; + #endif + + Post(DefaultEventPriority, this, message, post_time); + break; + } +} + +// +//############################################################################# +// RunMissionMessageHandler +//############################################################################# +// +void + Application::RunMissionMessageHandler( +#if DEBUG_LEVEL>0 + RunMissionMessage *message +#else + RunMissionMessage * +#endif + ) +{ + Check(this); + Check(message); + Verify(message->messageID == RunMissionMessageID); + + // + //-------------------------------------------------------------------------- + // If the application is already running then ignore this message + //-------------------------------------------------------------------------- + // + switch (GetApplicationState()) + { + case RunningMission: + return; + + case LaunchingMission: + // + // Start analysis sample + // + #if defined(USE_TRACE_LOG) + { + char *log_size_str = getenv("LOGSIZE"); + if (log_size_str) + { + size_t log_size = atoi(log_size_str); + if (log_size > 0) + { + trace_manager.CreateTraceLog(log_size,True); + } + } + } + #endif + #ifdef USE_TIME_ANALYSIS + trace_manager.StartTimingAnalysis(); + #endif + + Tell("Application::RunMissionMessageHandler - running mission\n"); + applicationState.SetState(RunningMission); + gameStarted = Now(); + break; + + case WaitingForLaunch: + { + Tell("Application::RunMissionMessageHandler - Translocation\n"); + applicationState.SetState(LaunchingMission); + Player *player = GetMissionPlayer(); + Check(player); + Player::MissionStartingMessage + launch( + Player::MissionStartingMessageID, + sizeof(Player::MissionStartingMessage) + ); + player->Dispatch(&launch); + break; + } + + default: + Fail("Application::RunMissionMessageHandler - Not ready to run!\n"); + break; + } +} + +// +//############################################################################# +// SuspendMissionMessageHandler +//############################################################################# +// +void + Application::SuspendMissionMessageHandler( +#if DEBUG_LEVEL>0 + SuspendMissionMessage *message +#else + SuspendMissionMessage * +#endif + ) +{ + Check(this); + Check(message); + Verify(message->messageID == SuspendMissionMessageID); + + // + //-------------------------------------------------------------------------- + // The application should be either running or already suspended + //-------------------------------------------------------------------------- + // + switch (GetApplicationState()) + { + case RunningMission: + { + Player::MissionEndingMessage + player_message( + Player::MissionEndingMessageID, + sizeof(Player::MissionEndingMessage) + ); + Player *player; + + Tell("Application::SuspendMissionMessageHandler - Suspending\n"); + applicationState.SetState(SuspendingMission); + + player = GetMissionPlayer(); + Check(player); + player->Dispatch(&player_message); + } + break; + + case SuspendingMission: + // + // Already suspended + // + break; + + default: + // + // Any other state is an error + // + Fail("Application::SuspendMissionMessageHandler - Illegal state"); + break; + } +} + +// +//############################################################################# +// ResumeMissionMessageHandler +//############################################################################# +// +void + Application::ResumeMissionMessageHandler( +#if DEBUG_LEVEL>0 + ResumeMissionMessage *message +#else + ResumeMissionMessage * +#endif + ) +{ + Check(this); + Check(message); + Verify(message->messageID == ResumeMissionMessageID); + + // + //-------------------------------------------------------------------------- + // The application should be in the suspended state or resuming + //-------------------------------------------------------------------------- + // + switch (GetApplicationState()) + { + case SuspendingMission: + { + Player::MissionStartingMessage + launch( + Player::MissionStartingMessageID, + sizeof(Player::MissionStartingMessage) + ); + Player *player; + + Tell("Application::ResumeMissionMessageHandler - Resuming mission\n"); + applicationState.SetState(ResumingMission); + player = GetMissionPlayer(); + Check(player); + player->Dispatch(&launch); + } + break; + + case ResumingMission: + Tell("Application::ResumeMissionMessageHandler - Running mission\n"); + applicationState.SetState(RunningMission); + gameStarted = Now(); + break; + + default: + Fail("Application::ResumeMissionMessageHandler - Illegal state\n"); + break; + } +} + +// +//############################################################################# +// StopMissionMessageHandler +//############################################################################# +// +void + Application::StopMissionMessageHandler( +#if DEBUG_LEVEL>0 + StopMissionMessage *message +#else + StopMissionMessage * +#endif + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StopMissionMessageID); + + // + //-------------------------------------------------------------------------- + // If the application is already stopping then ignore the message + //-------------------------------------------------------------------------- + // + switch (GetApplicationState()) + { + case StoppingMission: + return; + + case EndingMission: + case AbortingMission: + Stop(); + break; + + default: + { + applicationState.SetState(EndingMission); + Player *player = GetMissionPlayer(); + if (player) + { + networkManager->Mode(NetworkManager::ReliableMode); + Check(player); + Player::MissionEndingMessage + launch( + Player::MissionEndingMessageID, + sizeof(Player::MissionEndingMessage) + ); + player->Dispatch(&launch); + } + else + { + Stop(); + } + break; + } + } +} + +// +//############################################################################# +// StopMissionMessageHandler +//############################################################################# +// +void + Application::AbortMissionMessageHandler( +#if DEBUG_LEVEL>0 + AbortMissionMessage *message +#else + AbortMissionMessage * +#endif + ) +{ + Check(this); + Check(message); + Verify(message->messageID == AbortMissionMessageID); + + // + //-------------------------------------------------------------------------- + // If the application is already stopping then ignore the message + //-------------------------------------------------------------------------- + // + switch (GetApplicationState()) + { + case StoppingMission: + return; + + case EndingMission: + case AbortingMission: + Stop(); + break; + + default: + { + applicationState.SetState(AbortingMission); + Player *player = GetMissionPlayer(); + if (player) + { + Check(player); + Player::MissionEndingMessage + launch( + Player::MissionEndingMessageID, + sizeof(Player::MissionEndingMessage) + ); + player->Dispatch(&launch); + } + else + { + Stop(); + } + break; + } + } +} + +// +//############################################################################# +// KeyCommandMessageHandler +//############################################################################# +// +void + Application::KeyCommandMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + switch (message->dataContents) + { + case '&': + if (GetApplicationState() != StoppingMission) + { + Exit_Code = 1; + Stop(); + DEBUG_STREAM << "Mission stopped by keystroke!\n" << std::flush; + if (GetApplicationState() == WaitingForEgg) + { + applicationState.SetState(EndingMission); + } + } + break; + + #if defined(USE_TRACE_LOG) + case ' ': + trace_manager.MarkTraceLog(); + break; + case '/': + trace_manager.ResumeTraceLogging(); + break; + case '\\': + trace_manager.SuspendTraceLogging(); + break; + #endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~ Application__CheckLoadMessage ~~~~~~~~~~~~~~~~~~~~~~~~ + +Application__CheckLoadMessage::Application__CheckLoadMessage(): + NetworkClient::Message( + Application::CheckLoadMessageID, + sizeof(Application__CheckLoadMessage) + ) +{ +} + +#ifdef TEST_CLASS +# include "app.tcp" +#endif diff --git a/MUNGA/APP.h b/MUNGA/APP.h new file mode 100644 index 0000000..8728b67 --- /dev/null +++ b/MUNGA/APP.h @@ -0,0 +1,764 @@ +#pragma once + +#include "network.h" +#include "event.h" +#include "state.h" +#include "cstr.h" + +#if defined(TRACE_FOREGROUND_PROCESSING) + extern BitTrace Foreground_Processing; + #define SET_FOREGROUND_PROCESSING() Foreground_Processing.Set() + #define CLEAR_FOREGROUND_PROCESSING() Foreground_Processing.Clear() +#else + #define SET_FOREGROUND_PROCESSING() + #define CLEAR_FOREGROUND_PROCESSING() +#endif + +#if defined(TRACE_UPDATE_MANAGER) + extern BitTrace Update_Manager; + #define SET_UPDATE_MANAGER() Update_Manager.Set() + #define CLEAR_UPDATE_MANAGER() Update_Manager.Clear() +#else + #define SET_UPDATE_MANAGER() + #define CLEAR_UPDATE_MANAGER() +#endif + +#if defined(TRACE_RENDERER_MANAGER) + extern BitTrace Renderer_Manager; + #define SET_RENDERER_MANAGER() Renderer_Manager.Set() + #define CLEAR_RENDERER_MANAGER() Renderer_Manager.Clear() +#else + #define SET_RENDERER_MANAGER() + #define CLEAR_RENDERER_MANAGER() +#endif + +class Mission; +class Registry; +class InterestManager; +class HostManager; +class UpdateManager; +class RendererManager; +class ControlsManager; +class Entity; +class EntityManager; +class Renderer; +class BackgroundTasks; +class ApplicationManager; +class CameraShip; +class SpoolFile; +class AudioRenderer; +class VideoRenderer; +class GaugeRenderer; +class IcomManager; +class ModeManager; +class Player; +class GeneralEventQueue; +class Entity__MakeMessage; +class ResourceFile; + +//########################################################################## +//######################### Application ############################## +//########################################################################## + +class Application__StateQueryMessage; +class Application__CheckLoadMessage; +class Application__RunMissionMessage; +class Application__StopMissionMessage; +class Application__SuspendMissionMessage; +class Application__ResumeMissionMessage; +class Application__AbortMissionMessage; + +enum EventPriorities +{ + MinEventPriority = 0, + LowEventPriority, + DefaultEventPriority, + HighEventPriority, + MaxEventPriority +}; + +const EventPriorities ControlsEventPriority = HighEventPriority; +const EventPriorities CreationEventPriority = HighEventPriority; +const EventPriorities DestructionEventPriority = HighEventPriority; +const EventPriorities UpdateEventPriority = MaxEventPriority; +const EventPriorities HighInterestEventPriority = DefaultEventPriority; +const EventPriorities LowInterestEventPriority = LowEventPriority; +const EventPriorities EntityManagerEventPriority = DefaultEventPriority; +const EventPriorities EntityInvalidEventPriority = LowEventPriority; + +enum ApplicationID +{ + RPL4, + BTL4, + NDL4 +}; + +#define EVENT_PRIORITIES_COUNT (5) + +class Application: + public NetworkClient +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + Application( + ResourceFile *resource_file, + ApplicationID application_id, + ClassID class_ID=ApplicationClassID, + SharedData &shared_data=DefaultData + ); + ~Application(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execution control +// +public: + virtual void Initialize(); + virtual void + LoadBackgroundTasks(); + + virtual Logical + ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ); + + virtual void + ExecuteBackgroundTask(); + + void + Stop(); + + virtual Logical + Shutdown(int remainingApps); + + virtual void + Terminate(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Creation Callbacks +// +public: + void + CreateMission(NotationFile *egg_notation_file); + + virtual Entity* + MakeAndLinkViewpointEntity(Entity__MakeMessage *message); + +protected: + virtual Mission* + MakeMission( + NotationFile *notation_file, + ResourceFile *resources + ); + + virtual Entity* + MakeViewpointEntity(Entity__MakeMessage *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Current mission +// +public: + Mission* + GetCurrentMission(); + Player* + GetMissionPlayer() + {return missionPlayer;} + + SpoolFile* + GetSpoolFile() + {return spoolFile;} + +protected: + Player + *missionPlayer; + SpoolFile* + spoolFile; + Time + lastCreationMessage; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Application State +// +public: + enum { + InitializingState = 0, + WaitingForEgg, + LoadingMission, + WaitingForLaunch, + LaunchingMission, + RunningMission, + EndingMission, + StoppingMission, + SuspendingMission, + ResumingMission, + AbortingMission, + CreatingMission, + ApplicationStateCount + }; + + Enumeration + GetApplicationState(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// System level event processing +// +public: + void + Post( + int priority, + Receiver *target, + Receiver::Message *message, + const Time &when=Time::Null + ); + + void + SendEvent( + int priority, + HostID host_ID, + NetworkManager::ClientID client_ID, + Receiver::Message *message, + Time when=Time::Null + ); + + void + BroadcastEvent( + int priority, + NetworkManager::ClientID client_ID, + Receiver::Message *message, + Time when=Time::Null + ); + + void + ExclusiveBroadcastEvent( + int priority, + NetworkManager::ClientID client_ID, + Receiver::Message *message, + Time when=Time::Null + ); + + #if defined(TRACE_EVENT_COUNT) + size_t + GetEventCount(); + #endif + + void + DumpEventQueue(); + +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Creation and Interest Event Posting +// +public: + void + PostCreationEvent( + Receiver::Message *message, + const Time &when=Time::Null + ); + void + PostInterestEvent( + Entity *entity, + Renderer *renderer + ); + void + PostUpdateEvent( + Entity *entity, + Receiver::Message *message + ); + void + PostDestructionEvent( + Entity *entity, + Receiver::Message *message + ); +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// System level message processing +// +public: + void + SendMessage( + HostID host_ID, + NetworkManager::ClientID client_ID, + Receiver::Message *message + ); + + void + BroadcastMessage( + NetworkManager::ClientID client_ID, + Receiver::Message *message + ); + + void + ExclusiveBroadcastMessage( + NetworkManager::ClientID client_ID, + Receiver::Message *message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Event level event processing +// +public: + Logical + ProcessOneEvent(int min_priority=0); + + void + ProcessAllEvents(int min_priority=0); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +public: + Scalar + GetApplicationLoopFrameRate(); + Scalar + GetSecondsRemainingInGame() + {return secondsRemainingInGame;} + ApplicationID + GetApplicationID() + {return applicationID;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Module accessors +// +public: + // + // Managers + // + NetworkManager* + GetNetworkManager(); + EntityManager* + GetEntityManager(); + Registry* + GetRegistry(); + HostManager* + GetHostManager(); + InterestManager* + GetInterestManager(); + UpdateManager* + GetUpdateManager(); + RendererManager* + GetRendererManager(); + ControlsManager* + GetControlsManager(); + IcomManager* + GetIntercomManager(); + AudioRenderer* + GetAudioRenderer(); + VideoRenderer* + GetVideoRenderer(); + GaugeRenderer* + GetGaugeRenderer(); + ModeManager* + GetModeManager(); + + // + // StreamableResourceFile + // + ResourceFile* + GetResourceFile(); + void + SetResourceFile(ResourceFile *resources); + ApplicationManager* + GetApplicationManager(); + + // + // Viewpoint entity + // + Entity* + GetViewpointEntity(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum { + StateQueryMessageID = NetworkClient::NextMessageID, + CheckLoadMessageID, + RunMissionMessageID, + StopMissionMessageID, + KeyCommandMessageID, + SuspendMissionMessageID, + ResumeMissionMessageID, + LoadMissionMessageID, + AbortMissionMessageID, + NextMessageID + }; + + typedef Application__StateQueryMessage StateQueryMessage; + typedef Application__CheckLoadMessage CheckLoadMessage; + typedef Application__RunMissionMessage RunMissionMessage; + typedef Application__StopMissionMessage StopMissionMessage; + typedef Application__SuspendMissionMessage SuspendMissionMessage; + typedef Application__ResumeMissionMessage ResumeMissionMessage; + typedef Application__AbortMissionMessage AbortMissionMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + StateQueryMessageHandler(StateQueryMessage *message); + void + CheckLoadMessageHandler(CheckLoadMessage *message); + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + void + SuspendMissionMessageHandler(SuspendMissionMessage *message); + void + ResumeMissionMessageHandler(ResumeMissionMessage *message); + void + KeyCommandMessageHandler(ReceiverDataMessageOf *message); + void + LoadMissionMessageHandler(Message *message); + void + AbortMissionMessageHandler(AbortMissionMessage *message); + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + + static Logical DoSuppressGauges() { return suppressGauges; } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Modules +// +protected: + // + // Managers + // + NetworkManager + *networkManager; + EntityManager + *entityManager; + Registry + *registry; + HostManager + *hostManager; + InterestManager + *interestManager; + UpdateManager + *updateManager; + RendererManager + *rendererManager; + ControlsManager + *controlsManager; + IcomManager + *intercomManager; + AudioRenderer + *audioRenderer; + VideoRenderer + *videoRenderer; + GaugeRenderer + *gaugeRenderer; + ModeManager + *modeManager; + + static Logical suppressGauges; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Module Creation +// +protected: + // + // Managers + // + virtual NetworkManager* + MakeNetworkManager(); + + virtual Registry* + MakeRegistry(); + + virtual ControlsManager* + MakeControlsManager(); + + virtual IcomManager* + MakeIntercomManager(); + + virtual InterestManager* + MakeInterestManager(); + + virtual AudioRenderer* + MakeAudioRenderer(); + + virtual VideoRenderer* + MakeVideoRenderer(); + + virtual GaugeRenderer* + MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index); + + virtual ModeManager* + MakeModeManager(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +protected: + ApplicationID + applicationID; + Scalar + secondsRemainingInGame; + Time + gameStarted; + GeneralEventQueue + *eventQueue; + BackgroundTasks + *backgroundTasks; + ResourceFile + *resourceFile; + Entity + *viewpointEntity; + Logical + executeFrames; + StateIndicator + applicationState; + Mission + *currentMission; + Logical + routePacketFinished; +}; + +extern Application *application; +extern int Exit_Code; + +//~~~~~~~~~~~~~~~~~~~~ Application__CheckLoadMessage ~~~~~~~~~~~~~~~~~~~~~~~ + +class Application__CheckLoadMessage: + public NetworkClient::Message +{ +public: + Application__CheckLoadMessage(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ Application inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline Mission* + Application::GetCurrentMission() +{ + Check(this); + return currentMission; +} + +inline Enumeration + Application::GetApplicationState() +{ + Check(this); + return applicationState.GetState(); +} + +inline void + Application::Post( + int priority, + Receiver *target, + Receiver::Message *message, + const Time &when + ) +{ + Check(this); + eventQueue->Post(priority,target,message,when); +} + +inline void + Application::SendEvent( + int priority, + HostID host_ID, + NetworkClient::ClientID client_ID, + Receiver::Message *message, + Time when + ) +{ + Check(this); + eventQueue->SendEvent(priority,host_ID,client_ID,message,when); +} + +inline void + Application::BroadcastEvent( + int priority, + NetworkClient::ClientID client_ID, + Receiver::Message *message, + Time when + ) +{ + Check(this); + eventQueue->BroadcastEvent(priority,client_ID,message,when); +} + +inline void + Application::ExclusiveBroadcastEvent( + int priority, + NetworkClient::ClientID client_ID, + Receiver::Message *message, + Time when + ) +{ + Check(this); + eventQueue->ExclusiveBroadcastEvent(priority,client_ID,message,when); +} + +#if defined(GET_EVENT_COUNT) + inline size_t + Application::GetEventCount() + { + return eventQueue->GetEventCount(); + } +#endif + +inline void + Application::DumpEventQueue() +{ + eventQueue->DumpEventQueue(); +} + + +inline void + Application::SendMessage( + HostID host_ID, + NetworkClient::ClientID client_ID, + Receiver::Message *message + ) +{ + Check(this); + networkManager->Send(message,client_ID,host_ID); +} + +inline void + Application::BroadcastMessage( + NetworkManager::ClientID client_ID, + Receiver::Message *message + ) +{ + Check(this); + networkManager->Broadcast(message,client_ID); +} + +inline void + Application::ExclusiveBroadcastMessage( + NetworkManager::ClientID client_ID, + Receiver::Message *message + ) +{ + Check(this); + networkManager->ExclusiveBroadcast(message,client_ID); +} + +inline Logical + Application::ProcessOneEvent(int min_priority) +{ + Check(this); + return eventQueue->ProcessOneEvent(min_priority); +} + +inline void + Application::ProcessAllEvents(int min_priority) +{ + Check(this); + eventQueue->ProcessAllEvents(min_priority); +} + +inline NetworkManager* + Application::GetNetworkManager() +{ + Check(networkManager); + return networkManager; +} + +inline EntityManager* + Application::GetEntityManager() +{ + return entityManager; +} + +inline Registry* + Application::GetRegistry() +{ + return registry; +} + +inline HostManager* + Application::GetHostManager() +{ + return hostManager; +} + +inline InterestManager* + Application::GetInterestManager() +{ + return interestManager; +} + +inline UpdateManager* + Application::GetUpdateManager() +{ + return updateManager; +} + +inline RendererManager* + Application::GetRendererManager() +{ + return rendererManager; +} + +inline ControlsManager* + Application::GetControlsManager() +{ + return controlsManager; +} + +inline IcomManager* + Application::GetIntercomManager() +{ + return intercomManager; +} + +inline ResourceFile* + Application::GetResourceFile() +{ + return resourceFile; +} + +inline void + Application::SetResourceFile(ResourceFile *resources) +{ + resourceFile = resources; +} + +inline Entity* + Application::GetViewpointEntity() +{ + return viewpointEntity; +} + +inline AudioRenderer* + Application::GetAudioRenderer() +{ + return audioRenderer; +} + +inline VideoRenderer* + Application::GetVideoRenderer() +{ + return videoRenderer; +} + +inline GaugeRenderer* + Application::GetGaugeRenderer() +{ + return gaugeRenderer; +} + +inline ModeManager* + Application::GetModeManager() +{ + return modeManager; +} diff --git a/MUNGA/APPMGR.cpp b/MUNGA/APPMGR.cpp new file mode 100644 index 0000000..c2dd0c4 --- /dev/null +++ b/MUNGA/APPMGR.cpp @@ -0,0 +1,219 @@ +#include "munga.h" +#pragma hdrstop + +#include "appmgr.h" + +HWND ghWnd = 0; + +ApplicationManager* ApplicationManager::CurrentAppManager = NULL; + +ApplicationManager::ApplicationManager(HINSTANCE hInstance, HWND hWnd, Scalar frame_rate) : Node(ApplicationManagerClassID), runningApplications(this) +{ + frameRate = frame_rate; + frameDuration = 1.0f/frameRate; + mHInstance = hInstance; + ghWnd = hWnd; + ApplicationManager::CurrentAppManager = this; + Check_Fpu(); +} + +ApplicationManager::~ApplicationManager() +{ +} + +void ApplicationManager::StartApplication(Application *new_app) +{ + Check(this); + Check(new_app); + + runningApplications.Add(new_app); + application = new_app; + new_app->Initialize(); +} + +// +//############################################################################# +// RunMissions +//############################################################################# +// +void ApplicationManager::RunMissions() +{ + Check(this); + int backgroundTasksRun = 0; + int foregroundTasksRun = 0; + Time beginFrameTimestamp, lastFrameTimestamp; + + MSG msg; + SChainIteratorOf current_application(runningApplications); + SChainOf endedApplications(NULL); + SChainIteratorOf endingApplication(endedApplications); + +Start_Of_Frame: + backgroundTasksRun = 0; + foregroundTasksRun = 0; + beginFrameTimestamp = Now(); + + current_application.First(); + + lastFrameTimestamp = Now(); + + Time end_of_frame = Now(); + end_of_frame += frameDuration; + #if defined(LAB_ONLY) + int bad_count = 0; + #endif + + // + //---------------------------------- + // Run all relevant foreground loops + //---------------------------------- + // + + Time startForeground = Now(); + while ((application = current_application.ReadAndNext()) != NULL) + { + Check(application); + foregroundTasksRun++; + if (!application->ExecuteForeground(end_of_frame, frameDuration)) + { + if (!application->Shutdown(current_application.GetSize())) + { + endedApplications.Add(application); + + if (current_application.GetCurrent() == NULL) + { + current_application.Last(); + } else + { + current_application.Previous(); + } + current_application.Remove(); + } + } + } + Time endForeground = Now(); + + // + //----------------------------------------------------------------------- + // Check the Windows message queue for messages to be processed + //----------------------------------------------------------------------- + // + //InvalidateRect(ghWnd, NULL, false); + if (PeekMessage(&msg, NULL, 0, 0, PM_REMOVE)) + { + if (msg.message == WM_QUIT) + { + endingApplication.First(); + + while (application = endingApplication.ReadAndNext()) + { + application->Terminate(); + delete application; + } + + return; + } + TranslateMessage(&msg); + DispatchMessage(&msg); + } + + // + //----------------------------------------------------------------------- + // Run all relevant background loops until it is time for the next frame. + // If no applications remain, exit the whole loop + //----------------------------------------------------------------------- + // + current_application.First(); + application = current_application.GetCurrent(); + if (!application) + { + endingApplication.First(); + + while (application = endingApplication.ReadAndNext()) + { + application->Terminate(); + delete application; + } + return; + } + + do + { + while (application->GetNetworkManager()->RoutePacket()) + ; + + current_application.Next(); + application = current_application.GetCurrent(); + } while (application); + + current_application.First(); + application = current_application.GetCurrent(); + if (!application) + { + endingApplication.First(); + + while (application = endingApplication.ReadAndNext()) + { + application->Terminate(); + delete application; + } + return; + } + + // + //------------------------------------------------------------------ + // Give each application a chance to do at least one background task + //------------------------------------------------------------------ + // + Time startBackground = Now(); +Background_Loop: + do + { + Check(application); + application->ExecuteBackgroundTask(); + backgroundTasksRun++; + + // + // Move to the next application + // + current_application.Next(); + application = current_application.GetCurrent(); + } while (application); + + // + //--------------------------------------------------------------------- + // If time remains before the next frame is due, do another pass on the + // background tasks + //--------------------------------------------------------------------- + // + Time t2 = Now(); + Time lateTime = Now(); + lateTime += 15L; + + current_application.First(); + application = current_application.GetCurrent(); + + if (t2 < end_of_frame) + { + + #if defined(LAB_ONLY) + if (end_of_frame - t2 > 0.1f) + { + DEBUG_STREAM << t2 << ',' << end_of_frame << endl << std::flush; + if (++bad_count == 1000) + { + Fail("End-of-frame cannot be correctly calculated!"); + } + } + #endif + goto Background_Loop; + } + Time endBackground = Now(); + + //char str[256]; + //Scalar lastFrameLength = Now() - beginFrameTimestamp; + //sprintf(str, "RPL4 - %.2f FPS", 1.0f / lastFrameLength); + //SetWindowTextA(ghWnd, str); + + goto Start_Of_Frame; +} diff --git a/MUNGA/APPMGR.h b/MUNGA/APPMGR.h new file mode 100644 index 0000000..28b9e9d --- /dev/null +++ b/MUNGA/APPMGR.h @@ -0,0 +1,34 @@ +#pragma once + +#include "app.h" + +extern HWND ghWnd; + +class ApplicationManager : public Node +{ +public: + ApplicationManager(HINSTANCE hInstance, HWND hWnd, Scalar frame_rate); + ~ApplicationManager(); + + void StartApplication(Application *new_app); + + void RunMissions(); + + Scalar GetFrameRate() + { + Check(this); + return frameRate; + } + + HINSTANCE GetHInstance() { return mHInstance; } + HWND GetHWnd() { return ghWnd; } + + static ApplicationManager* GetCurrentManager() { return CurrentAppManager; } + +protected: + static ApplicationManager* CurrentAppManager; + + Scalar frameDuration, frameRate; + SChainOf runningApplications; + HINSTANCE mHInstance; +}; diff --git a/MUNGA/APPMSG.cpp b/MUNGA/APPMSG.cpp new file mode 100644 index 0000000..55e26dc --- /dev/null +++ b/MUNGA/APPMSG.cpp @@ -0,0 +1,46 @@ +#include "munga.h" +#pragma hdrstop + +#include "appmsg.h" +#include "app.h" + +//~~~~~~~~~~~~~~~~~~~~~ Application__StateQueryMessage ~~~~~~~~~~~~~~~~~~~~~~~~ +Application__StateQueryMessage::Application__StateQueryMessage(HostID requesting_host) + : NetworkClient::Message(Application::StateQueryMessageID, sizeof(Application__StateQueryMessage)) +{ + requestingHost = requesting_host; +} + +//~~~~~~~~~~~~~~~~~~~~~~ Application__RunMissionMessage ~~~~~~~~~~~~~~~~~~~~~~~ +Application__RunMissionMessage::Application__RunMissionMessage() + : NetworkClient::Message(Application::RunMissionMessageID, sizeof(Application__RunMissionMessage)) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~ Application__StopMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +Application__StopMissionMessage::Application__StopMissionMessage(Enumeration exit_code) + : NetworkClient::Message(Application::StopMissionMessageID, sizeof(Application__StopMissionMessage)) +{ + exitCode = exit_code; +} + +//~~~~~~~~~~~~~~~~~~~~~~ Application__AbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +Application__AbortMissionMessage::Application__AbortMissionMessage(Enumeration exit_code) + : NetworkClient::Message(Application::AbortMissionMessageID, sizeof(Application__AbortMissionMessage)) +{ + exitCode = exit_code; +} + +//~~~~~~~~~~~~~~~~~~~~ Application__SuspendMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +Application__SuspendMissionMessage::Application__SuspendMissionMessage() + : NetworkClient::Message(Application::SuspendMissionMessageID, sizeof(Application__SuspendMissionMessage)) +{ +} + +//~~~~~~~~~~~~~~~~~~~~ Application__ResumeMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +Application__ResumeMissionMessage::Application__ResumeMissionMessage() + : NetworkClient::Message(Application::ResumeMissionMessageID, sizeof(Application__ResumeMissionMessage)) +{ +} + +//============================================================================== diff --git a/MUNGA/APPMSG.h b/MUNGA/APPMSG.h new file mode 100644 index 0000000..31a24a6 --- /dev/null +++ b/MUNGA/APPMSG.h @@ -0,0 +1,223 @@ +#pragma once + +#if defined(MAC) + #include + #include +#else + #include "network.h" +#endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Application IDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC + enum ApplicationMessageID + { + StateQueryMessageID = NetworkEndpoint::NextMessageID, + CheckLoadMessageID, + RunMissionMessageID, + StopMissionMessageID, + KeyCommandMessageID, + SuspendMissionMessageID, + ResumeMissionMessageID, + LoadMissionMessageID, + AbortMissionMessageID, + ApplicationNextMessageID + }; + + enum ApplicationID + { + RPL4, + BTL4, + BTW4 + }; + typedef ApplicationID ApplicationID; + + enum ExitCodeID + { + NullExitCodeID = 0, + AbortExitCodeID, + RunRedPlanetExitCodeID, + RunBattleTechExitCodeID, + RunSinglePlayerRedPlanetExitCodeID, + RunSinglePlayerBattleTechExitCodeID, + DisplayMainTestPatternExitCodeID, + DisplayAuxTestPatternExitCodeID, + TestPlasmaDisplayExitCodeID, + ResetRIOExitCodeID, + RunAudioTestExitCodeID, + RunNortonDiskDoctorExitCodeID, + CheckDiskUsageExitCodeID, + RefreshRedPlanetExitCodeID, + RefreshBattleTechExitCodeID, + ChangeScreenModeExitCodeID, + SoftwareResetExitCodeID, + ClearCrashlogExitCodeID, + KillSpoolFileExitCodeID, + RunRedPlanetCameraExitCodeID, + RunBattleTechCameraExitCodeID, + RunRedPlanetMissionReviewExitCodeID, + RunBattleTechMissionReviewExitCodeID + }; + typedef ExitCodeID ExitCodeID; +#endif + + //~~~~~~~~~~~~~~~~~~~ Application__StateQueryMessage ~~~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__StateQueryMessage: + public NetworkEndpoint::Message + { + public: + Application__StateQueryMessage(HostID requesting_host); + + long + GetRequestingHostID() + {return requestingHost.value();} + + private: + HostID + requestingHost; + }; +#pragma options align=reset +#else + class Application__StateQueryMessage: + public NetworkClient::Message + { + public: + Application__StateQueryMessage(HostID requesting_host); + + HostID + GetRequestingHostID() + {return requestingHost;} + + private: + HostID + requestingHost; + }; +#endif + + //~~~~~~~~~~~~~~~~~~~~ Application__RunMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__RunMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__RunMissionMessage(); + }; +#pragma options align=reset +#else + class Application__RunMissionMessage: + public NetworkClient::Message + { + public: + Application__RunMissionMessage(); + }; +#endif + + //~~~~~~~~~~~~~~~~~~~~ Application__StopMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__StopMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__StopMissionMessage(ExitCodeID exit_code); + + ExitCodeID + GetExitCodeID() + {return((ExitCodeID) exitCode.value());} + + private: + LEDWORD + exitCode; + }; +#pragma options align=reset +#else + class Application__StopMissionMessage: + public NetworkClient::Message + { + public: + Application__StopMissionMessage(Enumeration exit_code); + + Enumeration + GetExitCode() + {return(exitCode);} + + private: + Enumeration + exitCode; + }; +#endif + + //~~~~~~~~~~~~~~~~~~~~ Application__AbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__AbortMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__AbortMissionMessage(ExitCodeID exit_code); + + ExitCodeID + GetExitCode() + {return((ExitCodeID) exitCode.value());} + + private: + LEDWORD + exitCode; + }; +#pragma options align=reset +#else + class Application__AbortMissionMessage: + public NetworkClient::Message + { + public: + Application__AbortMissionMessage(Enumeration exit_code); + + Enumeration + GetExitCode() + {return(exitCode);} + + private: + Enumeration + exitCode; + }; +#endif + + //~~~~~~~~~~~~~~~~~~ Application__SuspendMissionMessage ~~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__SuspendMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__SuspendMissionMessage(); + }; +#pragma options align=reset +#else + class Application__SuspendMissionMessage: + public NetworkClient::Message + { + public: + Application__SuspendMissionMessage(); + }; +#endif + + //~~~~~~~~~~~~~~~~~~~ Application__ResumeMissionMessage ~~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class Application__ResumeMissionMessage: + public NetworkEndpoint::Message + { + public: + Application__ResumeMissionMessage(); + }; +#pragma options align=reset +#else + class Application__ResumeMissionMessage: + public NetworkClient::Message + { + public: + Application__ResumeMissionMessage(); + }; +#endif diff --git a/MUNGA/APPTASK.cpp b/MUNGA/APPTASK.cpp new file mode 100644 index 0000000..010ca70 --- /dev/null +++ b/MUNGA/APPTASK.cpp @@ -0,0 +1,185 @@ +#include "munga.h" +#pragma hdrstop + +#include "apptask.h" +#include "renderer.h" +#include "audrend.h" +#include "app.h" +#include "nttmgr.h" +#include "gaugrend.h" + +#if defined(TRACE_COMPLETE_CYCLES) + BitTrace Complete_Cycles("Complete Cycles"); +#endif + +#if defined(TRACE_DEATH_ROW) + BitTrace Death_Row("Death Row"); +#endif + +//############################################################################# +//########################### ApplicationTask ########################### +//############################################################################# + +ApplicationTask::ApplicationTask(ClassID class_ID): + Component(class_ID) +{ +} + +ApplicationTask::~ApplicationTask() +{ +} + +//############################################################################# +//########################### BackgroundTasks ########################### +//############################################################################# + +BackgroundTasks::BackgroundTasks(): + taskSocket(NULL) +{ + taskIterator = new SChainIteratorOf(&taskSocket); + Register_Object(taskIterator); +} + +BackgroundTasks::~BackgroundTasks() +{ + Check(taskIterator); + taskIterator->DeletePlugs(); + Unregister_Object(taskIterator); + delete taskIterator; +} + +Logical + BackgroundTasks::TestInstance() const +{ + Component::TestInstance(); + Check(&taskSocket); + Check(taskIterator); + return True; +} + +void + BackgroundTasks::AddTask(ApplicationTask *task) +{ + Check(this); + Check(task); + taskSocket.Add(task); +} + +void + BackgroundTasks::Execute() +{ + Check(this); + + Check(taskIterator); + if (taskIterator->GetCurrent() == NULL) + { + taskIterator->First(); + } + + ApplicationTask *task = taskIterator->GetCurrent(); + Check(task); + + task->Execute(); + taskIterator->Next(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManagerTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + NetworkManagerTask::Execute() +{ + Check(this); + Check(application); + Check(application->GetNetworkManager()); + + Time start = Now(); + + application->GetNetworkManager()->ExecuteBackground(); + + Time end = Now(); + + if (end.ticks - start.ticks > 10) + { + end = start; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RoutePacketTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + RoutePacketTask::Execute() +{ + Check(this); + + Check(application); + Check(application->GetNetworkManager()); + application->GetNetworkManager()->RoutePacket(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ProcessEventTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + ProcessEventTask::Execute() +{ + Check(this); + Check(application); + application->ProcessOneEvent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + AudioRendererTask::Execute() +{ + Check(this); + Check(application); + if (application->GetAudioRenderer() != NULL) + { + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->ExecuteBackground(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + GaugeRendererTask::Execute() +{ + Check(this); + Check(application); + if (application->GetGaugeRenderer() != NULL) + { + Check(application->GetGaugeRenderer()); + application->GetGaugeRenderer()->ExecuteBackground(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ CompleteCyclesTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + CompleteCyclesTask::Execute() +{ + SET_COMPLETE_CYCLES(); + + Check(this); + Check(application); + Check(application->GetRendererManager()); +// application->GetRendererManager()->CompleteCycles(); + + CLEAR_COMPLETE_CYCLES(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ FryDeathRowTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + FryDeathRowTask::Execute() +{ + SET_DEATH_ROW(); + + Check(this); + Check(application); + Check(application->GetEntityManager()); + application->GetEntityManager()->FryDeathRow(); + + CLEAR_DEATH_ROW(); +} diff --git a/MUNGA/APPTASK.h b/MUNGA/APPTASK.h new file mode 100644 index 0000000..9d8714c --- /dev/null +++ b/MUNGA/APPTASK.h @@ -0,0 +1,153 @@ +#pragma once + +#include "style.h" +#include "cmpnnt.h" +#include "schain.h" + +#if defined(TRACE_COMPLETE_CYCLES) + extern BitTrace Complete_Cycles; + #define SET_COMPLETE_CYCLES() Complete_Cycles.Set() + #define CLEAR_COMPLETE_CYCLES() Complete_Cycles.Clear() +#else + #define SET_COMPLETE_CYCLES() + #define CLEAR_COMPLETE_CYCLES() +#endif + +#if defined(TRACE_DEATH_ROW) + extern BitTrace Death_Row; + #define SET_DEATH_ROW() Death_Row.Set() + #define CLEAR_DEATH_ROW() Death_Row.Clear() +#else + #define SET_DEATH_ROW() + #define CLEAR_DEATH_ROW() +#endif + +//########################################################################## +//####################### ApplicationTask ############################ +//########################################################################## + +class ApplicationTask: + public Component +{ +public: + ApplicationTask(ClassID class_ID = ApplicationTaskClassID); + ~ApplicationTask(); +}; + +//########################################################################## +//####################### BackgroundTasks ############################ +//########################################################################## + +class BackgroundTasks: + public Component +{ +public: + BackgroundTasks(); + ~BackgroundTasks(); + + Logical + TestInstance() const; + + void + AddTask(ApplicationTask *task); + + void + Execute(); + +private: + SChainOf + taskSocket; + SChainIteratorOf + *taskIterator; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManagerTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class NetworkManagerTask: + public ApplicationTask +{ +public: + NetworkManagerTask() {} + ~NetworkManagerTask() {} + + void + Execute(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ RoutePacketTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class RoutePacketTask: + public ApplicationTask +{ +public: + RoutePacketTask() {} + ~RoutePacketTask() {} + + void + Execute(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ ProcessEventTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class ProcessEventTask: + public ApplicationTask +{ +public: + ProcessEventTask() {} + ~ProcessEventTask() {} + + void + Execute(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AudioRendererTask: + public ApplicationTask +{ +public: + AudioRendererTask() {} + ~AudioRendererTask() {} + + void + Execute(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeRendererTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class GaugeRendererTask: + public ApplicationTask +{ +public: + GaugeRendererTask() {} + ~GaugeRendererTask() {} + + void + Execute(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ CompleteCyclesTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class CompleteCyclesTask: + public ApplicationTask +{ +public: + CompleteCyclesTask() {} + ~CompleteCyclesTask() {} + + void + Execute(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ FryDeathRowTask ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class FryDeathRowTask: + public ApplicationTask +{ +public: + FryDeathRowTask() {} + ~FryDeathRowTask() {} + + void + Execute(); +}; diff --git a/MUNGA/AUDCMP.cpp b/MUNGA/AUDCMP.cpp new file mode 100644 index 0000000..50224e0 --- /dev/null +++ b/MUNGA/AUDCMP.cpp @@ -0,0 +1,1523 @@ +#include "munga.h" +#pragma hdrstop + +#include "audcmp.h" +#include "audsrc.h" +#include "random.h" +#include "controls.h" +#include "objstrm.h" +#include "subsystm.h" +#include "namelist.h" + +//############################################################################# +//######################### AudioMessageWatcher ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioMessageWatcher::AudioMessageWatcher( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL), + messageTap(NULL) +{ + Check(stream); + Check(entity); + + // + // HACK - Get simulation pointer using names + // + Simulation *simulation; + CString subsystem_name; + + MemoryStream_Read(stream, &subsystem_name); + if ((simulation = entity->FindSubsystem(subsystem_name)) == NULL) + { + #if DEBUG_LEVEL>0 + { + CString entity_name("Entity"); + if (!(subsystem_name == entity_name)) + { + Dump(subsystem_name); + } + Verify(subsystem_name == entity_name); + } + #else + { + CString entity_name("Entity"); + if (!(subsystem_name == entity_name)) + { + DEBUG_STREAM << + "MessageWatcher::MessageWatcher - subsystem " << + subsystem_name << + "\n"; + Fail("MessageWatcher::MessageWatcher - subsystem not found\n"); + } + } + #endif + simulation = entity; + } + Check(simulation); + + // + // Get message id + // + Receiver::MessageID message_ID; + MemoryStream_Read(stream, &message_ID); + + // + // Get audio component, control ID, control value + // + AudioComponent *audio_component; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + + audioComponentSocket.Add(audio_component); + + // + // Make the message tap + // + messageTap = + MakeMessageTap( + simulation->GetDerivation(), + (ScanCallback)&AudioMessageWatcher::MessageTapScanCallback, + message_ID, + simulation + ); + Register_Object(messageTap); + + entity->AddAudioComponent(this); + + #if DEBUG_LEVEL>0 + verifyReceiver = simulation; + verifyMessageID = message_ID; + #endif +} + +// +//############################################################################# +//############################################################################# +// +AudioMessageWatcher::~AudioMessageWatcher() +{ + Unregister_Object(messageTap); + delete messageTap; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioMessageWatcher::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // HACK - Store simulation pointer using names + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, subsystem); + + // + // Store message ID + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, message_ID); + + // + // Store audio_component, control ID, control value + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioMessageWatcher::TestInstance() const +{ + Component::TestInstance(); + if (messageTap != NULL) + { + Check(messageTap); + } + Check(&audioComponentSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioMessageWatcher::MessageTapScanCallback( + Receiver::Message *message, + Receiver *receiver + ) +#else +void + AudioMessageWatcher::MessageTapScanCallback( + Receiver::Message *message, + Receiver* + ) +#endif +{ + Check(this); + Check(message); + Check(receiver); + Verify(verifyReceiver == receiver); + Verify(verifyMessageID == message->messageID); + + // + // Send the audio control message + // + if (DoesMessageMatch(message)) + { + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + controlValue + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlID, + controlValue + ); + #endif + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioMessageWatcher::ReceiveControl( + AudioControlID, + AudioControlValue + ) +{ +} + +//############################################################################# +//################# AudioControlsButtonMessageWatcher ################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioControlsButtonMessageWatcher::AudioControlsButtonMessageWatcher( + PlugStream *stream, + Entity *entity +): + AudioMessageWatcher(stream, entity) +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlsButtonMessageWatcher::~AudioControlsButtonMessageWatcher() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlsButtonMessageWatcher::DoesMessageMatch( + Receiver::Message *message + ) +{ + Check(this); + Check(message); + + ReceiverDataMessageOf *controls_button_message = + Cast_Object( + ReceiverDataMessageOf*, + message + ); + Check(controls_button_message); + + return (controls_button_message->dataContents > 0); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSend ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlSend::~AudioControlSend() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlSend::AudioControlSend( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream) +{ + AudioComponent *audio_component; + AudioControlID control_ID; + AudioControlValue control_value; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + MemoryStream_Read(stream, &control_ID); + MemoryStream_Read(stream, &control_value); + + Check(entity); + entity->AddAudioComponent(this); + + Check(audio_component); + #if 1 + audio_component->ReceiveControl(control_ID, control_value); + #else + audio_component->PostReceiveControl(control_ID, control_value); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSend::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSend::ReceiveControl( + AudioControlID, + AudioControlValue + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSplitter ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlSplitter::AudioControlSplitter( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL) +{ + int i, number_of_entries; + + MemoryStream_Read(stream, &number_of_entries); + for (i = 0; i < number_of_entries; i++) + { + AudioComponent *audio_component; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + Check(audio_component); + audioComponentSocket.Add(audio_component); + audio_component->AddWatcher(this); + } + + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlSplitter::~AudioControlSplitter() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSplitter::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Count number of entries + // + int number_of_entries = 0; + NameList::Entry *entry; + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_component")) + number_of_entries++; + entry = entry->GetNextEntry(); + } + + // + // Store entries + // + MemoryStream_Write(stream, &number_of_entries); + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_component")) + { + CString object_name; + ObjectID object_ID; + + Check_Pointer(entry->GetChar()); + object_name = entry->GetChar(); + + Check(stream); + object_ID = stream->FindObjectID(object_name); + if (object_ID == NullObjectID) + { + std::cout << "AudioControlSplitter::BuildFromPage - object_name == "; + std::cout << object_name << "\n"; + Fail("AudioControlSplitter::BuildFromPage - object_ID == NullObjectID"); + } + Verify(object_ID != NullObjectID); + MemoryStream_Write(stream, &object_ID); + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlSplitter::TestInstance() const +{ + AudioComponent::TestInstance(); + Check(&audioComponentSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSplitter::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + // + // Send to all of the components in the socket + // + SChainIteratorOf iterator(&audioComponentSocket); + AudioComponent *audio_component; + + Check(&iterator); + while ((audio_component = iterator.ReadAndNext()) != NULL) + { + Check(audio_component); + audio_component->ReceiveControl(control_ID, control_value); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlMixer ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlMixer::~AudioControlMixer() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlMixer::AudioControlMixer( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL) +{ + AudioComponent *audio_component; + AudioControlID first_input_control_ID; + AudioControlID last_input_control_ID; + AudioControlID output_control_ID; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + MemoryStream_Read(stream, &first_input_control_ID); + MemoryStream_Read(stream, &last_input_control_ID); + MemoryStream_Read(stream, &output_control_ID); + + AudioControlMixerX( + audio_component, + entity, + first_input_control_ID, + last_input_control_ID, + output_control_ID + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlMixer::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, first_input_control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, last_input_control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, output_control_ID); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlMixer::AudioControlMixerX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID first_input_control_ID, + AudioControlID last_input_control_ID, + AudioControlID output_control_ID + ) +{ + // + // Set up the control mix parameters + // + firstInputControlID = first_input_control_ID; + outputControlID = output_control_ID; + + Verify(last_input_control_ID > first_input_control_ID); + numberOfInputs = last_input_control_ID - first_input_control_ID + 1; + Verify(numberOfInputs <= AUDIO_CONTROL_MIXER_MAX_CONTROLS); + + for (int i = 0; i < numberOfInputs; i++) + { + Verify(i >= 0 && i < AUDIO_CONTROL_MIXER_MAX_CONTROLS); + controlValueArray[i] = 0.0f; + } + + // + // Remember the audio component to mix to and add this + // component to the entity + // + Check(audio_component); + audioComponentSocket.Add(audio_component); + audio_component->AddWatcher(this); + + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlMixer::TestInstance() const +{ + AudioComponent::TestInstance(); + Check(&audioComponentSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlMixer::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + // + // Index the controller into the mix table + // + int index = control_ID - firstInputControlID; + + if (index >= 0 && index < numberOfInputs) + { + // + // Set the control value + // + Verify(index >= 0 && index < AUDIO_CONTROL_MIXER_MAX_CONTROLS); + controlValueArray[index] = control_value; + + // + // Mix the new control value + // + AudioControlValue mixed_value = 0.0f; + + for (int i = 0; i < numberOfInputs; i++) + { + Verify(i >= 0 && i < AUDIO_CONTROL_MIXER_MAX_CONTROLS); + mixed_value += controlValueArray[i]; + } + + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + outputControlID, + mixed_value + ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlMultiplier ~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlMultiplier::~AudioControlMultiplier() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlMultiplier::AudioControlMultiplier( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL) +{ + AudioComponent *audio_component; + AudioControlID first_input_control_ID; + AudioControlID last_input_control_ID; + AudioControlID output_control_ID; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + MemoryStream_Read(stream, &first_input_control_ID); + MemoryStream_Read(stream, &last_input_control_ID); + MemoryStream_Read(stream, &output_control_ID); + + AudioControlMultiplierX( + audio_component, + entity, + first_input_control_ID, + last_input_control_ID, + output_control_ID + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlMultiplier::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, first_input_control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, last_input_control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, output_control_ID); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlMultiplier::AudioControlMultiplierX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID first_input_control_ID, + AudioControlID last_input_control_ID, + AudioControlID output_control_ID + ) +{ + // + // Set up the control mix parameters + // + firstInputControlID = first_input_control_ID; + outputControlID = output_control_ID; + + Verify(last_input_control_ID > first_input_control_ID); + numberOfInputs = last_input_control_ID - first_input_control_ID + 1; + Verify(numberOfInputs <= AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS); + + for (int i = 0; i < numberOfInputs; i++) + { + Verify(i >= 0 && i < AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS); + controlValueArray[i] = 1.0f; + } + + // + // Remember the audio component to mix to and add this + // component to the entity + // + Check(audio_component); + audioComponentSocket.Add(audio_component); + audio_component->AddWatcher(this); + + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlMultiplier::TestInstance() const +{ + AudioComponent::TestInstance(); + Check(&audioComponentSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlMultiplier::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + // + // Index the controller into the mix table + // + int index = control_ID - firstInputControlID; + + if (index >= 0 && index < numberOfInputs) + { + // + // Set the control value + // + Verify(index >= 0 && index < AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS); + controlValueArray[index] = control_value; + + // + // Multiply the new control value + // + AudioControlValue mult_value = 1.0f; + + for (int i = 0; i < numberOfInputs; i++) + { + Verify(i >= 0 && i < AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS); + mult_value *= controlValueArray[i]; + } + + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + outputControlID, + mult_value + ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSmoother ~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlSmoother::~AudioControlSmoother() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlSmoother::AudioControlSmoother( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL) +{ + // + // Get audio component + // + AudioComponent *audio_component; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + + // + // Get audio control id, sample size, and initial fill value + // + size_t number_of_samples; + AudioControlValue initial_fill_value; + AudioControlID control_ID; + + MemoryStream_Read(stream, &control_ID); + MemoryStream_Read(stream, &number_of_samples); + MemoryStream_Read(stream, &initial_fill_value); + audioControlAverage.SetSize(number_of_samples, initial_fill_value); + + AudioControlSmootherX( + audio_component, + entity, + control_ID + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSmoother::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store audio component + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + // + // Store audio control id, sample size, and initial fill value + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, size_t, number_of_samples); + + AudioControlValue initial_fill_value = 0.0f; + if (name_list->FindData("initial_fill_value") != NULL) + { + Check_Pointer(name_list->FindData("initial_fill_value")); + Convert_From_Ascii( + (const char *)name_list->FindData("initial_fill_value"), + &initial_fill_value + ); + } + MemoryStream_Write(stream, &initial_fill_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSmoother::AudioControlSmootherX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID control_ID + ) +{ + controlID = control_ID; + + // + // Remember the audio component and add this + // component to the entity + // + Check(audio_component); + audioComponentSocket.Add(audio_component); + audio_component->AddWatcher(this); + + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlSmoother::TestInstance() const +{ + AudioComponent::TestInstance(); + Check(&audioComponentSocket); + Check(&audioControlAverage); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSmoother::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + if (control_ID == controlID) + { + audioControlAverage.Add(control_value); + + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + audioControlAverage.CalculateOlympicAverage() + ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResourceSelector ~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioResourceSelector::~AudioResourceSelector() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioResourceSelector::AudioResourceSelector( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioSourceSocket(NULL) +{ + AudioSource *audio_source; + AudioResourceIndex *audio_resource_index; + AudioControlID control_ID; + AudioControlValue min_control_value; + AudioControlValue max_control_value; + Logical dump_value; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_source); + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource_index); + MemoryStream_Read(stream, &control_ID); + MemoryStream_Read(stream, &min_control_value); + MemoryStream_Read(stream, &max_control_value); + MemoryStream_Read(stream, &dump_value); + + AudioResourceSelectorX( + audio_source, + entity, + audio_resource_index, + control_ID, + min_control_value, + max_control_value, + dump_value + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResourceSelector::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + CString audio_source_name("audio_source"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_source_name); + + CString audio_resource_index_name("audio_resource_index"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_resource_index_name); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, min_control_value); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, max_control_value); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResourceSelector::AudioResourceSelectorX( + AudioSource *audio_source, + Entity *entity, + AudioResourceIndex *audio_resource_index, + AudioControlID control_ID, + AudioControlValue min_control_value, + AudioControlValue max_control_value, + Logical dump_value + ) +{ + controlID = control_ID; + minControlValue = min_control_value; + maxControlValue = max_control_value; + dumpValue = dump_value; + + Check(audio_resource_index); + audioResourceIndex = audio_resource_index; + + Check(audio_source); + audioSourceSocket.Add(audio_source); + audio_source->AddWatcher(this); + + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioResourceSelector::TestInstance() const +{ + AudioComponent::TestInstance(); + Check(&audioSourceSocket); + Check(audioResourceIndex); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResourceSelector::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + if (control_ID == controlID) + { + AudioComponent *audio_component; + AudioSource *audio_source; + + audio_component = audioSourceSocket.GetCurrent(); + audio_source = Cast_Object(AudioSource*, audio_component); + Check(audio_source); + + if (audio_source->GetAudioSourceState() == StoppedAudioSourceState) + { + AudioResource *audio_resource; + int index; + + Clamp(control_value, minControlValue, maxControlValue); + Verify(!Small_Enough(maxControlValue - minControlValue)); + + index = + ( ((Scalar)audioResourceIndex->GetSize()-1.0f) * + (control_value - minControlValue) / + (maxControlValue - minControlValue) ) + 0.5f; + #if DEBUG_LEVEL>0 + if (!(index >= 0 && index < audioResourceIndex->GetSize())) + { + Dump(control_value); + Dump(index); + Dump(audioResourceIndex->GetSize()); + } + #endif + Verify(index >= 0 && index < audioResourceIndex->GetSize()); + + #if DEBUG_LEVEL>0 + if (dumpValue) + { + Tell("index:" << index); + Tell("; size: " << audioResourceIndex->GetSize() << "\n"); + } + #endif + + audio_resource = audioResourceIndex->GetAudioResource(index); + Check(audio_resource); + audio_source->SetAudioResource(audio_resource); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSampleAndHold ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioSampleAndHold::AudioSampleAndHold( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL) +{ + AudioComponent *audio_component; + AudioControlID control_ID; + Scalar seconds; + AudioTime sample_duration; + Scalar min_value; + Scalar max_value; + + // + // audio_component + // + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + + // + // control_ID, sample_duration + // + MemoryStream_Read(stream, &control_ID); + MemoryStream_Read(stream, &seconds); + sample_duration = seconds; + + // + // min_value, max_value + // + MemoryStream_Read(stream, &min_value); + MemoryStream_Read(stream, &max_value); + + AudioSampleAndHoldX( + audio_component, + entity, + control_ID, + sample_duration, + min_value, + max_value + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSampleAndHold::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // audio_component + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + // + // control_ID, sample_duration + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, sample_duration); + + // + // min_value, max_value + // + Scalar min_value = 0.0f; + Scalar max_value = 1.0f; + + if (name_list->FindData("min_value") != NULL) + { + Convert_From_Ascii( + (const char *)name_list->FindData("min_value"), + &min_value + ); + } + if (name_list->FindData("max_value") != NULL) + { + Convert_From_Ascii( + (const char *)name_list->FindData("max_value"), + &max_value + ); + } + Verify(max_value > min_value); + MemoryStream_Write(stream, &min_value); + MemoryStream_Write(stream, &max_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSampleAndHold::AudioSampleAndHoldX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID audio_control_ID, + const AudioTime &sample_duration, + Scalar min_value, + Scalar max_value + ) +{ + audioControlID = audio_control_ID; + currentValue = 0.0f; + nextSampleTime = AudioTime::Now(); + sampleDuration = sample_duration; + Verify(max_value > min_value); + minValue = min_value; + maxValue = max_value; + + Check(audio_component); + audioComponentSocket.Add(audio_component); + audio_component->AddWatcher(this); + + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioSampleAndHold::~AudioSampleAndHold() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSampleAndHold::Execute() +{ + Check(this); + + AudioComponent::Execute(); + + if (AudioTime::Now() > nextSampleTime) + { + SampleAndHold(); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSampleAndHold::ReceiveControl( + AudioControlID control_ID, + AudioControlValue + ) +{ + Check(this); + + if (control_ID == StartAudioControlID) + { + SampleAndHold(); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSampleAndHold::SampleAndHold() +{ + Check(this); + + Scalar random_sample = Random; + + Verify(0.0f <= random_sample && random_sample <= 1.0f); + Verify(maxValue > minValue); + currentValue = minValue + random_sample * (maxValue - minValue); + + nextSampleTime = AudioTime::Now(); + nextSampleTime += sampleDuration; + + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + audioControlID, + currentValue + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLFO ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioLFO::AudioLFO( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL) +{ + AudioComponent *audio_component; + AudioControlID control_ID; + AudioLFOWaveForm wave_form; + Scalar the_period; + AudioControlValue min_value; + AudioControlValue max_value; + Logical dump_value; + + // + // audio_component + // + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + + // + // control_ID, wave_form, period + // + MemoryStream_Read(stream, &control_ID); + MemoryStream_Read(stream, &wave_form); + MemoryStream_Read(stream, &the_period); + + // + // min_value, max_value, dump_value + // + MemoryStream_Read(stream, &min_value); + MemoryStream_Read(stream, &max_value); + MemoryStream_Read(stream, &dump_value); + + AudioLFOX( + audio_component, + entity, + control_ID, + wave_form, + the_period, + min_value, + max_value, + dump_value + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLFO::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // audio_component + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + // + // control_ID, wave_form, period + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, wave_form); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, period); + + // + // min_value, max_value + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, min_value); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, max_value); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLFO::AudioLFOX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID audio_control_ID, + AudioLFOWaveForm wave_form, + Scalar the_period, + AudioControlValue min_value, + AudioControlValue max_value, + Logical dump_value + ) +{ + Check(audio_component); + audioComponentSocket.Add(audio_component); + audio_component->AddWatcher(this); + + audioControlID = audio_control_ID; + waveForm = wave_form; + minValue = min_value; + maxValue = max_value; + Verify(max_value > min_value); + + period = the_period; + startTime = AudioTime::Now(); + + dumpValue = dump_value; + + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioLFO::~AudioLFO() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLFO::Execute() +{ + Check(this); + AudioComponent::Execute(); + Generate(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLFO::ReceiveControl( + AudioControlID control_ID, + AudioControlValue + ) +{ + Check(this); + if (control_ID == StartAudioControlID) + { + Generate(); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLFO::Generate() +{ + Check(this); + + // + // HACK - For now, everything is sinusoidal + // + // res = sin( (now-start) * (PI/period) ) + // val = min + ( 0.5 * (res+1) ) * (max - min) + // + Scalar time_factor; + Scalar sample; + Scalar current_value; + + time_factor = AudioTime::Now(); + Verify(!Small_Enough((Scalar)period)); + time_factor = (time_factor - (Scalar)startTime) / (Scalar)period; + + sample = (sin(time_factor * PI) + 1.0f) * 0.5f; + Verify(0.0f <= sample && sample <= 1.0f); + Verify(maxValue > minValue); + current_value = minValue + sample * (maxValue - minValue); + + #if DEBUG_LEVEL>0 + if (dumpValue) + { + Dump(current_value); + } + #endif + + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + audioControlID, + current_value + ); +} diff --git a/MUNGA/AUDCMP.h b/MUNGA/AUDCMP.h new file mode 100644 index 0000000..180aa68 --- /dev/null +++ b/MUNGA/AUDCMP.h @@ -0,0 +1,720 @@ +#pragma once + +#include "style.h" +#include "audio.h" +#include "audloc.h" +#include "average.h" +#include "audtime.h" + +//########################################################################## +//######################## AudioMessageWatcher ####################### +//########################################################################## + +class AudioMessageWatcher: + public AudioComponent +{ +public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor + //----------------------------------------------------------------------- + // + AudioMessageWatcher( + PlugStream *stream, + Entity *entity + ); + ~AudioMessageWatcher(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // MessageTapScanCallback + //----------------------------------------------------------------------- + // + void + MessageTapScanCallback( + Receiver::Message *message, + Receiver *receiver + ); + + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + virtual Logical + DoesMessageMatch(Receiver::Message*) + {return True;} + + // + //----------------------------------------------------------------------- + // Private Data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlID controlID; + AudioControlValue controlValue; + + MessageTap *messageTap; + + #if DEBUG_LEVEL>0 + Receiver *verifyReceiver; + Receiver::MessageID verifyMessageID; + #endif +}; + +//########################################################################## +//############### AudioControlsButtonMessageWatcher ################## +//########################################################################## + +class AudioControlsButtonMessageWatcher: + public AudioMessageWatcher +{ +public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor + //----------------------------------------------------------------------- + // + AudioControlsButtonMessageWatcher( + PlugStream *stream, + Entity *entity + ); + ~AudioControlsButtonMessageWatcher(); + +private: + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + Logical + DoesMessageMatch(Receiver::Message*); +}; + +//########################################################################## +//######################### AudioControlSend ######################### +//########################################################################## + +class AudioControlSend: + public AudioComponent +{ +public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlSend( + PlugStream *stream, + Entity *entity + ); + ~AudioControlSend(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); +}; + +//########################################################################## +//####################### AudioControlSplitter ####################### +//########################################################################## + +class AudioControlSplitter: + public AudioComponent +{ +public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlSplitter( + PlugStream *stream, + Entity *entity + ); + void + AudioControlSplitterX(Entity *entity); + ~AudioControlSplitter(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SChainOf audioComponentSocket; +}; + +//########################################################################## +//####################### AudioControlMixer ########################## +//########################################################################## + +#define AUDIO_CONTROL_MIXER_MAX_CONTROLS (4) + +class AudioControlMixer: + public AudioComponent +{ +public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlMixer( + PlugStream *stream, + Entity *entity + ); + void + AudioControlMixerX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID first_input_control_ID, + AudioControlID last_input_control_ID, + AudioControlID output_control_ID + ); + ~AudioControlMixer(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlValue + controlValueArray[AUDIO_CONTROL_MIXER_MAX_CONTROLS]; + AudioControlID + firstInputControlID; + int + numberOfInputs; + AudioControlID + outputControlID; +}; + +//########################################################################## +//###################### AudioControlMultiplier ###################### +//########################################################################## + +#define AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS (4) + +class AudioControlMultiplier: + public AudioComponent +{ +public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlMultiplier( + PlugStream *stream, + Entity *entity + ); + void + AudioControlMultiplierX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID first_input_control_ID, + AudioControlID last_input_control_ID, + AudioControlID output_control_ID + ); + ~AudioControlMultiplier(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlValue + controlValueArray[AUDIO_CONTROL_MULTIPLIER_MAX_CONTROLS]; + AudioControlID + firstInputControlID; + int + numberOfInputs; + AudioControlID + outputControlID; +}; + +//########################################################################## +//######################## AudioControlSmoother ###################### +//########################################################################## + +class AudioControlSmoother: + public AudioComponent +{ +public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioControlSmoother( + PlugStream *stream, + Entity *entity + ); + void + AudioControlSmootherX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID control_ID + ); + ~AudioControlSmoother(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + AverageOf + audioControlAverage; + AudioControlID + controlID; +}; + +//########################################################################## +//####################### AudioResourceSelector ###################### +//########################################################################## + +class AudioResourceIndex; + +class AudioResourceSelector: + public AudioComponent +{ +public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + AudioResourceSelector( + PlugStream *stream, + Entity *entity + ); + void + AudioResourceSelectorX( + AudioSource *audio_source, + Entity *entity, + AudioResourceIndex *audio_resource_index, + AudioControlID control_ID, + AudioControlValue min_control_value, + AudioControlValue max_control_value, + Logical dump_value + ); + ~AudioResourceSelector(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SlotOf + audioSourceSocket; + + AudioResourceIndex + *audioResourceIndex; + + AudioControlID + controlID; + AudioControlValue + minControlValue, + maxControlValue; + + Logical + dumpValue; +}; + +//########################################################################## +//######################## AudioSampleAndHold ######################## +//########################################################################## + +class AudioSampleAndHold: + public AudioComponent +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioSampleAndHold( + PlugStream *stream, + Entity *entity + ); + void + AudioSampleAndHoldX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID audio_control_ID, + const AudioTime &sample_duration, + Scalar min_value, + Scalar max_value + ); + ~AudioSampleAndHold(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Execute + //-------------------------------------------------------------------- + // + void + Execute(); + + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //----------------------------------------------------------------------- + // Private methods + //----------------------------------------------------------------------- + // + void + SampleAndHold(); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlID + audioControlID; + AudioControlValue + minValue, + maxValue, + currentValue; + AudioTime + nextSampleTime, + sampleDuration; +}; + +//########################################################################## +//############################# AudioLFO ############################# +//########################################################################## + +enum AudioLFOWaveForm +{ + SinusoidalAudioLFOWaveForm = 0, + TriangularAudioLFOWaveForm = 1 +}; + +inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + AudioLFOWaveForm *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} +inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const AudioLFOWaveForm *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + +class AudioLFO: + public AudioComponent +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioLFO( + PlugStream *stream, + Entity *entity + ); + void + AudioLFOX( + AudioComponent *audio_component, + Entity *entity, + AudioControlID audio_control_ID, + AudioLFOWaveForm wave_form, + Scalar the_period, + AudioControlValue min_value, + AudioControlValue max_value, + Logical dump_value + ); + ~AudioLFO(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // Execute + //-------------------------------------------------------------------- + // + void + Execute(); + + // + //----------------------------------------------------------------------- + // Controller methods + //----------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + // + //----------------------------------------------------------------------- + // Private methods + //----------------------------------------------------------------------- + // + void + Generate(); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; + + AudioControlID + audioControlID; + AudioLFOWaveForm + waveForm; + AudioControlValue + minValue, + maxValue; + AudioTime + period; + AudioTime + startTime; + Logical + dumpValue; +}; diff --git a/MUNGA/AUDENT.cpp b/MUNGA/AUDENT.cpp new file mode 100644 index 0000000..e8b8195 --- /dev/null +++ b/MUNGA/AUDENT.cpp @@ -0,0 +1,177 @@ +#include "munga.h" +#pragma hdrstop + +#include "audent.h" +#include "jmover.h" +#include "app.h" +#include "hostmgr.h" + +//############################################################################# +//########################### AudioEntity ############################### +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* AudioEntity::GetClassDerivations() +{ static Derivation classDerivations(Explosion::GetClassDerivations(), "AudioEntity"); + return &classDerivations; +} + + +AudioEntity::SharedData + AudioEntity::DefaultData( + AudioEntity::GetClassDerivations(), + AudioEntity::GetMessageHandlers(), + AudioEntity::GetAttributeIndex(), + AudioEntity::StateCount, + (Entity::MakeHandler)AudioEntity::Make + ); + +// +//############################################################################# +//############################################################################# +// +AudioEntity::AudioEntity( + AudioEntity::MakeMessage *creation_message, + AudioEntity::SharedData &shared_data +): + Explosion(creation_message, shared_data), + parentEntitySocket(NULL) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + + // + // Get the parent entity + // + Entity *parent_entity; + + parent_entity = + application->GetHostManager()->GetEntityPointer( + creation_message->parentEntityID + ); + if (parent_entity != NULL) + { + parentEntitySocket.Add(parent_entity); + parentEntitySegment = creation_message->parentEntitySegment; + } + else + { + parentEntitySegment = NULL; + } + + // + // Set simulation + // + SetPerformance(&AudioEntity::AudioEntitySimulation); + SetValidFlag(); +} + +// +//############################################################################# +//############################################################################# +// +AudioEntity::~AudioEntity() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioEntity::TestInstance() const +{ + if (!IsDerivedFrom(*GetClassDerivations())) + { + return False; + } + Check(&parentEntitySocket); + if (parentEntitySegment != NULL) + { + Check(parentEntitySegment); + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +AudioEntity* + AudioEntity::Make(AudioEntity::MakeMessage *creation_message) +{ + return new AudioEntity(creation_message); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioEntity::AudioEntitySimulation(Scalar time_slice) +{ + Check(this); + + // + // Get the parent entity, if it does not exist, condemn to death row + // + Entity *parent_entity; + + if ((parent_entity = parentEntitySocket.GetCurrent()) == NULL) + { + CondemnToDeathRow(); + return; + } + + // + // Get the orign of the parent entities segment + // + JointedMover *jointed_mover; + + Verify(parent_entity->IsDerivedFrom(JointedMover::GetClassDerivations())); + jointed_mover = Cast_Object(JointedMover*, parent_entity); + Check(jointed_mover); + Check(parentEntitySegment); + jointed_mover->GetSegmentToWorld( + *parentEntitySegment, + &localToWorld + ); + + // + // Set the origin of this entity + // + localOrigin = localToWorld; + updateOrigin = localOrigin; + + // + // Call inherited simulation + // + Explosion::ExplosionSimulation(time_slice); +} + +//############################################################################# +//##################### AudioEntity__MakeMessage ######################## +//############################################################################# + +AudioEntity__MakeMessage::AudioEntity__MakeMessage( + ResourceDescription::ResourceID resource_ID, + Entity *parent_entity, + EntitySegment *parent_entity_segment +): + Explosion::MakeMessage( + AudioEntity::MakeMessageID, + sizeof(AudioEntity__MakeMessage), + RegisteredClass::AudioEntityClassID, + EntityID::Null, + resource_ID, + Entity::HermitInstance|Entity::DynamicFlag, + parent_entity->localOrigin, + parent_entity->GetEntityID(), + EntityID::Null + ), + parentEntityID(parent_entity->GetEntityID()), + parentEntitySegment(parent_entity_segment) +{ +} diff --git a/MUNGA/AUDENT.h b/MUNGA/AUDENT.h new file mode 100644 index 0000000..afb95dc --- /dev/null +++ b/MUNGA/AUDENT.h @@ -0,0 +1,72 @@ +#pragma once + +#include "explode.h" +#include "segment.h" +#include "slot.h" + +//########################################################################## +//########################## AudioEntity ############################# +//########################################################################## + +class AudioEntity__MakeMessage; + +class AudioEntity : public Explosion +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public types +// +public: + typedef AudioEntity__MakeMessage MakeMessage; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + AudioEntity(MakeMessage *creation_message, SharedData &shared_data = DefaultData); + ~AudioEntity(); + + static AudioEntity* Make(MakeMessage *creation_message); + + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void (AudioEntity::*Performance)(Scalar time_slice); + + void SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void AudioEntitySimulation(Scalar time_slice); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + SlotOf parentEntitySocket; + EntitySegment *parentEntitySegment; +}; + +//########################################################################## +//#################### AudioEntity__MakeMessage ###################### +//########################################################################## + +class AudioEntity__MakeMessage : public Explosion::MakeMessage +{ +public: + AudioEntity__MakeMessage(ResourceDescription::ResourceID resource_ID, Entity *parent_entity, EntitySegment *parent_entity_segment); + + EntityID parentEntityID; + EntitySegment *parentEntitySegment; +}; diff --git a/MUNGA/AUDIO.cpp b/MUNGA/AUDIO.cpp new file mode 100644 index 0000000..b017424 --- /dev/null +++ b/MUNGA/AUDIO.cpp @@ -0,0 +1,474 @@ +#include "munga.h" +#pragma hdrstop + +#include "audio.h" +#include "audrend.h" +#include "app.h" +#include "..\munga_l4\openal\al.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Audio Constants ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const Scalar AudioDoubleTriggerCutoff = 0.2f; + +const AudioControlValue MaxAudioVolume = 1.0f; +const AudioControlValue MinAudioVolume = 0.0f; +const AudioControlValue LowAudioVolumeThreshold = 0.3f; + +const AudioControlValue MaxAudioBrightness = 1.0f; +const AudioControlValue MinAudioBrightness = 0.0f; + +const AudioControlValue MaxAudioAttack = 1.0f; +const AudioControlValue MinAudioAttack = 0.0f; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioHead::AudioHead(): + headEntitySocket(NULL) +{ + // + // Start frame counter at 0, other counts should be at + // NullAudioFrameCount + // + audioFrameCount = 0; + + // + // Other audio parameters + // + clippingRadius = 100.0f; + distanceBetweenEars = 1.0f; + amplitudeRollOffExponent = 1.0f; + amplitudeRollOffKnee = 10.0f, + amplitudeRollOffDistanceScale = 0.05f; + highFrequencyRollOffExponent = 0.5f; + highFrequencyRollOffKnee = 10.0f; + highFrequencyRollOffDistanceScale = 0.05f; + reverbToDryRatio = 0.1f; + audioSoundSpeed = 345.0f; + audioDopplerConstant = 20.0f; + sourceCompressionExponent = 0.5f; + sourceCompressionScale = 0.5f; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +AudioHead::~AudioHead() +{ + Check(this); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioHead::TestInstance() const +{ + Check(&headEntitySocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::LinkToEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + // Remove existing entity, add new one + // + if (headEntitySocket.GetCurrent() != NULL) + { + headEntitySocket.Remove(); + } + headEntitySocket.Add(entity); + + alDistanceModel(AL_LINEAR_DISTANCE); + alDopplerFactor(0.3f); + + #if 0 + // + // Make the new clipping sphere + // + clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition); + #endif +} + +// +//############################################################################# +//############################################################################# +// +LinearMatrix + AudioHead::GetEarToWorld() +{ + Check(this); + + Entity *entity = headEntitySocket.GetCurrent(); + Check(entity); + return entity->localToWorld; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::Execute() +{ + Check(this); + + // + // Increment frame counter + // + audioFrameCount = Now().ticks; + Verify(audioFrameCount < LONG_MAX); + + //set current listener orientation + Vector3D headVelocity; + + headVelocity.MultiplyByInverse(this->GetHeadEntity()->GetWorldLinearVelocity(), this->GetHeadEntity()->localToWorld); + alListener3f(AL_VELOCITY, -headVelocity.x, -headVelocity.y, -headVelocity.z); + + #if 0 + // + // Get the entity + // + Entity *entity = headEntitySocket.GetCurrent(); + Check(entity); + + // + // Make the new clipping sphere + // + clippingSphere.SetCurrentOrigin(entity->localOrigin.linearPosition); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::DefineClippingSphere(Scalar radius) +{ + Check(this); + + clippingRadius = radius; + + #if 0 + // + // Get entity position + // + Entity *entity; + Point3D position(0.0f, 0.0f, 0.0f); + + if ((entity = headEntitySocket.GetCurrent()) != NULL) + { + Check(entity); + position = entity->localOrigin.linearPosition; + } + + // + // Make the new clipping sphere + // + clippingSphere.SetCurrentOrigin(position); + clippingSphere.SetReferenceRadius(radius); + #endif +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioHead::IsPointClipped(const Point3D &point) +{ + Check(this); + + Entity + *entity; + Vector3D + difference; + + entity = headEntitySocket.GetCurrent(); + Check(entity); + difference.Subtract(entity->localOrigin.linearPosition, point); + return difference.LengthSquared() > clippingRadius*clippingRadius; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlDopplerEffect( + Scalar doppler_constant, + Scalar sound_speed + ) +{ + Check(this); + audioDopplerConstant = doppler_constant; + audioSoundSpeed = sound_speed; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlAmplitudeRollOff( + Scalar exponent, + Scalar amplitude_rolloff_knee, + Scalar distance_scale + ) +{ + Check(this); + amplitudeRollOffExponent = exponent; + amplitudeRollOffKnee = amplitude_rolloff_knee; + amplitudeRollOffDistanceScale = distance_scale; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlHighFrequencyRollOff( + Scalar exponent, + Scalar high_frequency_rolloff_knee, + Scalar distance_scale + ) +{ + Check(this); + highFrequencyRollOffExponent = exponent; + highFrequencyRollOffKnee = high_frequency_rolloff_knee; + highFrequencyRollOffDistanceScale = distance_scale; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::ControlSourceCompression( + Scalar exponent, + Scalar scale + ) +{ + Check(this); + sourceCompressionExponent = exponent; + sourceCompressionScale = scale; + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioHead::SetPositionalCulling(Logical) +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +const Receiver::HandlerEntry + AudioComponent::MessageHandlerEntries[]= +{ + { + AudioComponent::ReceiveControlMessageID, + "ReceiveControl", + (AudioComponent::Handler)&AudioComponent::ReceiveControlMessageHandler + } +}; + +AudioComponent::MessageHandlerSet& AudioComponent::GetMessageHandlers() +{ + static AudioComponent::MessageHandlerSet messageHandlers(ELEMENTS(AudioComponent::MessageHandlerEntries), AudioComponent::MessageHandlerEntries, Component::GetMessageHandlers()); + return messageHandlers; +} + +// +//############################################################################# +//############################################################################# +// +Derivation* AudioComponent::GetClassDerivations() +{ + static Derivation classDerivations(Component::GetClassDerivations(), "AudioComponent"); + return &classDerivations; +} + +AudioComponent::SharedData + AudioComponent::DefaultData( + AudioComponent::GetClassDerivations(), + AudioComponent::GetMessageHandlers() + ); + +// +//############################################################################# +//############################################################################# +// +AudioComponent::AudioComponent( + PlugStream *stream, + SharedData &shared_data +): + Component(stream, shared_data), + audioWatcherSocket(NULL) +{ + nextExecuteWatcherFrame = NullAudioFrameCount; +} + +// +//############################################################################# +//############################################################################# +// +AudioComponent::~AudioComponent() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioComponent::TestInstance() const +{ + if (!IsDerivedFrom(*GetClassDerivations())) + { + return False; + } + Check(&audioWatcherSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::ExecuteWatchers() +{ + Check(this); + + // + // Execute watchers if this is the next watcher frame + // + AudioFrameCount + audio_frame_count; + + Check(application); + Check(application->GetAudioRenderer()); + audio_frame_count = application->GetAudioRenderer()->GetAudioFrameCount(); + if (nextExecuteWatcherFrame <= audio_frame_count) + { + nextExecuteWatcherFrame = audio_frame_count + DefaultAudioFrameDelay; + + // + // Execute watchers + // + ChainIteratorOf + iterator(&audioWatcherSocket); + Component + *component; + + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + component->Execute(); + } + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::Execute() +{ + Check(this); + ExecuteWatchers(); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::ReceiveControl( + AudioControlID, + AudioControlValue + ) +{ + Fail("AudioComponent::ReceiveControl - Should never reach here"); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::PostReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + ReceiveControlMessage + message(control_ID, control_value); + + Check(application); + // ECH 1/26/96 - application->Post(HighEventPriority, this, &message); + application->Post(DefaultEventPriority, this, &message); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioComponent::ReceiveControlMessageHandler(ReceiveControlMessage *message) +{ + Check(this); + Check(message); + ReceiveControl(message->controlID, message->controlValue); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~~~~ + + +AudioComponent__ReceiveControlMessage::AudioComponent__ReceiveControlMessage( + AudioControlID control_ID, + AudioControlValue control_value +): + Receiver::Message( + AudioComponent::ReceiveControlMessageID, + sizeof(AudioComponent__ReceiveControlMessage) + ) +{ + controlID = control_ID; + controlValue = control_value; +} diff --git a/MUNGA/AUDIO.h b/MUNGA/AUDIO.h new file mode 100644 index 0000000..bd74762 --- /dev/null +++ b/MUNGA/AUDIO.h @@ -0,0 +1,655 @@ +#pragma once + +#include "style.h" +#include "entity.h" +#include "sphere.h" +#include "slot.h" +#include "table.h" + +class PlugStream; + +// +//-------------------------------------------------------------------------- +// Support types +//-------------------------------------------------------------------------- +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef long AudioTick; +typedef long AudioDivisionsPerBeat; +typedef long AudioTempo; + +typedef long AudioFrameCount; +const AudioFrameCount NullAudioFrameCount = -1; +const AudioFrameCount DefaultAudioFrameDelay = 2; + +extern const Scalar AudioDoubleTriggerCutoff; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Resource types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef int AudioResourceID; +typedef int AudioVoiceCount; +typedef Scalar AudioRadiationProfile; +typedef Scalar AudioPitchCents; + +enum AudioRenderType +{ + TransientAudioRenderType = 0, + SustainedAudioRenderType = 1 +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +enum AudioRepresentation +{ + InternalAudioRepresentation = 0, + ExternalAudioRepresentation = 1 +}; + +#define AUDIO_SOURCE_PRIORITY_COUNT (5) +enum AudioSourcePriority +{ + MinAudioSourcePriority = 0, + LowAudioSourcePriority = 1, + MedAudioSourcePriority = 2, + HighAudioSourcePriority = 3, + MaxAudioSourcePriority = 4 +}; + +enum AudioSourceState +{ + StoppedAudioSourceState = 0, + DormantAudioSourceState = 1, + RunningAudioSourceState = 2, + SuspendedAudioSourceState = 3 +}; + +enum AudioSourceMixPresence +{ + ManualAudioSourceMixPresence = 0, + MaxAudioSourceMixPresence = 1, + HighAudioSourceMixPresence = 2, + MedAudioSourceMixPresence = 3, + LowAudioSourceMixPresence = 4, + MinAudioSourceMixPresence = 5 +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +enum AudioControlID +{ + NullAudioControlID = 0, + StartAudioControlID, + StopAudioControlID, + VolumeAudioControlID, + PitchAudioControlID, + BrightnessAudioControlID, + AttackVolumeAudioControlID, + AttackTimeAudioControlID, + NoteAudioControlID, + IdleAudioControlID, + DurationAudioControlID, + FlushMessagesAudioControlID, + TempoAudioControlID, + AudioControlIDCount +}; + +typedef Scalar AudioControlValue; + +extern const AudioControlValue MaxAudioVolume; +extern const AudioControlValue MinAudioVolume; +extern const AudioControlValue LowAudioVolumeThreshold; + +extern const AudioControlValue MaxAudioBrightness; +extern const AudioControlValue MinAudioBrightness; + +extern const AudioControlValue MaxAudioAttack; +extern const AudioControlValue MinAudioAttack; + +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AudioClippingSphere SIGNATURED +{ +public: + AudioClippingSphere(); + ~AudioClippingSphere(); + + void + SetReferenceRadius(Scalar radius); + void + SetCurrentOrigin(const Point3D &origin); + void + SetCurrentScale(Scalar scale); + Logical + Contains(const Point3D &point) const; + +private: + Scalar + referenceRadius; + Sphere + currentSphere; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~ AudioClippingSphere inlines ~~~~~~~~~~~~~~~~~~~~~~ + +inline AudioClippingSphere::AudioClippingSphere(): + referenceRadius(100.0f), + currentSphere(0.0f, 0.0f, 0.0f, 100.0f) +{ +} + +inline AudioClippingSphere::~AudioClippingSphere() +{ +} + +inline void + AudioClippingSphere::SetReferenceRadius(Scalar radius) +{ + Check(this); + referenceRadius = radius; + currentSphere.radius = radius; +} + +inline void + AudioClippingSphere::SetCurrentOrigin(const Point3D &origin) +{ + Check(this); + currentSphere.center = origin; +} + +inline void + AudioClippingSphere::SetCurrentScale(Scalar scale) +{ + Check(this); + currentSphere.radius = scale * referenceRadius; +} + +inline Logical + AudioClippingSphere::Contains(const Point3D &point) const +{ + Check(this); + return currentSphere.Contains(point); +} +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AudioSource; + +class AudioHead SIGNATURED +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioHead(); + ~AudioHead(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // Get current frame of audio simulation + //----------------------------------------------------------------------- + // + AudioFrameCount + GetAudioFrameCount() + {return audioFrameCount;} + + // + //----------------------------------------------------------------------- + // Sets the location and orientation of the head + //----------------------------------------------------------------------- + // + virtual void + LinkToEntity(Entity *entity); + Entity* + GetHeadEntity(); + + // + //----------------------------------------------------------------------- + // Get the ear to world linear matrix + //----------------------------------------------------------------------- + // + virtual LinearMatrix + GetEarToWorld(); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + virtual void + Execute(); + + // + //----------------------------------------------------------------------- + // Sets the distance between ears. Expressed in meters. + //----------------------------------------------------------------------- + // + void + SetDistanceBetweenEars(Scalar distance) + {distanceBetweenEars = distance;} + Scalar + GetDistanceBetweenEars() + {return distanceBetweenEars;} + + // + //----------------------------------------------------------------------- + // Controls Doppler effects + //----------------------------------------------------------------------- + // + void + ControlDopplerEffect( + Scalar doppler_constant, + Scalar sound_speed + ); + Scalar + GetAudioSoundSpeed() + {return audioSoundSpeed;} + AudioPitchCents + GetAudioDopplerConstant() + {return audioDopplerConstant;} + + // + //----------------------------------------------------------------------- + // Reverb scaling + //----------------------------------------------------------------------- + // + void + SetReverbToDryRatio(Scalar ratio) + {reverbToDryRatio = ratio;} + Scalar + GetReverbToDryRatio() + {return reverbToDryRatio;} + + // HACK + void + SetGlobalReverbScale(Scalar global_reverb_scale) + {globalReverbScale = global_reverb_scale;} + Scalar + GetGlobalReverbScale() + {return globalReverbScale;} + + // + //----------------------------------------------------------------------- + // Controls the attenuation of an audio source with respect to its + // distance from the head. + //----------------------------------------------------------------------- + // + void + ControlAmplitudeRollOff( + Scalar exponent, + Scalar amplitude_rolloff_knee, + Scalar distance_scale + ); + Scalar + GetAmplitudeRollOffExponent() + {return amplitudeRollOffExponent;} + Scalar + GetAmplitudeRollOffKnee() + {return amplitudeRollOffKnee;} + Scalar + GetAmplitudeRollOffDistanceScale() + {return amplitudeRollOffDistanceScale;} + + // + //----------------------------------------------------------------------- + // Controls the attenuation of the high frequencies + // of an audio source with respect to its distance from + // the head. + //----------------------------------------------------------------------- + // + void + ControlHighFrequencyRollOff( + Scalar exponent, + Scalar high_frequency_rolloff_knee, + Scalar distance_scale + ); + Scalar + GetHighFrequencyRollOffExponent() + {return highFrequencyRollOffExponent;} + Scalar + GetHighFrequencyRollOffKnee() + {return highFrequencyRollOffKnee;} + Scalar + GetHighFrequencyRollOffDistanceScale() + {return highFrequencyRollOffDistanceScale;} + + // + //----------------------------------------------------------------------- + // Controls source compression + //----------------------------------------------------------------------- + // + void + ControlSourceCompression( + Scalar exponent, + Scalar scale + ); + Scalar + GetSourceCompressionExponent() + {return sourceCompressionExponent;} + Scalar + GetSourceCompressionScale() + {return sourceCompressionScale;} + + // + //----------------------------------------------------------------------- + // Defines the audio clipping sphere + //----------------------------------------------------------------------- + // + void + DefineClippingSphere(Scalar radius); + Logical + IsPointClipped(const Point3D &point); + Scalar + GetClippingRadius() + {return clippingRadius;} + + // + //----------------------------------------------------------------------- + // ITD Difference + //----------------------------------------------------------------------- + // + void + SetITDDifference(Scalar itd_difference) + {itdDifference = itd_difference;} + Scalar + GetITDDifference() + {return itdDifference;} + + // + //----------------------------------------------------------------------- + // The SetPositionalCulling method allows the rendering process to + // not play audio locations whose positions are masked by other + // audio sources. This has found to be useful for controlling + // audio when resources are limited, but must be + // selectable globally or on a per audio effect basis. + //----------------------------------------------------------------------- + // + void + SetPositionalCulling(Logical turn_on); + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + AudioFrameCount + audioFrameCount; + SlotOf + headEntitySocket; + + Scalar + clippingRadius; + Scalar + distanceBetweenEars; + Scalar + amplitudeRollOffExponent, + amplitudeRollOffKnee, + amplitudeRollOffDistanceScale; + Scalar + highFrequencyRollOffExponent, + highFrequencyRollOffKnee, + highFrequencyRollOffDistanceScale; + Scalar + reverbToDryRatio; + Scalar + audioSoundSpeed; + Scalar + audioDopplerConstant; + Scalar + sourceCompressionExponent, + sourceCompressionScale; + Scalar + itdDifference; + Scalar + globalReverbScale; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHead inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline Entity* + AudioHead::GetHeadEntity() +{ + Check(this); + return headEntitySocket.GetCurrent(); +} + +//########################################################################## +//######################### AudioComponent ########################### +//########################################################################## + +class AudioComponent__ReceiveControlMessage; + +class AudioComponent: + public Component +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + AudioComponent( + PlugStream *stream, + SharedData &shared_data = DefaultData + ); + ~AudioComponent(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Audio Component Methods +// +public: + void + AddWatcher(Component *component); + + void + ExecuteWatchers(); + + void + Execute(); + + virtual void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + void + PostReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum { + ReceiveControlMessageID = Component::NextMessageID, + NextMessageID + }; + + typedef AudioComponent__ReceiveControlMessage + ReceiveControlMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + ReceiveControlMessageHandler( + ReceiveControlMessage *message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData + DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + AudioFrameCount + nextExecuteWatcherFrame; + ChainOf + audioWatcherSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioComponent inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + +inline void + AudioComponent::AddWatcher(Component *component) +{ + Check(component); + Check(&audioWatcherSocket); + audioWatcherSocket.Add(component); +} + +//~~~~~~~~~~~~~~~~~~ AudioComponent__ReceiveControlMessage ~~~~~~~~~~~~~~~~~ + +class AudioComponent__ReceiveControlMessage: + public Receiver::Message +{ + friend class AudioComponent; + +public: + AudioComponent__ReceiveControlMessage( + AudioControlID control_ID, + AudioControlValue control_value + ); + +private: + AudioControlID + controlID; + AudioControlValue + controlValue; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ Resource type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioRenderType *output + ) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioRenderType *input + ) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioRepresentation *output + ) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioRepresentation *input + ) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Source type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioSourceState *output + ) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioSourceState *input + ) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioSourcePriority *output + ) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioSourcePriority *input + ) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioSourceMixPresence *output + ) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioSourceMixPresence *input + ) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Control type inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + AudioControlID *output + ) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const AudioControlID *input + ) +{ + return stream->WriteBytes(input, sizeof(*input)); +} diff --git a/MUNGA/AUDLOC.cpp b/MUNGA/AUDLOC.cpp new file mode 100644 index 0000000..e028765 --- /dev/null +++ b/MUNGA/AUDLOC.cpp @@ -0,0 +1,508 @@ +#include "munga.h" +#pragma hdrstop + +#include "audloc.h" +#include "objstrm.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLocation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioLocation::AudioLocation( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + vectorToSource(0.0f, 0.0f, 0.0f), + locationOffset(0.0f, 0.0f, 0.0f) +{ + AudioFrameCount next_update_delay; + Scalar clipping_scale; + + MemoryStream_Read(stream, &locationOffset); + MemoryStream_Read(stream, &next_update_delay); + MemoryStream_Read(stream, &clipping_scale); + + AudioLocationX(entity, next_update_delay, clipping_scale); +} + +// +//############################################################################# +//############################################################################# +// +AudioLocation::~AudioLocation() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::AudioLocationX( + Entity *entity, + AudioFrameCount next_update_delay, + Scalar clipping_scale + ) +{ + Check(entity); + linkedEntity = entity; + entity->AddAudioComponent(this); + + clippingScale = clipping_scale; + isHeadSource = False; + distanceToSource = 1.0f; + dopplerCents = 0; + #if 0 + angleOffOrientation = 0.0f; + #endif + azimuthOfSource = 0.0f; + distanceVolumeScale = 1.0f; + highFreqCutoffScale = 1.0f; + #if 0 + reverbVolumeScale = 0.0f; + #endif + nextUpdateDelay = next_update_delay; + nextUpdateFrame = NullAudioFrameCount; +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLocation::TestInstance() const +{ + Component::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Point3D, location_offset); + + // + // Read update delay + // + CString update_delay_string("update_delay"); + AudioFrameCount update_delay = DefaultAudioFrameDelay; + + if (name_list->FindData(update_delay_string) != NULL) + { + Check_Pointer(name_list->FindData(update_delay_string)); + Convert_From_Ascii( + (const char *)name_list->FindData(update_delay_string), + &update_delay + ); + } + MemoryStream_Write(stream, &update_delay); + + // + // Read culling scale + // + CString clipping_scale_string("clipping_scale"); + Scalar clipping_scale = 1.0f; + + if (name_list->FindData(clipping_scale_string) != NULL) + { + Check_Pointer(name_list->FindData(clipping_scale_string)); + Convert_From_Ascii( + (const char *)name_list->FindData(clipping_scale_string), + &clipping_scale + ); + } + MemoryStream_Write(stream, &clipping_scale); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::ReceiveControl( + AudioControlID, + AudioControlValue + ) +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLocation::IsAudioLocationClipped(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + + // + // HACK - This is a rough approximation in that it does not + // take into account the offset of the location from the + // center of the entity. But, this is more efficient and is OK + // as long as the clipping sphere does not exclude the location + // unnaturally + // + Entity + *head_entity; + Vector3D + difference; + Scalar + scaled_radius; + + head_entity = audio_head->GetHeadEntity(); + Check(head_entity); + Check(linkedEntity); + difference.Subtract( + head_entity->localOrigin.linearPosition, + linkedEntity->localOrigin.linearPosition + ); + scaled_radius = audio_head->GetClippingRadius() * clippingScale; + return difference.LengthSquared() > scaled_radius * scaled_radius; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLocation::UpdateSpatialModelImplementation(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + + // + //-------------------------------------------------------------------------- + // Get head and source entity + //-------------------------------------------------------------------------- + // + Entity *source_entity = GetLinkedEntity(); + Entity *head_entity = audio_head->GetHeadEntity(); + + Check(source_entity); + Check(head_entity); + + // + //-------------------------------------------------------------------------- + // Catch case of head == source at origin + //-------------------------------------------------------------------------- + // + if ( + head_entity == source_entity && + locationOffset == Vector3D::Identity + ) + { + isHeadSource = True; + vectorToSource = Vector3D::Identity; + distanceToSource = 0.0f; + dopplerCents = 0; + #if 0 + angleOffOrientation = 0.0f; + #endif + azimuthOfSource = 0.0f; + distanceVolumeScale = 1.0f; + highFreqCutoffScale = 1.0f; + #if 0 + reverbVolumeScale = audio_head->GetReverbToDryRatio(); + #endif + return; + } + isHeadSource = False; + + // + //-------------------------------------------------------------------------- + // Get the ear to world linear matrix + //-------------------------------------------------------------------------- + // + LinearMatrix ear_to_world = audio_head->GetEarToWorld(); + + // + //-------------------------------------------------------------------------- + // Calculate vector to source with respect to local coordinate system + // of the ears + //-------------------------------------------------------------------------- + // + { + // + // Get the source location offset from the entity position in + // world coordinates + // + Vector3D world_location_offset; + Vector3D world_source_location; + + world_location_offset.Multiply( + locationOffset, + source_entity->localToWorld + ); + Check(&world_location_offset); + + world_source_location.Add( + source_entity->localOrigin.linearPosition, + world_location_offset + ); + Check(&world_source_location); + + // + // Get the vector from the ear to the source, note that the vector + // is not calculated by the ears offset but from the entities location + // + Vector3D world_ear_to_source_vector; + + world_ear_to_source_vector.Subtract( + world_source_location, + head_entity->localOrigin.linearPosition + ); + Check(&world_ear_to_source_vector); + + // + // Transform the vector into ear coordinates + // + vectorToSource.MultiplyByInverse( + world_ear_to_source_vector, + ear_to_world + ); + Check(&vectorToSource); + } + + // + //-------------------------------------------------------------------------- + // Calculate distance to source + //-------------------------------------------------------------------------- + // + distanceToSource = vectorToSource.Length(); + + // + //-------------------------------------------------------------------------- + // Calculate normal to source + //-------------------------------------------------------------------------- + // + Vector3D normal_to_source(0.0f, 0.0f, -1.0f); + + if (!Small_Enough(distanceToSource)) + { + normal_to_source.Normalize(vectorToSource); + Check(&normal_to_source); + } + + #if 0 + // + //-------------------------------------------------------------------------- + // Calculate angle between the orientation of the head and source + //-------------------------------------------------------------------------- + // + if (Small_Enough(distanceToSource)) + { + angleOffOrientation = 0.0f; + } + else + { + UnitVector direction; + Scalar cosine; + + ear_to_world.GetToAxis(Z_Axis, &direction); + Check(&direction); + + Check(&normal_to_source); + cosine = normal_to_source * direction; + Clamp(cosine, -1.0f, 1.0f); + angleOffOrientation = Arccos(cosine); + angleOffOrientation.Normalize(); + } + Verify( + angleOffOrientation <= 180.0f*RAD_PER_DEG && + angleOffOrientation >= -180.0f*RAD_PER_DEG + ); + #endif + + // + //-------------------------------------------------------------------------- + // Calculate azimuth + //-------------------------------------------------------------------------- + // + if (Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z)) + { + azimuthOfSource = 0.0f; + } + else + { + Verify(!(Small_Enough(vectorToSource.x) && Small_Enough(vectorToSource.z))); + azimuthOfSource = Arctan(vectorToSource.x, vectorToSource.z); + } + Verify( + azimuthOfSource <= 180.0f*RAD_PER_DEG && + azimuthOfSource >= -180.0f*RAD_PER_DEG + ); + + // + //-------------------------------------------------------------------------- + // Calculate distance volume scaling + // Apply clipping scale to rolloff distance scale, thereby giving this + // audio location a specifc rolloff characteristic + //-------------------------------------------------------------------------- + // + if (distanceToSource > audio_head->GetAmplitudeRollOffKnee()) + { + // + // y = 1 / 1 + (K(x - knee))^exp + // + Verify(!Small_Enough(clippingScale)); + const Scalar temp = + (audio_head->GetAmplitudeRollOffDistanceScale() / clippingScale) * + (distanceToSource - audio_head->GetAmplitudeRollOffKnee()); + const Scalar temp2 = + 1.0f + pow(temp, audio_head->GetAmplitudeRollOffExponent()); + + Verify(!Small_Enough(temp2)); + distanceVolumeScale = 1.0f / temp2; + } + else + { + distanceVolumeScale = 1.0f; + } + Verify(distanceVolumeScale >= 0.0f && distanceVolumeScale <= 1.0f); + + // + //-------------------------------------------------------------------------- + // Calculate high frequency cutoff scaling + // Apply clipping scale to high frequency rolloff distance scale, thereby + // giving this audio location a specifc rolloff characteristic + //-------------------------------------------------------------------------- + // + if (distanceToSource > audio_head->GetHighFrequencyRollOffKnee()) + { + // + // y = 1 / 1 + (K(x - knee))^exp + // + Verify(!Small_Enough(clippingScale)); + const Scalar temp = + (audio_head->GetHighFrequencyRollOffDistanceScale() / clippingScale) * + (distanceToSource - audio_head->GetHighFrequencyRollOffKnee()); + const Scalar temp2 = + 1.0f + pow(temp, audio_head->GetHighFrequencyRollOffExponent()); + + Verify(!Small_Enough(temp2)); + highFreqCutoffScale = 1.0f / temp2; + } + else + { + highFreqCutoffScale = 1.0f; + } + Verify(highFreqCutoffScale >= 0.0f && highFreqCutoffScale <= 1.0f); + + #if 0 + // + //-------------------------------------------------------------------------- + // Calculate reverb volume scaling + //-------------------------------------------------------------------------- + // + if (distanceToSource > audio_head->GetAmplitudeRollOffKnee()) + { + const Scalar temp = + distanceToSource - audio_head->GetAmplitudeRollOffKnee() + 1.0f; + + reverbVolumeScale = + audio_head->GetReverbToDryRatio() * + pow(temp, audio_head->GetAmplitudeRollOffExponent()); + if (reverbVolumeScale > 1.0f) + reverbVolumeScale = 1.0f; + } + else + { + reverbVolumeScale = audio_head->GetReverbToDryRatio(); + } + Verify(reverbVolumeScale >= 0.0f && reverbVolumeScale <= 1.0f); + #endif + + // + //-------------------------------------------------------------------------- + // Calculate relative velocity of source + //-------------------------------------------------------------------------- + // + Vector3D relative_velocity_temp; + Vector3D relative_velocity; + + relative_velocity_temp.Subtract( + source_entity->GetWorldLinearVelocity(), + head_entity->GetWorldLinearVelocity() + ); + Check(&relative_velocity_temp); + + relative_velocity.MultiplyByInverse( + relative_velocity_temp, + head_entity->localToWorld + ); + Check(&relative_velocity); + + // + //-------------------------------------------------------------------------- + // Calculate doppler shift in cents + // cents = (c / (c - v)) / ScaleRatio + //-------------------------------------------------------------------------- + // + if (!Small_Enough(distanceToSource)) + { + AudioPitchCents + cents; + Scalar speed_of_source = + normal_to_source * relative_velocity; + const Scalar ear_radius = + audio_head->GetDistanceBetweenEars() * 0.5f; + + if (distanceToSource < ear_radius) + { + Verify(!Small_Enough(ear_radius)); + speed_of_source *= (distanceToSource / ear_radius); + } + + if (CalculateDoppler(audio_head, speed_of_source, ¢s)) + { + dopplerCents = cents; + } + } + else + { + dopplerCents = 0; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLocation::CalculateDoppler( + AudioHead *audio_head, + Scalar speed, + AudioPitchCents *result + ) +{ + Check(this); + Check(audio_head); + Check_Pointer(result); + + Scalar speed_of_sound = audio_head->GetAudioSoundSpeed(); + + Clamp(speed, -speed_of_sound, speed_of_sound); + if (!Small_Enough(speed_of_sound - speed)) + { + *result = audio_head->GetAudioDopplerConstant() * + ( 1 - speed_of_sound / (speed_of_sound - speed) ); + return True; + } + return False; +} diff --git a/MUNGA/AUDLOC.h b/MUNGA/AUDLOC.h new file mode 100644 index 0000000..da717e6 --- /dev/null +++ b/MUNGA/AUDLOC.h @@ -0,0 +1,202 @@ +#pragma once + +#include "style.h" +#include "audio.h" + +//########################################################################## +//######################## AudioLocation ############################# +//########################################################################## + +class AudioLocation: + public AudioComponent +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + AudioLocation( + PlugStream *stream, + Entity *entity + ); + void + AudioLocationX( + Entity *entity, + AudioFrameCount next_update_delay, + Scalar clipping_scale + ); + ~AudioLocation(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Resource Building +// +public: +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Audio Component Support +// +public: + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Audio Location Support +// +public: + // + //----------------------------------------------------------------------- + // GetLinkedEntity + //----------------------------------------------------------------------- + // + Entity* + GetLinkedEntity(); + + // + //----------------------------------------------------------------------- + // IsAudioLocationClipped + //----------------------------------------------------------------------- + // + Logical + IsAudioLocationClipped(AudioHead *audio_head); + + // + //----------------------------------------------------------------------- + // UpdateSpatialModel + //----------------------------------------------------------------------- + // + void + UpdateSpatialModel(AudioHead *audio_head); + + // + //----------------------------------------------------------------------- + // Access to localization results + //----------------------------------------------------------------------- + // + Logical + IsHeadSource() + {return isHeadSource;} + Scalar + GetDistanceToSource() + {return distanceToSource;} + Scalar + GetDistanceToSourceListenerPlane(); + Radian + GetAzimuthOfSource() + {return azimuthOfSource;} + Scalar + GetDistanceVolumeScale() + {return distanceVolumeScale;} + Scalar + GetHighFreqCutoffScale() + {return highFreqCutoffScale;} + AudioPitchCents + GetDopplerCents() + {return dopplerCents;} + + Scalar getMaxDistance(AudioHead *audio_head) {return audio_head->GetClippingRadius() * clippingScale;} + Vector3D GetVectorToSource() { return this->vectorToSource; } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected Implementations +// +protected: + virtual void + UpdateSpatialModelImplementation(AudioHead *audio_head); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Methods +// +private: + Logical + CalculateDoppler( + AudioHead *audio_head, + Scalar speed, + AudioPitchCents *result + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + Entity + *linkedEntity; + + Point3D + locationOffset; + Scalar + clippingScale; + + Logical + isHeadSource; + Vector3D + vectorToSource; + Scalar + distanceToSource; + #if 0 + Radian + angleOffOrientation; + #endif + Radian + azimuthOfSource; + Scalar + distanceVolumeScale; + Scalar + highFreqCutoffScale; + #if 0 + Scalar + reverbVolumeScale; + #endif + AudioPitchCents + dopplerCents; + + AudioFrameCount + nextUpdateDelay; + AudioFrameCount + nextUpdateFrame; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLocation inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + +inline Entity* + AudioLocation::GetLinkedEntity() +{ + Check(this); + return linkedEntity; +} + +inline Scalar + AudioLocation::GetDistanceToSourceListenerPlane() +{ + Check(this); + Vector3D + vector_to_source_listener_plane( + vectorToSource.x, + 0.0f, + vectorToSource.z + ); + return vector_to_source_listener_plane.Length(); +} + +inline void + AudioLocation::UpdateSpatialModel(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + if (nextUpdateFrame <= audio_head->GetAudioFrameCount()) + { + nextUpdateFrame = audio_head->GetAudioFrameCount() + nextUpdateDelay; + UpdateSpatialModelImplementation(audio_head); + } +} diff --git a/MUNGA/AUDLVL.cpp b/MUNGA/AUDLVL.cpp new file mode 100644 index 0000000..7cbef6a --- /dev/null +++ b/MUNGA/AUDLVL.cpp @@ -0,0 +1,450 @@ +#include "munga.h" +#pragma hdrstop + +#include "audlvl.h" +#include "objstrm.h" +#include "namelist.h" +#include "app.h" +#include "audrend.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioLevelOfDetail::AudioLevelOfDetail(PlugStream *stream): + Plug(stream) +{ + #if 0 + amplitudeRadiationProfile = 0.0f; + filterRadiationProfile = 0.0f; + #endif + + // + // Read fields + // + MemoryStream_Read(stream, &voiceCount); + MemoryStream_Read(stream, &audioRenderType); + + // + // Read suspend seconds and calculate suspendDelay + // + Scalar + suspend_delay_seconds; + + MemoryStream_Read(stream, &suspend_delay_seconds); + Check(application); + Check(application->GetAudioRenderer()); + suspendDelay = suspend_delay_seconds * + application->GetAudioRenderer()->GetCalibrationRate() + 0.5f; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLevelOfDetail::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Plug::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioVoiceCount, voice_count); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, render_type); + + // + // Store suspend delay + // + CString suspend_delay_string("suspend_delay"); + Scalar suspend_delay_seconds = 0.33f; // HACK - should come from somewhere else + + if (name_list->FindData(suspend_delay_string) != NULL) + { + Check_Pointer(name_list->FindData(suspend_delay_string)); + Convert_From_Ascii( + (const char *)name_list->FindData(suspend_delay_string), + &suspend_delay_seconds + ); + } + MemoryStream_Write(stream, &suspend_delay_seconds); +} + +// +//############################################################################# +//############################################################################# +// +AudioLevelOfDetail::~AudioLevelOfDetail() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioLevelOfDetail::TestInstance() const +{ + Plug::TestInstance(); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioResource::AudioResource(PlugStream *stream): + Node(stream), + audioLevelOfDetailSocket(NULL, True) +{ + // + // Read the table + // + CollectionSize i, number_of_entries; + + MemoryStream_Read(stream, &number_of_entries); + for (i = 0; i < number_of_entries; i++) + { + Scalar distance; + AudioLevelOfDetail *audio_level_of_detail; + + MemoryStream_Read(stream, &distance); + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_level_of_detail); + Check(audio_level_of_detail); + audioLevelOfDetailSocket.AddValue(audio_level_of_detail, distance); + } + + // + // Verify that there is at least one entry and the first one is at 0.0f + // + #if DEBUG_LEVEL>0 + { + TableIteratorOf iterator(&audioLevelOfDetailSocket); + Check(&iterator); + Verify(iterator.GetSize() > 0); + Verify(iterator.GetCurrent() != NULL); + Verify(iterator.GetValue() == 0.0f); + } + #endif + + // + // Select the first entry + // + TableIteratorOf iterator(&audioLevelOfDetailSocket); + + audioLevelOfDetail = iterator.GetCurrent(); + Check(audioLevelOfDetail); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Node::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Count number of entries + // + int number_of_entries = 0; + NameList::Entry *entry; + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_level_of_detail")) + number_of_entries++; + entry = entry->GetNextEntry(); + } + + // + // Store entries + // + MemoryStream_Write(stream, &number_of_entries); + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_level_of_detail")) + { + CString object_string; + Scalar distance; + ObjectID object_ID; + + Check_Pointer(entry->GetChar()); + object_string = entry->GetChar(); + + Check_Pointer(object_string.GetNthToken(0)); + Convert_From_Ascii(object_string.GetNthToken(0), &distance); + MemoryStream_Write(stream, &distance); + + Check(stream); + Check_Pointer(object_string.GetNthToken(1)); + object_ID = stream->FindObjectID(object_string.GetNthToken(1)); + Verify(object_ID != NullObjectID); + MemoryStream_Write(stream, &object_ID); + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +//############################################################################# +// +AudioResource::~AudioResource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioResource::TestInstance() const +{ + Node::TestInstance(); + Check(&audioLevelOfDetailSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResource::SetDistance(Scalar distance) +{ + Check(this); + Verify(distance >= 0.0f); + + // + // Goto the last entry + // + TableIteratorOf + iterator(&audioLevelOfDetailSocket); + + Check(&iterator); + iterator.Last(); + + // + // While the distance is less than the distance of the entry + // + while (distance < iterator.GetValue()) + { + iterator.Previous(); + } + audioLevelOfDetail = iterator.GetCurrent(); + Check(audioLevelOfDetail); + + // + // Verify that the distance is greater than this entry, and less than + // the next + // + #if DEBUG_LEVEL>0 + Verify(distance >= iterator.GetValue()); + iterator.Next(); + if (iterator.GetCurrent() != NULL) + { + Verify(distance < iterator.GetValue()); + } + #endif + + // + // Dump the LOD of the resource + // + #if 0 + CollectionSize i = 0; + iterator.First(); + while (iterator.GetCurrent() != NULL) + { + Check(iterator.GetCurrent()); + if (audioLevelOfDetail == iterator.GetCurrent() /* && i > 0 */ ) + { + Tell( + "AudioLOD:" << i << + " d:" << distance << + " t:" << iterator.GetValue() << + "\n" + ); + break; + } + iterator.Next(); + i++; + } + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResourceIndex ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioResourceIndex::AudioResourceIndex(PlugStream *stream): + Node(stream), + audioResourceSocket(NULL, True) +{ + CollectionSize i, number_of_entries; + + MemoryStream_Read(stream, &number_of_entries); + for (i = 0; i < number_of_entries; i++) + { + AudioResource *audio_resource; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource); + Check(audio_resource); + AddAudioResource(audio_resource, i); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResourceIndex::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Node::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Count number of entries + // + int number_of_entries = 0; + NameList::Entry *entry; + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_resource")) + number_of_entries++; + entry = entry->GetNextEntry(); + } + + // + // Store entries + // + MemoryStream_Write(stream, &number_of_entries); + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("audio_resource")) + { + CString object_name; + ObjectID object_ID; + + Check_Pointer(entry->GetChar()); + object_name = entry->GetChar(); + + Check(stream); + object_ID = stream->FindObjectID(object_name); + Verify(object_ID != NullObjectID); + MemoryStream_Write(stream, &object_ID); + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +//############################################################################# +// +AudioResourceIndex::~AudioResourceIndex() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioResourceIndex::TestInstance() const +{ + Node::TestInstance(); + Check(&audioResourceSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioResourceIndex::AddAudioResource( + AudioResource *audio_resource, + Enumeration index + ) +{ + Check(this); + audioResourceSocket.AddValue(audio_resource, index); + + #if DEBUG_LEVEL>0 + TableIteratorOf iterator(&audioResourceSocket); + Check(&iterator); + for (int i = 0; i < iterator.GetSize(); i++) + { + Verify(iterator.GetNth(i) == audioResourceSocket.Find(i)); + } + #endif +} + +// +//############################################################################# +//############################################################################# +// +AudioResource* + AudioResourceIndex::GetAudioResource(Enumeration index) +{ + Check(this); + + TableIteratorOf iterator(&audioResourceSocket); + Check(&iterator); + Verify(iterator.GetNth(index) == audioResourceSocket.Find(index)); + + return iterator.GetNth(index); +} + +// +//############################################################################# +//############################################################################# +// +CollectionSize + AudioResourceIndex::GetSize() +{ + Check(this); + + TableIteratorOf iterator(&audioResourceSocket); + Check(&iterator); + + return iterator.GetSize(); +} diff --git a/MUNGA/AUDLVL.h b/MUNGA/AUDLVL.h new file mode 100644 index 0000000..8312df0 --- /dev/null +++ b/MUNGA/AUDLVL.h @@ -0,0 +1,247 @@ +#pragma once + +#include "style.h" +#include "audio.h" + +//########################################################################## +//####################### AudioLevelOfDetail ######################### +//########################################################################## + +class AudioLevelOfDetail: + public Plug +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioLevelOfDetail(PlugStream *stream); + ~AudioLevelOfDetail(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + virtual AudioVoiceCount + GetVoiceCount() + {return voiceCount;} + AudioRenderType + GetAudioRenderType() + {return audioRenderType;} + AudioFrameCount + GetSuspendDelay() + {return suspendDelay;} + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + + #if 0 + // + //----------------------------------------------------------------------- + // Defines the radial variation of the amplitude of the audio source. + // This feature is implemented well in Crystal River Engineering's + // API. The radiation profile of an audio source is specified with + // an array of sound levels in decibels paired with angles off of + // the audio source orientation. For example, you can design a + // rocket sound that is louder when heard from directly behind then + // from the side. + //----------------------------------------------------------------------- + // + AudioRadiationProfile + amplitudeRadiationProfile; + #endif + + #if 0 + // + //----------------------------------------------------------------------- + // Defines the radial variation of the high frequency content of the + // audio source. This concept is analogous to + // SetAmplitudeRadiationProfile except applied to the high frequency + // content of the audio source. Again, this allows the audio source + // to vary with respect to the position and orientation of the audio + // source and head. + //----------------------------------------------------------------------- + // + AudioRadiationProfile + filterRadiationProfile; + #endif + + // + //----------------------------------------------------------------------- + // Misc + //----------------------------------------------------------------------- + // + AudioVoiceCount + voiceCount; + AudioRenderType + audioRenderType; + AudioFrameCount + suspendDelay; +}; + +//########################################################################## +//########################## AudioResource ############################ +//########################################################################## + +class AudioResource: + public Node +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + AudioResource(PlugStream *stream); + ~AudioResource(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // SetDistance + //----------------------------------------------------------------------- + // + void + SetDistance(Scalar distance); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + AudioVoiceCount + GetVoiceCount(); + AudioRenderType + GetAudioRenderType(); + AudioFrameCount + GetSuspendDelay(); + +protected: + // + //----------------------------------------------------------------------- + // Protected data + //----------------------------------------------------------------------- + // + AudioLevelOfDetail* + GetAudioLevelOfDetail(); + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + AudioLevelOfDetail + *audioLevelOfDetail; + TableOf + audioLevelOfDetailSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioResource inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline AudioLevelOfDetail* + AudioResource::GetAudioLevelOfDetail() +{ + Check(this); + return audioLevelOfDetail; +} + +inline AudioVoiceCount + AudioResource::GetVoiceCount() +{ + Check(this); + Check(audioLevelOfDetail); + return audioLevelOfDetail->GetVoiceCount(); +} + +inline AudioRenderType + AudioResource::GetAudioRenderType() +{ + Check(this); + Check(audioLevelOfDetail); + return audioLevelOfDetail->GetAudioRenderType(); +} + +inline AudioFrameCount + AudioResource::GetSuspendDelay() +{ + Check(this); + Check(audioLevelOfDetail); + return audioLevelOfDetail->GetSuspendDelay(); +} + +//########################################################################## +//######################## AudioResourceIndex ######################## +//########################################################################## + +class AudioResourceIndex: + public Node +{ +public: + AudioResourceIndex(PlugStream *stream); + ~AudioResourceIndex(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + void + AddAudioResource( + AudioResource *audio_resource, + Enumeration index + ); + + AudioResource* + GetAudioResource(Enumeration index); + + CollectionSize + GetSize(); + +private: + TableOf + audioResourceSocket; +}; diff --git a/MUNGA/AUDMIDI.cpp b/MUNGA/AUDMIDI.cpp new file mode 100644 index 0000000..b7ceecb --- /dev/null +++ b/MUNGA/AUDMIDI.cpp @@ -0,0 +1,690 @@ +#include "munga.h" +#pragma hdrstop + +#include "audmidi.h" + +//############################################################################# +//########################### MidiParse ################################# +//############################################################################# + +#define NOTEOFF (0x80) +#define NOTEON (0x90) +#define PRESSURE (0xa0) +#define CONTROLLER (0xb0) +#define PITCHBEND (0xe0) +#define PROGRAM (0xc0) +#define CHANPRESSURE (0xd0) + +#define METATEXT "Text Event" +#define METACOPYRIGHT "Copyright Notice" +#define METASEQUENCE "Sequence/Track Name" +#define METAINSTRUMENT "Instrument Name" +#define METALYRIC "Lyric" +#define METAMARKER "Marker" +#define METACUE "Cue Point" +#define METAUNRECOGNIZED "Unrecognized" + +#define CHAR_BUFF_SIZE (32) + +// +//############################################################################# +//############################################################################# +// +MidiParse::MidiParse() +{ + Mf_nomerge = 0; // 1 => continue'ed system exclusives are not collapsed. + Mf_currtime = 0L; // current time in delta-time units + Mf_skipinit = 0; // 1 if initial garbage should be skipped + + Mf_toberead = 0L; + + Msgbuff = NULL; // message buffer + Msgsize = 0; // Size of currently allocated Msg + Msgindex = 0; // index of next available location in Msg +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::~MidiParse() +{ + if (Msgbuff != NULL) + { + Unregister_Pointer(Msgbuff); +#if 0 + free(Msgbuff); +#else + delete[] Msgbuff; +#endif + Msgbuff = NULL; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + MidiParse::TestInstance() const +{ + Node::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::CurTime() +{ + Check(this); + return Mf_currtime; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::Parse() +{ + Check(this); + + SignedWord ntrks; + + ntrks = readheader(); + Verify(ntrks > 0); + while (ntrks-- > 0) + readtrack(); +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::readmt( + char *s, + SignedWord skip + ) +{ + Check(this); + + SignedWord nread = 0; + char b[4]; + char buff[CHAR_BUFF_SIZE]; + SignedWord c; + char *errmsg = "expecting "; + + // read through the "MThd" or "MTrk" header string + // if 1, we attempt to skip initial garbage. + +retry: + while ( nread<4 ) + { + c = Mf_getc(); + if ( c == EOF ) + { + errmsg = "EOF while expecting "; + goto err; + } + b[nread++] = (char)c; + } + + // See if we found the 4 characters we're looking for + + if ( s[0]==b[0] && s[1]==b[1] && s[2]==b[2] && s[3]==b[3] ) + return 0; + if ( skip ) + { + + // If we are supposed to skip initial garbage, + // try again with the next character. + + b[0]=b[1]; + b[1]=b[2]; + b[2]=b[3]; + nread = 3; + goto retry; + } +err: + Str_Copy(buff, errmsg, CHAR_BUFF_SIZE); + Str_Cat(buff, s, CHAR_BUFF_SIZE); + mferror(buff); + return 0; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::egetc() +{ + Check(this); + + // read a single character and abort on EOF + + SignedWord c = Mf_getc(); + + if ( c == EOF ) + mferror("premature EOF"); + Mf_toberead--; + return c; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::readheader() +{ + Check(this); + + // read a header chunk + + SignedWord + format, ntrks, division; + + if ( readmt("MThd", Mf_skipinit) == EOF ) + return 0; + + Mf_toberead = read32bit(); + format = read16bit(); + ntrks = read16bit(); + division = read16bit(); + + Mf_header(format,ntrks,division); + + // flush any extra stuff, in case the length of header is not 6 + + while ( Mf_toberead > 0 ) + egetc(); + return ntrks; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::readtrack() +{ + Check(this); + + // read a track chunk + + // This array is indexed by the high half of a status byte. It's + // value is either the number of bytes needed (1 or 2) for a channel + // message, or 0 (meaning it's not a channel message). + + static SignedWord chantype[] = + { + 0, 0, 0, 0, 0, 0, 0, 0, // 0x00 through 0x70 + 2, 2, 2, 2, 1, 1, 2, 0 // 0x80 through 0xf0 + }; + + SignedLongWord lookfor, lng; + SignedWord c, c1, type; + SignedWord sysexcontinue = 0; // 1 if last message was an unfinished sysex + SignedWord running; // 1 when running status used + SignedWord status = 0; // (possibly running) status byte + SignedWord needed; + + if ( readmt("MTrk",0) == EOF ) + return; + + Mf_toberead = read32bit(); + Mf_currtime = 0; + + Mf_starttrack(); + + while ( Mf_toberead > 0 ) + { + Mf_currtime += readvarinum(); // delta time + + c = egetc(); + + if ( sysexcontinue && c != 0xf7 ) + mferror("didn't find expected continuation of a sysex"); + + if ( (c & 0x80) == 0 ) // running status? + { + if ( status == 0 ) + mferror("unexpected running status"); + running = 1; + } + else + { + status = c; + running = 0; + } + + needed = chantype[ (status>>4) & 0xf ]; + + if ( needed ) // ie. is it a channel message? + { + if ( running ) + c1 = c; + else + c1 = egetc(); + chanmessage( status, c1, (needed>1) ? egetc() : (SignedWord)0 ); + continue; + } + + switch ( c ) + { + case 0xff: // meta event + type = egetc(); + // watch out - Don't combine the next 2 statements + lng = readvarinum(); + lookfor = Mf_toberead - lng; + msginit(); + + while ( Mf_toberead > lookfor ) + msgadd(egetc()); + + metaevent(type); + break; + + case 0xf0: // start of system exclusive + // watch out - Don't combine the next 2 statements + lng = readvarinum(); + lookfor = Mf_toberead - lng; + msginit(); + msgadd(0xf0); + + while ( Mf_toberead > lookfor ) + msgadd(c=egetc()); + + if ( c==0xf7 || Mf_nomerge==0 ) + sysex(); + else + sysexcontinue = 1; // merge into next msg + break; + + case 0xf7: // sysex continuation or arbitrary stuff + // watch out - Don't combine the next 2 statements + lng = readvarinum(); + lookfor = Mf_toberead - lng; + + if ( ! sysexcontinue ) + msginit(); + + while ( Mf_toberead > lookfor ) + msgadd(c=egetc()); + + if ( ! sysexcontinue ) + { + Mf_arbitrary(msgleng(),msg()); + } + else if ( c == 0xf7 ) + { + sysex(); + sysexcontinue = 0; + } + break; + + default: + badbyte(c); + break; + } + } + Mf_endtrack(); + return; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::badbyte(SignedWord c) +{ + Check(this); + + char buff[CHAR_BUFF_SIZE]; + + sprintf(buff,"unexpected byte: 0x%02x",c); + mferror(buff); +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::metaevent(SignedWord type) +{ + Check(this); + + SignedWord leng = msgleng(); + char *m = msg(); + + switch ( type ) + { + case 0x00: + Mf_seqnum(to16bit(m[0],m[1])); + break; + case 0x01: // Text event + case 0x02: // Copyright notice + case 0x03: // Sequence/Track name + case 0x04: // Instrument name + case 0x05: // Lyric + case 0x06: // Marker + case 0x07: // Cue point + case 0x08: + case 0x09: + case 0x0a: + case 0x0b: + case 0x0c: + case 0x0d: + case 0x0e: + case 0x0f: + // These are all text events + Mf_text(type,leng,m); + break; + case 0x2f: // End of Track + Mf_eot(); + break; + case 0x51: // Set tempo + Mf_tempo(to32bit((SignedWord)0,m[0],m[1],m[2])); + break; + case 0x54: + Mf_smpte(m[0],m[1],m[2],m[3],m[4]); + break; + case 0x58: + Mf_timesig(m[0],m[1],m[2],m[3]); + break; + case 0x59: + Mf_keysig(m[0],m[1]); + break; + case 0x7f: + Mf_sqspecific(leng,m); + break; + default: + Mf_metamisc(type,leng,m); + } +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::sysex() +{ + Check(this); + Mf_sysex(msgleng(),msg()); +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::chanmessage( + SignedWord status, + SignedWord c1, + SignedWord c2 + ) +{ + Check(this); + + SignedWord chan = status & (SignedWord)0xf; + + switch ( status & 0xf0 ) + { + case NOTEOFF: + Mf_off(chan,c1,c2); + break; + case NOTEON: + Mf_on(chan,c1,c2); + break; + case PRESSURE: + Mf_pressure(chan,c1,c2); + break; + case CONTROLLER: + Mf_controller(chan,c1,c2); + break; + case PITCHBEND: + Mf_pitchbend(chan,c1,c2); + break; + case PROGRAM: + Mf_program(chan,c1); + break; + case CHANPRESSURE: + Mf_chanpressure(chan,c1); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::readvarinum() +{ + Check(this); + + // readvarinum - read a varying-length number, and return the + // number of characters it took. + + SignedLongWord value; + SignedWord c; + + c = egetc(); + value = c; + if (c & 0x80) + { + value &= 0x7f; + do + { + c = egetc(); + value <<= 7; + value += (c & 0x7f); + } while (c & 0x80); + } + return value; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::to32bit(SignedWord c1, SignedWord c2,SignedWord c3, SignedWord c4) +{ + Check(this); + + SignedLongWord value; + + value = (c1 & 0xff); + value = (value<<8) + (c2 & 0xff); + value = (value<<8) + (c3 & 0xff); + value = (value<<8) + (c4 & 0xff); + return value; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::to16bit(SignedWord c1,SignedWord c2) +{ + Check(this); + + SignedWord value; + + value = (c1 & (SignedWord)0xff); + value = (SignedWord)((SignedWord)(value<<8) + (c2 & (SignedWord)0xff)); + return value; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedLongWord + MidiParse::read32bit() +{ + Check(this); + + SignedWord c1, c2, c3, c4; + + c1 = egetc(); + c2 = egetc(); + c3 = egetc(); + c4 = egetc(); + return to32bit(c1,c2,c3,c4); +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::read16bit() +{ + Check(this); + + SignedWord c1, c2; + + c1 = egetc(); + c2 = egetc(); + return to16bit(c1,c2); +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::mferror(char *s) +{ + Check(this); + Mf_error(s); +} + +// The code below allows collection of a system exclusive message of +// arbitrary length. The Msgbuff is expanded as necessary. The only +// visible data/routines are msginit(), msgadd(), msg(), msgleng(). + +#define MSGINCREMENT ((SignedWord)128) + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::msginit() +{ + Check(this); + Msgindex = 0; +} + +// +//############################################################################# +//############################################################################# +// +char* + MidiParse::msg() +{ + Check(this); + return Msgbuff; +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::msgleng() +{ + Check(this); + return Msgindex; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::msgadd(SignedWord c) +{ + Check(this); + + // If necessary, allocate larger message buffer. + + if ( Msgindex >= Msgsize ) + msgenlarge(); + Msgbuff[Msgindex++] = (char)c; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::msgenlarge() +{ + Check(this); + + char *newmess; + char *oldmess = Msgbuff; + SignedWord oldleng = Msgsize; + + Msgsize += MSGINCREMENT; +#if 0 + newmess = (char*)malloc( sizeof(char)*Msgsize ); +#else + newmess = new char[Msgsize]; +#endif + Register_Pointer(newmess); + + // copy old message into larger new one + if ( oldmess != 0 ) + { + char *p = newmess; + char *q = oldmess; + char *endq = &oldmess[oldleng]; + + for ( ; q!=endq ; p++,q++ ) + *p = *q; + Unregister_Pointer(oldmess); +#if 0 + free(oldmess); +#else + delete[] oldmess; +#endif + } + Msgbuff = newmess; +} + +// METHODS TO OVERRIDE + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + MidiParse::Mf_getc() +{ + Fail("MidiParse::Mf_getc - Should never reach here"); + return 0; +} + +// +//############################################################################# +//############################################################################# +// +void + MidiParse::Mf_error(char*) +{ + Fail("MidiParse::Mf_error - Should never reach here"); +} diff --git a/MUNGA/AUDMIDI.h b/MUNGA/AUDMIDI.h new file mode 100644 index 0000000..8091105 --- /dev/null +++ b/MUNGA/AUDMIDI.h @@ -0,0 +1,147 @@ +#pragma once + +#include "node.h" + +//########################################################################## +//########################## MidiParse ############################### +//########################################################################## + +class MidiParse: + public Node +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + typedef long SignedLongWord; // 4 bytes + typedef short int SignedWord; // 2 bytes + typedef char SignedByte; // 1 bytes + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + MidiParse(); + ~MidiParse(); + Logical + TestInstance() const; + + void + Parse(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +protected: + SignedLongWord + CurTime(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Sub-class callbacks +// +private: + virtual SignedWord + Mf_getc(); + virtual void + Mf_error(char *); + + virtual void + Mf_starttrack() {} + virtual void + Mf_endtrack() {} + virtual void + Mf_eot() {} + virtual void + Mf_header(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_on(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_off(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_pressure(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_controller(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_pitchbend(SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_program(SignedWord,SignedWord) {} + virtual void + Mf_chanpressure(SignedWord,SignedWord) {} + virtual void + Mf_sysex(SignedWord,char*) {} + virtual void + Mf_arbitrary(SignedWord,char*) {} + virtual void + Mf_metamisc(SignedWord,SignedWord,char*) {} + virtual void + Mf_seqnum(SignedWord) {} + virtual void + Mf_smpte(SignedWord,SignedWord,SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_timesig(SignedWord,SignedWord,SignedWord,SignedWord) {} + virtual void + Mf_tempo(SignedLongWord) {} + virtual void + Mf_keysig(SignedWord,SignedWord) {} + virtual void + Mf_sqspecific(SignedWord,char*) {} + virtual void + Mf_text(SignedWord,SignedWord,char*) {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + SignedWord + readmt(char *s,SignedWord skip); + SignedWord + egetc(); + SignedWord + readheader(); + void + readtrack(); + void + badbyte(SignedWord c); + void + metaevent(SignedWord type); + void + sysex(); + void + chanmessage(SignedWord status,SignedWord c1,SignedWord c2); + SignedLongWord + readvarinum(); + SignedLongWord + to32bit(SignedWord c1, SignedWord c2,SignedWord c3, SignedWord c4); + SignedWord + to16bit(SignedWord c1,SignedWord c2); + SignedLongWord + read32bit(); + SignedWord + read16bit(); + void + mferror(char *s); + void + msginit(); + char* + msg(); + SignedWord + msgleng(); + void + msgadd(SignedWord c); + void + msgenlarge(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + SignedWord Mf_nomerge; + SignedLongWord Mf_currtime; + SignedWord Mf_skipinit; + + SignedLongWord Mf_toberead; + + char *Msgbuff; + SignedWord Msgsize; + SignedWord Msgindex; +}; diff --git a/MUNGA/AUDREND.cpp b/MUNGA/AUDREND.cpp new file mode 100644 index 0000000..2a2420f --- /dev/null +++ b/MUNGA/AUDREND.cpp @@ -0,0 +1,513 @@ +#include "munga.h" +#pragma hdrstop + +#include "audrend.h" +#include "audent.h" +#include "jmover.h" +#include "app.h" + +//############################################################################# +//########################### AudioRenderer ############################# +//############################################################################# + +// +//############################################################################# +// AudioRenderer +//############################################################################# +// +AudioRenderer::AudioRenderer(RendererRate render_rate): + Renderer( + render_rate, + MaxRendererComplexity, + DefaultRendererPriority, + AudioInterestType, + DefaultInterestDepth, + AudioRendererClassID + ), + audioEventSocket(NULL, False) +{ + audioHead = NULL; + + #ifdef LAB_ONLY + sourceClippedCount = 0; + sourceStartCount = 0; + sourceSuspendCount = 0; + sourceResumeCount = 0; + doubleTriggerCount = 0; + resourceStealCount = 0; + resourceStealPriorityCount = 0; + resourceStealVolumeCount = 0; + stealShortDurationCount = 0; + #endif +} + +// +//############################################################################# +// ~AudioRenderer +//############################################################################# +// +AudioRenderer::~AudioRenderer() +{ + Unregister_Object(audioHead); + delete audioHead; + + #ifdef LAB_ONLY + cout << "AudioRenderer::~AudioRenderer - sourceClippedCount=" + << sourceClippedCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - sourceStartCount=" + << sourceStartCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - sourceSuspendCount=" + << sourceSuspendCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - sourceResumeCount=" + << sourceResumeCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - doubleTriggerCount=" + << doubleTriggerCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - resourceStealCount=" + << resourceStealCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - resourceStealPriorityCount=" + << resourceStealPriorityCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - resourceStealVolumeCount=" + << resourceStealVolumeCount << "\n"; + cout << "AudioRenderer::~AudioRenderer - stealShortDurationCount=" + << stealShortDurationCount << "\n"; + #endif +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + AudioRenderer::Initialize() +{ + audioHead = MakeAudioHead(); + Register_Object(audioHead); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioRenderer::TestInstance() const +{ + Renderer::TestInstance(); + if (audioHead != NULL) + { + Check(audioHead); + } + Check(&audioEventSocket); + return True; +} + +// +//############################################################################# +// LinkToEntity +//############################################################################# +// +void + AudioRenderer::LinkToEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + //-------------------------------------------------------------------------- + // Link the head to the entity + //-------------------------------------------------------------------------- + // + Check(audioHead); + audioHead->LinkToEntity(entity); + + // + //-------------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------------- + // + Renderer::LinkToEntity(entity); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +void + AudioRenderer::ExecuteImplementation( + RendererComplexity, + RendererOrigin::InterestingEntityIterator* + ) +{ + Check(this); + Check(audioHead); + audioHead->Execute(); +} + +// +//############################################################################# +// PostAudioRequestMessage +//############################################################################# +// +void + AudioRenderer::PostAudioRequestMessage( + AudioSource *audio_source, + AudioSource::RequestMessage *message + ) +{ + Check(this); + Check(audio_source); + Check(message); + + // + //-------------------------------------------------------------------------- + // If audio source is clipped and the source is transient + // Then ignore + // Else set priority and volume + //-------------------------------------------------------------------------- + // + AudioSourcePriority + audio_source_priority; + AudioControlValue + audio_source_volume_scale; + + if (audio_source->IsAudioSourceClipped(GetAudioHead())) + { + // + // If it is a transient source then ignore request + // + if (audio_source->GetAudioRenderType() == TransientAudioRenderType) + { + #ifdef LAB_ONLY + sourceClippedCount++; + #endif + return; + } + audio_source_priority = audio_source->GetAudioSourcePriority(); + audio_source_volume_scale = 0.0f; + } + else + { + audio_source_priority = audio_source->GetAudioSourcePriority(); + audio_source_volume_scale = audio_source->CalculateSourceVolumeScale(); + } + + // + //-------------------------------------------------------------------------- + // If this a transient source and volume is lower than threshold + // Then return + //-------------------------------------------------------------------------- + // + if ( + message->controlID == StartAudioControlID && + audio_source->GetAudioRenderType() == TransientAudioRenderType && + audio_source_volume_scale < LowAudioVolumeThreshold + ) + { + #ifdef LAB_ONLY + sourceClippedCount++; + #endif + return; + } + + // + //-------------------------------------------------------------------------- + // Create audio weight based on priority and volume + // Add audio event + //-------------------------------------------------------------------------- + // + AudioWeighting + audio_weight(audio_source_priority, audio_source_volume_scale); + AudioEvent + *audio_event; + + audio_event = new AudioEvent(audio_source, message); + Register_Object(audio_event); + audioEventSocket.AddValue(audio_event, audio_weight); +} + +// +//############################################################################# +// ProcessAudioRequestMessage +//############################################################################# +// +Logical + AudioRenderer::ProcessAudioRequestMessage() +{ + // + // Process high priority, high volume event + // + AudioEventIterator + iterator(&audioEventSocket); + AudioEvent + *audio_event; + + Logical stuff = False; + while ((audio_event = iterator.GetCurrent()) != NULL) + { + stuff = True; + Check(audio_event); + audio_event->Process(); + //return True; + } + return stuff; +} + +// +//############################################################################# +// FlushAudioMessages +//############################################################################# +// +void + AudioRenderer::FlushAudioMessages(AudioSource *audio_source) +{ + Check(this); + Check(audio_source); + + // + // Process matching events + // + AudioEventIterator + iterator(&audioEventSocket); + AudioEvent + *audio_event; + + while ((audio_event = iterator.ReadAndNext()) != NULL) + { + Check(audio_event); + if (audio_event->targetReceiver.GetCurrent() == audio_source) + { + if (audio_event->messageToSend->controlID == StopAudioControlID) + { + audio_event->Process(); + } + else + { + Unregister_Object(audio_event); + delete audio_event; + } + } + } +} + +// +//############################################################################# +// MakeAudioHead +//############################################################################# +// +AudioHead* + AudioRenderer::MakeAudioHead() +{ + return new AudioHead; +} + +// +//############################################################################# +// StartEntityEffectImplementation +//############################################################################# +// +void + AudioRenderer::StartEntityEffectImplementation( + Entity *parent_entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ) +{ + SET_AUDIO_RENDERER(); + + Check(this); + Check(parent_entity); + Check(damage_zone); + Verify(resource_ID != ResourceDescription::NullResourceID); + + // + //-------------------------------------------------------------------------- + // Get the audio resource for this effect + //-------------------------------------------------------------------------- + // + ResourceDescription *audio_resource_description; + + Check(application); + Check(application->GetResourceFile()); + audio_resource_description = + application->GetResourceFile()->SearchList( + resource_ID, + ResourceDescription::AudioStreamListResourceType + ); + if (audio_resource_description == NULL) + { + CLEAR_AUDIO_RENDERER(); + return; + } + Check(audio_resource_description); + + // + //-------------------------------------------------------------------------- + // Get the resource ID for the model resource for the audio effect entity + //-------------------------------------------------------------------------- + // + ResourceDescription *model_resource_description; + + Check(application); + Check(application->GetResourceFile()); + Check(audio_resource_description); + model_resource_description = + application->GetResourceFile()->SearchList( + audio_resource_description->resourceID, + ResourceDescription::ModelListResourceType + ); + if (model_resource_description == NULL) + { + CLEAR_AUDIO_RENDERER(); + return; + } + Check(model_resource_description); + model_resource_description->Lock(); + audio_resource_description->Lock(); + + // + //-------------------------------------------------------------------------- + // Get the entity segment + //-------------------------------------------------------------------------- + // + Entity *linked_entity; + AudioRepresentation audio_representation; + EntitySegment *parent_entity_segment; + + linked_entity = GetLinkedEntity(); + Check(linked_entity); + audio_representation = + (AudioRepresentation)parent_entity->GetAudioRepresentation( + linked_entity + ); + + parent_entity_segment = damage_zone->GetCurrentEffectSite( + (audio_representation == InternalAudioRepresentation) ? + DamageZone::InternalAudioEffectSite : + DamageZone::ExternalAudioEffectSite + ); + Check(parent_entity_segment); + + // + //-------------------------------------------------------------------------- + // Create the audio effect entity with this resource + //-------------------------------------------------------------------------- + // + JointedMover *jointed_mover; + + Verify(parent_entity->IsDerivedFrom(JointedMover::GetClassDerivations())); + jointed_mover = Cast_Object(JointedMover*, parent_entity); + Check(jointed_mover); + + AudioEntity::MakeMessage + make_message( + model_resource_description->resourceID, + jointed_mover, + parent_entity_segment + ); + #if DEBUG_LEVEL>0 + AudioEntity *audio_entity = + #endif + AudioEntity::Make(&make_message); + Register_Object(audio_entity); + + model_resource_description->Unlock(); + audio_resource_description->Unlock(); + + CLEAR_AUDIO_RENDERER(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ AudioRenderer profile bits ~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(TRACE_AUDIO_RENDERER) + BitTrace Audio_Renderer("Audio Renderer"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_CREATE_OBJECTS) + BitTrace Audio_Renderer_Create_Objects("Audio Renderer Create Objects"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_DESTROY_OBJECTS) + BitTrace Audio_Renderer_Destroy_Objects("Audio Renderer Destroy Objects"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_START_HANDLER) + BitTrace Audio_Renderer_Start_Handler("Audio Renderer Start Handler"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_STOP_HANDLER) + BitTrace Audio_Renderer_Stop_Handler("Audio Renderer Stop Handler"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_EXECUTE) + BitTrace Audio_Renderer_Execute("Audio Renderer Execute"); +#endif + +//############################################################################# +//############################## AudioEvent ############################# +//############################################################################# + +MemoryBlock *AudioEvent::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(Event), AUDIOEVENT_MEMORYBLOCK_ALLOCATION, AUDIOEVENT_MEMORYBLOCK_ALLOCATION, "AudioEvents"); + return &allocatedMemory; +} + +// +//############################################################################# +//############################################################################# +// +AudioEvent::AudioEvent( + AudioSource *target, + AudioSource::RequestMessage *message +): + targetReceiver(this) +{ + Check(target); + Check(message); + + // + // Store the message + // + size_t long_size = (message->messageLength+3)>>2; + messageToSend = (AudioSource::RequestMessage*)new long[long_size]; + Check_Pointer(messageToSend); + Register_Pointer(messageToSend); + + Mem_Copy( + messageToSend, + message, + message->messageLength, + long_size*sizeof(long) + ); + + // + // Store the target receiver + // + targetReceiver.Add(target); +} + +// +//############################################################################# +//############################################################################# +// +AudioEvent::~AudioEvent() +{ + Unregister_Pointer(messageToSend); + delete messageToSend; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioEvent::ReleaseLinkHandler( + Socket*, + Plug* + ) +{ + Unregister_Object(this); + delete this; +} diff --git a/MUNGA/AUDREND.h b/MUNGA/AUDREND.h new file mode 100644 index 0000000..c157d8f --- /dev/null +++ b/MUNGA/AUDREND.h @@ -0,0 +1,250 @@ +#pragma once + +#include "renderer.h" +#include "audio.h" +#include "audsrc.h" +#include "audwgt.h" +#include "event.h" +#include "..\munga_l4\l4audhdw.h" + +//########################################################################## +//######################## AudioRenderer ############################# +//########################################################################## + +class AudioEvent; + +class AudioRenderer: + public Renderer +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + AudioRenderer(RendererRate render_rate); + ~AudioRenderer(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Renderer Interface +// +public: + virtual void + Initialize(); + + void + LinkToEntity(Entity *entity); + + AudioHead* + GetAudioHead(); + + AudioFrameCount + GetAudioFrameCount(); + + virtual void ReleaseSourceSet(SourceSet &sourceSet) = 0; + + void + PostAudioRequestMessage( + AudioSource *audio_source, + AudioSource::RequestMessage *message + ); + Logical + ProcessAudioRequestMessage(); + void + FlushAudioMessages(AudioSource *audio_source); + + Logical + ExecuteBackground(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +protected: + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Methods +// +private: + virtual AudioHead* + MakeAudioHead(); + + void + StartEntityEffectImplementation( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + typedef VChainOf + AudioEventSocket; + typedef VChainIteratorOf + AudioEventIterator; + + AudioHead + *audioHead; + AudioEventSocket + audioEventSocket; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Audio Renderer Statistics +// +#ifdef LAB_ONLY + public: + int + sourceClippedCount; + int + sourceStartCount; + int + sourceSuspendCount; + int + sourceResumeCount; + int + doubleTriggerCount; + int + resourceStealCount; + int + resourceStealPriorityCount; + int + resourceStealVolumeCount; + int + stealShortDurationCount; +#endif +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioRenderer inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + +inline AudioHead* + AudioRenderer::GetAudioHead() +{ + Check(audioHead); + return audioHead; +} + +inline AudioFrameCount + AudioRenderer::GetAudioFrameCount() +{ + Check(audioHead); + return audioHead->GetAudioFrameCount(); +} + +inline Logical + AudioRenderer::ExecuteBackground() +{ + Check(this); + return ProcessAudioRequestMessage(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ AudioRenderer profile macros ~~~~~~~~~~~~~~~~~~~~ + +#if defined(TRACE_AUDIO_RENDERER) + extern BitTrace Audio_Renderer; + #define SET_AUDIO_RENDERER() Audio_Renderer.Set() + #define CLEAR_AUDIO_RENDERER() Audio_Renderer.Clear() +#else + #define SET_AUDIO_RENDERER() + #define CLEAR_AUDIO_RENDERER() +#endif + +#if defined(TRACE_AUDIO_RENDERER_CREATE_OBJECTS) + extern BitTrace Audio_Renderer_Create_Objects; + #define SET_AUDIO_RENDERER_CREATE_OBJECTS() Audio_Renderer_Create_Objects.Set() + #define CLEAR_AUDIO_RENDERER_CREATE_OBJECTS() Audio_Renderer_Create_Objects.Clear() +#else + #define SET_AUDIO_RENDERER_CREATE_OBJECTS() + #define CLEAR_AUDIO_RENDERER_CREATE_OBJECTS() +#endif + +#if defined(TRACE_AUDIO_RENDERER_DESTROY_OBJECTS) + extern BitTrace Audio_Renderer_Destroy_Objects; + #define SET_AUDIO_RENDERER_DESTROY_OBJECTS() Audio_Renderer_Destroy_Objects.Set() + #define CLEAR_AUDIO_RENDERER_DESTROY_OBJECTS() Audio_Renderer_Destroy_Objects.Clear() +#else + #define SET_AUDIO_RENDERER_DESTROY_OBJECTS() + #define CLEAR_AUDIO_RENDERER_DESTROY_OBJECTS() +#endif + +#if defined(TRACE_AUDIO_RENDERER_START_HANDLER) + extern BitTrace Audio_Renderer_Start_Handler; + #define SET_AUDIO_RENDERER_START_HANDLER() Audio_Renderer_Start_Handler.Set() + #define CLEAR_AUDIO_RENDERER_START_HANDLER() Audio_Renderer_Start_Handler.Clear() +#else + #define SET_AUDIO_RENDERER_START_HANDLER() + #define CLEAR_AUDIO_RENDERER_START_HANDLER() +#endif + +#if defined(TRACE_AUDIO_RENDERER_STOP_HANDLER) + extern BitTrace Audio_Renderer_Stop_Handler; + #define SET_AUDIO_RENDERER_STOP_HANDLER() Audio_Renderer_Stop_Handler.Set() + #define CLEAR_AUDIO_RENDERER_STOP_HANDLER() Audio_Renderer_Stop_Handler.Clear() +#else + #define SET_AUDIO_RENDERER_STOP_HANDLER() + #define CLEAR_AUDIO_RENDERER_STOP_HANDLER() +#endif + +#if defined(TRACE_AUDIO_RENDERER_EXECUTE) + extern BitTrace Audio_Renderer_Execute; + #define SET_AUDIO_RENDERER_EXECUTE() Audio_Renderer_Execute.Set() + #define CLEAR_AUDIO_RENDERER_EXECUTE() Audio_Renderer_Execute.Clear() +#else + #define SET_AUDIO_RENDERER_EXECUTE() + #define CLEAR_AUDIO_RENDERER_EXECUTE() +#endif + +//########################################################################## +//######################### AudioEvent ############################### +//########################################################################## + +#define AUDIOEVENT_MEMORYBLOCK_ALLOCATION (20) + +class AudioEvent: + public Node +{ + friend class AudioRenderer; + +private: + AudioEvent( + AudioSource *target, + AudioSource::RequestMessage *message + ); + ~AudioEvent(); + + static MemoryBlock* GetAllocatedMemory(); + + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } + + void + Process(); + + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + + AudioSource::RequestMessage + *messageToSend; + SlotOf + targetReceiver; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioEvent inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline void + AudioEvent::Process() +{ + Check(targetReceiver.GetCurrent()); + targetReceiver.GetCurrent()->Receive(messageToSend); + Unregister_Object(this); + delete this; +} diff --git a/MUNGA/AUDSEQ.cpp b/MUNGA/AUDSEQ.cpp new file mode 100644 index 0000000..24a6d73 --- /dev/null +++ b/MUNGA/AUDSEQ.cpp @@ -0,0 +1,868 @@ +#include "munga.h" +#pragma hdrstop + +#include "audseq.h" +#include "objstrm.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlEvent ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlEvent::AudioControlEvent( + AudioTick start_tick, + AudioControlID audio_control_ID, + AudioControlValue audio_control_value +): + Plug(AudioControlEventClassID) +{ + startTick = start_tick; + audioControlID = audio_control_ID; + audioControlValue = audio_control_value; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlEvent::AudioControlEvent(): + Plug(AudioControlEventClassID) +{ + startTick = 0; + audioControlID = NullAudioControlID; + audioControlValue = 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlEvent::~AudioControlEvent() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlEvent::TestInstance() const +{ + Plug::TestInstance(); + Verify( + (Enumeration)audioControlID >= (Enumeration)0 && + (Enumeration)audioControlID < (Enumeration)AudioControlIDCount + ); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlEvent::Send(AudioComponent *audio_component) +{ + Check(this); + Check(audio_component); + audio_component->ReceiveControl(audioControlID, audioControlValue); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlEvent::Chase(AudioComponent *audio_component) +{ + Check(this); + Check(audio_component); + + switch (audioControlID) + { + case StartAudioControlID: + return False; + + case StopAudioControlID: + Send(audio_component); + return False; + + default: + break; + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + AudioControlEvent *control_event + ) +{ + Check(stream); + Check_Signature(control_event); + + MemoryStream_Read(stream, &control_event->startTick); + MemoryStream_Read(stream, &control_event->audioControlID); + MemoryStream_Read(stream, &control_event->audioControlValue); + + Check(control_event); + return *stream; +} + +// +//############################################################################# +//############################################################################# +// +MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const AudioControlEvent *control_event + ) +{ + Check(stream); + Check(control_event); + + MemoryStream_Write(stream, &control_event->startTick); + MemoryStream_Write(stream, &control_event->audioControlID); + MemoryStream_Write(stream, &control_event->audioControlValue); + return *stream; +} + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator << (std::ostream &strm, const AudioControlEvent &control_event) +{ + Check(&control_event); + + strm << "[" ; + strm << control_event.startTick << ","; + strm << control_event.audioControlID << ","; + strm << control_event.audioControlValue; + strm << "]"; + + return strm; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioControlSequence ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +AudioControlSequence::AudioControlSequence( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream), + audioComponentSocket(NULL), + audioControlEventSocket(NULL) +{ + Logical dump_value; + Logical is_looped; + AudioComponent *audio_component; + AudioControlEvent *audio_control_event; + CollectionSize i, number_of_control_events; + AudioDivisionsPerBeat divisions_per_beat; + AudioTempo tempo; + + MemoryStream_Read(stream, &dump_value); + MemoryStream_Read(stream, &is_looped); + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + MemoryStream_Read(stream, &divisions_per_beat); + MemoryStream_Read(stream, &tempo); + MemoryStream_Read(stream, &number_of_control_events); + + for (i = 0; i < number_of_control_events; i++) + { + audio_control_event = new AudioControlEvent; + Register_Object(audio_control_event); + MemoryStream_Read(stream, audio_control_event); + audioControlEventSocket.Add(audio_control_event); + } + + AudioControlSequenceX( + audio_component, + entity, + is_looped, + divisions_per_beat, + tempo, + dump_value + ); +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioControlSequence::AudioControlSequenceX( + AudioComponent *audio_component, + Entity *entity, + Logical is_looped, + AudioDivisionsPerBeat divisions_per_beat, + AudioTempo the_tempo, + Logical dump_value + ) +#else +void + AudioControlSequence::AudioControlSequenceX( + AudioComponent *audio_component, + Entity *entity, + Logical is_looped, + AudioDivisionsPerBeat divisions_per_beat, + AudioTempo the_tempo, + Logical + ) +#endif +{ + Check(audio_component); + audioComponentSocket.Add(audio_component); + + isLooped = is_looped; + isRunning = False; + startTime = AudioTime::Null; + audioControlEventIterator = NULL; + divisionsPerBeat = divisions_per_beat; + tempo = the_tempo; + + #if DEBUG_LEVEL>0 + dumpValue = dump_value; + #endif + + audio_component->AddWatcher(this); + Check(entity); + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlSequence::~AudioControlSequence() +{ + StopSequence(); + Verify(!isRunning); + Verify(audioControlEventIterator == NULL); + + AudioControlEventIterator iterator(&audioControlEventSocket); + Check(&iterator); + iterator.DeletePlugs(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, is_looped); + + // + // Write audio component + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); + + // + // Read tempo + // + AudioTempo tempo = 100; + + if (name_list->FindData("tempo") != NULL) + { + Check_Pointer(name_list->FindData("tempo")); + Convert_From_Ascii((const char *)name_list->FindData("tempo"), &tempo); + } + + // + // Read midi file + // + DynamicMemoryStream midi_file_stream; + + { + CString midi_file_name; + + Check_Pointer(name_list->FindData("midi_file")); + midi_file_name = (const char*)name_list->FindData("midi_file"); + + std::ifstream input_midi_file(midi_file_name, std::ios::in | std::ios::binary); + #if DEBUG_LEVEL>0 + if (!input_midi_file) + { + Dump(midi_file_name); + } + #endif + + MemoryStream_Write(&midi_file_stream, &input_midi_file); + midi_file_stream.Rewind(); + } + + // + // Parse midi stream + // + DynamicMemoryStream control_event_stream; + CreateAudioControlEventStream midi_parser; + + Check(&midi_file_stream); + Check(&control_event_stream); + Check(&midi_parser); + midi_parser.Parse(&midi_file_stream, &control_event_stream, tempo); + control_event_stream.Rewind(); + + // + // Write the divisions per beat and tempo + // + AudioDivisionsPerBeat divisions_per_beat; + + divisions_per_beat = midi_parser.GetDivisionsPerBeat(); + tempo = midi_parser.GetTempo(); + MemoryStream_Write(stream, &divisions_per_beat); + MemoryStream_Write(stream, &tempo); + + // + // Write control event stream + // + CollectionSize number_of_control_events; + + number_of_control_events = midi_parser.GetNumberOfEvents(); + MemoryStream_Write(stream, &number_of_control_events); + MemoryStream_Write(stream, &control_event_stream); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlSequence::TestInstance() const +{ + AudioComponent::TestInstance(); + + Check(&audioComponentSocket); + Check(&audioControlEventSocket); + if (isRunning) + { + Check(audioControlEventIterator); + } + else + { + Verify(audioControlEventIterator == NULL); + } + Verify(tempo >= 1 && tempo <= 600); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::StartSequence() +{ + Check(this); + + // + // If already running, stop sequence + // + if (isRunning) + { + StopSequence(); + } + + // + // Make an iterator for the control sequence + // + Verify(audioControlEventIterator == NULL); + audioControlEventIterator = + new AudioControlEventIterator(&audioControlEventSocket); + Register_Object(audioControlEventIterator); + + startTime = AudioTime::Now(); + isRunning = True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::StopSequence() +{ + Check(this); + + // + // If not running, return + // + if (!isRunning) + return; + + // + // Find next on or off event + // + AudioControlEvent *control_event; + + Check(audioControlEventIterator); + while ((control_event = audioControlEventIterator->ReadAndNext()) != NULL) + { + Check(control_event); + if (!control_event->Chase(audioComponentSocket.GetCurrent())) + break; + } + + // + // Destroy the iterator for the control sequence + // + Unregister_Object(audioControlEventIterator); + delete audioControlEventIterator; + audioControlEventIterator = NULL; + + isRunning = False; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::RunSequence() +{ + Check(this); + + // + // If the sequence is not running, then return + // + if (!isRunning) + return; + + // + // Play events which have a start time less then the + // current time + // + AudioControlEvent *control_event; + + Check(audioControlEventIterator); + control_event = audioControlEventIterator->GetCurrent(); + while ( + control_event != NULL && + IsEventReady(control_event) + ) + { + #if DEBUG_LEVEL>0 + if (dumpValue) + { + Dump(*control_event); + } + #endif + + #if 0 + // + // HACK - convert start control to use duration + // + Verify(control_event->audioControlID != StopAudioControlID); + if (control_event->audioControlID == StartAudioControlID) + { + // + // Convert ticks to seconds + // seconds = ticks / (divisionsPerBeat (t/b) * tempo (b/60s)) + // + Scalar denominator = + (Scalar)divisionsPerBeat * (Scalar)tempo / 60.0f; + Verify(!Small_Enough(denominator)); + control_event->audioControlValue = + control_event->audioControlValue / denominator; + } + #endif + + // + // Send the controller to the connected audio component + // + Check(control_event); + control_event->Send(audioComponentSocket.GetCurrent()); + + // + // Step to next event + // + audioControlEventIterator->Next(); + control_event = audioControlEventIterator->GetCurrent(); + } + + // + // If there are no more events to be played then stop running + // + if (control_event == NULL) + { + StopSequence(); + if (isLooped) + { + StartSequence(); + } + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlSequence::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + + switch(control_ID) + { + case StartAudioControlID: + StartSequence(); + break; + + case StopAudioControlID: + StopSequence(); + break; + + case IdleAudioControlID: + RunSequence(); + break; + + case TempoAudioControlID: + tempo = control_value; + Verify(tempo >= 1 && tempo <= 600); + break; + + default: + break; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioControlSequence::IsEventReady(AudioControlEvent *audio_control_event) +{ + Check(this); + + AudioTime offset_time(startTime); + offset_time += CalculateEventSeconds(audio_control_event); + return (offset_time <= AudioTime::Now()); +} + +// +//############################################################################# +//############################################################################# +// +Scalar + AudioControlSequence::CalculateEventSeconds( + AudioControlEvent *audio_control_event + ) +{ + Check(this); + Check(audio_control_event); + + // + // Convert ticks to seconds + // seconds = ticks / (divisionsPerBeat (t/b) * tempo (b/60s)) + // + Scalar denominator = (Scalar)divisionsPerBeat * (Scalar)tempo / 60.0f; + Verify(!Small_Enough(denominator)); + return (Scalar)audio_control_event->GetStartTick() / denominator; +} + +//############################################################################# +//#################### CreateAudioControlEventStream #################### +//############################################################################# + +CreateAudioControlEventStream::CreateAudioControlEventStream(): + audioControlEventSocket(NULL, False) +{ + inputStream = NULL; + outputStream = NULL; + divisionsPerBeat = 120; + tempo = 100; +} + +// +//############################################################################# +//############################################################################# +// +CreateAudioControlEventStream::~CreateAudioControlEventStream(void) +{ + AudioControlEventIterator iterator(&audioControlEventSocket); + Check(&iterator); + iterator.DeletePlugs(); +} + +// +//############################################################################# +//############################################################################# +// +Logical + CreateAudioControlEventStream::TestInstance() const +{ + MidiParse::TestInstance(); + Check(&audioControlEventSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Parse( + MemoryStream *input_stream, + MemoryStream *output_stream, + SignedLongWord tempo_argument + ) +{ + Check(this); + Check(input_stream); + Check(output_stream); + + inputStream = input_stream; + outputStream = output_stream; + + // + // Parse the stream + // + tempo = tempo_argument; + Verify(GetNumberOfEvents() == 0); + MidiParse::Parse(); + + // + // Write the events + // + AudioControlEventIterator iterator(&audioControlEventSocket); + AudioControlEvent *control_event; + + Check(&iterator); + while ((control_event = iterator.ReadAndNext()) != NULL) + { + Check(control_event); + MemoryStream_Write(outputStream, control_event); + } +} + +// +//############################################################################# +//############################################################################# +// +CollectionSize + CreateAudioControlEventStream::GetNumberOfEvents() +{ + Check(this); + + AudioControlEventIterator iterator(&audioControlEventSocket); + Check(&iterator); + return iterator.GetSize(); +} + +// +//############################################################################# +//############################################################################# +// +MidiParse::SignedWord + CreateAudioControlEventStream::Mf_getc() +{ + Check(this); + + unsigned char c; + + MemoryStream_Read(inputStream, &c); + return c; +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_error(char *str) +{ + Check(this); + Check_Pointer(str); + Fail(str); +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_header( + SignedWord, + SignedWord, + SignedWord division + ) +{ + Check(this); + divisionsPerBeat = division; +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_on( + SignedWord channel, + SignedWord pitch, + SignedWord vol + ) +{ + Check(this); + + // + // Interpret vol 0 as note off + // + if (vol == 0) + { + Mf_off(channel, pitch, vol); + return; + } + + // + // Verify that last event was a stop + // + #if DEBUG_LEVEL>0 + { + AudioControlEventIterator iterator(&audioControlEventSocket); + AudioControlEvent *last_control_event; + + iterator.Last(); + if ((last_control_event = iterator.GetCurrent()) != NULL) + { + Check(last_control_event); + Verify(last_control_event->audioControlID == StopAudioControlID); + } + } + #endif + + AudioTick current_ticks = CurTime(); + AudioControlEvent *audio_control_event; + + // + // Add note value event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + NoteAudioControlID, + (Scalar)pitch + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + + // + // Add velocity event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + AttackVolumeAudioControlID, + (Scalar)vol / (Scalar)127 + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + + // + // Add start event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + StartAudioControlID, + 0.0f + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_off( + SignedWord, + SignedWord pitch, + SignedWord + ) +{ + Check(this); + + AudioTick current_ticks = CurTime(); + AudioControlEvent *audio_control_event; + + #if 0 + // + // HACK - convert start control to use duration + // + AudioControlEventIterator + iterator(&audioControlEventSocket); + + iterator.Last(); + audio_control_event = iterator.GetCurrent(); + Check(audio_control_event); + Verify(audio_control_event->audioControlID == StartAudioControlID); + + audio_control_event->audioControlValue = + current_ticks - audio_control_event->startTick; + #else + // + // Add note value event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + NoteAudioControlID, + (Scalar)pitch + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + + // + // Add stop event + // + audio_control_event + = new AudioControlEvent( + current_ticks, + StopAudioControlID, + 0.0f + ); + Register_Object(audio_control_event); + audioControlEventSocket.AddValue(audio_control_event, current_ticks); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + CreateAudioControlEventStream::Mf_tempo(SignedLongWord) +{ + Check(this); + // tempo = i1; // HACK - Cakewalk appears to produce bogus tempo +} diff --git a/MUNGA/AUDSEQ.h b/MUNGA/AUDSEQ.h new file mode 100644 index 0000000..d542c25 --- /dev/null +++ b/MUNGA/AUDSEQ.h @@ -0,0 +1,244 @@ +#pragma once + +#include "style.h" +#include "audio.h" +#include "audmidi.h" +#include "vchain.h" +#include "audtime.h" + +//########################################################################## +//####################### AudioControlEvent ########################## +//########################################################################## + +class AudioControlEvent: + public Plug +{ + friend MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + AudioControlEvent *control_event + ); + + friend MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const AudioControlEvent *control_event + ); + +public: + AudioControlEvent( + AudioTick start_tick, + AudioControlID audio_control_ID, + AudioControlValue audio_control_value + ); + AudioControlEvent(); + ~AudioControlEvent(); + + Logical + AudioControlEvent::TestInstance() const; + + AudioTick + GetStartTick() + {return startTick;} + + void + Send(AudioComponent *audio_component); + + Logical + Chase(AudioComponent *audio_component); + +public: + friend std::ostream& operator << (std::ostream &strm, const AudioControlEvent &control_event); + +// private: // HACK + AudioTick + startTick; + AudioControlID + audioControlID; + AudioControlValue + audioControlValue; +}; + +//########################################################################## +//####################### AudioControlSequence ####################### +//########################################################################## + +class AudioControlSequence: + public AudioComponent +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + AudioControlSequence( + PlugStream *stream, + Entity *entity + ); + void + AudioControlSequenceX( + AudioComponent *audio_component, + Entity *entity, + Logical is_looped, + AudioDivisionsPerBeat divisions_per_beat, + AudioTempo tempo, + Logical dump_value + ); + ~AudioControlSequence(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Sequence methods +// +public: + // + //-------------------------------------------------------------------- + // Controller methods + //-------------------------------------------------------------------- + // + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + // + //-------------------------------------------------------------------- + // Sequence control + //-------------------------------------------------------------------- + // + void + StartSequence(); + void + RunSequence(); + void + StopSequence(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + Logical + IsEventReady(AudioControlEvent *audio_control_event); + Scalar + CalculateEventSeconds(AudioControlEvent *audio_control_event); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + typedef SChainOf + AudioControlEventSocket; + typedef SChainIteratorOf + AudioControlEventIterator; + + Logical isLooped; + Logical isRunning; + AudioTime startTime; + AudioDivisionsPerBeat divisionsPerBeat; + AudioTempo tempo; + + SlotOf + audioComponentSocket; + + AudioControlEventSocket + audioControlEventSocket; + AudioControlEventIterator + *audioControlEventIterator; + + #if DEBUG_LEVEL>0 + Logical + dumpValue; + #endif +}; + +//########################################################################## +//################### CreateAudioControlEventStream ################## +//########################################################################## + +class CreateAudioControlEventStream: + public MidiParse +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + CreateAudioControlEventStream(); + ~CreateAudioControlEventStream(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Parsing +// +public: + void + Parse( + MemoryStream *input_stream, + MemoryStream *output_stream, + SignedLongWord tempo=100 + ); + AudioDivisionsPerBeat + GetDivisionsPerBeat() + {return divisionsPerBeat;} + AudioTempo + GetTempo() + {return tempo;} + CollectionSize + GetNumberOfEvents(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +private: + SignedWord + Mf_getc(); + void + Mf_error(char *); + + void + Mf_header(SignedWord,SignedWord,SignedWord); + void + Mf_on(SignedWord,SignedWord,SignedWord); + void + Mf_off(SignedWord,SignedWord,SignedWord); + void + Mf_tempo(SignedLongWord); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + typedef VChainOf + AudioControlEventSocket; + typedef VChainIteratorOf + AudioControlEventIterator; + + MemoryStream + *inputStream; + MemoryStream + *outputStream; + + AudioDivisionsPerBeat + divisionsPerBeat; + AudioTempo + tempo; + + AudioControlEventSocket + audioControlEventSocket; +}; diff --git a/MUNGA/AUDSRC.cpp b/MUNGA/AUDSRC.cpp new file mode 100644 index 0000000..486e3c2 --- /dev/null +++ b/MUNGA/AUDSRC.cpp @@ -0,0 +1,817 @@ +#include "munga.h" +#pragma hdrstop + +#include "audsrc.h" +#include "audrend.h" +#include "objstrm.h" +#include "app.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSourceStartState ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// + +#define DEFAULT_NOTE (60) + +AudioSourceStartState::AudioSourceStartState() +{ + noteValue = DEFAULT_NOTE; + + isDurationSet = False; + hasDuration = False; + duration = 0.0f; + startTime = 0.0f; + endTime = 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +AudioSourceStartState::~AudioSourceStartState() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioSourceStartState::TestInstance() const +{ + if (isDurationSet || hasDuration) + { + Verify(duration >= 0.0f); + } + if (hasDuration) + { + Verify(endTime >= startTime); + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSourceStartState::CalculateDuration(AudioControlValue control_value) +{ + // + // Calculate duration + // + if (control_value > 0.0f) + { + hasDuration = True; + endTime = AudioTime::Now(); + endTime += control_value; + } + else if (isDurationSet) + { + hasDuration = True; + endTime = AudioTime::Now(); + endTime += duration; + isDurationSet = False; + } + else + { + hasDuration = False; + endTime = 0.0f; + } +} + +#if 0 +// +//############################################################################# +//############################################################################# +// +AudioTime + AudioSourceStartState::GetCurrentRunningTime() +{ + Check(this); + AudioTime current_duration = AudioTime::Now(); + return (current_duration -= startTime); +} +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +const Receiver::HandlerEntry + AudioSource::MessageHandlerEntries[]= +{ + { + AudioSource::StartMessageID, + "Start", + (AudioSource::Handler)&AudioSource::StartMessageHandler + }, + { + AudioSource::StopMessageID, + "Stop", + (AudioSource::Handler)&AudioSource::StopMessageHandler + } +}; + +AudioSource::MessageHandlerSet& AudioSource::GetMessageHandlers() +{ + static AudioSource::MessageHandlerSet messageHandlers(ELEMENTS(AudioSource::MessageHandlerEntries), AudioSource::MessageHandlerEntries, AudioComponent::GetMessageHandlers()); + return messageHandlers; +} + +// +//############################################################################# +//############################################################################# +// +Derivation* AudioSource::GetClassDerivations() +{ + static Derivation classDerivations(AudioComponent::GetClassDerivations(), "AudioSource"); + return &classDerivations; +} + +AudioSource::SharedData + AudioSource::DefaultData( + AudioSource::GetClassDerivations(), + AudioSource::GetMessageHandlers() + ); + +// +//############################################################################# +//############################################################################# +// +AudioSource::AudioSource( + PlugStream *stream, + Entity *entity +): + AudioComponent(stream, DefaultData) +{ + AudioResource *audio_resource; + AudioLocation *audio_location; + AudioSourcePriority priority; + AudioSourceMixPresence mix_presence; + AudioControlValue volume_mix_level; + AudioPitchCents pitch_mix_offset; + AudioControlValue brightness_mix_level; + Logical has_compression_curve; + Scalar seconds; + AudioTime compression_duration; + Logical use_brightness_scale; + Logical use_attack_time_scale; + + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_resource); + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_location); + MemoryStream_Read(stream, &priority); + MemoryStream_Read(stream, &mix_presence); + MemoryStream_Read(stream, &volume_mix_level); + MemoryStream_Read(stream, &pitch_mix_offset); + MemoryStream_Read(stream, &brightness_mix_level); + MemoryStream_Read(stream, &has_compression_curve); + MemoryStream_Read(stream, &seconds); + compression_duration = seconds; + MemoryStream_Read(stream, &use_brightness_scale); + MemoryStream_Read(stream, &use_attack_time_scale); + + AudioSourceX( + audio_resource, + audio_location, + entity, + priority, + mix_presence, + volume_mix_level, + pitch_mix_offset, + brightness_mix_level, + has_compression_curve, + compression_duration, + use_brightness_scale, + use_attack_time_scale + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioComponent::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + CString audio_resource_name("resource"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_resource_name); + + CString audio_location_name("location"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_location_name); + + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, priority); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, mix_presence); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, volume_mix_level); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioPitchCents, pitch_mix_offset); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, brightness_mix_level); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, has_compression_curve); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Scalar, compression_duration); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_brightness_scale); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_attack_time_scale); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AudioSourceX( + AudioResource *audio_resource, + AudioLocation *audio_location, + Entity *entity, + AudioSourcePriority priority, + AudioSourceMixPresence mix_presence, + AudioControlValue volume_mix_level, + AudioPitchCents pitch_mix_offset, + AudioControlValue brightness_mix_level, + Logical has_compression_curve, + const AudioTime &compression_duration, + Logical use_brightness_scale, + Logical use_attack_time_scale + ) +{ + Check(audio_resource); + Check(audio_location); + Check(entity); + + audioLocation = audio_location; + audioResource = audio_resource; + + audioSourceState = StoppedAudioSourceState; + + attackVolumeScale = 1.0f; + useAttackTimeScale = use_attack_time_scale; + attackTimeScale = 0.0f; + + audioSourcePriority = priority; + + audioSourceMixPresence = mix_presence; + volumeCompressionScale = 1.0f; + + hasCompressionCurve = has_compression_curve; + compressionDuration = compression_duration; + + volumeMixScale = volume_mix_level; + pitchMixOffset = pitch_mix_offset; + useBrightnessScale = use_brightness_scale; + brightnessMixScale = brightness_mix_level; + + volumeScale = 1.0f; + pitchOffset = 0.0f; + brightnessScale = 1.0f; + + nextExecuteFrame = NullAudioFrameCount; + suspendFinishedFrame = NullAudioFrameCount; + + entity->AddAudioComponent(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioSource::~AudioSource() +{ + Verify(audioSourceState == StoppedAudioSourceState); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioSource::TestInstance() const +{ + AudioComponent::TestInstance(); + return True; +} + +// +// Resource methods +// + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::SetAudioResource(AudioResource *audio_resource) +{ + Check(this); + Check(audio_resource); + + Verify(audioSourceState == StoppedAudioSourceState); + Check(audioResource); + audioResource = audio_resource; +} + +// +// Current State/Status Accessors +// + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AssignAudioSourceState(AudioSourceState audio_source_state) +{ + Check(this); + + // + // Initialize the next start state if the source is now running + // + if (audio_source_state == RunningAudioSourceState) + { + AudioSourceStartState null_state; + nextStartState = null_state; + } + audioSourceState = audio_source_state; +} + +// +// Mixing & Logical compression methods +// + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioSource::CalculateSourceCompressionEffect() +{ + Check(this); + + // + // Get current volume level + // + AudioControlValue current_volume_level; + + current_volume_level = CalculateSourceVolumeScale(); + Verify(current_volume_level >= 0.0f && current_volume_level <= 1.0f); + + // + // Calculate the amount of this to apply to compression + // + if (hasCompressionCurve) + { + // + // scale = 1 / (1 + ((1/comp_dur) * duration)^2) + // + Scalar current_running_time = GetCurrentRunningTime(); + Scalar compression_duration = compressionDuration; + Scalar duration_factor; + Scalar denominator; + AudioControlValue compression_effect; + + Verify(!Small_Enough(compression_duration)); + duration_factor = pow((1.0f/compression_duration) * current_running_time, 2.0f); + // Warn(!(duration_factor > 0.0f)); + + denominator = 1.0f + duration_factor; + Verify(!Small_Enough(denominator)); + compression_effect = 1.0f / denominator; + Verify(compression_effect >= 0.0f && compression_effect <=1.0f); + + return compression_effect * current_volume_level; + } + return current_volume_level; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioSource::CalculateSourceVolumeScale() +{ + Check(this); + + // + // Execute the watchers that will update the volume related + // member parameters + // + ExecuteWatchers(); + + // + // Calculate the resulting volume scale + // + AudioControlValue + volume_scale; + + volume_scale = volumeScale * volumeMixScale * volumeCompressionScale; + Clamp(volume_scale, MinAudioVolume, MaxAudioVolume); + return volume_scale; +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioSource::CalculateSourceBrightnessScale() +{ + Check(this); + + AudioControlValue brightness_mix_scale; + + brightness_mix_scale = brightnessScale * brightnessMixScale; + Clamp(brightness_mix_scale, MinAudioBrightness, MaxAudioBrightness); + + return brightness_mix_scale; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ) +{ + Check(this); + switch (control_ID) + { + // + //---------------------------------------------------------------------- + // StartAudioControlID + //---------------------------------------------------------------------- + // + case StartAudioControlID: + { + StartMessage message(control_value); + + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->PostAudioRequestMessage( + this, + &message + ); + } + break; + + // + //---------------------------------------------------------------------- + // StopAudioControlID + //---------------------------------------------------------------------- + // + case StopAudioControlID: + { + StopMessage message; + + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->PostAudioRequestMessage( + this, + &message + ); + } + break; + + // + //---------------------------------------------------------------------- + // Misc... + //---------------------------------------------------------------------- + // + case VolumeAudioControlID: + VolumeAudioHandler(control_value); + break; + + case PitchAudioControlID: + PitchAudioHandler(control_value); + break; + + case BrightnessAudioControlID: + BrightnessAudioHandler(control_value); + break; + + case AttackVolumeAudioControlID: + AttackVolumeAudioHandler(control_value); + break; + + case AttackTimeAudioControlID: + AttackTimeAudioHandler(control_value); + break; + + case NoteAudioControlID: + NoteAudioHandler(control_value); + break; + + case DurationAudioControlID: + DurationAudioHandler(control_value); + break; + + case FlushMessagesAudioControlID: + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->FlushAudioMessages(this); + break; + + case NullAudioControlID: + case IdleAudioControlID: + break; + + default: + Fail("AudioSource::ReceiveControl - Should never reach here"); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::StartMessageHandler(StartMessage *message) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_START_HANDLER(); + + Check(this); + Check(message); + Verify(message->messageID == StartMessageID); + + // + //-------------------------------------------------------------------------- + // if double trigger condition exists + // then return + //-------------------------------------------------------------------------- + // + AudioTime double_trigger_cutoff(AudioDoubleTriggerCutoff); + + #if 0 + double_trigger_cutoff = AudioDoubleTriggerCutoff; + #endif + if ( + audioSourceState == RunningAudioSourceState && + GetCurrentRunningTime() <= double_trigger_cutoff + ) + { + #ifdef LAB_ONLY + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->doubleTriggerCount++; + #endif + CLEAR_AUDIO_RENDERER_START_HANDLER(); + CLEAR_AUDIO_RENDERER(); + return; + } + + // + //-------------------------------------------------------------------------- + // If the source is not stopped then stop it + //-------------------------------------------------------------------------- + // + if (audioSourceState != StoppedAudioSourceState) + { + StopMessage stop_message; + StopMessageHandler(&stop_message); + } + + // + //-------------------------------------------------------------------------- + // Verify that the state is stopped + // Copy the next start state into the current start state + // Calculate duration + //-------------------------------------------------------------------------- + // + Verify(audioSourceState == StoppedAudioSourceState); + currentStartState = nextStartState; + currentStartState.CalculateDuration(message->controlValue); + + // + //-------------------------------------------------------------------------- + // Implementation specific start request + //-------------------------------------------------------------------------- + // + StartMessageImplementation(); + + CLEAR_AUDIO_RENDERER_START_HANDLER(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +//############################################################################# +// +void +#if DEBUG_LEVEL>0 + AudioSource::StopMessageHandler(StopMessage *message) +#else + AudioSource::StopMessageHandler(StopMessage*) +#endif +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_STOP_HANDLER(); + + Check(this); + Check(message); + Verify(message->messageID == StopMessageID); + + // + // if the source is stopped + // then return + // + if (audioSourceState == StoppedAudioSourceState) + { + CLEAR_AUDIO_RENDERER_STOP_HANDLER(); + CLEAR_AUDIO_RENDERER(); + return; + } + + // + // Implementation specific stop request + // + StopMessageImplementation(); + + CLEAR_AUDIO_RENDERER_STOP_HANDLER(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::VolumeAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioVolume, MaxAudioVolume); + volumeScale = control_value / (MaxAudioVolume - MinAudioVolume); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::PitchAudioHandler(AudioControlValue control_value) +{ + Check(this); + pitchOffset = control_value; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::BrightnessAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioBrightness, MaxAudioBrightness); + brightnessScale = control_value / (MaxAudioBrightness - MinAudioBrightness); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AttackVolumeAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioAttack, MaxAudioAttack); + attackVolumeScale = control_value / (MaxAudioAttack - MinAudioAttack); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::AttackTimeAudioHandler(AudioControlValue control_value) +{ + Check(this); + Clamp(control_value, MinAudioAttack, MaxAudioAttack); + attackTimeScale = control_value / (MaxAudioAttack - MinAudioAttack); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::NoteAudioHandler(AudioControlValue control_value) +{ + Check(this); + nextStartState.SetNoteValue(control_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::DurationAudioHandler(AudioControlValue control_value) +{ + Check(this); + nextStartState.SetDurationValue(control_value); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::StartImplementation() +{ + currentStartState.Start(); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::StopImplementation() +{ + Fail("AudioSource::StopImplementation - Should never reach here"); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::SuspendImplementation() +{ + StopImplementation(); + Check(application); + Check(application->GetAudioRenderer()); + Check(audioResource); + suspendFinishedFrame = + application->GetAudioRenderer()->GetAudioFrameCount() + + audioResource->GetSuspendDelay(); + #ifdef LAB_ONLY + application->GetAudioRenderer()->sourceSuspendCount++; + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::ResumeImplementation() +{ + StartImplementation(); + suspendFinishedFrame = NullAudioFrameCount; + #ifdef LAB_ONLY + Check(application); + Check(application->GetAudioRenderer()); + application->GetAudioRenderer()->sourceResumeCount++; + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + AudioSource::Execute() +{ + Check(this); + + // + // Execute source if this is the next execution frame + // + AudioRenderer + *audio_renderer; + + Check(application); + audio_renderer = application->GetAudioRenderer(); + Check(audio_renderer); + if (nextExecuteFrame <= audio_renderer->GetAudioFrameCount()) + { + nextExecuteFrame = + audio_renderer->GetAudioFrameCount() + DefaultAudioFrameDelay; + + // + // Update the sources spatial model + // Execute inherited method + // Execute this sources sound model + // + UpdateSpatialModel(audio_renderer->GetAudioHead()); + AudioComponent::Execute(); + ExecuteModel(False); + } +} diff --git a/MUNGA/AUDSRC.h b/MUNGA/AUDSRC.h new file mode 100644 index 0000000..fdfb6d4 --- /dev/null +++ b/MUNGA/AUDSRC.h @@ -0,0 +1,664 @@ +#pragma once + +#include "style.h" +#include "audio.h" +#include "audloc.h" +#include "audlvl.h" +#include "audwgt.h" +#include "audtime.h" + +//########################################################################## +//##################### AudioSourceStartState ######################## +//########################################################################## + +class AudioSourceStartState SIGNATURED +{ +public: + AudioSourceStartState(); + ~AudioSourceStartState(); + + Logical + TestInstance() const; + + void + CalculateDuration(AudioControlValue control_value); + Logical + IsFinishedPlaying(); + AudioTime + GetCurrentRunningTime(); + + void + SetNoteValue(AudioControlValue note_value) + {noteValue = note_value;} + AudioControlValue + GetNoteValue() + {return noteValue;} + void + SetDurationValue(AudioControlValue duration_value); + void + Start() + {startTime = AudioTime::Now();} + +private: + AudioControlValue + noteValue; + + Logical + isDurationSet; + Logical + hasDuration; + Scalar + duration; + AudioTime + startTime; + AudioTime + endTime; +}; + +//~~~~~~~~~~~~~~~~~~~~~ AudioSourceStartState inlines ~~~~~~~~~~~~~~~~~~~~~~ + +inline Logical + AudioSourceStartState::IsFinishedPlaying() +{ + Check(this); + if (hasDuration) + { + return (AudioTime::Now() > endTime); + } + return False; +} + +inline void + AudioSourceStartState::SetDurationValue(AudioControlValue duration_value) +{ + Check(this); + isDurationSet = True; + duration = duration_value; +} + +inline AudioTime + AudioSourceStartState::GetCurrentRunningTime() +{ + Check(this); + return (AudioTime::Now() - startTime); +} + +//########################################################################## +//######################### AudioSource ############################## +//########################################################################## + +class AudioSource__RequestMessage; +class AudioSource__StartMessage; +class AudioSource__StopMessage; + +class AudioSource: + public AudioComponent +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + AudioSource( + PlugStream *stream, + Entity *entity + ); + void + AudioSource::AudioSourceX( + AudioResource *audio_resource, + AudioLocation *audio_location, + Entity *entity, + AudioSourcePriority priority, + AudioSourceMixPresence mix_presence, + AudioControlValue volume_mix_level, + AudioPitchCents pitch_mix_offset, + AudioControlValue brightness_mix_level, + Logical has_compression_curve, + const AudioTime &compression_duration, + Logical use_brightness_scale, + Logical use_attack_time_scale + ); + ~AudioSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Location methods +// +public: + AudioLocation* + GetAudioLocation(); + void + UpdateSpatialModel(AudioHead *audio_head); + Scalar + GetDistanceToSource(); + virtual Logical + IsAudioSourceClipped(AudioHead *audio_head); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Resource methods +// +public: + void + SetAudioResource(AudioResource *audio_resource); + AudioResource* + GetAudioResource(); + + AudioVoiceCount + GetAudioVoiceCount(); + AudioRenderType + GetAudioRenderType(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Current State/Status Accessors +// +public: + void + AssignAudioSourceState(AudioSourceState audio_source_state); + AudioSourceState + GetAudioSourceState(); + + Logical + IsFinishedPlaying(); + AudioTime + GetCurrentRunningTime(); + + AudioControlValue + GetCurrentNoteValue(); + AudioControlValue + CalculateSourceAttackVolumeScale(); + Logical + UseSourceAttackTime(); + AudioControlValue + CalculateSourceAttackTime(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Priority Accessors +// +public: + void + SetAudioSourcePriority(AudioSourcePriority audio_source_priority); + AudioSourcePriority + GetAudioSourcePriority(); + + AudioWeighting + CalculateAudioWeighting(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Mixing & Logical compression methods +// +public: + AudioSourceMixPresence + GetAudioSourceMixPresence(); + + void + SetVolumeCompressionScale(AudioControlValue compression_scale); + AudioControlValue + CalculateSourceCompressionEffect(); + + virtual AudioControlValue + CalculateSourceVolumeScale(); + virtual AudioPitchCents + CalculateSourcePitchOffset(); + Logical + UseSourceBrightnessScale(); + virtual AudioControlValue + CalculateSourceBrightnessScale(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Controller methods +// +public: + void + ReceiveControl( + AudioControlID control_ID, + AudioControlValue control_value + ); + + virtual void + VolumeAudioHandler(AudioControlValue); + virtual void + PitchAudioHandler(AudioControlValue); + virtual void + BrightnessAudioHandler(AudioControlValue); + virtual void + AttackVolumeAudioHandler(AudioControlValue); + virtual void + AttackTimeAudioHandler(AudioControlValue); + virtual void + NoteAudioHandler(AudioControlValue); + virtual void + DurationAudioHandler(AudioControlValue); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// State implementations +// +public: + virtual void + StartImplementation(); + virtual void + StopImplementation(); + + virtual void + SuspendImplementation(); + virtual void + ResumeImplementation(); + +protected: + virtual void + StartMessageImplementation() {} + virtual void + StopMessageImplementation() {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execution +// +public: + Logical + RequiresMaintenance(AudioHead *audio_head); + Logical + CanResume(AudioHead *audio_head); + void + Execute(); + +protected: + virtual void + ExecuteModel(Logical force_update) {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum { + StartMessageID = AudioComponent::NextMessageID, + StopMessageID, + NextMessageID + }; + + typedef AudioSource__RequestMessage + RequestMessage; + typedef AudioSource__StartMessage + StartMessage; + typedef AudioSource__StopMessage + StopMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + StartMessageHandler(StartMessage *message); + void + StopMessageHandler(StopMessage *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData + DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + // + // Location data + // + AudioLocation + *audioLocation; + + // + // Resource data + // + AudioResource + *audioResource; + + // + // State/Status data + // + AudioSourceState + audioSourceState; + + AudioSourceStartState + nextStartState, + currentStartState; + + AudioControlValue + attackVolumeScale; + Logical + useAttackTimeScale; + AudioControlValue + attackTimeScale; + + // + // Priority data + // + AudioSourcePriority + audioSourcePriority; + + // + // Mixing and compression + // + AudioSourceMixPresence + audioSourceMixPresence; + AudioControlValue + volumeCompressionScale; + + Logical + hasCompressionCurve; + AudioTime + compressionDuration; + + AudioControlValue + volumeMixScale; + AudioPitchCents + pitchMixOffset; + Logical + useBrightnessScale; + AudioControlValue + brightnessMixScale; + + AudioControlValue + volumeScale; + AudioPitchCents + pitchOffset; + AudioControlValue + brightnessScale; + + // + // Execution + // + AudioFrameCount + nextExecuteFrame; + AudioFrameCount + suspendFinishedFrame; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioSource inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +// Location methods +// + +inline AudioLocation* + AudioSource::GetAudioLocation() +{ + Check(this); + return audioLocation; +} + +inline void + AudioSource::UpdateSpatialModel(AudioHead *audio_head) +{ + Check(this); + Check(audioLocation); + audioLocation->UpdateSpatialModel(audio_head); +} + +inline Scalar + AudioSource::GetDistanceToSource() +{ + Check(this); + Check(audioLocation); + return audioLocation->GetDistanceToSource(); +} + +inline Logical + AudioSource::IsAudioSourceClipped(AudioHead *audio_head) +{ + Check(this); + Check(audioLocation); + return audioLocation->IsAudioLocationClipped(audio_head); +} + +// +// Resource methods +// + +inline AudioResource* + AudioSource::GetAudioResource() +{ + Check(this); + return audioResource; +} + +inline AudioVoiceCount + AudioSource::GetAudioVoiceCount() +{ + Check(this); + Check(audioResource); + return audioResource->GetVoiceCount(); +} + +inline AudioRenderType + AudioSource::GetAudioRenderType() +{ + Check(this); + Check(audioResource); + return audioResource->GetAudioRenderType(); +} + +// +// Current State/Status Accessors +// + +inline AudioSourceState + AudioSource::GetAudioSourceState() +{ + Check(this); + return audioSourceState; +} + +inline Logical + AudioSource::IsFinishedPlaying() +{ + Check(this); + return currentStartState.IsFinishedPlaying(); +} + +inline AudioTime + AudioSource::GetCurrentRunningTime() +{ + Check(this); + Verify(audioSourceState == RunningAudioSourceState); + return currentStartState.GetCurrentRunningTime(); +} + +inline AudioControlValue + AudioSource::GetCurrentNoteValue() +{ + Check(this); + return currentStartState.GetNoteValue(); +} + +inline AudioControlValue + AudioSource::CalculateSourceAttackVolumeScale() +{ + Check(this); + return attackVolumeScale; +} + +inline Logical + AudioSource::UseSourceAttackTime() +{ + Check(this); + return useAttackTimeScale; +} + +inline AudioControlValue + AudioSource::CalculateSourceAttackTime() +{ + Check(this); + return attackTimeScale; +} + +// +// Priority Accessors +// + +inline void + AudioSource::SetAudioSourcePriority( + AudioSourcePriority audio_source_priority + ) +{ + Check(this); + audioSourcePriority = audio_source_priority; +} + +inline AudioSourcePriority + AudioSource::GetAudioSourcePriority() +{ + Check(this); + return audioSourcePriority; +} + +inline AudioWeighting + AudioSource::CalculateAudioWeighting() +{ + Check(this); + AudioWeighting + audio_weight( + GetAudioSourcePriority(), + CalculateSourceVolumeScale() + ); + return audio_weight; +} + +// +// Mixing & Logical compression methods +// + +inline AudioSourceMixPresence + AudioSource::GetAudioSourceMixPresence() +{ + Check(this); + return audioSourceMixPresence; +} + +inline void + AudioSource::SetVolumeCompressionScale( + AudioControlValue compression_level + ) +{ + Check(this); + volumeCompressionScale = compression_level; +} + +inline AudioPitchCents + AudioSource::CalculateSourcePitchOffset() +{ + Check(this); + return pitchMixOffset + pitchOffset; +} + +inline Logical + AudioSource::UseSourceBrightnessScale() +{ + Check(this); + return useBrightnessScale; +} + +// +// Execute +// + +inline Logical + AudioSource::RequiresMaintenance(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + return (nextExecuteFrame <= audio_head->GetAudioFrameCount()); +} + +inline Logical + AudioSource::CanResume(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + return (suspendFinishedFrame <= audio_head->GetAudioFrameCount()); +} + +//~~~~~~~~~~~~~~~~~~~~~~ AudioSource__RequestMessage ~~~~~~~~~~~~~~~~~~~~~~~ + +class AudioSource__RequestMessage: + public Receiver::Message +{ +public: + AudioSource__RequestMessage( + Receiver::MessageID id, + size_t message_length, + AudioControlID control_ID, + AudioControlValue control_value + ); + + AudioControlID + controlID; + AudioControlValue + controlValue; +}; + +inline AudioSource__RequestMessage::AudioSource__RequestMessage( + Receiver::MessageID message_ID, + size_t message_length, + AudioControlID control_ID, + AudioControlValue control_value +): + Receiver::Message( + message_ID, + message_length + ) +{ + controlID = control_ID; + controlValue = control_value; +} + +//~~~~~~~~~~~~~~~~~~~~~~ AudioSource__StartMessage ~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AudioSource__StartMessage: + public AudioSource::RequestMessage +{ +public: + AudioSource__StartMessage(AudioControlValue control_value); +}; + +inline AudioSource__StartMessage::AudioSource__StartMessage( + AudioControlValue control_value +): + AudioSource::RequestMessage( + AudioSource::StartMessageID, + sizeof(AudioSource__StartMessage), + StartAudioControlID, + control_value + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~ AudioSource__StopMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AudioSource__StopMessage: + public AudioSource::RequestMessage +{ +public: + AudioSource__StopMessage(); +}; + +inline AudioSource__StopMessage::AudioSource__StopMessage(): + AudioSource::RequestMessage( + AudioSource::StopMessageID, + sizeof(AudioSource__StopMessage), + StopAudioControlID, + 0.0f + ) +{ +} diff --git a/MUNGA/AUDTIME.cpp b/MUNGA/AUDTIME.cpp new file mode 100644 index 0000000..d57951c --- /dev/null +++ b/MUNGA/AUDTIME.cpp @@ -0,0 +1,54 @@ +#include "munga.h" +#pragma hdrstop + +#include "audtime.h" +#include "app.h" +#include "audrend.h" + +//############################################################################# +//############################# AudioTime ############################### +//############################################################################# + +const AudioTime AudioTime::Null; + +// +//############################################################################# +//############################################################################# +// +Logical AudioTime::TestInstance() const +{ + return True; +} + +// +//############################################################################# +//############################################################################# +// +AudioTime AudioTime::Now() +{ + Check(application); + Check(application->GetAudioRenderer()); + return AudioTime(application->GetAudioRenderer()->GetAudioFrameCount()); +} + +// +//############################################################################# +//############################################################################# +// +AudioFrameCount AudioTime::Seconds_To_Frames(Scalar seconds) const +{ + Check(application); + Check(application->GetAudioRenderer()); + return (seconds * application->GetAudioRenderer()->GetCalibrationRate() + 0.5f); +} + +// +//############################################################################# +//############################################################################# +// +Scalar AudioTime::Frames_To_Seconds(AudioFrameCount frames) const +{ + Check(application); + Check(application->GetAudioRenderer()); + return ((Scalar)frames / application->GetAudioRenderer()->GetCalibrationRate()); +} \ No newline at end of file diff --git a/MUNGA/AUDTIME.h b/MUNGA/AUDTIME.h new file mode 100644 index 0000000..c240171 --- /dev/null +++ b/MUNGA/AUDTIME.h @@ -0,0 +1,258 @@ +#pragma once + +#include "scalar.h" +#include "audio.h" + +//########################################################################## +//########################## AudioTime ############################### +//########################################################################## + +class AudioTime SIGNATURED +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + AudioTime(); + AudioTime(const AudioTime&); + AudioTime(Scalar seconds); + AudioTime(AudioFrameCount frame_count); + ~AudioTime(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Assignment +// +public: + AudioTime& + operator=(const AudioTime&); + AudioTime& + operator=(Scalar seconds); + AudioTime& + operator=(AudioFrameCount frame_count); + + operator Scalar() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Logical Operators +// +public: + Logical + operator<(const AudioTime&) const; + Logical + operator<=(const AudioTime&) const; + Logical + operator>(const AudioTime&) const; + Logical + operator>=(const AudioTime&) const; + Logical + operator==(const AudioTime&) const; + Logical + operator!=(const AudioTime&) const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Addition Operators +// +public: + operator AudioFrameCount() const; + + AudioTime + operator+(const AudioTime&) const; + AudioTime + operator-(const AudioTime&) const; + + AudioTime& + operator+=(const AudioTime &t); + AudioTime& + operator-=(const AudioTime &t); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public Constants +// +public: + static const AudioTime + Null; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Current Time +// +public: + static AudioTime + Now(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Methods +// +private: + AudioFrameCount + Seconds_To_Frames(Scalar seconds) const; + Scalar + Frames_To_Seconds(AudioFrameCount frames) const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + AudioFrameCount + frameCount; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioTime inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +// Construction, Destruction, and Testing +// +inline AudioTime::AudioTime(): + frameCount(NullAudioFrameCount) +{ +} + +inline AudioTime::AudioTime(const AudioTime &audio_time): + frameCount(audio_time.frameCount) +{ +} + +inline AudioTime::AudioTime(Scalar seconds) +{ + frameCount = Seconds_To_Frames(seconds); +} + +inline AudioTime::AudioTime(AudioFrameCount frame_count): + frameCount(frame_count) +{ +} + +inline AudioTime::~AudioTime() +{ +} + +// +// Assignment +// +inline AudioTime& + AudioTime::operator=(const AudioTime &audio_time) +{ + Check(this); + Check(&audio_time); + frameCount = audio_time.frameCount; + return *this; +} + +inline AudioTime& + AudioTime::operator=(Scalar seconds) +{ + Check(this); + frameCount = Seconds_To_Frames(seconds); + return *this; +} + +inline AudioTime& + AudioTime::operator=(AudioFrameCount frame_count) +{ + Check(this); + frameCount = frame_count; + return *this; +} + +inline + AudioTime::operator Scalar() const +{ + Check(this); + return Frames_To_Seconds(frameCount); +} + +// +// Logical Operators +// +inline Logical + AudioTime::operator<(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return frameCount < audio_time.frameCount; +} + +inline Logical + AudioTime::operator<=(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return frameCount <= audio_time.frameCount; +} + +inline Logical + AudioTime::operator>(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return frameCount > audio_time.frameCount; +} + +inline Logical + AudioTime::operator>=(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return frameCount >= audio_time.frameCount; +} + +inline Logical + AudioTime::operator==(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return frameCount == audio_time.frameCount; +} + +inline Logical + AudioTime::operator!=(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return frameCount != audio_time.frameCount; +} + +// +// Addition Operators +// +inline AudioTime::operator AudioFrameCount() const +{ + Check(this); + return frameCount; +} + +inline AudioTime + AudioTime::operator+(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return AudioTime(frameCount + audio_time.frameCount); +} + +inline AudioTime + AudioTime::operator-(const AudioTime &audio_time) const +{ + Check(this); + Check(&audio_time); + return AudioTime(frameCount - audio_time.frameCount); +} + +inline AudioTime& + AudioTime::operator+=(const AudioTime &audio_time) +{ + Check(this); + Check(&audio_time); + frameCount += audio_time.frameCount; + return *this; +} + +inline AudioTime& + AudioTime::operator-=(const AudioTime &audio_time) +{ + Check(this); + Check(&audio_time); + frameCount -= audio_time.frameCount; + return *this; +} diff --git a/MUNGA/AUDTOOLS.cpp b/MUNGA/AUDTOOLS.cpp new file mode 100644 index 0000000..4a27cff --- /dev/null +++ b/MUNGA/AUDTOOLS.cpp @@ -0,0 +1,102 @@ +#include "munga.h" +#pragma hdrstop + +#include "audtools.h" + +#include +#include +#include + +#include "audio.h" +#include "boxsolid.h" + +AudioCreateSymbols::AudioCreateSymbols() +{ +} + +AudioCreateSymbols::~AudioCreateSymbols() +{ +} + +void AudioCreateSymbols::MakeFileReadWrite(const CString &file_name) +{ + if (access(file_name, 0) == 0) + { + int amode = S_IREAD|S_IWRITE; + #if DEBUG_LEVEL>0 + int ret = + #endif + chmod(file_name, amode); + Verify(ret == 0); + } +} + +void AudioCreateSymbols::Execute() +{ + CString file_name("audio\\symbols.scp"); + + MakeFileReadWrite(file_name); + + std::ofstream symbol_file(file_name, std::ios::out); + + Verify(symbol_file); + symbol_file << "[macro]\n"; + + WriteEntryStream(symbol_file); +} + +void AudioCreateSymbols::WriteEntryStream(std::ofstream &symbol_file) +{ + #define WRITE_ENTRY(name)\ + {\ + Verify(symbol_file);\ + symbol_file << #name;\ + symbol_file << "=";\ + symbol_file << name;\ + symbol_file << "\n";\ + } + + // + // Solids + // + WRITE_ENTRY(BoxedSolid::StoneMaterial); + WRITE_ENTRY(BoxedSolid::GravelMaterial); + WRITE_ENTRY(BoxedSolid::ConcreteMaterial); + WRITE_ENTRY(BoxedSolid::WoodMaterial); + WRITE_ENTRY(BoxedSolid::RockMaterial); + WRITE_ENTRY(BoxedSolid::OurCraftMaterial); + WRITE_ENTRY(BoxedSolid::OtherCraftMaterial); + + // + // Audio + // + WRITE_ENTRY(TransientAudioRenderType); + WRITE_ENTRY(SustainedAudioRenderType); + + WRITE_ENTRY(MinAudioSourcePriority); + WRITE_ENTRY(LowAudioSourcePriority); + WRITE_ENTRY(MedAudioSourcePriority); + WRITE_ENTRY(HighAudioSourcePriority); + WRITE_ENTRY(MaxAudioSourcePriority); + + WRITE_ENTRY(MinAudioSourceMixPresence); + WRITE_ENTRY(LowAudioSourceMixPresence); + WRITE_ENTRY(MedAudioSourceMixPresence); + WRITE_ENTRY(HighAudioSourceMixPresence); + WRITE_ENTRY(MaxAudioSourceMixPresence); + WRITE_ENTRY(ManualAudioSourceMixPresence); + + WRITE_ENTRY(NullAudioControlID); + WRITE_ENTRY(NoteAudioControlID); + WRITE_ENTRY(AttackVolumeAudioControlID); + WRITE_ENTRY(AttackTimeAudioControlID); + WRITE_ENTRY(DurationAudioControlID); + WRITE_ENTRY(VolumeAudioControlID); + WRITE_ENTRY(PitchAudioControlID); + WRITE_ENTRY(BrightnessAudioControlID); + WRITE_ENTRY(StartAudioControlID); + WRITE_ENTRY(StopAudioControlID); + WRITE_ENTRY(IdleAudioControlID); + WRITE_ENTRY(FlushMessagesAudioControlID); + WRITE_ENTRY(TempoAudioControlID); +} diff --git a/MUNGA/AUDTOOLS.h b/MUNGA/AUDTOOLS.h new file mode 100644 index 0000000..25d70b7 --- /dev/null +++ b/MUNGA/AUDTOOLS.h @@ -0,0 +1,19 @@ +#pragma once + +#include "style.h" +#include "cstr.h" + +class AudioCreateSymbols +{ +public: + AudioCreateSymbols(); + ~AudioCreateSymbols(); + + void Execute(); + +private: + static void MakeFileReadWrite(const CString &file_name); + +protected: + virtual void WriteEntryStream(std::ofstream &symbol_file); +}; diff --git a/MUNGA/AUDWGT.cpp b/MUNGA/AUDWGT.cpp new file mode 100644 index 0000000..3ae4084 --- /dev/null +++ b/MUNGA/AUDWGT.cpp @@ -0,0 +1,12 @@ +#include "munga.h" +#pragma hdrstop + +#include "audwgt.h" + +const AudioWeighting AudioWeighting::Null; + +Logical AudioWeighting::TestInstance() const +{ + return True; +} + diff --git a/MUNGA/AUDWGT.h b/MUNGA/AUDWGT.h new file mode 100644 index 0000000..5b354d8 --- /dev/null +++ b/MUNGA/AUDWGT.h @@ -0,0 +1,128 @@ +#pragma once + +#include "style.h" +#include "audio.h" + +//########################################################################## +//######################## AudioWeighting ############################ +//########################################################################## + +class AudioWeighting SIGNATURED +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + AudioWeighting(); + AudioWeighting(const AudioWeighting&); + AudioWeighting(AudioSourcePriority audio_priority, AudioControlValue audio_volume); + + AudioWeighting& operator=(const AudioWeighting&); + + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Logical Operators +// +public: + Logical operator<(const AudioWeighting&) const; + Logical operator<=(const AudioWeighting&) const; + Logical operator>(const AudioWeighting&) const; + Logical operator>=(const AudioWeighting&) const; + Logical operator==(const AudioWeighting&) const; + Logical operator!=(const AudioWeighting&) const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public Constants +// +public: + static const AudioWeighting Null; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + Scalar weight; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioWeighting inlines ~~~~~~~~~~~~~~~~~~~~~~~ + +inline AudioWeighting::AudioWeighting(): + weight(0.0f) +{ +} + +inline AudioWeighting::AudioWeighting(const AudioWeighting &audio_weighting): + weight(audio_weighting.weight) +{ +} + +inline AudioWeighting::AudioWeighting( + AudioSourcePriority audio_priority, + AudioControlValue audio_volume +) +{ + Verify( + (Enumeration)audio_priority >= 0 && + (Enumeration)audio_priority < AUDIO_SOURCE_PRIORITY_COUNT + ); + Verify( + (Enumeration)audio_priority >= (Enumeration)MinAudioSourcePriority && + (Enumeration)audio_priority <= (Enumeration)MaxAudioSourcePriority + ); + Verify( + audio_volume >= 0.0f && + audio_volume <= 1.0f + ); + weight = 0.0f -(Scalar)audio_priority - audio_volume; +} + +inline AudioWeighting& + AudioWeighting::operator=(const AudioWeighting &audio_weighting) +{ + Check(this); + weight = audio_weighting.weight; + return *this; +} + +inline Logical + AudioWeighting::operator<(const AudioWeighting &audio_weighting) const +{ + Check(this); + return weight < audio_weighting.weight; +} + +inline Logical + AudioWeighting::operator<=(const AudioWeighting &audio_weighting) const +{ + Check(this); + return weight <= audio_weighting.weight; +} + +inline Logical + AudioWeighting::operator>(const AudioWeighting &audio_weighting) const +{ + Check(this); + return weight > audio_weighting.weight; +} + +inline Logical + AudioWeighting::operator>=(const AudioWeighting &audio_weighting) const +{ + Check(this); + return weight >= audio_weighting.weight; +} + +inline Logical + AudioWeighting::operator==(const AudioWeighting &audio_weighting) const +{ + Check(this); + return Close_Enough(weight, audio_weighting.weight, 0.01f); +} + +inline Logical + AudioWeighting::operator!=(const AudioWeighting &audio_weighting) const +{ + Check(this); + return !Close_Enough(weight, audio_weighting.weight, 0.01f); +} diff --git a/MUNGA/AUDWTHR.cpp b/MUNGA/AUDWTHR.cpp new file mode 100644 index 0000000..b360b91 --- /dev/null +++ b/MUNGA/AUDWTHR.cpp @@ -0,0 +1,1048 @@ +#include "munga.h" +#pragma hdrstop + +#include "audwthr.h" +#include "objstrm.h" +#include "namelist.h" + +//############################################################################# +//########################### AudioIdleWatcher ########################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioIdleWatcher::AudioIdleWatcher( + PlugStream *stream, + Entity *entity +): + Component(stream), + audioComponentSocket(this) +{ + AudioComponent *audio_component; + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + AudioIdleWatcherX(audio_component, entity); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::AudioIdleWatcherX( + AudioComponent *audio_component, + Entity *entity + ) +{ + Check(audio_component); + Check(entity); + audioComponentSocket.Add(audio_component); + entity->AddAudioWatcher(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioIdleWatcher::~AudioIdleWatcher() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Component::BuildFromPage(stream, name_list, class_ID, object_ID); + + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID(stream, name_list, audio_component_name); +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioIdleWatcher::TestInstance() const +{ + Component::TestInstance(); + Check(&audioComponentSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::ReleaseLinkHandler( + Socket *socket, + Plug *plug + ) +{ + if (socket == &audioComponentSocket) + { + Check(&audioComponentSocket); + Check(socket); + Unregister_Object(this); + delete this; + } + else + { + Component::ReleaseLinkHandler(socket, plug); + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIdleWatcher::Execute() +{ + Check(this); + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + IdleAudioControlID, + 0.0f + ); +} + +//############################################################################# +//############################## AudioMotionTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioMotionTrigger::AudioMotionTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + MemoryStream_Read(stream, &motionType); + MemoryStream_Read(stream, &motionValue); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioMotionTrigger::~AudioMotionTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioMotionTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_type); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_value); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioMotionTrigger::ExtractInterestingValue(const Motion *attribute_ptr) +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->linearMotion.x; + case YMotionValue: + return attribute_ptr->linearMotion.y; + case ZMotionValue: + return attribute_ptr->linearMotion.z; + case LengthMotionValue: + return attribute_ptr->linearMotion.Length(); + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->angularMotion.x; + case YMotionValue: + return attribute_ptr->angularMotion.y; + case ZMotionValue: + return attribute_ptr->angularMotion.z; + case LengthMotionValue: + return attribute_ptr->angularMotion.Length(); + } + break; + } + + Fail("AudioMotionTrigger::ExtractInterestingValue - Should never reach here"); + return 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioMotionTrigger::DumpValue(const Motion *attribute_ptr) +#else +void + AudioMotionTrigger::DumpValue(const Motion*) +#endif +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->linearMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->linearMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->linearMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->linearMotion.Length()); + break; + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->angularMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->angularMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->angularMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->angularMotion.Length()); + break; + } + break; + } +} + +//############################################################################# +//############################## AudioMotionScale ####################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioMotionScale::AudioMotionScale( + PlugStream *stream, + Entity *entity +): + AudioScaleOf(stream, entity) +{ + MemoryStream_Read(stream, &motionType); + MemoryStream_Read(stream, &motionValue); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioMotionScale::~AudioMotionScale() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioMotionScale::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioScaleOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_type); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, motion_value); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioMotionScale::ExtractInterestingValue(const Motion *attribute_ptr) +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->linearMotion.x; + case YMotionValue: + return attribute_ptr->linearMotion.y; + case ZMotionValue: + return attribute_ptr->linearMotion.z; + case LengthMotionValue: + return attribute_ptr->linearMotion.Length(); + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + return attribute_ptr->angularMotion.x; + case YMotionValue: + return attribute_ptr->angularMotion.y; + case ZMotionValue: + return attribute_ptr->angularMotion.z; + case LengthMotionValue: + return attribute_ptr->angularMotion.Length(); + } + break; + } + + Fail("AudioMotionScale::ExtractInterestingValue - Should never reach here"); + return 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioMotionScale::DumpValue(const Motion *attribute_ptr) +#else +void + AudioMotionScale::DumpValue(const Motion*) +#endif +{ + Check(this); + Check(attribute_ptr); + + switch (motionType) + { + case LinearMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->linearMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->linearMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->linearMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->linearMotion.Length()); + break; + } + break; + + case AngularMotionType: + switch (motionValue) + { + case XMotionValue: + Dump(attribute_ptr->angularMotion.x); + break; + case YMotionValue: + Dump(attribute_ptr->angularMotion.y); + break; + case ZMotionValue: + Dump(attribute_ptr->angularMotion.z); + break; + case LengthMotionValue: + Dump(attribute_ptr->angularMotion.Length()); + break; + } + break; + } +} + +//############################################################################# +//############################## AudioHingeScale ######################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioHingeScale::AudioHingeScale( + PlugStream *stream, + Entity *entity +): + AudioScaleOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioHingeScale::~AudioHingeScale() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioHingeScale::ExtractInterestingValue(const Hinge *attribute_ptr) +{ + Check(this); + Check(attribute_ptr); + return attribute_ptr->rotationAmount; +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + AudioHingeScale::DumpValue(const Hinge *attribute_ptr) +#else +void + AudioHingeScale::DumpValue(const Hinge*) +#endif +{ + Check(this); + Check(attribute_ptr); + Dump(attribute_ptr->rotationAmount); +} + +//############################################################################# +//############################## AudioScalarTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioScalarTrigger::AudioScalarTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioScalarTrigger::~AudioScalarTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioScalarTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioScalarTrigger::ExtractInterestingValue(const Scalar *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//####################### AudioScalarDeltaTrigger ####################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioScalarDeltaTrigger::AudioScalarDeltaTrigger( + PlugStream *stream, + Entity *entity +): + AudioDeltaOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioScalarDeltaTrigger::~AudioScalarDeltaTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioScalarDeltaTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioDeltaOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +//############################################################################# +//############################## AudioScalarScale ####################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioScalarScale::AudioScalarScale( + PlugStream *stream, + Entity *entity +): + AudioScaleOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioScalarScale::~AudioScalarScale() +{ +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioScalarScale::ExtractInterestingValue(const Scalar *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//######################### AudioLogicalTrigger ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioLogicalTrigger::AudioLogicalTrigger( + PlugStream *stream, + Entity *entity +): + AudioMatchOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioLogicalTrigger::~AudioLogicalTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioLogicalTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioMatchOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +int + AudioLogicalTrigger::ExtractInterestingValue(const Logical *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//######################### AudioEnumerationTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationTrigger::AudioEnumerationTrigger( + PlugStream *stream, + Entity *entity +): + AudioMatchOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationTrigger::~AudioEnumerationTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioEnumerationTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioMatchOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +int + AudioEnumerationTrigger::ExtractInterestingValue(const Enumeration *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//###################### AudioEnumerationDeltaTrigger ################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationDeltaTrigger::AudioEnumerationDeltaTrigger( + PlugStream *stream, + Entity *entity +): + AudioDeltaOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioEnumerationDeltaTrigger::~AudioEnumerationDeltaTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioEnumerationDeltaTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioDeltaOf::BuildFromPage( + stream, + name_list, + class_ID, + object_ID + ); +} + +//############################################################################# +//############################# AudioIntegerTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioIntegerTrigger::AudioIntegerTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioIntegerTrigger::~AudioIntegerTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioIntegerTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioIntegerTrigger::ExtractInterestingValue(const int *attribute_ptr) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//###################### AudioControlsButtonTrigger ##################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioControlsButtonTrigger::AudioControlsButtonTrigger( + PlugStream *stream, + Entity *entity +): + AudioTriggerOf(stream, entity) +{ + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlsButtonTrigger::~AudioControlsButtonTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioControlsButtonTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioTriggerOf::BuildFromPage( + stream, + name_list, + class_ID, + object_ID + ); +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + AudioControlsButtonTrigger::ExtractInterestingValue( + const ControlsButton *attribute_ptr + ) +{ + Check(this); + Check_Pointer(attribute_ptr); + return *attribute_ptr; +} + +//############################################################################# +//########################### AudioStateWatcher ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioStateWatcher::AudioStateWatcher( + PlugStream *stream, + Entity *entity +): + AudioWatcherOf(stream, entity) +{ + Check_Pointer(attributePointer); + Cast_Object(StateIndicator*, attributePointer)->AddAudioWatcher(this); +} + +// +//############################################################################# +//############################################################################# +// +AudioStateWatcher::~AudioStateWatcher() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateWatcher::SendNotificationOfChange() +{ + Check(this); + + StateIndicator *state_indicator = GetCurrentPointer(); + + Check(state_indicator); + StateChanged( + state_indicator->GetOldState(), + state_indicator->GetState() + ); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateWatcher::StateChanged( + Enumeration, + Enumeration + ) +{ + Fail("AudioStateWatcher::StateChanged - Should never reach here"); +} + +//############################################################################# +//############################## AudioStateTrigger ###################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AudioStateTrigger::AudioStateTrigger( + PlugStream *stream, + Entity *entity +): + AudioStateWatcher(stream, entity) +{ + MemoryStream_Read(stream, &triggerState); + MemoryStream_Read(stream, &inverseTrigger); + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + MemoryStream_Read(stream, &excludeTransition); + MemoryStream_Read(stream, &excludeState); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +AudioStateTrigger::~AudioStateTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioStateWatcher::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Write standard fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, trigger_state); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, inverse_trigger); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value); + + // + // Write optional fields + // + Logical exclude_transition = False; + Enumeration exclude_state = 0; + + if ((name_list)->FindData("exclude_state") != NULL) + { + exclude_transition = True; + Check_Pointer((name_list)->FindData("exclude_state")); + Convert_From_Ascii( + (const char *)(name_list)->FindData("exclude_state"), + &exclude_state + ); + } + MemoryStream_Write(stream, &exclude_transition); + MemoryStream_Write(stream, &exclude_state); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioStateTrigger::StateChanged( + Enumeration old_state, + Enumeration new_state + ) +{ + Check(this); + + // + // If the exclude switch is on then check for the transition + // + if (excludeTransition) + { + if ( + !inverseTrigger && + new_state == triggerState && + old_state == excludeState + ) + { + return; + } + if ( + inverseTrigger && + old_state == triggerState && + new_state == excludeState + ) + { + return; + } + } + + // + // Check for the trigger state + // + if ( + (!inverseTrigger && new_state == triggerState) || + (inverseTrigger && old_state == triggerState) + ) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + controlValue + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlID, + controlValue + ); + #endif + } +} diff --git a/MUNGA/AUDWTHR.h b/MUNGA/AUDWTHR.h new file mode 100644 index 0000000..0ed3634 --- /dev/null +++ b/MUNGA/AUDWTHR.h @@ -0,0 +1,1557 @@ +#pragma once + +#include "watcher.h" +#include "audio.h" +#include "simulate.h" +#include "objstrm.h" +#include "controls.h" +#include "motion.h" + +//########################################################################## +//######################## AudioIdleWatcher ########################## +//########################################################################## + +class AudioIdleWatcher: + public Component +{ +public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor, Testing + //----------------------------------------------------------------------- + // + AudioIdleWatcher( + PlugStream *stream, + Entity *entity + ); + void + AudioIdleWatcherX( + AudioComponent *audio_component, + Entity *entity + ); + ~AudioIdleWatcher(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // ReleaseLinkHandler + //----------------------------------------------------------------------- + // + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + void + Execute(); + +protected: + // + //----------------------------------------------------------------------- + // Protected data + //----------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; +}; + +//########################################################################## +//########################### AudioWatcherOf ######################### +//########################################################################## + +template class AudioWatcherOf: + public AttributeWatcherOf +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioWatcherOf( + PlugStream *stream, + Entity *entity + ); + ~AudioWatcherOf(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //-------------------------------------------------------------------- + // ReleaseLinkHandler + //-------------------------------------------------------------------- + // + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + +protected: + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + SlotOf + audioComponentSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ AudioWatcherOf templates ~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioWatcherOf::AudioWatcherOf( + PlugStream *stream, + Entity *entity + ): + AttributeWatcherOf(stream, entity), + audioComponentSocket(this) +{ + // + // Get audio component + // + AudioComponent *audio_component; + PlugStream_ReadObjectIDAndFindPlug(stream, &audio_component); + Check(audio_component); + audioComponentSocket.Add(audio_component); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioWatcherOf::~AudioWatcherOf() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioWatcherOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AttributeWatcherOf::BuildFromPage( + stream, name_list, class_ID, object_ID + ); + + // + // Store audio_component object ID + // + CString audio_component_name("audio_component"); + PlugStream_FindEntryAndWriteObjectID( + stream, name_list, audio_component_name + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template Logical + AudioWatcherOf::TestInstance() const +{ + AttributeWatcherOf::TestInstance(); + Check(&audioComponentSocket); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioWatcherOf::ReleaseLinkHandler( + Socket *socket, + Plug *plug + ) +{ + if (socket == &audioComponentSocket) + { + Check(&audioComponentSocket); + Check(socket); + Unregister_Object(this); + delete this; + } + else + { + AttributeWatcherOf::ReleaseLinkHandler(socket, plug); + } +} + +//########################################################################## +//########################### AudioTriggerOf ######################### +//########################################################################## + +template class AudioTriggerOf: + public AudioWatcherOf +{ +public: + // + //-------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------- + // + AudioTriggerOf( + PlugStream *stream, + Entity *entity + ); + ~AudioTriggerOf(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //-------------------------------------------------------------------- + // SendNotificationOfChange + //-------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + virtual AudioControlValue + ExtractInterestingValue(const T *attribute_ptr); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Scalar + attributeValueThreshold; + Logical + inverseTrigger; + AudioControlID + controlIDOn, + controlIDOff; + AudioControlValue + controlValueOn, + controlValueOff; + Logical + triggerOn; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioTriggerOf templates ~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioTriggerOf::AudioTriggerOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) +{ + Check(simulation); + simulation->AddAudioWatcher(this); + + // + // Get other fields + // + MemoryStream_Read(stream, &attributeValueThreshold); + MemoryStream_Read(stream, &inverseTrigger); + + MemoryStream_Read(stream, &controlIDOn); + MemoryStream_Read(stream, &controlIDOff); + + MemoryStream_Read(stream, &controlValueOn); + MemoryStream_Read(stream, &controlValueOff); + + triggerOn = False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioTriggerOf::~AudioTriggerOf() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioTriggerOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store other fields + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, attribute_value_threshold + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Logical, inverse_trigger + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID_on + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID_off + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_on + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_off + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioTriggerOf::SendNotificationOfChange() +{ + // + // Get current value + // + T *attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + Scalar current_value = ExtractInterestingValue(attribute_ptr); + + if (triggerOn) + { + if ( + (!inverseTrigger && current_value <= attributeValueThreshold) || + (inverseTrigger && current_value >= attributeValueThreshold) + ) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlIDOff, + controlValueOff + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlIDOff, + controlValueOff + ); + #endif + triggerOn = False; + } + } + else + { + if ( + (!inverseTrigger && current_value > attributeValueThreshold) || + (inverseTrigger && current_value < attributeValueThreshold) + ) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlIDOn, + controlValueOn + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlIDOn, + controlValueOn + ); + #endif + triggerOn = True; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template AudioControlValue + AudioTriggerOf::ExtractInterestingValue(const T*) +{ + Fail("AudioTriggerOf::ExtractInterestingValue - Should never reach here"); + return 0; +} + +//########################################################################## +//########################### AudioScaleOf ########################### +//########################################################################## + +template class AudioScaleOf: + public AudioWatcherOf +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor + //-------------------------------------------------------------------- + // + AudioScaleOf( + PlugStream *stream, + Entity *entity + ); + ~AudioScaleOf(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //-------------------------------------------------------------------- + // SendNotificationOfChange + //-------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + virtual AudioControlValue + ExtractInterestingValue(const T *attribute_ptr); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Scalar + attributeValueBoundary1, + attributeValueBoundary2; + AudioControlID + controlID; + AudioControlValue + controlValueBoundary1, + controlValueBoundary2; + Scalar + exponent; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioScaleOf templates ~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioScaleOf::AudioScaleOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) +{ + // + // Get audio component + // + AudioComponent *audio_component = audioComponentSocket.GetCurrent(); + Check(audio_component); + audio_component->AddWatcher(this); + + // + // Get other fields + // + MemoryStream_Read(stream, &attributeValueBoundary1); + MemoryStream_Read(stream, &attributeValueBoundary2); + + MemoryStream_Read(stream, &controlID); + + MemoryStream_Read(stream, &controlValueBoundary1); + MemoryStream_Read(stream, &controlValueBoundary2); + MemoryStream_Read(stream, &exponent); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioScaleOf::~AudioScaleOf() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioScaleOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store other fields + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Scalar, attribute_value_boundary1 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Scalar, attribute_value_boundary2 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_boundary1 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value_boundary2 + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Scalar, exponent + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioScaleOf::SendNotificationOfChange() +{ + // + // Get current value + // + T *attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + Scalar current_value = ExtractInterestingValue(attribute_ptr); + + // + // Clamp value within range + // + Scalar min_attribute_boundary = + Min(attributeValueBoundary1, attributeValueBoundary2); + Scalar max_attribute_boundary = + Max(attributeValueBoundary1, attributeValueBoundary2); + + Clamp(current_value, min_attribute_boundary, max_attribute_boundary); + Verify( + current_value >= min_attribute_boundary && + current_value <= max_attribute_boundary + ); + + // + // Calculate scale + // + Verify(!Small_Enough(attributeValueBoundary2 - attributeValueBoundary1)); + Scalar current_scale = + (current_value - attributeValueBoundary1) / + (attributeValueBoundary2 - attributeValueBoundary1); + Verify(current_scale >= -1.0f && current_scale <= 1.0f); + + // + // Apply exponent + // + if (exponent != 1.0f) + { + Scalar old_scale = current_scale; // HACK - for debugging + + current_scale = pow(old_scale, exponent); + + #if DEBUG_LEVEL>0 + if (!(current_scale >= -1.0f && current_scale <= 1.0f)) + { + Dump(old_scale); + Dump(exponent); + Dump(current_scale); + } + #endif + } + Verify(current_scale >= -1.0f && current_scale <= 1.0f); + + // + // Calculate control value + // + AudioControlValue control_value = + current_scale * (controlValueBoundary2 - controlValueBoundary1) + + controlValueBoundary1; + + #if DEBUG_LEVEL>0 + AudioControlValue min_control_boundary = + Min(controlValueBoundary1, controlValueBoundary2); + AudioControlValue max_control_boundary = + Max(controlValueBoundary1, controlValueBoundary2); + + Verify( + control_value >= min_control_boundary && + control_value <= max_control_boundary + ); + #endif + + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + control_value + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template AudioControlValue + AudioScaleOf::ExtractInterestingValue(const T*) +{ + Fail("AudioScaleOf::ExtractInterestingValue - Should never reach here"); + return 0; +} + +//########################################################################## +//########################## AudioMatchOf ############################ +//########################################################################## + +template class AudioMatchOf: + public AudioWatcherOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioMatchOf( + PlugStream *stream, + Entity *entity + ); + ~AudioMatchOf(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // SendNotificationOfChange + //----------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + virtual int + ExtractInterestingValue(const T *attribute_ptr); + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + int + attributeMatchValue; + AudioControlID + controlID; + AudioControlValue + controlValue; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioMatchOf templates ~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioMatchOf::AudioMatchOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) +{ + Check(simulation); + simulation->AddAudioWatcher(this); + + // + // Get other fields + // + MemoryStream_Read(stream, &attributeMatchValue); + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioMatchOf::~AudioMatchOf() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioMatchOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store other fields + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, int, attribute_match_value + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioMatchOf::SendNotificationOfChange() +{ + // + // Get current value + // + T *attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + int current_value = ExtractInterestingValue(attribute_ptr); + + if (current_value == attributeMatchValue) + { + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + controlValue + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlID, + controlValue + ); + #endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template int + AudioMatchOf::ExtractInterestingValue(const T*) +{ + Fail("AudioMatchOf::ExtractInterestingValue - Should never reach here"); + return 0; +} + +//########################################################################## +//########################## AudioDeltaOf ############################ +//########################################################################## + +template class AudioDeltaOf: + public AudioWatcherOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioDeltaOf( + PlugStream *stream, + Entity *entity + ); + ~AudioDeltaOf(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // SendNotificationOfChange + //----------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + T + lastValue; + T + deltaTrigger; + AudioControlID + controlID; + AudioControlValue + controlValue; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioDeltaOf templates ~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioDeltaOf::AudioDeltaOf( + PlugStream *stream, + Entity *entity + ): + AudioWatcherOf(stream, entity) +{ + Check(simulation); + simulation->AddAudioWatcher(this); + + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + MemoryStream_Read(stream, &deltaTrigger); + + lastValue = GetCurrentValue(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AudioDeltaOf::~AudioDeltaOf() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioDeltaOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioWatcherOf::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // control_ID, control_value + // + MEM_STRM_WRITE_ENTRY( + *stream, name_list, Enumeration, control_ID + ); + MEM_STRM_WRITE_ENTRY( + *stream, name_list, AudioControlValue, control_value + ); + + // + // delta_value + // + T delta_trigger = SMALL; + + if (name_list->FindData("delta_trigger") != NULL) + { + Convert_From_Ascii( + (const char *)name_list->FindData("delta_trigger"), + &delta_trigger + ); + } + MemoryStream_Write(stream, &delta_trigger); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AudioDeltaOf::SendNotificationOfChange() +{ + T *attribute_ptr; + T delta_change; + + attribute_ptr = GetCurrentPointer(); + Check_Pointer(attribute_ptr); + delta_change = *attribute_ptr - lastValue; + + if (Abs(delta_change) >= deltaTrigger) + { + lastValue = *attribute_ptr; + + Check(&audioComponentSocket); + Check(audioComponentSocket.GetCurrent()); + #if 1 + audioComponentSocket.GetCurrent()->ReceiveControl( + controlID, + controlValue + ); + #else + audioComponentSocket.GetCurrent()->PostReceiveControl( + controlID, + controlValue + ); + #endif + } +} + +//########################################################################## +//########################### AudioMotionTrigger ##################### +//########################################################################## + +enum MotionType +{ + LinearMotionType = 0, + AngularMotionType = 1 +}; + +inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + MotionType *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} +inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const MotionType *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + +enum MotionValue +{ + XMotionValue = 0, + YMotionValue = 1, + ZMotionValue = 2, + LengthMotionValue = 3 +}; + +inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + MotionValue *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} +inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const MotionValue *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + +class AudioMotionTrigger: + public AudioTriggerOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioMotionTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioMotionTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Motion *attribute_ptr); + +private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const Motion *attribute_ptr); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + MotionType + motionType; + MotionValue + motionValue; +}; + +//########################################################################## +//########################### AudioMotionScale ####################### +//########################################################################## + +class AudioMotionScale: + public AudioScaleOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioMotionScale( + PlugStream *stream, + Entity *entity + ); + ~AudioMotionScale(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Motion *attribute_ptr); + +private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const Motion *attribute_ptr); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + MotionType + motionType; + MotionValue + motionValue; +}; + +//########################################################################## +//########################### AudioHingeScale ######################### +//########################################################################## + +class AudioHingeScale: + public AudioScaleOf +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioHingeScale( + PlugStream *stream, + Entity *entity + ); + ~AudioHingeScale(); + +protected: + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Hinge *attribute_ptr); + +private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const Hinge *attribute_ptr); +}; + +//########################################################################## +//########################### AudioScalarTrigger ##################### +//########################################################################## + +class AudioScalarTrigger: + public AudioTriggerOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioScalarTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioScalarTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Scalar *attribute_ptr); +}; + +//########################################################################## +//###################### AudioScalarDeltaTrigger ##################### +//########################################################################## + +class AudioScalarDeltaTrigger: + public AudioDeltaOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioScalarDeltaTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioScalarDeltaTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); +}; + +//########################################################################## +//########################### AudioScalarScale ######################## +//########################################################################## + +class AudioScalarScale: + public AudioScaleOf +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioScalarScale( + PlugStream *stream, + Entity *entity + ); + ~AudioScalarScale(); + +protected: + // + //-------------------------------------------------------------------- + // ExtractInterestingValue + //-------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const Scalar *attribute_ptr); +}; + +//########################################################################## +//######################## AudioLogicalTrigger ####################### +//########################################################################## + +class AudioLogicalTrigger: + public AudioMatchOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioLogicalTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioLogicalTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + int + ExtractInterestingValue(const Logical *attribute_ptr); +}; + +//########################################################################## +//###################### AudioEnumerationTrigger ##################### +//########################################################################## + +class AudioEnumerationTrigger: + public AudioMatchOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioEnumerationTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioEnumerationTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + int + ExtractInterestingValue(const Enumeration *attribute_ptr); +}; + +//########################################################################## +//################### AudioEnumerationDeltaTrigger ################### +//########################################################################## + +class AudioEnumerationDeltaTrigger: + public AudioDeltaOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioEnumerationDeltaTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioEnumerationDeltaTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); +}; + +//########################################################################## +//####################### AudioIntegerTrigger ######################## +//########################################################################## + +class AudioIntegerTrigger: + public AudioTriggerOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioIntegerTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioIntegerTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const int *attribute_ptr); +}; + +//########################################################################## +//################### AudioControlsButtonTrigger ##################### +//########################################################################## + +class AudioControlsButtonTrigger: + public AudioTriggerOf +{ +public: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AudioControlsButtonTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioControlsButtonTrigger(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //----------------------------------------------------------------------- + // ExtractInterestingValue + //----------------------------------------------------------------------- + // + AudioControlValue + ExtractInterestingValue(const ControlsButton *attribute_ptr); +}; + +//########################################################################## +//######################## AudioStateWatcher ######################### +//########################################################################## + +class AudioStateWatcher: + public AudioWatcherOf +{ +public: + // + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + // + ~AudioStateWatcher(); + +protected: + // + //-------------------------------------------------------------------- + // Constructor + //-------------------------------------------------------------------- + // + AudioStateWatcher( + PlugStream *stream, + Entity *entity + ); + + // + //-------------------------------------------------------------------- + // SendNotificationOfChange + //-------------------------------------------------------------------- + // + void + SendNotificationOfChange(); + + // + //-------------------------------------------------------------------- + // StateChanged + //-------------------------------------------------------------------- + // + virtual void + StateChanged( + Enumeration old_state, + Enumeration new_state + ); +}; + +//########################################################################## +//########################### AudioStateTrigger ###################### +//########################################################################## + +class AudioStateTrigger: + public AudioStateWatcher +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor + //-------------------------------------------------------------------- + // + AudioStateTrigger( + PlugStream *stream, + Entity *entity + ); + ~AudioStateTrigger(); + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //-------------------------------------------------------------------- + // StateChanged + //-------------------------------------------------------------------- + // + void + StateChanged( + Enumeration old_state, + Enumeration new_state + ); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Enumeration + triggerState; + Logical + inverseTrigger; + AudioControlID + controlID; + AudioControlValue + controlValue; + Logical + excludeTransition; + Enumeration + excludeState; +}; diff --git a/MUNGA/AVERAGE.cpp b/MUNGA/AVERAGE.cpp new file mode 100644 index 0000000..f15e492 --- /dev/null +++ b/MUNGA/AVERAGE.cpp @@ -0,0 +1,4 @@ +#include "munga.h" +#pragma hdrstop + +#include "average.h" \ No newline at end of file diff --git a/MUNGA/AVERAGE.h b/MUNGA/AVERAGE.h new file mode 100644 index 0000000..d565508 --- /dev/null +++ b/MUNGA/AVERAGE.h @@ -0,0 +1,298 @@ +#pragma once + +#include "style.h" + +//########################################################################## +//########################### AverageOf ############################## +//########################################################################## + +template class AverageOf SIGNATURED +{ +public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor, Testing + //----------------------------------------------------------------------- + // + AverageOf(); + AverageOf( + size_t size, + T initial=(T)0 + ); + ~AverageOf(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // SetSize + //----------------------------------------------------------------------- + // + void + SetSize( + size_t size, + T initial=(T)0 + ); + + // + //----------------------------------------------------------------------- + // Add + //----------------------------------------------------------------------- + // + void + Add(T value); + + // + //----------------------------------------------------------------------- + // CalculateAverage + //----------------------------------------------------------------------- + // + T + CalculateAverage(); + + // + //----------------------------------------------------------------------- + // CalculateOlympicAverage + //----------------------------------------------------------------------- + // + T + CalculateOlympicAverage(); + + // + //----------------------------------------------------------------------- + // Calculate Trend of Average + //----------------------------------------------------------------------- + // + Scalar + CalculateTrend(); + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + size_t size; + size_t next; + T *array; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AverageOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AverageOf::AverageOf() +{ + array = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AverageOf::AverageOf( + size_t the_size, + T initial + ) +{ + array = NULL; + SetSize(the_size, initial); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AverageOf::SetSize( + size_t the_size, + T initial + ) +{ + if (array != NULL) + { + Unregister_Pointer(array); + delete[] array; + } + + size = the_size; + array = new T[size]; + Register_Pointer(array); + next = 0; + + for (size_t i = 0; i < size; i++) + { + Check_Pointer(array); + Verify(i < size); + array[i] = initial; + Check_Fpu(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AverageOf::~AverageOf() +{ + Unregister_Pointer(array); + delete[] array; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template Logical + AverageOf::TestInstance() const +{ + Check_Pointer(array); + Verify(next < size); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AverageOf::Add(T value) +{ + Check(this); + Check_Pointer(array); + Verify(next < size); + array[next] = value; + ++next; + if (next >= size) + { + Verify(next == size); + next = 0; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template T + AverageOf::CalculateAverage() +{ + Check(this); + size_t i; + T accumulate; + + for (i = 0, accumulate = (T)0; i < size; i++) + { + Check_Pointer(array); + Verify(i < size); + accumulate += array[i]; + Check_Fpu(); + } + + Verify(!Small_Enough((T)size)); + return (accumulate / (T)size); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template T + AverageOf::CalculateOlympicAverage() +{ + Check(this); + size_t i; + T accumulate, min_value, max_value; + + Verify(0 < size); + min_value = array[0]; + max_value = array[0]; + Check_Fpu(); + + for (i = 0, accumulate = (T)0; i < size; i++) + { + Check_Pointer(array); + Verify(i < size); + accumulate += array[i]; + Check_Fpu(); + + min_value = Min(array[i], min_value); + max_value = Max(array[i], max_value); + Check_Fpu(); + } + accumulate -= min_value; + accumulate -= max_value; + Check_Fpu(); + + Verify(!Small_Enough((T)(size - 2))); + return (accumulate / (T)(size - 2)); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template Scalar + AverageOf::CalculateTrend() +{ + Check(this); + size_t i; + Scalar f = 0.0f; + Scalar fx = 0.0f; + Scalar x1 = size; + Scalar x2 = x1*x1/2.0f; + Scalar x3 = x2 + x1*x1*x1/3.0f + x1/6.0f; + x2 += x1/2.0f; + + i = next; + Scalar t = 1.0f; + do + { + f += array[i]; + fx += t*array[i]; + t += 1.0f; + if (++i == size) + { + i = 0; + } + } while (i != next); + return (x1*fx - x2*f) / (x1*x3 - x2*x2); +} + +//########################################################################## +//######################## StaticAverageOf ########################### +//########################################################################## + +template class StaticAverageOf SIGNATURED +{ +public: + // + //----------------------------------------------------------------------- + // Constructor, Destructor, Testing + //----------------------------------------------------------------------- + // + StaticAverageOf() + {size = (T)0; total = (T)0;} + ~StaticAverageOf() + {} + + Logical + TestInstance() const + {return True;} + + // + //----------------------------------------------------------------------- + // Add + //----------------------------------------------------------------------- + // + void + Add(T value) + {Check(this); size++; total += value;} + + // + //----------------------------------------------------------------------- + // CalculateAverage + //----------------------------------------------------------------------- + // + T + CalculateAverage() + {Check(this); return (size == 0) ? ((T)0) : (total / (T)size);} + + // + //----------------------------------------------------------------------- + // GetSize + //----------------------------------------------------------------------- + // + size_t + GetSize() + {Check(this); return size;} + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + size_t size; + T total; +}; diff --git a/MUNGA/BNDGBOX.cpp b/MUNGA/BNDGBOX.cpp new file mode 100644 index 0000000..05a24cc --- /dev/null +++ b/MUNGA/BNDGBOX.cpp @@ -0,0 +1,435 @@ +#include "munga.h" +#pragma hdrstop + +#include "bndgbox.h" +#include "origin.h" +#include "line.h" + +//############################################################################# +//############################## BoundingBox ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox::BoundingBox(const ExtentBox &extents): + ExtentBox(extents) +{ + Check_Pointer(this); + Check(&extents); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox::BoundingBox() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void + BoundingBox::PlaceBoundingBox(const Origin& origin) +{ + Check(this); + Check(&origin); + + Dump(origin); + + minX += origin.linearPosition.x; + maxX += origin.linearPosition.x; + minY += origin.linearPosition.y; + maxY += origin.linearPosition.y; + minZ += origin.linearPosition.z; + maxZ += origin.linearPosition.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox::~BoundingBox() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::Intersects(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + if (ExtentBox::Intersects(extents)) + { + ExtentBox slice; + slice.Intersect(*this, extents); + return IntersectsBounded(slice); + } + else + { + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::Intersects( + const ExtentBox &extents, + ExtentBox *slice + ) +{ + Check(this); + Check(&extents); + Check_Pointer(slice); + + if (ExtentBox::Intersects(extents)) + { + slice->Intersect(*this, extents); + return IntersectsBounded(*slice); + } + else + { + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::Contains(const Point3D &point) +{ + Check(this); + Check(&point); + + if (ExtentBox::Contains(point)) + { + return ContainsBounded(point); + } + else + { + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoundingBox::FindDistanceBelow(const Point3D &point) +{ + Check(this); + Check(&point); + + if ( + minX <= point.x && maxX >= point.x && minY <= point.y + && minZ <= point.z && maxZ >= point.z + ) + { + return FindDistanceBelowBounded(point); + } + else + { + return -1.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::HitBy(Line *line) +{ + Check(this); + Check(line); + + Scalar + enter, + leave, + perpendicular, + drift, + distance; + + // + //-------------------- + // Set up for the test + //-------------------- + // + Logical entered = False; + Logical left = False; + for (int i=0; i<6; ++i) + { + // + //-------------------------------------------------------------------- + // Figure out what axis we are dealing with, then based upon the + // direction of the face, find out the distance from the origin to the + // place against the normal, and find out how fast the perpendicular + // distance changes with a unit movement along the line + //-------------------------------------------------------------------- + // + int face = i; + int axis = face >> 1; + if (face&1) + { + perpendicular = line->origin[axis] - (*this)[face]; + drift = line->direction[axis]; + } + else + { + perpendicular = (*this)[face] - line->origin[axis]; + drift = -line->direction[axis]; + } + + // + //------------------------------------------------------------------- + // If the line is parallel to the face, figure out whether or not the + // line origin lies within the face's half-space + //------------------------------------------------------------------- + // + if (Small_Enough(drift)) + { + if (perpendicular > 0.0f) + { + return False; + } + else + { + continue; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + distance = -perpendicular / drift; + if (drift < 0.0f) + { + if (!entered) + { + entered = True; + enter = distance; + } + else if (distance > enter) + { + enter = distance; + } + if (enter > line->length) + { + return False; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + else + { + if (!left) + { + left = True; + leave = distance; + } + else if (distance < leave) + { + leave = distance; + } + if (leave < 0.0f) + { + return False; + } + } + } + + // + //----------------------------------------------------------------------- + // If we exit the loop, then make sure that we actually hit the interior, + // and let the box figure out if the what happens inside it + //----------------------------------------------------------------------- + // + if (enter <= leave) + { + return HitByBounded(line, enter, leave); + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical +#if DEBUG_LEVEL>0 + BoundingBox::IntersectsBounded(const ExtentBox &extents) +#else + BoundingBox::IntersectsBounded(const ExtentBox &) +#endif +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical +#if DEBUG_LEVEL>0 + BoundingBox::ContainsBounded(const Point3D &point) +#else + BoundingBox::ContainsBounded(const Point3D &) +#endif +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoundingBox::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + Scalar result = point.y - maxY; + return Max(result, 0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::HitByBounded( + Line *line, + Scalar enters, +#if DEBUG_LEVEL>0 + Scalar leaves +#else + Scalar +#endif + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBox::TestInstance() const +{ + return True; +} + +//############################################################################# +//######################### BoundingBoxCollision ######################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxCollision::TestInstance() const +{ + return True; +} + +//############################################################################# +//####################### BoundingBoxCollisionList ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxCollisionList::BoundingBoxCollisionList(int max_length) +{ + listStart = new BoundingBoxCollision[max_length]; + Register_Pointer(listStart); + maxCollisions = max_length; + Reset(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxCollisionList::AddCollisionToList( + BoundingBox *tree_volume, + const ExtentBox &slice + ) +{ + Check(tree_volume); + Check(&slice); + Check(this); + Check_Pointer(nextCollision); + Verify(collisionsLeft); + + nextCollision->treeVolume = tree_volume; + nextCollision->collisionSlice = slice; + ++nextCollision; + --collisionsLeft; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxCollisionList::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################### TaggedBoundingBox ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TaggedBoundingBox::TaggedBoundingBox(void *tag) +{ + tagPointer = tag; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TaggedBoundingBox::TaggedBoundingBox( + const ExtentBox &extents, + void *tag +): + BoundingBox(extents) +{ + tagPointer = tag; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +TaggedBoundingBox::~TaggedBoundingBox() +{ +} + +#if defined(TEST_CLASS) + #include "bndgbox.tcp" +#endif diff --git a/MUNGA/BNDGBOX.h b/MUNGA/BNDGBOX.h new file mode 100644 index 0000000..af5ead3 --- /dev/null +++ b/MUNGA/BNDGBOX.h @@ -0,0 +1,195 @@ +#pragma once + +#include "extntbox.h" + +class Line; +class Point3D; +class Origin; +class BoundingBoxTreeNode; +class BoundingBoxList; +class BoundingBoxCollision; + +//########################################################################## +//########################### BoundingBox ############################ +//########################################################################## + +class BoundingBox: + public ExtentBox +{ + friend class BoundingBoxTreeNode; + friend class BoundingBoxList; + +public: + BoundingBox(); + BoundingBox(const ExtentBox &extents); + virtual ~BoundingBox(); + + Logical + Intersects(const ExtentBox &extents); + Logical + Intersects( + const ExtentBox &extents, + ExtentBox *slice + ); + Logical + Contains(const Point3D &point); + Scalar + FindDistanceBelow(const Point3D &point); + Logical + HitBy(Line *line); + + void + PlaceBoundingBox(const Origin& origin); + +protected: + virtual Logical + IntersectsBounded(const ExtentBox &extents); + virtual Logical + ContainsBounded(const Point3D &point); + virtual Scalar + FindDistanceBelowBounded(const Point3D &point); + virtual Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + +public: + static Logical + TestClass(); + virtual Logical + TestInstance() const; +}; + +//########################################################################## +//###################### BoundingBoxCollision ######################## +//########################################################################## + +class BoundingBoxCollision SIGNATURED +{ +public: + BoundingBox + *treeVolume; + ExtentBox + collisionSlice; + + BoundingBox* + GetTreeVolume() + {Check(this); return treeVolume;} + Logical + TestInstance() const; +}; + +//########################################################################## +//#################### BoundingBoxCollisionList ###################### +//########################################################################## + +class BoundingBoxCollisionList SIGNATURED +{ + friend class BoundingBoxTreeNode; + friend class BoundingBoxList; + +protected: + BoundingBoxCollision + *listStart, + *nextCollision; + int + maxCollisions, + collisionsLeft; + +public: + BoundingBoxCollisionList(int max_length); + ~BoundingBoxCollisionList() + {Check(this); Unregister_Pointer(listStart); delete[] listStart;} + void + Reset() + {nextCollision = listStart; collisionsLeft = maxCollisions;} + + void + AddCollisionToList( + BoundingBox *tree_volume, + const ExtentBox &slice + ); + + BoundingBoxCollision& + operator[](int index) + { + Check(this); Verify((unsigned)index < maxCollisions); + return listStart[index]; + } + int + GetCollisionCount() + {Check(this); return maxCollisions - collisionsLeft;} + int + GetCollisionsLeft() + {Check(this); return collisionsLeft;} + + Logical + TestInstance() const; +}; + +//########################################################################## +//######################## TaggedBoundingBox ######################### +//########################################################################## + +class TaggedBoundingBox: + public BoundingBox +{ +public: + void* + GetTagPointer() + {Check(this); return tagPointer;} + +protected: + TaggedBoundingBox(void *tag = NULL); + TaggedBoundingBox( + const ExtentBox &extents, + void *tag = NULL + ); + ~TaggedBoundingBox(); + + void *tagPointer; +}; + +//########################################################################## +//####################### TaggedBoundingBoxOf ######################## +//########################################################################## + +template class TaggedBoundingBoxOf: + public TaggedBoundingBox +{ +public: + TaggedBoundingBoxOf(T *tag); + TaggedBoundingBoxOf( + const ExtentBox &extents, + T *tag = NULL + ); + ~TaggedBoundingBoxOf(); + + T* + GetTagPointer() + {return (T*)tagPointer;} +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ TaggedBoundingBoxOf templates ~~~~~~~~~~~~~~~~~~~ + +template + TaggedBoundingBoxOf::TaggedBoundingBoxOf(T *tag): + TaggedBoundingBox(tag) +{ +} + +template + TaggedBoundingBoxOf::TaggedBoundingBoxOf( + const ExtentBox &extents, + T *tag + ): + TaggedBoundingBox(extents, tag) +{ +} + +template + TaggedBoundingBoxOf::~TaggedBoundingBoxOf() +{ +} diff --git a/MUNGA/BOXCONE.cpp b/MUNGA/BOXCONE.cpp new file mode 100644 index 0000000..2b0ae83 --- /dev/null +++ b/MUNGA/BOXCONE.cpp @@ -0,0 +1,464 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "line.h" + +//############################################################################# +//############################### BoxedCone ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedCone::BoxedCone( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, ConeType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedCone::~BoxedCone() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //------------------------------------------------------------------------ + // Find the center point in the XZ plane of the cone, and find the biggest + // radius of the cone by measuring in the X axis, along with its height + //------------------------------------------------------------------------ + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = minY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Verify(!Small_Enough(radius)); + + // + //-------------------------------------------------------------------------- + // Convert the closest point in the slice to the coordinates of the cone, + // putting the apex of the cone at the origin, then make sure that the point + // isn't in one of the corners of the box + //-------------------------------------------------------------------------- + // + Vector3D nearest(center); + extents.Constrain(&nearest); + center.y = maxY; + nearest.Subtract(center,nearest); + Scalar r = nearest.x*nearest.x + nearest.z*nearest.z; + if (r > radius*radius) + { + return False; + } + + // + //-------------------------------------------------------------------------- + // Compute the distance from the axis, and then see if the slope of the line + // from the cone apex to the test point is less than the slope of the cone + //-------------------------------------------------------------------------- + // + r = Sqrt(r); + Scalar height = maxY - minY; + return r*height <= nearest.y*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Find the center point in the XZ plane of the cone, and find the biggest + // radius of the cone by measuring in the X axis, along with its height + //------------------------------------------------------------------------ + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = maxY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Verify(!Small_Enough(radius)); + + // + //-------------------------------------------------------------------------- + // Convert the closest point in the slice to the coordinates of the cone, + // putting the apex of the cone at the origin, then make sure that the point + // isn't in one of the corners of the box + //-------------------------------------------------------------------------- + // + Vector3D nearest; + nearest.Subtract(center, point); + Scalar r = nearest.x*nearest.x + nearest.z*nearest.z; + if (r > radius*radius) + { + return False; + } + + // + //-------------------------------------------------------------------------- + // Compute the distance from the axis, and then see if the slope of the line + // from the cone apex to the test point is less than the slope of the cone + //-------------------------------------------------------------------------- + // + r = Sqrt(r); + Scalar height = maxY - minY; + return r*height <= nearest.y*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedCone::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Find the center point in the XZ plane of the cone, and find the biggest + // radius of the cone by measuring in the X axis, along with its height + //------------------------------------------------------------------------ + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = maxY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Verify(!Small_Enough(radius)); + + // + //-------------------------------------------------------------------------- + // Convert the closest point in the slice to the coordinates of the cone, + // putting the apex of the cone at the origin, then make sure that the point + // isn't in one of the corners of the box + //-------------------------------------------------------------------------- + // + Vector3D nearest; + nearest.Subtract(point, center); + Scalar r = nearest.x*nearest.x + nearest.z*nearest.z; + if (r > radius*radius) + { + return -1.0f; + } + + // + //-------------------------------------------------------------------------- + // Compute the distance from the axis, and then see if the slope of the line + // from the cone apex to the test point is less than the slope of the cone + //-------------------------------------------------------------------------- + // + r = Sqrt(r); + Scalar height = maxY - minY; + nearest.y += r*(height/radius); + return Max(nearest.y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// This function is a helper function used in the derivation for the terms of +// the quadratic equation to find t when colliding a line and a cone. I'm not +// real clear on the physical representation of this kind of dot product +// +static Scalar + Special_Cone_Dot_Product( + const Vector3D &v1, + const Vector3D &v2, + Scalar squared_tan + ) +{ + return v1.x*v2.x - squared_tan*v1.y*v2.y + v1.z*v2.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //-------------------------------------------------------------------------- + // Find out the size of the box, and set up the height and maximum radius of + // the cone, along with the squared tangent of the spread angle + //-------------------------------------------------------------------------- + // + Vector3D center; + center.x = (minX + maxX) * 0.5f; + center.y = maxY; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + Scalar height = maxY - minY; + Verify(!Small_Enough(height)); + Scalar squared_tan = radius*radius/(height*height); + + // + //------------------------------------------------------------------------- + // Find the line between the point of the cone and the origin of our line, + // then set up the conditions for the quadratic equation. The following + // equation sets up a*t^2 + b*t + c = 0. The terms a, b, and c are derived + // by solving the following equations for t: + // + // p == line->origin + line->direction * t + // r == p - cone->apex + // r.x^2 + r.z^2 == tan^2(cone_angle)*r.y^2 + // + // The special cone dot product function is a handy way to reduce the + // complexity of the problem + //------------------------------------------------------------------------- + // + Vector3D v; + v.Subtract(line->origin,center); + + // + //-------------------------------------------------------------------------- + // If the line diverges from the axis at the same angle as the spread angle, + // we need to find the closest point on the line to the axis. We then drop + // a vertical plane containing the line through the cone at this point, thus + // generating a hyperbola. We then solve the hyperbola vs. line equation to + // get our intersection point + //-------------------------------------------------------------------------- + // + Scalar a = + Special_Cone_Dot_Product(line->direction, line->direction, squared_tan); + if (Small_Enough(a)) + { + } + + // + //----------------------------------------------- + // Otherwise, continue solving the first equation + //----------------------------------------------- + // + else + { + Scalar b = + 2.0f * Special_Cone_Dot_Product(v, line->direction, squared_tan); + Scalar c = Special_Cone_Dot_Product(v, v, squared_tan); + + // + //----------------------------------------------------------------------- + // Now, use the quadratic equation to determine where the two points + // intersect the cone. If there is no solution, than the line missed the + // cone + //----------------------------------------------------------------------- + // + Verify(!Small_Enough(a)); + Scalar t = -b / (2.0f * a); + Scalar i = b*b - 4.0f*a*c; + + if (i < 0.0f) + { + return False; + } + + // + //---------------------------------------------------------------------- + // If the interval is zero, then the line hits the cone in one spot only + // (a tangential hit). Check to see if hits the lower half of the conic + // equation (our cone) + //---------------------------------------------------------------------- + // + if (Small_Enough(i)) + { + Scalar y = v.y + line->direction.y * t; + if (y > 0.0f) + { + return False; + } + + // + //---------------------------------------------------------------- + // It hit the lower cone, so see if it was entering or leaving the + // cone + //---------------------------------------------------------------- + // + if (line->direction.y > 0.0f) + { + // + //------------------------------------------------------------- + // The line is leaving the cone, so see if we need to reset the + // leaving distance + //------------------------------------------------------------- + // + if (t < leaves) + { + leaves = t; + } + } + + // + //------------------------------------------------------------ + // The line is entering the cone, so see if we need to set the + // entering distance + //------------------------------------------------------------ + // + else if (t > enters) + { + enters = t; + } + + // + //------------------------------------------------------------------- + // See if we still have a collision with the cone, and if so, set the + // new line length + //------------------------------------------------------------------- + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //---------------------------------------------------------------------- + // If the interval is non-zero, then the conic section was struck in two + // places. Find out the lengths to those places and the y values for + // those points + //---------------------------------------------------------------------- + // + i = Sqrt(i) / (2.0f * a); + Scalar t1,t2; + if (i > 0.0f) + { + t1 = t - i; + t2 = t + i; + } + else + { + t1 = t + i; + t2 = t - i; + } + Scalar y1 = v.y + line->direction.y * t1; + Scalar y2 = v.y + line->direction.y * t2; + + // + //---------------------------------------------------------------------- + // There are four combinations of the signs of the y values. Each has a + // different effect on missing/hitting, entering or leaving distances. + // First check to see if only the upper conic was hit + //---------------------------------------------------------------------- + // + if (y1 > 0.0f) + { + if (y2 > 0.0f) + { + return False; + } + + // + //----------------------------------------------------------------- + // The ray is entering our conic, so set the distance appropriately + //----------------------------------------------------------------- + // + if (t2 > enters) + { + enters = t2; + } + } + + // + //---------------------------------------------------------------------- + // See if the ray is leaving the lower conic, and if so, set the leaving + // distance accordingly + //---------------------------------------------------------------------- + // + else + { + if (y2 > 0.0f) + { + if (t1 < leaves) + { + leaves = t1; + } + } + + // + //-------------------------------------------------------------------- + // Both spots are in the lower conic, so set both leaving and entering + // distances + //-------------------------------------------------------------------- + // + else + { + if (t1 > enters) + { + enters = t1; + } + if (t2 < leaves) + { + leaves = t2; + } + } + } + + // + //----------------------------------------------------------------------- + // See if we still have a collision with the cone, and if so, set the new + // line length + //----------------------------------------------------------------------- + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + line->length = Max(enters, 0.0f); + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedCone::TestInstance() const +{ + return solidType == ConeType; +} diff --git a/MUNGA/BOXDISKS.cpp b/MUNGA/BOXDISKS.cpp new file mode 100644 index 0000000..c2c4687 --- /dev/null +++ b/MUNGA/BOXDISKS.cpp @@ -0,0 +1,1773 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "line.h" +#include "plane.h" + +//############################################################################# +//########################## BoxedXAxisCylinder ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedXAxisCylinder::BoxedXAxisCylinder( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, XAxisCylinderType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedXAxisCylinder::~BoxedXAxisCylinder() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //--------------------------------------------------------------------- + // Find the center point in the YZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the Y axis. The X value will + // automatically be within the cylinder if Y & Z are + //--------------------------------------------------------------------- + // + Scalar y = (minY + maxY) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxY - y; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + Scalar y2 = y; + Scalar z2 = z; + Clamp(y2, extents.minY, extents.maxY); + Clamp(z2, extents.minZ, extents.maxZ); + y2 -= y; + z2 -= z; + return y2*y2 + z2*z2 <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the YZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the Y axis. The X value will + // automatically be within the cylinder if Y & Z are + //--------------------------------------------------------------------- + // + Scalar y = (minY + maxY) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxY - y; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + y -= point.y; + z -= point.z; + return y*y + z*z <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedXAxisCylinder::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxZ - z; + + // + //-------------------------------------------------------------------------- + // figure out the thickness of cylinder slice where a plane perpendicular to + // X drops through the cylinder and the test point + //-------------------------------------------------------------------------- + // + z = point.z - z; + Scalar y = radius - Sqrt(radius*radius - z*z); + if (point.y > maxY - y) + { + return point.y - maxY + y; + } + else if (point.y < minY + y) + { + return -1.0f; + } + else + { + return 0.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + Scalar y = (minY + maxY) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxY - y; + + Scalar a = + line->direction.y*line->direction.y + + line->direction.z*line->direction.z; + + // + //-------------------------------------------------------------------------- + // If the line is parallel to the cylinder, see if it hits the bottom/top of + // the cylinder in the X-Z plane. If it does, it hits the cylinder when it + // hits the box, otherwise it misses altogether + //-------------------------------------------------------------------------- + // + if (Small_Enough(a)) + { + y -= line->origin.y; + z -= line->origin.z; + if (y*y + z*z > radius*radius) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //----------------------------------------------------------------------- + // The line is not parallel to the cylinder, so solve the equation giving + // the intersection of the line with the cylinder using the quadratic + // equation + //----------------------------------------------------------------------- + // + y = line->origin.y - y; + z = line->origin.z - z; + + Scalar b = 2.0f * (line->direction.y*y + line->direction.z*z); + Scalar c = y*y + z*z - radius*radius; + Scalar i = b*b - 4.0f*a*c; + + if (i < SMALL) + { + return False; + } + + // + //------------------------------------------------------------------------- + // If the line does hit the cylinder, update the enter/leaving distances to + // take the cylinder surface into account + //------------------------------------------------------------------------- + // + Verify(a > SMALL); + Scalar ratio = Sqrt(a)/(a*a); + i = Sqrt(i); + b *= -ratio; + i *= ratio; + Scalar enter = (b - i) * 0.5f; + if (enter > enters) + { + enters = enter; + } + + Scalar leave = enter + i; + if (leave < leaves) + { + leaves = leave; + } + + // + //------------------------------------------------------------------------ + // If we have pushed the entering distance after the leaving distance, the + // cylinder was missed, otherwise it is hit at the new entering distance + //------------------------------------------------------------------------ + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedXAxisCylinder::TestInstance() const +{ + return solidType == XAxisCylinderType; +} + +//############################################################################# +//########################## BoxedYAxisCylinder ######################### +//############################################################################# + +enum { + Min_X_Bit = 0x01, + Max_X_Bit = 0x02, + X_Bits = Min_X_Bit|Max_X_Bit, + Min_Y_Bit = 0x04, + Max_Y_Bit = 0x08, + Y_Bits = Min_Y_Bit|Max_Y_Bit, + Min_Z_Bit = 0x10, + Max_Z_Bit = 0x20, + Z_Bits = Min_Z_Bit|Max_Z_Bit, + X_Axis_Bit = 0x04, + Y_Axis_Bit = 0x02, + Z_Axis_Bit = 0x01 +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedYAxisCylinder::BoxedYAxisCylinder( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, YAxisCylinderType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedYAxisCylinder::~BoxedYAxisCylinder() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::VerifyCollision(BoxedSolidCollision &collision) +{ + Check(this); + Check(&collision); + + Verify(minX <= collision.collisionSlice.minX); + Verify(maxX >= collision.collisionSlice.maxX); + Verify(minY <= collision.collisionSlice.minY); + Verify(maxY >= collision.collisionSlice.maxY); + Verify(minZ <= collision.collisionSlice.minZ); + Verify(maxZ >= collision.collisionSlice.maxZ); + + Scalar + x, + z, + their_x, + their_z, + radius, + their_radius; + + BoxedSolid* solid = collision.GetTreeVolume(); + + // + //-------------------------------------------------------------------------- + // See which type of collision we are going to have to verify, and branch to + // it + //-------------------------------------------------------------------------- + // + switch (solid->solidType) + { + + // + //------------------------------------------------------------------------- + // When colliding with a ramp or horizontal cylinder, go ahead and have the + // collision slice assume it is from a block. The error thus generated is + // actually very small and not really noticed by anyone + //------------------------------------------------------------------------- + // + case BlockType: + case SphereType: + case ReducibleBlockType: + case RampFacingNegativeZType: + case RampFacingNegativeXType: + case RampFacingPositiveZType: + case RampFacingPositiveXType: + case InvertedRampFacingNegativeZType: + case InvertedRampFacingNegativeXType: + case InvertedRampFacingPositiveZType: + case InvertedRampFacingPositiveXType: + case WedgeFacingNegativeZAndPositiveXType: + case WedgeFacingNegativeZAndNegativeXType: + case WedgeFacingPositiveZAndNegativeXType: + case WedgeFacingPositiveZAndPositiveXType: + case XAxisCylinderType: + case ZAxisCylinderType: + case RightHandedTileType: + case LeftHandedTileType: + return IntersectsBounded(collision.collisionSlice); + + // + //-------------------------------------------------------------------------- + // When colliding with another upright cylinder, simply calculate the + // distance between the two center points and see if it is less than the sum + // of the two radii + //-------------------------------------------------------------------------- + // + case YAxisCylinderType: + x = (maxX + minX) * 0.5f; + z = (maxZ + minZ) * 0.5f; + radius = maxX - x; + + their_x = (solid->maxX + solid->minX) * 0.5f; + their_z = (solid->maxZ + solid->minZ) * 0.5f; + their_radius = solid->maxX - their_x; + + radius += their_radius; + x -= their_x; + z -= their_z; + + return radius*radius >= x*x + z*z; + + // + //------------------------------------------------------------------------ + // When colliding with a cone, we will base all the calculations on the + // assumption that the collision can be detected identically by a cylinder + // created by the the intersection of the bottom plane of this volume with + // the cone + //------------------------------------------------------------------------ + // + case ConeType: + x = (maxX + minX) * 0.5f; + z = (maxZ + minZ) * 0.5f; + radius = maxX - x; + + their_x = (solid->maxX + solid->minX) * 0.5f; + their_z = (solid->maxZ + solid->minZ) * 0.5f; + their_radius = solid->maxX - their_x; + their_radius *= (solid->maxY - minY) / (solid->maxY - solid->minY); + + radius += their_radius; + x -= their_x; + z -= their_z; + + return radius*radius >= x*x + z*z; + + // + //------------------------------ + // Fail on the unsupported types + //------------------------------ + // + default: + #if defined(LAB_ONLY) + DEBUG_STREAM << collision.GetTreeVolume()->solidType << endl << std::flush; + Fail("Unsupported collision primative\n"); + #endif + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::ProcessCollision( + BoxedSolidCollision &collision, + const Vector3D &velocity, + BoxedSolidCollisionList *last_collisions, + Normal *normal, + Scalar *penetration + ) +{ + Check(this); + Check(&collision); + Check(&velocity); + Check_Pointer(normal); + Check_Pointer(penetration); + + Scalar + result, + len; + int + i, + axes, + axis, + face, + mask = 0, + opp_face, + temp; + bool ok = false; + BoxedSolid *solid = collision.GetTreeVolume(); + Vector3D + position; + + // + //----------------------------------------------------- + // First verify that the collision really should happen + //----------------------------------------------------- + // + if (Small_Enough(velocity.LengthSquared())) + { + return False; + } + if (!VerifyCollision(collision)) + { + return False; + } + + // + //------------------------------------------------------------------------ + // Look at each of the three coordinates of motion, and make sure that the + // collision slice is valid for at least one of them + //------------------------------------------------------------------------ + // + for (axis=X_Axis; axis<=Z_Axis; ++axis) + { + // + //------------------------------------------------------------------- + // Make sure we have actual velocity along this axis, then figure out + // which face to test + //------------------------------------------------------------------- + // + (*normal)[axis] = 0.0f; + mask <<= 1; + if (Small_Enough(velocity[axis])) + { + continue; + } + face = (axis<<1) + (velocity[axis]>0.0f); + opp_face = face ^ 1; + + // + //---------------------------------------------------------------------- + // Find out which faces of the cylinder's bounding box should be + // considered for purposes of the collision. Sides are only considered + // valid if the leading face of the collision slice matches the leading + // face of the disk. + //---------------------------------------------------------------------- + // + if ( + collision.collisionSlice[face] == (*this)[face] && + ( + (face&1) && (*this)[opp_face] < collision.collisionSlice[opp_face] + || + !(face&1) + && (*this)[opp_face] > collision.collisionSlice[opp_face] + ) + ) + mask |= 1; + } + + // + //----------------------------------------------------------------- + // Handle the actual collision based upon the type of model and the + // components involved in the collision + //----------------------------------------------------------------- + // + switch (solid->solidType) + { + + // + //-------------------------- + // Handle the Z facing Ramps + //-------------------------- + // + case RampFacingNegativeZType: + normal->y = solid->maxZ - solid->minZ; + normal->z = solid->maxY - solid->minY; + position.y = collision.collisionSlice.minY - solid->maxY; + position.z = collision.collisionSlice.minZ - solid->minZ; + + // + //-------------------------------------------------------------------- + // The normal y and z values are assumed at this point to point in the + // right direction although their lengths are screwed up + //-------------------------------------------------------------------- + // +Compute_X: + len = Sqrt(normal->y*normal->y + normal->z*normal->z); + Verify(!Small_Enough(len)); + normal->y /= len; + normal->z /= len; + Check_Fpu(); + + result = velocity.y*normal->y + velocity.z*normal->z; + if (result > -SMALL) + { + if (mask&X_Axis_Bit) + { + goto X_Only; + } + else + { + break; + } + } + *penetration = + fabs((position.y*normal->y + position.z*normal->z) / result); + Check_Fpu(); + + // + //----------------------------------------------------------------------- + // If the side of the ramp was involved in the collision, pick either the + // ramp or side to reflect off of based upon which opposes motion more + //----------------------------------------------------------------------- + // + if (mask&X_Axis_Bit) + { + // + //---------------------------------------------------------------- + // Compute plane equation and find the distance from the most + // penetrating slice point to the plane. If the ray comes out the + // ramp, we hit that, otherwise we hit the side + //---------------------------------------------------------------- + // + result = fabs((solid->maxX - solid->minX) / velocity.x); + Check_Fpu(); + if (result < *penetration) + { +X_Only: + normal->x = (velocity.x > 0.0f) ? -1.0f : 1.0f; + normal->y = 0.0f; + normal->z = 0.0f; + *penetration = result; + } + } + goto Reflect; + + case RampFacingPositiveZType: + normal->y = solid->maxZ - solid->minZ; + normal->z = solid->minY - solid->maxY; + position.y = collision.collisionSlice.minY - solid->maxY; + position.z = collision.collisionSlice.maxZ - solid->maxZ; + goto Compute_X; + + case InvertedRampFacingNegativeZType: + normal->y = solid->minZ - solid->maxZ; + normal->z = solid->maxY - solid->minY; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.z = collision.collisionSlice.minZ - solid->maxZ; + goto Compute_X; + + case InvertedRampFacingPositiveZType: + normal->y = solid->minZ - solid->maxZ; + normal->z = solid->minY - solid->maxY; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.z = collision.collisionSlice.maxZ - solid->minZ; + goto Compute_X; + + // + //-------------------------- + // Handle the X facing ramps + //-------------------------- + // + case RampFacingNegativeXType: + normal->x = solid->maxY - solid->minY; + normal->y = solid->maxX - solid->minX; + position.y = collision.collisionSlice.minY - solid->maxY; + position.x = collision.collisionSlice.minX - solid->minX; + + // + //-------------------------------------------------------------------- + // The normal x and y values are assumed at this point to point in the + // right direction although their lengths are screwed up + //-------------------------------------------------------------------- + // +Compute_Z: + len = Sqrt(normal->x*normal->x + normal->y*normal->y); + Verify(!Small_Enough(len)); + normal->x /= len; + normal->y /= len; + Check_Fpu(); + + result = velocity.y*normal->y + velocity.x*normal->x; + if (result > -SMALL) + { + if (mask&Z_Axis_Bit) + { + goto Z_Only; + } + else + { + break; + } + } + *penetration = + fabs((position.y*normal->y + position.x*normal->x) / result); + Check_Fpu(); + + // + //----------------------------------------------------------------------- + // If the side of the ramp was involved in the collision, pick either the + // ramp or side to reflect off of based upon which opposes motion more + //----------------------------------------------------------------------- + // + if (mask&Z_Axis_Bit) + { + // + //---------------------------------------------------------------- + // Compute plane equation and find the distance from the most + // penetrating slice point to the plane. If the ray comes out the + // ramp, we hit that, otherwise we hit the side + //---------------------------------------------------------------- + // + result = fabs((solid->maxZ - solid->minZ) / velocity.z); + Check_Fpu(); + if (result < *penetration) + { +Z_Only: + normal->x = 0.0f; + normal->y = 0.0f; + normal->z = (velocity.z > 0.0f) ? -1.0f : 1.0f; + *penetration = result; + } + } + goto Reflect; + + case RampFacingPositiveXType: + normal->x = solid->minY - solid->maxY; + normal->y = solid->maxX - solid->minX; + position.y = collision.collisionSlice.minY - solid->maxY; + position.x = collision.collisionSlice.maxX - solid->maxX; + goto Compute_Z; + + case InvertedRampFacingNegativeXType: + normal->x = solid->maxY - solid->minY; + normal->y = solid->minX - solid->maxX; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.x = collision.collisionSlice.minX - solid->maxX; + goto Compute_Z; + + case InvertedRampFacingPositiveXType: + normal->x = solid->minY - solid->maxY; + normal->y = solid->minX - solid->maxX; + position.y = collision.collisionSlice.maxY - solid->maxY; + position.x = collision.collisionSlice.maxX - solid->minX; + goto Compute_Z; + + // + //------------------ + // Handle the wedges + //------------------ + // + case WedgeFacingNegativeZAndPositiveXType: + normal->x = solid->minZ - solid->maxZ; + normal->z = solid->maxX - solid->minX; + position.x = collision.collisionSlice.maxX - solid->minX; + position.z = collision.collisionSlice.minZ - solid->minZ; + + // + //-------------------------------------------------------------------- + // The normal x and z values are assumed at this point to point in the + // right direction although their lengths are screwed up + //-------------------------------------------------------------------- + // +Compute_Y: + len = Sqrt(normal->x*normal->x + normal->z*normal->z); + Verify(!Small_Enough(len)); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + + result = velocity.x*normal->x + velocity.z*normal->z; + if (result > -SMALL) + { + if (mask&Y_Axis_Bit) + { + goto Y_Only; + } + else + { + break; + } + } + *penetration = + fabs((position.x*normal->x + position.z*normal->z) / result); + Check_Fpu(); + + // + //----------------------------------------------------------------------- + // If the top of the wedge was involved in the collision, pick either the + // side or top to reflect off of based upon which opposes motion more + //----------------------------------------------------------------------- + // + if (mask&Y_Axis_Bit) + { + // + //---------------------------------------------------------------- + // Compute plane equation and find the distance from the most + // penetrating slice point to the plane. If the ray comes out the + // ramp, we hit that, otherwise we hit the side + //---------------------------------------------------------------- + // + result = fabs((solid->maxY - solid->minY) / velocity.y); + Check_Fpu(); + if (result < *penetration) + { +Y_Only: + normal->x = 0.0f; + normal->y = (velocity.y > 0.0f) ? -1.0f : 1.0f; + normal->z = 0.0f; + *penetration = result; + } + } + goto Reflect; + + case WedgeFacingNegativeZAndNegativeXType: + normal->x = solid->maxZ - solid->minZ; + normal->z = solid->maxX - solid->minX; + position.x = collision.collisionSlice.minX - solid->maxX; + position.z = collision.collisionSlice.minZ - solid->minZ; + goto Compute_Y; + + case WedgeFacingPositiveZAndNegativeXType: + normal->x = solid->maxZ - solid->minZ; + normal->z = solid->minX - solid->maxX; + position.x = collision.collisionSlice.minX - solid->minX; + position.z = collision.collisionSlice.maxZ - solid->minZ; + goto Compute_Y; + + case WedgeFacingPositiveZAndPositiveXType: + normal->x = solid->minZ - solid->maxZ; + normal->z = solid->minX - solid->maxX; + position.x = collision.collisionSlice.maxX - solid->maxX; + position.z = collision.collisionSlice.maxZ - solid->minZ; + goto Compute_Y; + + // + //---------------------------------------------------------------------- + //---------------------------------------------------------------------- + // + case XAxisCylinderType: + normal->y = minY + maxY - solid->minY - solid->maxY; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->y*normal->y + normal->z*normal->z; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->y /= len; + normal->z /= len; + Check_Fpu(); + *penetration = 1.0f; + goto Reflect; + + case ZAxisCylinderType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->y = minY + maxY - solid->minY - solid->maxY; + len = normal->x*normal->x + normal->y*normal->y; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->x /= len; + normal->y /= len; + Check_Fpu(); + *penetration = 1.0f; + goto Reflect; + + case YAxisCylinderType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->x*normal->x + normal->z*normal->z; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + *penetration = 1.0f; + + if (mask & Y_Axis_Bit) + { + len = (velocity.z > 0.0f) ? -1.0f : 1.0f; + if (len*velocity.y < velocity.x*normal->x + velocity.z*normal->z) + { + normal->x = 0.0f; + normal->y = len; + normal->z = 0.0f; + } + } + goto Reflect; + + // + //------------- + // Handle cones + //------------- + // + case ConeType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->x*normal->x + normal->z*normal->z; + *penetration = 1.0f; + if (Small_Enough(len)) + { + goto Reverse; + } + normal->y = + 0.5f * (solid->maxX - solid->minX) * Sqrt(len) + / (solid->maxY - solid->minY); + Check_Fpu(); + normal->Normalize(*normal); + goto Reflect; + + // + //--------------- + // Handle spheres + //--------------- + // + case SphereType: + normal->x = minX + maxX - solid->minX - solid->maxX; + normal->y = minY + maxY - solid->minY - solid->maxY; + normal->z = minZ + maxZ - solid->minZ - solid->maxZ; + len = normal->x*normal->x + normal->y*normal->y + normal->z*normal->z; + if (Small_Enough(len)) + { + goto Reverse; + } + len = Sqrt(len); + normal->x /= len; + normal->y /= len; + normal->z /= len; + Check_Fpu(); + *penetration = 1.0f; + goto Reflect; + + // + //--------------------------------- + // Handle reflecting off of a block + //--------------------------------- + // + case BlockType: + case ReducibleBlockType: + + // + //--------------------------------------------------- + // Count the number of axes involved in the collision + //--------------------------------------------------- + // + temp = mask; + for (axes=0; temp; temp>>=1) + { + if (temp&1) + { + ++axes; + } + } + + // + //------------------------------------------------------ + // Handle as appropriate to the number of sides involved + //------------------------------------------------------ + // + switch (axes) + { + + // + //--------------------------------------------------------------------- + // If no sides were found to be involved in the collision, then we have + // a weird case where the disk has completely penetrated through the + // block + //--------------------------------------------------------------------- + // + case 0: + + // + //------------------------------------------------------------------- + // This is where we will check the current volume against our list of + // volumes hit last time. If we have not already hit this solid, + // reverse the motion as we have penetrated the object + //------------------------------------------------------------------- + // + i = 0; + if (last_collisions) + { + for (i=0; iGetCollisionCount(); ++i) + { + if ((*last_collisions)[i].GetTreeVolume() == solid) + { + break; + } + } + } + if (!last_collisions || i == last_collisions->GetCollisionCount()) + { +Reverse: + *penetration = 1.0f; + result = -1.0f / velocity.Length(); + Check_Fpu(); + normal->x = velocity.x*result; + normal->y = velocity.y*result; + normal->z = velocity.z*result; + ok = true; + break; + } + + // + //-------------------------------------------------------------------- + // Since this is not a fresh hit, check to see if any part of the + // colliding disk sticks out of the slice. If so, then we are heading + // out of the solid in that direction, so let the motion continue. + // WHAT IS THE VELOCITY TRIGGER FOR???? + //-------------------------------------------------------------------- + // + position.x = (maxX + minX) * 0.5f; + position.y = (maxY + minY) * 0.5f; + position.z = (maxZ + minZ) * 0.5f; + for (face=0; face<6; ++face) + { + i = face >> 1; + if (face&1) + { + if + ( + (*this)[face] > collision.collisionSlice[face] + && position[i] > collision.collisionSlice[face] + && velocity[i] < 5.0f + ) + break; + } + else if + ( + (*this)[face] < collision.collisionSlice[face] + && position[i] < collision.collisionSlice[face] + && velocity[i] > -5.0f + ) + break; + } + if (face != 6) + { + break; + } + + // + //------------------------------------------------------------------- + // Otherwise, generate a normal opposing motion towards the center of + // the solid. For each component, if it does not oppose motion, zero + // it out. This will give a better approximation of the brick + //------------------------------------------------------------------- + // + normal->x = position.x - (solid->minX + solid->maxX) * 0.5f; + normal->y = position.y - (solid->minY + solid->maxY) * 0.5f; + normal->z = position.z - (solid->minZ + solid->maxZ) * 0.5f; + for (i=0; i<3; ++i) + { + if ((*normal)[i]*velocity[i] >= 0.0) + { + (*normal)[i] = 0.0; + } + } + + // + //---------------------------------------------------------------- + // Normalize the vector, making sure we don't get killed by a zero + // case + //---------------------------------------------------------------- + // + result = normal->Length(); + if (!Small_Enough(result)) + { + normal->x /= result; + normal->y /= result; + normal->z /= result; + Check_Fpu(); + } + else + { + break; + } + *penetration = 1.0f; + goto Reflect; + + // + //----------------------------------------------------------------- + // If only one side is involved in the collision, reflect off of it + //----------------------------------------------------------------- + // + case 1: +Test_Corner: + position.x = 0.5f * (minX + maxX); + position.z = 0.5f * (minZ + maxZ); + switch (mask) + { + case X_Axis_Bit: + face = X_Axis << 1; + + // + //---------------------------------- + // Figure out the z bounce direction + //---------------------------------- + // + if (collision.collisionSlice.minZ > position.z) + { + normal->z = position.z - collision.collisionSlice.minZ; + } + else if (collision.collisionSlice.maxZ < position.z) + { + normal->z = position.z - collision.collisionSlice.maxZ; + } + + // + //---------------------------------- + // Figure out the x bounce direction + //---------------------------------- + // + len = maxX - position.x; + normal->x = len*len - normal->z*normal->z; + Verify(normal->x >= 0.0f); + normal->x = Sqrt(normal->x); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + if (velocity.x > 0.0f) + { + normal->x = -normal->x; + } + break; + + case Y_Axis_Bit: + face = Y_Axis << 1; + *penetration = + fabs( + ( + collision.collisionSlice[face] + - collision.collisionSlice[face^1] + ) / velocity[face>>1] + ); + Check_Fpu(); + goto Pick_Side; + + case Z_Axis_Bit: + face = Z_Axis << 1; + + // + //---------------------------------- + // Figure out the x bounce direction + //---------------------------------- + // + if (collision.collisionSlice.minX > position.x) + { + normal->x = position.x - collision.collisionSlice.minX; + } + else if (collision.collisionSlice.maxX < position.x) + { + normal->x = position.x - collision.collisionSlice.maxX; + } + + // + //---------------------------------- + // Figure out the z bounce direction + //---------------------------------- + // + len = maxX - position.x; + normal->z = len*len - normal->x*normal->x; + Verify(normal->z >= 0.0f); + normal->z = Sqrt(normal->z); + normal->x /= len; + normal->z /= len; + Check_Fpu(); + if (velocity.z > 0.0f) + { + normal->z = -normal->z; + } + break; + } + *penetration = + fabs( + ( + collision.collisionSlice[face] + - collision.collisionSlice[face^1] + ) / velocity[face>>1] + ); + Check_Fpu(); + + // + //------------------------------------------------------------------- + // Check to make sure that the normal opposes velocity. If it + // doesn't look to see if this is the first hit on the object, and if + // so, reverse the velocity + //------------------------------------------------------------------- + // +Reflect: + Check(normal); + ok = (*normal * velocity < 0.0f); + if (!ok) + { + i = 0; + if (last_collisions) + { + for (i=0; iGetCollisionCount(); ++i) + { + if ((*last_collisions)[i].GetTreeVolume() == solid) + { + break; + } + } + } + if (!last_collisions || i == last_collisions->GetCollisionCount()) + { + goto Reverse; + } + } + break; + + // + //--------------------------------------------------------------------- + // If two faces were involved, we hit an edge, so figure out which face + // we really hit and mask off the other face + //--------------------------------------------------------------------- + // + case 2: + switch (mask) + { + case X_Axis_Bit|Z_Axis_Bit: + position.x = + collision.collisionSlice.maxX - collision.collisionSlice.minX; + position.z = + collision.collisionSlice.maxZ - collision.collisionSlice.minZ; + mask ^= + (fabs(position.z*velocity.x) > fabs(position.x*velocity.z)) + ? Z_Axis_Bit : X_Axis_Bit; + break; + + case X_Axis_Bit|Y_Axis_Bit: + position.x = + collision.collisionSlice.maxX - collision.collisionSlice.minX; + position.y = + collision.collisionSlice.maxY - collision.collisionSlice.minY; + mask ^= + (fabs(position.y*velocity.x) > fabs(position.x*velocity.y)) + ? Y_Axis_Bit : X_Axis_Bit; + break; + + case Y_Axis_Bit|Z_Axis_Bit: + position.y = + collision.collisionSlice.maxY - collision.collisionSlice.minY; + position.z = + collision.collisionSlice.maxZ - collision.collisionSlice.minZ; + mask ^= + (fabs(position.y*velocity.z) > fabs(position.z*velocity.y)) + ? Y_Axis_Bit : Z_Axis_Bit; + break; + } + goto Test_Corner; + + + // + //----------------------------------------------------------------------- + // Otherwise, project the intruding vertex back along the velocity vector + // to try and find out which face to bounce off of + //----------------------------------------------------------------------- + // + default: + position.x = + collision.collisionSlice.maxX - collision.collisionSlice.minX; + position.y = + collision.collisionSlice.maxY - collision.collisionSlice.minY; + position.z = + collision.collisionSlice.maxZ - collision.collisionSlice.minZ; + + position.x = fabs(position.x/velocity.x); + position.y = fabs(position.y/velocity.y); + position.z = fabs(position.z/velocity.z); + + if (position.x < position.y) + { + face = (position.x < position.z) ? (X_Axis<<1) : (Z_Axis<<1); + } + else + { + face = (position.y < position.z) ? (Y_Axis<<1) : (Z_Axis<<1); + } + *penetration = position[face>>1]; + +Pick_Side: + if (velocity[face>>1] > 0.0f) + { + (*normal)[face>>1] = -1.0f; + } + else + { + (*normal)[face>>1] = 1.0f; + } + goto Reflect; + } + break; + + #if defined(LAB_ONLY) + default: + Fail("Unsupported collision type!...\n"); + break; + #endif + } + + if (ok) + { + Check(normal); + if (*penetration < 0.0f) + { + return False; + } + } + return ok; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + Scalar x2 = x; + Scalar z2 = z; + Clamp(x2, extents.minX, extents.maxX); + Clamp(z2, extents.minZ, extents.maxZ); + x2 -= x; + z2 -= z; + return x2*x2 + z2*z2 <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + x -= point.x; + z -= point.z; + return x*x + z*z <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedYAxisCylinder::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); //z); //GY + Verify(maxX >= point.x); //z); //GY + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + x -= point.x; + z -= point.z; + if (x*x + z*z > radius*radius) + { + return -1.0f; + } + + Scalar height = point.y - maxY; + return Abs(height); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + Scalar x = (minX + maxX) * 0.5f; + Scalar z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - x; + + Scalar a = + line->direction.x*line->direction.x + + line->direction.z*line->direction.z; + + // + //-------------------------------------------------------------------------- + // If the line is parallel to the cylinder, see if it hits the bottom/top of + // the cylinder in the X-Z plane. If it does, it hits the cylinder when it + // hits the box, otherwise it misses altogether + //-------------------------------------------------------------------------- + // + if (Small_Enough(a)) + { + x -= line->origin.x; + z -= line->origin.z; + if (x*x + z*z > radius*radius) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //----------------------------------------------------------------------- + // The line is not parallel to the cylinder, so solve the equation giving + // the intersection of the line with the cylinder using the quadratic + // equation + //----------------------------------------------------------------------- + // + x = line->origin.x - x; + z = line->origin.z - z; + + Scalar b = 2.0f * (line->direction.x*x + line->direction.z*z); + Scalar c = x*x + z*z - radius*radius; + Scalar i = b*b - 4.0f*a*c; + + if (i < SMALL) + { + return False; + } + + // + //------------------------------------------------------------------------- + // If the line does hit the cylinder, update the enter/leaving distances to + // take the cylinder surface into account + //------------------------------------------------------------------------- + // + Verify(a > SMALL); + Scalar ratio = Sqrt(a)/(a*a); + i = Sqrt(i); + b *= -ratio; + i *= ratio; + Scalar enter = (b - i) * 0.5f; + if (enter > enters) + { + enters = enter; + } + + Scalar leave = enter + i; + if (leave < leaves) + { + leaves = leave; + } + + // + //------------------------------------------------------------------------ + // If we have pushed the entering distance after the leaving distance, the + // cylinder was missed, otherwise it is hit at the new entering distance + //------------------------------------------------------------------------ + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedYAxisCylinder::TestInstance() const +{ + return solidType == YAxisCylinderType; +} + +//############################################################################# +//########################## BoxedZAxisCylinder ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedZAxisCylinder::BoxedZAxisCylinder( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, ZAxisCylinderType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedZAxisCylinder::~BoxedZAxisCylinder() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar y = (minY + maxY) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + Scalar x2 = x; + Scalar y2 = y; + Clamp(x2, extents.minX, extents.maxX); + Clamp(y2, extents.minY, extents.maxY); + x2 -= x; + y2 -= y; + return x2*x2 + y2*y2 <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar y = (minY + maxY) * 0.5f; + Scalar radius = maxX - x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the cylinder, putting the + // center point of the cylinder at the origin. Note that we are + // subtracting the point from the center point as opposed to the normal + // way. This will result in both X and Y being negated, but since we are + // squaring them, this will not matter + //----------------------------------------------------------------------- + // + x -= point.x; + y -= point.y; + return x*x + y*y <= radius*radius; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedZAxisCylinder::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x);//z); //GY + Verify(maxX >= point.x);//z); //GY + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------------------------- + // Find the center point in the XZ plane of the cylinder, and find the + // radius of the cylinder by measuring in the X axis. The Y value will + // automatically be within the cylinder if X & Z are + //--------------------------------------------------------------------- + // + Scalar x = (minX + maxX) * 0.5f; + Scalar radius = maxX - x; + + // + //-------------------------------------------------------------------------- + // figure out the thickness of cylinder slice where a plane perpendicular to + // X drops through the cylinder and the test point + //-------------------------------------------------------------------------- + // + x = point.x - x; + Scalar y = radius - Sqrt(radius*radius - x*x); + if (point.y > maxY - y) + { + return point.y - maxY + y; + } + else if (point.y < minY + y) + { + return -1.0f; + } + else + { + return 0.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + Scalar x = (minX + maxX) * 0.5f; + Scalar y = (minY + maxY) * 0.5f; + Scalar radius = maxX - x; + + Scalar a = + line->direction.y*line->direction.y + + line->direction.x*line->direction.x; + + // + //-------------------------------------------------------------------------- + // If the line is parallel to the cylinder, see if it hits the bottom/top of + // the cylinder in the X-Z plane. If it does, it hits the cylinder when it + // hits the box, otherwise it misses altogether + //-------------------------------------------------------------------------- + // + if (Small_Enough(a)) + { + y -= line->origin.y; + x -= line->origin.x; + if (y*y + x*x > radius*radius) + { + return False; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //----------------------------------------------------------------------- + // The line is not parallel to the cylinder, so solve the equation giving + // the intersection of the line with the cylinder using the quadratic + // equation + //----------------------------------------------------------------------- + // + y = line->origin.y - y; + x = line->origin.x - x; + + Scalar b = 2.0f * (line->direction.y*y + line->direction.x*x); + Scalar c = y*y + x*x - radius*radius; + Scalar i = b*b - 4.0f*a*c; + + if (i < SMALL) + { + return False; + } + + // + //------------------------------------------------------------------------- + // If the line does hit the cylinder, update the enter/leaving distances to + // take the cylinder surface into account + //------------------------------------------------------------------------- + // + Verify(a > SMALL); + Scalar ratio = Sqrt(a)/(a*a); + i = Sqrt(i); + b *= -ratio; + i *= ratio; + Scalar enter = (b - i) * 0.5f; + if (enter > enters) + { + enters = enter; + } + + Scalar leave = enter + i; + if (leave < leaves) + { + leaves = leave; + } + + // + //------------------------------------------------------------------------ + // If we have pushed the entering distance after the leaving distance, the + // cylinder was missed, otherwise it is hit at the new entering distance + //------------------------------------------------------------------------ + // + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedZAxisCylinder::TestInstance() const +{ + return solidType == ZAxisCylinderType; +} \ No newline at end of file diff --git a/MUNGA/BOXIRAMP.cpp b/MUNGA/BOXIRAMP.cpp new file mode 100644 index 0000000..5a29ad5 --- /dev/null +++ b/MUNGA/BOXIRAMP.cpp @@ -0,0 +1,911 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "plane.h" + +extern Logical + BoxedRampContainsLine( + Line *line, + const Plane& plane, + Scalar enters, + Scalar leaves + ); + +//############################################################################# +//##################### BoxedInvertedRampFacingNegativeZ ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeZ::BoxedInvertedRampFacingNegativeZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingNegativeZType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeZ::~BoxedInvertedRampFacingNegativeZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.maxY - minY; + Scalar z = extents.minZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingNegativeZ::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (z*rise <= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = minZ - maxZ; + ramp.normal.z = maxY - minY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = maxY*ramp.normal.y + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeZ::TestInstance() const +{ + return solidType == InvertedRampFacingNegativeZType; +} + +//############################################################################# +//##################### BoxedInvertedRampFacingPositiveZ ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveZ::BoxedInvertedRampFacingPositiveZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingPositiveZType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveZ::~BoxedInvertedRampFacingPositiveZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.maxY - minY; + Scalar z = extents.maxZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingPositiveZ::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (z*rise >= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = minZ - maxZ; + ramp.normal.z = minY - maxY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = minY*ramp.normal.y + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveZ::TestInstance() const +{ + return solidType == InvertedRampFacingPositiveZType; +} + +//############################################################################# +//##################### BoxedInvertedRampFacingNegativeX ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeX::BoxedInvertedRampFacingNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingNegativeXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingNegativeX::~BoxedInvertedRampFacingNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - minX; + Scalar y = extents.maxY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingNegativeX::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (x*rise <= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = minX - maxX; + ramp.normal.x = maxY - minY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = minY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingNegativeX::TestInstance() const +{ + return solidType == InvertedRampFacingNegativeXType; +} + +//############################################################################# +//##################### BoxedInvertedRampFacingPositiveX ################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveX::BoxedInvertedRampFacingPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + InvertedRampFacingPositiveXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedInvertedRampFacingPositiveX::~BoxedInvertedRampFacingPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - maxX; + Scalar y = extents.maxY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= x*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedInvertedRampFacingPositiveX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------- + // If the point is above the ramp, it will hit the top of the ramp + //---------------------------------------------------------------- + // + if (point.y > maxY) + { + return point.y - maxY; + } + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + return (x*rise >= y*run) ? 0.0f : -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = minX - maxX; + ramp.normal.x = minY - maxY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = maxY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedInvertedRampFacingPositiveX::TestInstance() const +{ + return solidType == InvertedRampFacingPositiveXType; +} \ No newline at end of file diff --git a/MUNGA/BOXLIST.cpp b/MUNGA/BOXLIST.cpp new file mode 100644 index 0000000..14ff5e1 --- /dev/null +++ b/MUNGA/BOXLIST.cpp @@ -0,0 +1,311 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxlist.h" + +//############################################################################# +//######################### BoundingBoxListNode ######################### +//############################################################################# + +MemoryBlock *BoundingBoxListNode::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(BoundingBoxListNode), 500, 50, "BoundingBoxList Nodes"); + return &allocatedMemory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxListNode::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################### BoundingBoxList ########################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxList::BoundingBoxList() +{ + root = NULL; + nodeCount = 0; + scoreBoard = NULL; + boundingBoxIndex = NULL; + isXMajorAxis = True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxList::~BoundingBoxList() +{ + if (scoreBoard) + { + Unregister_Pointer(scoreBoard); + delete scoreBoard; + } + if (boundingBoxIndex) + { + Unregister_Pointer(boundingBoxIndex); + delete boundingBoxIndex; + } + EraseList(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Add( + BoundingBox* volume, + const ExtentBox &slice + ) +{ + Check(this); + Check(volume); + + ++nodeCount; + BoundingBoxListNode *node = new BoundingBoxListNode(volume, slice); + Register_Object(node); + node->previousNode = root; + root = node; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Remove(BoundingBox* volume) +{ + Check(this); + Check(volume); + + // + //-------------------------------------------------------------------------- + // Spin through all the boxes until we find the one we are after or until we + // run off the list + //-------------------------------------------------------------------------- + // + BoundingBoxListNode + *p = NULL, + *c = root; + while (c) + { + Check(c); + if (c->boundingBox == volume) + { + break; + } + p = c; + c = c->previousNode; + } + + // + //---------------------------------------------- + // Unlink the node from the list if it was found + //---------------------------------------------- + // + if (!c) + { + return; + } + + Check(c); + if (p) + { + Check(p); + p->previousNode = c->previousNode; + } + else + { + root = c->previousNode; + } + + // + //----------------- + // Delete this node + //----------------- + // + --nodeCount; + Unregister_Object(c); + delete c; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::EraseList() +{ + Check(this); + + // + //----------------------------- + // Delete each node in the list + //----------------------------- + // + BoundingBoxListNode *p = root; + while (p) + { + Check(p); + BoundingBoxListNode *q = p; + p = p->previousNode; + Unregister_Object(q); + delete q; + } + root = NULL; + nodeCount = 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxList::FindBoundingBoxContaining(const Point3D &point) +{ + Check(this); + Check(&point); + + // + //-------------------------------------------------------------------------- + // Spin through each of the boxes in reverse order until we find a box which + // contains the specified point. It will be default have priority over any + // boxes put in before it + //-------------------------------------------------------------------------- + // + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + if (box->Contains(point)) + { + return box; + } + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::FindBoundingBoxesContaining( + BoundingBox *volume, + BoundingBoxCollisionList &list + ) +{ + Check(this); + Check(volume); + Check(&list); + + // + //------------------------------------------------------------- + // Spin through each of the boxes in reverse order, looking for + // intesections between the test volume and the box list + //------------------------------------------------------------- + // + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + if (box->ExtentBox::Intersects(*volume)) + { + // + //---------------------------------------------------------------- + // Build the intersection slice, and make sure that it really does + // intersect the list box + //---------------------------------------------------------------- + // + ExtentBox slice; + slice.Intersect(*volume, *box); + if (box->IntersectsBounded(slice)) + { + + // + //------------------------------------------------------------ + // It intersects, so add this to the list. If we are out of + // collisions in the list, we are finished detecting, and just + // return + //------------------------------------------------------------ + // + Verify(list.collisionsLeft); + list.AddCollisionToList(box, slice); + if (!list.collisionsLeft) + { + return; + } + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxList::FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ) +{ + Check(this); + Check(&point); + Check_Pointer(height); + + // + //----------------------------------------------------------------------- + // Spin through each of the bounding boxes, keeping track of which box is + // hit after the shortest distance + //----------------------------------------------------------------------- + // + BoundingBox *best_box = NULL; + *height = -1.0f; + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + + Scalar h = box->FindDistanceBelow(point); + if (h != -1.0f) + { + if (!best_box || *height > h) + { + best_box = box; + *height = h; + } + } + } + return best_box; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxList::FindBoundingBoxHitBy(Line *line) +{ + // + //----------------------------------------------------------------------- + // Spin through each of the boxes, letting each box in turn clip the line + // lengths + //----------------------------------------------------------------------- + // + BoundingBox *best_box = NULL; + for (BoundingBoxListNode *p=root; p; p = p->previousNode) + { + Check(p); + BoundingBox *box = p->boundingBox; + Check(box); + + Logical h = box->HitBy(line); + if (h) + { + best_box = box; + } + } + return best_box; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxList::TestInstance() const +{ + return True; +} diff --git a/MUNGA/BOXLIST.h b/MUNGA/BOXLIST.h new file mode 100644 index 0000000..534d659 --- /dev/null +++ b/MUNGA/BOXLIST.h @@ -0,0 +1,147 @@ +#pragma once + +#include "bndgbox.h" +#include "memblock.h" + +//########################################################################## +//####################### BoundingBoxListNode ######################## +//########################################################################## + +class BoundingBoxList; +class BoxedSolidList; +class BoundingBoxTree; + +class BoundingBoxListNode SIGNATURED +{ + friend class BoundingBoxList; + friend class BoxedSolidList; + +//########################################################################## +// Memory Allocation +// +private: + static MemoryBlock* GetAllocatedMemory(); + + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } + +//########################################################################## +// Construction and Destruction +// +protected: + BoundingBox + *boundingBox; + BoundingBoxListNode + *previousNode; + + BoundingBoxListNode( + BoundingBox *volume, + const ExtentBox &slice + ): + boundingBox(volume), + solidSlice(slice), + previousNode(NULL) + {Check_Pointer(this); Check(volume);} + ~BoundingBoxListNode() + {Check(this);} + +public: + ExtentBox + solidSlice; + BoundingBox* + GetBoundingBox() + {Check(this); return boundingBox;} + BoundingBoxListNode* + GetNextNode() + {Check(this); return previousNode;} + +//########################################################################## +// Test Support +// +public: + Logical + TestInstance() const; +}; + +//########################################################################## +//######################## BoundingBoxList ########################### +//########################################################################## + +class BoundingBoxList SIGNATURED +{ + +//########################################################################## +// Construction and Destruction +// +protected: + BoundingBoxListNode + *root; + int + nodeCount; + int* + scoreBoard; + BoundingBox + **boundingBoxIndex; + Logical + isXMajorAxis; + +public: + BoundingBoxList(); + ~BoundingBoxList(); + + void + Add( + BoundingBox* volume, + const ExtentBox &slice + ); + void + Remove(BoundingBox* volume); + void + EraseList(); + + BoundingBoxListNode* + GetRoot() + {Check(this); return root;} + +//########################################################################## +// Tree Traversal Functions +// +public: + BoundingBox* + FindBoundingBoxContaining(const Point3D &point); + + void + FindBoundingBoxesContaining( + BoundingBox *volume, + BoundingBoxCollisionList &list + ); + + BoundingBox* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ); + + BoundingBox* + FindBoundingBoxHitBy(Line *line); + + void + Reduce(); + void + SortForTree(); + +protected: + void + Sort( + BoundingBoxList &active_solids, + ExtentBox &clipping_box, + BoundingBoxTree &tree_so_far + ); + +//########################################################################## +// Test Support +// +public: + Logical + TestInstance() const; +}; diff --git a/MUNGA/BOXRAMP.cpp b/MUNGA/BOXRAMP.cpp new file mode 100644 index 0000000..ccb9223 --- /dev/null +++ b/MUNGA/BOXRAMP.cpp @@ -0,0 +1,924 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "plane.h" +#include "line.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampContainsLine( + Line *line, + const Plane& plane, + Scalar enters, + Scalar leaves + ) +{ + // + //------------------------------------------------------------------------ + // Find the perpendicular distance from the origin of the ray to the ramp, + // and find the direction of the ray relative to the ramp + //------------------------------------------------------------------------ + // + Scalar distance = plane.DistanceTo(line->origin); + Scalar drift = line->direction*plane.normal; + + // + //-------------------------------------------------------------------------- + // If the ray is going out of the ramp and the origin of the + // ray is in the half-space that the plane's normal points to + //-------------------------------------------------------------------------- + // + if (drift > 0 && distance > 0) + { + return False; + } + + // + //-------------------------------------------------------------------------- + // If the ray is parallel to the ramp, the ray will hit if the origin of the + // ray is not in the half-space that the plane's normal points to + //-------------------------------------------------------------------------- + // + if (!drift) + { + if (distance <= 0.0f) + { + line->length = Max(enters, 0.0f); + return True; + } + return False; + } + + // + //-------------------------------------------------------------------- + // Otherwise, if the plane faces the ray, check to see how far the ray + // travels before hitting it + //-------------------------------------------------------------------- + // + if (drift < 0.0f) + { + distance /= -drift; + + // + //----------------------------------------------------------------------- + // If the ray strikes the plane after all other facing surfaces, then the + // ray enters the solid through this plane. So check to make sure that + // the ray does not miss the plane as clipped by the other surfaces, and + // if it hits, return this distance as the projection length. If the ray + // enters the ramp through an edge face of the bounding box, set the line + // length to the entering value calculated for the box + //----------------------------------------------------------------------- + // + if (distance > enters) + { + if (distance > leaves || distance > line->length) + { + return False; + } + enters = distance; + } + line->length = Max(enters, 0.0f); + return True; + } + + // + //------------------------------------------------------------------------ + // If the plane faces away from the ray, check to see how far the ray + // travels before exiting it, and ensure this is not before the ray enters + // the object + //------------------------------------------------------------------------ + // + distance /= -drift; + if (distance >= enters) + { + line->length = Max(enters, 0.0f); + return True; + } + return False; +} + +//############################################################################# +//######################### BoxedRampFacingNegativeZ #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeZ::BoxedRampFacingNegativeZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingNegativeZType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeZ::~BoxedRampFacingNegativeZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.minY - minY; + Scalar z = extents.minZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/z yields + // rise*z <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingNegativeZ::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*z; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = maxZ - minZ; + ramp.normal.z = maxY - minY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = maxY*ramp.normal.y + minZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeZ::TestInstance() const +{ + return solidType == RampFacingNegativeZType; +} + +//############################################################################# +//######################### BoxedRampFacingPositiveZ #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveZ::BoxedRampFacingPositiveZ( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingPositiveZType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveZ::~BoxedRampFacingPositiveZ() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = extents.minY - minY; + Scalar z = extents.maxZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/z slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/z yields + // rise*z >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return z*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingPositiveZ::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar rise = maxY - minY; + Scalar run = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar y = point.y - minY; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*z; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.x = 0.0f; + ramp.normal.y = maxZ - minZ; + ramp.normal.z = minY - maxY; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.z /= temp; + ramp.offset = minY*ramp.normal.y + minZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveZ::TestInstance() const +{ + return solidType == RampFacingPositiveZType; +} + +//############################################################################# +//######################### BoxedRampFacingNegativeX #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeX::BoxedRampFacingNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingNegativeXType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingNegativeX::~BoxedRampFacingNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - maxX; + Scalar y = extents.minY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= y/x yields + // rise*x <= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise <= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingNegativeX::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*x; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = maxX - minX; + ramp.normal.x = maxY - minY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = maxY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingNegativeX::TestInstance() const +{ + return solidType == RampFacingNegativeXType; +} + +//############################################################################# +//######################### BoxedRampFacingPositiveX #################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveX::BoxedRampFacingPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, RampFacingPositiveXType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedRampFacingPositiveX::~BoxedRampFacingPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - minX; + Scalar y = extents.minY - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= x*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than y/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= y/x yields + // rise*x >= y*run, which avoids any divide-by-0 errors + //------------------------------------------------------------------------ + // + return x*rise >= y*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedRampFacingPositiveX::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin. If the run is zero, make sure no divide by zero + // happens + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxY - minY; + Verify(!Small_Enough(run)); + + // + //---------------------------------------------------------- + // Get the point coordinates local the the start of the ramp + //---------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar y = point.y - minY; + + // + //------------------------------------------------------------------- + // Return the distance from the point to where it intersects the ramp + //------------------------------------------------------------------- + // + y -= (rise/run)*x; + return Max(y,0.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + Scalar + temp; + + // + //------------------------------------------------------------------- + // Make a vector pointing normal to the face of the north facing ramp + //------------------------------------------------------------------- + // + ramp.normal.y = maxX - minX; + ramp.normal.x = minY - maxY; + ramp.normal.z = 0.0f; + + // + //------------------------------------------------------------- + // Scale the vector to a normal and figure out the plane offset + //------------------------------------------------------------- + // + temp = ramp.normal.y*ramp.normal.y + ramp.normal.x*ramp.normal.x; + Verify(!Small_Enough(temp)) + temp = Sqrt(temp); + ramp.normal.y /= temp; + ramp.normal.x /= temp; + ramp.offset = minY*ramp.normal.y + minX*ramp.normal.x; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedRampFacingPositiveX::TestInstance() const +{ + return solidType == RampFacingPositiveXType; +} diff --git a/MUNGA/BOXSOLID.cpp b/MUNGA/BOXSOLID.cpp new file mode 100644 index 0000000..1c94dd6 --- /dev/null +++ b/MUNGA/BOXSOLID.cpp @@ -0,0 +1,1406 @@ +#include "munga.h" +#include "windows.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "fileutil.h" +#include "origin.h" +#include "linmtrx.h" +#include "line.h" +#include "notation.h" + +//############################################################################# +//############################## BoxedSolid ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid::BoxedSolid( + const ExtentBox &extents, + BoxedSolid::Type type, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + TaggedBoundingBox(extents, owner) +{ + + Check_Pointer(this); + solidType = type; + materialType = material; + nextSolid = next_solid; + if (nextSolid) + { + Check(nextSolid); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid::BoxedSolid( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid +): + TaggedBoundingBox(extents, owner) +{ + Check_Pointer(this); + solidType = BlockType; + materialType = material; + nextSolid = next_solid; + if (nextSolid) + { + Check(nextSolid); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid::~BoxedSolid() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid * + BoxedSolid::MakeBoxedSolid( + BoxedSolidResource *boxed_solid_resource, + Simulation *owner, + BoxedSolid *next_solid + ) +{ + + BoxedSolid *boxed_solid; + + switch(boxed_solid_resource->solidType) + { + case BoxedSolid::BlockType: + boxed_solid = + new BoxedSolid( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::SphereType: + boxed_solid = + new BoxedSphere( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::ConeType: + boxed_solid = + new BoxedCone( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::ReducibleBlockType: + boxed_solid = + new BoxedReducibleBlock( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingNegativeZType: + boxed_solid = + new BoxedRampFacingNegativeZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingNegativeXType: + boxed_solid = + new BoxedRampFacingNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingPositiveZType: + boxed_solid = + new BoxedRampFacingPositiveZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::RampFacingPositiveXType: + boxed_solid = + new BoxedRampFacingPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingNegativeZType: + boxed_solid = + new BoxedInvertedRampFacingNegativeZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingNegativeXType: + boxed_solid = + new BoxedInvertedRampFacingNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingPositiveZType: + boxed_solid = + new BoxedInvertedRampFacingPositiveZ( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::InvertedRampFacingPositiveXType: + boxed_solid = + new BoxedInvertedRampFacingPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingNegativeZAndPositiveXType: + boxed_solid = + new BoxedWedgeFacingNegativeZAndPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingNegativeZAndNegativeXType: + boxed_solid = + new BoxedWedgeFacingNegativeZAndNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingPositiveZAndNegativeXType: + boxed_solid = + new BoxedWedgeFacingPositiveZAndNegativeX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::WedgeFacingPositiveZAndPositiveXType: + boxed_solid = + new BoxedWedgeFacingPositiveZAndPositiveX( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::XAxisCylinderType: + boxed_solid = + new BoxedXAxisCylinder( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::YAxisCylinderType: + boxed_solid = + new BoxedYAxisCylinder( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; + case BoxedSolid::ZAxisCylinderType: + boxed_solid = + new BoxedZAxisCylinder( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid + ); + break; +#if 0 + case BoxedSolid::RightHandedTileType: + { + TileResource *terrain = + (TileResource*)boxed_solid_resource; + boxed_solid = + new RightHandedTile( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid, + terrain->cornerHeight + ); + } + break; + case BoxedSolid::LeftHandedTileType: + { + TileResource *terrain = + (TileResource*)boxed_solid_resource; + boxed_solid = + new LeftHandedTile( + boxed_solid_resource->solidExtents, + boxed_solid_resource->materialType, + owner, + next_solid, + terrain->cornerHeight + ); + } + break; +#endif + default: + boxed_solid = NULL; + } + + Check(boxed_solid); + return boxed_solid; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical +#if DEBUG_LEVEL>0 + BoxedSolid::VerifyCollision(BoxedSolidCollision &collision) +#else + BoxedSolid::VerifyCollision(BoxedSolidCollision &) +#endif +{ + Check(this); + Check(&collision); + + Verify(minX <= collision.collisionSlice.minX); + Verify(maxX >= collision.collisionSlice.maxX); + Verify(minY <= collision.collisionSlice.minY); + Verify(maxY >= collision.collisionSlice.maxY); + Verify(minZ <= collision.collisionSlice.minZ); + Verify(maxZ >= collision.collisionSlice.maxZ); + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSolid::ProcessCollision( + BoxedSolidCollision &, + const Vector3D &, + BoxedSolidCollisionList *, + Normal *, + Scalar * + ) +{ + Fail("Unsupported mover collision type!\n"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +Logical + BoxedSolid::TestInstance() const +{ + return solidType == BlockType; +} + +//############################################################################# +//########################## BoxedSolidResource ######################### +//############################################################################# + +static const BoxedSolid::Type + Left_90[BoxedSolid::SolidTypeCount]= +{ + BoxedSolid::BlockType, BoxedSolid::SphereType, + BoxedSolid::ConeType, BoxedSolid::ReducibleBlockType, + + BoxedSolid::RampFacingNegativeXType, + BoxedSolid::RampFacingPositiveZType, + BoxedSolid::RampFacingPositiveXType, + BoxedSolid::RampFacingNegativeZType, + + BoxedSolid::InvertedRampFacingNegativeXType, + BoxedSolid::InvertedRampFacingPositiveZType, + BoxedSolid::InvertedRampFacingPositiveXType, + BoxedSolid::InvertedRampFacingNegativeZType, + + BoxedSolid::WedgeFacingNegativeZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndPositiveXType, + + BoxedSolid::ZAxisCylinderType, + BoxedSolid::YAxisCylinderType, + BoxedSolid::XAxisCylinderType, + + BoxedSolid::LeftHandedTileType, + BoxedSolid::RightHandedTileType +}; + +static const BoxedSolid::Type + Left_180[BoxedSolid::SolidTypeCount]= +{ + BoxedSolid::BlockType, BoxedSolid::SphereType, + BoxedSolid::ConeType, BoxedSolid::ReducibleBlockType, + + BoxedSolid::RampFacingPositiveZType, + BoxedSolid::RampFacingPositiveXType, + BoxedSolid::RampFacingNegativeZType, + BoxedSolid::RampFacingNegativeXType, + + BoxedSolid::InvertedRampFacingPositiveZType, + BoxedSolid::InvertedRampFacingPositiveXType, + BoxedSolid::InvertedRampFacingNegativeZType, + BoxedSolid::InvertedRampFacingNegativeXType, + + BoxedSolid::WedgeFacingPositiveZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndNegativeXType, + + BoxedSolid::XAxisCylinderType, + BoxedSolid::YAxisCylinderType, + BoxedSolid::ZAxisCylinderType, + + BoxedSolid::RightHandedTileType, + BoxedSolid::LeftHandedTileType +}; + +static const BoxedSolid::Type + Left_270[BoxedSolid::SolidTypeCount]= +{ + BoxedSolid::BlockType, BoxedSolid::SphereType, + BoxedSolid::ConeType, BoxedSolid::ReducibleBlockType, + + BoxedSolid::RampFacingPositiveXType, + BoxedSolid::RampFacingNegativeZType, + BoxedSolid::RampFacingNegativeXType, + BoxedSolid::RampFacingPositiveZType, + + BoxedSolid::InvertedRampFacingPositiveXType, + BoxedSolid::InvertedRampFacingNegativeZType, + BoxedSolid::InvertedRampFacingNegativeXType, + BoxedSolid::InvertedRampFacingPositiveZType, + + BoxedSolid::WedgeFacingPositiveZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndPositiveXType, + BoxedSolid::WedgeFacingNegativeZAndNegativeXType, + BoxedSolid::WedgeFacingPositiveZAndNegativeXType, + + BoxedSolid::ZAxisCylinderType, + BoxedSolid::YAxisCylinderType, + BoxedSolid::XAxisCylinderType, + + BoxedSolid::LeftHandedTileType, + BoxedSolid::RightHandedTileType +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoxedSolidResource::Instance( + const BoxedSolidResource &source, + const Origin& origin + ) +{ + materialType = source.materialType; + solidType = source.solidType; + recordLength = source.recordLength; + + // + //------------------- + // Handle no rotation + //------------------- + // + if (Close_Enough(origin.angularPosition.w, 1.0f)) + { + solidType = source.solidType; + solidExtents = source.solidExtents; + sliceExtents = source.sliceExtents; + } + + // + //------------------------------- + // Test for a 180 degree rotation + //------------------------------- + // + else if (Close_Enough(fabs(origin.angularPosition.y), 1.0f)) + { + solidType = Left_180[source.solidType]; + solidExtents.minX = -source.solidExtents.maxX; + solidExtents.maxX = -source.solidExtents.minX; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = -source.solidExtents.maxZ; + solidExtents.maxZ = -source.solidExtents.minZ; + sliceExtents.minX = -source.sliceExtents.maxX; + sliceExtents.maxX = -source.sliceExtents.minX; + sliceExtents.minY = source.sliceExtents.minY; + sliceExtents.maxY = source.sliceExtents.maxY; + sliceExtents.minZ = -source.sliceExtents.maxZ; + sliceExtents.maxZ = -source.sliceExtents.minZ; + } + + // + //--------------------------------- + // Handle a 90 degree left rotation + //--------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, origin.angularPosition.y)) + { + solidType = Left_90[source.solidType]; + solidExtents.minX = source.solidExtents.minZ; + solidExtents.maxX = source.solidExtents.maxZ; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = -source.solidExtents.maxX; + solidExtents.maxZ = -source.solidExtents.minX; + sliceExtents.minX = source.sliceExtents.minZ; + sliceExtents.maxX = source.sliceExtents.maxZ; + sliceExtents.minY = source.sliceExtents.minY; + sliceExtents.maxY = source.sliceExtents.maxY; + sliceExtents.minZ = -source.sliceExtents.maxX; + sliceExtents.maxZ = -source.sliceExtents.minX; + } + + // + //---------------------------------- + // Handle a 90 degree right rotation + //---------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, -origin.angularPosition.y)) + { + solidType = Left_270[source.solidType]; + solidExtents.minX = -source.solidExtents.maxZ; + solidExtents.maxX = -source.solidExtents.minZ; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = source.solidExtents.minX; + solidExtents.maxZ = source.solidExtents.maxX; + sliceExtents.minX = -source.sliceExtents.maxZ; + sliceExtents.maxX = -source.sliceExtents.minZ; + sliceExtents.minY = source.sliceExtents.minY; + sliceExtents.maxY = source.sliceExtents.maxY; + sliceExtents.minZ = source.sliceExtents.minX; + sliceExtents.maxZ = source.sliceExtents.maxX; + } + + // + //------------------------------------------------------------------------- + // Handle an arbitrary rotation. Make sure that only vertically symetrical + // solids get here + //------------------------------------------------------------------------- + // + else if ( + source.solidType == BoxedSolid::YAxisCylinderType + || source.solidType == BoxedSolid::ConeType + || source.solidType == BoxedSolid::SphereType + ) + { + solidType = source.solidType; + Verify(source.solidExtents.minX == source.sliceExtents.minX); + Verify(source.solidExtents.maxX == source.sliceExtents.maxX); + Verify(source.solidExtents.minY == source.sliceExtents.minY); + Verify(source.solidExtents.maxY == source.sliceExtents.maxY); + Verify(source.solidExtents.minZ == source.sliceExtents.minZ); + Verify(source.solidExtents.maxZ == source.sliceExtents.maxZ); + Vector3D center; + center.x = (source.solidExtents.minX + source.solidExtents.maxX) * 0.5f; + center.y = source.solidExtents.minY; + center.z = (source.solidExtents.minZ + source.solidExtents.maxZ) * 0.5f; + Scalar radius = center.x - source.solidExtents.minX; + LinearMatrix m; + m = origin.angularPosition; + Vector3D translated; + translated.Multiply(center, m); + + solidExtents.minX = translated.x - radius; + solidExtents.maxX = translated.x + radius; + solidExtents.minY = source.solidExtents.minY; + solidExtents.maxY = source.solidExtents.maxY; + solidExtents.minZ = translated.z - radius; + solidExtents.maxZ = translated.z + radius; + sliceExtents = solidExtents; + } + + // + //---------------- + // Otherwise, barf + //---------------- + // + #if defined(LAB_ONLY) + else + { + Fail("Illegal solid for a non-90 degree rotation!\n"); + } + #endif + + solidExtents.minX += origin.linearPosition.x; + solidExtents.maxX += origin.linearPosition.x; + solidExtents.minY += origin.linearPosition.y; + solidExtents.maxY += origin.linearPosition.y; + solidExtents.minZ += origin.linearPosition.z; + solidExtents.maxZ += origin.linearPosition.z; + sliceExtents.minX += origin.linearPosition.x; + sliceExtents.maxX += origin.linearPosition.x; + sliceExtents.minY += origin.linearPosition.y; + sliceExtents.maxY += origin.linearPosition.y; + sliceExtents.minZ += origin.linearPosition.z; + sliceExtents.maxZ += origin.linearPosition.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + TileResource::Instance( + const TileResource &source, + const Origin& origin + ) +{ + BoxedSolidResource::Instance(source, origin); + + // + //------------------------------- + // Test for a 180 degree rotation + //------------------------------- + // + if (Close_Enough(fabs(origin.angularPosition.y), 1.0f)) + { + cornerHeight[0] = source.cornerHeight[3]; + cornerHeight[1] = source.cornerHeight[2]; + cornerHeight[2] = source.cornerHeight[1]; + cornerHeight[3] = source.cornerHeight[0]; + } + + // + //--------------------------------- + // Handle a 90 degree left rotation + //--------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, origin.angularPosition.y)) + { + cornerHeight[0] = source.cornerHeight[1]; + cornerHeight[1] = source.cornerHeight[3]; + cornerHeight[2] = source.cornerHeight[0]; + cornerHeight[3] = source.cornerHeight[2]; + } + + // + //---------------------------------- + // Handle a 90 degree right rotation + //---------------------------------- + // + else if (Close_Enough(origin.angularPosition.w, -origin.angularPosition.y)) + { + cornerHeight[0] = source.cornerHeight[2]; + cornerHeight[1] = source.cornerHeight[0]; + cornerHeight[2] = source.cornerHeight[3]; + cornerHeight[3] = source.cornerHeight[1]; + } +} + +//############################################################################# + +ResourceDescription::ResourceID + BoxedSolidResource::CreateBoxedSolidStream( + const char *entry_data, + ResourceFile *file, + const ResourceDirectories *resource_directories, + Logical convert_boxes + ) +{ + char *filename = + MakePathedFilename(resource_directories->collisionDirectory, entry_data); + Register_Pointer(filename); + + NotationFile *collision_file = new NotationFile(filename); + Unregister_Pointer(filename); + delete filename; + Register_Object(collision_file); + + + ResourceDescription::ResourceID collision_ID; + + if (collision_file->PageCount()) + { +// LAB_ONLY |= collision_file->IsMarkedLabOnly(); + + BoxedSolidList *box_solid_list = new BoxedSolidList; + Register_Object(box_solid_list); + + int size = box_solid_list->AddBoxedSolids(collision_file); + + BoxedSolidResource *boxed_solid_resource = + new BoxedSolidResource[size]; + Register_Pointer(boxed_solid_resource); + + int j = 0; + + + BoundingBoxListNode *p; + + for (p = box_solid_list->GetRoot(); p; p = p->GetNextNode()) + { + Verify(j < size); + Check(p); + BoxedSolid *box = (BoxedSolid *)p->GetBoundingBox(); + Check(box); + + boxed_solid_resource[j].materialType = box->materialType; + + if ((box->solidType == BoxedSolid::BlockType) && (convert_boxes)) + { + boxed_solid_resource[j].solidType = BoxedSolid::ReducibleBlockType; + } + else + { + boxed_solid_resource[j].solidType = box->solidType; + } + + boxed_solid_resource[j].solidExtents = *box; + boxed_solid_resource[j].sliceExtents = p->solidSlice; + boxed_solid_resource[j].recordLength = sizeof(boxed_solid_resource[j]); + + ++j; + } + + for (p = box_solid_list->GetRoot(); p; p = p->GetNextNode()) + { + + Check(p); + BoxedSolid *box = (BoxedSolid *)p->GetBoundingBox(); + Check(box); + + Unregister_Object(box); + delete(box); + + } + + ResourceDescription *res_description = file->FindResourceDescription(entry_data, + ResourceDescription::BoxedSolidStreamResourceType); + + if(res_description == NULL) + { + collision_ID = + file->AddResource( + entry_data, + ResourceDescription::BoxedSolidStreamResourceType, + 1, + ResourceDescription::Preload, + boxed_solid_resource, + size * sizeof(BoxedSolidResource) + )->resourceID; + } + else + { + collision_ID = res_description->resourceID; + } + + Unregister_Pointer(boxed_solid_resource); + delete boxed_solid_resource; + + Unregister_Object(box_solid_list); + delete box_solid_list; + + } + else + { + //---------------------------------------------- + // display warning that collision file is empty + //---------------------------------------------- + DEBUG_STREAM << "** Collision file '" << entry_data << "' empty or not found. **" << std::endl << std::flush; + //---------------------------------------------- + // continue to show all missing collision files + //---------------------------------------------- + } + + Unregister_Object(collision_file); + delete collision_file; + + return collision_ID; +} +//############################################################################# +//########################## BoxedSolidCollision ######################## +//############################################################################# + +static const int + Cant_Occlude[BoxedSolid::SolidTypeCount]= +{ + 0, 1<<(X_Axis|Y_Axis|Z_Axis), 1<<(X_Axis|Z_Axis), 0, + 1<solidType] & (1<solidType != second->solidType + ) + { + continue; + } + + // + //---------------------------------------------------------------------- + // Figure out what face to check against, and make sure that the face of + // the possibly occluding slice is nearer than the other slice + //---------------------------------------------------------------------- + // + int face = (axis<<1) + (velocity[axis] < 0.0f); + int opposite_face = face^1; + if (face&1) + { + if (first->solidType == BoxedSolid::BlockType) + { + if (collisionSlice[face] <= collision.collisionSlice[face]) + { + continue; + } + } + else if ( + collisionSlice[opposite_face] < collision.collisionSlice[face] + ) + { + continue; + } + } + else + { + if (first->solidType == BoxedSolid::BlockType) + { + if (collisionSlice[face] >= collision.collisionSlice[face]) + { + continue; + } + } + else if ( + collisionSlice[opposite_face] > collision.collisionSlice[face] + ) + { + continue; + } + } + + // + //------------------------------------------------------------------ + // Check the faces on the other axes to make sure that the occluding + // object at least covers the extent of the occluded object + //------------------------------------------------------------------ + // + for (face=0; face<6; ++face) + { + if ((face>>1) == axis) + { + continue; + } + if (face&1) + { + if (collisionSlice[face] < collision.collisionSlice[face]) + { + break; + } + } + else if (collisionSlice[face] > collision.collisionSlice[face]) + { + break; + } + } + + // + //----------------------------------------------------------------------- + // If everything checked out, then List[i] occludes List[j]. Stretch the + // definition of List[i] to include the slice occluded if necessary + //----------------------------------------------------------------------- + // + if (face == 6) + { + face = axis<<1; + if (velocity[axis] > 0.0f) + { + ++face; + collisionSlice[face] = + Max(collisionSlice[face], collision.collisionSlice[face]); + } + else + { + collisionSlice[face] = + Min(collisionSlice[face], collision.collisionSlice[face]); + } + return True; + } + } + return False; +} + +//############################################################################# +//######################## BoxedSolidCollisionList ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoxedSolidCollisionList::ReduceCollisionList(const Vector3D &velocity) +{ + Check(this); + Check(&velocity); + + int + i,j; + + // + //-------------------------------------------------------------------------- + // Fuse the collision slices together into the largest possible chunks based + // upon the collision model of each of the involved slices. Repeat until no + // fusings were made in the last pass or only one collision slice remains + //-------------------------------------------------------------------------- + // + Logical again = True; + int collisions = GetCollisionCount(); + phantomCollisions = 0; + while (again && collisions>1) + { + again = False; + + // + //-------------------------------------------------------------------- + // Check each collision slice against the remaining slices in the list + //-------------------------------------------------------------------- + // + for (i=0; iGetTreeVolume()->solidType + != second->GetTreeVolume()->solidType + ) + { + continue; + } + + // + //---------------------------------------------------- + // Make sure that the faces on two sets of sides match + //---------------------------------------------------- + // + + int matches = 0; + int face = -1; + for (int side=0; side<6; side += 2) + { + if ( + first->collisionSlice[side] == second->collisionSlice[side] + && first->collisionSlice[side+1] + == second->collisionSlice[side+1] + ) + { + ++matches; + } + else if (face<0) + { + face = side; + } + } + if (matches != 2) + { + continue; + } + + // + //---------------------------------------------------------------- + // Check to make sure that the two slices have an opposing face in + // common, which will allow the slices to be fused + //---------------------------------------------------------------- + // + if ( + first->collisionSlice[face] != second->collisionSlice[face+1] + && first->collisionSlice[face+1] + != second->collisionSlice[face] + ) + { + continue; + } + + // + //---------------------------------------------------------------- + // Find the face to fuse, then find out which solid description to + // use based upon the velocity vector + //---------------------------------------------------------------- + // + if (first->collisionSlice[face+1] == second->collisionSlice[face]) + { + ++face; + } + BoxedSolid *original = NULL; + if ( + first->GetTreeVolume() != second->GetTreeVolume() + && second->Occludes(*first, velocity) + ) + { + original = first->GetTreeVolume(); + first->treeVolume = second->GetTreeVolume(); + } + + // + //------------------------- + // Fuse the blocks together + //------------------------- + // + first->collisionSlice[face] = second->collisionSlice[face]; + + // + //----------------------------------------------- + // Erase the second slice from the collision list + //----------------------------------------------- + // + for (int k=j+1; k1) + { + // + //-------------------------- + // Erase the occlusion table + //-------------------------- + // + Logical* occluded = new Logical[collisions]; + Register_Pointer(occluded); + BoxedSolid **volumes = new BoxedSolid* [collisions]; + Register_Pointer(volumes); + for (i=0; ij) + { + listStart[j] = listStart[i]; + } + ++j; + } + else + { + volumes[++occludeds] = (BoxedSolid*)listStart[i].treeVolume; + } + } + i = 0; + while (j= point.x && minY <= point.y + && minZ <= point.z && maxZ >= point.z + ) + { + Scalar result = point.y - maxY; + return Max(result, 0.0f); + } + else + { + return -1.0f; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedReducibleBlock::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Scalar + perpendicular, + drift, + distance; + + // + //-------------------- + // Set up for the test + //-------------------- + // + for (int i=0; i<6; ++i) + { + // + //-------------------------------------------------------------------- + // Figure out what axis we are dealing with, then based upon the + // direction of the face, find out the distance from the origin to the + // place against the normal, and find out how fast the perpendicular + // distance changes with a unit movement along the line + //-------------------------------------------------------------------- + // + int face = i; + int axis = face >> 1; + if (face&1) + { + perpendicular = line->origin[axis] - (*this)[face]; + drift = line->direction[axis]; + } + else + { + perpendicular = (*this)[face] - line->origin[axis]; + drift = -line->direction[axis]; + } + + // + //------------------------------------------------------------------- + // If the line is parallel to the face, figure out whether or not the + // line origin lies within the face's half-space + //------------------------------------------------------------------- + // + if (Small_Enough(drift)) + { + if (perpendicular > 0.0f) + { + return False; + } + else + { + continue; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + distance = -perpendicular / drift; + if (drift < 0.0f) + { + if (distance > enters) + { + enters = distance; + } + if (enters > line->length) + { + return False; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + else + { + if (distance < leaves) + { + leaves = distance; + } + if (leaves < 0.0f) + { + return False; + } + } + } + + // + //----------------------------------------------------------------------- + // If we exit the loop, then make sure that we actually hit the interior, + // and let the box figure out if the what happens inside it + //----------------------------------------------------------------------- + // + if (enters <= leaves) + { + line->length = Max(enters, 0.0f); + return True; + } + else + { + return False; + } +} + +//############################################################################# +//########################### BoxedSolidList ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +int + BoxedSolidList::AddBoxedSolids(NotationFile *notation_file) +{ + char page_name[50]; + int solidnumber = 0; + int type; + + BoxedSolidResource boxed_solid_resource; + BoxedSolid *boxed_solid; + + + if (!notation_file->GetEntry("COLLISION", "count", &solidnumber)) + { + DEBUG_STREAM << "No 'COLLISION' entry!!!!!" << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + for (int j=0; j < solidnumber; ++j) + { + sprintf(page_name, "volume %d", j); + + if (!notation_file->GetEntry(page_name, "TypeNumber", &type)) + { + DEBUG_STREAM << "No solid at collision number : " << j << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + boxed_solid_resource.solidType = (BoxedSolid::Type)type; + + if (!notation_file->GetEntry(page_name, "MaterialNumber", &type)) + { + DEBUG_STREAM << "No material at collision number : " << j << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + boxed_solid_resource.materialType = (BoxedSolid::Material)type; + + int errorvalue = 0; + + errorvalue |= !notation_file->GetEntry(page_name, "extminX", &(boxed_solid_resource.solidExtents.minX)); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxX", &(boxed_solid_resource.solidExtents.maxX)); + errorvalue |= !notation_file->GetEntry(page_name, "extminY", &(boxed_solid_resource.solidExtents.minY)); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxY", &(boxed_solid_resource.solidExtents.maxY)); + errorvalue |= !notation_file->GetEntry(page_name, "extminZ", &(boxed_solid_resource.solidExtents.minZ)); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxZ", &(boxed_solid_resource.solidExtents.maxZ)); + + if ( errorvalue ) + { + DEBUG_STREAM << "Collision number : " << j + << " does not have valid extents\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + errorvalue = 0; + errorvalue |= !notation_file->GetEntry(page_name, "slcminX", &(boxed_solid_resource.sliceExtents.minX)); + errorvalue |= !notation_file->GetEntry(page_name, "slcmaxX", &(boxed_solid_resource.sliceExtents.maxX)); + errorvalue |= !notation_file->GetEntry(page_name, "slcminY", &(boxed_solid_resource.sliceExtents.minY)); + errorvalue |= !notation_file->GetEntry(page_name, "slcmaxY", &(boxed_solid_resource.sliceExtents.maxY)); + errorvalue |= !notation_file->GetEntry(page_name, "slcminZ", &(boxed_solid_resource.sliceExtents.minZ)); + errorvalue |= !notation_file->GetEntry(page_name, "slcmaxZ", &(boxed_solid_resource.sliceExtents.maxZ)); + + if ( errorvalue ) + { + DEBUG_STREAM << "Collision number : " << j + << " does not have valid slice extents\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + + boxed_solid = + BoxedSolid::MakeBoxedSolid(&boxed_solid_resource, NULL, NULL); + + Register_Object(boxed_solid); + + Add(boxed_solid, boxed_solid_resource.sliceExtents); + } + + return solidnumber; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + + +#if defined(TEST_CLASS) +# include "boxsolid.tcp" +#endif diff --git a/MUNGA/BOXSOLID.h b/MUNGA/BOXSOLID.h new file mode 100644 index 0000000..5ea9977 --- /dev/null +++ b/MUNGA/BOXSOLID.h @@ -0,0 +1,976 @@ +#pragma once + +#include "bndgbox.h" +#include "boxtree.h" +#include "boxlist.h" +#include "resource.h" + +struct BoxedSolidResource; +class BoxedSolidCollision; +class BoxedSolidCollisionList; +class Simulation; +class NotationFile; +class Normal; + +//########################################################################## +//########################### BoxedSolid ############################# +//########################################################################## + +class BoxedSolid: + public TaggedBoundingBox +{ +public: + enum Type { + BlockType=0, + SphereType=1, + ConeType=2, + ReducibleBlockType=3, + RampType=4, + RampFacingNegativeZType=4, + RampFacingNegativeXType, + RampFacingPositiveZType, + RampFacingPositiveXType, + InvertedRampType=8, + InvertedRampFacingNegativeZType=8, + InvertedRampFacingNegativeXType, + InvertedRampFacingPositiveZType, + InvertedRampFacingPositiveXType, + WedgeType=12, + WedgeFacingNegativeZAndPositiveXType=12, + WedgeFacingNegativeZAndNegativeXType, + WedgeFacingPositiveZAndNegativeXType, + WedgeFacingPositiveZAndPositiveXType, + XAxisCylinderType=16, + YAxisCylinderType=17, + ZAxisCylinderType=18, + RightHandedTileType=19, + LeftHandedTileType=20, + SolidTypeCount + } + solidType; + + enum Material { + StoneMaterial = 0, + GravelMaterial, + ConcreteMaterial, + SteelMaterial, + WoodMaterial, + RockMaterial, + OurCraftMaterial, + OtherCraftMaterial, + MaterialCount + } + materialType; + + BoxedSolid( + const ExtentBox &extents, + Type type, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + BoxedSolid( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedSolid(); + + static BoxedSolid* + MakeBoxedSolid( + BoxedSolidResource *resource, + Simulation *owner, + BoxedSolid *next_solid + ); + + virtual Logical + VerifyCollision(BoxedSolidCollision &collision); + virtual Logical + ProcessCollision( + BoxedSolidCollision &collision, + const Vector3D &velocity, + BoxedSolidCollisionList *last_collisions, + Normal *normal, + Scalar *penetration + ); + + Logical + TestInstance() const; + static Logical + TestClass(); + + Simulation* + GetOwningSimulation() + {Check(this); return (Simulation*)GetTagPointer();} + BoxedSolid* + GetNextSolid() + {Check(this); return nextSolid;} + + protected: + BoxedSolid + *nextSolid; +}; + +//########################################################################## +//####################### BoxedSolidCollision ######################## +//########################################################################## + +class BoxedSolidCollision: + public BoundingBoxCollision +{ +public: + BoxedSolid* + GetTreeVolume() + {Check(this); return (BoxedSolid*)treeVolume;} + Logical + Occludes( + BoxedSolidCollision &collision, + const Vector3D &velocity + ); +}; + +//########################################################################## +//##################### BoxedSolidCollisionList ###################### +//########################################################################## + +class BoxedSolidCollisionList: + public BoundingBoxCollisionList +{ +protected: + int phantomCollisions; + +public: + BoxedSolidCollisionList(int max_length = 10): + BoundingBoxCollisionList(max_length) + {Reset();} + void + Reset() + {phantomCollisions = 0; BoundingBoxCollisionList::Reset();} + + BoxedSolidCollision& + operator[](int index) + { + Check(this); Verify((unsigned)index < maxCollisions); + return ((BoxedSolidCollision*)listStart)[index]; + } + int + GetRealCollisions() + {Check(this); return GetCollisionCount() - phantomCollisions;} + + void + ReduceCollisionList(const Vector3D &velocity); +}; + +//########################################################################## +//####################### BoxedSolidResource ######################### +//########################################################################## + +struct BoxedSolidResource +{ + size_t recordLength; + ExtentBox + solidExtents, + sliceExtents; + BoxedSolid::Type solidType; + BoxedSolid::Material materialType; + + void + Instance( + const BoxedSolidResource &source, + const Origin& origin + ); + + static ResourceDescription::ResourceID + CreateBoxedSolidStream( + const char *entry_data, + ResourceFile *file, + const ResourceDirectories *resource_directories, + Logical convert_boxes = False + ); +}; + +//########################################################################## +//########################### BoxedSphere ############################ +//########################################################################## + +class BoxedSphere: + public BoxedSolid +{ +public: + BoxedSphere( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedSphere(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//############################ BoxedCone ############################# +//########################################################################## + +class BoxedCone: + public BoxedSolid +{ +public: + BoxedCone( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedCone(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//####################### BoxedReducibleBlock ######################## +//########################################################################## + +class BoxedReducibleBlock: + public BoxedSolid +{ +public: + BoxedReducibleBlock( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedReducibleBlock(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//###################### BoxedRampFacingNegativeZ #################### +//########################################################################## + +class BoxedRampFacingNegativeZ: + public BoxedSolid +{ +public: + BoxedRampFacingNegativeZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingNegativeZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//#################### BoxedRampFacingPositiveX ###################### +//########################################################################## + +class BoxedRampFacingPositiveX: + public BoxedSolid +{ +public: + BoxedRampFacingPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//#################### BoxedRampFacingPositiveZ ###################### +//########################################################################## + +class BoxedRampFacingPositiveZ: + public BoxedSolid +{ +public: + BoxedRampFacingPositiveZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingPositiveZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//#################### BoxedRampFacingNegativeX ###################### +//########################################################################## + +class BoxedRampFacingNegativeX: + public BoxedSolid +{ +public: + BoxedRampFacingNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedRampFacingNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//################## BoxedInvertedRampFacingNegativeZ ################ +//########################################################################## + +class BoxedInvertedRampFacingNegativeZ: + public BoxedSolid +{ +public: + BoxedInvertedRampFacingNegativeZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingNegativeZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//################## BoxedInvertedRampFacingNegativeX ################ +//########################################################################## + +class BoxedInvertedRampFacingNegativeX: + public BoxedSolid +{ +public: + BoxedInvertedRampFacingNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//################## BoxedInvertedRampFacingPositiveZ ################ +//########################################################################## + +class BoxedInvertedRampFacingPositiveZ: + public BoxedSolid +{ +public: + BoxedInvertedRampFacingPositiveZ( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingPositiveZ(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//################## BoxedInvertedRampFacingPositiveX ################ +//########################################################################## + +class BoxedInvertedRampFacingPositiveX: + public BoxedSolid +{ +public: + BoxedInvertedRampFacingPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedInvertedRampFacingPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//############## BoxedWedgeFacingNegativeZAndPositiveX ############### +//########################################################################## + +class BoxedWedgeFacingNegativeZAndPositiveX: + public BoxedSolid +{ +public: + BoxedWedgeFacingNegativeZAndPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingNegativeZAndPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//############## BoxedWedgeFacingPositiveZAndPositiveX ############### +//########################################################################## + +class BoxedWedgeFacingPositiveZAndPositiveX: + public BoxedSolid +{ +public: + BoxedWedgeFacingPositiveZAndPositiveX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingPositiveZAndPositiveX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//############## BoxedWedgeFacingPositiveZAndNegativeX ############### +//########################################################################## + +class BoxedWedgeFacingPositiveZAndNegativeX: + public BoxedSolid +{ +public: + BoxedWedgeFacingPositiveZAndNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingPositiveZAndNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//############## BoxedWedgeFacingNegativeZAndNegativeX ############### +//########################################################################## + +class BoxedWedgeFacingNegativeZAndNegativeX: + public BoxedSolid +{ +public: + BoxedWedgeFacingNegativeZAndNegativeX( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedWedgeFacingNegativeZAndNegativeX(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//####################### BoxedXAxisCylinder ######################### +//########################################################################## + +class BoxedXAxisCylinder: + public BoxedSolid +{ +public: + BoxedXAxisCylinder( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedXAxisCylinder(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//####################### BoxedYAxisCylinder ######################### +//########################################################################## + +class BoxedYAxisCylinder: + public BoxedSolid +{ +public: + BoxedYAxisCylinder( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedYAxisCylinder(); + + Logical + VerifyCollision(BoxedSolidCollision &collision); + Logical + ProcessCollision( + BoxedSolidCollision &collision, + const Vector3D &velocity, + BoxedSolidCollisionList *last_collisions, + Normal *normal, + Scalar *penetration + ); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//####################### BoxedZAxisCylinder ######################### +//########################################################################## + +class BoxedZAxisCylinder: + public BoxedSolid +{ +public: + BoxedZAxisCylinder( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid + ); + ~BoxedZAxisCylinder(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//##################### RightHandedTile ####################### +//########################################################################## + +class RightHandedTile: + public BoxedSolid +{ +public: + RightHandedTile( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *cornerHeights, + Type type=RightHandedTileType + ); + ~RightHandedTile(); + + Scalar + cornerHeight[4]; + + Logical + IntersectsBounded(const ExtentBox &extents); + Logical + ContainsBounded(const Point3D &point); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//######################## LeftHandedTile ######################### +//########################################################################## + +class LeftHandedTile: + public RightHandedTile +{ +public: + LeftHandedTile( + const ExtentBox &extents, + Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *cornerHeights + ); + ~LeftHandedTile(); + + Logical + IntersectsBounded(const ExtentBox &extents); + Scalar + FindDistanceBelowBounded(const Point3D &point); + Logical + HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ); + + Logical + TestInstance() const; +}; + +//########################################################################## +//####################### TerrainTileResource ######################## +//########################################################################## + +struct TileResource: + public BoxedSolidResource +{ + Scalar + cornerHeight[4]; + + void + Instance( + const TileResource &source, + const Origin& origin + ); +}; + +//########################################################################## +//######################## BoxedSolidTree ############################ +//########################################################################## + +class BoxedSolidTree: + public BoundingBoxTree +{ + +//########################################################################## +// Construction and Destruction +// +public: + BoxedSolidTree() + {} + ~BoxedSolidTree() + {} + +//########################################################################## +// Tree Traversal Functions +// +public: + BoxedSolid* + FindBoundingBoxContaining(const Point3D &point) + { + return + (BoxedSolid*) + BoundingBoxTree::FindBoundingBoxContaining(point); + } + + BoxedSolid* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ) + { + return + (BoxedSolid*) + BoundingBoxTree::FindBoundingBoxUnder(point, height); + } + + BoxedSolid* + FindBoundingBoxHitBy(Line *line) + {return (BoxedSolid*)BoundingBoxTree::FindBoundingBoxHitBy(line);} +}; + +//########################################################################## +//######################## BoxedSolidList ############################ +//########################################################################## + +class BoxedSolidList: + public BoundingBoxList +{ +//########################################################################## +// Construction and Destruction +// +public: + BoxedSolidList() {} + ~BoxedSolidList() {} + +//########################################################################## +// Tree Traversal Functions +// +public: + int + AddBoxedSolids(NotationFile *notation_file); + + BoxedSolid* + FindBoundingBoxContaining(const Point3D &point) + { + return + (BoxedSolid*) + BoundingBoxList::FindBoundingBoxContaining(point); + } + + BoxedSolid* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ) + { + return + (BoxedSolid*) + BoundingBoxList::FindBoundingBoxUnder(point, height); + } + + BoxedSolid* + FindBoundingBoxHitBy(Line *line) + {return (BoxedSolid*)BoundingBoxList::FindBoundingBoxHitBy(line);} + + void + Reduce(); +}; diff --git a/MUNGA/BOXSORT.cpp b/MUNGA/BOXSORT.cpp new file mode 100644 index 0000000..17035d5 --- /dev/null +++ b/MUNGA/BOXSORT.cpp @@ -0,0 +1,474 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "vector3d.h" + +//############################################################################# +//########################### BoxedSolidList ############################ +//############################################################################# + +enum { + X_Axis_Bit = 1, + Y_Axis_Bit = 2, + Z_Axis_Bit = 4 +}; + +enum { + Min_Side = 0x001, + Inside = 0x002, + Max_Side = 0x004, + Both_Sides = Min_Side|Max_Side, + Shift = 3, + X_Shift = 2 * Shift, + Min_X_Side = Min_Side << X_Shift, + Inside_X = Inside << X_Shift, + Max_X_Side = Max_Side << X_Shift, + X_Mask = Min_X_Side|Inside_X|Max_X_Side, + Y_Shift = Shift, + Min_Y_Side = Min_Side << Y_Shift, + Inside_Y = Inside << Y_Shift, + Max_Y_Side = Max_Side << Y_Shift, + Y_Mask = Min_Y_Side|Inside_Y|Max_Y_Side, + Z_Shift = 0, + Min_Z_Side = Min_Side << Z_Shift, + Inside_Z = Inside << Z_Shift, + Max_Z_Side = Max_Side << Z_Shift, + Z_Mask = Min_Z_Side|Inside_Z|Max_Z_Side +}; + +int + Legal_To_Fuse[BoxedSolid::SolidTypeCount]= +{ + X_Axis_Bit|Y_Axis_Bit|Z_Axis_Bit, 0, 0, 0, + X_Axis_Bit, Z_Axis_Bit, X_Axis_Bit, Z_Axis_Bit, + X_Axis_Bit, Z_Axis_Bit, X_Axis_Bit, Z_Axis_Bit, + Y_Axis_Bit, Y_Axis_Bit, Y_Axis_Bit, Y_Axis_Bit, + X_Axis_Bit, Y_Axis_Bit, Z_Axis_Bit +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Reduce() +{ + Check(this); + + BoundingBoxListNode + *i, *j, *previous; + + // + //-------------------------------------------------------------------------- + // Fuse the collision slices together into the largest possible chunks based + // upon the collision model of each of the involved slices. Repeat until no + // fusings were made in the last pass or only one collision slice remains + //-------------------------------------------------------------------------- + // + Logical again = True; + while (again) + { + again = False; + + // + //-------------------------------------------------------------------- + // Check each collision slice against the remaining slices in the list + //-------------------------------------------------------------------- + // + for (i=root; i; i = i->previousNode) + { + Check(i); + previous = i; + j = i->previousNode; + while (j) + { + Check(j); + // + //------------------------------------------------------------- + // If the model types are different, these two slices cannot be + // fused + //------------------------------------------------------------- + // + BoundingBox *first = i->boundingBox; + BoundingBox *second = j->boundingBox; + + // + //---------------------------------------------------- + // Make sure that the faces on two sets of sides match + //---------------------------------------------------- + // + int matches = 0; + int face = -1; + for (int side=0; side<6; side += 2) + { + if ( + (*first)[side] == (*second)[side] + && (*first)[side+1] == (*second)[side+1] + ) + { + ++matches; + } + else if (face<0) + { + face = side; + } + } + if (matches != 2) + { +Next_Solid: + previous = j; + j = j->previousNode; + continue; + } + + // + //---------------------------------------------------------------- + // Check to make sure that the two solids have an opposing face in + // common, which will allow the solids to be fused + //---------------------------------------------------------------- + // + if ( + (*first)[face] != (*second)[face+1] + && (*first)[face+1] != (*second)[face] + ) + { + goto Next_Solid; + } + + // + //---------------------------------------------------- + // Find the face to fuse, and fuse the blocks together + //---------------------------------------------------- + // + if ((*first)[face+1] == (*second)[face]) + { + ++face; + } + (*first)[face] = (*second)[face]; + + // + //----------------------------------------------- + // Erase the second solid from the collision list + //----------------------------------------------- + // + --nodeCount; + if (previous) + { + previous->previousNode = j->previousNode; + Unregister_Object(j); + delete(j); + j = previous->previousNode; + } + else + { + root = j->previousNode; + Unregister_Object(j); + delete(j); + j = root; + } + again = True; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::SortForTree() +{ + Check(this); + + int + i, j; + BoundingBoxListNode + *p, *q; + + // + //----------------------------------------------------------------------- + // Find out how many collision solids are in the list, and figure out the + // total extent box so that we can set the traversal order correctly + //----------------------------------------------------------------------- + // + ExtentBox map_extents; + map_extents.minX = 65535.9999f; + map_extents.minY = 65535.9999f; + map_extents.minZ = 65535.9999f; + map_extents.maxX = -65535.9999f; + map_extents.maxY = -65535.9999f; + map_extents.maxZ = -65535.9999f; + for (p=root; p; p = p->previousNode) + { + Check(p); + if (p->boundingBox->minX < map_extents.minX) + { + map_extents.minX = p->boundingBox->minX; + } + if (p->boundingBox->maxX > map_extents.maxX) + { + map_extents.maxX = p->boundingBox->maxX; + } + + if (p->boundingBox->minY < map_extents.minY) + { + map_extents.minY = p->boundingBox->minY; + } + if (p->boundingBox->maxY > map_extents.maxY) + { + map_extents.maxY = p->boundingBox->maxY; + } + + if (p->boundingBox->minZ < map_extents.minZ) + { + map_extents.minZ = p->boundingBox->minZ; + } + if (p->boundingBox->maxZ > map_extents.maxZ) + { + map_extents.maxZ = p->boundingBox->maxZ; + } + } + if ( + map_extents.maxZ - map_extents.minZ + > map_extents.maxX - map_extents.minX + ) + { + isXMajorAxis = False; + } + + // + //---------------------------------------------------- + // Allocate a scoreboard and fill it with sorting info + //---------------------------------------------------- + // + Verify(!scoreBoard); + scoreBoard = new int[nodeCount * nodeCount]; + Register_Pointer(scoreBoard); + int *score = scoreBoard; + + boundingBoxIndex = new BoundingBox* [nodeCount]; + Register_Pointer(boundingBoxIndex); + + for (p=root,i=0; p; p = p->previousNode,++i) + { + Check(p); + BoundingBox *first = p->boundingBox; + boundingBoxIndex[i] = first; + for (q=root,j=0; q; q = q->previousNode,++j,++score) + { + + // + //------------------------------ + // Ignore scoring against itself + //------------------------------ + // + Check(q); + *score = 0; + if (p == q) + { + continue; + } + BoundingBox *second = q->boundingBox; + + // + //-------------------------------------------------------------------- + // Step through the three axes and set the flags showing how the + // second solid is split up by the first solid. Make sure that if the + // second solid completely covers the first that this inside bit is + // set correctly + //-------------------------------------------------------------------- + // + for (int axis = X_Axis; axis <= Z_Axis; --axis) + { + *score <<= Shift; + int face = axis << 1; + if ((*second)[face] < (*first)[face]) + { + *score |= Min_Side; + } + else if ((*second)[face] < (*first)[face+1]) + { + *score |= Inside; + } + if ((*second)[face+1] > (*first)[face+1]) + { + *score |= Max_Side; + } + else if ((*second)[face+1] > (*first)[face]) + { + *score |= Inside; + } + + if ((*score & Both_Sides) == Both_Sides) + { + *score |= Inside; + } + } + } + } + + // + //-------------------------------------------------------------------------- + // Create a new BoxedSolid list for results to go into, and a third in which + // to pass the active list + //-------------------------------------------------------------------------- + // + BoundingBoxList active; + active.root = root; + active.nodeCount = nodeCount; + root = NULL; + BoundingBoxTree tree_so_far; + + Sort( + active, + map_extents, + tree_so_far + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxList::Sort( + BoundingBoxList &,//active, + ExtentBox &,//map_extents, + BoundingBoxTree &//tree_so_far + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoxedSolidList::Reduce() +{ + Check(this); + + BoundingBoxListNode + *i, *j, *previous; + + // + //-------------------------------------------------------------------------- + // Fuse the collision slices together into the largest possible chunks based + // upon the collision model of each of the involved slices. Repeat until no + // fusings were made in the last pass or only one collision slice remains + //-------------------------------------------------------------------------- + // + Logical again = True; + while (again) + { + again = False; + + // + //-------------------------------------------------------------------- + // Check each collision slice against the remaining slices in the list + //-------------------------------------------------------------------- + // + for (i=root; i; i = i->previousNode) + { + Check(i); + previous = i; + j = i->previousNode; + while (j) + { + Check(j); + // + //------------------------------------------------------------- + // If the model types are different, these two slices cannot be + // fused + //------------------------------------------------------------- + // + BoxedSolid *first = Cast_Object(BoxedSolid*, i->boundingBox); + BoxedSolid *second = Cast_Object(BoxedSolid*, j->boundingBox); + if (first->solidType != second->solidType) + { +Next_Solid: + previous = j; + j = j->previousNode; + continue; + } + + // + //---------------------------------------------------- + // Make sure that the faces on two sets of sides match + //---------------------------------------------------- + // + int matches = 0; + int face = -1; + for (int side=0; side<6; side += 2) + { + if ( + (*first)[side] == (*second)[side] + && (*first)[side+1] == (*second)[side+1] + ) + { + ++matches; + } + else if (face<0) + { + face = side; + } + } + if (matches != 2) + { + goto Next_Solid; + } + + // + //---------------------------------------------------------------- + // Check to make sure that the two solids have an opposing face in + // common, which will allow the solids to be fused + //---------------------------------------------------------------- + // + if ( + (*first)[face] != (*second)[face+1] + && (*first)[face+1] != (*second)[face] + ) + { + goto Next_Solid; + } + + // + //--------------------------------------------------------------- + // Make sure that this type of solid is legal to be fused in this + // direction + //--------------------------------------------------------------- + // + if (!(Legal_To_Fuse[first->solidType] & (face>>1))) + { + goto Next_Solid; + } + + // + //---------------------------------------------------- + // Find the face to fuse, and fuse the blocks together + //---------------------------------------------------- + // + if ((*first)[face+1] == (*second)[face]) + { + ++face; + } + (*first)[face] = (*second)[face]; + + // + //----------------------------------------------- + // Erase the second solid from the collision list + //----------------------------------------------- + // + if (previous) + { + previous->previousNode = j->previousNode; + Unregister_Object(j); + delete(j); + j = previous->previousNode; + } + else + { + root = j->previousNode; + Unregister_Object(j); + delete(j); + j = root; + } + again = True; + } + } + } +} diff --git a/MUNGA/BOXSPHR.cpp b/MUNGA/BOXSPHR.cpp new file mode 100644 index 0000000..d672486 --- /dev/null +++ b/MUNGA/BOXSPHR.cpp @@ -0,0 +1,235 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "origin.h" +#include "linmtrx.h" +#include "line.h" + +//############################################################################# +//############################## BoxedSphere ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSphere::BoxedSphere( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid(extents, SphereType, material, owner, next_solid) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSphere::~BoxedSphere() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //-------------------------------------------------------------------------- + // Constrain the centerpoint of the sphere to be within the bounded extents. + // Then see if the constrained point is within the radius of the sphere. If + // so, it is an intersection + //-------------------------------------------------------------------------- + // + Point3D closest = center; + extents.Constrain(&closest); + closest -= center; + return radius*radius >= closest.LengthSquared(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //------------------------------------------------------------------------- + // translate the test point into the sphere's frame of reference and see if + // it is close enough + //------------------------------------------------------------------------- + // + center -= point; + return radius*radius >= center.LengthSquared(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedSphere::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //----------------------------------------------------------------------- + // Convert the point to the coordinates of the sphere, putting the center + // point of the sphere at the origin. Note that we are subtracting the + // point from the center point as opposed to the normal way. This will + // result in both X and Y being negated, but since we are squaring them, + // this will not matter + //----------------------------------------------------------------------- + // + Scalar x = center.x - point.x; + Scalar z = center.z - point.z; + Scalar h = radius*radius - x*x - z*z; + if (h < SMALL) + { + return -1.0f; + } + + // + //------------------------------------------------------------------- + // If the point is in the XZ shadow of the sphere, then the height is + // determined by the height of the sphere at that point + //------------------------------------------------------------------- + // + Scalar height = point.y - (center.y + Sqrt(h)); + return Abs(height); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //---------------------------------------------- + // Find the centerpoint and radius of the sphere + //---------------------------------------------- + // + Point3D center; + center.x = (minX + maxX) * 0.5f; + center.y = (minY + maxY) * 0.5f; + center.z = (minZ + maxZ) * 0.5f; + Scalar radius = maxX - center.x; + + // + //------------------------------------------------------------------------- + // Find the point of closest approach to the center of the sphere, and make + // sure that it is within the boundaries of the sphere + //------------------------------------------------------------------------- + // + Scalar midlen = line->LengthToClosestPointTo(center); + Point3D closest; + line->Project(midlen, &closest); + closest -= center; + Scalar v = radius*radius - closest.LengthSquared(); + if (v < 0.0f) + { + return False; + } + + // + //--------------------------------------------------------------------- + // Find the closest possible length of ray traversal before hitting the + // sphere + //--------------------------------------------------------------------- + // + v = Sqrt(v); + Scalar enter = midlen - v; + if (enter > enters) + { + enters = enter; + } + Scalar leave = midlen + v; + if (leave < leaves) + { + leaves = leave; + } + + if (enters > leaves || enters > line->length || leaves < 0.0f) + { + return False; + } + + line->length = Max(enters, 0.0f); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedSphere::TestInstance() const +{ + return solidType == SphereType; +} diff --git a/MUNGA/BOXTILE.cpp b/MUNGA/BOXTILE.cpp new file mode 100644 index 0000000..c6dc95c --- /dev/null +++ b/MUNGA/BOXTILE.cpp @@ -0,0 +1,641 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "origin.h" +#include "linmtrx.h" +#include "line.h" +#include "plane.h" +#include "vector2d.h" + +//############################################################################# +//######################### RightHandedTile ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RightHandedTile::RightHandedTile( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *corners, + Type type +): + BoxedSolid(extents, type, material, owner, next_solid) +{ + Check_Pointer(this); + for (int i=0; i= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //------------------------------------------------------------------- + // See if the box hits the upper-right triangle anywhere on its plane + //------------------------------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + + Plane plane1(p0, p1, p2); + if (plane1.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + + // + //------------------------------------------------------------------ + // See if the box hits the lower-left triangle anywhere on its plane + //------------------------------------------------------------------ + // + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + + Plane plane2(p0, p1, p2); + if (plane2.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RightHandedTile::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(maxY >= point.y); + return FindDistanceBelowBounded(point) <= 0.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + RightHandedTile::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------- + // Figure out which triangle the point will reside in + //--------------------------------------------------- + // + Scalar rise = maxX - minX; + Scalar run = maxZ - minZ; + Verify(rise > SMALL); + Verify(run > SMALL); + + Scalar dx = point.x - minX; + Scalar dz = point.z - minZ; + + // + //----------------------------------------------------------------- + // Set up the appropriate triangle based upon which have it lies in + //----------------------------------------------------------------- + // + Point3D p0,p1,p2; + if (dx*run > dz*rise) + { + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + } + else + { + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + } + + // + //--------------------------------------------------------------------- + // Make a plane out of the triangle, and have the plane solve for the Y + // coordinate + //--------------------------------------------------------------------- + // + Plane plane(p0, p1, p2); + Verify(!Small_Enough(plane.normal.y)); + Scalar height = point.y - plane.CalculateY(point.x, point.z); + Check_Fpu(); + return height; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +static Scalar + LineHitsTriangle( + Line *line, + const Point3D &p0, + const Point3D &p1, + const Point3D &p2, + Scalar *cosine + ) +{ + // + //-------------------------------------------------------------------------- + // Make the plane out of the three corner points, and figure out how far the + // ray must travel to reach this plane. Try some trivial rejections: + // parallel lines, lines starting outside the halfspace heading away from + // the plane, and lines starting outside the halfspace and heading towards + // the plane but are too far away + //-------------------------------------------------------------------------- + // + Plane plane(p0, p1, p2); + Scalar length = line->DistanceTo(plane, cosine); + if ( + Small_Enough(*cosine) + || *cosine > 0.0f && length < 0.0f + || *cosine < 0.0f && length > line->length + ) + { + return -1.0f; + } + + // + //-------------------------------------------------------- + // Project the impact point and triangle unto the XZ plane + //-------------------------------------------------------- + // + Point3D impact; + line->Project(length, &impact); + Vector2DOf proj(impact.x - p0.x, impact.z - p0.z); + Scalar x = p1.x - p0.x; + Scalar z = p2.z - p0.z; + + // + //------------------------------------------------------------------------- + // Make sure that the area of the triangle made with the test point and the + // first leg is not negative or greater than the area of the triangle made + // by the two legs. The area of the triangle is half the cross product of + // the legs of that triangle + //------------------------------------------------------------------------- + // + Scalar area_ratio = z*x; + Verify(!Small_Enough(area_ratio)); + area_ratio = x*proj.y / area_ratio; + Check_Fpu(); + if (area_ratio >= 0.0f && area_ratio <= 1.0f) + { + // + //---------------------------------------------------------------------- + // The area ratio represents the height of the test triangle relative to + // the given triangle. One edge of the value is represented by + // projecting the second leg a percentage equal to the ratio. The bounds + // of its variance is 1-area_ratio * the first leg of the triangle + //---------------------------------------------------------------------- + // + Scalar span = proj.x / x; + Check_Fpu(); + if (span >= 0.0f && span+area_ratio <= 1.0f) + { + return length; + } + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RightHandedTile::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //---------------------------------------------- + // See if the line hits the upper-right triangle + //---------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + + Scalar cosine; + Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //--------------------------------------------- + // See if the line hits the lower left triangle + //--------------------------------------------- + // + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + + length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //------------------------------------------- + // Neither triangle was entered, so we missed + //------------------------------------------- + // + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RightHandedTile::TestInstance() const +{ + return solidType == RightHandedTileType; +} + +//############################################################################# +//######################### LeftHandedTile ###################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +LeftHandedTile::LeftHandedTile( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid, + Scalar *corners +): + RightHandedTile( + extents, + material, + owner, + next_solid, + corners, + LeftHandedTileType + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +LeftHandedTile::~LeftHandedTile() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LeftHandedTile::IntersectsBounded(const ExtentBox &extents) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //------------------------------------------------------------------- + // See if the box hits the upper-left triangle anywhere on its plane + //------------------------------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[2]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[1]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[0]; + p2.z = maxZ; + + Plane plane1(p0, p1, p2); + if (plane1.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + + // + //------------------------------------------------------------------ + // See if the box hits the lower-right triangle anywhere on its plane + //------------------------------------------------------------------ + // + p0.x = minX; + p0.y = cornerHeight[1]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[2]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[3]; + p2.z = minZ; + + Plane plane2(p0, p1, p2); + if (plane2.ContainsSomeOf(extents)) + { + // + //------------------------------------------------------------------- + // Make sure the XZ projections of the triangle and the box intersect + //------------------------------------------------------------------- + // + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + LeftHandedTile::FindDistanceBelowBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //--------------------------------------------------- + // Figure out which triangle the point will reside in + //--------------------------------------------------- + // + Scalar rise = maxX - minX; + Scalar run = maxZ - minZ; + Verify(rise > SMALL); + Verify(run > SMALL); + + Scalar dx = point.x - minX; // HACK - needs to be set up for other diagonal + Scalar dz = point.z - minZ; + + // + //----------------------------------------------------------------- + // Set up the appropriate triangle based upon which have it lies in + //----------------------------------------------------------------- + // + Point3D p0,p1,p2; + if (dx*run > dz*rise) + { + p0.x = maxX; + p0.y = cornerHeight[1]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[0]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[3]; + p2.z = maxZ; + } + else + { + p0.x = minX; + p0.y = cornerHeight[2]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[3]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[0]; + p2.z = minZ; + } + + // + //--------------------------------------------------------------------- + // Make a plane out of the triangle, and have the plane solve for the Y + // coordinate + //--------------------------------------------------------------------- + // + Plane plane(p0, p1, p2); + Verify(!Small_Enough(plane.normal.y)); + Scalar height = point.y - plane.CalculateY(point.x, point.z); + Check_Fpu(); + return height; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LeftHandedTile::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Check(this); + Check(line); + + Verify(enters <= leaves); + Verify(leaves >= 0.0f); + + // + //---------------------------------------------- + // See if the line hits the upper-right triangle + //---------------------------------------------- + // + Point3D p0,p1,p2; + p0.x = maxX; + p0.y = cornerHeight[2]; + p0.z = minZ; + + p1.x = minX; + p1.y = cornerHeight[1]; + p1.z = minZ; + + p2.x = maxX; + p2.y = cornerHeight[0]; + p2.z = maxZ; + + Scalar cosine; + Scalar length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //--------------------------------------------- + // See if the line hits the lower left triangle + //--------------------------------------------- + // + p0.x = minX; + p0.y = cornerHeight[1]; + p0.z = maxZ; + + p1.x = maxX; + p1.y = cornerHeight[2]; + p1.z = maxZ; + + p2.x = minX; + p2.y = cornerHeight[3]; + p2.z = minZ; + + length = LineHitsTriangle(line, p0, p1, p2, &cosine); + + // + //-------------------------------------------------------------- + // If we are entering the the plane, set the new entering length + //-------------------------------------------------------------- + // + if (length >= 0.0f && cosine < 0.0f && length >= enters && length <= leaves) + { + line->length = length; + return True; + } + + // + //------------------------------------------- + // Neither triangle was entered, so we missed + //------------------------------------------- + // + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LeftHandedTile::TestInstance() const +{ + return solidType == LeftHandedTileType; +} diff --git a/MUNGA/BOXTREE.cpp b/MUNGA/BOXTREE.cpp new file mode 100644 index 0000000..7d18750 --- /dev/null +++ b/MUNGA/BOXTREE.cpp @@ -0,0 +1,1340 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxtree.h" +#include "point3d.h" +#include "line.h" + +//############################################################################# +//######################### BoundingBoxTreeNode ######################### +//############################################################################# + +MemoryBlock *BoundingBoxTreeNode::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(BoundingBoxTreeNode), 500, 50, "BoundingBoxTree Nodes"); + return &allocatedMemory; +} + +int + BoundingBoxTreeNode::TraversalOrder[6]={4,5,0,1,2,3}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTreeNode::SetTraversalOrder( + int first, + int second, + int third + ) +{ + Verify((unsigned)first <= Z_Axis && first != second); + Verify((unsigned)second <= Z_Axis && second != third); + Verify((unsigned)third <= Z_Axis && third != first); + + TraversalOrder[0] = first << 1; + TraversalOrder[1] = TraversalOrder[0] + 1; + TraversalOrder[2] = second << 1; + TraversalOrder[3] = TraversalOrder[2] + 1; + TraversalOrder[4] = third << 1; + TraversalOrder[5] = TraversalOrder[4] + 1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxTreeNode::BoundingBoxTreeNode( + BoundingBox *volume, + const ExtentBox &extents +) +{ + Check_Pointer(this); + Check(&extents); + + nodeExtents = extents; + staticContents = volume; + innerNode = NULL; + for (int i=0; i nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] < nodeExtents[face]; + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (clipped_box[face] < nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] > nodeExtents[face]; + } + else + { + continue; + } + } + + // + //--------------------------------------------------------------------- + // If the new box is to be clipped, save the old value for the opposite + // face and replace it with this space's bounding face + //--------------------------------------------------------------------- + // + if (is_clipped) + { + save = clipped_box[opp_face]; + clipped_box[opp_face] = nodeExtents[face]; + } + + // + //----------------------------------------------------------------------- + // Make sure that we are not registering an empty slice of the new volume + //----------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + + // + //-------------------------------------------------------------------- + // If no spaces have been defined within the facing voxel, construct + // a new one out of the clipped box, otherwise call this routine again + // with the given voxel and the clipped box + //-------------------------------------------------------------------- + // + if (!nodeBranches[face]) + { + nodeBranches[face] = + new BoundingBoxTreeNode(volume, clipped_box); + Register_Object(nodeBranches[face]); + } + else + { + Check(nodeBranches[face]); + nodeBranches[face]->Add(volume, clipped_box); + } + } + + // + //--------------------------------------------------------------------- + // If no clipping was necessary for this voxel, then no portion of + // the box remains to be tested, so abort the loop. Otherwise, restore + // the opposing face of the new box, and clip the newly created + // voxel out of the new box + //--------------------------------------------------------------------- + // + if (!is_clipped) + return; + clipped_box[opp_face] = save; + clipped_box[face] = nodeExtents[face]; + } + + //----------------------------------------------------------------------- + // Make sure that we are not registering an empty slice of the new volume + //----------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + + // + //---------------------------------------------------------------------- + // The remaining portion of the box is inside our current space, so link + // it there + //---------------------------------------------------------------------- + // + if (!innerNode) + { + innerNode = new BoundingBoxTreeNode(volume, clipped_box); + Register_Object(innerNode); + } + else + { + Check(innerNode); + innerNode->Add(volume, clipped_box); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTreeNode::Remove( + BoundingBox *volume, + const ExtentBox &extents + ) +{ + Check(this); + Check(volume); + Check(&extents); + + // + //---------------------------------------------------------------------- + // If this node contains the desired volume, immediately NULL it out and + // return + //---------------------------------------------------------------------- + // + if (staticContents == volume) + { + staticContents = NULL; + return; + } + + // + //--------------------------------------------------- + // Make our copy of the new box for clipping purposes + //--------------------------------------------------- + // + ExtentBox clipped_box(extents); + + // + //------------------------------------------------------------------------ + // Check along each of the six faces, separately clipping off elements of + // the new box which do not lie within this voxel + //------------------------------------------------------------------------ + // + for (int i=0; i<6; ++i) + { + int + is_clipped; + Scalar + save; + + // + //------------------------------------------------------------------ + // Handle testing the maximum value side of the box. Make sure that + // volumes actually extend into the current voxel before they are + // clipped, preventing insertion of zero-thickness voxels + //------------------------------------------------------------------ + // + int face = TraversalOrder[i]; + int opp_face = face^1; + if (face&1) + { + if (clipped_box[face] > nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] < nodeExtents[face]; + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (clipped_box[face] < nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] > nodeExtents[face]; + } + else + { + continue; + } + } + + // + //--------------------------------------------------------------------- + // If the new box is to be clipped, save the old value for the opposite + // face and replace it with this space's bounding face + //--------------------------------------------------------------------- + // + if (is_clipped) + { + save = clipped_box[opp_face]; + clipped_box[opp_face] = nodeExtents[face]; + } + + // + //--------------------------------------------------------------------- + // Because the volume has already been added, branches must exist along + // all faces it gets clipped by unless it was an empty slice + //--------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + Check(nodeBranches[face]); + nodeBranches[face]->Remove(volume, clipped_box); + } + + // + //--------------------------------------------------------------------- + // If no clipping was necessary for this voxel, then no portion of + // the box remains to be tested, so abort the loop. Otherwise, restore + // the opposing face of the new box, and clip the newly created + // voxel out of the new box + //--------------------------------------------------------------------- + // + if (!is_clipped) + return; + clipped_box[opp_face] = save; + clipped_box[face] = nodeExtents[face]; + } + + // + //-------------------------------------------------------------------------- + // If we are not dealing with an empty slice of the volume, the remaining + // slice of the extents must have been entered as internal subspacing + //-------------------------------------------------------------------------- + // + if (volume->IntersectsBounded(clipped_box)) + { + Check(innerNode); + innerNode->Remove(volume, clipped_box); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxTreeNode* + BoundingBoxTreeNode::FindSmallestNodeContaining( + const ExtentBox &extents, + BoundingBoxTreeNode *parent + ) +{ + Check(&extents); + + // + //------------------------------------------------------------------------ + // Check along each of the six faces to see if this volume cuts any of the + // planes of the node, + //------------------------------------------------------------------------ + // + BoundingBoxTreeNode *branch = this; +Check_Node: + Check(branch); + for (int i=0; i<6; ++i) + { + // + //------------------------------------------------- + // Handle testing the maximum value side of the box + //------------------------------------------------- + // + int face = TraversalOrder[i]; + int opp_face = face^1; + if (face&1) + { + if (extents[face] > branch->nodeExtents[face]) + { + if (extents[opp_face] <= branch->nodeExtents[face]) + { + return (parent) ? parent : branch; + } + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (extents[face] < branch->nodeExtents[face]) + { + if (extents[opp_face] >= branch->nodeExtents[face]) + { + return (parent) ? parent : branch; + } + } + else + { + continue; + } + } + + // + //---------------------------------------------------- + // If no branch exists, then this is the smallest node + //---------------------------------------------------- + // + if (!branch->nodeBranches[face]) + { + return (parent) ? parent : branch; + } + branch = branch->nodeBranches[face]; + Check(branch); + goto Check_Node; + } + + // + //--------------------------------------------------------- + // If no inner space exists, then this is the smallest node + //--------------------------------------------------------- + // + if (!branch->innerNode) + { + return branch; + } + + // + //------------------------------------------------------------------------- + // Once we cross into an innerspace, we have to modify the behaviour of the + // previous, as a volume which is enclosed by the node could itself enclose + // the innerspace node, meaning that the parent node should be reported as + // the smallest node + //------------------------------------------------------------------------- + // + parent = branch; + branch = branch->innerNode; + Check(branch); + goto Check_Node; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBoxTreeNode* + BoundingBoxTreeNode::FindSmallestNodeContainingColumn( + const ExtentBox &extents + ) +{ + Check(&extents); + + // + //------------------------------------------------------------------------ + // Check along each of the six faces to see if this volume cuts any of the + // planes of the node, + //------------------------------------------------------------------------ + // + BoundingBoxTreeNode *branch = this; +Check_Node: + Check(this); + for (int i=0; i<4; ++i) + { + // + //------------------------------------------------- + // Handle testing the maximum value side of the box + //------------------------------------------------- + // + int face = TraversalOrder[i]; + int opp_face = face^1; + if (face&1) + { + if (extents[face] > branch->nodeExtents[face]) + { + if (extents[opp_face] <= branch->nodeExtents[face]) + { + return branch; + } + } + else + { + continue; + } + } + + // + //------------------------------------------------- + // Handle testing the minimum value side of the box + //------------------------------------------------- + // + else + { + if (extents[face] < branch->nodeExtents[face]) + { + if (extents[opp_face] >= branch->nodeExtents[face]) + { + return branch; + } + } + else + { + continue; + } + } + + // + //---------------------------------------------------- + // If no branch exists, then this is the smallest node + //---------------------------------------------------- + // + if (!branch->nodeBranches[face]) + { + return branch; + } + branch = branch->nodeBranches[face]; + Check(branch); + goto Check_Node; + } + + return branch; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTreeNode::FindBoundingBoxContaining( + const Point3D &point, + BoundingBox *parent + ) +{ + Check(this); + Check(&point); + + // + //---------------------------------------------------- + // Set the content pointer to point at this root voxel + //---------------------------------------------------- + // + BoundingBoxTreeNode + *branch = this; + + // + //------------------------------------------------------------------------- + // Keep checking our voxel branches until the point lies inside the current + // voxel + //------------------------------------------------------------------------- + // +Check_Node: + Check(branch); + for (int i=0; i<6; ++i) + { + // + //------------------------------------------------------- + // Keep looking if the point is not beyond a given extent + //------------------------------------------------------- + // + int face = TraversalOrder[i]; + int axis = face >> 1; + if (face&1) + { + if (point[axis] <= branch->nodeExtents[face]) + { + continue; + } + } + else if (point[axis] >= branch->nodeExtents[face]) + { + continue; + } + + // + //----------------------------------------------------------------------- + // The point lies in a side's subspace, so make sure that the subspace on + // that side exists. If not, no voxel will contain the point so return + // the parent. If a facing subspace exists, set the branch pointer to + // that subspace, then check to see where the point is relative to that + // subspace + //----------------------------------------------------------------------- + // + if (!branch->nodeBranches[face]) + { + return parent; + } + branch = branch->nodeBranches[face]; + goto Check_Node; + } + + // + //------------------------------------------------------------------------- + // Since we exited the loop, we have to check inside the node to see if it + // has been subspaced. If so, restart the function again on the internal + // subspace, using the contents of this subspace as the new parent solid. + // + // Note that negative space will not be correctly handled for cases where + // the space being carved out does not fully occupy the zones it is in such + // as with a cylinder + //------------------------------------------------------------------------- + // + if (branch->innerNode) + { + if (branch->staticContents) + { + Check(branch->staticContents); + if (branch->staticContents->ContainsBounded(point)) + { + parent = branch->staticContents; + } + } + else + { + parent = NULL; + } + branch = branch->innerNode; + goto Check_Node; + } + + // + //---------------------------------------------------------------------- + // If our content pointer is NULL, then this node is considered negative + // space, and thus empty + //---------------------------------------------------------------------- + // + if (!branch->staticContents) + { + return NULL; + } + + // + //-------------------------------------------------------------------------- + // We are pointing at a real solid, so if it does in fact contain our point, + // go ahead a return the volume, otherwise return our parent volume + //-------------------------------------------------------------------------- + // + Check(branch->staticContents); + if (branch->staticContents->ContainsBounded(point)) + { + parent = branch->staticContents; + } + return parent; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTreeNode::FindBoundingBoxesContaining( + BoundingBox *volume, + const ExtentBox &slice, + BoundingBoxCollisionList &list + ) +{ + Check(this); + Check(volume); + Check(&slice); + Check(&list); + Verify(list.collisionsLeft>0); + + // + //--------------------------------------------------------------------- + // Check along each of the six faces, to see if any portion of the test + // volume lies within any of the subspace partitions + //--------------------------------------------------------------------- + // + ExtentBox clipped_box = slice; + for (int i=0; i<6; ++i) + { + int + is_clipped; + Scalar + save; + + // + //----------------------------------------------------------------------- + // Figure out the opposing face, then check to see if we are testing + // against a maximum face. If so, check to see if some part of the test + // volume protrudes into the defined subspace. If it does, figure out if + // some portion of the test volume remains to be checked, otherwise keep + // checking faces + //----------------------------------------------------------------------- + // + int face = TraversalOrder[i]; + int opp_face = face ^ 1; + if (face&1) + { + if (clipped_box[face] > nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] <= nodeExtents[face]; + } + else + { + continue; + } + } + + // + //----------------------------------------------------------------------- + // Otherwise, we are testing against a maximum face. If so, check to see + // if some part of the test volume protrudes into the defined subspace. + // If it does, figure out if some portion of the test volume remains to + // be checked, otherwise keep checking faces + //----------------------------------------------------------------------- + // + else + { + if (clipped_box[face] < nodeExtents[face]) + { + is_clipped = clipped_box[opp_face] >= nodeExtents[face]; + } + else + { + continue; + } + } + + // + //------------------------------------------------------------------- + // If the test volume needs to be clipped, save the old value for the + // opposite face and replace it with this space's bounding face + //------------------------------------------------------------------- + // + if (is_clipped) + { + save = clipped_box[opp_face]; + clipped_box[opp_face] = nodeExtents[face]; + } + + // + //---------------------------------------------------------------------- + // If a facing node exists, call this routine again with it and the part + // of the test volume we just trimmed off + //---------------------------------------------------------------------- + // + if (nodeBranches[face]) + { + Check(nodeBranches[face]); + nodeBranches[face]->FindBoundingBoxesContaining( + volume, + clipped_box, + list + ); + } + + // + //----------------------------------------------------------------------- + // If no clipping was necessary for this subspace, or we found no entries + // remain in the collision list, we are done checking, so just return + //----------------------------------------------------------------------- + // + if (!is_clipped || !list.collisionsLeft) + { + return; + } + + // + //------------------------------------------------------------------ + // Otherwise, restore the opposing face of the new box, and clip the + // already tested slice out of the test volume + //------------------------------------------------------------------ + // + clipped_box[opp_face] = save; + clipped_box[face] = nodeExtents[face]; + } + + // + //------------------------------------------------------------------------- + // If we exited the loop, then we have to check inside the node. If this + // node is not a hole, make sure that it collides against the slice. If it + // doesn't, don't override the parent setting, otherwise do override it + //------------------------------------------------------------------------- + // + BoundingBox *hit = NULL; + if (staticContents) + { + Check(staticContents); + if (staticContents->IntersectsBounded(clipped_box)) + { + hit = staticContents; + } + } + + // + //------------------------------------------------------------------ + // If the solid has been subspaced, have it check against collisions + //------------------------------------------------------------------ + // + if (innerNode) + { + Check(innerNode); + innerNode->FindBoundingBoxesContaining( + volume, + clipped_box, + list + ); + } + + // + //------------------------------------------------------------------------- + // Otherwise, if the volume this node points to is not a hole, go ahead and + // add it to the list + //------------------------------------------------------------------------- + // + if (hit && list.collisionsLeft) + { + Check(hit); + list.AddCollisionToList(hit, clipped_box); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTreeNode::FindBoundingBoxUnder( + const Point3D &point, + Scalar* height + ) +{ + Check(this); + Check(&point); + Check_Pointer(height); + Verify((TraversalOrder[4]>>1) == Y_Axis) + + BoundingBoxTreeNode *branch = this; + BoundingBox *floor; + + // + //-------------------------------------------------------------------------- + // Check along each of the faces to see if the point lies within any of + // these subspaces. Note the change in the comparison resulting in only the + // first four coordinates (for X and Z) being checked, as the Y coordinate + // needs special treatment + //-------------------------------------------------------------------------- + // +Find_Column: + Check(branch); + for (int i=0; i<4; ++i) + { + int face = TraversalOrder[i]; + int axis = face >> 1; + if (face&1) + { + if (point[axis] <= branch->nodeExtents[face]) + { + continue; + } + } + else if (point[axis] >= branch->nodeExtents[face]) + { + continue; + } + + // + //--------------------------------------------------------------------- + // If a facing subspace exists, start this routine again with the given + // subspace and the point. If it doesn't exist, nothing will be hit + //--------------------------------------------------------------------- + // + if (branch->nodeBranches[face]) + { + branch = branch->nodeBranches[face]; + goto Find_Column; + } + else + { + *height = -1.0f; + return NULL; + } + } + + // + //------------------------------------------------------------------------- + // We now know that the object has a presence along the line defined by the + // projection of the point unto the XZ plane. If the point lies above the + // object, and other objects exist in the maxZ subspace, and they are able + // to determine the height, return the height they returned + //------------------------------------------------------------------------- + // + if (point.y > branch->nodeExtents.maxY && branch->nodeBranches[3]) + { + Check(branch->nodeBranches[3]); + floor = branch->nodeBranches[3]->FindBoundingBoxUnder(point, height); + if (floor) + { + return floor; + } + } + + // + //-------------------------------------------------------------------------- + // Handle processing the ray internal to this solid if we need to project + // the ray into our solid. If we are negative space, allow the ray to + // project through the node unhindered. + // + // Note that this code will not properly handle going through negative space + // if the negative space does not completely bore through solids + //-------------------------------------------------------------------------- + // + if (point.y >= branch->nodeExtents.minY) + { + if (branch->staticContents) + { + Check(branch->staticContents); + floor = branch->staticContents; + *height = branch->staticContents->FindDistanceBelowBounded(point); + if (*height == -1.0f || point.y - *height < branch->nodeExtents.minY) + { + goto Missed_Us; + } + } + else + { +Missed_Us: + floor = NULL; + *height = -1.0f; + } + + // + //----------------------------------------------------------------------- + // If there is internal space defined, we will rely upon it to return the + // proper value if it supersedes this node's height value + //----------------------------------------------------------------------- + // + if (branch->innerNode) + { + Check(branch->innerNode); + Scalar height_2; + BoundingBox *floor_2; + floor_2 = branch->innerNode->FindBoundingBoxUnder(point, &height_2); + if (floor_2 && (height_2 < *height || !floor)) + { + *height = height_2; + floor = floor_2; + } + } + + // + //-------------------------------------------------- + // If something was struck, return that as the floor + //-------------------------------------------------- + // + if (floor) + { + return floor; + } + } + + // + //-------------------------------------------------------------------------- + // We now know that the projection went through our bounding box without + // intersecting our solid. If any objects exist in our Min_Z subspace, have + // them try and return the height + //-------------------------------------------------------------------------- + // + if (branch->nodeBranches[2]) + { + Check(branch->nodeBranches[2]); + return branch->nodeBranches[2]->FindBoundingBoxUnder(point, height); + } + + // + //-------------------------------------------------------------- + // Since there is nothing below this bounding box, return no hit + //-------------------------------------------------------------- + // + else + { + *height = -1.0f; + return NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTreeNode::FindBoundingBoxHitBy(Line *line) +{ + Check(this); + Check(line); + + int + test_queue[7]; + Scalar + enter = 0.0f, + leave = 0.0f, + perpendicular, + drift, + distance; + BoundingBox + *result; + + // + //-------------------- + // Set up for the test + //-------------------- + // + int first = 0; + int last = 6; + Logical entered = False; + Logical left = False; + int i; + for (i=0; i<6; ++i) + { + // + //-------------------------------------------------------------------- + // Figure out what axis we are dealing with, then based upon the + // direction of the face, find out the distance from the origin to the + // place against the normal, and find out how fast the perpendicular + // distance changes with a unit movement along the line + //-------------------------------------------------------------------- + // + int face = TraversalOrder[i]; + int axis = face >> 1; + if (face&1) + { + perpendicular = line->origin[axis] - nodeExtents[face]; + drift = line->direction[axis]; + } + else + { + perpendicular = nodeExtents[face] - line->origin[axis]; + drift = -line->direction[axis]; + } + + // + //---------------------------------------------------------------------- + // If the line is parallel to the face, figure out whether or not the + // line origin lies within the face's half-space. If not, put it in the + // list and abort the loop + //---------------------------------------------------------------------- + // + if (Small_Enough(drift)) + { + if (perpendicular > 0.0f) + { + if (nodeBranches[face]) + { + test_queue[first++] = face; + } + break; + } + else + { + continue; + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + distance = -perpendicular / drift; + if (drift < 0.0f) + { + if (!entered) + { + entered = True; + enter = distance; + } + else if (distance > enter) + { + enter = distance; + } + + // + //-------------------------------------------------------------------- + // Queue up the node branch if the origin lies outside of this plane's + // halfspace. If the line cannot reach the plane, abort any more + // testing + //-------------------------------------------------------------------- + // + if (perpendicular >= 0.0f) + { + if (nodeBranches[face]) + { + test_queue[first++] = face; + } + if (distance > line->length || left && enter > leave) + { + break; + } + } + } + + // + //-------------------------------------------------------------------- + // If the drift is towards the plane's halfspace, this plane is one of + // the one through which the line could enter the node + //-------------------------------------------------------------------- + // + else + { + if (!left) + { + left = True; + leave = distance; + } + else if (distance < leave) + { + leave = distance; + } + + // + //-------------------------------------------------------------------- + // Queue up the node branch if the origin lies outside of this plane's + // halfspace, and stop further testing. If the origin is inside the + // halfspace, register this branch if the line will reach the plane + //-------------------------------------------------------------------- + // + if (perpendicular >= 0.0f) + { + if (nodeBranches[face]) + { + test_queue[last--] = face; + } + break; + } + if (distance <= line->length) + { + if (nodeBranches[face]) + { + test_queue[last--] = face; + } + } + if (entered && leave < enter) + { + break; + } + } + } + + // + //------------------------------------------------------------------------- + // If the loop exited normally, check to see if the bounding box was struck + // by the ray. If it was, then the interior of the voxel must be checked. + // We know that the box was hit if the farthest face opposing the ray + // direction is not farther than the nearest face not opposing the ray + //------------------------------------------------------------------------- + // + if (i == 6) + { + test_queue[last--] = 6; + } + + // + //------------------------------------------------------------------------- + // Step through the queue, checking in each of the identified regions to be + // processed first. If a hit is found in one of these, immediately return + // the result + //------------------------------------------------------------------------- + // + for (i=0; iFindBoundingBoxHitBy(line); + if (result) + { + Check(result); + return result; + } + } + + // + //----------------------------------- + // Process the interior if it's there + //----------------------------------- + // + if (last<6 && test_queue[last+1] == 6) + { + result = NULL; + if (!staticContents) + { + if (innerNode) + { + Check(innerNode); + result = innerNode->FindBoundingBoxHitBy(line); + } + } + else + { + Check(staticContents); + if (staticContents->HitByBounded(line, enter, leave)) + { + result = staticContents; + } + if (innerNode) + { + Check(innerNode); + BoundingBox + *result2 = innerNode->FindBoundingBoxHitBy(line); + if (result2) + { + result = result2; + } + } + } + + // + //--------------------------------------------------------------------- + // If the ray hit something, return the result, otherwise increment the + // last pointer so that we don't process this subspace again + //--------------------------------------------------------------------- + // + if (result) + { + Check(result); + return result; + } + last++; + } + + // + //------------------------------------------------------------------------- + // Step through the queue, checking in each of the identified regions to be + // processed last. If a hit is found, immediately return the result + //------------------------------------------------------------------------- + // + for (i=last+1; i<7; ++i) + { + Check(nodeBranches[test_queue[i]]); + result = nodeBranches[test_queue[i]]->FindBoundingBoxHitBy(line); + if (result) + { + Check(result); + return result; + } + } + + // + //---------------------------------------------------------- + // The ray hit nothing in this voxel, so return the sentinel + //---------------------------------------------------------- + // + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxTreeNode::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################### BoundingBoxTree ########################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTree::Add( + BoundingBox* volume, + const ExtentBox &slice + ) +{ + Check(this); + Check(volume); + + if (!root) + { + root = new BoundingBoxTreeNode(volume, slice); + Register_Object(root); + } + else + { + Check(root); + root->Add(volume, slice); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + BoundingBoxTree::EraseTree() +{ + if (root) + { + Unregister_Object(root); + delete root; + } + root = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoundingBox* + BoundingBoxTree::FindBoundingBoxHitBy(Line *line) +{ + Check(this); + Check(line); + Check(root); + + Point3D line_end; + line->FindEnd(&line_end); + ExtentBox line_volume(line->origin, line_end); + return + root->FindSmallestNodeContaining(line_volume, NULL) + ->FindBoundingBoxHitBy(line); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoundingBoxTree::TestInstance() const +{ + return True; +} diff --git a/MUNGA/BOXTREE.h b/MUNGA/BOXTREE.h new file mode 100644 index 0000000..c1f5594 --- /dev/null +++ b/MUNGA/BOXTREE.h @@ -0,0 +1,208 @@ +#pragma once + +#include "bndgbox.h" +#include "memblock.h" + +//########################################################################## +//####################### BoundingBoxTreeNode ######################## +//########################################################################## + +class BoundingBoxTree; + +class BoundingBoxTreeNode SIGNATURED +{ + friend class BoundingBoxTree; + +//########################################################################## +// Memory Allocation +// +private: + static MemoryBlock* GetAllocatedMemory(); + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } + +//########################################################################## +// Construction and Destruction +// +protected: + ExtentBox + nodeExtents; + BoundingBox + *staticContents; + BoundingBoxTreeNode + *nodeBranches[6], + *innerNode; + + BoundingBoxTreeNode( + BoundingBox *volume, + const ExtentBox &extents + ); + ~BoundingBoxTreeNode(); + + void + Add( + BoundingBox *BoundingBox, + const ExtentBox &extents + ); + void + Remove( + BoundingBox *BoundingBox, + const ExtentBox &extents + ); + +//########################################################################## +// Tree Traversal Functions +// +protected: + static int + TraversalOrder[6]; + + static void + SetTraversalOrder( + int first, + int second, + int third + ); + +public: + BoundingBoxTreeNode* + FindSmallestNodeContaining( + const ExtentBox &extents, + BoundingBoxTreeNode *parent + ); + + BoundingBoxTreeNode* + FindSmallestNodeContainingColumn(const ExtentBox &extents); + + BoundingBox* + FindBoundingBoxContaining( + const Point3D &point, + BoundingBox *parent + ); + + void + FindBoundingBoxesContaining( + BoundingBox *volume, + const ExtentBox &slice, + BoundingBoxCollisionList &list + ); + + BoundingBox* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ); + + BoundingBox* + FindBoundingBoxHitBy(Line *line); + +//########################################################################## +// Test Support +// +public: + Logical + TestInstance() const; +}; + +//########################################################################## +//######################## BoundingBoxTree ########################### +//########################################################################## + +class BoundingBoxTree SIGNATURED +{ + +//########################################################################## +// Construction and Destruction +// +protected: + BoundingBoxTreeNode *root; + +public: + BoundingBoxTree() + {Check_Pointer(this); root = NULL;} + ~BoundingBoxTree() + {Check(this); EraseTree();} + + static void + SetTraversalOrder( + int first, + int second, + int third + ) + {BoundingBoxTreeNode::SetTraversalOrder(first, second, third);} + + void + Add( + BoundingBox* volume, + const ExtentBox &extents + ); + void + Remove(BoundingBox* volume) + { + Check(this); Check(volume); Check(root); + root->Remove(volume, *volume); + } + void + EraseTree(); + +//########################################################################## +// Tree Traversal Functions +// +public: + BoundingBox* + FindBoundingBoxContaining(const Point3D &point) + { + Check(this); Check(&point); Check(root); + return root->FindBoundingBoxContaining(point, NULL); + } + + BoundingBoxTreeNode* + FindSmallestNodeContaining(const ExtentBox &extents) + { + Check(this); Check(&extents); Check(root); + return root->FindSmallestNodeContaining(extents, NULL); + } + + void + FindBoundingBoxesContaining( + BoundingBox *volume, + BoundingBoxCollisionList &list + ) + { + Check(this); Check(volume); Check(&list); Check(root); + root->FindBoundingBoxesContaining( + volume, + *volume, + list + ); + } + + BoundingBoxTreeNode* + FindSmallestNodeContainingColumn(const ExtentBox &extents) + { + Check(this); Check(&extents); Check(root); + Verify((BoundingBoxTreeNode::TraversalOrder[4]>>1) == Y_Axis); + return root->FindSmallestNodeContainingColumn(extents); + } + + BoundingBox* + FindBoundingBoxUnder( + const Point3D &point, + Scalar *height + ) + { + Check(this); Check(&point); Check(root); Check_Pointer(height); + Verify((BoundingBoxTreeNode::TraversalOrder[4]>>1) == Y_Axis); + return root->FindBoundingBoxUnder(point, height); + } + + BoundingBox* + FindBoundingBoxHitBy(Line *line); + +//########################################################################## +// Test Support +// +public: + Logical + TestInstance() const; +}; diff --git a/MUNGA/BOXWEDGE.cpp b/MUNGA/BOXWEDGE.cpp new file mode 100644 index 0000000..8afcd43 --- /dev/null +++ b/MUNGA/BOXWEDGE.cpp @@ -0,0 +1,872 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "plane.h" + +extern Logical + BoxedRampContainsLine( + Line *line, + const Plane& plane, + Scalar enters, + Scalar leaves + ); + +//############################################################################# +//################# BoxedWedgeFacingNegativeZAndPositiveX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndPositiveX::BoxedWedgeFacingNegativeZAndPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingNegativeZAndPositiveXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndPositiveX::~BoxedWedgeFacingNegativeZAndPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - minX; + Scalar z = extents.minZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingNegativeZAndPositiveX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = maxX - minX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise >= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = minZ - maxZ; + ramp.normal.y = 0.0f; + ramp.normal.z = maxX - minX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = maxX*ramp.normal.x + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndPositiveX::TestInstance() const +{ + return solidType == WedgeFacingNegativeZAndPositiveXType; +} + +//############################################################################# +//################# BoxedWedgeFacingPositiveZAndNegativeX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndNegativeX::BoxedWedgeFacingPositiveZAndNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingPositiveZAndNegativeXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndNegativeX::~BoxedWedgeFacingPositiveZAndNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - maxX; + Scalar z = extents.maxZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise >= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingPositiveZAndNegativeX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = minX - maxX; + Scalar rise = minZ - maxZ; + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more positive than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run >= z/x yields + // rise*x >= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise >= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = maxZ - minZ; + ramp.normal.y = 0.0f; + ramp.normal.z = minX - maxX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = maxX*ramp.normal.x + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndNegativeX::TestInstance() const +{ + return solidType == WedgeFacingPositiveZAndNegativeXType; +} + +//############################################################################# +//################# BoxedWedgeFacingPositiveZAndPositiveX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndPositiveX::BoxedWedgeFacingPositiveZAndPositiveX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingPositiveZAndPositiveXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingPositiveZAndPositiveX::~BoxedWedgeFacingPositiveZAndPositiveX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.maxX - minX; + Scalar z = extents.maxZ - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = maxX - minX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingPositiveZAndPositiveX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = maxX - minX; + Scalar rise = minZ - maxZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - minX; + Scalar z = point.z - maxZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise <= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = minZ - maxZ; + ramp.normal.y = 0.0f; + ramp.normal.z = minX - maxX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = maxX*ramp.normal.x + minZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingPositiveZAndPositiveX::TestInstance() const +{ + return solidType == WedgeFacingPositiveZAndPositiveXType; +} + +//############################################################################# +//################# BoxedWedgeFacingNegativeZAndNegativeX ############### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndNegativeX::BoxedWedgeFacingNegativeZAndNegativeX( + const ExtentBox &extents, + BoxedSolid::Material material, + Simulation *owner, + BoxedSolid *next_solid +): + BoxedSolid( + extents, + WedgeFacingNegativeZAndNegativeXType, + material, + owner, + next_solid + ) +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedWedgeFacingNegativeZAndNegativeX::~BoxedWedgeFacingNegativeZAndNegativeX() +{ + Check_Pointer(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::IntersectsBounded( + const ExtentBox &extents + ) +{ + Check(this); + Check(&extents); + + Verify(minX <= extents.minX); + Verify(maxX >= extents.maxX); + Verify(minY <= extents.minY); + Verify(maxY >= extents.maxY); + Verify(minZ <= extents.minZ); + Verify(maxZ >= extents.maxZ); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = extents.minX - maxX; + Scalar z = extents.minZ - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::ContainsBounded(const Point3D &point) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(maxY >= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //---------------------------------------------------------------------- + // Calculate the "slope" of the ramp when the base of the ramp is placed + // at the origin + //---------------------------------------------------------------------- + // + Scalar run = minX - maxX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + return x*rise <= z*run; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + BoxedWedgeFacingNegativeZAndNegativeX::FindDistanceBelowBounded( + const Point3D &point + ) +{ + Check(this); + Check(&point); + + Verify(minX <= point.x); + Verify(maxX >= point.x); + Verify(minY <= point.y); + Verify(minZ <= point.z); + Verify(maxZ >= point.z); + + // + //------------------------------------------------------------------------ + // Calculate the "slope" of the ramp when the NW corner the ramp is placed + // at the origin + //------------------------------------------------------------------------ + // + Scalar run = minX - maxX; + Scalar rise = maxZ - minZ; + Verify(!Small_Enough(run)); + + // + //------------------------------------------------------------------- + // Calculate the "slope" of the line from the base of the ramp to the + // lower-north edge of the block + //------------------------------------------------------------------- + // + Scalar x = point.x - maxX; + Scalar z = point.z - minZ; + + // + //------------------------------------------------------------------------ + // If the slope rise/run is more negative than z/x slope, then the extent + // box of the disk has clipped the ramp. Note that rise/run <= z/x yields + // rise*x <= z*run, which avoids any divide-by-0 errors. + //------------------------------------------------------------------------ + // + if (x*rise <= z*run) + { + x = point.y - maxY; + return Max(x,0.0f); + } + return -1.0f; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::HitByBounded( + Line *line, + Scalar enters, + Scalar leaves + ) +{ + Plane + ramp; + + ramp.normal.x = maxZ - minZ; + ramp.normal.y = 0.0f; + ramp.normal.z = maxX - minX; + + // + //----------------------------- + // Scale the vector to a normal + //----------------------------- + // + Scalar temp = ramp.normal.x*ramp.normal.x + ramp.normal.z*ramp.normal.z; + Verify(!Small_Enough(temp)); + temp = Sqrt(temp); + ramp.normal.x /= temp; + ramp.normal.z /= temp; + ramp.offset = minX*ramp.normal.x + maxZ*ramp.normal.z; + + // + //--------------------------------------------------------------------- + // Now that we have added a new plane into the definition of the convex + // polyhedron, call a common ramp line collider + //--------------------------------------------------------------------- + // + return BoxedRampContainsLine(line, ramp, enters, leaves); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BoxedWedgeFacingNegativeZAndNegativeX::TestInstance() const +{ + return solidType == WedgeFacingNegativeZAndNegativeXType; +} diff --git a/MUNGA/CAMINST.cpp b/MUNGA/CAMINST.cpp new file mode 100644 index 0000000..3e1df05 --- /dev/null +++ b/MUNGA/CAMINST.cpp @@ -0,0 +1,567 @@ +#include "munga.h" +#pragma hdrstop + +#include "caminst.h" +#include "notation.h" + +//########################################################################## +//############################# CameraInstance ####################### +//########################################################################## + +//########################################################################## +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance::CameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type +) +{ + Str_Copy(cameraName, "camera", sizeof(cameraName)); + itoa(camera_ID, cameraName+6, 10); + cameraID = camera_ID; + cameraDataType = camera_type; + SetLocalOrigin(camera_origin); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance::CameraInstance(StreamedInstance *model) +{ + cameraID = model->cameraID; + localOrigin = model->localOrigin; + cameraToWorld = localOrigin; + cameraDataType = model->cameraType; + for (int i=0; i<4; ++i) + { + clampValues[i] = model->clampValues[i]; + } + Str_Copy(cameraName, "camera", sizeof(cameraName)); + itoa(cameraID, cameraName+6, 10); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define READ_CAMERA_ENTRY(name,value)\ + if (\ + !cam_file->GetEntry(\ + camera_page_name,\ + name,\ + &value\ + )\ + )\ + { \ + DEBUG_STREAM << camera_page_name << " missing " name "!\n" << std::flush;\ + Fail("Bad cameras!");\ + } + +CameraInstance::CameraInstance( + NotationFile *cam_file, + const char *camera_page_name +) +{ + Check(this); + Check(cam_file); + Check_Pointer(camera_page_name); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PageName represents the cameraName + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Str_Copy(cameraName, camera_page_name, sizeof(cameraName)); + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Read in the position + //~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("tranx", localOrigin.linearPosition.x); + READ_CAMERA_ENTRY("trany", localOrigin.linearPosition.y); + READ_CAMERA_ENTRY("tranz", localOrigin.linearPosition.z); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the Orientation + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("quatx", localOrigin.angularPosition.x); + READ_CAMERA_ENTRY("quaty", localOrigin.angularPosition.y); + READ_CAMERA_ENTRY("quatz", localOrigin.angularPosition.z); + READ_CAMERA_ENTRY("quatw", localOrigin.angularPosition.w); + cameraToWorld = localOrigin; + + // + //--------------------- + // Read in camera clamp + //--------------------- + // + clampValues[0] = -PI; + cam_file->GetEntry( + camera_page_name, + "minYawClamp", + &clampValues[0].angle + ); + clampValues[1] = PI; + cam_file->GetEntry( + camera_page_name, + "maxYawClamp", + &clampValues[1].angle + ); + clampValues[2] = -PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "minPitchClamp", + &clampValues[2].angle + ); + clampValues[3] = PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "maxPitchClamp", + &clampValues[3].angle + ); + + // + // Overwrite default cameraID + // + const char *camera_data_entry; + if( + !cam_file->GetEntry( + camera_page_name, + "cameraType", + &camera_data_entry + ) + ) + { + cameraDataType = DefaultCameraType; + } + else + { + Check_Pointer(camera_data_entry); + cameraDataType = FindCameraType(camera_data_entry); + } + + READ_CAMERA_ENTRY("cameraID", cameraID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance::~CameraInstance() +{ +} + +//########################################################################## +// Data Access Funtions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + CameraInstance::FindCameraType(const char *camera_data_type) +{ + + if(strcmp("DefaultCameraType", camera_data_type) == 0) + { + return DefaultCameraType; + } + else if(strcmp("AlwaysSeesCameraType", camera_data_type) == 0) + { + return AlwaysSeesCameraType; + } + return ErrorCameraType; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void + CameraInstance::GetCameraTypeString(char *camera_type_string) +{ + switch(cameraDataType) + { + case DefaultCameraType: + Str_Copy( + camera_type_string, + "DefaultCameraType", + (sizeof(char) * 128) + ); + break; + case AlwaysSeesCameraType: + Str_Copy( + camera_type_string, + "AlwaysSeesCameraType", + (sizeof(char) * 128) + ); + break; + default: + Tell(cameraDataType); + Warn(" Invalid cameraType !\n"); + break; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::CalculateCameraRotation( + YawPitchRoll *result, + const Point3D &world + ) +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Given a Vector this function finds a rotation involving only + // pitch and yaw, roll will not be affected. In addition the rotation + // chosed will always be in the direction of least rotation + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(this); + Check(result); + Check(&world); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // find the vector from where we are to where we want to point + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Point3D local; + local.MultiplyByInverse(world, cameraToWorld); + if (Small_Enough(local.LengthSquared())) + { + *result = YawPitchRoll::Identity; + return; + } + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Calculate the angles + //~~~~~~~~~~~~~~~~~~~~~ + // + result->yaw = Radian::Normalize(Arctan(-local.x, -local.z)); + Scalar xz_direction = Sqrt((local.x * local.x) + (local.z *local.z)); + result->pitch = Radian::Normalize(Arctan(local.y, xz_direction)); + result->roll = 0.0f; + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::SetLocalOrigin( + const Origin &new_origin + ) +{ + Check(this); + Check(&new_origin); + + YawPitchRoll ypr; + ypr = new_origin.angularPosition; + clampValues[0] = clampValues[1] = 0.0f; + clampValues[2] = clampValues[3] = ypr.pitch; + ypr.pitch = 0.0f; + localOrigin.linearPosition = new_origin.linearPosition; + localOrigin.angularPosition = ypr; + cameraToWorld = localOrigin; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::LookAt( + Origin *result, + const Point3D &world_point + ) +{ + result->linearPosition = localOrigin.linearPosition; + YawPitchRoll first,local; + first = localOrigin.angularPosition; + CalculateCameraRotation(&local, world_point); + Clamp(local.yaw, clampValues[0], clampValues[1]); + Clamp(local.pitch, clampValues[2], clampValues[3]); + first.yaw += local.yaw; + first.pitch = local.pitch; + result->angularPosition = first; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::AllowLookingAt(const Point3D &world) +{ + YawPitchRoll local; + CalculateCameraRotation(&local, world); + if (local.yaw < clampValues[0]) + { + clampValues[0] = local.yaw; + } + else if (local.yaw > clampValues[1]) + { + clampValues[1] = local.yaw; + } + if (local.pitch < clampValues[2]) + { + clampValues[2] = local.pitch; + } + else if (local.pitch > clampValues[3]) + { + clampValues[3] = local.pitch; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define YAW_SLOP (PI/12.0) +#define PITCH_SLOP (0.75*(YAW_SLOP)) + +Logical + CameraInstance::CanCameraSee(const Point3D &world_point) +{ + YawPitchRoll ypr; + CalculateCameraRotation(&ypr, world_point); + return + clampValues[0]-YAW_SLOP <= ypr.yaw + && clampValues[1]+YAW_SLOP >= ypr.yaw + && clampValues[2]-PITCH_SLOP <= ypr.pitch + && clampValues[3]+PITCH_SLOP >= ypr.pitch; +} + +//########################################################################## +// Test Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraInstance::TestInstance() const +{ + return True; +} + +//########################################################################## +// Tool Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstance::WriteNotationPage(NotationFile *camera_stream) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Output this camera's information to the given notation file +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(this); + Check(camera_stream); + camera_stream->SetEntry( + cameraName, + "cameraID", + cameraID + ); + + char camera_type[128]; + GetCameraTypeString(camera_type); + camera_stream->SetEntry( + cameraName, + "cameraType", + camera_type + ); + + camera_stream->SetEntry( + cameraName, + "tranx", + localOrigin.linearPosition.x + ); + camera_stream->SetEntry( + cameraName, + "trany", + localOrigin.linearPosition.y + ); + camera_stream->SetEntry( + cameraName, + "tranz", + localOrigin.linearPosition.z + ); + camera_stream->SetEntry( + cameraName, + "quatx", + localOrigin.angularPosition.x + ); + camera_stream->SetEntry( + cameraName, + "quaty", + localOrigin.angularPosition.y + ); + camera_stream->SetEntry( + cameraName, + "quatz", + localOrigin.angularPosition.z + ); + camera_stream->SetEntry( + cameraName, + "quatw", + localOrigin.angularPosition.w + ); + camera_stream->SetEntry( + cameraName, + "minYawClamp", + clampValues[0] + ); + camera_stream->SetEntry( + cameraName, + "maxYawClamp", + clampValues[1] + ); + camera_stream->SetEntry( + cameraName, + "minPitchClamp", + clampValues[2] + ); + camera_stream->SetEntry( + cameraName, + "maxPitchClamp", + clampValues[3] + ); + camera_stream->AppendEntry(cameraName, NULL, (char *)NULL); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#undef READ_CAMERA_ENTRY +#define READ_CAMERA_ENTRY(name,value)\ + if (\ + !cam_file->GetEntry(\ + camera_page_name,\ + name,\ + &value\ + )\ + )\ + { \ + DEBUG_STREAM << camera_page_name << " missing " name "!\n" << std::flush;\ + return False;\ + } + +Logical + CameraInstance::CreateStreamedInstance( + StreamedInstance *model, + NotationFile *cam_file, + const char *camera_page_name + ) +{ + Check_Pointer(model); + Check(cam_file); + Check_Pointer(camera_page_name); + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Read in the position + //~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("tranx", model->localOrigin.linearPosition.x); + READ_CAMERA_ENTRY("trany", model->localOrigin.linearPosition.y); + READ_CAMERA_ENTRY("tranz", model->localOrigin.linearPosition.z); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the Orientation + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + READ_CAMERA_ENTRY("quatx", model->localOrigin.angularPosition.x); + READ_CAMERA_ENTRY("quaty", model->localOrigin.angularPosition.y); + READ_CAMERA_ENTRY("quatz", model->localOrigin.angularPosition.z); + READ_CAMERA_ENTRY("quatw", model->localOrigin.angularPosition.w); + + // + //--------------------- + // Read in camera clamp + //--------------------- + // + model->clampValues[0] = -PI; + cam_file->GetEntry( + camera_page_name, + "minYawClamp", + &model->clampValues[0].angle + ); + model->clampValues[1] = PI; + cam_file->GetEntry( + camera_page_name, + "maxYawClamp", + &model->clampValues[1].angle + ); + model->clampValues[2] = -PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "minPitchClamp", + &model->clampValues[2].angle + ); + model->clampValues[3] = PI_OVER_2; + cam_file->GetEntry( + camera_page_name, + "maxPitchClamp", + &model->clampValues[3].angle + ); + + // + // Overwrite default cameraID + // + const char *camera_data_entry; + if( + !cam_file->GetEntry( + camera_page_name, + "cameraType", + &camera_data_entry + ) + ) + { + model->cameraType = DefaultCameraType; + } + else + { + Check_Pointer(camera_data_entry); + model->cameraType = FindCameraType(camera_data_entry); + } + + READ_CAMERA_ENTRY("cameraID", model->cameraID); + + model->instanceSize = sizeof(*model); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlwaysSeesCameraInstance::AlwaysSeesCameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type +): + CameraInstance(camera_ID, camera_origin, camera_type) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlwaysSeesCameraInstance::AlwaysSeesCameraInstance(StreamedInstance *model): + CameraInstance(model) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlwaysSeesCameraInstance::AlwaysSeesCameraInstance( + NotationFile *cam_file, + const char *camera_page_name +): + CameraInstance(cam_file, camera_page_name) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + AlwaysSeesCameraInstance::CanCameraSee(const Point3D &) +{ + return True; +} \ No newline at end of file diff --git a/MUNGA/CAMINST.h b/MUNGA/CAMINST.h new file mode 100644 index 0000000..2a2d3c8 --- /dev/null +++ b/MUNGA/CAMINST.h @@ -0,0 +1,173 @@ +#pragma once + +#include "plug.h" +#include "origin.h" +#include "rotation.h" +#include "linmtrx.h" + +class NotationFile; + +struct CameraInstance__StreamedInstance +{ + size_t instanceSize; + int + cameraType, + cameraID; + Origin + localOrigin; + Radian + clampValues[4]; +}; + +//########################################################################## +//############################# CameraInstance ####################### +//########################################################################## + +class CameraInstance : + public Plug +{ + friend class CameraInstanceManager; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// local member data +// + public: + + enum { + ErrorCameraType, + DefaultCameraType, + AlwaysSeesCameraType, + CameraTypeCount, + }; + + Radian + clampValues[4]; + + protected: + Origin + localOrigin; + LinearMatrix + cameraToWorld; + + static int + FindCameraType(const char *camera_data_type); + + void + GetCameraTypeString(char *camera_type_string); + + Enumeration + cameraDataType; + + int + cameraID; + + char + cameraName[128]; + + void + CalculateCameraRotation( + YawPitchRoll *result, + const Point3D &world + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// public member data access functions +// + public: + int + GetCameraID() + {Check(this); return cameraID;} + + const char* + GetCameraName() + {Check(this); return cameraName;} + void + SetCameraName(const char* camera_name) + {Str_Copy(cameraName, camera_name, sizeof(cameraName));} + + const Enumeration + GetCameraType() + {Check(this); return cameraDataType;} + + const Origin& + GetLocalOrigin() + {Check(this); return localOrigin;} + void + SetLocalOrigin(const Origin &new_origin); + const Point3D& + GetPosition() + {Check(this); return localOrigin.linearPosition;} + + void + LookAt( + Origin *result, + const Point3D &world_point + ); + void + AllowLookingAt(const Point3D &world); + + virtual Logical + CanCameraSee(const Point3D &world_point); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Class Support +// + public: + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Contruction and Destruction Support +// + public: + typedef CameraInstance__StreamedInstance StreamedInstance; + + CameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type = DefaultCameraType + ); + CameraInstance(StreamedInstance *model); + CameraInstance( + NotationFile *cam_file, + const char *camera_page_name + ); + + ~CameraInstance(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Tool Support +// + public: + void + WriteNotationPage(NotationFile *camera_stream); + static Logical + CreateStreamedInstance( + StreamedInstance *model, + NotationFile *cam_file, + const char *camera_page_name + ); +}; + +//########################################################################## +//############################# CameraInstance ####################### +//########################################################################## + +class AlwaysSeesCameraInstance : + public CameraInstance +{ +public: + AlwaysSeesCameraInstance( + int camera_ID, + const Origin &camera_origin, + Enumeration camera_type = DefaultCameraType + ); + AlwaysSeesCameraInstance(StreamedInstance *model); + AlwaysSeesCameraInstance( + NotationFile *cam_file, + const char *camera_page_name + ); + + Logical + CanCameraSee(const Point3D &world_point); +}; diff --git a/MUNGA/CAMMGR.cpp b/MUNGA/CAMMGR.cpp new file mode 100644 index 0000000..d8ed262 --- /dev/null +++ b/MUNGA/CAMMGR.cpp @@ -0,0 +1,748 @@ +#include "munga.h" +#pragma hdrstop + +#include "cammgr.h" +#include "mission.h" +#include "app.h" +#include "notation.h" +#include "namelist.h" + +//########################################################################## +//##################### CameraInstanceManager ####################### +//########################################################################## + +//########################################################################## +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstanceManager::CameraInstanceManager() : + cameraList(NULL) +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize local member data + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + cameraIterator = new SChainIteratorOf(cameraList); + Register_Object(cameraIterator); + InitializeCameraInstances(); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstanceManager::~CameraInstanceManager() +{ + DeleteCameraList(); + Unregister_Object(cameraIterator); + delete cameraIterator; + cameraIterator = NULL; + Check_Fpu(); +} + +//########################################################################## +// CameraInstance Creation and Deletion Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + CameraInstanceManager::FindUniqueCameraID() +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Finds a cameraID that has been freed up or the next sequential number +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + SChainIteratorOf iterator(cameraList); + CameraInstance *camera_instance; + int camera_ID = 0; + Logical ID_exists = False; + + while(1) + { + // + //~~~~~~~~~~~~~~~~~~~~ + // Reset the iterator + //~~~~~~~~~~~~~~~~~~~~ + // + iterator.First(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Iterate through the list of all cameraInstances for every ID Chosen + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + while ( (camera_instance = iterator.ReadAndNext()) != NULL) + { + if(camera_ID == camera_instance->GetCameraID()) + { + ID_exists = True; + break; + } + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If this cameraID not already used return the ID + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(!ID_exists) + { + break; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Otherwise increment the ID and reset the boolean + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ++camera_ID; + ID_exists = False; + } + + Check_Fpu(); + return camera_ID; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::SetCamera( + const Origin &new_origin, + CameraInstance *camera_instance + ) +{ + + if(!camera_instance) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // No camera passed as an argument use cameraIterator + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + camera_instance = cameraIterator->GetCurrent(); + if(!camera_instance) + { + CreateCameraInstance(new_origin); + } + else + { + camera_instance->SetLocalOrigin(new_origin); + } + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Camera passed in set its origin + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + camera_instance->SetLocalOrigin(new_origin); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::CreateCameraInstance(const Origin &new_origin) +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Find a Unique CameraID + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + int camera_ID; + camera_ID = FindUniqueCameraID(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the new cameraInstance + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CameraInstance *camera_instance = + new CameraInstance( + camera_ID, + new_origin + ); + Register_Object(camera_instance); + AddCameraInstance(camera_instance); + + Check_Fpu(); + return camera_instance; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::AddCameraInstance(CameraInstance *camera_instance) +{ + Check(this); + Check(cameraIterator); + Check(&cameraList); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Insert the new Camera Instance into the cameraList + // & Point the cameraIterator to it + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (!cameraIterator->GetCurrent()) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If nothing in the cameraList create the first element + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + cameraList.Add(camera_instance); + cameraIterator->First(); + Tell("Created the First Camera Instance \n"); + } + else + { + cameraList.Add(camera_instance); + cameraIterator->Next(); + Tell("Created a Camera Instance \n"); + } + Check_Fpu(); + return camera_instance; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::DeleteCameraInstance() +{ + CameraInstance *camera_instance = cameraIterator->GetCurrent(); + if(!camera_instance) + { + return NULL; + } + + cameraIterator->Remove(); + if(!cameraIterator->GetCurrent()) + { + cameraIterator->First(); + } + Unregister_Object(camera_instance); + delete camera_instance; + return GetCurrent(); +} + +//########################################################################## +// CameraList Manipulator Functions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::DeleteCameraList() +{ + while (cameraIterator->GetCurrent() != NULL) + { + DeleteCameraInstance(); + } +} + +//########################################################################## +// CameraList Iterator Manipulator Functions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::IncrementIterator() +{ + Check(this); + if (cameraIterator->GetCurrent()) + { + Check(cameraIterator); + cameraIterator->ReadAndNext(); + if (!cameraIterator->GetCurrent()) + { + cameraIterator->First(); + } + } + Check_Fpu(); + return GetCurrent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::DecrementIterator() +{ + Check(this); + if (cameraIterator->GetCurrent()) + { + Check(cameraIterator); + cameraIterator->ReadAndPrevious(); + if (!cameraIterator->GetCurrent()) + { + cameraIterator->Last(); + } + } + Check_Fpu(); + return GetCurrent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::AdvanceIterator(const CameraInstance &camera_instance) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Search for the camera_instance in the cameraList +// Iterator points to camera_instance upon return +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(&camera_instance); + Check(&cameraList); + Check(cameraIterator); + + CameraInstance *current_instance; + cameraIterator->First(); + + while((current_instance = cameraIterator->GetCurrent()) != NULL) + { + if(current_instance == &camera_instance) + { + Check_Fpu(); + return current_instance; + } + cameraIterator->Next(); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // camera_instance not found return NULL + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check_Fpu(); + return NULL; +} + +//########################################################################## +// CameraList Searching and Query Functions +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraInstance* + CameraInstanceManager::FindClosestCamera(const Point3D &point_3D) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Use a Simple distance formula to find closest camera +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(this); + CameraInstance *closest_camera = NULL; + Scalar dist_to_goal, min_dist=1e8f; + + SChainIteratorOf iterator(cameraList); + CameraInstance *camera_instance; + while ( (camera_instance = iterator.ReadAndNext()) != NULL) + { + Check(camera_instance); + if (camera_instance->CanCameraSee(point_3D)) + { + Vector3D v; + v.Subtract(point_3D, camera_instance->GetPosition()); + dist_to_goal = v.LengthSquared(); + Check_Fpu(); + if (dist_to_goal < min_dist) + { + min_dist = dist_to_goal; + closest_camera = camera_instance; + } + } + } + Check_Fpu(); + return closest_camera; +} + +//########################################################################## +// Test Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraInstanceManager::TestInstance() const +{ + return True; +} + +//########################################################################## +// Tool Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::InitializeCameraInstances() +{ + Check(application); + ResourceDescription::ResourceID map_ID; + map_ID = application->GetCurrentMission()->GetMapID(); + + ResourceFile *res_file; + res_file = application->GetResourceFile(); + Check(res_file); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the camera filename from the map name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *res = res_file->FindResourceDescription(map_ID); + Check(res); + Str_Copy( + cameraFilename, + "cameras\\", + sizeof(cameraFilename) + ); + // + // cam name matches map name + // + Str_Cat( + cameraFilename, + res->resourceName, + sizeof(cameraFilename) + ); + // + // trunc cam name to DOS filename size + // + int name_length = strlen(cameraFilename); + if(name_length > 17) + { + cameraFilename[17] = '\0'; + } + + // + // Add the extension + // + Str_Cat( + cameraFilename, + ".cam", + sizeof(cameraFilename) + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // See if the file exists + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + std::fstream cam_file; + //cam_file.open(cameraFilename, std::ios::nocreate | std::ios::in | std::ios::out); + // following alternate line created by Ryan Bunker on 1/6/07 + cam_file.open(cameraFilename, std::ios.in); + if(cam_file) //NOTE: this appears broken (RB 1/6/07) + { + cam_file.close(); + ReadNotationFile(); + } + else + { + cam_file.close(); + CreateStreamedCameraInstances(res_file, res->resourceName); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::ReadNotationFile() +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a Notation file out of the camera file + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NotationFile *cam_file = new NotationFile(cameraFilename); + Register_Object(cam_file); + + NameList* camera_namelist = cam_file->MakePageList(); + Register_Object(camera_namelist); + + NameList::Entry *camera_entry = camera_namelist->GetFirstEntry(); + + char + camera_page_name[128]; + + while (camera_entry) + { + Str_Copy( + camera_page_name, + camera_entry->GetName(), + sizeof(camera_page_name) + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a new camera Instance for this page + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CameraInstance *camera_instance; + const char *camera_data_entry; + int cam_type; + if( + !cam_file->GetEntry( + camera_page_name, + "cameraType", + &camera_data_entry + ) + ) + { + cam_type = CameraInstance::DefaultCameraType; + } + else + { + Check_Pointer(camera_data_entry); + cam_type = CameraInstance::FindCameraType(camera_data_entry); + } + switch (cam_type) + { + case CameraInstance::DefaultCameraType: + camera_instance = new CameraInstance(cam_file, camera_page_name); + break; + case CameraInstance::AlwaysSeesCameraType: + camera_instance = + new AlwaysSeesCameraInstance(cam_file, camera_page_name); + break; + } + Register_Object(camera_instance); + AddCameraInstance(camera_instance); + camera_entry = camera_entry->GetNextEntry(); + } + Unregister_Object(camera_namelist); + delete camera_namelist; + Unregister_Object(cam_file); + delete cam_file; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define PAGE_NAME_SIZE 128 + +void + CameraInstanceManager::CreateStreamedCameraInstances( + ResourceFile *res_file, + const char *map_name + ) +{ + Check(this); + Check_Pointer(res_file); + Check_Pointer(map_name); + + ResourceDescription *res = + res_file->FindResourceDescription( + map_name, + ResourceDescription::CameraStreamResourceType + ); + if (!res) + { + Check_Fpu(); + return; + } + + res->Lock(); + + MemoryStream camera_stream(res->resourceAddress, res->resourceSize); + int camera_count = *(int*)camera_stream.GetPointer(); + camera_stream.AdvancePointer(sizeof(camera_count)); + + // + //-------------------- + // Read in each camera + //-------------------- + // + while (camera_count--) + { + Check(&camera_stream); + CameraInstance::StreamedInstance *model = + (CameraInstance::StreamedInstance*)camera_stream.GetPointer(); + Check_Pointer(model); + CameraInstance *camera_instance; + switch (model->cameraType) + { + case CameraInstance::DefaultCameraType: + camera_instance = new CameraInstance(model); + break; + case CameraInstance::AlwaysSeesCameraType: + camera_instance = new AlwaysSeesCameraInstance(model); + break; + } + Register_Object(camera_instance); + AddCameraInstance(camera_instance); + camera_stream.AdvancePointer(model->instanceSize); + } + res->Unlock(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraInstanceManager::WriteNotationFile() +{ + Check(this); + Check(&cameraList); + + NotationFile *camera_stream = new NotationFile(); + Register_Object(camera_stream); + + if(!camera_stream) + { + Fail("Error Opening Camera File\n"); + } + SChainIteratorOf iterator(cameraList); + CameraInstance *camera_instance; + + iterator.First(); + while ( (camera_instance = iterator.ReadAndNext()) != NULL) + { + camera_instance->WriteNotationPage(camera_stream); + } + camera_stream->WriteFile(cameraFilename); + Unregister_Object(camera_stream); + delete camera_stream; + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define PAGE_NAME_SIZE 128 +ResourceDescription::ResourceID + CameraInstanceManager::CreateCameraInstancesStream( + ResourceFile *resource_file, + const char *camera_name, + const ResourceDirectories *directories + ) +{ + Check_Pointer(camera_name); + Check_Pointer(directories); + + // + //------------------- + // Open the .cam file + //------------------- + // + int length = strlen(camera_name) + strlen(directories->mapDirectory)+ 1; + + char *filename = new char[length]; + Register_Pointer(filename); + + Str_Copy(filename, directories->mapDirectory, length); + strncat(filename, camera_name, strlen(camera_name)-3); + Str_Cat(filename, "cam", length); + + NotationFile *camera_notation = new NotationFile(filename); + Register_Object(camera_notation); + + if (camera_notation->PageCount() == 0) + { + DEBUG_STREAM << "Missing .cam file" << std::endl << std::flush; +Dump_And_Die: + Unregister_Object(camera_notation); + delete camera_notation; + Unregister_Pointer(filename); + delete[] filename; + return ResourceDescription::NullResourceID; + } + + int camera_count = 0; + NameList *pagelist = camera_notation->MakePageList(); + Register_Object(pagelist); + NameList::Entry *entry = pagelist->GetFirstEntry(); + char page_name[PAGE_NAME_SIZE]; + + while (entry) + { + ++camera_count; + entry = entry->GetNextEntry(); + } + + size_t array_size = + sizeof(CameraInstance::StreamedInstance) * camera_count * 2; + long *camera_array = new long[(array_size+3) >> 2]; + Register_Pointer(camera_array); + MemoryStream camera_stream(camera_array, array_size); + + *(int*)camera_stream.GetPointer() = camera_count; + camera_stream.AdvancePointer(sizeof(camera_count)); + + entry = pagelist->GetFirstEntry(); + while (entry) + { + Str_Copy( + page_name, + entry->GetName(), + sizeof(page_name) + ); + + if(strcmp(page_name, "CameraInfo") == 0) + { + entry = entry->GetNextEntry(); + continue; + } + + Check(&camera_stream); + CameraInstance::StreamedInstance *model = + (CameraInstance::StreamedInstance*)camera_stream.GetPointer(); + Check_Pointer(model); + if ( + !CameraInstance::CreateStreamedInstance( + model, + camera_notation, + page_name + ) + ) + { + Unregister_Pointer(camera_array); + delete[] camera_array; + Unregister_Object(pagelist); + delete pagelist; + goto Dump_And_Die; + } + camera_stream.AdvancePointer(model->instanceSize); + entry = entry->GetNextEntry(); + } + + // + //------------------------------- + // Write the stream out to disk. + // + + Str_Copy(filename, camera_name, length); + filename[strlen(camera_name)-4] = '\0'; + + ResourceDescription *new_res = + resource_file->AddResource( + filename, + ResourceDescription::CameraStreamResourceType, + 1, + ResourceDescription::LoadOnDemandFlag, + camera_array, + camera_stream.GetBytesUsed() + ); + Check(new_res); + + //----------- + // Free Mem + // + + + Unregister_Pointer(camera_array); + delete[] camera_array; + Unregister_Pointer(filename); + delete[] filename; + Unregister_Object(camera_notation); + delete camera_notation; + Unregister_Object(pagelist); + delete pagelist; + + return new_res->resourceID; +} diff --git a/MUNGA/CAMMGR.h b/MUNGA/CAMMGR.h new file mode 100644 index 0000000..41a1699 --- /dev/null +++ b/MUNGA/CAMMGR.h @@ -0,0 +1,106 @@ +#pragma once + +#include "resource.h" +#include "schain.h" +#include "caminst.h" + +//########################################################################## +//##################### CameraInstanceManager ####################### +//########################################################################## + +class CameraInstanceManager SIGNATURED +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// local member data +// +protected: + // + // cameraList is a circular Linked list + // which holds cameraInstances + // + SChainOf cameraList; + // + // CameraIterator holds the current position in the + // camera list for the lifetime of the class + // & == NULL if the list is empty + // + SChainIteratorOf *cameraIterator; + + int FindUniqueCameraID(); + + char cameraFilename[128]; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public Member Manipulation Functions +// +public: + // + // CameraList Manipulator Functions + // + void SetCamera(const Origin &new_origin, CameraInstance *camera_instance = NULL); + + CameraInstance* CreateCameraInstance(const Origin &new_origin); + + CameraInstance* AddCameraInstance(CameraInstance *camera_instance); + + CameraInstance* DeleteCameraInstance(); + + void DeleteCameraList(); + + // + // Iterator Manipulator Functions (Circular Chain) + // + CameraInstance* IncrementIterator(); + + CameraInstance* DecrementIterator(); + + CameraInstance* AdvanceIterator(const CameraInstance &camera_instance); + + CameraInstance* GetCurrent() const + { + Check(this); + return cameraIterator->GetCurrent(); + } + + CameraInstance* First() + { + Check(this); + Check(cameraIterator->GetCurrent()); + cameraIterator->First(); + return GetCurrent(); + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CameraList Searching and Query Functions +// +public: + CameraInstance* FindClosestCamera(const Point3D &point_3D); + CameraInstance* FindClosestCameraShowing(const Point3D *points); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Class Support +// +public: + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + CameraInstanceManager(); + ~CameraInstanceManager(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Tool Support +// +protected: + + void InitializeCameraInstances(); + +public: + void ReadNotationFile(); + void CreateStreamedCameraInstances(ResourceFile *res_file, const char *map_name); + + void WriteNotationFile(); + static ResourceDescription::ResourceID CreateCameraInstancesStream(ResourceFile *resource_file, const char *camera_name, const ResourceDirectories *directories); +}; diff --git a/MUNGA/CAMMPPR.cpp b/MUNGA/CAMMPPR.cpp new file mode 100644 index 0000000..063af52 --- /dev/null +++ b/MUNGA/CAMMPPR.cpp @@ -0,0 +1,244 @@ +#include "munga.h" +#pragma hdrstop + +#include "cammppr.h" + +//############################################################################# +// Shared Data Support +// +CameraControlsMapper::SharedData + CameraControlsMapper::DefaultData( + CameraControlsMapper::GetClassDerivations(), + CameraControlsMapper::GetMessageHandlers(), + CameraControlsMapper::GetAttributeIndex(), + CameraControlsMapper::StateCount + ); + +Derivation* CameraControlsMapper::GetClassDerivations() +{ + static Derivation classDerivations(Subsystem::GetClassDerivations(), "CameraControlsMapper"); + return &classDerivations; +} + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraControlsMapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraControlsMapper, Keypress), + MESSAGE_ENTRY(CameraControlsMapper, DirectorMode), + MESSAGE_ENTRY(CameraControlsMapper, IncrementCamera), + MESSAGE_ENTRY(CameraControlsMapper, DecrementCamera), + MESSAGE_ENTRY(CameraControlsMapper, CreateCameraInstance), + MESSAGE_ENTRY(CameraControlsMapper, DeleteCameraInstance), + MESSAGE_ENTRY(CameraControlsMapper, OutputCameraInstances) +}; + +CameraControlsMapper::MessageHandlerSet& CameraControlsMapper::GetMessageHandlers() +{ + static CameraControlsMapper::MessageHandlerSet messageHandlers(ELEMENTS(CameraControlsMapper::MessageHandlerEntries), CameraControlsMapper::MessageHandlerEntries, Subsystem::GetMessageHandlers()); + return messageHandlers; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::KeypressMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + switch (message->dataContents) + { + case 'd': + case 'D': + { + ReceiverDataMessageOf + button_message2( + CameraControlsMapper::DirectorModeMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + Dispatch(&button_message2); + break; + } + + case 'o': + case 'O': + { + ReceiverDataMessageOf + button_message2( + CameraControlsMapper::OutputCameraInstancesMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + Dispatch(&button_message2); + break; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::DirectorModeMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + if(camera->GetSimulationState() != CameraShip::ConfigureCamerasState) + { + camera->SetPerformance(&CameraShip::DriveCamera); + camera->SetSimulationState(CameraShip::ConfigureCamerasState); + CameraInstance *cam = camera->GetCurrentCamera(); + Check(cam); + //DEBUG_STREAM << cam->GetCameraName() << std::endl << std::flush; + } + else + { + camera->SetPerformance(&CameraShip::FollowGoal); + camera->SetSimulationState(CameraShip::DefaultState); + camera->lastSwitch = Now(); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::IncrementCameraMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if(message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->IncrementCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::DecrementCameraMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->DecrementCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::CreateCameraInstanceMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->CreateCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::DeleteCameraInstanceMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->DeleteCameraInstance(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraControlsMapper::OutputCameraInstancesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + CameraShip *camera = GetEntity(); + Check(camera); + camera->OutputCameraList(); + } +} + +//############################################################################# +// Attribute Support +// +const CameraControlsMapper::IndexEntry + CameraControlsMapper::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(CameraControlsMapper, StickPosition, stickPosition), + ATTRIBUTE_ENTRY(CameraControlsMapper, ThrottlePosition, throttlePosition), + ATTRIBUTE_ENTRY(CameraControlsMapper, PedalsPosition, pedalsPosition), + ATTRIBUTE_ENTRY(CameraControlsMapper, ReverseThrust, reverseThrust), + ATTRIBUTE_ENTRY(CameraControlsMapper, DriveCamera, driveCamera), + ATTRIBUTE_ENTRY(CameraControlsMapper, SlideOrClamp, slideOrClamp) +}; + +CameraControlsMapper::AttributeIndexSet& CameraControlsMapper::GetAttributeIndex() +{ + static CameraControlsMapper::AttributeIndexSet attributeIndex(ELEMENTS(CameraControlsMapper::AttributePointers), + CameraControlsMapper::AttributePointers, + Subsystem::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraControlsMapper::CameraControlsMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + Subsystem(owner, subsystem_ID, subsystem_resource, shared_data) +{ + stickPosition.x = 0.0f; + stickPosition.y = 0.0f; + throttlePosition = 0.0f; + pedalsPosition = 0.0f; + driveCamera = 0; + slideOrClamp = 0; + reverseThrust = 0; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraControlsMapper::~CameraControlsMapper() +{ +} + +Logical + CameraControlsMapper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/CAMMPPR.h b/MUNGA/CAMMPPR.h new file mode 100644 index 0000000..cbd1d64 --- /dev/null +++ b/MUNGA/CAMMPPR.h @@ -0,0 +1,110 @@ +#pragma once + +#include "subsystm.h" +#include "camship.h" +#include "controls.h" + +//########################################################################## +//####################### CameraControlsMapper ######################## +//########################################################################## +class CameraControlsMapper : public Subsystem +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging Support +// +public: + enum + { + KeypressMessageID = Subsystem::NextMessageID, + DirectorModeMessageID, + IncrementCameraMessageID, + DecrementCameraMessageID, + CreateCameraInstanceMessageID, + DeleteCameraInstanceMessageID, + OutputCameraInstancesMessageID, + NextMessageID + }; + + void KeypressMessageHandler(ReceiverDataMessageOf *message); + + void DirectorModeMessageHandler(ReceiverDataMessageOf *message); + + void IncrementCameraMessageHandler(ReceiverDataMessageOf *message); + + void DecrementCameraMessageHandler(ReceiverDataMessageOf *message); + + void CreateCameraInstanceMessageHandler(ReceiverDataMessageOf *message); + + void DeleteCameraInstanceMessageHandler(ReceiverDataMessageOf *message); + + void OutputCameraInstancesMessageHandler(ReceiverDataMessageOf *message); + +protected: + static const HandlerEntry MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum + { + StickPositionAttributeID = Subsystem::NextAttributeID, + ThrottlePositionAttributeID, + PedalsPositionAttributeID, + ReverseThrustAttributeID, + DriveCameraAttributeID, + SlideOrClampAttributeID, + NextAttributeID + }; +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + ControlsJoystick stickPosition; + Scalar throttlePosition; + Scalar pedalsPosition; + ControlsButton reverseThrust; + ControlsButton driveCamera; + ControlsButton slideOrClamp; + +//########################################################################## +// Model support +// +public: + CameraShip* GetEntity() { return (CameraShip*)Subsystem::GetEntity(); } + + typedef void (CameraControlsMapper::*Performance)(Scalar time_slice); + + void SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +protected: + CameraControlsMapper(CameraShip *owner, int subsystem_ID, SubsystemResource *subsystem_resource, SharedData &shared_data); + +public: + ~CameraControlsMapper(); + + Logical TestInstance() const; +}; diff --git a/MUNGA/CAMSHIP.cpp b/MUNGA/CAMSHIP.cpp new file mode 100644 index 0000000..9e8e0db --- /dev/null +++ b/MUNGA/CAMSHIP.cpp @@ -0,0 +1,732 @@ +#include "munga.h" +#pragma hdrstop + +#include "camship.h" +#include "player.h" +#include "mission.h" +#include "cammppr.h" +#include "app.h" +#include "hostmgr.h" + +//########################################################################## +//############################# CameraShip ################################ +//########################################################################## + +//############################################################################# +// Shared Data Support +// +Derivation* CameraShip::GetClassDerivations() +{ static Derivation classDerivations(Mover::GetClassDerivations(), "CameraShip"); + return &classDerivations; +} + + +CameraShip::SharedData + CameraShip::DefaultData( + CameraShip::GetClassDerivations(), + CameraShip::MessageHandlers, + CameraShip::GetAttributeIndex(), + CameraShip::StateCount, + (Entity::MakeHandler)CameraShip::Make + ); + +//############################################################################# +// Attribute Support +// + +const CameraShip::IndexEntry + CameraShip::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(CameraShip, MapRange, mapRange), + ATTRIBUTE_ENTRY(CameraShip, MapLinearPosition, mapLinearPosition), + ATTRIBUTE_ENTRY(CameraShip, MapAngularPosition, mapAngularPosition) +}; + +CameraShip::AttributeIndexSet& CameraShip::GetAttributeIndex() +{ + static CameraShip::AttributeIndexSet attributeIndex(ELEMENTS(CameraShip::AttributePointers), + CameraShip::AttributePointers, + Mover::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraShip::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraShip, Direction) +}; + +CameraShip::MessageHandlerSet + CameraShip::MessageHandlers( + ELEMENTS(CameraShip::MessageHandlerEntries), + CameraShip::MessageHandlerEntries, + Entity::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DirectionMessageHandler(DirectionMessage *message) +{ + Check(this); + Check(message); + + Check(application); + HostManager *host = application->GetHostManager(); + Check(host); + SetGoalEntity(host->GetEntityPointer(message->goalEntity)); + Check(goalEntity); + mapLinearPosition = &goalEntity->localOrigin.linearPosition; + focusOffset = message->focusOffset; + SetSimulationState(DefaultState); + timeOnCamera = message->timeOnCamera; + lastSwitch = Now(); + lastSwitch -= timeOnCamera; + Check_Fpu(); +} + +//############################################################################# +// ControlsMapper Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::SetMappingSubsystem(CameraControlsMapper *mapper) +{ + Check(this); + Check(mapper); + if(subsystemArray[ControlsMapperSubsystem]) + { + Unregister_Object(subsystemArray[ControlsMapperSubsystem]); + delete subsystemArray[ControlsMapperSubsystem]; + } + subsystemArray[ControlsMapperSubsystem] = mapper; + Check_Fpu(); +} + +//############################################################################# +// Simulation Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DriveCamera(Scalar time_slice) +{ + Check(this); + CameraControlsMapper* controls = + Cast_Object( + CameraControlsMapper*, + GetSubsystem(CameraShip::ControlsMapperSubsystem) + ); + Check(controls); + + // + //----------------------------------------------- + // If we are in positioning mode, move the camera + //----------------------------------------------- + // + if (controls->driveCamera > 0) + { + ApplyControlledPanAndTilt(controls, time_slice); + ApplyControlledCameraMotion(controls, time_slice); + ApplyControlledCameraHeight(controls); + currentCamera->SetLocalOrigin(localOrigin); + } + + // + //------------------------------------------------------------------------ + // Operate in camera mode, obeying the limits of the camera as established + // by the clamps + //------------------------------------------------------------------------ + // + else + { + // + //------------------------- + // Stop any existing motion + //------------------------- + // + worldLinearVelocity = Vector3D::Identity; + + // + //----------------------------------------------------------------------- + // Read the controls for panning the camera, and if the clamp override is + // on, tell the camera to allow this orientation + //----------------------------------------------------------------------- + // + ApplyControlledPanAndTilt(controls, time_slice); + localToWorld = localOrigin; + + // + //--------------------------------------------------------------------- + // Establish an aim point along negative Z and figure out where that is + // in world space, then point the camera there. The camera clamps will + // automatically do their thing + //--------------------------------------------------------------------- + // + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + if (controls->slideOrClamp > 0) + { + currentCamera->AllowLookingAt(world_aim); + } + AimCameraAtPoint(world_aim); + } + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::ApplyControlledPanAndTilt( + CameraControlsMapper *controls, + Scalar time_slice + ) +{ + Check(this); + Check(controls); + + // + //----------------------------------------- + // Point the Camera in the direction of the + // Joystick Position Calc Pitch and Yaw only + //----------------------------------------- + // + Scalar rotation_amount; + if(controls->stickPosition.x < -0.02f) + { + + rotation_amount = controls->stickPosition.x + 0.02f; + rotation_amount *= rotation_amount; + rotation_amount *= -1.0f; + } + else if (controls->stickPosition.x > 0.02f) + { + rotation_amount = controls->stickPosition.x - 0.02f; + rotation_amount *= rotation_amount; + } + else + { + rotation_amount = 0.0f; + } + YawPitchRoll ypr; + ypr = localOrigin.angularPosition; + + ypr.yaw += rotation_amount * PI * time_slice; + ypr.pitch += controls->stickPosition.y * PI * 0.2f * time_slice; + + localOrigin.angularPosition = ypr; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::ApplyControlledCameraHeight(CameraControlsMapper *controls) +{ + Check(this); + Check(controls); + + // + //---------------------------------------------------- + // Raise and lower the cameraShip according to the pedals + //---------------------------------------------------- + // + localOrigin.linearPosition.y += controls->pedalsPosition; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::ApplyControlledCameraMotion( + CameraControlsMapper *controls, + Scalar time_slice + ) +{ + Check(this); + Check(controls); + + localAcceleration.linearMotion.z = + -25.0f * controls->throttlePosition * time_slice; + if (controls->reverseThrust > 0) + { + localAcceleration.linearMotion.z = -localAcceleration.linearMotion.z; + } + + // + //~~~~~~~~~~~~~~~~~~~ + // Apply Linear Drag + //~~~~~~~~~~~~~~~~~~~ + // + Vector3D drag_force; + + drag_force.Multiply( + localVelocity.linearMotion, + positiveLinearDragCoefficients + ); + + Vector3D new_accel; + new_accel.Subtract( + localAcceleration.linearMotion, + drag_force + ); + + localAcceleration.linearMotion = new_accel; + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // ApplyWorldAccelerations + //~~~~~~~~~~~~~~~~~~~~~~~~ + localVelocity.linearMotion += localAcceleration.linearMotion; + + worldLinearVelocity.Multiply( + localVelocity.linearMotion, + localToWorld + ); + localOrigin.linearPosition += worldLinearVelocity; + + Check_Fpu(); +} + +//############################################################################# +// Follow GoalEntity Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::FollowGoal(Scalar time_slice) +{ + Check(this); + + // + //----------------------------------------------- + // If no goalEntity assigned ask for one and wait + //----------------------------------------------- + // + if (!goalEntity) + { + return; + } + Check(goalEntity); + Point3D target; + target.Multiply(focusOffset, goalEntity->localToWorld); + + // + //------------------------------------------------------------------------ + // If time has not yet expired on this camera, keep with it if can see the + // goal entity + //------------------------------------------------------------------------ + // + Check(currentCamera); + if ( + lastPerformance - lastSwitch > timeOnCamera + || !currentCamera->CanCameraSee(target) + ) + { + CameraInstance *old_camera = currentCamera; + GoToClosestCamera(target); + if (!currentCamera) + { + currentCamera = old_camera; + } + Check(currentCamera); + + // + //------------------------------------------------------------------------ + // If we need to switch cameras, have the new camera point directly at the + // target + //------------------------------------------------------------------------ + // + if (currentCamera != old_camera) + { + AimCameraAtPoint(target); + lastSwitch = lastPerformance; + } + else + { + goto Rotate_Camera; + } + } + + // + //--------------------------------------------------- + // Otherwise, rotate the camera as needed and allowed + //--------------------------------------------------- + // + else + { +Rotate_Camera: + RotateCameraToPoint(time_slice, target); + } + + // + //------------------------ + // Set the tranform matrix + //------------------------ + // + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::GoToClosestCamera(const Point3D &point_3D) +{ + Check(this); + currentCamera = cameraManager.FindClosestCamera(point_3D); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::AimCameraAtPoint(const Point3D &point_3D) +{ + Check(this); + Check(currentCamera); + currentCamera->LookAt(&localOrigin, point_3D); + localVelocity.angularMotion = Vector3D::Identity; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::RotateCameraToPoint( + Scalar time_slice, + const Point3D &point_3D + ) +{ + Check(this); + Check(currentCamera); + Check(&point_3D); + + // + //--------------------------------------------------------- + // Calculate the rotation needed to point to the goalEntity + //--------------------------------------------------------- + // + Origin target; + currentCamera->LookAt(&target, point_3D); + YawPitchRoll new_yaw_pitch_roll; + new_yaw_pitch_roll = target.angularPosition; + + Vector3D new_pos(new_yaw_pitch_roll.pitch, new_yaw_pitch_roll.yaw, 0.0f); + YawPitchRoll old_pos_euler; + old_pos_euler = localOrigin.angularPosition; + + Vector3D old_pos(old_pos_euler.pitch, old_pos_euler.yaw, 0.0f); + old_pos.x = Radian::Normalize(old_pos.x); + old_pos.y = Radian::Normalize(old_pos.y); + + // + // new - old position + // + if (new_pos.x-old_pos.x > PI) { + new_pos.x -= TWO_PI; + } + else if (new_pos.x-old_pos.x < -PI) { + new_pos.x += TWO_PI; + } + if (new_pos.y-old_pos.y > PI) { + new_pos.y -= TWO_PI; + } + else if (new_pos.y-old_pos.y < -PI) { + new_pos.y += TWO_PI; + } + Vector3D delta_rot; + delta_rot.Subtract( + new_pos, + old_pos + ); + + // + //------------------- + // Apply Angular Drag + //------------------- + // + Vector3D + drag; + + drag.Multiply( + localVelocity.angularMotion, + angularDragCoefficients + ); + + // + //~~~~~~~~~~~~~~~~~~~~~ + // Apply SpringConstant + //~~~~~~~~~~~~~~~~~~~~~ + // + Vector3D + delta_rot_spring; + delta_rot_spring.Multiply( + delta_rot, + elasticityCoefficient + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Calculate the new angular acceleration + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + localAcceleration.angularMotion.Subtract( + delta_rot_spring, + drag + ); + + Scalar halft_squared = 0.5 *(time_slice * time_slice); + + Vector3D + accel_comp; + accel_comp.Multiply( + localAcceleration.angularMotion, + halft_squared + ); + + // + // velocity * delta time + // + Vector3D + scaled_velocity; + scaled_velocity.Multiply( + localVelocity.angularMotion, + time_slice + ); + + Vector3D + tmp_position; + tmp_position.Add( + scaled_velocity, + accel_comp + ); + Vector3D + clamped_accel; + clamped_accel.Add( + old_pos, + tmp_position + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Apply Acceleration to angular Position + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + YawPitchRoll + new_yawpitchroll(clamped_accel.y, clamped_accel.x, clamped_accel.z); + + LinearMatrix + rot_matrix(LinearMatrix::Identity); + rot_matrix = new_yawpitchroll; + localOrigin.angularPosition = rot_matrix; + + // + // Calc new Velocity + // + Vector3D + scaled_accel; + scaled_accel.Multiply( + localAcceleration.angularMotion, + time_slice + ); + Vector3D + ang_vel; + ang_vel.Add( + localVelocity.angularMotion, + scaled_accel + ); + localVelocity.angularMotion = ang_vel; + + Check_Fpu(); +} + +//############################################################################# +// CameraInstanceManager Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::CreateCameraInstance() +{ + Check(this); + Check(&cameraManager); + currentCamera = cameraManager.CreateCameraInstance(localOrigin); + DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DeleteCameraInstance() +{ + Check(this); + + // + //--------------------------------------------- + // If this is the last camera, don't delete it! + //--------------------------------------------- + // + Check(&cameraManager); + CameraInstance *next_camera = cameraManager.IncrementIterator(); + if (next_camera == currentCamera) + { + return; + } + + currentCamera = cameraManager.DeleteCameraInstance(); + Check(currentCamera); + DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush; + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::IncrementCameraInstance() +{ + Check(this); + Check(&cameraManager); + currentCamera = cameraManager.IncrementIterator(); + Check(currentCamera); + DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush; + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraShip::DecrementCameraInstance() +{ + Check(this); + Check(&cameraManager); + currentCamera = cameraManager.DecrementIterator(); + Check(currentCamera); + DEBUG_STREAM << currentCamera->GetCameraName() << std::endl << std::flush; + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + Check_Fpu(); +} + +//############################################################################# +// Motion Support Functions +// + +//############################################################################# +// Construction and Destruction Support +// +CameraShip::CameraShip( + CameraShip::MakeMessage *creation_message, + CameraShip::SharedData &virtual_data +): + Mover(creation_message, virtual_data) +{ + SetValidFlag(); + if (GetInstance() == ReplicantInstance) + { + return; + } + // + //---------------------------- + // Initialize local variables + //---------------------------- + // + goalEntity = NULL; + localOrigin = Origin::Identity; + focusOffset = Vector3D::Identity; + + // + //------------------------------ + // Initialize attributes + //------------------------------ + // + mapRange = 1000.0; // number of meters across display + mapLinearPosition = NULL; // force nav display to use object's lin. pos + mapAngularPosition = NULL; // force nav display to not turn or tilt + // + //------------------------------ + // Initialize the subsystemArray + //------------------------------ + // + subsystemCount = BasicSubsystemCount; + Verify(!subsystemArray); + subsystemArray = new (Subsystem (*[subsystemCount])); + Register_Pointer(subsystemArray); + subsystemArray[ControlsMapperSubsystem] = NULL; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the camera's viewpoint to the first camera + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + currentCamera = cameraManager.GetCurrent(); + if (!currentCamera) + { + CreateCameraInstance(); + } + Check(currentCamera); + localOrigin = currentCamera->GetLocalOrigin(); + localToWorld = localOrigin; + Point3D local_aim(0.0f, 0.0f, -1.0f); + Point3D world_aim; + world_aim.Multiply(local_aim, localToWorld); + AimCameraAtPoint(world_aim); + localToWorld = localOrigin; + lastSwitch = Now(); + timeOnCamera = 0.0f; + + SetPerformance(&CameraShip::FollowGoal); + SetSimulationState(DefaultState); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraShip* + CameraShip::Make(MakeMessage *creation_message) +{ + return new CameraShip(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraShip::~CameraShip() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraShip::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/CAMSHIP.h b/MUNGA/CAMSHIP.h new file mode 100644 index 0000000..ff313ff --- /dev/null +++ b/MUNGA/CAMSHIP.h @@ -0,0 +1,202 @@ +#pragma once + +#include "mover.h" +#include "cammgr.h" + +class CameraControlsMapper; + +//########################################################################## +//############### CameraShip::DirectionMessage ################# +//########################################################################## + +class CameraShip__DirectionMessage : public Mover::Message +{ +public: + EntityID goalEntity; + Scalar timeOnCamera; + Point3D focusOffset; + + CameraShip__DirectionMessage(Receiver::MessageID message_ID, size_t length, const EntityID& goal_entity, Scalar time_on_camera, const Point3D& focus) : Entity::Message(message_ID, length), goalEntity(goal_entity), timeOnCamera(time_on_camera), focusOffset(focus) {} +}; + +//########################################################################## +//############################# CameraShip ################################ +//########################################################################## + +class CameraShip : public Mover +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging support +// +protected: + static const HandlerEntry MessageHandlerEntries[]; + static MessageHandlerSet MessageHandlers; + +public: + enum + { + DirectionMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef CameraShip__DirectionMessage DirectionMessage; + + void DirectionMessageHandler(DirectionMessage *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum + { + MapRangeAttributeID = Mover::NextAttributeID, + MapLinearPositionAttributeID, + MapAngularPositionAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +public: + Scalar mapRange; + Point3D *mapLinearPosition; // pointer to linear position of object or NULL + Quaternion *mapAngularPosition; // pointer to angular position of object or NULL + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model support +// +public: + enum + { + ControlsMapperSubsystem, + BasicSubsystemCount + }; + void SetMappingSubsystem(CameraControlsMapper *mapper); + + // + // Various States of the CameraShip + // + enum + { + ConfigureCamerasState = Mover::StateCount, + StateCount + }; + + typedef void (CameraShip::*Performance)(Scalar time_slice); + + void SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void FollowGoal(Scalar time_slice); + + void DriveCamera(Scalar time_slice); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Flag Support +// +public: + enum + { + DefaultFlags = Mover::DefaultFlags | NoCollisionVolumeFlag | NoCollisionTestFlag | InitialStasisFlag + }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + static CameraShip* Make(MakeMessage *creation_message); + + CameraShip(MakeMessage *creation_message, SharedData &virtual_data = DefaultData); + ~CameraShip(); + + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public Data and Member Access Functions +// +public: + void SetGoalEntity(Entity *goal_entity) + { + Check(this); + Check(goal_entity); + goalEntity = goal_entity; + } + + Entity* GetGoalEntity() + { + Check(this); + return goalEntity; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local Member Data +// +public: + void GoToClosestCamera(const Point3D &point_3D); + CameraInstance* GetCurrentCamera() + { + Check(this); + return currentCamera; + } + + Time lastSwitch; + Scalar timeOnCamera; + +protected: + CameraInstanceManager cameraManager; + Entity *goalEntity; + CameraInstance *currentCamera; + Point3D focusOffset; + + void MoveCameraShip(CameraInstance *camera_instance); + + void AimCameraAtPoint(const Point3D &point_3D); + + void RotateCameraToPoint(Scalar time_slice, const Point3D &point_3D); + + // + // Camera Motion Support + // +public: + void ResetMotionVariables() + { + Check(this); + localVelocity = Motion::Identity; + localAcceleration = Motion::Identity; + worldLinearVelocity = Vector3D::Identity; + worldLinearAcceleration = Vector3D::Identity; + } + +protected: + void ApplyControlledPanAndTilt(CameraControlsMapper *controls, Scalar time_slice); + void ApplyControlledCameraHeight(CameraControlsMapper *controls); + + void ApplyControlledCameraMotion(CameraControlsMapper *controls, Scalar time_slice); + + // + // Camera Manager Support + // +public: + void CreateCameraInstance(); + void DeleteCameraInstance(); + void IncrementCameraInstance(); + void DecrementCameraInstance(); + +public: + void OutputCameraList() { cameraManager.WriteNotationFile(); } +}; diff --git a/MUNGA/CHAIN.cpp b/MUNGA/CHAIN.cpp new file mode 100644 index 0000000..78e46c1 --- /dev/null +++ b/MUNGA/CHAIN.cpp @@ -0,0 +1,451 @@ +#include "munga.h" +#pragma hdrstop + +#include "chain.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +MemoryBlock *ChainLink::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(ChainLink), CHAINLINK_MEMORYBLOCK_ALLOCATION, CHAINLINK_MEMORYBLOCK_ALLOCATION, "ChainLink"); + return &allocatedMemory; +} + +// +//############################################################################# +// ChainLink +//############################################################################# +// +ChainLink::ChainLink( + Chain *chain, + Plug *plug, + ChainLink *next_link, + ChainLink *prev_link +): + Link(chain, plug) +{ + // + //------------------------- + // Link into existing chain + //------------------------- + // + if ((nextChainLink = next_link) != NULL) + { + Check(nextChainLink); + nextChainLink->prevChainLink = this; + } + if ((prevChainLink = prev_link) != NULL) + { + Check(prevChainLink); + prevChainLink->nextChainLink = this; + } +} + +// +//############################################################################# +// ~ChainLink +//############################################################################# +// +ChainLink::~ChainLink() +{ + Chain *chain = Cast_Object(Chain*, socket); + + // + //-------------------------------------- + // Remove this link from the linked list + //-------------------------------------- + // + if (prevChainLink != NULL) + { + Check(prevChainLink); + prevChainLink->nextChainLink = nextChainLink; + } + else + { + Check(chain); + chain->head = nextChainLink; + } + if (nextChainLink != NULL) + { + Check(nextChainLink); + nextChainLink->prevChainLink = prevChainLink; + } + else + { + Check(chain); + chain->tail = prevChainLink; + } + prevChainLink = nextChainLink = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (chain->GetReleaseNode() != NULL) + { + Check(chain->GetReleaseNode()); + chain->GetReleaseNode()->ReleaseLinkHandler(chain, plug); + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + ChainLink::TestInstance() const +{ + Link::TestInstance(); + + if (prevChainLink != NULL) + { + Check_Signature(prevChainLink); + } + if (nextChainLink != NULL) + { + Check_Signature(nextChainLink); + } + return( True ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Chain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Chain +//############################################################################# +// +Chain::Chain(Node *node): + Socket(node) +{ + head = NULL; + tail = NULL; +} + +// +//############################################################################# +// ~Chain +//############################################################################# +// +Chain::~Chain() +{ + SetReleaseNode(NULL); + while (head != NULL) + { + Unregister_Object(head); + delete head; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Chain::TestInstance() const +{ + Socket::TestInstance(); + + if (head != NULL) + { + Check(head); + } + if (tail != NULL) + { + Check(tail); + } + return True; +} + +// +//############################################################################# +// AddImplementation +//############################################################################# +// +void + Chain::AddImplementation(Plug *plug) +{ + Check(this); + + tail = new ChainLink(this, plug, NULL, tail); + Register_Object(tail); + + if (head == NULL) + { + head = tail; + } +} + +// +//############################################################################# +// InsertChainLink +//############################################################################# +// +ChainLink* + Chain::InsertChainLink( + Plug *plug, + ChainLink *current_link + ) +{ + Check(this); + Check(plug); + Check(current_link); + + ChainLink *new_link = + new ChainLink( + this, + plug, + current_link, + current_link->prevChainLink + ); + Register_Object(new_link); + + Check(head); + if (head == current_link) + { + head = new_link; + } + return new_link; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ChainIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// ChainIterator +//############################################################################# +// +ChainIterator::ChainIterator(Chain *chain): + SocketIterator(chain) +{ + Check(chain); + currentLink = chain->head; +} + +ChainIterator::ChainIterator(const ChainIterator &iterator): + SocketIterator(Cast_Object(Chain*, iterator.socket)) +{ + Check(&iterator); + currentLink = iterator.currentLink; +} + +ChainIterator::~ChainIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + ChainIterator::TestInstance() const +{ + SocketIterator::TestInstance(); + + if (currentLink != NULL) + { + Check( currentLink ); + } + return(True); +} + +// +//########################################################################### +// First +//########################################################################### +// +void + ChainIterator::First() +{ + currentLink = Cast_Object(Chain*, socket)->head; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + ChainIterator::Last() +{ + currentLink = Cast_Object(Chain*, socket)->tail; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + ChainIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->nextChainLink; +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + ChainIterator::Previous() +{ + Check( currentLink ); + currentLink = currentLink->prevChainLink; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void* + ChainIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->nextChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void* + ChainIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->prevChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + ChainIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + return currentLink->plug; + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + ChainIterator::GetSize() +{ + + ChainLink *link; + CollectionSize count; + + count = 0; + + for ( + link = Cast_Object(Chain*, socket)->head; + link != NULL; + link = link->nextChainLink + ) { + Check(link); + count++; + } + return count; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void* + ChainIterator::GetNthImplementation(CollectionSize index) +{ + ChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(Chain*, socket)->head; + link != NULL; + link = link->nextChainLink + ) { + Check(link); + if (count == index) { + currentLink = link; + return currentLink->plug; + } + count++; + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + ChainIterator::Remove() +{ + ChainLink *oldLink = currentLink; + + Check(currentLink); + currentLink = currentLink->nextChainLink; + + Unregister_Object(oldLink); + delete oldLink ; +} + +// +//########################################################################### +// InsertImplementation +//########################################################################### +// +void + ChainIterator::InsertImplementation(Plug *plug) +{ + currentLink = + Cast_Object(Chain*, socket)->InsertChainLink(plug, currentLink); + Check(currentLink); +} + +#ifdef TEST_CLASS +# include "chain.tcp" +#endif diff --git a/MUNGA/CHAIN.h b/MUNGA/CHAIN.h new file mode 100644 index 0000000..2f6cdb7 --- /dev/null +++ b/MUNGA/CHAIN.h @@ -0,0 +1,157 @@ +#pragma once + +#include "node.h" +#include "memblock.h" + +class Chain; +class ChainIterator; + +#define CHAINLINK_MEMORYBLOCK_ALLOCATION (100) + +class ChainLink : public Link +{ + friend class Chain; + friend class ChainIterator; + +public: + ~ChainLink(); + Logical TestInstance() const; + +private: + ChainLink(Chain *chain, Plug *plug, ChainLink *nextChainLink, ChainLink *prevChainLink); + + ChainLink *nextChainLink; + ChainLink *prevChainLink; + +private: + static MemoryBlock* GetAllocatedMemory(); + + void *operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } +}; + +class Chain : public Socket +{ + friend class ChainLink; + friend class ChainIterator; + +public: + Chain(Node *node); + ~Chain(); + + Logical TestInstance() const; + static Logical TestClass(); + static Logical ProfileClass(); + +protected: + void AddImplementation(Plug *plug); + +private: + ChainLink *InsertChainLink(Plug *plug, ChainLink *current_link); + + ChainLink *head, *tail; +}; + +template class ChainOf : public Chain +{ +public: + ChainOf(Node *node); + ~ChainOf(); + + void Add(T plug) + { + Chain::AddImplementation(Cast_Object(Plug*, plug)); + } +}; + +template ChainOf::ChainOf(Node *node) : Chain(node) +{ +} + +template ChainOf::~ChainOf() +{ +} + +class ChainIterator : public SocketIterator +{ +public: + ChainIterator(Chain *chain); + ChainIterator(const ChainIterator &iterator); + ~ChainIterator(); + + Logical TestInstance() const; + + void First(); + void Last(); + void Next(); + void Previous(); + CollectionSize GetSize(); + void Remove(); + +protected: + void *ReadAndNextImplementation(); + void *ReadAndPreviousImplementation(); + void *GetCurrentImplementation(); + void *GetNthImplementation(CollectionSize index); + void InsertImplementation(Plug*); + + ChainLink *currentLink; +}; + +template class ChainIteratorOf : public ChainIterator +{ +public: + ChainIteratorOf(ChainOf *chain); + ChainIteratorOf(ChainOf &chain); + ChainIteratorOf(const ChainIteratorOf &iterator); + ~ChainIteratorOf(); + + T ReadAndNext() { return (T)ReadAndNextImplementation(); } + T ReadAndPrevious() { return (T)ReadAndPreviousImplementation(); } + T GetCurrent() { return (T)GetCurrentImplementation(); } + T GetNth(CollectionSize index) { return (T)GetNthImplementation(index); } + void Insert(T plug) { InsertImplementation(Cast_Object(Plug*, plug)); } + + ChainIteratorOf& Begin() { return (ChainIteratorOf&)BeginImplementation(); } + ChainIteratorOf& End() { return (ChainIteratorOf&)EndImplementation(); } + ChainIteratorOf& Forward() { return (ChainIteratorOf&)ForwardImplementation(); } + ChainIteratorOf& Backward() { return (ChainIteratorOf&)BackwardImplementation(); } + +#if 0 + Logical operator!() { return currentLink == NULL; } + operator T*() { return GetCurrent(); } + T* operator->() { return GetCurrent(); } + T& operator*() { return *GetCurrent(); } + + ChainIteratorOf& operator++() + { + Next(); + return *this; + } + + ChainIteratorOf& operator--() + { + Previous(); + return *this; + } + + T* operator++(int) { return ReadAndNext(); } + T* operator--(int) { return ReadAndPrevious(); } +#endif +}; + +template ChainIteratorOf::ChainIteratorOf(ChainOf *chain) : ChainIterator(chain) +{ +} + +template ChainIteratorOf::ChainIteratorOf(ChainOf &chain) : ChainIterator(&chain) +{ +} + +template ChainIteratorOf::ChainIteratorOf(const ChainIteratorOf &iterator) : ChainIterator(iterator) +{ +} + +template ChainIteratorOf::~ChainIteratorOf() +{ +} \ No newline at end of file diff --git a/MUNGA/CMPNNT.cpp b/MUNGA/CMPNNT.cpp new file mode 100644 index 0000000..c870c6b --- /dev/null +++ b/MUNGA/CMPNNT.cpp @@ -0,0 +1,59 @@ +#include "munga.h" +#pragma hdrstop + +#include "cmpnnt.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +// Shared Data Support +// +Derivation* Component::GetClassDerivations() +{ + static Derivation classDerivations(Receiver::GetClassDerivations(), "Component"); + return &classDerivations; +} + +Component::SharedData Component::DefaultData(Component::GetClassDerivations(), Component::GetMessageHandlers()); + +// +//############################################################################# +//############################################################################# +// +Component::Component(ClassID class_id, SharedData &shared_data) : Receiver(class_id, shared_data) +{ +} + +// +//############################################################################# +//############################################################################# +// +Component::Component(PlugStream *stream, SharedData &shared_data) : Receiver(stream, shared_data) +{ +} + +// +//############################################################################# +//############################################################################# +// +Component::~Component() +{ +} + +// +//############################################################################# +//############################################################################# +// +void Component::Execute() +{ + Fail("Component::Execute - Should never reach here"); +} + +// +//############################################################################# +//############################################################################# +// +Logical Component::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/CMPNNT.h b/MUNGA/CMPNNT.h new file mode 100644 index 0000000..e760bd1 --- /dev/null +++ b/MUNGA/CMPNNT.h @@ -0,0 +1,22 @@ +#pragma once + +#include "receiver.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Component ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Component : public Receiver +{ +public: + ~Component(); + + virtual void Execute(); + + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + + Logical TestInstance() const; + +protected: + Component(ClassID class_id = TrivialComponentClassID, SharedData &shared_data = DefaultData); + Component(PlugStream *stream, SharedData &shared_data = DefaultData); +}; \ No newline at end of file diff --git a/MUNGA/COLLASST.cpp b/MUNGA/COLLASST.cpp new file mode 100644 index 0000000..a4c46cc --- /dev/null +++ b/MUNGA/COLLASST.cpp @@ -0,0 +1,367 @@ +#include "munga.h" +#pragma hdrstop + +#include "collasst.h" +#include "mover.h" +#include "app.h" +#include "interest.h" + +// +//############################################################################# +// Make +//############################################################################# +// +CollisionAssistant* + CollisionAssistant::Make(Mover *mover) +{ + Check(mover); + + // + // Create the collision assistant + // + CollisionAssistant *collision_assistant; + + collision_assistant = new CollisionAssistant(mover->GetInterestZoneID()); + Check(collision_assistant); + return collision_assistant; +} + +// +//############################################################################# +// CollisionAssistant +//############################################################################# +// +CollisionAssistant::CollisionAssistant(InterestZoneID interest_zone_ID): + collisionOriginSocket(NULL) +{ + Verify(interest_zone_ID != NullInterestZoneID); + currentInterestZoneID = interest_zone_ID; + LinkToInterestZone(interest_zone_ID); +} + +// +//############################################################################# +// ~CollisionAssistant +//############################################################################# +// +CollisionAssistant::~CollisionAssistant() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + CollisionAssistant::TestInstance() const +{ + Node::TestInstance(); + Verify(currentInterestZoneID != NullInterestZoneID); + Check(&collisionOriginSocket); + return True; +} + +// +//############################################################################# +// Update +//############################################################################# +// +void + CollisionAssistant::Update(InterestZoneID interest_zone_ID) +{ + Check(this); + Verify(interest_zone_ID != NullInterestZoneID); + + if (interest_zone_ID == currentInterestZoneID) + return; + currentInterestZoneID = interest_zone_ID; + + // + // Remove current collision origin and link to new one + // + if (collisionOriginSocket.GetCurrent() != NULL) + { + collisionOriginSocket.Remove(); + } + LinkToInterestZone(interest_zone_ID); +} + +// +//############################################################################# +// LinkToInterestZone +//############################################################################# +// +void + CollisionAssistant::LinkToInterestZone(InterestZoneID interest_zone_ID) +{ + Check(this); + Verify(interest_zone_ID != NullInterestZoneID); + + // + //-------------------------------------------------------------------------- + // Does the interest zone have a collision origin? + //-------------------------------------------------------------------------- + // + InterestZone *interest_zone; + CollisionOrigin *collision_origin; + + Check(application); + Check(application->GetInterestManager()); + interest_zone = + application->GetInterestManager()->GetInterestZone(interest_zone_ID); + Check(interest_zone); + + collision_origin = interest_zone->GetCollisionOrigin(); + if (collision_origin == NULL) + { + // + // It does not, so create one + // + collision_origin = new CollisionOrigin(interest_zone_ID); + Register_Object(collision_origin); + interest_zone->AdoptCollisionOrigin(collision_origin); + + application->GetInterestManager()->AdoptInterestOrigin(collision_origin); + } + Check(collision_origin); + + // + // link to the collision origin + // + collisionOriginSocket.Add(collision_origin); +} + +//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~ + +CollisionAssistant__MovingEntityIterator:: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ): + CollisionOrigin__MovingEntityIterator( + collision_assistant->collisionOriginSocket.GetCurrent() + ) +{ +} + +CollisionAssistant__MovingEntityIterator:: + ~CollisionAssistant__MovingEntityIterator() +{ +} + +#if 0 +// +//############################################################################# +// Make +//############################################################################# +// +CollisionAssistant* + CollisionAssistant::Make(Mover *mover) +{ + Check(mover); + + // + //----------------------------------------------------------------------- + // Create the collision assistant + //----------------------------------------------------------------------- + // + CollisionAssistant *collision_assistant; + + Check(application); + collision_assistant = new CollisionAssistant( + application->GetApplicationLoopFrameRate() + ); + Check(collision_assistant); + + // + //----------------------------------------------------------------------- + // Prime the collision assistant + //----------------------------------------------------------------------- + // + collision_assistant->LinkToMover(mover); + collision_assistant->LoadMission(NULL); // JM - This should work... + + return collision_assistant; +} + +// +//############################################################################# +// CollisionAssistant +//############################################################################# +// +CollisionAssistant::CollisionAssistant(RendererRate render_rate): + Renderer( + render_rate, + MaxRendererComplexity, + DefaultRendererPriority, + CollisionInterestType, + DefaultInterestDepth, + CollisionAssistantClassID + ), + movingEntitySocket(NULL) +{ +} + +// +//############################################################################# +// ~CollisionAssistant +//############################################################################# +// +CollisionAssistant::~CollisionAssistant() +{ + Suspend(); + UnlinkFromEntity(); + Shutdown(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + CollisionAssistant::TestInstance() const +{ + Renderer::TestInstance(); + Check(&movingEntitySocket); + return True; +} + +// +//############################################################################# +// LinkToEntity +//############################################################################# +// +void + CollisionAssistant::LinkToMover(Mover *mover) +{ + Check(this); + Check(mover); + + // + // Call inherited method + // + Renderer::LinkToEntity(mover); + + // + //----------------------------------------------------------------- + // Tell the entity that is collisionable here ... + //----------------------------------------------------------------- + // +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + CollisionAssistant::NotifyOfNewInterestingEntity( + Entity *interesting_entity + ) +{ + Check(this); + Check(interesting_entity); + + // + //------------------------------------------------------------------------- + // Make sure that we don't check against ourself our against something that + // doesn't move + //------------------------------------------------------------------------- + // + if ( + interesting_entity != GetLinkedEntity() + && interesting_entity->IsDynamic() + ) + { + + // + //------------------------------------------------------------- + // If it is a mover and tangible, or a door, add it to our list + //------------------------------------------------------------- + // + if (interesting_entity->IsDerivedFrom(Mover::GetClassDerivations())) + { + Mover *mover = Cast_Object(Mover*, interesting_entity); + if (mover->IsTangible()) + { + goto Add_Entity; + } + } + else if (interesting_entity->IsDerivedFrom(DoorFrame::GetClassDerivations())) + { +Add_Entity: + movingEntitySocket.Add(interesting_entity); + } + } +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntity +//############################################################################# +// +void + CollisionAssistant::NotifyOfBecomingUninterestingEntity( + Entity *uninteresting_entity + ) +{ + // + // HACK - ECH The following may not be a legitimate assertion + // + #if DEBUG_LEVEL>0 && 0 + { + SChainIteratorOf iterator(&movingEntitySocket); + Verify(iterator.IsPlugMember(uninteresting_entity) == True); + } + #endif + + // + // Remove from socket + // + PlugIterator iterator(uninteresting_entity); + + iterator.RemoveSocket(&movingEntitySocket); +} + +// +//############################################################################# +// GetCollisionRoot +//############################################################################# +// +BoxedSolidTree* + CollisionAssistant::GetCollisionRoot() +{ + Check(GetInterestOrigin()); + Check(GetInterestOrigin()->GetInterestArena()); + return GetInterestOrigin()->GetInterestArena()->GetCollisionRoot(); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +void + CollisionAssistant::ExecuteImplementation( + RendererComplexity, + InterestOrigin::InterestingEntityIterator* + ) +{ +} + +//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +CollisionAssistant__MovingEntityIterator:: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ): + SChainIteratorOf(collision_assistant->movingEntitySocket) +{ +} + +CollisionAssistant__MovingEntityIterator:: + ~CollisionAssistant__MovingEntityIterator() +{ +} +#endif diff --git a/MUNGA/COLLASST.h b/MUNGA/COLLASST.h new file mode 100644 index 0000000..9a7a1e5 --- /dev/null +++ b/MUNGA/COLLASST.h @@ -0,0 +1,180 @@ +#pragma once + +#include "node.h" +#include "slot.h" +#include "collorgn.h" + +//########################################################################## +//####################### CollisionAssistant ######################### +//########################################################################## + +class Mover; + +class CollisionAssistant: +public Node +{ + friend class CollisionAssistant__MovingEntityIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public Types +// +public: + typedef CollisionAssistant__MovingEntityIterator + MovingEntityIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + CollisionAssistant(InterestZoneID interest_zone_ID); + ~CollisionAssistant(); + + Logical + TestInstance() const; + + static CollisionAssistant* + Make(Mover *mover); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Update +// +public: +void + Update(InterestZoneID interest_zone_ID); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private +// +private: + void + LinkToInterestZone(InterestZoneID interest_zone_ID); + + InterestZoneID + currentInterestZoneID; + SlotOf + collisionOriginSocket; +}; + +//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~ + +class CollisionAssistant__MovingEntityIterator: + public CollisionOrigin__MovingEntityIterator +{ +public: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ); + ~CollisionAssistant__MovingEntityIterator(); +}; + +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ CollisionAssistant ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class CollisionAssistant: + public Renderer +{ + friend class CollisionAssistant__MovingEntityIterator; + +public: + // + //-------------------------------------------------------------------- + // Public Types + //-------------------------------------------------------------------- + // + typedef CollisionAssistant__MovingEntityIterator + MovingEntityIterator; + + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + CollisionAssistant(RendererRate render_rate); + ~CollisionAssistant(); + + Logical + TestInstance() const; + + static CollisionAssistant* + Make(Mover *mover); + + // + //-------------------------------------------------------------------- + // LinkToEntity + //-------------------------------------------------------------------- + // + void + LinkToMover(Mover *mover); + + // + //-------------------------------------------------------------------- + // NotifyOfNewInterestingEntity + //-------------------------------------------------------------------- + // + void + NotifyOfNewInterestingEntity(Entity *interesting_entity); + + // + //-------------------------------------------------------------------- + // NotifyOfBecomingUninterestingEntity + //-------------------------------------------------------------------- + // + void + NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity); + + // + //-------------------------------------------------------------------- + // GetCollisionRoot + //-------------------------------------------------------------------- + // + BoxedSolidTree* + GetCollisionRoot(); + +protected: + // + //-------------------------------------------------------------------- + // ExecuteImplementation + //-------------------------------------------------------------------- + // + void + ExecuteImplementation( + RendererComplexity complexity_update, + InterestOrigin::InterestingEntityIterator *iterator + ); + +private: + // + //-------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------- + // + void + LoadMissionImplementation(Mission*) {} + void + ShutdownImplementation() {} + void + SuspendImplementation() {} + void + ResumeImplementation() {} + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + SChainOf + movingEntitySocket; +}; + +//~~~~~~~~~~~~~~~~~ CollisionAssistant__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class CollisionAssistant__MovingEntityIterator: + public SChainIteratorOf +{ +public: + CollisionAssistant__MovingEntityIterator( + CollisionAssistant *collision_assistant + ); + ~CollisionAssistant__MovingEntityIterator(); +}; +#endif diff --git a/MUNGA/COLLORGN.cpp b/MUNGA/COLLORGN.cpp new file mode 100644 index 0000000..ad65412 --- /dev/null +++ b/MUNGA/COLLORGN.cpp @@ -0,0 +1,144 @@ +#include "munga.h" +#pragma hdrstop + +#include "collorgn.h" +#include "mover.h" +#include "doorfram.h" + +// +//############################################################################# +// CollisionOrigin +//############################################################################# +// +CollisionOrigin::CollisionOrigin(InterestZoneID interest_zone_ID): + InterestOrigin( + interest_zone_ID, + CollisionInterestType, + DefaultInterestDepth + ), + movingEntitySocket(NULL) +{ +} + +// +//############################################################################# +// ~CollisionOrigin +//############################################################################# +// +CollisionOrigin::~CollisionOrigin() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + CollisionOrigin::TestInstance() const +{ + InterestOrigin::TestInstance(); + Check(&movingEntitySocket); + return True; +} + +// +//############################################################################# +// AddInterestingEntity +//############################################################################# +// +void + CollisionOrigin::AddInterestingEntity(Entity *interesting_entity) +{ + Check(this); + Check(interesting_entity); + + // + //-------------------------------------------------------------------------- + // Make sure that we don't check against something that doesn't move + //-------------------------------------------------------------------------- + // + if (interesting_entity->IsDynamic()) + { + // + //----------------------------------------------------------------------- + // If it is a mover and tangible, or a door, add it to our list + //----------------------------------------------------------------------- + // + if (interesting_entity->IsDerivedFrom(*Mover::GetClassDerivations())) + { + Mover *mover = Cast_Object(Mover*, interesting_entity); + if (mover->IsCollisionTestable()) + { + movingEntitySocket.Add(interesting_entity); + } + } + else if (interesting_entity->IsDerivedFrom(*DoorFrame::GetClassDerivations())) + { + movingEntitySocket.Add(interesting_entity); + } + } +} + +// +//############################################################################# +// RemoveUninterestingEntity +//############################################################################# +// +void + CollisionOrigin::RemoveUninterestingEntity(Entity *uninteresting_entity) +{ + Check(this); + Check(uninteresting_entity); + + // + // HACK - ECH The following may not be a legitimate assertion + // + #if DEBUG_LEVEL>0 && 0 + { + SChainIteratorOf iterator(&movingEntitySocket); + Verify(iterator.IsPlugMember(uninteresting_entity) == True); + } + #endif + + // + // Remove from socket + // + PlugIterator iterator(uninteresting_entity); + + Check(&iterator); + iterator.RemoveSocket(&movingEntitySocket); +} + +// +//############################################################################# +// RemoveUninterestingEntities +//############################################################################# +// +void + CollisionOrigin::RemoveUninterestingEntities() +{ + Check(this); + + SChainIteratorOf iterator(&movingEntitySocket); + + Check(&iterator); + while (iterator.GetCurrent() != NULL) + { + Check(iterator.GetCurrent()); + iterator.Remove(); + } +} + +//~~~~~~~~~~~~~~~~~~~ CollisionOrigin__MovingEntityIterator ~~~~~~~~~~~~~~~~~~~ + +CollisionOrigin__MovingEntityIterator::CollisionOrigin__MovingEntityIterator( + CollisionOrigin *collision_origin +): + SChainIteratorOf(collision_origin->movingEntitySocket) +{ +} + +CollisionOrigin__MovingEntityIterator::~CollisionOrigin__MovingEntityIterator() +{ +} diff --git a/MUNGA/COLLORGN.h b/MUNGA/COLLORGN.h new file mode 100644 index 0000000..8ee1c28 --- /dev/null +++ b/MUNGA/COLLORGN.h @@ -0,0 +1,50 @@ +#pragma once + +#include "interest.h" + +//########################################################################## +//###################### CollisionOrigin ############################# +//########################################################################## + +class CollisionOrigin : public InterestOrigin +{ + friend class CollisionOrigin__MovingEntityIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest Manager support +// +public: + typedef CollisionOrigin__MovingEntityIterator MovingEntityIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + CollisionOrigin(InterestZoneID interest_zone_ID); + ~CollisionOrigin(); + + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest Manager support +// +protected: + void AddInterestingEntity(Entity *interesting_entity); + void RemoveUninterestingEntity(Entity *uninteresting_entity); + void RemoveUninterestingEntities(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + SChainOf movingEntitySocket; +}; + +//~~~~~~~~~~~~~~~~~~~~ CollisionOrigin__MovingEntityIterator ~~~~~~~~~~~~~~~ + +class CollisionOrigin__MovingEntityIterator : public SChainIteratorOf +{ +public: + CollisionOrigin__MovingEntityIterator(CollisionOrigin *collision_origin); + ~CollisionOrigin__MovingEntityIterator(); +}; diff --git a/MUNGA/COLOR.cpp b/MUNGA/COLOR.cpp new file mode 100644 index 0000000..58777e6 --- /dev/null +++ b/MUNGA/COLOR.cpp @@ -0,0 +1,68 @@ +#include "munga.h" +#pragma hdrstop + +#include "color.h" +#include "cstr.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +void Convert_From_Ascii(const char *str, RGBColor *color) +{ + Check_Pointer(str); + Check_Signature(color); + + CString parse_string(str); + + Check_Pointer(parse_string.GetNthToken(0)); + color->Red = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + color->Green = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + color->Blue = atof(parse_string.GetNthToken(2)); + + Check(color); +} + +// +//########################################################################### +//########################################################################### +// +Logical RGBColor::TestInstance() const +{ + return True; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +void Convert_From_Ascii(const char *str, RGBAColor *color) +{ + Check_Pointer(str); + Check_Signature(color); + + CString parse_string(str); + + Check_Pointer(parse_string.GetNthToken(0)); + color->Red = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + color->Green = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + color->Blue = atof(parse_string.GetNthToken(2)); + + Check_Pointer(parse_string.GetNthToken(3)); + color->Alpha = atof(parse_string.GetNthToken(3)); + + Check(color); +} diff --git a/MUNGA/COLOR.h b/MUNGA/COLOR.h new file mode 100644 index 0000000..110dd42 --- /dev/null +++ b/MUNGA/COLOR.h @@ -0,0 +1,92 @@ +#pragma once + +#include "memstrm.h" +#include "scalar.h" + +//########################################################################## +//############## RGBColor ############################################ +//########################################################################## + +class RGBColor +{ + friend class RGBAColor; + +public: + Scalar Red, Green, Blue; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile RGBColor *p) + { + return False; + } + #endif + + + RGBColor() + { + Red = Green = Blue = -1.0f; + } + + RGBColor(Scalar r, Scalar g, Scalar b) + { + Red = r; + Green = g; + Blue = b; + } + + Logical operator==(const RGBColor &a_RGBColor) const + { + return !memcmp(this, &a_RGBColor, sizeof(RGBColor)); + } + Logical operator!=(const RGBColor &a_RGBColor) const + { + return memcmp(this, &a_RGBColor, sizeof(RGBColor)); + } + + Logical TestInstance() const; + + RGBColor operator+(const RGBColor &a_RGBColor) const { return RGBColor(Min(this->Red + a_RGBColor.Red, 1.0), Min(this->Green + a_RGBColor.Green, 1.0), Min(this->Blue + a_RGBColor.Blue, 1.0)); } + Scalar Infrared() const { return 0.3 * this->Red + 0.5 * this->Green + 0.2 * this->Blue; } + +// +// Support functions +// + friend std::ostream& operator<<(std::ostream& stream, const RGBColor& C); +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void Convert_From_Ascii(const char *str, RGBColor *color); + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, RGBColor *output) { return stream->ReadBytes(output, sizeof(*output)); } +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const RGBColor *input) { return stream->WriteBytes(input, sizeof(*input)); } + +//########################################################################## +//############## RGBAColor ########################################### +//########################################################################## + +class RGBAColor : public RGBColor +{ +public: + Scalar Alpha; + + RGBAColor() : RGBColor() { Alpha = -1.0f; } + + RGBAColor(Scalar r, Scalar g, Scalar b, Scalar a) : RGBColor(r, g, b) { Alpha = a; } + + Logical operator==(const RGBAColor &a_RGBAColor) const { return !memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); } + Logical operator!=(const RGBAColor &a_RGBAColor) const { return memcmp(this, &a_RGBAColor, sizeof(RGBAColor)); } + +// +// Support functions +// + friend std::ostream& operator<<(std::ostream& stream, const RGBAColor& c); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RGBAColor functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void Convert_From_Ascii(const char *str, RGBAColor *color); + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, RGBAColor *output) { return stream->ReadBytes(output, sizeof(*output)); } +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const RGBAColor *input) { return stream->WriteBytes(input, sizeof(*input)); } \ No newline at end of file diff --git a/MUNGA/CONFIG.h b/MUNGA/CONFIG.h new file mode 100644 index 0000000..6f857fb --- /dev/null +++ b/MUNGA/CONFIG.h @@ -0,0 +1,151 @@ +#pragma once + +#if DEBUG_LEVEL >= 3 + #undef USE_ACTIVE_PROFILE // Disables trace activity + #define USE_TIME_ANALYSIS // Enables trace time statistics + #undef USE_TRACE_LOG // Disables logging functions + #define USE_FPU_ANALYSIS // Enables entity FPU checks + #define USE_MEMORY_ANALYSIS // Enables heap statistics + #undef USE_EVENT_STATISTICS // Disables event statistics +#elif DEBUG_LEVEL == 2 + #undef USE_ACTIVE_PROFILE // Disables trace activity + #define USE_TIME_ANALYSIS // Enables trace time statistics + #undef USE_TRACE_LOG // Disables logging functions + #define USE_FPU_ANALYSIS // Enables entity FPU checks + #define USE_MEMORY_ANALYSIS // Enables heap statistics + #undef USE_EVENT_STATISTICS // Disables event statistics +#elif DEBUG_LEVEL == 1 + #undef USE_ACTIVE_PROFILE // Disables trace activity + #define USE_TIME_ANALYSIS // Enables trace time statistics + #undef USE_TRACE_LOG // Disables logging functions + #define USE_FPU_ANALYSIS // Enables entity FPU checks + #define USE_MEMORY_ANALYSIS // Enables heap statistics + #undef USE_EVENT_STATISTICS // Disables event statistics +#elif DEBUG_LEVEL == 0 + #if defined(LAB_ONLY) + #undef USE_ACTIVE_PROFILE // Disables trace activity + #define USE_TIME_ANALYSIS // Enables trace time statistics + #define USE_TRACE_LOG // Enables logging functions + #undef USE_FPU_ANALYSIS // Disables entity FPU checks + #undef USE_MEMORY_ANALYSIS // Disables heap statistics + #define USE_EVENT_STATISTICS // Enables event statistics + #else + #undef USE_ACTIVE_PROFILE // Disables trace activity + #undef USE_TIME_ANALYSIS // Disables trace time statistics + #undef USE_TRACE_LOG // Disables logging functions + #undef USE_FPU_ANALYSIS // Disables entity FPU checks + #undef USE_MEMORY_ANALYSIS // Disables heap statistics + #undef USE_EVENT_STATISTICS // Disables event statistics + #endif +#endif + +#if defined(USE_TIME_ANALYSIS) || defined(USE_ACTIVE_PROFILE) || defined(USE_TRACE_LOG) + #define TRACE_ON +#endif + +// +// Traces are expensive, release build should not have them +// +#if defined(TRACE_ON) && defined(LAB_ONLY) + + #define TRACE_FOREGROUND_PROCESSING +// #define TRACE_RENDERER_MANAGER +// #define TRACE_PROCESS_EVENT + #define TRACE_EVENT_COUNT + +// +// Update Manager Group +// + +// #define TRACE_UPDATE_MANAGER +// #define TRACE_UPDATE_MASTER +// #define TRACE_UPDATE_REPLICANTS + +// +// Networking Group +// + +// #define TRACE_SEND_PACKET +// #define TRACE_ROUTE_PACKET +// #define TRACE_LOST_DATA +// #define TRACE_SEND_BUFFER +// +// Video Renderer group +// To see all the video renderer traces seperately, DO NOT define USE_ONE_VIDEO_TRACE +// To see all of the video renderer on the same trace, enable the following: +// +// USE_ONE_VIDEO_TRACE +// TRACE_VIDEO_RENDERER +// TRACE_VIDEO_BECOME_INTERESTING +// TRACE_VIDEO_BECOME_UNINTERESTING +// TRACE_VIDEO_RENDERER_FRAME_DONE +// +// The time used by the above four traces will all appear on the video renderer +// trace together. This configuration should not cause any buzzing of traces and +// should capture 100% of the video renderer's activity. +// Other video renderer traces may be enabled but will appear seperately +// +// CAUTION: Depending on the setup, TRACE_VIDEO_RENDERABLES can buzz, severly +// lengthening the video renderer profile times. Use carefully. +// +// #define USE_ONE_VIDEO_TRACE +// #define TRACE_VIDEO_RENDERER +// #define TRACE_VIDEO_BECOME_INTERESTING +// #define TRACE_VIDEO_BECOME_UNINTERESTING +// #define TRACE_VIDEO_RENDERER_FRAME_DONE + +// #define TRACE_VIDEO_CULL_SETUP +// #define TRACE_VIDEO_VEHICLE_RENDERABLES +// #define TRACE_VIDEO_ALL_RENDERABLES +// #define TRACE_VIDEO_MECH_CULL_RENDERABLE +// #define TRACE_VIDEO_BATCH_FLUSH +// #define TRACE_VIDEO_LOAD_OBJECT +// #define TRACE_VIDEO_PICKPOINT +// #define TRACE_VIDEO_RENDERABLES +// #define TRACE_VIDEO_CONSTRUCT_ROOT // construct the root of +// #define TRACE_VIDEO_FIRST_FRAME_DONE // obsolete soon + +// +// Audio renderer group +// + +// #define TRACE_AUDIO_RENDERER +// #define TRACE_AUDIO_RENDERER_MIDI +// #define TRACE_AUDIO_RENDERER_CREATE_OBJECTS +// #define TRACE_AUDIO_RENDERER_DESTROY_OBJECTS +// #define TRACE_AUDIO_RENDERER_START_HANDLER +// #define TRACE_AUDIO_RENDERER_STOP_HANDLER +// #define TRACE_AUDIO_RENDERER_EXECUTE +// #define TRACE_AUDIO_RENDERER_RUNNING_SOURCES +// #define TRACE_AUDIO_RENDERER_RUNNING_SORT +// #define TRACE_AUDIO_RENDERER_CALCULATE_MIX +// #define TRACE_AUDIO_RENDERER_EXECUTE_SOURCES +// #define TRACE_AUDIO_RENDERER_DORMANT_SOURCES + +// +// Gauge renderer group +// + +// #define TRACE_GAUGE_RENDERER +// #define TRACE_SCREEN_COPY + +// +// Other leftovers, these are probably obsolete, if you know ones that are, kill +// kill them off as appropriate. +// + + #if 0 + #define TRACE_COMPLETE_CYCLES + #define TRACE_DEATH_ROW + + #define TRACE_EXECUTE_ENTITY + #define TRACE_PERFORM_ENTITY + #define TRACE_PERFORM_SUBSYSTEMS + #define TRACE_EXECUTE_WATCHERS + + #define TRACE_RIO_RECEIVE_PACKET + #define TRACE_RIO_SEND_PACKET + #define TRACE_CHECK_BUFFERS + #define TRACE_CALL_NETNUB + #endif +#endif diff --git a/MUNGA/CONSOLE.cpp b/MUNGA/CONSOLE.cpp new file mode 100644 index 0000000..44396b6 --- /dev/null +++ b/MUNGA/CONSOLE.cpp @@ -0,0 +1,85 @@ +#include "munga.h" +#pragma hdrstop + +#include "console.h" + +//~~~~~~~~~~~~~~~~~~ ConsoleApplicationReadyToRunMessage ~~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationReadyToRunMessage:: + ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID): + NetworkClient::Message( + ConsoleApplicationReadyToRunMessageID, + sizeof(ConsoleApplicationReadyToRunMessage) + ) +{ + readyToRunHostID = ready_to_run_host_ID; +} + +//~~~~~~~~~~~~~~~~ ConsoleApplicationStateResponseMessage ~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationStateResponseMessage::ConsoleApplicationStateResponseMessage( + HostID responding_host_ID, + Enumeration application_state, + Enumeration application_type +): + NetworkClient::Message( + ConsoleApplicationStateResponseMessageID, + sizeof(ConsoleApplicationStateResponseMessage) + ) +{ + respondingHostID = responding_host_ID; + applicationState = application_state; + application = application_type; +} + +//~~~~~~~~~~~~~~~~~~ ConsoleApplicationEndMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationEndMissionMessage:: + ConsoleApplicationEndMissionMessage( + HostID player_host_ID, + int final_score + ): + NetworkClient::Message( + ConsoleApplicationEndMissionMessageID, + sizeof(ConsoleApplicationEndMissionMessage) + ) +{ + playerHostID = player_host_ID; + finalScore = final_score; +} + +//~~~~~~~~~~~~~~~~~~ ConsoleApplicationAbortMissionMessage ~~~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationAbortMissionMessage:: + ConsoleApplicationAbortMissionMessage( + HostID player_host_ID + ): + NetworkClient::Message( + ConsoleApplicationAbortMissionMessageID, + sizeof(ConsoleApplicationAbortMissionMessage) + ) +{ + playerHostID = player_host_ID; +} + +//~~~~~~~~~~~~~~~~ ConsoleApplicationTeamEndMissionMessage ~~~~~~~~~~~~~~~~~~~~ + +ConsoleApplicationTeamEndMissionMessage:: + ConsoleApplicationTeamEndMissionMessage( + HostID player_host_ID, + int player_score, + int team_ID, + int team_score + ): + NetworkClient::Message( + ConsoleApplicationTeamEndMissionMessageID, + sizeof(ConsoleApplicationTeamEndMissionMessage) + ) +{ + playerHostID = player_host_ID; + playerScore = player_score; + teamID = team_ID; + teamScore = team_score; +} + +//============================================================================== diff --git a/MUNGA/CONSOLE.h b/MUNGA/CONSOLE.h new file mode 100644 index 0000000..dad4be3 --- /dev/null +++ b/MUNGA/CONSOLE.h @@ -0,0 +1,281 @@ +#pragma once + +#if defined(MAC) + #include + #include +#else + #include "network.h" +#endif + + //~~~~~~~~~~~~~~~~~~~~~~~~ Console Message IDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + enum ConsoleMessageID + { + ConsoleApplicationReadyToRunMessageID = 0, + ConsoleApplicationStateResponseMessageID = 1, + ConsoleApplicationEndMissionMessageID = 7, + ConsoleApplicationAbortMissionMessageID = 11, + ConsoleApplicationTeamEndMissionMessageID = 14 + }; + + //~~~~~~~~~~~~~~~~~~ ConsoleApplicationReadyToRunMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationReadyToRunMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID); + + long + GetReadyToRunHostID() + {return readyToRunHostID.value();} + + private: + HostID + readyToRunHostID; + }; +#pragma options align=reset +#else + class ConsoleApplicationReadyToRunMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationReadyToRunMessage(HostID ready_to_run_host_ID); + + HostID + GetReadyToRunHostID() + {return readyToRunHostID;} + + private: + HostID + readyToRunHostID; + }; +#endif + + //~~~~~~~~~~~~~~~~ ConsoleApplicationStateResponseMessage ~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationStateResponseMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationStateResponseMessage( + HostID responding_host_ID, + LEDWORD application_state, + LEDWORD application_type + ); + + long + GetRespondingHostID() + {return respondingHostID.value();} + long + GetApplicationState() + {return applicationState.value();} + ApplicationID + GetApplication() + {return((ApplicationID) application.value());} + + private: + HostID + respondingHostID; + LEDWORD + applicationState; + LEDWORD + application; + }; +#pragma options align=reset +#else + class ConsoleApplicationStateResponseMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationStateResponseMessage( + HostID responding_host_ID, + Enumeration application_state, + Enumeration application + ); + + HostID + GetRespondingHostID() + {return respondingHostID;} + Enumeration + GetApplicationState() + {return applicationState;} + Enumeration + GetApplication() + {return application;} + + private: + HostID + respondingHostID; + Enumeration + applicationState; + Enumeration + application; + }; +#endif + + //~~~~~~~~~~~~~~~~~~ ConsoleApplicationEndMissionMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationEndMissionMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationEndMissionMessage( + HostID player_ID, + LEDWORD final_score + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetFinalScore() + {return finalScore.value();} + + private: + HostID + playerHostID; + LEDWORD + finalScore; + }; +#pragma options align=reset +#else + class ConsoleApplicationEndMissionMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationEndMissionMessage( + HostID player_host_ID, + int final_score + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + int + GetFinalScore() + {return finalScore;} + + private: + HostID + playerHostID; + int + finalScore; + }; +#endif + + //~~~~~~~~~~~~~~~~~~ ConsoleApplicationAbortMissionMessage ~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationAbortMissionMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationAbortMissionMessage( + HostID player_ID + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + + private: + HostID + playerHostID; + }; +#pragma options align=reset +#else + class ConsoleApplicationAbortMissionMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationAbortMissionMessage( + HostID player_host_ID + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + + private: + HostID + playerHostID; + }; +#endif + + //~~~~~~~~~~~~~~~~ ConsoleApplicationTeamEndMissionMessage ~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte + class ConsoleApplicationTeamEndMissionMessage: + public NetworkEndpoint::Message + { + public: + ConsoleApplicationTeamEndMissionMessage( + HostID player_ID, + LEDWORD player_score, + LEDWORD team_id, + LEDWORD team_score + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetPlayerScore() + {return playerScore.value();} + long + GetTeamID() + {return teamID.value();} + long + GetTeamScore() + {return teamScore.value();} + + private: + HostID + playerHostID; + LEDWORD + playerScore; + LEDWORD + teamID; + LEDWORD + teamScore; + }; +#pragma options align=reset +#else + class ConsoleApplicationTeamEndMissionMessage: + public NetworkClient::Message + { + public: + ConsoleApplicationTeamEndMissionMessage( + HostID player_host_ID, + int player_score, + int team_id, + int team_score + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + int + GetFinalScore() + {return playerScore;} + int + GetTeamID() + {return teamID;} + int + GetTeamScore() + {return teamScore;} + + private: + HostID + playerHostID; + int + playerScore; + int + teamID; + int + teamScore; + }; +#endif diff --git a/MUNGA/CONTROLS.cpp b/MUNGA/CONTROLS.cpp new file mode 100644 index 0000000..36dea01 --- /dev/null +++ b/MUNGA/CONTROLS.cpp @@ -0,0 +1,660 @@ +#include "munga.h" +#pragma hdrstop + +#include "controls.h" +#include "app.h" + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//############################################################################ +//####################### ControlsInstance ############################# +//############################################################################ + +ControlsInstance::ControlsInstance( + ClassID class_ID, + ModeMask mode_mask, + Plug *dependant +): + Node(class_ID), + dependantPlug(this) +{ + Check_Pointer(this); + modeMask = mode_mask; + dependantPlug.Add(dependant); + + Check_Fpu(); +} + +ControlsInstance::~ControlsInstance() +{ + Check(this); + Check_Fpu(); +} + +void + ControlsInstance::Update(void *) +{ + Fail("ControlsInstance::Update not overridden!"); +} + +// +//############################################################################# +//############################################################################# +// +void + ControlsInstance::ReleaseLinkHandler( + Socket*, + Plug* + ) +{ + Unregister_Object(this); + delete this; + Check_Fpu(); +} + +//############################################################################ +//######################### ControlsMappingGroup ############################# +//############################################################################ + +// +// The ControlsMappingGroup object maintains a group of ControlInstances. +// +// ControlsMappingGroup.Update() will call ControlsInstance.Update() +// for each instance in the group. +// + +ControlsMappingGroup::ControlsMappingGroup(): + Node(ControlsMappingGroup::ControlsMappingGroupClassID), + instanceList(this) +{ + Check_Pointer(this); + Check_Fpu(); +} + +ControlsMappingGroup::~ControlsMappingGroup() +{ + Check(this); + Remove(0); // remove all mappings + Check_Fpu(); +} + +void ControlsMappingGroup::Remove(ModeMask mode_mask) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + ControlsInstance + *controls_instance; + + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //--------------------------------------------- + // Remove mapping bit(s) + //--------------------------------------------- + controls_instance->modeMask &= ~mode_mask; + //--------------------------------------------- + // If no bits left, delete mapping + //--------------------------------------------- + if (controls_instance->modeMask == (ModeMask)0) + { + Unregister_Object(controls_instance); + delete controls_instance; + } + } + Check_Fpu(); +} + +void + ControlsMappingGroup::Update(void *data_source, ModeMask mode_mask) +{ + Check(this); + Check_Pointer(data_source); + + ChainIteratorOf + i(instanceList); + + ControlsInstance + *controls_instance; + + while ((controls_instance=i.ReadAndNext()) != NULL) + { + //------------------------------------------------ + // Process only if at least one mode bit matches + //------------------------------------------------ + Check(controls_instance); + if (controls_instance->modeMask & mode_mask) + { + controls_instance->Update(data_source); + } + } + Check_Fpu(); +} + +Logical + ControlsMappingGroup::CurrentFilterStatus(ModeMask mode_mask) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + ControlsInstance + *controls_instance; + + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + + if (controls_instance->modeMask & mode_mask) + { + Check_Fpu(); + return True; + } + } + Check_Fpu(); + return False; +} + +//############################################################################ +//########################### ControlsManager ################################ +//############################################################################ + +//--------------------------------------------------------------------------- +// Class derivation +//--------------------------------------------------------------------------- +Derivation* ControlsManager::GetClassDerivations() +{ + static Derivation classDerivations(Receiver::GetClassDerivations(), "ControlsManager"); + return &classDerivations; +} + +unsigned int + ControlsManager::nextOwnerID=0; + +ControlsManager + *ControlsManager::headControlsManager = NULL; + +// +//############################################################################ +// ControlsManager +// +// Creator method +//---------------------------------------------------------------------------- +// Enter: virtualDataPtr +//############################################################################ +// +ControlsManager::ControlsManager( + ClassID class_ID, + SharedData &shared_data +): + Receiver( + class_ID, + shared_data + ) +{ + activeDestination = NULL; + activeReceiver = NULL; + activeMessageID = (Receiver::MessageID) 0; + activeDependant = NULL; + //---------------------------------------------------- + // Add this object to the chain + //---------------------------------------------------- + nextControlsManager = headControlsManager; + headControlsManager = this; + Check_Fpu(); +} + +// +//############################################################################ +// ~ControlsManager +// +// Destructor method +//############################################################################ +// +ControlsManager::~ControlsManager() +{ + //---------------------------------------------------- + // Unlink this object from the chain + //---------------------------------------------------- + ControlsManager + *controls_manager, + *previous_controls_manager(NULL); + + // + // Search for 'this' in the chain + // + for( + controls_manager = headControlsManager; + controls_manager != NULL; + controls_manager = controls_manager->nextControlsManager + ) + { + if (controls_manager == this) + { + // + // Found! head of list? + // + if (previous_controls_manager == NULL) + { + headControlsManager = nextControlsManager; + } + // + // Not head, remove from chain + // + else + { + previous_controls_manager->nextControlsManager = + nextControlsManager; + } + break; + } + // + // Keep track of 'previous' object + // + previous_controls_manager = controls_manager; + } + Check_Fpu(); +} + +void + ControlsManager::Remove(ModeMask /*mode_mask*/) +{ + Fail("ControlsManager::Remove should not be called!\n"); +} + +void + ControlsManager::Execute() +{ + Fail("ControlsManager::Execute should not be called!\n"); +} + +void + ControlsManager::StartMappableButtonsConfigure( + void *active_direct_target, + Receiver *target, + Plug *dependant, + Receiver::MessageID active_message_id, + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ) +{ + Check(this); + + activeReceiver = target; + activeMessageID = active_message_id; + activeDestination = active_direct_target; + activeDependant = dependant; + + Check(application); + ModeManager + *mode_manager = application->GetModeManager(); + Check(mode_manager); + + mode_manager->RemoveModeMask(remove_mode_mask); + mode_manager->AddModeMask(add_mode_mask); + + Check_Fpu(); +} + +void + ControlsManager::StopMappableButtonsConfigure( + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ) +{ + Check(this); + + Check(application); + ModeManager + *mode_manager = application->GetModeManager(); + Check(mode_manager); + + mode_manager->RemoveModeMask(remove_mode_mask); + mode_manager->AddModeMask(add_mode_mask); + + activeDestination = NULL; + activeReceiver = NULL; + activeMessageID = (Receiver::MessageID) 0; + activeDependant = NULL; + + Check_Fpu(); +} + +void + ControlsManager::AddOrEraseMappableButton( + int /*button_number*/, + ModeMask /*mode_mask*/ + ) +{ + Check(this); + Check_Fpu(); +} + +// +//############################################################################ +// TestInstance +// +//############################################################################ +// +Logical + ControlsManager::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +// +//############################################################################ +// Shutdown +// +//############################################################################ +// +void + ControlsManager::Shutdown() +{ + ControlsManager + *controls_manager; + + for( + controls_manager = headControlsManager; + controls_manager != NULL; + controls_manager = controls_manager->nextControlsManager + ) + { + controls_manager->LocalShutdown(); + } + Check_Fpu(); +} + +void + ControlsManager::LocalShutdown() +{ + Check(this); + Check_Fpu(); +} + +//######################################################################### +//############################# ControlsString ############################ +//######################################################################### +int + ControlsString::nextID = 1; + +ControlsString::ControlsString( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + int user_code +): + Node(RegisteredClass::ControlsStringClassID) +{ + Test_Tell( + "ControlsString creator('" new_string << + "'," << keypad_unit_number << + "," << receiver_pointer << + "," << message_id << + ")\n" + ); + Check_Pointer(this); + Check_Pointer(new_string); + Check(receiver_pointer); + + //---------------------------------------------- + // Assign unique ID + //---------------------------------------------- + id = nextID++; + matchStringPointer = new_string; + keypadUnitNumber = keypad_unit_number; + //---------------------------------------------- + // Save message data + //---------------------------------------------- + receiverPointer = receiver_pointer; + messageID = message_id; + userCode = user_code; + //---------------------------------------------- + // Clear the buffer + //---------------------------------------------- + string[0] = '\0'; + stringLength = 0; + + Check_Fpu(); +} + +ControlsString::~ControlsString() +{ + Test_Tell("ControlsString destructor\n"); + Check(this); + Check_Fpu(); +} + +Logical + ControlsString::TestInstance() const +{ + return True; +} + +void + ControlsString::Update(int keypad_unit_number, ControlsKey new_key) +{ + Test_Tell( + "ControlsString::Update(" << keypad_unit_number << + "," << new_key << + "\n" + ); + Check(this); + + //---------------------------------------------- + // Update only if proper keyboard unit + //---------------------------------------------- + if (keypad_unit_number == keypadUnitNumber) + { + //-------------------------------------- + // Get string length + //-------------------------------------- + Check_Pointer(matchStringPointer); + int + length = strlen(matchStringPointer); + if (length > maxStringLength) + { + length = maxStringLength; + } + + if (stringLength > length) // in case matchString changes + { + stringLength = length; + string[stringLength] = '\0'; + } + //-------------------------------------- + // Update string buffer + //-------------------------------------- + if (stringLength < length) + { + string[stringLength++] = (char) new_key; + string[stringLength] = '\0'; + } + else + { + if (length > 1) + { + memmove(&string[0],&string[1], length-1); + } + string[length-1] = (char) new_key; + } + Test_Tell("string=" << string << "\n"); + //-------------------------------------- + // Check for match + //-------------------------------------- + if (strnicmp(string, matchStringPointer, length) == 0) + { + Test_Tell( + "ControlsString::Update, '" << matchStringPointer << + "' matched!\n" + ); + //-------------------------------------- + // Match found, send message + //-------------------------------------- + Check(receiverPointer); + Check(application); + + ControlsStringMessage + message(messageID, this->userCode); + receiverPointer->Dispatch(&message); + //-------------------------------------- + // Clear the string + //-------------------------------------- + string[0] = '\0'; + stringLength = 0; + } + } + Check_Fpu(); +} + +//######################################################################### +//######################## ControlsStringManager ########################## +//######################################################################### +ControlsStringManager::ControlsStringManager() : + Node(RegisteredClass::ControlsStringManagerClassID), + instanceList(this) +{ + Test_Tell("ControlsStringManager creator\n"); + Check_Pointer(this); +} + +ControlsStringManager::~ControlsStringManager() +{ + Test_Tell("ControlsStringManager destructor\n"); + Check(this); + //---------------------------------------------- + // Remove all ControlStrings + //---------------------------------------------- + Remove(0); + + Check_Fpu(); +} + +Logical + ControlsStringManager::TestInstance() const +{ + return True; +} + +ControlsStringID + ControlsStringManager::Add( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + int user_code + ) +{ + Test_Tell("ControlsStringManager::Add(" << new_string << + "," << keypad_unit_number << + "," << receiver_pointer << + "," << message_id << + "\n" + ); + Check(this); + Check_Pointer(new_string); + Check(receiver_pointer); + + //---------------------------------------------- + // Create the ControlsString + //---------------------------------------------- + ControlsString + *string_item = new ControlsString( + new_string, + keypad_unit_number, + receiver_pointer, + message_id, + user_code + ); + Check(string_item); + Register_Object(string_item); + //---------------------------------------------- + // Add to the instance list + //---------------------------------------------- + instanceList.Add(string_item); + //---------------------------------------------- + // return the new string's (unique) ID + //---------------------------------------------- + Check_Fpu(); + return string_item->id; +} + +void + ControlsStringManager::Remove(ControlsStringID string_id) +{ + Test_Tell("ControlsStringManager::Remove(" << string_id << ")\n"); + Check(this); + + ChainIteratorOf + i(instanceList); + + ControlsString + *controls_string; + + //---------------------------------------------- + // Search for the given ID (or universal match) + //---------------------------------------------- + while ((controls_string=i.ReadAndNext()) != NULL) + { + Check(controls_string); + if ( + (string_id == 0) || + (controls_string->id == string_id) + ) + { + Unregister_Object(controls_string); + delete controls_string; + //------------------------------------------ + // If this is not a 'universal' remove, + // we're done (ID's are unique) + //------------------------------------------ + if (string_id != 0) + { + break; + } + } + } + Check_Fpu(); +} + +void + ControlsStringManager::Update( + int keypad_unit_number, + ControlsKey new_key + ) +{ + Test_Tell("ControlsStringManager::Update(" << keypad_unit_number << + "," << new_key << + ")\n" + ); + Check(this); + + //-------------------------------------- + // Update all matching string items + //-------------------------------------- + ChainIteratorOf + i(instanceList); + + ControlsString + *controls_string; + + while ((controls_string=i.ReadAndNext()) != NULL) + { + Check(controls_string); + controls_string->Update(keypad_unit_number, new_key); + } + Check_Fpu(); +} + + +#if defined(TEST_CLASS) + #include "controls.tcp" +#endif diff --git a/MUNGA/CONTROLS.h b/MUNGA/CONTROLS.h new file mode 100644 index 0000000..cfbea8a --- /dev/null +++ b/MUNGA/CONTROLS.h @@ -0,0 +1,910 @@ +#pragma once + +#include "style.h" + +class Controls; +class ControlsInstance; +class ControlsMappingGroup; +struct ControlsMapping; +class ControlsOwner; +class ControlsManager; + +#include "slot.h" +#include "chain.h" +#include "vector2d.h" +#include "receiver.h" +#include "simulate.h" +#include "mode.h" + +//######################################################################## +//######################## Basic control typedefs ######################## +//######################################################################## + +typedef Scalar ControlsScalar; +typedef Vector2DOf ControlsJoystick; +typedef int ControlsKey; +typedef int ControlsButton; // negative for release +typedef Vector2DOf ControlsMouse; + +//######################################################################### +//######################### ControlsInstance ############################## +//######################################################################### + +// The ControlsInstance object exists to serve the ControlsMappingGroup +// object. It maintains one instance of a mapping from a physical +// input device to either an entity event message or a value. + +class ControlsInstance : + public Node +{ + friend class ControlsMappingGroup; + friend class ControlsManager; // required for testing + friend class L4MappableButtonManager; + +public: + ControlsInstance( + ClassID class_id, + ModeMask mode_mask, + Plug *dependant + ); + ~ControlsInstance(); + + ModeMask + modeMask; // lots of objects (and templates) need access to this + +protected: + virtual void Update(void *data_source); + + SlotOf + dependantPlug; + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ControlsInstanceDirectOf ~~~~~~~~~~~~~~~~~~ + +template class ControlsInstanceDirectOf: + public ControlsInstance +{ + friend class ControlsMappingGroup; + friend class ControlsManager; // required for testing + +public: + ControlsInstanceDirectOf( + ModeMask mode_mask, + T* data_pointer, + Plug *dependant + ); + ControlsInstanceDirectOf( + ControlsInstanceDirectOf *original + ); + ~ControlsInstanceDirectOf(); + Logical + TestInstance() const; + +// protected: + void Update(void *data_source); + + T *dataPointer; +}; + +template ControlsInstanceDirectOf::ControlsInstanceDirectOf( + ModeMask mode_mask, + T* data, + Plug *dependant +): + ControlsInstance( + DirectControlsInstanceClassID, + mode_mask, + dependant + ), + dataPointer(data) + {} + +template ControlsInstanceDirectOf::ControlsInstanceDirectOf( + ControlsInstanceDirectOf *original +): + ControlsInstance( + DirectControlsInstanceClassID, + original->modeMask, + original->dependantPlug.GetCurrent() + ), + dataPointer(original->dataPointer) + {} + +template ControlsInstanceDirectOf::~ControlsInstanceDirectOf() + {} + +template void + ControlsInstanceDirectOf::Update(void *data_source) +{ + Check(this); + Check_Pointer(data_source); + Check_Pointer(dataPointer); + *dataPointer = *(T*)data_source; + Verify(*dataPointer == *(T*)data_source); + Check_Fpu(); +} + +template Logical + ControlsInstanceDirectOf::TestInstance() const +{ + Check_Pointer(this); + Check_Pointer(dataPointer); + Check_Fpu(); + return Plug::TestInstance(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ControlsInstanceEventOf ~~~~~~~~~~~~~~~~~~ + +template class ControlsInstanceEventOf: + public ControlsInstance +{ + friend class ControlsMappingGroup; + friend class ControlsManager; // required for testing + +public: + ControlsInstanceEventOf( + ModeMask mode_mask, + Receiver *receiver, + Receiver::MessageID message_id, + Plug *dependant + ); + ControlsInstanceEventOf( + ControlsInstanceEventOf *original + ); + + ~ControlsInstanceEventOf(); + Logical + TestInstance() const; + +// protected: + void Update(void *data_source); + + Receiver *receiverPointer; + Receiver::MessageID messageID; +}; + +template ControlsInstanceEventOf::ControlsInstanceEventOf( + ModeMask mode_mask, + Receiver *receiver, + Receiver::MessageID message_id, + Plug *dependant +): + ControlsInstance( + EventControlsInstanceClassID, + mode_mask, + dependant + ), + receiverPointer(receiver), + messageID(message_id) + {} + +template ControlsInstanceEventOf::ControlsInstanceEventOf( + ControlsInstanceEventOf *original +): + ControlsInstance( + EventControlsInstanceClassID, + original->modeMask, + original->dependantPlug.GetCurrent() + ), + receiverPointer(original->receiverPointer), + messageID(original->messageID) + {} + +template ControlsInstanceEventOf::~ControlsInstanceEventOf() + {} + +template void + ControlsInstanceEventOf::Update(void *data_source) +{ + Check(this); + Check_Pointer(data_source); + Check(application); + + ReceiverDataMessageOf + update_message( + messageID, + sizeof(ReceiverDataMessageOf), + *(T*)data_source + ); + + application->Post( + ControlsEventPriority, + receiverPointer, + &update_message + ); +} + +template Logical + ControlsInstanceEventOf::TestInstance() const +{ + Check_Pointer(this); + Check(receiverPointer); + Check_Fpu(); + return Plug::TestInstance(); +} + +//######################################################################### +//######################### ControlsMappingGroup ########################## +//######################################################################### + +// The ControlsMappingGroup object maintains a group of ControlInstances. +// +// ControlsMappingGroup.Update() will call ControlsInstance.Update() +// for each instance in the group. + +class ControlsMappingGroup : + public Node +{ + friend class ControlsManager; // required for testing + +public: + ControlsMappingGroup(); + ~ControlsMappingGroup(); + + void + Add(ControlsInstance *mapping) + { + Check(this); + Check(mapping); + instanceList.Add(mapping); + } + + virtual void + Remove(ModeMask mode_mask); + + virtual void + Update(void *value, ModeMask mode_mask); + + Logical // returns true if at least one button active + CurrentFilterStatus(ModeMask mode_mask); + +protected: + ChainOf + instanceList; +}; + +//######################################################################### +//########################## ControlsUpdateManager ######################## +//######################################################################### + +template class ControlsUpdateManager : + public ControlsMappingGroup +{ +public: + ControlsUpdateManager(); + ~ControlsUpdateManager(); + + Logical + TestInstance() const; + + virtual ControlsInstance* + Add( + ModeMask mode_mask, + Receiver *receiver_pointer, + Receiver::MessageID id, + Plug *dependant + ); + + virtual ControlsInstance* + Add( + ModeMask mode_mask, + T *destination, + Plug *dependant + ); + + virtual ControlsInstance* + AddOrErase( + ModeMask mode_mask, + Receiver *target, + Receiver::MessageID message_ID, + Plug *dependant + ); + + virtual ControlsInstance* + AddOrErase( + ModeMask mode_mask, + T *destination, + Plug *dependant + ); + + enum + { + unmapped = 0, + mappedByOthers = 1, + mappedByMe = 2 + }; + + virtual int + GetMapState( + void *direct_destination, + Receiver *event_receiver, + Receiver::MessageID message_id, + ModeMask mode_mask + ); + + virtual void + Update(void *sourcePointer, ModeMask mode_mask); + + void + ForceUpdate(T *sourcePointer, ModeMask mode_mask); + + T + previousValue; +}; + +template Logical + ControlsUpdateManager::TestInstance() const +{ + return True; +} + +template + ControlsUpdateManager::ControlsUpdateManager() + : ControlsMappingGroup() +{ +} + +template ControlsUpdateManager::~ControlsUpdateManager() +{ +} + +template void + ControlsUpdateManager::Update( + void * source_pointer, + ModeMask mode_mask + ) +{ + Check(this); + Check_Pointer(source_pointer); + + if (previousValue != *(T*) source_pointer) + { + ForceUpdate((T*)source_pointer, mode_mask); + } + Check_Fpu(); +} + +template void + ControlsUpdateManager::ForceUpdate( + T* source_pointer, + ModeMask mode_mask + ) +{ + Check(this); + Check_Pointer(source_pointer); + previousValue = *source_pointer; + ControlsMappingGroup::Update(source_pointer, mode_mask); + Check_Fpu(); +} + +template ControlsInstance* + ControlsUpdateManager::Add( + ModeMask mode_mask, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + Plug *dependant + ) +{ + Check(this); + Check(receiver_pointer); + + ControlsInstanceEventOf *instance = + new ControlsInstanceEventOf( + mode_mask, + receiver_pointer, + message_id, + dependant + ); + Register_Object(instance); + ControlsMappingGroup::Add(instance); + Check_Fpu(); + return instance; +} + +template ControlsInstance* + ControlsUpdateManager::Add( + ModeMask mode_mask, + T *destination, + Plug *dependant + ) +{ + Check(this); + Check_Pointer(destination); + + ControlsInstanceDirectOf *instance = + new ControlsInstanceDirectOf( + mode_mask, + destination, + dependant + ); + Register_Object(instance); + ControlsMappingGroup::Add(instance); + Check_Fpu(); + return instance; +} + +template ControlsInstance* + ControlsUpdateManager::AddOrErase( + ModeMask mode_mask, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + Plug *dependant + ) +{ + Check(this); + Check(receiver_pointer); + + ChainIteratorOf + i(instanceList); + ControlsInstance + *controls_instance; + ControlsInstanceEventOf + *event_mapping; + + //----------------------------------------------- + // Search through all mappings + //----------------------------------------------- + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //----------------------------------------------- + // Process only the event mappings + //----------------------------------------------- + if (controls_instance->GetClassID() == EventControlsInstanceClassID) + { + event_mapping = (ControlsInstanceEventOf *)controls_instance; + Check(event_mapping); + //----------------------------------------------- + // Process only if the target is correct, AND + // if the mapping is allowed under the given + // mode mask + //----------------------------------------------- + if ( + (event_mapping->receiverPointer == receiver_pointer) && + (event_mapping->messageID == message_id) && + (event_mapping->modeMask & mode_mask) + ) + { + //----------------------------------------------- + // Found! Remove mode enable bit(s) + //----------------------------------------------- + event_mapping->modeMask &= ~mode_mask; + //----------------------------------------------- + // If this mapping no longer matches ANY mode + // (i.e., all bits cleared), delete it, 'cuz + // it doesn't do anything anymore. + //----------------------------------------------- + if (event_mapping->modeMask == (ModeMask)0) + { + Unregister_Object(event_mapping); + delete event_mapping; + } + //----------------------------------------------- + // We found the match, break out of the loop + //----------------------------------------------- + break; + } + } + } + + //---------------------------------------------------------- + // If the mapping wasn't found (controls_instance == NULL), + // then create one. + //---------------------------------------------------------- + if (controls_instance == NULL) + { + event_mapping = + new ControlsInstanceEventOf( + mode_mask, + receiver_pointer, + message_id, + dependant + ); + Register_Object(event_mapping); + ControlsMappingGroup::Add(event_mapping); + Check_Fpu(); + return event_mapping; + } + Check_Fpu(); + return NULL; +} + +template ControlsInstance* + ControlsUpdateManager::AddOrErase( + ModeMask mode_mask, + T *destination, + Plug *dependant + ) +{ + Check(this); + Check_Pointer(destination); + + ChainIteratorOf + i(instanceList); + ControlsInstance + *controls_instance; + ControlsInstanceDirectOf + *direct_mapping; + + //----------------------------------------------- + // Search through all mappings + //----------------------------------------------- + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //----------------------------------------------- + // Process only the direct mappings + //----------------------------------------------- + if (controls_instance->GetClassID() == DirectControlsInstanceClassID) + { + direct_mapping = (ControlsInstanceDirectOf *)controls_instance; + Check(direct_mapping); + //----------------------------------------------- + // Process only if the target is correct, AND + // if the mapping is allowed under the given + // mode mask + //----------------------------------------------- + if ( + (direct_mapping->dataPointer == destination) && + (direct_mapping->modeMask & mode_mask) + ) + { + //----------------------------------------------- + // Found! Remove mode enable bit(s) + //----------------------------------------------- + direct_mapping->modeMask &= ~mode_mask; + //----------------------------------------------- + // If this mapping no longer matches ANY mode + // (i.e., all bits cleared), delete it, 'cuz + // it doesn't do anything anymore. + //----------------------------------------------- + if (direct_mapping->modeMask == (ModeMask)0) + { + Unregister_Object(direct_mapping); + delete direct_mapping; + } + //----------------------------------------------- + // We found the match, break out of the loop + //----------------------------------------------- + break; + } + } + } + //---------------------------------------------------------- + // If the mapping wasn't found (controls_instance == NULL), + // then create one. + //---------------------------------------------------------- + if (controls_instance == NULL) + { + direct_mapping = + new ControlsInstanceDirectOf( + mode_mask, + destination, + dependant + ); + Register_Object(direct_mapping); + ControlsMappingGroup::Add(direct_mapping); + Check_Fpu(); + return direct_mapping; + } + Check_Fpu(); + return NULL; +} + +template int + ControlsUpdateManager::GetMapState( + void *direct_destination, + Receiver *event_receiver, + Receiver::MessageID message_id, + ModeMask mode_mask + ) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + ControlsInstance + *controls_instance; + int + map_state = 0; + + //----------------------------------------------- + // Search through all mappings + //----------------------------------------------- + while ((controls_instance=i.ReadAndNext()) != NULL) + { + Check(controls_instance); + //------------------------------------ + // Process if allowed mode + //------------------------------------ + if (controls_instance->modeMask & mode_mask) + { + //------------------------------------ + // Process direct mappings + //------------------------------------ + if (controls_instance->GetClassID() == + DirectControlsInstanceClassID + ) + { + ControlsInstanceDirectOf + *direct_mapping = (ControlsInstanceDirectOf *) + controls_instance; + + Check(direct_mapping); + if (direct_mapping->dataPointer == direct_destination) + { + map_state |= mappedByMe; + } + else + { + map_state |= mappedByOthers; + } + } + //------------------------------------ + // Process event mappings + //------------------------------------ + else + { + Verify(controls_instance->GetClassID() == + EventControlsInstanceClassID + ); + + ControlsInstanceEventOf + *event_mapping = (ControlsInstanceEventOf *) + controls_instance; + + Check(event_mapping); + if ( + (event_mapping->receiverPointer == event_receiver) && + (event_mapping->messageID == message_id) + ) + { + map_state |= mappedByMe; + } + else + { + map_state |= mappedByOthers; + } + } + } + } + Check_Fpu(); + return map_state; +} + +//######################################################################### +//############################ ControlsManager ############################ +//######################################################################### +class ControlsManager: + public Receiver +{ + friend class ControlsMappingGroup; // for access to groupEnable + //------------------------------------------------------------------- + // Shared data support + //------------------------------------------------------------------- +public: + static Derivation *GetClassDerivations(); +// static SharedData DefaultData; + + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- +protected: + ControlsManager( + ClassID class_ID = ControlsManagerClassID, + SharedData &shared_data = ControlsManager::DefaultData + ); +public: + ~ControlsManager(); + + unsigned int + UniqueOwnerID() + { + if ((nextOwnerID+1)==0) { ++nextOwnerID; } + Check_Fpu(); + return (++nextOwnerID); + } + + virtual void + Remove(ModeMask mode_mask); + + virtual void + Execute(); + + static Logical + TestClass(); + + Logical + TestInstance() const; + + static void + Shutdown(); + + virtual void + LocalShutdown(); + + //------------------------------------------------------------------- + // Mode control + //------------------------------------------------------------------- + virtual void + StartMappableButtonsConfigure( + void *active_direct_target, + Receiver *target, + Plug *dependant, + Receiver::MessageID active_message_id, + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ); + + virtual void + StopMappableButtonsConfigure( + ModeMask remove_mode_mask, + ModeMask add_mode_mask + ); + + virtual void + AddOrEraseMappableButton( + int button_number, + ModeMask mode_mask + ); + //------------------------------------------------------------------- + // Gauge support + //------------------------------------------------------------------- + void + *activeDestination; + Receiver + *activeReceiver; + Receiver::MessageID + activeMessageID; + Plug + *activeDependant; + +private: + static ControlsManager + *headControlsManager; + + ControlsManager + *nextControlsManager; + + static unsigned int + nextOwnerID; +}; + + +//######################################################################### +//############################ ControlsMapping ############################ +//######################################################################### +// Used by tools for building/reading control map streams +struct ControlsMapping +{ +public: + enum { + DirectMapping=0, + EventMapping=1 + }; + + Enumeration + controlsGroup, + controlsElement, + mappingType, + subsystemID; + ModeMask + modeMask; + union + { + Simulation::AttributeID attributeID; + Receiver::MessageID messageID; + }; +}; + +//######################################################################### +//############################ ControlsString ############################# +//######################################################################### + +typedef int ControlsStringID; + +class ControlsString : + public Node +{ + friend class ControlsStringManager; +protected: + + enum + { + maxStringLength=16 + }; + + ControlsString( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID message_id, + int user_code + ); + ~ControlsString(); + + Logical + TestInstance() const; + void + Update(int keypad_unit_number, ControlsKey new_key); + + ControlsStringID + id; + const char + *matchStringPointer; + char + string[maxStringLength+1]; + int + stringLength, + keypadUnitNumber, + userCode; + Receiver + *receiverPointer; + Receiver::MessageID + messageID; + + static ControlsStringID + nextID; +}; + + + +//######################################################################### +//######################## ControlsStringMessage ########################## +//######################################################################### +// This is sent by the controlsString object when a match is detected + +class ControlsStringMessage: + public Receiver::Message +{ +public: + ControlsStringMessage( + Receiver::MessageID message_ID, + int user_code + ): + Receiver::Message(message_ID, sizeof(ControlsStringMessage)), + userCode(user_code) + {} + + int + userCode; +}; + +//######################################################################### +//######################## ControlsStringManager ########################## +//######################################################################### +// This class matches strings from a keypad. When the given string +// is matched, it sends an event to the given receiver. + +class ControlsStringManager : + public Node +{ +public: + ControlsStringManager(); + ~ControlsStringManager(); + + Logical + TestInstance() const; + + ControlsStringID + Add( + const char *new_string, + int keypad_unit_number, + Receiver *receiver_pointer, + Receiver::MessageID id, + int user_code = 0 + ); + void + Remove(ControlsStringID string_id); + + void + Update(int keypad_unit_number, ControlsKey new_key); + + ChainOf + instanceList; +}; diff --git a/MUNGA/CSTR.cpp b/MUNGA/CSTR.cpp new file mode 100644 index 0000000..cf1c6f8 --- /dev/null +++ b/MUNGA/CSTR.cpp @@ -0,0 +1,444 @@ +#include "munga.h" +#include "cstr.h" +#include "memstrm.h" + +//namespace Munga +//{ + rString StringRepresentation::operator+=(char chr) + { + Check(this); + size_t len = strlen(&firstByte); + *(&firstByte + len++) = chr; + *(&firstByte + len) = '\0'; + return *this; + } + + #if defined(USE_SIGNATURE) + int Is_Signature_Bad(const StringRepresentation *) + { + return false; + } + #endif + + MemoryStream& MemoryStream_Read(MemoryStream *stream, StringRepresentation *str) + { + Check(stream); + Check(str); + + pString ptr = *str; + for (*stream >> ptr[(size_t)0]; ptr[(size_t)0]; ++ptr) + *stream >> ptr[(size_t)0]; + return *stream; + } + + MemoryStream& MemoryStream_Write(MemoryStream *stream, const StringRepresentation &str) + { + Check(stream); + Check(&str); + + return stream->WriteBytes((const char*)str, str.GetLength() + 1); + } + + #define DELETE_FILL_CHAR ('0') + + size_t CStringRepresentation::allocationIncrement = 8; + + inline size_t CStringRepresentation::CalculateSize(size_t needed) + { + Verify(!Small_Enough(allocationIncrement)); + size_t x = ((needed + allocationIncrement) / allocationIncrement) * allocationIncrement; + return x; + } + + CStringRepresentation::CStringRepresentation() + { + stringLength = 0; + stringSize = 0; + stringText = NULL; + referenceCount = 0; + } + + CStringRepresentation::CStringRepresentation(const CStringRepresentation &str) + { + Check(&str); + stringLength = str.stringLength; + stringSize = str.stringSize; + + if (str.stringText == NULL) + stringText = NULL; + else + { + stringText = new char[stringSize]; + Register_Pointer(stringText); + Mem_Copy(stringText, str.stringText, stringLength + 1, stringSize); + } + referenceCount = 0; + } + + CStringRepresentation::CStringRepresentation(const char *cstr) + { + if ((cstr == NULL) || (cstr[0] == '\x00')) + { + stringLength = 0; + stringSize = 0; + stringText = NULL; + } + else + { + stringLength = strlen(cstr); + stringSize = CalculateSize(stringLength); + + stringText = new char[stringSize]; + Register_Pointer(stringText); + Mem_Copy(stringText, cstr, stringLength + 1, stringSize); + } + referenceCount = 0; + } + + CStringRepresentation::~CStringRepresentation() + { + if (stringText != NULL) + { + #if DEBUG_LEVEL>0 + memset(stringText, DELETE_FILL_CHAR, stringSize); + #endif + Unregister_Pointer(stringText); + delete[] stringText; + } + } + + Logical CStringRepresentation::TestInstance() const + { + if (stringText == NULL) + { + Verify(stringSize == 0); + Verify(stringLength == 0); + } + else + { + Verify(stringSize > 0); + Verify(stringLength == strlen(stringText)); + } + return true; + } + + CStringRepresentation CStringRepresentation::operator = (const CStringRepresentation &str) + { + Check(this); + + if (this == &str) + return *this; + + if (stringText != NULL) + { + #if DEBUG_LEVEL>0 + memset(stringText, DELETE_FILL_CHAR, stringSize); + #endif + Unregister_Pointer(stringText); + delete[] stringText; + } + + Check(&str); + stringLength = str.stringLength; + stringSize = str.stringSize; + + if (stringSize == 0) + stringText = NULL; + else + { + stringText = new char[stringSize]; + Register_Pointer(stringText); + Mem_Copy(stringText, str.stringText, stringLength + 1, stringSize); + } + + return *this; + } + + CStringRepresentation CStringRepresentation::operator = (const char *cstr) + { + Check(this); + + if (stringText != NULL) + { + #if DEBUG_LEVEL>0 + memset(stringText, DELETE_FILL_CHAR, stringSize); + #endif + Unregister_Pointer(stringText); + delete[] stringText; + } + + if ((cstr == NULL) || (cstr[0] == '\x00')) + { + stringLength = 0; + stringSize = 0; + stringText = NULL; + } + else + { + stringLength = strlen(cstr); + stringSize = CalculateSize(stringLength); + + stringText = new char[stringSize]; + Register_Pointer(stringText); + Mem_Copy(stringText, cstr, stringLength + 1, stringSize); + } + + return *this; + } + + CStringRepresentation operator + (const CStringRepresentation &str1, const CStringRepresentation &str2) + { + Check(&str1); + Check(&str2); + + CStringRepresentation temp; + + unsigned long totalLen = str1.stringLength + str2.stringLength; + + if (totalLen == 0) + return temp; + + temp.stringLength = 0; + temp.stringSize = CStringRepresentation::CalculateSize((size_t)totalLen); + temp.stringText = new char[temp.stringSize]; + Register_Pointer(temp.stringText); + + Verify(temp.stringSize >= 1); + temp.stringText[0] = '\000'; + + if (str1.stringText != NULL) + { + Mem_Copy(temp.stringText, str1.stringText, str1.stringLength, temp.stringSize); + temp.stringLength = str1.stringLength; + } + + if (str2.stringText != NULL) + { + Verify(temp.stringLength < temp.stringSize); + Mem_Copy(&temp.stringText[temp.stringLength], str2.stringText, str2.stringLength + 1, temp.stringSize - temp.stringLength); + temp.stringLength += str2.stringLength; + } + + Check(&temp); + return temp; + } + + CStringRepresentation operator + (const CStringRepresentation &str, char ch) + { + Check(&str); + + CStringRepresentation temp; + + if (str.stringText == NULL) + { + temp.stringLength = 1; + temp.stringSize = CStringRepresentation::allocationIncrement; + temp.stringText = new char [temp.stringSize]; + Register_Pointer(temp.stringText); + + Verify(temp.stringSize >= 2); + temp.stringText[0] = ch; + temp.stringText[1] = '\000'; + } + else + { + Verify(str.stringLength != UINT_MAX); + + temp.stringLength = str.stringLength + 1; + + if (temp.stringLength == str.stringSize) + temp.stringSize = str.stringSize + CStringRepresentation::allocationIncrement; + else + temp.stringSize = str.stringSize; + + temp.stringText = new char[temp.stringSize]; + Register_Pointer(temp.stringText); + Mem_Copy(temp.stringText, str.stringText, str.stringLength, temp.stringSize); + + Verify(str.stringLength < temp.stringSize); + Verify(temp.stringLength < temp.stringSize); + temp.stringText[str.stringLength] = ch; + temp.stringText[temp.stringLength] = '\000'; + } + + Check(&temp); + return temp; + } + + int CStringRepresentation::Compare(const CStringRepresentation &str) const + { + Check(this); + Check(&str); + + // handle special cases where one string is empty + if (stringText == NULL) + { + if (str.stringText == NULL) + return 0; + else + return -1; + } + if (str.stringText == NULL) + return 1; + + return strcmp(stringText, str.stringText); + } + + CStringRepresentation CStringRepresentation::GetNthToken(size_t nth_token, char *delimiters) const + { + Check(this); + + // + // Which delimters to use + // + char *delimter_string = " \t,"; + + if (delimiters != NULL) + delimter_string = delimiters; + Check_Pointer(delimter_string); + + // + // Make temporary + // + CStringRepresentation temp(*this); + + if (temp.stringText == NULL) + return temp; + + // + // Parse string with strtok + // + size_t i; + char *ptr; + + Check_Pointer(temp.stringText); + ptr = strtok(temp.stringText, delimter_string); + for (i = 0; i < nth_token; i++) + if ((ptr = strtok(NULL, delimter_string)) == NULL) + break; + + if (ptr == NULL) + { + CStringRepresentation null_return; + return null_return; + } + CStringRepresentation token_return(ptr); + return token_return; + } + + #if 0 + void CStringRepresentation::ToUpper() + { + Check(this); + if (stringText != NULL) + strupr(stringText); + } + + void CStringRepresentation::ToLower() + { + Check(this); + if (stringText != NULL) + strlwr(stringText); + } + #endif + + MemoryStream& MemoryStream_Read(MemoryStream *stream, CStringRepresentation *str) + { + Check(stream); + Check(str); + + size_t string_length; + char *ptr; + + MemoryStream_Read(stream, &string_length); + ptr = new char[string_length + 1]; + Register_Pointer(ptr); + stream->ReadBytes(ptr, string_length + 1); + + *str = ptr; + + Unregister_Pointer(ptr); + delete[] ptr; + + Check(str); + return *stream; + } + + MemoryStream& MemoryStream_Write(MemoryStream *stream, const CStringRepresentation &str) + { + Check(stream); + Check(&str); + + MemoryStream_Write(stream, &str.stringLength); + return stream->WriteBytes(str.stringText, str.stringLength + 1); + } + + void Convert_From_Ascii(const char *str, CStringRepresentation *value) + { + #if 0 + Check_Pointer(str); + Check(value); + *value = str; + #else + if (str == NULL) + Fail("Convert_From_Ascii - str == NULL"); + if (value == NULL) + Fail("Convert_From_Ascii - value == NULL"); + *value = str; + #endif + } + + CString CString::operator = (const CString &str) + { + Check(this); + Check(&str); + + if (this == &str) + return *this; + + Check(representation); + representation->DecrementReferenceCount(); + representation = str.representation; + representation->IncrementReferenceCount(); + return *this; + } + + CString CString::operator = (const char *cstr) + { + Check(representation); + representation->DecrementReferenceCount(); + representation = new CStringRepresentation(cstr); + Register_Object(representation); + representation->IncrementReferenceCount(); + return *this; + } + + MemoryStream& MemoryStream_Read(MemoryStream *stream, CString *str) + { + Check(str); + Check(str->representation); + str->representation->DecrementReferenceCount(); + str->representation = new CStringRepresentation; + Register_Object(str->representation); + str->representation->IncrementReferenceCount(); + Verify(str->representation->referenceCount == 1); + return MemoryStream_Read(stream, str->representation); + } + + void Convert_From_Ascii(const char *str, CString *value) + { + Check(value); + Check(value->representation); + value->representation->DecrementReferenceCount(); + value->representation = new CStringRepresentation; + Register_Object(value->representation); + value->representation->IncrementReferenceCount(); + Verify(value->representation->referenceCount == 1); + Convert_From_Ascii(str, value->representation); + } +//} + +#if defined(TEST_CLASS) + #include "cstr.tcp" +#endif + diff --git a/MUNGA/CSTR.h b/MUNGA/CSTR.h new file mode 100644 index 0000000..342223a --- /dev/null +++ b/MUNGA/CSTR.h @@ -0,0 +1,644 @@ +#pragma once + +#include "style.h" + +//namespace Munga +//{ + class CStringRepresentation; + class CString; + + class MemoryStream; + + class StringRepresentation; + class pString; + class pcString; + typedef StringRepresentation& rString; + typedef const StringRepresentation& rcString; + + class StringRepresentation + { + private: + char firstByte; + + StringRepresentation(); + StringRepresentation(rcString string); + + public: + const char& operator[](size_t index) const + { + Check(this); + return (&firstByte)[index]; + } + + char& operator[](size_t index) + { + Check(this); + return (&firstByte)[index]; + } + + operator const char*() const + { + Check(this); + return &firstByte; + } + operator char*() + { + Check(this); + return &firstByte; + } + + size_t GetLength() const + { + Check(this); + return strlen(&firstByte); + } + + public: + rString operator=(const char* string) + { + Check(this); + Check_Pointer(string); + strcpy(&firstByte, string); + return *this; + } + + rString operator=(rcString string) + { + Check(this); + Check(&string); + strcpy(&firstByte, &string.firstByte); + return *this; + } + + rString operator=(char byte) + { + Check(this); + firstByte = byte; + return *this; + } + + rString operator+=(const char* string) + { + Check(this); + Check_Pointer(string); + strcat(&firstByte, string); + return *this; + } + + rString operator+=(char chr); + + public: + int Compare(const char *string) const { return strcmp(&firstByte, string); } + + int Compare(const char *string, size_t length) const { return strncmp(&firstByte, string, length); } + + int CaselessCompare(const char *string) const { return stricmp(&firstByte, string); } + + int CaselessCompare(const char *string, size_t length) const { return strnicmp(&firstByte, string, length); } + + Logical operator<(const char* string) const { return Compare(string) < 0; } + Logical operator<=(const char* string) const { return Compare(string) <= 0; } + Logical operator>(const char* string) const { return Compare(string) > 0; } + Logical operator>=(const char* string) const { return Compare(string) >= 0; } + Logical operator==(const char* string) const { return Compare(string) == 0; } + Logical operator!=(const char* string) const { return Compare(string) != 0; } + + Logical operator<(char chr) const { return firstByte < chr; } + Logical operator<=(char chr) const { return firstByte <= chr; } + Logical operator>(char chr) const { return firstByte > chr; } + Logical operator>=(char chr) const { return firstByte >= chr; } + Logical operator==(char chr) const { return firstByte == chr; } + Logical operator!=(char chr) const { return firstByte != chr; } + + public: + friend std::ostream& operator <<(std::ostream &strm, rcString str) { return strm << &str.firstByte; } + friend MemoryStream& MemoryStream_Read(MemoryStream* stream, StringRepresentation *str); + friend MemoryStream& MemoryStream_Write(MemoryStream* stream, const StringRepresentation *str); + + public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const StringRepresentation *p); + #endif + + Logical TestInstance() const { return true; } + }; + + class pString SIGNATURED + { + friend class pcString; + + protected: + StringRepresentation* stringText; + + public: + pString(char *string = NULL) { stringText = (StringRepresentation*)string; } + pString(rString string) { stringText = &string; } + pString(const pString& string) { stringText = string.stringText; } + + public: + pString& operator= (char *string) + { + stringText = (StringRepresentation*)string; + return *this; + } + + pString& operator= (rString string) + { + stringText = &string; + return *this; + } + + pString& operator= (const pString& string) + { + stringText = string.stringText; + return *this; + } + + public: + pString& operator++() + { + ++SKIPPY_CAST(char*, stringText); + return *this; + } + + pString operator++(int) { return pString(SKIPPY_CAST(char*,stringText)++); } + + pString& operator--() + { + --SKIPPY_CAST(char*,stringText); + return *this; + } + + pString operator--(int) { return pString(SKIPPY_CAST(char*, stringText)--); } + + public: + rString operator*() const { return *stringText; } + StringRepresentation* operator->() const { return stringText; } + + char& operator[](size_t index) const + { + Check(this); + return (*stringText)[index]; + } + + operator char*() const + { + Check(this); + return (char*)stringText; + } + + Logical operator!() const { return !stringText; } + + char** GetTextPtr() { return (char**)&stringText; } + + public: + friend MemoryStream& MemoryStream_Read(MemoryStream* stream, pString str) { return MemoryStream_Read(stream, str.stringText); } + + public: + Logical TestInstance() const { return true; } + }; + + class pcString SIGNATURED + { + protected: + const StringRepresentation* stringText; + + public: + pcString(const char *string = NULL) { stringText = (const StringRepresentation*)string; } + pcString(rcString string) { stringText = &string; } + pcString(const pString& string) { stringText = string.stringText; } + pcString(const pcString& string) { stringText = string.stringText; } + + public: + pcString& operator=(const char *string) + { + stringText = (const StringRepresentation*)string; + return *this; + } + pcString& operator=(rcString string) + { + stringText = &string; + return *this; + } + pcString& operator=(const pString& string) + { + stringText = string.stringText; + return *this; + } + pcString& operator=(const pcString& string) + { + stringText = string.stringText; + return *this; + } + + public: + pcString& operator++() + { + ++SKIPPY_CAST(const char*, stringText); + return *this; + } + pcString operator++(int) { return pcString(SKIPPY_CAST(const char*, stringText)++); } + pcString& operator--() + { + --SKIPPY_CAST(const char*, stringText); + return *this; + } + pcString operator--(int) { return pcString(SKIPPY_CAST(const char*, stringText)--); } + + public: + rcString operator*() const { return *stringText; } + const StringRepresentation* operator->() const { return stringText; } + + const char& operator[](size_t index) const + { + Check(this); + return (*stringText)[index]; + } + + operator const char*() const + { + Check(this); + return (const char*)stringText; + } + Logical operator!() const { return !stringText; } + + const char** GetTextPtr() { return (const char**)&stringText; } + + public: + Logical TestInstance() const { return true; } + }; + + void Convert_From_Ascii(const char* str, char* value); + void Convert_From_Ascii(const char* str, Byte* value); + void Convert_From_Ascii(const char* str, short* value); + void Convert_From_Ascii(const char* str, Word* value); + void Convert_From_Ascii(const char* str, int* value); + void Convert_From_Ascii(const char* str, unsigned* value); + void Convert_From_Ascii(const char* str, long* value); + void Convert_From_Ascii(const char* str, LWord* value); + + class CStringRepresentation SIGNATURED + { + friend CString; + + friend CString operator + (const CString &str1, const CString &str2); + friend CString operator + (const CString &str1, char ch); + friend MemoryStream& MemoryStream_Read(MemoryStream* stream, CString *str); + friend void Convert_From_Ascii(const char *str, CString *value); + + friend CStringRepresentation operator + (const CStringRepresentation &str1, const CStringRepresentation &str2); + friend CStringRepresentation operator + (const CStringRepresentation &str1, char ch); + + private: + CStringRepresentation(); + CStringRepresentation(const CStringRepresentation &str); + CStringRepresentation(const char *cstr); + + public: + ~CStringRepresentation(); + + Logical TestInstance() const; + + private: + size_t Length() const; + size_t Size() const; + + private: + operator char*() const; + + CStringRepresentation operator = (const CStringRepresentation &str); + CStringRepresentation operator = (const char *cstr); + + void operator += (const CStringRepresentation &str); + void operator += (char ch); + + int Compare(const CStringRepresentation &str) const; + + int operator < (const CStringRepresentation &str) const; + int operator > (const CStringRepresentation &str) const; + int operator <= (const CStringRepresentation &str) const; + int operator >= (const CStringRepresentation &str) const; + int operator == (const CStringRepresentation &str) const; + int operator != (const CStringRepresentation &str) const; + + char operator [] (size_t pos) const; + + CStringRepresentation GetNthToken(size_t nth_token, char *delimiters = NULL) const; + + #if 0 + void ToUpper(); + void ToLower(); + #endif + + friend std::ostream& operator << (std::ostream &strm, const CStringRepresentation &str); + + friend MemoryStream& MemoryStream_Read(MemoryStream* stream, CStringRepresentation *str); + + friend MemoryStream& MemoryStream_Write(MemoryStream* stream, const CStringRepresentation& str); + + friend void Convert_From_Ascii(const char *str, CStringRepresentation *value); + + private: + void IncrementReferenceCount(); + + void DecrementReferenceCount(); + + private: + static size_t allocationIncrement; + + static size_t CalculateSize(size_t needed); + + size_t stringSize; + size_t stringLength; + char *stringText; + + int referenceCount; + }; + + inline size_t CStringRepresentation::Length() const + { + Check(this); + return stringLength; + } + + inline size_t CStringRepresentation::Size() const + { + Check(this); + return stringSize; + } + + inline CStringRepresentation::operator char *() const + { + Check(this); + return stringText; + } + + inline void CStringRepresentation::operator += (const CStringRepresentation &str) + { + Check(this); + *this = *this + str; + } + + inline void CStringRepresentation::operator +=(char ch) + { + Check(this); + *this = *this + ch; + } + + inline int CStringRepresentation::operator <(const CStringRepresentation &str) const + { + return (Compare(str) < 0); + } + + inline int CStringRepresentation::operator >(const CStringRepresentation &str) const + { + return (Compare(str) > 0); + } + + inline int CStringRepresentation::operator <=(const CStringRepresentation &str) const + { + return !(Compare(str) > 0); + } + + inline int CStringRepresentation::operator >=(const CStringRepresentation &str) const + { + return !(Compare(str) < 0); + } + + inline int CStringRepresentation::operator ==(const CStringRepresentation &str) const + { + return (Compare(str) == 0); + } + + inline int CStringRepresentation::operator !=(const CStringRepresentation &str) const + { + return (Compare(str) != 0); + } + + inline char CStringRepresentation::operator [](size_t pos) const + { + Check(this); + return (pos >= stringLength) ? ('\x00') : (stringText[pos]); + } + + inline std::ostream& operator << (std::ostream &strm, const CStringRepresentation &str) + { + Check(&str); + strm << str.stringText; + return strm; + } + + inline void CStringRepresentation::IncrementReferenceCount() + { + Check(this); + Verify(referenceCoutn >= 0); + referenceCount++; + } + + inline void CStringRepresentation::DecrementReferenceCount() + { + Check(this); + Verify(referenceCount > 0); + if (--referenceCount == 0) + { + Unregister_Object(this); + delete this; + } + } + + class CString SIGNATURED + { + public: + CString(); + CString(const CString &str); + CString(const char *cstr); + + ~CString(); + + Logical TestInstance() const; + static Logical TestClass(); + + public: + size_t Length() const; + size_t Size() const; + + public: + operator char*() const; + + CString operator = (const CString &str); + CString operator = (const char *cstr); + + friend CString operator + (const CString &str1, const CString &str2); + + friend CString operator + (const CString &str1, char ch); + + void operator += (const CString &str); + void operator += (char ch); + + int Compare(const CString &str) const; + + int operator < (const CString &str) const; + int operator > (const CString &str) const; + int operator <= (const CString &str) const; + int operator >= (const CString &str) const; + int operator == (const CString &str) const; + int operator != (const CString &str) const; + + char operator [] (size_t pos) const; + + CString GetNthToken(size_t nth_token, char *delimiters = NULL) const; + + friend std::ostream& operator << (std::ostream &strm, const CString &str); + + friend MemoryStream& MemoryStream_Read(MemoryStream* stream, CString *str); + friend MemoryStream& MemoryStream_Write(MemoryStream* stream, const CString* str); + friend void Convert_From_Ascii(const char *str, CString *value); + + private: + CStringRepresentation *representation; + }; + + inline CString::CString() + { + representation = new CStringRepresentation; + Register_Object(representation); + representation->IncrementReferenceCount(); + Verify(representation->referenceCount == 1); + } + + inline CString::CString(const CString &str) + { + Check(&str); + representation = str.representation; + Check(representation); + representation->IncrementReferenceCount(); + } + + inline CString::CString(const char *cstr) + { + representation = new CStringRepresentation(cstr); + Register_Object(representation); + representation->IncrementReferenceCount(); + Verify(representation->referenceCount == 1); + } + + inline CString::~CString() + { + Check(representation); + representation->DecrementReferenceCount(); + } + + inline Logical CString::TestInstance() const + { + Check(representation); + return true; + } + + inline size_t CString::Length() const + { + Check(representation); + return representation->Length(); + } + + inline size_t CString::Size() const + { + Check(representation); + return representation->Size(); + } + + inline CString::operator char *() const + { + Check(representation); + return representation->stringText; + } + + inline CString operator + (const CString &str1, const CString &str2) + { + Check(&str1); + Check(&str2); + CStringRepresentation temp = *str1.representation + *str2.representation; + return CString(temp.stringText); + } + + inline CString operator + (const CString &str1, char ch) + { + Check(&str1); + CStringRepresentation temp = *str1.representation + ch; + return CString(temp.stringText); + } + + inline void CString::operator +=(const CString &str) + { + Check(this); + Check(&str); + *this = *this + str; + } + + inline void CString::operator +=(char ch) + { + Check(this); + *this = *this + ch; + } + + inline int CString::Compare(const CString &str) const + { + Check(&str); + Check(representation); + return representation->Compare(*str.representation); + } + + inline int CString::operator <(const CString &str) const + { + return (Compare(str) < 0); + } + + inline int CString::operator >(const CString &str) const + { + return (Compare(str) > 0); + } + + inline int CString::operator <=(const CString &str) const + { + return !(Compare(str) > 0); + } + + inline int CString::operator >=(const CString &str) const + { + return !(Compare(str) < 0); + } + + inline int CString::operator ==(const CString &str) const + { + return (Compare(str) == 0); + } + + inline int CString::operator !=(const CString &str) const + { + return (Compare(str) != 0); + } + + inline char CString::operator [](size_t pos) const + { + Check(representation); + return (*representation)[pos]; + } + + inline CString CString::GetNthToken(size_t nth_token, char *delimiters) const + { + Check(representation); + CStringRepresentation temp = representation->GetNthToken(nth_token, delimiters); + return CString(temp.stringText); + } + + inline std::ostream& operator << (std::ostream &strm, const CString &str) + { + Check(&str); + strm << *str.representation; + return strm; + } + + inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const CString* str) + { + return MemoryStream_Write(stream, *str->representation); + } +//} \ No newline at end of file diff --git a/MUNGA/CULTURAL.cpp b/MUNGA/CULTURAL.cpp new file mode 100644 index 0000000..aa6675f --- /dev/null +++ b/MUNGA/CULTURAL.cpp @@ -0,0 +1,1073 @@ +#include "munga.h" +#pragma hdrstop + +#include "cultural.h" +#include "terrain.h" +#include "fileutil.h" +#include "boxtree.h" +#include "boxsolid.h" +#include "scnrole.h" +#include "mission.h" +#include "explode.h" +#include "app.h" +#include "interest.h" +#include "hostmgr.h" +#include "nttmgr.h" +#include "namelist.h" +#include "console.h" + +//########################################################################## +//##################### Class CulturalIcon ########################## +//########################################################################## + +//############################################################################# +// Shared Data Support +// +Derivation* CulturalIcon::GetClassDerivations() +{ static Derivation classDerivations(UnscalableTerrain::GetClassDerivations(), "CulturalIcon"); + return &classDerivations; +} + + +CulturalIcon::SharedData + CulturalIcon::DefaultData( + CulturalIcon::GetClassDerivations(), + CulturalIcon::GetMessageHandlers(), + CulturalIcon::GetAttributeIndex(), + CulturalIcon::StateCount, + (UnscalableTerrain::MakeHandler)CulturalIcon::Make + ); +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + CulturalIcon::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CulturalIcon, TakeDamage), + MESSAGE_ENTRY(CulturalIcon, SetBurningState) +}; + +CulturalIcon::MessageHandlerSet& CulturalIcon::GetMessageHandlers() +{ + static CulturalIcon::MessageHandlerSet messageHandlers(ELEMENTS(CulturalIcon::MessageHandlerEntries), CulturalIcon::MessageHandlerEntries, UnscalableTerrain::GetMessageHandlers()); + return messageHandlers; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + + +void + CulturalIcon::SetBurningStateMessageHandler(Message * /*burning_message*/) +{ + + SetSimulationState(CulturalIcon::BurningState); + ForceUpdate(DefaultUpdateModelFlag); + AlwaysExecute(); + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CulturalIcon::TakeDamageMessageHandler(TakeDamageMessage *damage_message) +{ + Check(damage_message); + + + if (damage_message->damageZone == -1 ) + { + damage_message->damageZone = 0; + } + + if (GetSimulationState() == CulturalIcon::DefaultState) + { + // + //~~~~~~~~~~~~~~~~~~ + // Update Replicants + //~~~~~~~~~~~~~~~~~~ + // + if (GetInstance() != ReplicantInstance) + { + ForceUpdate(DamageZoneUpdateModelFlag | DefaultUpdateModelFlag); + AlwaysExecute(); + } + // + //~~~~~~~~~~~~~~~~~~~~~ + // Call Derived Classes + //~~~~~~~~~~~~~~~~~~~~~ + // + UnscalableTerrain::TakeDamageMessageHandler(damage_message); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update Collision Volumes if we died + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + + for(int ii=0;iiGetDamageZoneState() == DamageZone::BurningState) + { + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the explosion + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Origin explode_origin = localOrigin; + + ResourceDescription::ResourceID explosion_ID; + + if ((damage_message->damageData.damageType == Damage::CollisionDamageType )&& + (crunchExplosionResourceID != -1)) + { + explosion_ID = crunchExplosionResourceID; + } + else + { + explosion_ID = explosionResourceID; + } + + Explosion::MakeMessage exp_message( + Explosion::MakeMessageID, + sizeof(Explosion::MakeMessage), + RegisteredClass::ExplosionClassID, + EntityID::Null, + explosion_ID, + Explosion::DefaultFlags, + explode_origin, + GetEntityID(), + GetEntityID() + ); + + #if (DEBUG_LEVEL > 0) + Explosion *new_exp = + #endif + Explosion::Make(&exp_message); + Register_Object(new_exp); + + Message dummy_message(SetBurningStateMessageID, sizeof(Message)); + Check(application); + Time now = Now(); + now += timeDelay; + application->Post(CreationEventPriority, this, &dummy_message, now); + + SetSimulationState(WaitingToBurn); + + UpdateCollisionVolumes(); + break; + } + } + } + Check_Fpu(); +} + + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CulturalIcon::UpdateCollisionVolumes() +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Tree for these Collision Volumes + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + InterestManager *interest_mgr = + application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = + interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update Volumes based on RemoveVolume Flag + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + BoxedSolid *box = collisionVolumes; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + if (RemoveCollisionVolumeOnDeath()) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Delete the Collision Volume + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + tree->Remove(box); + Unregister_Object(box); + delete box; + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~ + // Move Collision Volume + //~~~~~~~~~~~~~~~~~~~~~~ + // + box->minY += destroyedYTranslation; + box->maxY += destroyedYTranslation; + } + box = next_box; + } + collisionVolumes = NULL; + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const CulturalIcon::IndexEntry + CulturalIcon::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(CulturalIcon, TeamName, teamName) +}; + +CulturalIcon::AttributeIndexSet& CulturalIcon::GetAttributeIndex() +{ + static CulturalIcon::AttributeIndexSet attributeIndex(ELEMENTS(CulturalIcon::AttributePointers), + CulturalIcon::AttributePointers, + UnscalableTerrain::GetAttributeIndex() + ); + return attributeIndex; +} +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CulturalIcon::CulturalIcon( + MakeMessage *creation_message, + SharedData &shared_data +) : + UnscalableTerrain(creation_message, shared_data) +{ + + Str_Copy(teamName, "Defualt", sizeof(teamName)); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the ModelResource Information + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *res = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + ModelResource* model_resource = (ModelResource*)res->resourceAddress; + Check_Pointer(model_resource); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Determine if we move or Destroy the + // Collision volume in Death of the map entity + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (model_resource->sinkCollisionVolume) + { + destroyedYTranslation = model_resource->destroyedYTranslation; + } + else + { + destroyedYTranslation = 0.0f; + SetRemoveCollisionVolumeFlag(); + } + + timeDelay = model_resource->timeDelay; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Is Stopping Collision Volume ? + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (model_resource->stoppingCollisionVolume) + { + SetStoppingCollisionVolumeFlag(); + } + + explosionResourceID = model_resource->explosionResourceID; + crunchExplosionResourceID = model_resource->crunchExplosionResourceID; + res->Unlock(); + + //DEBUG_STREAM << model_resource->crunchExplosionResourceID << std::endl << std::flush; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in DamageZone Information from the Resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *dmg_res = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::DamageZoneStreamResourceType + ); + Check(dmg_res); + dmg_res->Lock(); + DynamicMemoryStream damage_stream ( + dmg_res->resourceAddress, + dmg_res->resourceSize + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // skip over DamageZoneCount + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + damage_stream.AdvancePointer(sizeof(damageZoneCount)); + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Create the DamageZones + //~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;iiUnlock(); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + + + +void + CulturalIcon::ReadUpdateRecord(Simulation::UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + + UnscalableTerrain::ReadUpdateRecord(message); + + if (simulationState.GetOldState() != GetSimulationState() && (GetSimulationState() == BurningState)) + { + UpdateCollisionVolumes(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +Logical + CulturalIcon::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories +) +{ + Check(creation_message); + Check(model_file); + + if (!UnscalableTerrain::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->messageLength = sizeof(MakeMessage); + creation_message->classToCreate = CulturalIconClassID; + creation_message->instanceFlags = MasterInstance|DynamicFlag|MapFlag|TrappedFlag; + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CulturalIcon* + CulturalIcon::Make(MakeMessage *creation_message) +{ + Check_Fpu(); + return new CulturalIcon(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CulturalIcon::~CulturalIcon() +{ + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + CulturalIcon::CreateModelResource( + #if DEBUG_LEVEL>0 + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model + #else + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *, + ModelResource* model + #endif +) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Allocate memory for the resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + if ( + !model_file->GetEntry( + "gamedata", + "DestroyedYTranslation", + &local_model->destroyedYTranslation + ) + ) + { + local_model->sinkCollisionVolume = False; + local_model->destroyedYTranslation = 0.0f; + } + else + { + local_model->sinkCollisionVolume = True; + } + + if (!model_file->GetLogicalEntry( + "gamedata", + "StoppingCollisionVolume", + &local_model->stoppingCollisionVolume + ) + ) + { + local_model->stoppingCollisionVolume = False; + } + + if ( + !model_file->GetEntry( + "gamedata", + "TimeDelay", + &local_model->timeDelay + ) + ) + { + DEBUG_STREAM << model_name << " TimeDelay is missing " << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + + // + //---------------------------------------------------------------------- + // Read in the Model Filename of the Explosion renderable, then find its + // resource ID in the resource file + //---------------------------------------------------------------------- + // + const char *explosion = "Unspecified"; + if ( + !model_file->GetEntry( + "gamedata", + "ExplosionModelFile", + &explosion + ) + ) + { + std::cout << model_name << " missing ExplosionModelFile!\n"; + Check_Fpu(); + return False; + } + + + ResourceDescription *res = NULL; + + if (strcmp(explosion,"Unspecified")) + { + res = resource_file->FindResourceDescription( + explosion, + ResourceDescription::ModelListResourceType + ); + } + if (!res) + { + std::cout << model_name << " cannot find " << explosion + << " in resource file!\n"; + Check_Fpu(); + return False; + } + if (res) + { + local_model->explosionResourceID = res->resourceID; + } + + + + const char *crunch_explosion = "Unspecified"; + + model_file->GetEntry( + "gamedata", + "CrunchExplosionModelFile", + &crunch_explosion + ); + + + local_model->crunchExplosionResourceID = -1; + + if (strcmp(crunch_explosion,"Unspecified")) + { + //res = NULL; + res = resource_file->FindResourceDescription( + crunch_explosion, + ResourceDescription::ModelListResourceType + ); + + if (!res) + { + std::cout << model_name << " cannot find " << crunch_explosion + << " in resource file!\n"; + Check_Fpu(); + return False; + } + else + { + local_model->crunchExplosionResourceID = res->resourceID; + } + + + } + + //DEBUG_STREAM << ":" << local_model->crunchExplosionResourceID << std::endl << std::flush; + + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write the model to the resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + CulturalIcon::CreateDamageZoneStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .dmg file + //------------------- + // + const char* dmg_file_cname; + if ( + !model_file->GetEntry( + "gamedata", + "DamageZones", + &dmg_file_cname + ) + ) + { + std::cerr << model_name << " is missing .dmg file specification!\n"; + return -1; + } + + CString dmg_filename = + MakePathedFilename(directories->modelDirectory, dmg_file_cname); + + NotationFile *dmg_file = new NotationFile(dmg_filename); + Register_Object(dmg_file); + int page_count = dmg_file->PageCount(); + if (!page_count) + { + std::cerr << dmg_filename << " is empty or missing!\n"; + Unregister_Object(dmg_file); + delete dmg_file; + return -1; + } + + DynamicMemoryStream damage_stream; + + damage_stream << page_count; + NameList *dmg_namelist = dmg_file->MakePageList(); + Register_Object(dmg_namelist); + + NameList::Entry *dmg_entry = dmg_namelist->GetFirstEntry(); + + CString dmg_page_name; + while(dmg_entry) + { + dmg_page_name = dmg_entry->GetName(); + DamageZone::CreateStreamedDamageZone( + model_file, + model_name, + NULL, + dmg_page_name, + &damage_stream, + dmg_file, + directories + ); + dmg_entry = dmg_entry->GetNextEntry(); + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Add Stream to Resource + //~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *new_res = + resource_file->AddResourceMemoryStream( + model_name, + ResourceDescription::DamageZoneStreamResourceType, + 1, + ResourceDescription::Preload, + &damage_stream + ); + Check(new_res); + + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dmg_namelist); + delete dmg_namelist; + + return new_res->resourceID; +} + +//########################################################################## +//#################### Class Landmark ########################## +//########################################################################## + +//############################################################################# +// Shared Data Support +// +Derivation* Landmark::GetClassDerivations() +{ static Derivation classDerivations(CulturalIcon::GetClassDerivations(), "Landmark"); + return &classDerivations; +} + + +Landmark::SharedData + Landmark::DefaultData( + Landmark::GetClassDerivations(), + Landmark::MessageHandlers, + Landmark::GetAttributeIndex(), + Landmark::StateCount, + (Landmark::MakeHandler)Landmark::Make + ); +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Landmark::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Landmark, TakeDamage) +}; + +Landmark::MessageHandlerSet + Landmark::MessageHandlers( + ELEMENTS(Landmark::MessageHandlerEntries), + Landmark::MessageHandlerEntries, + CulturalIcon::GetMessageHandlers() + ); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Landmark::TakeDamageMessageHandler(TakeDamageMessage *damage_message) +{ + Check(damage_message); + + if (owningTeam == NULL) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the owning team pointer + // with the Teams entity Group + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application); + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *team_group = entity_manager->UseGroup("Teams"); + if (team_group) + { + ChainIteratorOf team_iterator(team_group->groupMembers); + Team *current_team; + while((current_team = (Team*) team_iterator.ReadAndNext() ) != NULL) + { + if (!strcmp(current_team->teamName, teamName)) + { + owningTeam = current_team; + break; + } + } + } + } + + + + if (owningTeam == NULL) + { + DEBUG_STREAM << "TEAM : '" << teamName << "' was never found! " << std::endl << std::flush; + exit (-1); + } + + + if (GetSimulationState() != BurningState) + { + CulturalIcon::TakeDamageMessageHandler(damage_message); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Calculate the Score Loss based + // on the Scenario Data + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(scenarioRole); + #if 0 + Logical landmark_destroyed = GetSimulationState() == BurningState; + Scalar score_loss = scenarioRole->CalcDamageReceivedScore( + damage_message->damageData.damageAmount + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Tell the Console about the Damage + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + + if (console_host) + { + Check(console_host); + ConsoleLandmarkDamagedMessage landmark_damaged_message( + damage_message->inflictingEntity.GetHostID(), + landmarkID, + damage_message->damageData.damageAmount, + landmark_destroyed, + score_loss + ); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &landmark_damaged_message + ); + } + #endif + } +} + +Logical + CulturalIcon::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Landmark::Landmark( + MakeMessage *creation_message, + SharedData &shared_data +) : + CulturalIcon ( creation_message, shared_data) +{ + scenarioRole = NULL; + owningTeam = NULL; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the owning team pointer + // with the Teams entity Group + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application); + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *team_group = entity_manager->UseGroup("Teams"); + if (team_group) + { + ChainIteratorOf team_iterator(team_group->groupMembers); + Team *current_team; + while((current_team = (Team*) team_iterator.ReadAndNext() ) != NULL) + { + if (!strcmp(current_team->teamName, creation_message->teamName)) + { + owningTeam = current_team; + break; + } + } + } + + // + // If the team is null, that's ok. It will either show up over the network + // or be a free for all + // + + + Str_Copy(teamName, creation_message->teamName, sizeof(teamName)); + + + Check(application->GetCurrentMission()); + scenarioRole = + application->GetCurrentMission()->GetScenarioRole(creation_message->roleName); + if (!scenarioRole) + { + + scenarioRole = new ScenarioRole("Role::MapAssigned",creation_message->roleName); + Register_Object(scenarioRole); + application->GetCurrentMission()->AddScenarioRole(scenarioRole); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Add this landmark to the Landmark Entity Group + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + EntityGroup *landmark_group = entity_manager->UseGroup("Landmarks"); + Check(landmark_group); + landmark_group->Add(this); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Landmark::~Landmark() +{ + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Landmark::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories +) +{ + Check(creation_message); + Check(model_file); + + if (!CulturalIcon::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->messageLength = sizeof(MakeMessage); + creation_message->classToCreate = LandmarkClassID; + + char *p; + + // + //---------------------------- + // landmarkID allocated + // by map stream creation + //---------------------------- + // + + // + //~~~~~~~~~~~~~~~ + // Get the teamName + //~~~~~~~~~~~~~~~ + // + if ((p = strtok(NULL, ",")) == NULL) + { + std::cerr << "teamName missing!\n"; + return False; + } + Str_Copy(creation_message->teamName,p, sizeof(creation_message->teamName)); + + + // + //~~~~~~~~~~~~~~~~~ + // Get the roleName + //~~~~~~~~~~~~~~~~~ + // + if ((p = strtok(NULL, ",")) == NULL) + { + std::cerr << "roleName missing!\n"; + return False; + } + Str_Copy(creation_message->roleName,p, sizeof(creation_message->roleName)); + + + // + //~~~~~~~~~~~~~~~~~~~~~~ + // Get the Landmark Name + //~~~~~~~~~~~~~~~~~~~~~~ + // + if ((p = strtok(NULL, ",")) == NULL) + { + std::cerr << "Landmark Name missing!\n"; + return False; + } + Str_Copy(creation_message->landmarkName,p, sizeof(creation_message->landmarkName)); + + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Landmark* + Landmark::Make(MakeMessage *creation_message) +{ + Check_Fpu(); + return new Landmark(creation_message); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + Landmark::CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model +) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + + CulturalIcon::CreateModelResource(resource_file, model_name, model_file, directories, model); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Allocate memory for the resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + +#if 0 + const char *role_model_file; + if (!model_file->GetEntry( + "gamedata", + "RoleModelFile", + &role_model_file + ) + ) + { + std::cerr<FindResourceDescription( + role_model_file, + ResourceDescription::ModelListResourceType + ); + if (!res) + { + std::cout << model_name << " cannot find " << role_model_file + << " in resource file!\n"; + goto Dump_And_Die; + } + local_model->roleResourceID = res->resourceID; + } +#endif + + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write the model to the resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} + +Logical + Landmark::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/DAMAGE.cpp b/MUNGA/DAMAGE.cpp new file mode 100644 index 0000000..6e69f89 --- /dev/null +++ b/MUNGA/DAMAGE.cpp @@ -0,0 +1,800 @@ +#include "munga.h" +#pragma hdrstop + +#include "segment.h" +#include "exptbl.h" +#include "fileutil.h" +#include "jmover.h" +#include "schain.h" +#include "notation.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MaterialList::MaterialList() : + materialList(NULL) +{ + listIterator = new CStringSocketIterator(materialList); + Register_Object(listIterator); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MaterialList::~MaterialList() +{ + DeletePlugs(); + + Unregister_Object(listIterator); + delete listIterator; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Damage::Damage() +{ + damageAmount = 0.0f; + damageForce = Vector3D::Identity; + surfaceNormal.x = 0.0f; + surfaceNormal.y = 1.0f; + surfaceNormal.z = 0.0f; + impactPoint = Point3D::Identity; + burstCount = 1.0f; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +EntitySegment* + DamageZone::GetCurrentEffectSite(Enumeration effect_site_type) +{ + Check(this); + EntitySegment *return_segment; + switch(effect_site_type) + { +Return_Default_Effect: + case DefaultEffectSite: + default: + { + SChainIteratorOf iterator(defaultEffectSiteChain); + Check(iterator.GetCurrent()); + return iterator.GetCurrent(); + } + case InternalVideoEffectSite: + { + SChainIteratorOf iterator(internalVideoEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + case ExternalVideoEffectSite: + { + SChainIteratorOf iterator(externalVideoEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + case InternalAudioEffectSite: + { + SChainIteratorOf iterator(internalAudioEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + case ExternalAudioEffectSite: + { + SChainIteratorOf iterator(externalAudioEffectSiteChain); + return_segment = iterator.GetCurrent(); + if (return_segment) + { + Check(return_segment); + return return_segment; + } + else + { + goto Return_Default_Effect; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::Reset(Logical ) +{ + SetDamageZoneState(DefaultState); + damageZoneGraphicState.SetState(ExistsGraphicState); + damageLevel = 0.0f; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::WriteUpdateRecord(UpdateRecord *update_record) +{ + Check(this); + Check_Pointer(update_record); + update_record->damageLevel = damageLevel; + update_record->damageZoneState = damageZoneState.GetState(); + update_record->damageZoneGraphicState = damageZoneGraphicState.GetState(); + update_record->damageZoneIndex = damageZoneIndex; + update_record->changedFlags = changedFlags; + update_record->recordLength = sizeof(*update_record); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Clear Flags here for MasterInstance DamageZones! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResetChangedFlags(); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::ReadUpdateRecord(UpdateRecord *update_record) +{ + Check(this); + Check_Pointer(update_record); + Verify(damageZoneIndex == update_record->damageZoneIndex); + + damageLevel = update_record->damageLevel; + damageZoneState.SetState(update_record->damageZoneState); + damageZoneGraphicState.SetState(update_record->damageZoneGraphicState); + changedFlags = update_record->changedFlags; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DamageZone::DamageZone(Simulation *owner, int damage_zone_index) : + Node(DamageZoneClassID), + materialTable(NULL, False), + damageZoneState(DamageStateCount), + damageZoneGraphicState(GraphicStateCount), + defaultEffectSiteChain(NULL), + internalVideoEffectSiteChain(NULL), + externalVideoEffectSiteChain(NULL), + internalAudioEffectSiteChain(NULL), + externalAudioEffectSiteChain(NULL) +{ + Check(owner); + damageZoneIndex = damage_zone_index; + owningSimulation = owner; + damageLevel = 0.0f; + explosionTable = NULL; + for(int ii=0;ii> damageZoneName; + + if (owningSimulation->IsDerivedFrom(*JointedMover::GetClassDerivations())) + { + JointedMover *jointed_mover = Cast_Object( + JointedMover*, + owningSimulation + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in all Effect Sites + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int effect_site_count; + int effect_site_index; + EntitySegment *effect_site_segment; + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Read in External Video + //~~~~~~~~~~~~~~~~~~~~~~~ + // + for (int jj=0;jj> effect_site_count; + for(int ii=0;ii> effect_site_index; + effect_site_segment = jointed_mover->GetSegment(effect_site_index); + Check(effect_site_segment); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Add the Segment to the Appropriate Chain + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + switch (jj) + { + case DefaultEffectSite: + defaultEffectSiteChain.Add(effect_site_segment); + break; + case ExternalVideoEffectSite : + externalVideoEffectSiteChain.Add(effect_site_segment); + break; + case InternalVideoEffectSite : + internalVideoEffectSiteChain.Add(effect_site_segment); + break; + case ExternalAudioEffectSite : + externalAudioEffectSiteChain.Add(effect_site_segment); + break; + case InternalAudioEffectSite : + internalAudioEffectSiteChain.Add(effect_site_segment); + break; + + } + } + } + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in these for consistancy + // and for later improvements for + // not Jointed Mover Objects! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int filler_int; + for (int jj=0;jj> filler_int; + } + } + + *stream >> defaultArmorPoints; + + int ii; + for (ii=0; ii> damageScale[ii]; + } + + int skeleton_count; + EntitySegment::SkeletonType skl_type; + + *stream >> skeleton_count; + + for(ii=0;ii> skl_type; + + int material_count; + *stream >> material_count; + if(!material_count) + { + continue; + } + MaterialList *material_list = new MaterialList; + Register_Object(material_list); + for(int jj=0;jj> new_material; + MaterialList::CStringPlug *new_plug = + new MaterialList::CStringPlug(new_material); + Register_Object(new_plug); + material_list->Add(new_plug); + } + material_list->First(); + materialTable.AddValue(material_list, skl_type); + } + + changedFlags = 0; + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DamageZone::~DamageZone() +{ + MaterialTableIterator iterator(materialTable); + iterator.DeletePlugs(); + + if (explosionTable) + { + Unregister_Object(explosionTable); + delete explosionTable; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExplosionTable* + DamageZone::CreateExplosionTable(MemoryStream *explosion_stream) +{ + Check(this); + explosionTable = new ExplosionTable(explosion_stream); + Register_Object(explosionTable); + Check_Fpu(); + return explosionTable; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DamageZone::TakeDamage(Damage &damage) +{ + Check(this); + Check_Pointer(&damage); + + damageLevel += damage.damageAmount * damageScale[damage.damageType]; + Clamp(damageLevel, 0.0f, 1.0f); + SetDamageLevelChangedFlag(); + if (damageLevel >= 1.0f) + { + SetDamageZoneState(BurningState); + SetGraphicState(DestroyedGraphicState); + SetGraphicStateChangedFlag(); + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DamageZone::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DamageZone::CreateStreamedDamageZone( + NotationFile *model_file, + const char *, + NotationFile *skl_file, + CString damage_zone_name, + MemoryStream *damage_zone_stream, + NotationFile *dmg_file, + const ResourceDirectories *directories + ) +{ + Check_Pointer(damage_zone_name); + Check_Pointer(&damage_zone_stream); + Check_Pointer(directories); + Check(dmg_file); + + *damage_zone_stream << damage_zone_name; + + // + // Find dzone name in .dmg file + // + if(!dmg_file->PageExists(damage_zone_name)) + { + std::cerr << damage_zone_name <<" listed in .skl, does not exist in .dmg file"<GetEntry( + damage_zone_name, + "WeaponDamagePoints", + &default_points + ) + ) + { + std::cerr<GetEntry( + damage_zone_name, + "CollisionDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + if (point_data == 0.0f) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + Check_Fpu(); + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "BallisticDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "ExplosiveDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "LaserDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + if(!dmg_file->GetEntry( + damage_zone_name, + "EnergyDamagePoints", + &point_data + ) + ) + { + modified_armor = 1.0f/default_points; + } + else + { + modified_armor = 1.0f/point_data; + } + *damage_zone_stream << modified_armor; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get dzm filename + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *dzm_namelist = model_file->MakeEntryList("video","dzm"); + if(!dzm_namelist) + { + int zero_scalar(0.0f); + *damage_zone_stream << zero_scalar; + return True; + } + Register_Object(dzm_namelist); + int dzm_filecount; + dzm_filecount = dzm_namelist->EntryCount(); + *damage_zone_stream << dzm_filecount; + + if(dzm_filecount) + { + NameList::Entry *dzm_fileentry = dzm_namelist->GetFirstEntry(); + while(dzm_fileentry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // write out the skeleton type of the material + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + // + CString dzm_entry_name; + dzm_entry_name = dzm_fileentry->GetName(); + + EntitySegment::SkeletonType skeleton_type; + if (! dzm_entry_name.Compare("dzm") ) + { + skeleton_type = EntitySegment::SkeletonType_N; + } + else if (! dzm_entry_name.Compare("dzms") ) + { + skeleton_type = EntitySegment::SkeletonType_S; + } + else if (! dzm_entry_name.Compare("dzmt") ) + { + skeleton_type = EntitySegment::SkeletonType_T; + } + else if (! dzm_entry_name.Compare("dzmo") ) + { + skeleton_type = EntitySegment::SkeletonType_O; + } + else if (! dzm_entry_name.Compare("dzma") ) + { + skeleton_type = EntitySegment::SkeletonType_A; + } + else if (! dzm_entry_name.Compare("dzmb") ) + { + skeleton_type = EntitySegment::SkeletonType_B; + } + else if (! dzm_entry_name.Compare("dzmc") ) + { + skeleton_type = EntitySegment::SkeletonType_C; + } + else if (! dzm_entry_name.Compare("dzmd") ) + { + skeleton_type = EntitySegment::SkeletonType_D; + } + *damage_zone_stream << skeleton_type; + + // + // Get the name of the dzm File + // + char *filename = MakePathedFilename( + directories->videoDirectory, + dzm_fileentry->GetChar() + ); + Register_Pointer(filename); + // + // Create a Notation file from the dzm ASCII File + // + NotationFile *dzm_file = new NotationFile(filename); + Register_Object(dzm_file); + + NameList *material_list; + material_list = dzm_file->MakeEntryList(damage_zone_name, "material"); + int entry_count(0); + if(material_list) + { + + Register_Object(material_list); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write out how many materials + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + entry_count = material_list->EntryCount(); + *damage_zone_stream << entry_count; + if(entry_count) + { + NameList::Entry *dzm_entry; + dzm_entry = material_list->GetFirstEntry(); + Check(dzm_entry); + CString material_name; + while(dzm_entry) + { + material_name = dzm_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write out the material name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + *damage_zone_stream << material_name; + dzm_entry = dzm_entry->GetNextEntry(); + } + } + Unregister_Object(material_list); + delete material_list; + } + else + { + *damage_zone_stream << entry_count; + } + dzm_fileentry = dzm_fileentry->GetNextEntry(); + Unregister_Pointer(filename); + delete filename; + Unregister_Object(dzm_file); + delete dzm_file; + } + } + Unregister_Object(dzm_namelist); + delete dzm_namelist; + + Check_Fpu(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + DamageZone::WriteEffectSegmentIndicies( + MemoryStream *damage_zone_stream, + const char *damage_zone_name, + NotationFile *dmg_file, + NotationFile *skl_file, + const char *effect_type + ) +{ + Check(dmg_file); + Check(skl_file); + Check_Pointer(damage_zone_name); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an Entry list for this type of effect Site + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int effect_count(0); + NameList::Entry *effect_entry; + NameList *effect_namelist = dmg_file->MakeEntryList(damage_zone_name, effect_type); + if (!effect_namelist) + { + // + //~~~~~~~~~~~ + // No Entries + //~~~~~~~~~~~ + // + *damage_zone_stream << effect_count; + Check_Fpu(); + return 1; + } + else + { + Register_Object(effect_namelist); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write Out number of sites + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + effect_count = effect_namelist->EntryCount(); + *damage_zone_stream << effect_count; + effect_entry = effect_namelist->GetFirstEntry(); + CString site_page_name; + int effect_site_index; + while(effect_entry) + { + site_page_name = effect_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get SegmentIndex for this effect site Name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + effect_site_index = + JointedMover::GetSegmentIndex(site_page_name, skl_file); + if (effect_site_index == -1) + { + std::cerr<GetNextEntry(); + } + Unregister_Object(effect_namelist); + delete effect_namelist; + } + Check_Fpu(); + return 1; +} diff --git a/MUNGA/DAMAGE.h b/MUNGA/DAMAGE.h new file mode 100644 index 0000000..7ee5239 --- /dev/null +++ b/MUNGA/DAMAGE.h @@ -0,0 +1,384 @@ +#pragma once + +#include "point3d.h" +#include "node.h" +#include "normal.h" +#include "cstr.h" +#include "table.h" +#include "schain.h" +#include "simulate.h" + +class MaterialList; +class EntitySegment; +class ExplosionTable; +class Simulation; +class MemoryStream; +class NotationFile; +struct ResourceDirectories; +class Entity; + +//########################################################################## +//########################### Damage ################################# +//########################################################################## + +class Damage +{ +public: + enum { + CollisionDamageType, + BallisticDamageType, + ExplosiveDamageType, + LaserDamageType, + EnergyDamageType, + DamageTypeCount + }; + Enumeration + damageType; + Scalar + damageAmount; + + Vector3D + damageForce; + Normal + surfaceNormal; + + // impact point should be in the global coordinate space. + Point3D + impactPoint; + // + // burst count should be thought of as number of times + // to apply the damage. + // + + int + burstCount; + + + Damage(); +}; + +//########################################################################## +//######################### MaterialList ############################# +//########################################################################## + +class MaterialList : + public Plug +{ + public: + + typedef PlugOf CStringPlug; + + typedef SChainOf + CStringSocket; + + typedef SChainIteratorOf + CStringSocketIterator; + +protected: + + CStringSocketIterator* + listIterator; + + CStringSocket + materialList; + + public: + + MaterialList(); + ~MaterialList(); + + void + DeletePlugs() + {Check(this); listIterator->DeletePlugs();} + + void + Add(CStringPlug *new_plug) + {Check(this); materialList.Add(new_plug);} + + void + First() + { Check(this);listIterator->First();} + + void + Last() + {Check(this); listIterator->Last(); } + + CString* + ReadAndNext() + { + Check(this); + if (!listIterator->GetCurrent()) + return NULL; + else + return listIterator->ReadAndNext()->GetPointer(); + } + + CString* + GetCurrent() + { + Check(this); + if (!listIterator->GetCurrent()) + return NULL; + else + return listIterator->GetCurrent()->GetPointer(); + } + + void + Next() + {Check(this); if(listIterator->GetCurrent()) listIterator->Next();} +}; +//########################################################################## +//################# DamageZone::UpdateRecord ######################### +//########################################################################## + +struct DamageZone__UpdateRecord +{ + public: + size_t recordLength; + int damageZoneIndex; + Scalar damageLevel; + Enumeration damageZoneState; + Enumeration damageZoneGraphicState; + LWord changedFlags; +}; + +//########################################################################## +//######################### DamageZone ############################### +//########################################################################## + +class DamageZone: + public Node +{ +protected: + + Simulation* + owningSimulation; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// State Support +// +private: + + StateIndicator + damageZoneState; + + StateIndicator + damageZoneGraphicState; + +public: + + enum{ + ExistsGraphicState = 0, + DestroyedGraphicState, + GoneGraphicState, + GraphicStateCount + }; + + enum{ + DefaultState = 0, + BurningState, + DamageStateCount + }; + + StateIndicator* + GetGraphicStatePointer() + {Check(this); return &damageZoneGraphicState;} + + Enumeration + GetDamageZoneState() + {Check(this); return damageZoneState.GetState();} + + void + SetDamageZoneState(Enumeration new_state) + {Check(this); damageZoneState.SetState(new_state); } + + Enumeration + GetGraphicState() + {Check(this); return damageZoneGraphicState.GetState();} + + virtual void + SetGraphicState(Enumeration new_state) + { + Check(this); + damageZoneGraphicState.SetState(new_state); + SetGraphicStateChangedFlag(); + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Flag Support +// + +public: + + enum { + DamageLevelChangedBit = 2, + GraphicStateChangedBit, + NextBit + }; + + enum { + DamageLevelChangedFlag = 1 << DamageLevelChangedBit, + GraphicStateChangedFlag = 1 << GraphicStateChangedBit + }; + + Logical + DamageLevelChanged() const + {Check(this); return ((changedFlags & DamageLevelChangedFlag) != 0); } + + Logical + GraphicStateChanged() const + {Check(this); return ((changedFlags & GraphicStateChangedFlag) != 0); } + + void + SetDamageLevelChangedFlag() + {Check(this); changedFlags |= DamageLevelChangedFlag; } + + void + SetGraphicStateChangedFlag() + {Check(this); changedFlags |= GraphicStateChangedFlag; } + + void + ResetChangedFlags() + {Check(this); changedFlags = 0; } + + LWord + changedFlags; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Update Support +// +public: + typedef DamageZone__UpdateRecord UpdateRecord; + + virtual void + ReadUpdateRecord(UpdateRecord *message); + + virtual void + WriteUpdateRecord(UpdateRecord *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Material Support +// + +public: + typedef TableOf + MaterialTable; + + typedef TableIteratorOf + MaterialTableIterator; + + MaterialList* + GetMaterialList(Enumeration skl_type) + { + Check(this); + return materialTable.Find(skl_type); + } + + protected: + + MaterialTable + materialTable; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Explosion Support +// + +protected: + + ExplosionTable + *explosionTable; + +public: + + ExplosionTable* + CreateExplosionTable(MemoryStream *explosion_stream); + + ExplosionTable* + GetExplosionTable() + {Check(this); return explosionTable; } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Effect Support +// +public: + SChainOf + defaultEffectSiteChain, + internalVideoEffectSiteChain, + externalVideoEffectSiteChain, + internalAudioEffectSiteChain, + externalAudioEffectSiteChain; + + enum { + DefaultEffectSite, + ExternalVideoEffectSite, + InternalVideoEffectSite, + ExternalAudioEffectSite, + InternalAudioEffectSite, + EffectSiteCount + }; + + EntitySegment* + GetCurrentEffectSite(Enumeration effect_site_type = DefaultEffectSite); + + static int WriteEffectSegmentIndicies(MemoryStream *damage_zone_stream, const char *damage_zone_name, NotationFile *dmg_file, NotationFile *skl_file, const char *effect_type); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local Support +// +public: + +Simulation* + GetOwningSimulation() + {return owningSimulation;} + + int + damageZoneIndex; + + Scalar + defaultArmorPoints; + + Scalar + damageScale[Damage::DamageTypeCount]; + + Scalar + damageLevel; + + CString damageZoneName; + + virtual void + TakeDamage(Damage &damage); + + void + Reset(Logical full_reset=True); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction / Destruction Support +// + DamageZone( + Simulation *owner, + int damage_zone_index, + MemoryStream *dzone_res + ); + + DamageZone(Simulation *owner, int damage_zone_index); + + virtual ~DamageZone(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Resource Support +// + static Logical + CreateStreamedDamageZone( + NotationFile *model_file, + const char *model_name, + NotationFile *skl_file, + CString damage_zone_name, + MemoryStream *damage_zone_stream, + NotationFile *dmg_file, + const ResourceDirectories *directories + ); +}; diff --git a/MUNGA/DEBUG1ON.h b/MUNGA/DEBUG1ON.h new file mode 100644 index 0000000..eb4c5e0 --- /dev/null +++ b/MUNGA/DEBUG1ON.h @@ -0,0 +1,134 @@ +#pragma once + +#include + +#if !defined(OLD_DEBUG_LEVEL) + #define OLD_DEBUG_LEVEL 1 +#else + #undef OLD_DEBUG_LEVEL + #if DEBUG_LEVEL >= 3 + #define OLD_DEBUG_LEVEL 3 + #elif DEBUG_LEVEL == 1 + #define OLD_DEBUG_LEVEL 1 + #elif DEBUG_LEVEL == 0 + #define OLD_DEBUG_LEVEL 0 + #endif +#endif + +#undef DEBUG_LEVEL +#undef Verify +#undef Verify_And_Dump +#undef Dump +#undef Tell +#undef Warn +#undef Warn_And_Dump +#undef Check_Signature +#undef Check_Pointer +#undef Check +#undef Check_Fpu +#undef Fail +#undef Cast_Object +#undef DEBUG_CODE +#undef Mem_Copy +#undef Str_Copy +#undef Str_Cat +#undef Sqrt +#undef Arctan +#undef Arccos +#undef Arcsin + +#define DEBUG_LEVEL 1 + +#define DEBUG_CODE(x) { x } + +#define Dump(v)\ + (DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl << flush) + +#define Verify(c)\ + if (!(c)) {\ + Verify_Failed(#c,__FILE__,__LINE__);\ + } + +#define Verify_And_Dump(c,v)\ + if (!(c)) {\ + DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl << std::flush;\ + Verify_Failed(#c,__FILE__,__LINE__);\ + } + +#define Warn(c)\ + if (c) {\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\ + } + +#define Warn_And_Dump(c,v)\ + if (c) {\ + DEBUG_STREAM << __FILE__ "(" << __LINE__ << "): "#v" = " << (v) << endl << std::flush;\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): Warning -> "#c"\n" << flush;\ + } + +#define Tell(m)\ + (DEBUG_STREAM << m << flush) + +#define Check_Pointer(p) Verify(p) + +#define Check_Fpu() Verify(Fpu_Ok()) + +#define Mem_Copy(destination, source, length, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + memcpy(destination, source, length);\ + } + +#define Str_Copy(destination, source, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + strcpy(destination, source);\ + } + +#define Str_Cat(destination, source, available)\ + {\ + Check_Pointer(destination);\ + Check_Pointer(source);\ + strcat(destination, source);\ + } + +#define Sqrt(value)\ + ((value>=0.0f) ? sqrt(value) : (Fail("Bad parameter to sqrt"),0.0f)) + +#define Arctan(y,x)\ + (\ + (!Small_Enough(y) || !Small_Enough(x))\ + ? atan2((y),(x)) :\ + (Fail("Zero Arctan!"),0.0f)\ + ) + +#define Arccos(x)\ + (\ + ((x)>=-1.0f && (x)<=1.0f)\ + ? acos(x) :\ + (Fail("Out of range Arccos!"),0.0f)\ + ) + +#define Arcsin(x)\ + (\ + ((x)>=-1.0f && (x)<=1.0f)\ + ? asin(x) :\ + (Fail("Out of range Arcsin!"),0.0f)\ + ) + +#define Power(x,y)\ + (\ + ((x)<0.0f)\ + ? (Fail("Out of range Power!"),0.0f) :\ + pow(x,y)\ + ) + +#define Check_Signature(p) Check_Pointer(p) +#define Check(p) Check_Pointer(p) + +#define Fail(m) Fail_To_Debugger(m,__FILE__,__LINE__) + +#define Cast_Object(type, ptr) ((type)(ptr)) + diff --git a/MUNGA/DEBUGOFF.h b/MUNGA/DEBUGOFF.h new file mode 100644 index 0000000..feccbac --- /dev/null +++ b/MUNGA/DEBUGOFF.h @@ -0,0 +1,63 @@ +#pragma once + +#include + +#if !defined(OLD_DEBUG_LEVEL) + #define OLD_DEBUG_LEVEL 0 +#else + #undef OLD_DEBUG_LEVEL + #if DEBUG_LEVEL>=3 + #define OLD_DEBUG_LEVEL 3 + #elif DEBUG_LEVEL==2 + #define OLD_DEBUG_LEVEL 2 + #elif DEBUG_LEVEL==1 + #define OLD_DEBUG_LEVEL 1 + #endif +#endif + +#undef DEBUG_LEVEL +#undef Verify +#undef Verify_And_Dump +#undef Warn +#undef Warn_And_Dump +#undef Dump +#undef Tell +#undef Check_Signature +#undef Check_Pointer +#undef Mem_Copy +#undef Str_Copy +#undef Str_Cat +#undef Check +#undef Check_Fpu +#undef Fail +#undef Cast_Object +#undef DEBUG_CODE +#undef Sqrt +#undef Arctan +#undef Arccos +#undef Arcsin + +#define DEBUG_LEVEL 0 +#define DEBUG_CODE(x) +#define Verify(c) +#define Verify_And_Dump(c,v) +#define Warn(c) +#define Warn_And_Dump(c,v) +#define Dump(v) +#define Tell(m) +#define Check_Pointer(p) +#define Check_Fpu() +#define Mem_Copy(destination, source, length, available) memcpy(destination, source, length) +#define Str_Copy(destination, source, available) strcpy(destination, source); +#define Str_Cat(destination, source, available) strcat(destination, source); +#define Sqrt(value) sqrt(value) +#define Arctan(y,x) atan2(y,x) +#define Arccos(x) acos(x) +#define Arcsin(x) asin(x) +#define Power(x,y) pow(x,y) + +#define Check(p) +#define Check_Signature(p) +//#define Fail(m) Fail_To_Debugger(m,__FILE__,__LINE__) +#define Fail(m) abort(); +#define Cast_Object(type, ptr) ((type)(ptr)) \ No newline at end of file diff --git a/MUNGA/DIRECTOR.cpp b/MUNGA/DIRECTOR.cpp new file mode 100644 index 0000000..4f87d93 --- /dev/null +++ b/MUNGA/DIRECTOR.cpp @@ -0,0 +1,309 @@ +#include "munga.h" +#pragma hdrstop + +#include "director.h" +#include "mission.h" +#include "player.h" +#include "app.h" +#include "hostmgr.h" +#include "nttmgr.h" + +//############################################################################# +// Shared Data support +// +Derivation* CameraDirector::GetClassDerivations() +{ static Derivation classDerivations(Player::GetClassDerivations(), "CameraDirector"); + return &classDerivations; +} + + +CameraDirector::SharedData + CameraDirector::DefaultData( + CameraDirector::GetClassDerivations(), + CameraDirector::MessageHandlers, + CameraDirector::GetAttributeIndex(), + CameraDirector::StateCount, + (Entity::MakeHandler) CameraDirector::Make + ); + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraDirector::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraDirector, AttachCameraShip) +}; + +CameraDirector::MessageHandlerSet + CameraDirector::MessageHandlers( + ELEMENTS(CameraDirector::MessageHandlerEntries), + CameraDirector::MessageHandlerEntries, + Player::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::AttachCameraShipMessageHandler( + AttachCameraShipMessage *in_message + ) +{ + Check(in_message); + Check(application); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the cameraship ID to attach to + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + HostManager *host = application->GetHostManager(); + Check(host); + Entity *entity_ptr = host->GetEntityPointer(in_message->cameraShipID); + Check(entity_ptr); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the cameraShip Pointer Object + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CameraShip *camera_ship; + camera_ship = Cast_Object(CameraShip*, entity_ptr); + Check(this); + Check(camera_ship); + cameraShip = camera_ship; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::UpdateHUD( + Scalar time_slice + ) +{ + Check(this); + Check(application); + + // + //~~~~~~~~~~~~ + // HUD Support + //~~~~~~~~~~~~ + // + if (GetGoalEntity()) + { + Check(GetGoalEntity()); + Player *goal_player = GetGoalEntity()->GetPlayerLink(); + if (goal_player) + { + Check(goal_player); + goalPlayerIndex = goal_player->playerBitmapIndex; + } + } + + if ( + application->GetApplicationState() == Application::StoppingMission || + application->GetApplicationState() == Application::EndingMission + ) + { + displayRankingWindow = False; + return; + } + else if (application->GetSecondsRemainingInGame() <= 30.0f) + { + displayRankingWindow = True; + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Check times for Ranking Window Display + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (displayRankingWindow) + { + timeDisplayed += time_slice; + if(timeDisplayed >= displayIntervalOn) + { + timeTillDisplayed = displayIntervalOff; + displayRankingWindow = False; + } + } + else + { + timeTillDisplayed -= time_slice; + if (timeTillDisplayed <= 0.0f) + { + timeDisplayed = 0.0f; + displayRankingWindow = True; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::BeADirector(Scalar time_slice) +{ + Check(this); + + Player::PlayerSimulation(time_slice); + UpdateHUD(time_slice); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Time To Cut To a new Player? + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if ( + timeLeftOnPlayer > 0.0f + && application->GetApplicationState() == Application::RunningMission) + { + timeLeftOnPlayer -= time_slice; + return; + } + + Player *top_dog = FindPlayerByRank(0); + if (top_dog) + { + Check(top_dog); + Entity *vehicle = top_dog->GetPlayerVehicle(); + if (vehicle) + { + Check(vehicle); + if ((GetGoalEntity() != vehicle)) + { + SetGoalEntity(vehicle); + timeLeftOnPlayer = 10.0f; + Check(cameraShip); + CameraShip::DirectionMessage direction_message( + CameraShip::DirectionMessageID, + sizeof(CameraShip::DirectionMessage), + GetGoalEntity()->GetEntityID(), + 0.0f, + Point3D::Identity + ); + Check(cameraShip); + cameraShip->Dispatch(&direction_message); + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraDirector::CreateCameraShip(Scalar) +{ + CreatePlayerVehicle(localOrigin); + PlayerLinkMessage player_link_message ( + PlayerLinkMessageID, + sizeof(PlayerLinkMessage), + this->GetEntityID() + ); + Check(playerVehicle); + playerVehicle->Dispatch(&player_link_message); + playerVehicle->DispatchToReplicants(&player_link_message); + SetPerformance(&CameraDirector::BeADirector); + deathCount = 0; + + CameraDirector::AttachCameraShipMessage + message( + CameraDirector::AttachCameraShipMessageID, + sizeof(CameraDirector::AttachCameraShipMessage), + playerVehicle->GetEntityID() + ); + Dispatch(&message); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraDirector::CameraDirector( + CameraDirector::MakeMessage *creation_message, + CameraDirector::SharedData &virtual_data +) : + Player(creation_message, virtual_data), + goalEntity(this) +{ + cameraShip = NULL; + SetValidFlag(); + timeLeftOnPlayer = -1.0f; + if (GetInstance() != ReplicantInstance) + { + SetPerformance(&CameraDirector::CreateCameraShip); + } + // + //~~~~~~~~~~~~ + // HUD Support + //~~~~~~~~~~~~ + // + goalPlayerIndex = -1; + displayRankingWindow = False; + displayIntervalOn = 10.0f; + displayIntervalOff = 15.0f; + timeDisplayed = 0.0f; + timeTillDisplayed = displayIntervalOff; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraDirector* + CameraDirector::Make(MakeMessage *creation_message) +{ + return new CameraDirector(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraDirector::~CameraDirector() +{ + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Player* + CameraDirector::FindPlayerByRank(int rank_to_find) +{ + Check(application); + + // + //--------------------------------------- + // Get all players from the entity group + //--------------------------------------- + // + EntityGroup *player_group = + application->GetEntityManager()->FindGroup("Players"); + if(player_group) + { + Player *leading_player; + + // + //----------------------------------------------------- + // Iterate through the players find the leading player + //----------------------------------------------------- + // + ChainIteratorOf iterator(player_group->groupMembers); + while ((leading_player = (Player*) iterator.ReadAndNext()) != NULL) + { + Check(leading_player); + if (leading_player->playerRanking == rank_to_find) + { + return leading_player; + } + } + } + return NULL; +} + +Logical + CameraDirector::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/DIRECTOR.h b/MUNGA/DIRECTOR.h new file mode 100644 index 0000000..82b09a6 --- /dev/null +++ b/MUNGA/DIRECTOR.h @@ -0,0 +1,157 @@ +#pragma once + +#include "style.h" +#include "player.h" +#include "schain.h" +#include "camship.h" +#include "graph2d.h" +#include "slot.h" + +//########################################################################## +//################# CameraDirector::AttachCameraShip ################# +//########################################################################## + +class CameraDirector__AttachCameraShipMessage: + public Player::Message +{ + public: + + EntityID + cameraShipID; + + CameraDirector__AttachCameraShipMessage( + Receiver::MessageID message_ID, + size_t length, + EntityID camera_ship_ID + ): + Entity::Message(message_ID, length), + cameraShipID(camera_ship_ID) + {} +}; + +//########################################################################## +//############################# CameraDirector ############################# +//########################################################################## + +class CameraDirector: + public Player +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging support +// +public: + friend class CameraDirector__AttachCameraShipMessage; + + enum{ + AttachCameraShipMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef CameraDirector__AttachCameraShipMessage AttachCameraShipMessage; + + void + AttachCameraShipMessageHandler(AttachCameraShipMessage *message); + +protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Simulation Support +// +public: + typedef void + (CameraDirector::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + CreateCameraShip(Scalar time_slice); + void + BeADirector(Scalar time_slice); + void + UpdateHUD(Scalar time_slice); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + CameraDirector( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + + static CameraDirector* + CameraDirector::Make(CameraDirector::MakeMessage *creation_message); + + ~CameraDirector(); + + Logical + TestInstance() const; + + enum { + DefaultFlags = Entity::DefaultFlags | PreRunFlag | CameraShipPlayerFlag + }; + + static Player* + FindPlayerByRank(int rank_to_find); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Simulation Support Data & Functions +// +protected: + + SlotOf + goalEntity; + + void + SetGoalEntity(Entity *goal_entity) + { + Check(this); + goalEntity.Remove(); + Check(goal_entity); + goalEntity.Add(goal_entity); + } + + Entity* + GetGoalEntity() + {Check(this); return goalEntity.GetCurrent(); } + + Scalar + timeLeftOnPlayer; + + CameraShip + *cameraShip; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HUD Support +// +public: + + int + goalPlayerIndex; + + Logical + displayRankingWindow; + + Scalar + timeDisplayed, + timeTillDisplayed, + displayIntervalOn, + displayIntervalOff; +}; diff --git a/MUNGA/DOOR.cpp b/MUNGA/DOOR.cpp new file mode 100644 index 0000000..b749f5d --- /dev/null +++ b/MUNGA/DOOR.cpp @@ -0,0 +1,537 @@ +#include "munga.h" +#pragma hdrstop + +#include "door.h" +#include "fileutil.h" +#include "boxsolid.h" +#include "doorfram.h" +#include "app.h" +#include "notation.h" + +//############################################################################# +// Shared Data Support +// +Door::SharedData + Door::DefaultData( + Door::GetClassDerivations(), + Door::GetMessageHandlers(), + Door::GetAttributeIndex(), + Door::StateCount + ); + +Derivation* Door::GetClassDerivations() +{ + static Derivation classDerivations(Subsystem::GetClassDerivations(), "Door"); + return &classDerivations; +} + + +//############################################################################# +// Messaging Support +// + + +//############################################################################# +// Attribute Support +// + +const Door::IndexEntry + Door::AttributePointers[]= +{ + { + Door::CurrentPositionAttributeID, + "CurrentPosition", + (Simulation::AttributePointer)&Door::currentPosition + }, + { + Door::VideoResourceAttributeID, + "VideoResource", + (Simulation::AttributePointer)&Door::videoResource + }, + { + Door::PercentOpenAttributeID, + "PercentOpen", + (Simulation::AttributePointer)&Door::percentOpen + }, + { + Door::CurrentVelocityAttributeID, + "CurrentVelocity", + (Simulation::AttributePointer)&Door::currentVelocity + } +}; + +Door::AttributeIndexSet& Door::GetAttributeIndex() +{ + static Door::AttributeIndexSet attributeIndex(ELEMENTS(Door::AttributePointers), + Door::AttributePointers, + Subsystem::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// +void + Door::ReadUpdateRecord(Simulation::UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + Subsystem::ReadUpdateRecord(message); + UpdateRecord* record = (UpdateRecord*) message; + + percentOpen = record->percentOpen; + switch (GetSimulationState()) + { + case Opening: + case Closing: + phaseTimeRemaining = travelTime; + break; + case Opened: + case Closed: + phaseTimeRemaining = deadTime; + break; + } +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door updated to state " +// << GetSimulationState() << " @ " +// << application->GetSecondsRemainingInGame() << endl; + MoveCollisionVolume(percentOpen); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Door::WriteUpdateRecord(Simulation::UpdateRecord *record, int update_model) +{ + Check(this); + Check_Pointer(record); + + Subsystem::WriteUpdateRecord(record, update_model); + + UpdateRecord *update = (UpdateRecord*)record; + update->percentOpen = percentOpen; + update->recordLength = sizeof(*update); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Door::SlideDoor(Scalar time_slice) +{ + Check(this); + + // + //------------------------------------------------------------ + // Advance the clock, then branch based upon our current state + //------------------------------------------------------------ + // + int new_state; + if (time_slice > 1.0f) + { + Check_Fpu(); + return; + } + phaseTimeRemaining -= time_slice; + Scalar percent_open; + switch (GetSimulationState()) + { + + // + //------------------------------------------------------------------------ + // If the door is not done opening, set its new position, otherwise branch + // to the opened state + //------------------------------------------------------------------------ + // + case Opening: +Door_Opening: + new_state = Opening; + if (phaseTimeRemaining > 0.0f) + { + percent_open = 1.0f - phaseTimeRemaining/travelTime; + } + else + { + phaseTimeRemaining += deadTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opened @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Opened; + } + currentVelocity.Subtract( + worldExtent, + GetEntity()->localOrigin.linearPosition + ); + currentVelocity /= travelTime; + Check_Fpu(); + break; + + // + //------------------------------------------------------------- + // If the door is ready to start closing, jump to closing state + //------------------------------------------------------------- + // + case Opened: +Door_Opened: + new_state = Opened; + if (phaseTimeRemaining <= 0.0f) + { + phaseTimeRemaining += travelTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closing @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Closing; + } + percent_open = 1.0f; + currentVelocity = Vector3D::Identity; + Check_Fpu(); + break; + + // + //------------------------------------------------------------------------ + // If the door is not done closing, set its new position, otherwise branch + // to the closed state + //------------------------------------------------------------------------ + // + case DefaultState: + phaseTimeRemaining = travelTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door default @ " +// << application->GetSecondsRemainingInGame() << endl; + case Closing: +Door_Closing: + new_state = Closing; + if (phaseTimeRemaining > 0.0f) + { + percent_open = phaseTimeRemaining/travelTime; + } + else + { + phaseTimeRemaining += deadTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door closed @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Closed; + } + currentVelocity.Subtract( + GetEntity()->localOrigin.linearPosition, + worldExtent + ); + currentVelocity /= travelTime; + Check_Fpu(); + break; + + // + //------------------------------------------------------------- + // If the door is ready to start opening, jump to opening state + //------------------------------------------------------------- + // + case Closed: +Door_Closed: + new_state = Closed; + if (phaseTimeRemaining <= 0.0f) + { + phaseTimeRemaining += travelTime; +// DEBUG_STREAM << GetEntity()->GetEntityID() << " door opening @ " +// << application->GetSecondsRemainingInGame() << endl; + goto Door_Opening; + } + percent_open = 0.0f; + currentVelocity = Vector3D::Identity; + Check_Fpu(); + break; + + } + + // + //------------------------------------------------- + // Move the collision volumes and set the new state + //------------------------------------------------- + // + MoveCollisionVolume(percent_open); + SetSimulationState(new_state); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Door::MoveCollisionVolume(Scalar percent_open) +{ + Check(this); + + // + //--------------------------------------------------------- + // If the door hasn't moved, don't bother updating anything + //--------------------------------------------------------- + // + Entity *entity = GetEntity(); + Check(entity); + + if ( + GetSimulationState() != simulationState.GetOldState() + && entity->GetInstance() == Entity::MasterInstance + && entity->IsDynamic() + ) + { + ForceUpdate(); + } + if (percent_open == percentOpen) + { + return; + } + + // + //----------------------------------- + // Otherwise, lerp the local position + //----------------------------------- + // + percentOpen = percent_open; + currentPosition.Lerp(Point3D::Identity, localExtent, percentOpen); + + // + //----------------------------------------------------------- + // Now, lerp the world position and set the collision volumes + //----------------------------------------------------------- + // + Point3D world; + world.Lerp( + GetEntity()->localOrigin.linearPosition, + worldExtent, + percentOpen + ); + + BoxedSolid* temp = collisionTemplates; + BoxedSolid* vol = collisionVolumes; + while (temp) + { + Check(temp); + Check(vol); + + vol->minX = temp->minX + world.x; + vol->maxX = temp->maxX + world.x; + vol->minY = temp->minY + world.y; + vol->maxY = temp->maxY + world.y; + vol->minZ = temp->minZ + world.z; + vol->maxZ = temp->maxZ + world.z; + + vol = vol->GetNextSolid(); + temp = temp->GetNextSolid(); + } + Verify(!vol); + Check_Fpu(); +} + +//############################################################################# +// Constructer/Destructor Support +// + +Door::Door( + DoorFrame *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + Subsystem(entity, subsystem_ID, subsystem_resource, DefaultData) +{ + Check_Pointer(this); + Check(entity); + Check_Pointer(subsystem_resource); + + // + // GetStream data NOTE::This must be in the same order as below!!! + // + localExtent = subsystem_resource->motionExtent; + travelTime = subsystem_resource->travelTime; + deadTime = subsystem_resource->deadTime; + + // + // Initialize variables + // + phaseTimeRemaining = 0.0f; + currentPosition = Point3D::Identity; + + SetPerformance(&Door::SlideDoor); + SetSimulationState(DefaultState); + + collisionVolumeCount = 0; + collisionTemplates = NULL; + collisionVolumes = NULL; + percentOpen = -1.0f; + + // + //------------------------------------- + // Establish the worldspace coordinates + //------------------------------------- + // + worldExtent.Multiply(localExtent, entity->localToWorld); + Origin local_origin = entity->localOrigin; + local_origin.linearPosition = Point3D::Identity; + + // + //------------------------------ + // Read in the collision volumes + //------------------------------ + // + Check(application); + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + ResourceDescription *res = + res_file->FindResourceDescription(subsystem_resource->collisionID); + Check(res); + res->Lock(); + BoxedSolidResource* box = + (BoxedSolidResource*)res->resourceAddress; + Check_Pointer(box); + collisionVolumeCount = res->resourceSize / sizeof(BoxedSolidResource); + + for (int i=0; ilocalOrigin); + local_box.Instance(*box,local_origin); + + collisionTemplates = + BoxedSolid::MakeBoxedSolid(&local_box, this, collisionTemplates); + Register_Object(collisionTemplates); + + collisionVolumes = + BoxedSolid::MakeBoxedSolid(&world_box, this, collisionVolumes); + Register_Object(collisionVolumes); + + ++box; + } + res->Unlock(); + + MoveCollisionVolume(0.0f); + Check(this); +} + +Door::~Door() +{ + BoxedSolid *box = collisionTemplates; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } + box = collisionVolumes; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateStreamedSubsystem +// +Logical + Door::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char* subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + ResourceFile *res_file + ) +{ + if ( + !Subsystem::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + directories + ) + ) + { + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::DoorClassID; + + // + // Get the motion Extent + // + const char *extent_data; + if( + !subsystem_file->GetEntry( + subsystem_name, + "MotionExtent", + &extent_data + ) + ) + { + std::cerr << subsystem_name << " missing MotionExtent!!\n"; + return -1; + } + sscanf( + extent_data, + "%f %f %f", + &subsystem_resource->motionExtent.x, + &subsystem_resource->motionExtent.y, + &subsystem_resource->motionExtent.z + ); + + // + // Get the travelTime + // + + if( + !subsystem_file->GetEntry( + subsystem_name, + "TravelTime", + &subsystem_resource->travelTime + ) + ) + { + std::cerr << subsystem_name << " missing TravelTime!\n"; + return -1; + } + + // + // Read in the Deadtime + // + if( + !subsystem_file->GetEntry( + subsystem_name, + "DeadTime", + &subsystem_resource->deadTime + ) + ) + { + std::cerr << subsystem_name << " missing DeadTime!\n"; + return False; + } + + const char* collision_file; + if ( + !subsystem_file->GetEntry( + subsystem_name, + "Collision", + &collision_file + ) + ) + { + std::cerr << subsystem_name << " missing Collision!\n"; + return False; + } + subsystem_resource->collisionID = + BoxedSolidResource::CreateBoxedSolidStream( + collision_file, + res_file, + directories + ); + + return True; +} + +Logical + Door::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/DOOR.h b/MUNGA/DOOR.h new file mode 100644 index 0000000..fd966ba --- /dev/null +++ b/MUNGA/DOOR.h @@ -0,0 +1,164 @@ +#pragma once + +#include "subsystm.h" +#include "boxsolid.h" + +class DoorFrame; + +//########################################################################## +//##################### Door::SubsystemResource ################### +//########################################################################## + +struct Door__SubsystemResource: + public Subsystem::SubsystemResource +{ + Vector3D motionExtent; + Scalar + travelTime, + deadTime; + ResourceDescription::ResourceID + collisionID; +}; + +//########################################################################## +//##################### Chute::UpdateRecord ##################### +//########################################################################## + +struct Door__UpdateRecord : + public Subsystem::UpdateRecord +{ + Scalar + percentOpen; +}; + +//########################################################################## +//######################### CLASS Door ######################## +//########################################################################## + +class Door : + public Subsystem +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + PercentOpenAttributeID = Subsystem::NextAttributeID, + CurrentPositionAttributeID, + VideoResourceAttributeID, + CurrentVelocityAttributeID, + NextAttributeID + }; + +private: + + static const IndexEntry AttributePointers[]; + +protected: + + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +public: + + Scalar percentOpen; + ResourceDescription::ResourceID videoResource; + Point3D currentPosition; + Vector3D currentVelocity; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + enum { + Opening = Subsystem::StateCount, + Opened, + Closing, + Closed, + StateCount + }; + + typedef void + (Door::*Performance)(Scalar time_slice); + typedef Door__UpdateRecord UpdateRecord; + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + SlideDoor(Scalar time_slice); + + void + MoveCollisionVolume(Scalar open_percent); + BoxedSolid* + GetFirstBoxedSolid() + {Check(this); return collisionVolumes;} + +protected: + void + WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// + +public: + typedef Door__SubsystemResource SubsystemResource; + + Door( + DoorFrame *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Door(); + + Logical + TestInstance() const; + + static Logical + CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories, + ResourceFile *res_file + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local Support +// +private: + Point3D + localExtent, + worldExtent; + + Scalar + phaseTimeRemaining, + travelTime, + deadTime; + + int collisionVolumeCount; + + BoxedSolid + *collisionTemplates, + *collisionVolumes; +}; diff --git a/MUNGA/DOORFRAM.cpp b/MUNGA/DOORFRAM.cpp new file mode 100644 index 0000000..6931710 --- /dev/null +++ b/MUNGA/DOORFRAM.cpp @@ -0,0 +1,278 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "fileutil.h" +#include "doorfram.h" +#include "door.h" +#include "app.h" +#include "notation.h" +#include "namelist.h" + +//############################################################################# +// Shared Data Support +// +Derivation* DoorFrame::GetClassDerivations() +{ static Derivation classDerivations(UnscalableTerrain::GetClassDerivations(), "DoorFrame"); + return &classDerivations; +} + + +DoorFrame::SharedData + DoorFrame::DefaultData( + DoorFrame::GetClassDerivations(), + DoorFrame::GetMessageHandlers(), + DoorFrame::GetAttributeIndex(), + DoorFrame::StateCount, + (Entity::MakeHandler)DoorFrame::Make + ); +//############################################################################# +// Test Support +// +Logical + DoorFrame::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DoorFrame::DoorFrame( + DoorFrame::MakeMessage *creation_message, + DoorFrame::SharedData &virtual_data +): + UnscalableTerrain(creation_message, virtual_data) +{ + Check_Pointer(this); + Check(creation_message); + Check(&virtual_data); + + SetValidFlag(); + SetPerformance(&DoorFrame::DoNothing); + + // + // Get the subsystem_resource from the resource file + // + Check(application); + ResourceDescription *subsystem_resource = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::SubsystemModelStreamResourceType + ); + Check(subsystem_resource); + subsystem_resource->Lock(); + Check_Pointer(subsystem_resource->resourceAddress); + MemoryStream subsystem_stream( + subsystem_resource->resourceAddress, + subsystem_resource->resourceSize); + + subsystemCount = *(int*)subsystem_stream.GetPointer(); + subsystem_stream.AdvancePointer(sizeof(int)); + Verify(subsystemCount); + + // + // Set up Subsystems + // + subsystemArray = new (Subsystem(*[subsystemCount])); + Register_Pointer(subsystemArray); + + // + // Attach the doors as defined in the mod file + // + for (int ii=BasicSubsystemCount; iisubsystemModelSize); + } + + subsystem_resource->Unlock(); + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DoorFrame* + DoorFrame::Make(DoorFrame::MakeMessage *creation_message) +{ + return new DoorFrame(creation_message); +} + +Logical + DoorFrame::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if ( + !UnscalableTerrain::CreateMakeMessage( + creation_message, + model_file, + directories + ) + ) + { + return false; + } + + creation_message->classToCreate = RegisteredClass::DoorFrameClassID; + creation_message->instanceFlags = + MasterInstance|DynamicFlag|MapFlag|TrappedFlag; + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DoorFrame::~DoorFrame() +{ +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + DoorFrame::CreateSubsystemStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .sub file + //------------------- + // + const char* entry_data; + if ( + !model_file->GetEntry( + "gamedata", + "Subsystems", + &entry_data + ) + ) + { + std::cerr << model_name << " is missing .sub file specification!\n"; + return -1; + } + + char *sub_filename = MakePathedFilename(directories->modelDirectory, entry_data); + Register_Pointer(sub_filename); + + NotationFile *sub_file = new NotationFile(sub_filename); + Register_Object(sub_file); + NameList *sub_namelist = sub_file->MakePageList(); + Register_Object(sub_namelist); + int subsystem_count = sub_file->PageCount(); + if (!subsystem_count) + { + std::cerr << sub_filename << " empty of missing!\n"; +Dump_And_Die: + Unregister_Pointer(sub_filename); + delete sub_filename; + Unregister_Object(sub_file); + delete sub_file; + Unregister_Object(sub_namelist); + delete sub_namelist; + return -1; + } + int buf_size = + subsystem_count * sizeof(Door::SubsystemResource) + sizeof(int); + char *buffer = new char[buf_size]; + Register_Pointer(buffer); + MemoryStream subsystem_stream(buffer, buf_size); + + *(int*)subsystem_stream.GetPointer() = subsystem_count; + subsystem_stream.AdvancePointer(sizeof(int)); + + NameList::Entry *sub_entry = sub_namelist->GetFirstEntry(); + while(sub_entry) + { + char subsystem_name[32]; + Str_Copy(subsystem_name, sub_entry->GetName(), sizeof(subsystem_name)); + const char *sub_type; + if(!sub_file->GetEntry( + subsystem_name, + "Type", + &sub_type + ) + ) + { + std::cerr << model_name << ':' << subsystem_name << " missing Type!\n"; +Dump_And_Die_2: + Unregister_Pointer(buffer); + delete[] buffer; + goto Dump_And_Die; + } + + Subsystem::SubsystemResource *sub_res = + (Subsystem::SubsystemResource*)subsystem_stream.GetPointer(); + if (!strcmp(sub_type, "DoorClassID")) + { + if ( + Door::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + (Door::SubsystemResource*)sub_res, + sub_file, + directories, + resource_file + ) == -1 + ) + { + goto Dump_And_Die_2; + } + } + else + { + std::cerr << model_name << ':' << subsystem_name + << " has an unknown component type of " << sub_type << std::endl; + goto Dump_And_Die_2; + } + subsystem_stream.AdvancePointer(sub_res->subsystemModelSize); + sub_entry = sub_entry->GetNextEntry(); + } + ResourceDescription *res_desc = resource_file-> + ResourceFile::AddResourceMemoryStream( + model_name, + ResourceDescription::SubsystemModelStreamResourceType, + 1, + ResourceDescription::Preload, + &subsystem_stream + ); + ResourceDescription::ResourceID res_id; + + if(!res_desc) + { + res_id = ResourceDescription::NullResourceID; + } + else + { + res_id = res_desc->resourceID; + } + + Unregister_Pointer(sub_filename); + delete sub_filename; + Unregister_Object(sub_file); + delete sub_file; + Unregister_Object(sub_namelist); + delete sub_namelist; + Unregister_Pointer(buffer); + delete[] buffer; + return res_id; + +} diff --git a/MUNGA/DOORFRAM.h b/MUNGA/DOORFRAM.h new file mode 100644 index 0000000..915ac4a --- /dev/null +++ b/MUNGA/DOORFRAM.h @@ -0,0 +1,52 @@ +#pragma once + +#include "terrain.h" + +//########################################################################## +//############################# DoorFrame ################################ +//########################################################################## + +class DoorFrame : public UnscalableTerrain +{ +public: +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Instance support +// + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model support +// + enum + { + BasicSubsystemCount + }; + +public: + typedef void (DoorFrame::*Performance)(Scalar time_slice); + + void SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + static Logical CreateMakeMessage(MakeMessage *creation_message, NotationFile *model_file, const ResourceDirectories *directories); + static ResourceDescription::ResourceID CreateSubsystemStream(ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories *directories); + + static DoorFrame* Make(MakeMessage *creation_message); + + DoorFrame(MakeMessage *creation_message, SharedData &virtual_data = DefaultData); + ~DoorFrame(); +}; \ No newline at end of file diff --git a/MUNGA/DROPZONE.cpp b/MUNGA/DROPZONE.cpp new file mode 100644 index 0000000..2e9c1ff --- /dev/null +++ b/MUNGA/DROPZONE.cpp @@ -0,0 +1,447 @@ +#include "munga.h" +#pragma hdrstop + +#include "dropzone.h" +#include "random.h" +#include "app.h" +#include "hostmgr.h" +#include "nttmgr.h" +#include "notation.h" +#include "namelist.h" +#include "player.h" + +#define DOWN_TIME 5.0f + +//############################################################################# +//############################### DropZone ################################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* DropZone::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(),"DropZone"); + return &classDerivations; +} + +DropZone::SharedData + DropZone::DefaultData( + DropZone::GetClassDerivations(), + DropZone::GetMessageHandlers(), + DropZone::GetAttributeIndex(), + DropZone::StateCount, + (Entity::MakeHandler)DropZone::Make + ); + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + DropZone::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(DropZone, AssignDropZone) +}; + +Receiver::MessageHandlerSet& DropZone::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(DropZone::MessageHandlerEntries), DropZone::MessageHandlerEntries, Entity::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DropZone::DropZone( + DropZone::MakeMessage *creation_message, + DropZone::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + + SetValidFlag(); + dropZoneCount = 0; + dropZones = NULL; + + // + //-------------------------------------------------------------- + // Name the drop zone, and enter the zone in the drop zone group + //-------------------------------------------------------------- + // + Str_Copy(dropZoneName, creation_message->dropZoneName, sizeof(dropZoneName)); + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup* drop_zones = entity_manager->UseGroup("DropZones"); + Check(drop_zones); + drop_zones->Add(this); + + // + //----------------------------------------------------------------------- + // Now, interpret the data to create the appropriate number of drop zones + //----------------------------------------------------------------------- + // + MemoryStream + stream( + creation_message, + creation_message->messageLength, + sizeof(*creation_message) + ); + dropZoneCount = creation_message->dropZoneCount; + Verify(dropZoneCount > 0); + dropZones = new Origin[dropZoneCount]; + Register_Pointer(dropZones); + lastUsageTime = new Time[dropZoneCount]; + Register_Pointer(lastUsageTime); + lastUsedBy = new EntityID[dropZoneCount]; + Register_Pointer(lastUsedBy); + lastDeathCount = new int[dropZoneCount]; + Register_Pointer(lastDeathCount); + + for (int i=0; i= 0 && index < dropZoneCount); + Check(application); + + return + !lastUsageTime[index].ticks + || Now() - lastUsageTime[index] > DOWN_TIME + && application->GetApplicationState() == Application::RunningMission; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DropZone::AssignDropZoneMessageHandler(AssignDropZoneMessage* message) +{ + Check(this); + Check_Pointer(message); + + Check(application); + HostManager *host = application->GetHostManager(); + Check(host); + Entity *entity = host->GetEntityPointer(message->requestingEntity); + Check(entity); + + // + //--------------------------------------------------------------------- + // If we have allocated a dropzone within the last ten seconds for this + // player, resend the data + //--------------------------------------------------------------------- + // + Origin *drop_zone = NULL; + int + lowest, highest, remaining, i; + for (i=0; irequestingEntity + && lastDeathCount[i] == message->deathCount + ) + { + lastUsageTime[i] = Now(); + drop_zone = &dropZones[i]; + goto Found_One; + } + } + + // + //------------------------------------------------------------------------ + // Figure out how many drop zones are available. If none are, repost this + // message to ourself + //------------------------------------------------------------------------ + // + lowest = dropZoneCount; + highest = -1; + remaining = 0; + for (i=0; i highest) + { + highest = i; + } + } + } + + // + //----------------------------------------------------- + // Now, randomly look about until we find one available + //----------------------------------------------------- + // + highest = highest - lowest + 1; + while (remaining) + { + i = lowest + Random(highest); + Verify(i < dropZoneCount && i >= 0); + if (IsAvailable(i)) + { + // + //------------------------------------------------------------------- + // Check to see if vehicle attached to a player is within 2 meters of + // this drop zone. If so, mark it unavailable for 3 seconds + //------------------------------------------------------------------- + // + EntityManager *entity_mgr = application->GetEntityManager(); + Check(entity_mgr); + EntityGroup *player_group = entity_mgr->FindGroup("Players"); + if ( + player_group + && application->GetApplicationState() + == Application::RunningMission + ) + { + Player *player; + ChainIteratorOf iterator(player_group->groupMembers); + while ((player = (Player*)iterator.ReadAndNext()) != NULL) + { + Check(player); + Entity *vehicle = player->GetPlayerVehicle(); + if (vehicle && player != entity) + { + Check(vehicle); + Vector3D distance; + distance.Subtract( + vehicle->localOrigin.linearPosition, + dropZones[i].linearPosition + ); + if (distance.LengthSquared() <= 4.0f) + { + lastUsedBy[i] = NULL; + lastUsageTime[i] = Now(); + lastUsageTime[i] -= DOWN_TIME - 1.0f; + --remaining; + if (i == lowest) + { + ++lowest; + --highest; + } + else if (i == lowest + highest - 1) + { + --highest; + } + break; + } + } + } + + // + //---------------------------------------------------------- + // If someone was in this spot, keep looking for another one + //---------------------------------------------------------- + // + if (player) + { + continue; + } + } + + lastUsageTime[i] = Now(); + drop_zone = &dropZones[i]; + lastUsedBy[i] = message->requestingEntity; + lastDeathCount[i] = message->deathCount; + remaining = 0; + } + } + + + // + //---------------------------------------------------------------- + // If no drop_zone could be found, repost the message to ourselves + //---------------------------------------------------------------- + // + if (!drop_zone) + { + Time when=Now(); + when += 0.1f; + application->Post(MaxEventPriority, this, message, when); + return; + } + + // + //-------------------------------------------------------------------- + // Send a message back to the requesting object what sent this message + //-------------------------------------------------------------------- + // +Found_One: + ReplyMessage + reply( + message->replyMessageID, + sizeof(ReplyMessage), + *drop_zone, + message->deathCount + ); + entity->Dispatch(&reply); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DropZone::CreateMakeMessage( + MakeMessage *creation_message, + const char* model_name, + const char* resource_name, + NotationFile *map_file + ) +{ + Check(creation_message); + Check(map_file); + Check_Pointer(model_name); + Check_Pointer(resource_name); + + if (!Entity::CreateMakeMessage(creation_message, map_file, NULL)) + { + return False; + } + + creation_message->classToCreate = RegisteredClass::DropZoneClassID; + creation_message->instanceFlags = MapFlag|TrappedFlag; + + // + //----------------------------------------------- + // Count up the number of drop zones in our model + //----------------------------------------------- + // + Enumeration save_modes = map_file->GetModes(); + map_file->SetMode(NotationFile::CleanListMode); + + NameList *zone_list = + map_file->MakeEntryList(model_name, "dropzone"); + Register_Object(zone_list); + creation_message->dropZoneCount = zone_list->EntryCount(); + creation_message->messageLength = + sizeof(*creation_message) + + creation_message->dropZoneCount*sizeof(Origin); + if (!creation_message->dropZoneCount) + { + std::cout << "Error: " << model_name << " hasn't specified any drop zones!\n"; +Dump_And_Die: + Unregister_Object(zone_list); + delete zone_list; + map_file->PutModes(save_modes); + return False; + } + + // + //--------------------------------------------- + // Allocate a buffer to hold the drop zone data + //--------------------------------------------- + // + MemoryStream + stream( + creation_message, + creation_message->messageLength, + sizeof(*creation_message) + ); + + // + //---------------------------- + // zero out the drop zone name + //---------------------------- + // + for (int ii=0; iidropZoneName); ii++) + { + creation_message->dropZoneName[ii] = '\0'; + } + + Str_Copy( + creation_message->dropZoneName, + resource_name, + sizeof(creation_message->dropZoneName) + ); + + // + //----------------- + // Read in the data + //----------------- + // + NameList::Entry *drop_zone = zone_list->GetFirstEntry(); + while (drop_zone) + { + Point3D translation; + EulerAngles tmp_rotation; + + const char* zone_data = drop_zone->GetChar(); + sscanf( + zone_data, + "%f %f %f %f %f %f", + &translation.x, + &translation.y, + &translation.z, + &tmp_rotation.pitch, + &tmp_rotation.yaw, + &tmp_rotation.roll + ); + + ((Origin*)stream.GetPointer())->linearPosition = translation; + ((Origin*)stream.GetPointer())->angularPosition = tmp_rotation; + stream.AdvancePointer(sizeof(Origin)); + drop_zone = drop_zone->GetNextEntry(); + } + + Unregister_Object(zone_list); + delete zone_list; + map_file->PutModes(save_modes); + + return True; +} + +Logical + DropZone::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/DROPZONE.h b/MUNGA/DROPZONE.h new file mode 100644 index 0000000..dac4506 --- /dev/null +++ b/MUNGA/DROPZONE.h @@ -0,0 +1,152 @@ +#pragma once + +#include "entity.h" +#include "cstr.h" + +//########################################################################## +//##################### Mover::ModelResource ######################### +//########################################################################## + +class DropZone__MakeMessage: + public Entity::MakeMessage +{ +public: + char dropZoneName[32]; + int dropZoneCount; +}; + +//########################################################################## +//################# DropZone::AssignDropZoneMessage ################## +//########################################################################## + +class DropZone__AssignDropZoneMessage: + public Entity::Message +{ +public: + EntityID + requestingEntity; + Receiver::MessageID + replyMessageID; + int + deathCount; + + DropZone__AssignDropZoneMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &reply_to, + Receiver::MessageID reply_ID, + int death_count + ): + Entity::Message(message_ID, length), + requestingEntity(reply_to), + replyMessageID(reply_ID), + deathCount(death_count) + {} +}; + +//########################################################################## +//##################### DropZone::ReplyMessage ########################## +//########################################################################## + +class DropZone__ReplyMessage: + public Entity::Message +{ +public: + Origin + dropZoneLocation; + int + deathCount; + + DropZone__ReplyMessage( + Receiver::MessageID message_ID, + size_t length, + const Origin &location, + int death_count + ): + Entity::Message(message_ID, length), + dropZoneLocation(location), + deathCount(death_count) + {} +}; + +//########################################################################## +//########################### DropZone ################################ +//########################################################################## + +class DropZone: + public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum { + AssignDropZoneMessageID = Entity::NextMessageID, + NextMessageID + }; + +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet& GetMessageHandlers(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef DropZone__MakeMessage MakeMessage; + + static DropZone* + Make(MakeMessage *creation_message); + + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + const char* model_name, + const char* resource_name, + NotationFile *map_file + ); + + DropZone( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~DropZone(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Dropzone assignment +// +public: + typedef DropZone__AssignDropZoneMessage AssignDropZoneMessage; + typedef DropZone__ReplyMessage ReplyMessage; + + const char* + GetDropZoneName() + {Check(this); return dropZoneName;} + + Logical + IsAvailable(int index); + +protected: + int dropZoneCount; + char dropZoneName[32]; + Origin *dropZones; + Time *lastUsageTime; + EntityID *lastUsedBy; + int *lastDeathCount; + + void + AssignDropZoneMessageHandler(AssignDropZoneMessage *message); +}; diff --git a/MUNGA/ENTITY.cpp b/MUNGA/ENTITY.cpp new file mode 100644 index 0000000..2fa4fe4 --- /dev/null +++ b/MUNGA/ENTITY.cpp @@ -0,0 +1,1571 @@ +#include "munga.h" +#pragma hdrstop + +#include "entity.h" +#include "interest.h" +#include "exptbl.h" +#include "hostmgr.h" +#include "player.h" +#include "audio.h" +#include "fileutil.h" +#include "registry.h" +#include "event.h" +#include "app.h" +#include "nttmgr.h" +#include "subsystm.h" +#include "namelist.h" +#include "notation.h" + +#if defined(TRACE_EXECUTE_ENTITY) + static BitTrace Execute_Entity("Execute Entity"); + #define SET_EXECUTE_ENTITY() Execute_Entity.Set() + #define CLEAR_EXECUTE_ENTITY() Execute_Entity.Clear() +#else + #define SET_EXECUTE_ENTITY() + #define CLEAR_EXECUTE_ENTITY() +#endif + +#if defined(TRACE_PERFORM_ENTITY) + static BitTrace Perform_Entity("Perform Entity"); + #define SET_PERFORM_ENTITY() Perform_Entity.Set() + #define CLEAR_PERFORM_ENTITY() Perform_Entity.Clear() +#else + #define SET_PERFORM_ENTITY() + #define CLEAR_PERFORM_ENTITY() +#endif + +#if defined(TRACE_PERFORM_SUBSYSTEMS) + static BitTrace Perform_Subsystems("Perform Subsystems"); + #define SET_PERFORM_SUBSYSTEMS() Perform_Subsystems.Set() + #define CLEAR_PERFORM_SUBSYSTEMS() Perform_Subsystems.Clear() +#else + #define SET_PERFORM_SUBSYSTEMS() + #define CLEAR_PERFORM_SUBSYSTEMS() +#endif + +//############################################################################# +//############################## Entity ################################# +//############################################################################# + +//############################################################################# +// Virtual Data support +// +Derivation* Entity::GetClassDerivations() +{ + static Derivation classDerivations(Simulation::GetClassDerivations(), "Entity"); + return &classDerivations; +} + +Entity::SharedData + Entity::DefaultData( + Entity::GetClassDerivations(), + Entity::GetMessageHandlers(), + Entity::GetAttributeIndex(), + Entity::StateCount, + Entity::Make + ); + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Entity::MessageHandlerEntries[]= +{ + { + Entity::MakeMessageID, + "Make", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::MakeReadyMessageID, + "MakeReady", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeEntityMessageID, + "RemakeEntity", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeReadyMessageID, + "RemakeReady", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeCompleteMessageID, + "RemakeComplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::RemakeIncompleteMessageID, + "RemakeIncomplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + MESSAGE_ENTRY(Entity, DestroyEntity), + { + Entity::TransferEntityMessageID, + "TransferEntity", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::TransferCompleteMessageID, + "TransferComplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::TransferIncompleteMessageID, + "TransferIncomplete", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + MESSAGE_ENTRY(Entity, BecomeInteresting), + MESSAGE_ENTRY(Entity, BecomeUninteresting), + MESSAGE_ENTRY(Entity, Update), + { + Entity::SubscribeReplicantMessageID, + "SubscribeReplicant", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + { + Entity::UnsubscribeReplicantMessageID, + "UnsubscribeReplicant", + (Entity::Handler)&Entity::DefaultMessageHandler + }, + MESSAGE_ENTRY(Entity, TakeDamage), + MESSAGE_ENTRY(Entity, PlayerLink), + MESSAGE_ENTRY(Entity, TakeDamageStream) +}; + +Entity::MessageHandlerSet& Entity::GetMessageHandlers() +{ + static Entity::MessageHandlerSet messageHandlers(ELEMENTS(Entity::MessageHandlerEntries), Entity::MessageHandlerEntries, Receiver::GetMessageHandlers()); + return messageHandlers; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::Receive(Event* event) +{ + Check(this); + Check(event); + + // + //------------------------------------------------------------------------- + // If the entity is being transferred, post the message to the new owner of + // the entity + //------------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------------- + // If the object is not valid, filter the message to determine which ones to + // defer and which ones to immediately process + //-------------------------------------------------------------------------- + // + if (!IsValid()) + { + //switch case commented out by Ryan Bunker on 1/6/07 + //switch (event->messageToSend->messageID) + { + // + //---------------------------------------------------------------------- + // The messages which should be allowed through should just break out of + // this switch + //---------------------------------------------------------------------- + // + + //default: + // + //------------------- + // Defer the messages + //------------------- + // + event->Defer(); + return; + } + } + + // + //------------------------------------------------ + // Go ahead and dispatch the message to the entity + //------------------------------------------------ + // + Receiver::Receive(event); + + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + Receiver::MessageHandlerSet *handlers = + shared_data->activeMessageHandlers; + DEBUG_STREAM << derivation->className << ',' << GetInstance() << endl << std::flush; + DEBUG_STREAM << handlers->GetName(event->messageToSend->messageID) + << endl; + Fail("Event corrupted FPU!"); + } + #else + Check_Fpu(); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::Dispatch(Receiver::Message* incoming) +{ + Message *message = (Message*) incoming; + Check(this); + Check(message); + + // + // Call Receiver if it is not entity aware!!!!! + // + if (message->messageID < Receiver::NextMessageID) + { + Receiver::Dispatch(message); + } + + // + //----------------------------------------- + // Initialize the entity information fields + //----------------------------------------- + // + message->entityID = entityID; + message->interestZoneID = interestZoneID; + + // + //------------------------------------------------------------------- + // If this is a replicant instance, reroute the message to the master + //------------------------------------------------------------------- + // + if (GetInstance() == ReplicantInstance) + { + application->SendMessage( + ownerID, + EntityManager::EntityManagerClientID, + message + ); + } + + // + //-------------------------------------------------------- + // If this entity is invalid, post the message as an event + //-------------------------------------------------------- + // + else if (!IsValid()) + { + // ECH 1/28/96 - application->Post(DefaultEventPriority, this, message); + application->Post(EntityInvalidEventPriority, this, message); + } + + // + //-------------------------------------------- + // Otherwise, go ahead and receive the message + //-------------------------------------------- + // + else + { + Receiver::Receive(message); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::DispatchToReplicants(Message *what) +{ + Check(this); + Check(what); + + what->entityID = entityID; + what->interestZoneID = interestZoneID; + Check(application); + InterestManager *int_mgr = application->GetInterestManager(); + Check(int_mgr); + int_mgr->EntityBroadcastToReplicants(this, what); + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const Entity::IndexEntry + Entity::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Entity, LocalToWorld, localToWorld), + ATTRIBUTE_ENTRY(Entity, LocalOrigin, localOrigin), + ATTRIBUTE_ENTRY(Entity, DamageZoneCount, damageZoneCount), + ATTRIBUTE_ENTRY(Entity, DamageZones, damageZones) +}; + +Entity::AttributeIndexSet& Entity::GetAttributeIndex() +{ + static Entity::AttributeIndexSet attributeIndex(ELEMENTS(Entity::AttributePointers), + Entity::AttributePointers, + Simulation::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::WriteUpdateRecord( + Simulation::UpdateRecord *record, + int update_model + ) +{ + Check(this); + Check_Pointer(record); + + switch (update_model) + { + case DefaultUpdateModelBit: + { + Simulation::WriteUpdateRecord(record, update_model); + + // + //---------------------------- + // Write out the record update + //---------------------------- + // + UpdateRecord *update = (UpdateRecord*)record; + update->localOrigin = localOrigin; + updateOrigin = localOrigin; + update->recordLength = sizeof(*update); + } + break; + case DamageZoneUpdateModelBit: + record->timeStamp = lastPerformance; + record->recordID = (Word)update_model; + WriteDamageUpdateRecord(record); + break; + + default: + Simulation::WriteUpdateRecord(record, update_model); + break; + } + record->subsystemID = (Word)(EntitySubsystemID + 1); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::UpdateMessageHandler(UpdateMessage *message) +{ + Check(this); + Check(message); + + // + //------------------------------------------------------ + // Position to the beginning of the update record blocks + //------------------------------------------------------ + // + MemoryStream stream(message, message->messageLength, sizeof(*message)); + + // + //------------------------------------------------------------------------ + // Step through each block until there are no more remaining, and send the + // update out the the simulation indicated by the subsystemID + //------------------------------------------------------------------------ + // + while (stream.GetBytesRemaining()) + { + Simulation::UpdateRecord *update = + (Simulation::UpdateRecord*)stream.GetPointer(); + Check_Pointer(update); + Simulation *simulation = GetSimulation((int)update->subsystemID-1); + Check(simulation); + simulation->ReadUpdateRecord(update); + stream.AdvancePointer(update->recordLength); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::ReadUpdateRecord(Simulation::UpdateRecord *record) +{ + Check(this); + Check_Pointer(record); + + switch(record->recordID) + { + case DefaultUpdateModelBit: + { + // + //----------------------- + // Read the record update + //----------------------- + // + UpdateRecord *update = (UpdateRecord*)record; + updateOrigin = update->localOrigin; + + // + //------------------------------------------------------------------ + // If we aren't able to run yet, we must update local origin as well + //------------------------------------------------------------------ + // + Check(application); + int app_state = application->GetApplicationState(); + if ( + app_state < Application::RunningMission + || app_state == Application::CreatingMission + ) + { + localOrigin = updateOrigin; + localToWorld = localOrigin; + } + Simulation::ReadUpdateRecord(record); + } + break; + case DamageZoneUpdateModelBit: + ReadDamageUpdateRecord(record); + break; + default: + Simulation::ReadUpdateRecord(record); + } + + + + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::ReadDamageUpdateRecord(Simulation::UpdateRecord *update_record) +{ + // + //------------------------------------------------------------------------ + // Step through each block until there are no more remaining, and send the + // update out the the damageZone indicated by the damageZoneIndex + //------------------------------------------------------------------------ + // + MemoryStream stream( + update_record, + update_record->recordLength, + sizeof(*update_record) + ); + + while (stream.GetBytesRemaining()) + { + DamageZone::UpdateRecord *damage_zone_record = + (DamageZone::UpdateRecord*)stream.GetPointer(); + int damage_zone_index = damage_zone_record->damageZoneIndex; + damageZones[damage_zone_index]->ReadUpdateRecord(damage_zone_record); + stream.AdvancePointer(damage_zone_record->recordLength); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define MAX_UPDATE_LENGTH 1400 + +static long Update_Buffer[MAX_UPDATE_LENGTH >> 2]; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::WriteDamageUpdateRecord(Simulation::UpdateRecord *update_record) +{ + Check(this); + Check_Pointer(update_record); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make a memory stream this size of a network packet + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + MemoryStream stream( + update_record, + sizeof(Update_Buffer) - ((char*)update_record - (char*)Update_Buffer), + sizeof(*update_record) + ); + DamageZone::UpdateRecord *record_start = + (DamageZone::UpdateRecord*)stream.GetPointer(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Update Every DamageZone For NOW + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;iiWriteUpdateRecord(damage_zone_update); + stream.AdvancePointer(damage_zone_update->recordLength); + } + + // + //----------------------------------------------- + // Check to see if an update message is necessary + //----------------------------------------------- + // + if (stream.GetPointer() != record_start) + { + Simulation::UpdateRecord *damage_update = + (Simulation::UpdateRecord*)update_record; + damage_update->recordLength = + (char*)stream.GetPointer() - (char*)update_record; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity::UpdateMessage* + Entity::Execute(const Time& till) +{ + SET_EXECUTE_ENTITY(); + Check(this); + Check(&till); + + MemoryStream + stream(Update_Buffer, sizeof(Update_Buffer), sizeof(UpdateMessage)); + char *record_start = (char*)stream.GetPointer(); + + // + //----------------------------------------------------------------------- + // Check to see if the application will let us run. If We are starting a + // mission, only the player class objects can execute + //----------------------------------------------------------------------- + // + Check(application); + if ( + application->GetApplicationState() == Application::RunningMission + || application->GetApplicationState() == Application::EndingMission + || IsPreRunnable() + ) + { + PerformAndWatch(till, &stream); + } + else + { + WriteSimulationUpdate(&stream); + } + + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + DEBUG_STREAM << derivation->className << ',' << GetInstance() << endl << std::flush; + Fail("Simulation corrupted FPU!"); + } + #endif + + // + //----------------------------------------------- + // Check to see if an update message is necessary + //----------------------------------------------- + // + if (stream.GetPointer() != record_start) + { + UpdateMessage *update = (UpdateMessage*)Update_Buffer; + update->messageID = UpdateMessageID; + update->messageLength = (char*)stream.GetPointer() - (char*)Update_Buffer; + update->messageFlags = 0; + CLEAR_EXECUTE_ENTITY(); + return update; + } + + // + //------------------------------------- + // Otherwise, return NULL for no update + //------------------------------------- + // + Check_Fpu(); + CLEAR_EXECUTE_ENTITY(); + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation* + Entity::GetSimulation(int index) +{ + Check(this); + + if (index == EntitySubsystemID) + { + return this; + } + + Check_Fpu(); + if ((unsigned)index < subsystemCount) + { + return subsystemArray[index]; + } + else + { + return NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Subsystem* + Entity::FindSubsystem(const char* name) +{ + Check(this); + Check_Pointer(name); + + for (int i=0; iGetName(), name)) + { + return subsystemArray[i]; + } + } + } + Check_Fpu(); + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define MAX_SUB_FILE_NAME (256) + +int + Entity::FindSubsytemID + ( +#if DEBUG_LEVEL>0 + const char *model_name, + const char *subsystem_name +#else + const char *, + const char *subsystem_name +#endif + ) +{ + Check_Pointer(model_name); + Check_Pointer(subsystem_name); + + int subsytem_id = EntitySubsystemID; + int sub_count = 0; + + CString sub_file_string; + CString sub_directory_string("models\\"); + CString model_name_string("model_name"); + CString sub_post_string(".sub"); + + sub_file_string = + sub_directory_string + model_name_string + sub_post_string; + + NotationFile sub_file(sub_file_string); + Check(&sub_file); + + NameList *page_list = sub_file.MakePageList(); + Register_Object(page_list); + NameList::Entry *entry=page_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + Check_Pointer(entry->GetName()); + if (!stricmp(subsystem_name, entry->GetName())) + { + subsytem_id = sub_count; + break; + } + + ++sub_count; + entry = entry->GetNextEntry(); + } + + Unregister_Object(page_list); + delete page_list; + + return subsytem_id; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::PerformAndWatch( + const Time &till, + MemoryStream *update_stream + ) +{ + Check(this); + Check(&till); + + // + //----------------------------------------- + // Execute all the subsystems, then ourself + //----------------------------------------- + // + SET_PERFORM_SUBSYSTEMS(); + if (subsystemArray) + { + Check_Pointer(subsystemArray); + + // + //--------------------------------------------------- + // If this is not a replicant, execute all subsystems + //--------------------------------------------------- + // + if (GetInstance() != ReplicantInstance) + { + for (int i=0; iIsNonReplicantExecutable()) + { + subsystem->PerformAndWatch(till, update_stream); + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + DEBUG_STREAM << derivation->className + << "\nExecuting subsystem[" << i << "], " + << subsystem->GetName() << endl; + Fail("Simulation corrupted FPU!"); + } + #endif + } + } + } + } + + // + //-------------------------------------------------------------------- + // If this is a replicant, execute only those subsystems which need to + //-------------------------------------------------------------------- + // + else + { + for (int i=0; iIsReplicantExecutable()) + { + subsystem->PerformAndWatch(till, update_stream); + #if defined(USE_FPU_ANALYSIS) + if (!Fpu_Ok()) + { + Registry *registry = application->GetRegistry(); + Receiver::SharedData *shared_data = + registry->GetStaticData(GetClassID()); + Derivation *derivation = shared_data->derivedClasses; + DEBUG_STREAM << derivation->className + << " replicant\nExecuting subsystem[" << i << "], " + << subsystem->GetName() << endl; + Fail("Simulation corrupted FPU!"); + } + #endif + } + } + } + } + } + CLEAR_PERFORM_SUBSYSTEMS(); + + SET_PERFORM_ENTITY(); + Simulation::PerformAndWatch(till, update_stream); + Check_Fpu(); + CLEAR_PERFORM_ENTITY(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::PlayerLinkMessageHandler(PlayerLinkMessage *message) +{ + Check(application); + HostManager *host = application->GetHostManager(); + Check(host); + playerLink =(Player*) host->GetEntityPointer(message->playerID); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::TakeDamageStreamMessageHandler(TakeDamageStreamMessage *message) +{ + Check(this); + Check(message); + + // + //------------------------------------------------- + // Extract the common information out of the stream + //------------------------------------------------- + // + Damage damage_data; + EntityID shooting_entity = message->shootingEntity; + int damage_zone_index = message->damageZoneIndex; + damage_data.impactPoint = message->impactPoint; + + // + //--------------------------------------------------- + // Figure out how many damage messages there are here + //--------------------------------------------------- + // + DynamicMessage damage_stream( + message, + message->messageLength, + sizeof(*message) + ); + int entry_count; + damage_stream >> entry_count; + + for (int i=0; i> damage_data.damageType >> damage_data.damageAmount; + int subsystem; + damage_stream >> subsystem; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Apply the damage to the appropriate damageZone + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + TakeDamageMessage + message( + TakeDamageMessageID, + sizeof(TakeDamageMessage), + shooting_entity, + damage_zone_index, + damage_data, + subsystem + ); + Dispatch(&message); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::TakeDamageMessageHandler(TakeDamageMessage *message) +{ + // + //------------------------------------- + // YOU MUST CHECK FOR -1 DamageZone!!!! + //------------------------------------- + // + if (!damageZones || message->damageZone == -1) + { + return; + } + + // + //---------------------------------------------------------------------- + // If we have no damage zones allocated, we ignore any damage sent to us + //---------------------------------------------------------------------- + // + Verify(message->damageZone < damageZoneCount); + Verify(message->damageZone >= 0 ); + Check_Pointer(damageZones); + Check(damageZones[message->damageZone]); + damageZones[message->damageZone]->TakeDamage(message->damageData); + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity::Entity( + Entity::MakeMessage *creation_message, + Entity::SharedData &virtual_data +): + Simulation(creation_message->classToCreate,virtual_data), + staticVideoSocket(NULL), + dynamicVideoSocket(NULL), + audioSocket(NULL) +{ + Check_Pointer(this); + Check(creation_message); + + // + // Get host manager pointer + // + HostManager *host_manager; + + Check(application); + host_manager = application->GetHostManager(); + Check(host_manager); + + // + //----------------------------- + // Initialize the entity fields + //----------------------------- + // + playerLink = NULL; + resourceID = creation_message->resourceID; + owningPlayer = (Player*)host_manager->GetEntityPointer( + creation_message->owningPlayerID + ); + simulationFlags = creation_message->instanceFlags; + entityID = creation_message->entityID; + ownerID = creation_message->ownerID; + creationTime = Now(); + interestZoneID = creation_message->interestZoneID; + interestCount = 0; + + // initialize attributes + localOrigin = creation_message->localOrigin; + updateOrigin = localOrigin; + localToWorld = localOrigin; + + // initialize camera stuff + cameraOffset = Origin::Identity; + + SetInvalidFlag(); + + // initialize model stuff + lastPerformance = creationTime; + subsystemCount = 0; + subsystemArray = NULL; + damageZones = NULL; + damageZoneCount = 0; + + // + //-------------------------------- + // Allocate the damageZones array + //-------------------------------- + // + + // + // Read In DamageZones and Create DamageZoneID's + // + if (resourceID != ResourceDescription::NullResourceID) + { + ResourceDescription *dmg_res = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::DamageZoneStreamResourceType + ); + + // + //-------------------------------------------- + // Allocate damageZones for this entity only + // if they were defined in the resource + //-------------------------------------------- + // + if (dmg_res) + { + dmg_res->Lock(); + DynamicMemoryStream damage_zone_stream( + dmg_res->resourceAddress, + dmg_res->resourceSize); + + damage_zone_stream >> damageZoneCount; + damageZones = new (::DamageZone(*[damageZoneCount])); + Register_Pointer(damageZones); + dmg_res->Unlock(); + } + } + + // + //--------------------------------------------------------- + // Create a new entity ID and assign ownership to this host + // If (this is a master entity) or + // (this is a dynamic hermit) or + // (this is the initial independent) + //--------------------------------------------------------- + // + if ( + (GetInstance() == MasterInstance) || + (GetInstance() == HermitInstance && IsDynamic()) || + ( + (GetInstance() == IndependantInstance) && + (creation_message->ownerID == NullHostID || + creation_message->ownerID == MapHostID) + ) + ) + { + entityID = host_manager->MakeUniqueEntityID(); + ownerID = host_manager->GetLocalHostID(); + creation_message->entityID = entityID; + creation_message->ownerID = ownerID; + } + + // + //-------------------------------------------- + // Tell the host manager about this new entity + //-------------------------------------------- + // + Check(host_manager); + host_manager->NotifyOfEntityCreation(this, creation_message); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity* + Entity::Make(Entity::MakeMessage *creation_message) +{ + return new Entity(creation_message,DefaultData); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Entity::CreateMakeMessage( + MakeMessage *creation_message, +#if DEBUG_LEVEL>0 + NotationFile *model_file, +#else + NotationFile *, +#endif + const ResourceDirectories * + ) +{ + Check(creation_message); + Check(model_file); + char *p; + + creation_message->messageLength = sizeof(Entity::MakeMessage); + creation_message->messageID = Entity::MakeMessageID; + creation_message->owningPlayerID = EntityID::Null; + creation_message->messageFlags = 0; + creation_message->classToCreate = RegisteredClass::TrivialEntityClassID; + creation_message->instanceFlags = 0; //DefaultFlags; + + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "X position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.x = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Y position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.y = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Z position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.z = atof(p); + + EulerAngles pyr; + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Pitch missing!\n"; + return False; + } + pyr.pitch = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Yaw missing!\n"; + return False; + } + pyr.yaw = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Roll missing!\n"; + return False; + } + pyr.roll = atof(p); + creation_message->localOrigin.angularPosition = pyr; + return True; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Entity::CreateMakeMapMessage( + MakeMapMessage *creation_message, + ResourceDescription::ResourceID resource_id, +#if DEBUG_LEVEL>0 + NotationFile *model_file, +#else + NotationFile *, +#endif + const ResourceDirectories * + ) +{ + Check(creation_message); + Check(model_file); + char *p; + + creation_message->messageLength = sizeof(Entity::MakeMapMessage); + creation_message->messageID = Entity::MakeMessageID; + creation_message->messageFlags = Entity::MakeMessage::MapStreamMarkerFlag; + + + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "X position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.x = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Y position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.y = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Z position coordinate missing!\n"; + return False; + } + creation_message->localOrigin.linearPosition.z = atof(p); + + EulerAngles pyr = EulerAngles::Identity; +#if 0 + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Pitch missing!\n"; + return False; + } + pyr.pitch = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Yaw missing!\n"; + return False; + } + pyr.yaw = atof(p); + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Roll missing!\n"; + return False; + } + pyr.roll = atof(p); +#endif + + creation_message->localOrigin.angularPosition = pyr; + creation_message->resourceID = resource_id; + + return True; + +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Entity::DestroyEntityMessageHandler(Message *) +{ + CondemnToDeathRow(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity::~Entity() +{ + // + // Notify the host manager that we are going away + // + Check(application); + application->GetHostManager()->NotifyOfEntityDestruction(this); + + // + // Delete the subsystem array + // + if (subsystemArray) + { + Check_Pointer(subsystemArray); + for (int i=0; iGetEntityManager(); + Check(entity_manager); + + // + //------------------------------------------------- + // Make sure we are not entered into deathrow twice + //------------------------------------------------- + // + if (!IsCondemned()) + { + entity_manager->deathRow->Add(this); + SetCondemnedFlag(); + NeverExecute(); + } + Check_Fpu(); +} + +//############################################################################# +// Test Support +// + +Logical + Entity::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//########################################################################## +// Renderer Support +// +void + Entity::AddStaticVideoComponent(Component *component) +{ + Check(component); + Check(&staticVideoSocket); + staticVideoSocket.Add(component); + Check_Fpu(); +} + +void + Entity::AddDynamicVideoComponent(Component *component) +{ + Check(component); + Check(&dynamicVideoSocket); + dynamicVideoSocket.Add(component); + Check_Fpu(); +} + +void + Entity::AddAudioComponent(Component *component) +{ + Check(component); + Check(&audioSocket); + audioSocket.Add(component); + Check_Fpu(); +} + +Enumeration + Entity::GetAudioRepresentation(Entity *linked_entity) +{ + Check(this); + Check(linked_entity); + + return + (linked_entity == this) ? + InternalAudioRepresentation : ExternalAudioRepresentation; +} + +//############################################################################# +// Interest Support +// +void + Entity::BecomeInteresting() +{ + BecomeInterestingMessage + message( + Entity::BecomeInterestingMessageID, + sizeof(BecomeInterestingMessage) + ); + + Receiver::Dispatch(&message); + Check_Fpu(); +} + +void Entity::BecomeInterestingMessageHandler(const Receiver::Message*) +{ + ++interestCount; + Check_Fpu(); +} + +void + Entity::BecomeUninterestingMessageHandler() +{ + --interestCount; + Check_Fpu(); +} + +Enumeration + Entity::GetInterestPriority(Entity *linked_entity) +{ + Check(this); + Check(linked_entity); + + return (linked_entity == this) ? HighInterestPriority : LowInterestPriority; +} + + + +int + Entity::GetDamageZoneIndex(const CString &damage_zone_name) const +{ + + for(int ii=0;iidamageZoneName.Compare(damage_zone_name) == 0) + { + return ii; + } + } + return -1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + Entity::CreateDamageZoneStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .dmg file + //------------------- + // + const char* dmg_file_cname; + if ( + !model_file->GetEntry( + "gamedata", + "DamageZones", + &dmg_file_cname + ) + ) + { + std::cerr << model_name << " is missing .dmg file specification!\n"; + return -1; + } + + CString dmg_filename = + MakePathedFilename(directories->modelDirectory, dmg_file_cname); + + NotationFile *dmg_file = new NotationFile(dmg_filename); + Register_Object(dmg_file); + int page_count = dmg_file->PageCount(); + if (!page_count) + { + std::cerr << dmg_filename << " is empty or missing!\n"; + Unregister_Object(dmg_file); + delete dmg_file; + return -1; + } + + DynamicMemoryStream damage_stream; + + damage_stream << page_count; + NameList *dmg_namelist = dmg_file->MakePageList(); + Register_Object(dmg_namelist); + + NameList::Entry *dmg_entry = dmg_namelist->GetFirstEntry(); + + CString dmg_page_name; + while(dmg_entry) + { + dmg_page_name = dmg_entry->GetName(); + DamageZone::CreateStreamedDamageZone( + model_file, + model_name, + NULL, + dmg_page_name, + &damage_stream, + dmg_file, + directories + ); + dmg_entry = dmg_entry->GetNextEntry(); + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Add Stream to Resource + //~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *new_res = + resource_file->AddResourceMemoryStream( + model_name, + ResourceDescription::DamageZoneStreamResourceType, + 1, + ResourceDescription::Preload, + &damage_stream + ); + Check(new_res); + + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dmg_namelist); + delete dmg_namelist; + + return new_res->resourceID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + Entity::CreateExplosionTableStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + // + //~~~~~~~~~~~~~~~~~ + // Find *.dmg file + //~~~~~~~~~~~~~~~~~ + // + const char *entry_data; + if (!model_file->GetEntry( + "gamedata", + "DamageZones", + &entry_data + ) + ) + { + DEBUG_STREAM << model_name << " is missing .dmg file specification!\n" << std::flush; + return -1; + } + CString filename = + MakePathedFilename(directories->modelDirectory, entry_data); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make a notation file of the DMG Entries + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NotationFile *dmg_file = new NotationFile(filename); + Register_Object(dmg_file); + + if(dmg_file->IsEmpty()) + { + DEBUG_STREAM << model_name << " *.dmg file is empty or missing!\n" << std::flush; + Unregister_Object(dmg_file); + delete dmg_file; + return -1; + } + + DynamicMemoryStream explosion_stream; + NameList *dmg_namelist = dmg_file->MakePageList(); + Register_Object(dmg_namelist); + + NameList::Entry *dmg_entry = dmg_namelist->GetFirstEntry(); + while(dmg_entry) + { + const char *entry_data; + if (dmg_file->GetEntry( + dmg_entry->GetName(), + "ExplosionTable", + &entry_data + ) + ) + { + CString filename = + MakePathedFilename(directories->modelDirectory, entry_data); + + NotationFile *exp_file = new NotationFile(filename); + Register_Object(exp_file); + + if(exp_file->IsEmpty()) + { + std::cerr<GetNextEntry(); + } + + ResourceDescription *new_res = + resource_file->AddResourceMemoryStream( + model_name, + ResourceDescription::ExplosionTableStreamResourceType, + 1, + ResourceDescription::Preload, + &explosion_stream + ); + Check(new_res); + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dmg_namelist); + delete dmg_namelist; + return new_res->resourceID; +} + +#if defined(TEST_CLASS) +# include "entity.tcp" +#endif diff --git a/MUNGA/ENTITY.h b/MUNGA/ENTITY.h new file mode 100644 index 0000000..4f53fba --- /dev/null +++ b/MUNGA/ENTITY.h @@ -0,0 +1,621 @@ +#pragma once + +#include "simulate.h" +#include "origin.h" +#include "linmtrx.h" + +class Player; +class NotationFile; +class DamageZone; +class Damage; +class Subsystem; + +#define ENTITY_CONTINUATION +#include "entity2.h" + +//########################################################################## +//########################### Entity ################################# +//########################################################################## + +class Entity: + public Simulation +{ + friend class Entity__StaticVideoSocketIterator; + friend class Entity__DynamicVideoSocketIterator; + friend class Entity__AudioSocketIterator; + friend class Entity__GaugeSocketIterator; + friend class Entity__AudioLocationIterator; + +//########################################################################## +// Shared Data support +// +public: + typedef Entity__SharedData SharedData; + SharedData* + GetSharedData(); + + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//########################################################################## +// Message Support +// +public: + enum { + MakeMessageID = Simulation::NextMessageID, + MakeReadyMessageID, + RemakeEntityMessageID, + RemakeReadyMessageID, + RemakeCompleteMessageID, + RemakeIncompleteMessageID, + DestroyEntityMessageID, + TransferEntityMessageID, + TransferCompleteMessageID, + TransferIncompleteMessageID, + BecomeInterestingMessageID, + BecomeUninterestingMessageID, + UpdateMessageID, + SubscribeReplicantMessageID, + UnsubscribeReplicantMessageID, + TakeDamageMessageID, + TakeDamageStreamMessageID, + PlayerLinkMessageID, + NextMessageID + }; + + typedef Entity__Message Message; + typedef Entity__MakeMessage MakeMessage; + typedef Entity__MakeReadyMessage MakeReadyMessage; + typedef Entity__RemakeEntityMessage RemakeEntityMessage; + typedef Entity__RemakeReadyMessage RemakeReadyMessage; + typedef Entity__RemakeCompleteMessage RemakeCompleteMessage; + typedef Entity__RemakeIncompleteMessage RemakeIncompleteMessage; + typedef Entity__DestroyEntityMessage DestroyEntityMessage; + typedef Entity__TransferEntityMessage TransferEntityMessage; + typedef Entity__TransferCompleteMessage TransferCompleteMessage; + typedef Entity__TransferIncompleteMessage TransferIncompleteMessage; + typedef Entity__BecomeInterestingMessage BecomeInterestingMessage; + typedef Entity__BecomeUninterestingMessage BecomeUninterestingMessage; + typedef Entity__UpdateMessage UpdateMessage; + typedef Entity__SubscribeReplicantMessage SubscribeReplicantMessage; + typedef Entity__UnsubscribeReplicantMessage UnsubscribeReplicantMessage; + typedef Entity__TakeDamageMessage TakeDamageMessage; + typedef Entity__TakeDamageStreamMessage TakeDamageStreamMessage; + typedef Entity__PlayerLinkMessage PlayerLinkMessage; + typedef Entity__DynamicMessage DynamicMessage; + typedef Entity__MakeMapMessage MakeMapMessage; + + + void + Receive(Event *event); + + void + LocalDispatch(Message *what) + {Receiver::Receive(Cast_Object(Receiver::Message*,what));} + + void + Dispatch(Receiver::Message *what); + + void + DispatchToReplicant( + Message *what, + HostID host + ); + + void + DispatchToReplicants(Message *what); + +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//########################################################################## +// Attribute Support +// +public: + enum { + LocalToWorldAttributeID = Simulation::NextAttributeID, + LocalOriginAttributeID, + DamageZoneCountAttributeID, + DamageZonesAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + LinearMatrix localToWorld; + Origin localOrigin; + int damageZoneCount; + DamageZone **damageZones; + + + int + GetDamageZoneIndex(const CString &damage_zone_name) const; + + +// +// virtual access +// +public: + virtual Vector3D + GetWorldLinearVelocity() + {return Vector3D(0.0f, 0.0f, 0.0f);} + virtual Vector3D + GetWorldLinearAcceleration() + {return Vector3D(0.0f, 0.0f, 0.0f);} + +//########################################################################## +// Model Support +// +public: + UpdateMessage* + Execute(const Time &till); + + Subsystem* + GetSubsystem(int index) + { + Check(this); Verify((unsigned)index < subsystemCount); + return subsystemArray[index]; + } + Simulation* + GetSimulation(int index); + int + GetSubsystemCount() + {Check(this); return subsystemCount;} + Subsystem* + FindSubsystem(const char* name); + + typedef void + (Entity::*Performance)(Scalar time_slice); + + typedef Entity__UpdateRecord UpdateRecord; + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + enum { + EntitySubsystemID = -1 + }; + + static int + FindSubsytemID( + const char *model_name, + const char *subsystem_name + ); +public: + + enum { + DamageZoneUpdateModelBit = Simulation::NextUpdateModelBit, + NextUpdateModelBit + }; + + enum { + DamageZoneUpdateModelFlag = 1 << DamageZoneUpdateModelBit + }; + + Logical DamageZoneUpdateModelFlagSet() + { + Check(this); + return ((updateModel & DamageZoneUpdateModelFlag) != 0); + } + +protected: + + void + WriteUpdateRecord( + Simulation::UpdateRecord *message, + int update_model + ); + void + UpdateMessageHandler(UpdateMessage *message); + + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + void + ReadDamageUpdateRecord(Simulation::UpdateRecord *update_record); + + void + WriteDamageUpdateRecord(Simulation::UpdateRecord *update_record); + + void + PerformAndWatch( + const Time &till, + MemoryStream *update_stream + ); + + int + subsystemCount; + Subsystem + **subsystemArray; + Origin + updateOrigin; + + void + TakeDamageStreamMessageHandler(TakeDamageStreamMessage *message); + void + TakeDamageMessageHandler(TakeDamageMessage *message); + void + PlayerLinkMessageHandler(PlayerLinkMessage *message); + +//########################################################################## +// Renderer Support +// +public: + void + AddStaticVideoComponent(Component *component); + void + AddDynamicVideoComponent(Component *component); + void + AddAudioComponent(Component *component); + + typedef Entity__StaticVideoSocketIterator + StaticVideoSocketIterator; + typedef Entity__DynamicVideoSocketIterator + DynamicVideoSocketIterator; + typedef Entity__AudioSocketIterator + AudioSocketIterator; + + virtual Enumeration + GetAudioRepresentation(Entity *linked_entity); + +private: + SChainOf + staticVideoSocket; + SChainOf + dynamicVideoSocket; + SChainOf + audioSocket; + +//########################################################################## +// Flag Support +// +public: + // + // MasterInstance - created on owning host, replicated on remote hosts, + // sends updates to replicants + // ReplicantInstance - created on remote hosts, receives updates from + // MasterInstance + // IndependantInstance - created on owning host, replicated on remote + // hosts, never receives updates from MasterInstance + // HermitInstance - created on owning host, is not replicated, does + // send updates + // + enum { + InstanceBits = Simulation::NextBit, + ValidBit = InstanceBits+2, + TransferableBit, + InterestBit, + InterestLockedBit, + DynamicBit, + TrappedBit, + StatueBit, + MapBit, + PreRunBit, + CondemnedBit, + NextBit + }; + enum Instance + { + MasterInstance=0, + ReplicantInstance=1<entityID = entityID; + message->interestZoneID = interestZoneID; + message->ownerID = ownerID; + } + +#include "entity3.h" +#undef ENTITY_CONTINUATION \ No newline at end of file diff --git a/MUNGA/ENTITY2.cpp b/MUNGA/ENTITY2.cpp new file mode 100644 index 0000000..923f168 --- /dev/null +++ b/MUNGA/ENTITY2.cpp @@ -0,0 +1,80 @@ +#include "munga.h" +#pragma hdrstop + +#include "hostmgr.h" +#include "registry.h" +#include "app.h" +#include "namelist.h" +#include "notation.h" +#include "entity.h" + +//########################################################################## +//############# Entity::StaticVideoSocketIterator #################### +//########################################################################## + +Entity__StaticVideoSocketIterator::Entity__StaticVideoSocketIterator(Entity *entity) : SChainIteratorOf(&entity->staticVideoSocket) +{ +} + +Entity__StaticVideoSocketIterator::Entity__StaticVideoSocketIterator(const Entity__StaticVideoSocketIterator &iterator) : SChainIteratorOf(iterator) +{ +} + +Entity__StaticVideoSocketIterator::~Entity__StaticVideoSocketIterator() +{ +} + +//########################################################################## +//############# Entity::DynamicVideoSocketIterator ################### +//########################################################################## + +Entity__DynamicVideoSocketIterator::Entity__DynamicVideoSocketIterator(Entity *entity) : SChainIteratorOf(&entity->dynamicVideoSocket) +{ +} + +Entity__DynamicVideoSocketIterator::Entity__DynamicVideoSocketIterator(const Entity__DynamicVideoSocketIterator &iterator) : SChainIteratorOf(iterator) +{ +} + +Entity__DynamicVideoSocketIterator::~Entity__DynamicVideoSocketIterator() +{ +} + +//########################################################################## +//################ Entity::AudioSocketIterator ####################### +//########################################################################## + +Entity__AudioSocketIterator::Entity__AudioSocketIterator(Entity *entity) : SChainIteratorOf(&entity->audioSocket) +{ +} + +Entity__AudioSocketIterator::~Entity__AudioSocketIterator() +{ +} + +int Find_Subsystem_Index(NotationFile *file, const char* name) +{ + Check(file); + Check_Pointer(name); + + NameList *namelist = file->MakePageList(); + Register_Object(namelist); + NameList::Entry *entry = namelist->GetFirstEntry(); + + int count = 0; + while (entry) + { + if (!strcmp(name, entry->GetName())) + { + Unregister_Object(namelist); + delete namelist; + return count; + } + ++count; + entry = entry->GetNextEntry(); + } + + Unregister_Object(namelist); + delete namelist; + return (!strcmp(name, "None")) ? count : -1; +} diff --git a/MUNGA/ENTITY2.h b/MUNGA/ENTITY2.h new file mode 100644 index 0000000..b31ee40 --- /dev/null +++ b/MUNGA/ENTITY2.h @@ -0,0 +1,118 @@ +#if defined(ENTITY_CONTINUATION) + + #include "entityid.h" + + class Entity; + class Entity__SharedData; + class Entity__MakeMessage; + class Entity__TakeDamageMessage; + class Entity__PlayerLinkMessage; + class Entity__DynamicMessage; + class Entity__UpdateMessage; + class Entity__MakeMapMessage; + class Entity__TakeDamageStreamMessage; + class Entity__DestroyEntityMessage; + + class EntityID; + + // + //--------------------------------------------------- + // Support types for entity identity and host manager + //--------------------------------------------------- + // + + //########################################################################## + //####################### Entity::Message ############################ + //########################################################################## + + class Entity__Message : public Receiver::Message + { + public: + // + // The following fields need to be filled in by the sending manager + // + enum + { + DontSpoolBit = Receiver::Message::NextBit, + NextBit + }; + + enum + { + DontSpoolFlag = 1 << DontSpoolBit + }; + + + // This field will be already set for map entities + EntityID entityID; + + InterestZoneID interestZoneID; + HostID ownerID; + + Entity__Message(Receiver::MessageID messageID, size_t length) : Receiver::Message(messageID, length), entityID(EntityID::Null), interestZoneID(NullInterestZoneID), ownerID(NullHostID) {} + + // This constructor exists for constructing map entities + Entity__Message(Receiver::MessageID messageID, size_t length, const EntityID &entity_ID) : Receiver::Message(messageID, length), entityID(entity_ID), interestZoneID(NullInterestZoneID), ownerID(NullHostID) {} + }; + + // + // Various typedefs for unimplemented messages + // + typedef Entity__Message Entity__MakeReadyMessage; + typedef Entity__Message Entity__RemakeEntityMessage; + typedef Entity__Message Entity__RemakeReadyMessage; + typedef Entity__Message Entity__RemakeCompleteMessage; + typedef Entity__Message Entity__RemakeIncompleteMessage; + typedef Entity__Message Entity__TransferEntityMessage; + typedef Entity__Message Entity__TransferCompleteMessage; + typedef Entity__Message Entity__TransferIncompleteMessage; + typedef Entity__Message Entity__BecomeInterestingMessage; + typedef Entity__Message Entity__BecomeUninterestingMessage; + typedef Entity__Message Entity__SubscribeReplicantMessage; + typedef Entity__Message Entity__UnsubscribeReplicantMessage; + + //########################################################################## + //############# Entity::StaticVideoSocketIterator #################### + //########################################################################## + + class Entity__StaticVideoSocketIterator : public SChainIteratorOf + { + public: + Entity__StaticVideoSocketIterator(Entity *entity); + Entity__StaticVideoSocketIterator(const Entity__StaticVideoSocketIterator &iterator); + ~Entity__StaticVideoSocketIterator(); + }; + + //########################################################################## + //############ Entity::DynamicVideoSocketIterator #################### + //########################################################################## + + class Entity__DynamicVideoSocketIterator : public SChainIteratorOf + { + public: + Entity__DynamicVideoSocketIterator(Entity *entity); + Entity__DynamicVideoSocketIterator(const Entity__DynamicVideoSocketIterator &iterator); + ~Entity__DynamicVideoSocketIterator(); + }; + + //########################################################################## + //################ Entity::AudioSocketIterator ####################### + //########################################################################## + + class Entity__AudioSocketIterator : public SChainIteratorOf + { + public: + Entity__AudioSocketIterator(Entity *entity); + ~Entity__AudioSocketIterator(); + }; + + //########################################################################## + //#################### Entity::UpdateRecord ########################## + //########################################################################## + + struct Entity__UpdateRecord : public Simulation__UpdateRecord + { + public: + Origin localOrigin; + }; +#endif \ No newline at end of file diff --git a/MUNGA/ENTITY3.h b/MUNGA/ENTITY3.h new file mode 100644 index 0000000..bb092e7 --- /dev/null +++ b/MUNGA/ENTITY3.h @@ -0,0 +1,324 @@ +#if defined(ENTITY_CONTINUATION) + + #include "damage.h" + + //########################################################################## + //#################### Entity::SharedData ########################### + //########################################################################## + + class Entity__SharedData: + public Simulation::SharedData + { + public: + Entity__SharedData( + Derivation* derivation, + Receiver::MessageHandlerSet &message_handlers, + Entity::AttributeIndexSet &attribute_index, + int state_count, + Entity::MakeHandler make_handler + ): + Simulation::SharedData( + derivation, + message_handlers, + attribute_index, + state_count + ), + makeHandler(make_handler) + {} + + Entity::MakeHandler makeHandler; + }; + + inline Entity::SharedData* + Entity::GetSharedData() + {return Cast_Object(SharedData*,sharedData);} + + //########################################################################## + //##################### Entity::MakeMessage ########################## + //########################################################################## + + class Entity__MakeMessage: + public Entity::Message + { + public: + enum { + MapStreamMarkerBit = Entity::Message::NextBit, + NextBit + }; + + enum { + MapStreamMarkerFlag = 1 << MapStreamMarkerBit + }; + + Entity::ClassID + classToCreate; + EntityID + owningPlayerID; + ResourceDescription::ResourceID + resourceID; + LWord + instanceFlags; + Origin + localOrigin; + + Entity__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin + ): + Entity::Message(message_ID, length), + classToCreate(class_ID), + owningPlayerID(owner_ID), + resourceID(resource_ID), + instanceFlags(instance_flags), + localOrigin(origin) + {} + Entity__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin + ): + Entity::Message(message_ID, length, entity_ID), + classToCreate(class_ID), + owningPlayerID(owner_ID), + resourceID(resource_ID), + instanceFlags(instance_flags), + localOrigin(origin) + {} + }; + + //########################################################################## + //#################### Entity::UpdateMessage ######################### + //########################################################################## + + class Entity__UpdateMessage: + public Entity::Message + { + public: + Entity__UpdateMessage( + Receiver::MessageID message_ID, + size_t length + ): + Entity::Message(message_ID, length) + {messageFlags &= ~ReliableFlag;} + }; + + //########################################################################## + //################## Entity::TakeDamageMessage ####################### + //########################################################################## + + class Entity__TakeDamageMessage: + public Entity::Message + { + public: + EntityID + inflictingEntity; + + // WARNING: + // Since the current collision system cannot resolve the damage zone of + // entities with multiple damage zones, specializations of Entity's + // TakeDamage message handler are responsible for handling an invalid zone. + // Mechs use cylinder lookup table. + // For BattleTech, damage zones are only valid via reticle based weapons. + // Due to existing RP implementation, damageZone is not an optional + // arg to the constructor. + + int + damageZone; + Logical invalidDamageZone; + + Damage + damageData; + + + // NOTE: + // BattleTech's message manager needs to know the subsystemID of the + // inflicting weapon in order to bundle explosion resource IDs. + + int inflictingSubsystemID; + Logical invalidSubsystem; + + Entity__TakeDamageMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + int damage_zone, + Damage &damage + ): + Entity::Message(message_ID, length), + inflictingEntity(entity_ID), + damageZone(damage_zone), + damageData(damage), + invalidDamageZone(damageZone<0), + inflictingSubsystemID(-1), + invalidSubsystem(inflictingSubsystemID<0) + + { } + + Entity__TakeDamageMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + int damage_zone, + Damage &damage, + int inflicting_subsystem_ID + ): + Entity::Message(message_ID, length), + inflictingEntity(entity_ID), + damageZone(damage_zone), + damageData(damage), + invalidDamageZone(damageZone<0), + inflictingSubsystemID(inflicting_subsystem_ID), + invalidSubsystem(inflictingSubsystemID<0) + { } + }; + + //########################################################################## + //############### Entity::TakeDamageStreamMessage ##################### + //########################################################################## + + class Entity__TakeDamageStreamMessage : + public Entity::Message + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Holds A Group Of Damage Messages with some Common Fields + // used for instantaneous hit weapons + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + public: + Point3D + impactPoint; + int + damageZoneIndex; + EntityID + shootingEntity; + + Entity__TakeDamageStreamMessage( + Entity::MessageID message_ID, + size_t message_size, + const EntityID &shooting_entity, + int damage_zone_index, + const Point3D &impact_point + ): + Entity::Message(message_ID, message_size), + shootingEntity(shooting_entity), + damageZoneIndex(damage_zone_index), + impactPoint(impact_point) + {} + + ~Entity__TakeDamageStreamMessage() + {} + }; + + //########################################################################## + //################## Entity::PlayerLinkMessage ####################### + //########################################################################## + + + class Entity__PlayerLinkMessage: + public Entity::Message + { + public: + EntityID + playerID; + + Entity__PlayerLinkMessage( + Receiver::MessageID message_ID, + size_t length, + EntityID player_id + ): + Entity::Message(message_ID, length) + {playerID = player_id;} + }; + // Tool support function + + extern int + Find_Subsystem_Index( + NotationFile *file, + const char* name + ); + + //########################################################################## + //################## Entity::PlayerLinkMessage ####################### + //########################################################################## + + class Entity__DestroyEntityMessage: + public Entity::Message + { + public: + Entity__DestroyEntityMessage( + Receiver::MessageID message_ID, + size_t length + ): + Entity::Message(message_ID, length) + {} + }; + + //########################################################################## + //################# Entity::DynamicMessage ########################### + //########################################################################## + + class Entity__DynamicMessage : + public Receiver::DynamicMessage + { + public: + Entity__DynamicMessage() + { } + + Entity__DynamicMessage( + Entity::MessageID message_ID, + size_t message_size = sizeof(Entity::Message) + ) : Receiver::DynamicMessage(message_ID, message_size) + { } + + Entity__DynamicMessage( + void *message_ptr, + size_t stream_size, + size_t initial_offset = sizeof(Entity::Message) + ) : Receiver::DynamicMessage(message_ptr, stream_size, initial_offset) + { } + + ~Entity__DynamicMessage() + { } + + }; + + + + //########################################################################## + //####################### Entity::MakeMapMessage ##################### + //########################################################################## + + class Entity__MakeMapMessage: + public Receiver::Message + { + public: + // + // The following fields need to be filled in by the sending manager + // + + ResourceDescription::ResourceID + resourceID; + Origin + localOrigin; + + Entity__MakeMapMessage( + Receiver::MessageID messageID, + size_t length + ): + Receiver::Message(messageID, length) + {} + }; + +#endif + diff --git a/MUNGA/ENTITYID.cpp b/MUNGA/ENTITYID.cpp new file mode 100644 index 0000000..9d37095 --- /dev/null +++ b/MUNGA/ENTITYID.cpp @@ -0,0 +1,209 @@ +#include "munga.h" +#pragma hdrstop + +#include "entityid.h" + +//############################################################################# +//############################# EntityID ################################ +//############################################################################# + +EntityID + EntityID::Null; + +EntityID::LocalID + EntityID::LocalNull = 0; + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile EntityID *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID(): + hostID(NullHostID), + localID(LocalNull) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID(const EntityID &entityID): + hostID(entityID.hostID), + localID(entityID.localID) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID(HostID hostID) +{ + this->hostID = hostID; + this->localID = LocalNull; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::EntityID( + HostID hostID, + LocalID localID +) +{ + this->hostID = hostID; + this->localID = localID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator=(const EntityID &entityID) +{ + hostID = entityID.hostID; + localID = entityID.localID; + + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator+=(const EntityID &entityID) +{ + Check(this); + Check(&entityID); + + hostID += entityID.hostID; + localID += entityID.localID; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID + EntityID::operator-(const EntityID &entityID) const +{ + Check(this); + Check(&entityID); + + return EntityID( + (HostID)(hostID - entityID.hostID), + (HostID)(localID - entityID.localID) + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator-=(const EntityID &entityID) +{ + Check(this); + Check(&entityID); + + hostID -= entityID.hostID; + localID -= entityID.localID; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator+=(LocalID i) +{ + Check(this); + + localID += i; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID& + EntityID::operator-=(LocalID i) +{ + Check(this); + + localID -= i; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator<(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID < entityID.localID) : + (hostID < entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator<=(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID <= entityID.localID) : + (hostID < entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator>(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID > entityID.localID) : + (hostID > entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator>=(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID) ? + (localID >= entityID.localID) : + (hostID > entityID.hostID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator==(const EntityID &entityID) const +{ + return + (hostID == entityID.hostID && + localID == entityID.localID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityID::operator!=(const EntityID &entityID) const +{ + return + (hostID != entityID.hostID || + localID != entityID.localID); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityID::operator int() const +{ + return int(localID); +} diff --git a/MUNGA/ENTITYID.h b/MUNGA/ENTITYID.h new file mode 100644 index 0000000..21dff08 --- /dev/null +++ b/MUNGA/ENTITYID.h @@ -0,0 +1,61 @@ +#pragma once + +#include "network.h" + +//########################################################################## +//########################## EntityID ################################ +//########################################################################## + +class EntityID +{ +public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile EntityID *); + #endif + + typedef Enumeration LocalID; + + EntityID(); + EntityID(const EntityID&); + EntityID(HostID); + EntityID(HostID, LocalID); + + Logical TestInstance() const; + HostID GetHostID() { return hostID; } + + Logical operator!() const + { + Check(this); + return operator==(Null); + } + EntityID& operator=(const EntityID&); + + EntityID operator-(const EntityID&) const; + + EntityID& operator+=(const EntityID&); + EntityID& operator-=(const EntityID&); + + EntityID& operator+=(LocalID); + EntityID& operator-=(LocalID); + + Logical operator<(const EntityID&) const; + Logical operator<=(const EntityID&) const; + Logical operator>(const EntityID&) const; + Logical operator>=(const EntityID&) const; + Logical operator==(const EntityID&) const; + Logical operator!=(const EntityID&) const; + + operator int() const; + + static EntityID Null; + static LocalID LocalNull; + + friend std::ostream& operator<<(std::ostream& stream, const EntityID& v) + { + return stream << v.hostID << ':' << v.localID; + } + +private: + HostID hostID; + LocalID localID; +}; \ No newline at end of file diff --git a/MUNGA/ENVIRNMT.cpp b/MUNGA/ENVIRNMT.cpp new file mode 100644 index 0000000..998375e --- /dev/null +++ b/MUNGA/ENVIRNMT.cpp @@ -0,0 +1,97 @@ +#include "munga.h" +#pragma hdrstop + +#include "envirnmt.h" +#include "cstr.h" + +//############################################################################# +//########################### Environment ############################### +//############################################################################# + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const Environment *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical Environment::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Environment functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void Convert_From_Ascii(const char *str, Environment *environment) +{ + Check_Pointer(str); + Check_Signature(environment); + + CString parse_string(str); + Check(&parse_string); + + Check_Pointer(parse_string.GetNthToken(0)); + environment->gravityConstant = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + environment->airDensity = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + environment->audioReverbTime = atof(parse_string.GetNthToken(2)); + + Check_Pointer(parse_string.GetNthToken(3)); + environment->audioAverageSurfaceReflectivity = atof(parse_string.GetNthToken(3)); + + Check_Pointer(parse_string.GetNthToken(4)); + environment->audioAirAbsorption = atof(parse_string.GetNthToken(4)); + + Check_Pointer(parse_string.GetNthToken(5)); + environment->windVelocity.x = atof(parse_string.GetNthToken(5)); + + Check_Pointer(parse_string.GetNthToken(6)); + environment->windVelocity.y = atof(parse_string.GetNthToken(6)); + + Check_Pointer(parse_string.GetNthToken(7)); + environment->windVelocity.z = atof(parse_string.GetNthToken(7)); + + Check_Pointer(parse_string.GetNthToken(8)); + environment->ambientTemperature = atof(parse_string.GetNthToken(8)); + + Check(environment); +} + +//############################################################################# +//######################### EnvironmentList ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EnvironmentList::EnvironmentList(int environments) +{ + Verify(environments > 0); + + environmentCount = environments; + environmentArray = new Environment[environments]; + Register_Pointer(environmentArray); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EnvironmentList::~EnvironmentList() +{ + Unregister_Pointer(environmentArray); + delete[] environmentArray; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical EnvironmentList::TestInstance() const +{ + return True; +} + +EnvironmentList *Environments; diff --git a/MUNGA/ENVIRNMT.h b/MUNGA/ENVIRNMT.h new file mode 100644 index 0000000..24af373 --- /dev/null +++ b/MUNGA/ENVIRNMT.h @@ -0,0 +1,76 @@ +#pragma once + +#include "style.h" +#include "vector3d.h" + +class Environment +{ + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const Environment *p); + #endif + +public: + Scalar gravityConstant; + Scalar airDensity; + Scalar audioReverbTime; + Scalar audioAverageSurfaceReflectivity; + Scalar audioAirAbsorption; + Vector3D windVelocity; + Scalar ambientTemperature; // Kelvin + + const Vector3D& GetWindVelocity() { return windVelocity; } + + Environment() {} + Environment(Scalar gravity, Scalar air_density, Scalar reverb_time, Scalar surface_reflectivity, Scalar air_absorption, const Vector3D &wind_velocity, Scalar ambient_temperature) + : gravityConstant(gravity), airDensity(air_density), audioReverbTime(reverb_time), audioAverageSurfaceReflectivity(surface_reflectivity), audioAirAbsorption(air_absorption), windVelocity(wind_velocity), ambientTemperature(ambient_temperature) + { + } + + Logical TestInstance() const; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ Environment functions ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void Convert_From_Ascii(const char *str, Environment *environment); + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, Environment *output) +{ + return stream->ReadBytes(output, sizeof(*output)); +} +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const Environment *input) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + +//########################################################################## +//###################### EnvironmentList ############################# +//########################################################################## + +class EnvironmentList SIGNATURED +{ +protected: + int environmentCount; + + Environment *environmentArray; + +public: + EnvironmentList(int environments); + virtual ~EnvironmentList(); + + int GetEnvironmentCount() + { + Check(this); + return environmentCount; + } + + virtual Environment& GetEnvironment(int index) + { + Check(this); + Verify((unsigned)index < environmentCount); + return environmentArray[index]; + } + + Logical TestInstance() const; +}; + +extern EnvironmentList *Environments; diff --git a/MUNGA/EVENT.cpp b/MUNGA/EVENT.cpp new file mode 100644 index 0000000..1ce56e0 --- /dev/null +++ b/MUNGA/EVENT.cpp @@ -0,0 +1,1079 @@ +#include "munga.h" +#pragma hdrstop + +#include "event.h" +#include "registry.h" +#include "app.h" +#include "entity.h" +#include "evtstat.h" + +#if defined(TRACE_PROCESS_EVENT) + static BitTrace Process_Event("Process Event"); +# define SET_PROCESS_EVENT() Process_Event.Set() +# define CLEAR_PROCESS_EVENT() Process_Event.Clear() +#else +# define SET_PROCESS_EVENT() +# define CLEAR_PROCESS_EVENT() +#endif + +//############################################################################# +//########################### AbstractEvent ############################# +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AbstractEvent::AbstractEvent( + Receiver::Message *message, + Time time, + ClassID class_id +): + Node(class_id) +{ + Verify(message); + alarmTime = time; + + // + //-------------------------------------------------------- + // Allocate some memory to store the message parameters in + //-------------------------------------------------------- + // + size_t long_size = (message->messageLength+3)>>2; + messageToSend = (Receiver::Message*)new long[long_size]; + Check_Pointer(messageToSend); + Register_Pointer(messageToSend); + + Mem_Copy( + messageToSend, + message, + message->messageLength, + long_size*sizeof(long) + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AbstractEvent::~AbstractEvent() +{ + if (messageToSend) + { + Unregister_Pointer(messageToSend); + delete messageToSend; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + AbstractEvent::Process() +{ + Fail("AbstractEvent::Process should not be called!\n"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + AbstractEvent::DumpData() +{ + Fail("AbstractEvent::DumpData should not be called!\n"); +} + +//############################################################################# +//############################### Event ################################# +//############################################################################# + +MemoryBlock *Event::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(Event), 20, 10, "Events"); + return &allocatedMemory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Event::Event( + Receiver *target, + Receiver::Message *message, + Time time +): + AbstractEvent(message, time, EventClassID), + targetReceiver(this) +{ + targetReceiver.Add(target); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Event::~Event() +{ +#if defined(TRACE_EVENT_COUNT) + // + //------------------------------------------- + // Delete the link to the current event queue + //------------------------------------------- + // + PlugIteratorOf + old_queue_link(this); + Node *node; + while ((node = old_queue_link.GetCurrent()) != NULL) + { + Check(node); + if ( + node->GetClassID() == EventQueueClassID + || node->GetClassID() == GeneralEventQueueClassID + ) + { + GeneralEventQueue *q = Cast_Object(GeneralEventQueue*, node); + while (q->priorityLevels < 0) + { + --q; + Check(q); + } + --q->eventCount; + if (q->eventCountTrace) + { + Check(q->eventCountTrace); + q->eventCountTrace->TakeSnapshot(q->eventCount); + } + break; + } + } +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::Repost( + EventQueue* queue, + int priority, + Time new_time + ) +{ + Check(this); + Check(queue); + + // + //------------------------------------------- + // Delete the link to the current event queue + //------------------------------------------- + // + PlugIteratorOf + old_queue_link(this); + Node *node; + while ((node = old_queue_link.GetCurrent()) != NULL) + { + Check(node); + if ( + node->GetClassID() == EventQueueClassID + || node->GetClassID() == GeneralEventQueueClassID + || node->GetClassID() == DeferredEventQueueClassID + ) + { + #if defined(TRACE_EVENT_COUNT) + if (node->GetClassID() != DeferredEventQueueClassID) + { + GeneralEventQueue *q = Cast_Object(GeneralEventQueue*, node); + while (q->priorityLevels < 0) + { + --q; + Check(q); + } + --q->eventCount; + if (q->eventCountTrace) + { + Check(q->eventCountTrace); + q->eventCountTrace->TakeSnapshot(q->eventCount); + } + } + #endif + + old_queue_link.Remove(); + break; + } + else + { + old_queue_link.Next(); + } + } + + // + //----------------------------------------------------------------------- + // Now, if necessary, reset the time and stuff the event in the new event + // queue + //----------------------------------------------------------------------- + // + if (new_time.ticks) + { + alarmTime = new_time; + } + queue->Enqueue(priority,this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::Defer() +{ + // + //----------------------------------------------- + // See if the target has a deferred queue already + //----------------------------------------------- + // + Receiver *target = targetReceiver.GetCurrent(); + Check(target); + PlugIteratorOf + blind_links(target); + DeferredEventQueue + *deferred_queue; + while ((deferred_queue = blind_links.ReadAndNext()) != NULL) + { + if (deferred_queue->GetClassID() == DeferredEventQueueClassID) + { + break; + } + } + + // + //---------------------------------------------------------------------- + // If we couldn't find a deferred queue, then a new one must be created + // and attached to the object + //---------------------------------------------------------------------- + // + if (!deferred_queue) + { + deferred_queue = new DeferredEventQueue(target); + Register_Object(deferred_queue); + } + + // + //------------------------------------------------- + // Now, simply repost the event to this event queue + //------------------------------------------------- + // + Repost(deferred_queue->deferredEvents,0); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::Process() +{ + Check(this); + targetReceiver.GetCurrent()->Receive(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::DumpData() +{ + Check(this); + + Receiver *target = targetReceiver.GetCurrent(); + Check(target); + Check(application); + Registry *registry = application->GetRegistry(); + if (registry) + { + Check(registry); + Receiver::SharedData *shared_data = + registry->GetStaticData(target->GetClassID()); + if (shared_data) + { + Check(shared_data); + Derivation *derivation = shared_data->derivedClasses; + Check(derivation); + Receiver::MessageHandlerSet *handlers = + shared_data->activeMessageHandlers; + Check(handlers); + DEBUG_STREAM << handlers->GetName(messageToSend->messageID) << " message for class " << derivation->className << std::endl << std::flush; + } + else + { + goto Vanilla_Message; + } + } + else + { +Vanilla_Message: + DEBUG_STREAM << "Message " << messageToSend->messageID << " for object of classID " << target->GetClassID() << std::endl << std::flush; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Event::ReleaseLinkHandler( + Socket*, + Plug* + ) +{ + Unregister_Object(this); + delete this; +} + +//############################################################################# +//########################### NetworkEvent ############################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkEvent::NetworkEvent( + HostID host_ID, + NetworkManager::ClientID client_ID, + EventStyle event_style, + Receiver::Message *message, + Time time +): + AbstractEvent(message, time, NetworkEventClassID) +{ + hostID = host_ID; + clientID = client_ID; + eventStyle = event_style; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkEvent::~NetworkEvent() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NetworkEvent::Process() +{ + Check(this); + switch (eventStyle) + { + case SendStyle: + Check(application); + application->GetNetworkManager()->Send( + messageToSend, + clientID, + hostID + ); + break; + + case BroadcastStyle: + Check(application); + application->GetNetworkManager()->Broadcast( + messageToSend, + clientID + ); + break; + + case ExclusiveBroadcastStyle: + Check(application); + application->GetNetworkManager()->ExclusiveBroadcast( + messageToSend, + clientID + ); + break; + } + + Unregister_Object(this); + delete this; +} + +//############################################################################# +//####################### GeneralEventQueue ############################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue::GeneralEventQueue(ClassID class_ID): + Node(class_ID), + pendingEvents(this), + timedEvents(this) +{ + priorityLevels = -1; + eventCount = 0; + #if defined(TRACE_EVENT_COUNT) + eventCountTrace = NULL; + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue::GeneralEventQueue(): + Node(GeneralEventQueueClassID), + pendingEvents(this), + timedEvents(this) +{ + priorityLevels = -1; + eventCount = 0; + #if defined(TRACE_EVENT_COUNT) + eventCountTrace = NULL; + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue::~GeneralEventQueue() +{ + #if defined(TRACE_EVENT_COUNT) + if (eventCountTrace) + { + Unregister_Object(eventCountTrace); + delete eventCountTrace; + } + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GeneralEventQueue* + GeneralEventQueue::Make( + int priorities, + #if defined(TRACE_EVENT_COUNT) + const char* trace_name + #else + const char* + #endif + ) +{ + GeneralEventQueue *queue = new GeneralEventQueue[priorities]; + Register_Object(queue); + + queue->priorityLevels = priorities; + #if defined(TRACE_EVENT_COUNT) + if (trace_name) + { + Check_Pointer(trace_name); + queue->eventCountTrace = + new TraceOf( + trace_name, + 0, + Trace::IntegerType, + TraceSample::IntegerSnapshot + ); + Register_Object(queue->eventCountTrace); + } + #endif + return queue; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::Post( + int priority, + Receiver *target, + Receiver::Message *message, + Time time + ) +{ + Check(this); + Check(target); + Check(message); + + // + //------------------------------------------------------------------------ + // Create a new event, then insert it at the end of the event queue. This + // means that timed events get put in sort of haphazardly!!!! + //------------------------------------------------------------------------ + // + Event *event = new Event(target, message, time); + Register_Object(event); + + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::SendEvent( + int priority, + HostID host_ID, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when + ) +{ + Check(this); + Check(message); + + NetworkEvent *event = + new NetworkEvent( + host_ID, client_id, NetworkEvent::SendStyle, message, when + ); + Register_Object(event); + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::BroadcastEvent( + int priority, + NetworkManager::ClientID client_ID, + Receiver::Message *message, + Time when + ) +{ + Check(this); + Check(message); + + // + // HACK - What is a null network address? + // + NetworkEvent *event = + new NetworkEvent( + (NetworkAddress)0, + client_ID, + NetworkEvent::BroadcastStyle, + message, + when + ); + Register_Object(event); + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::ExclusiveBroadcastEvent( + int priority, + NetworkManager::ClientID client_ID, + Receiver::Message *message, + Time when + ) +{ + Check(this); + Check(message); + + // + // HACK - What is a null network address? + // + NetworkEvent *event = + new NetworkEvent( + (NetworkAddress)0, + client_ID, + NetworkEvent::ExclusiveBroadcastStyle, + message, + when + ); + Register_Object(event); + Enqueue(priority, event); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::Enqueue( + int priority, + AbstractEvent *event + ) +{ + Check(event); + Verify((unsigned)priority < priorityLevels); + + // + //------------------------------------------------------------ + // If this is not a timed event, stuff it in the pending queue + //------------------------------------------------------------ + // + if (!event->alarmTime.ticks) + { + this[priority].pendingEvents.Add(event); + } + + // + //---------------------------------------- + // Otherwise, sort it into the timed queue + //---------------------------------------- + // + else + { + ChainIteratorOf + timed_events(this[priority].timedEvents); + timed_events.Last(); + AbstractEvent* next_event = timed_events.GetCurrent(); + + // + //--------------------------------------------------------------------- + // If the timed queue is empty, or if we are later than the last entry, + // just add the event to the end + //--------------------------------------------------------------------- + // + if (!next_event || next_event->alarmTime.ticks <= event->alarmTime.ticks) + { + this[priority].timedEvents.Add(event); + } + + // + //-------------------------------------------------------------------- + // Find the event to insert before. If we run off the beginning, stop + // checking and set the iterator to the first event in the queue + //-------------------------------------------------------------------- + // + else + { + do + { + timed_events.Previous(); + next_event = timed_events.GetCurrent(); + if (!next_event) + { + timed_events.First(); + break; + } + } while (next_event->alarmTime.ticks > event->alarmTime.ticks); + + // + //-------------------------------------------------------------------- + // If we didn't run off the queue, we need to insert after the current + // event, so bump the iterator forward one event + //-------------------------------------------------------------------- + // + if (next_event) + { + timed_events.Next(); + } + + // + //------------------------------------------------------------------ + // Insert the new event ahead of where the iterator currently points + //------------------------------------------------------------------ + // + timed_events.Insert(event); + } + } + #if defined(TRACE_EVENT_COUNT) + ++eventCount; + if (eventCountTrace) + { + Check(eventCountTrace); + eventCountTrace->TakeSnapshot(eventCount); + } + #endif + #if defined(USE_EVENT_STATISTICS) + event_statistics_manager.Maintain(Cast_Object(Event*, event)); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AbstractEvent* + GeneralEventQueue::PeekAtNextEvent(int min_priority) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Start at the top of the priority queue, searching backwards until we find + // an available event or run off the minimum queue priority + //-------------------------------------------------------------------------- + // + Verify(min_priority >= 0); + int priority = priorityLevels; + while (--priority >= min_priority) + { + // + //------------------------------------------------------------------- + // See if the first event in the timed queue is ready to go. If not, + // none of the other timed events will be ready to go either + //------------------------------------------------------------------- + // + ChainIteratorOf + timed_events(this[priority].timedEvents); + AbstractEvent + *event = timed_events.GetCurrent(); + if (event) + { + Check(event); + if (event->alarmTime.ticks <= Now().ticks) + { + return event; + } + } + + // + //------------------------------ + // Now look in the untimed queue + //------------------------------ + // + ChainIteratorOf + events(this[priority].pendingEvents); + event = events.GetCurrent(); + if (event) + { + Check(event); + return event; + } + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + GeneralEventQueue::IsPriorityEmpty(int priority) +{ + Check(this); + + Verify(priority >= 0 && priority < priorityLevels); + ChainIteratorOf i(this[priority].pendingEvents); + ChainIteratorOf j(this[priority].timedEvents); + return !i.GetCurrent() && !j.GetCurrent(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + GeneralEventQueue::ProcessOneEvent(int min_priority) +{ + Check(this); + Verify(min_priority >= 0); + + AbstractEvent *event=PeekAtNextEvent(min_priority); + if (event) + { + SET_PROCESS_EVENT(); + event->Process(); + CLEAR_PROCESS_EVENT(); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::ProcessAllEvents(int min_priority) +{ + Check(this); + Verify(min_priority >= 0); + while (ProcessOneEvent(min_priority)); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::FlushAllEvents(int max_priority) +{ + Check(this); + Verify(max_priority < priorityLevels); + + // + //----------------------------------------- + // Make sure that max_priority is set right + //----------------------------------------- + // + if (max_priority < 0) + { + max_priority = priorityLevels - 1; + } + + // + //--------------------------------------------------------------------- + // Step through each of the priority queues and delete any events found + // within + //--------------------------------------------------------------------- + // + for (int priority=max_priority; priority>=0; --priority) + { + + // + //--------------------------------------- + // Delete the events from the timed queue + //--------------------------------------- + // + ChainIteratorOf i(this[priority].timedEvents); + AbstractEvent *event; + while ((event = i.ReadAndNext()) != NULL) + { + Unregister_Object(event); + delete event; + } + + // + //----------------------------------------- + // Delete the events from the regular queue + //----------------------------------------- + // + ChainIteratorOf j(this[priority].pendingEvents); + while ((event = j.ReadAndNext()) != NULL) + { + Unregister_Object(event); + delete event; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::FlushMatchingEvents( + Receiver::MessageID target_message, + int max_priority + ) +{ + Check(this); + Verify(max_priority < priorityLevels); + + // + //----------------------------------------- + // Make sure that max_priority is set right + //----------------------------------------- + // + if (max_priority < 0) + { + max_priority = priorityLevels - 1; + } + + // + //--------------------------------------------------------------------- + // Step through each of the priority queues and delete any events found + // within + //--------------------------------------------------------------------- + // + for (int p=max_priority; p>=0; --p) + { + // + //------------------------------------------- + // Delete events from the regular queue first + //------------------------------------------- + // + ChainIteratorOf i(this[p].pendingEvents); + AbstractEvent *event; + while ((event = i.ReadAndNext()) != NULL) + { + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + target_message == Receiver::AnyMessageID + || target_message == event->messageToSend->messageID + ) + { + Unregister_Object(event); + delete event; + } + } + + // + //----------------------------------- + // Delete events from the timed queue + //----------------------------------- + // + ChainIteratorOf j(this[p].timedEvents); + while ((event = j.ReadAndNext()) != NULL) + { + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + target_message == Receiver::AnyMessageID + || target_message == event->messageToSend->messageID + ) + { + Unregister_Object(event); + delete event; + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GeneralEventQueue::DumpEventQueue() +{ + Check(this); + + // + //---------------------------------------------------------------------- + // Step through each of the priority queues and display any events found + // within + //---------------------------------------------------------------------- + // + CollectionSize total_count = 0; + for (int priority=priorityLevels - 1; priority>=0; --priority) + { + DEBUG_STREAM << "EventQueue priority " << priority + << "\n--------------------------------------------------------------\n"; + + ChainIteratorOf i(this[priority].pendingEvents); + AbstractEvent *event; + size_t count=0; + while ((event = i.ReadAndNext()) != NULL) + { + ++count; + event->DumpData(); + } + DEBUG_STREAM << count << " priority " << priority << " events\n\n" << std::flush; + count = 0; + ChainIteratorOf j(this[priority].timedEvents); + while ((event = j.ReadAndNext()) != NULL) + { + ++count; + event->DumpData(); + } + DEBUG_STREAM << count << " priority " << priority << " timed events\n\n" << std::flush; + total_count += count; + + } + DEBUG_STREAM << total_count << " total events in queues\n\n" << std::flush; +} + +//############################################################################# +//############################ EventQueue ############################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EventQueue::EventQueue(): + GeneralEventQueue(EventQueueClassID) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EventQueue::~EventQueue() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EventQueue* + EventQueue::Make( + int priorities, + #if defined(TRACE_EVENT_COUNT) + const char* trace_name + #else + const char* + #endif + ) +{ + EventQueue *queue = new EventQueue[priorities]; + Register_Object(queue); + + queue->priorityLevels = priorities; + #if defined(TRACE_EVENT_COUNT) + if (trace_name) + { + Check_Pointer(trace_name); + queue->eventCountTrace = + new TraceOf( + trace_name, + 0, + Trace::IntegerType, + TraceSample::IntegerSnapshot + ); + Register_Object(queue->eventCountTrace); + } + #endif + return queue; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EventQueue::ProcessMatchingEvents( + Receiver *receiver, + Receiver::MessageID message_ID + ) +{ + Check(this); + Check(receiver); + + // + //---------------------------------------------------------------- + // Step through each of the priority queues and process any events + // found within + //---------------------------------------------------------------- + // + for (int p=priorityLevels-1; p>=0; --p) + { + Event *event; + AbstractEvent *abstract_event; + ChainIteratorOf i(this[p].pendingEvents); + while ((abstract_event = i.ReadAndNext()) != NULL) + { + Check(abstract_event); + event = Cast_Object(Event*, abstract_event); + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + (event->targetReceiver.GetCurrent() == receiver) && + (message_ID == Receiver::AnyMessageID || + message_ID == event->messageToSend->messageID) + ) + { + event->Process(); + } + } + + ChainIteratorOf j(this[p].timedEvents); + while ((abstract_event = j.ReadAndNext()) != NULL) + { + Check(abstract_event); + event = Cast_Object(Event*, abstract_event); + + // + //------------------------------ + // Make sure the message matches + //------------------------------ + // + if ( + (event->targetReceiver.GetCurrent() == receiver) && + (message_ID == Receiver::AnyMessageID || + message_ID == event->messageToSend->messageID) + ) + { + event->Process(); + } + } + } +} + +//############################################################################# +//######################## DeferredEventQueue ########################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DeferredEventQueue::DeferredEventQueue(Receiver* target): + Node(DeferredEventQueueClassID), + waitingReceiver(this) +{ + deferredEvents = new EventQueue; + Register_Object(deferredEvents); + + waitingReceiver.Add(target); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DeferredEventQueue::~DeferredEventQueue() +{ + Unregister_Object(deferredEvents); + delete deferredEvents; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DeferredEventQueue::ReleaseLinkHandler( + Socket*, + Plug* + ) +{ + Unregister_Object(this); + delete this; +} + +#if defined(TEST_CLASS) + #include "event.tcp" +#endif diff --git a/MUNGA/EVENT.h b/MUNGA/EVENT.h new file mode 100644 index 0000000..fe66219 --- /dev/null +++ b/MUNGA/EVENT.h @@ -0,0 +1,342 @@ +#pragma once + +#include "time.h" +#include "slot.h" +#include "network.h" + +class GeneralEventQueue; +class EventQueue; +class DeferredEventQueue; +class Entity; + +//########################################################################## +//######################## AbstractEvent ############################# +//########################################################################## + +class AbstractEvent: + public Node +{ + friend class GeneralEventQueue; + friend class EventStatisticsManager; + +//########################################################################## +// Event Functionality +// +protected: + AbstractEvent( + Receiver::Message *message, + Time time, + ClassID class_id + ); + ~AbstractEvent(); + +public: + virtual void + Process(); + virtual void + DumpData(); + +protected: + Time alarmTime; + Receiver::Message* messageToSend; +}; + +//########################################################################## +//############################ Event ################################# +//########################################################################## + +class Event: + public AbstractEvent +{ + friend class GeneralEventQueue; + friend class EventQueue; + friend class Receiver; + friend class DeferredEventQueue; + friend class Entity; + friend class EventStatisticsManager; + +//########################################################################## +// Node Support +// +private: + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + +//########################################################################## +// Memory Allocation Support +// +private: + static MemoryBlock* GetAllocatedMemory(); + + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } + + +//########################################################################## +// Event Functionality +// +private: + Event( + Receiver *target, + Receiver::Message *message, + Time time + ); + ~Event(); + +public: + void + Repost( + EventQueue *queue, + int priority, + Time new_time=Time::Null + ); + + void + Defer(); + + void + Process(); + void + DumpData(); + +private: + SlotOf targetReceiver; +}; + +//########################################################################## +//######################## NetworkEvent ############################## +//########################################################################## + +class NetworkEvent: + public AbstractEvent +{ + friend class GeneralEventQueue; + +//########################################################################## +// Event Functionality +// +private: + enum EventStyle + { + SendStyle, + BroadcastStyle, + ExclusiveBroadcastStyle + }; + + NetworkEvent( + HostID hostID, + NetworkManager::ClientID client_ID, + EventStyle event_style, + Receiver::Message *message, + Time time + ); + ~NetworkEvent(); + +public: + void + Process(); + +private: + HostID + hostID; + NetworkManager::ClientID + clientID; + EventStyle + eventStyle; +}; + +//########################################################################## +//#################### GeneralEventQueue ############################ +//########################################################################## +// +// NOTE: Do not create any static event queues! new must be used to allocate +// all event queue objects +// +class GeneralEventQueue: + public Node +{ + friend class Event; + +//########################################################################## +// EventQueue Allocation +// +public: + GeneralEventQueue(ClassID class_ID); + GeneralEventQueue(); + ~GeneralEventQueue(); + + static GeneralEventQueue* + Make( + int priorities, + const char* trace_name=NULL + ); + +protected: + int + priorityLevels; + ChainOf + pendingEvents; + ChainOf + timedEvents; + int + eventCount; + #if defined(TRACE_EVENT_COUNT) + TraceOf + *eventCountTrace; + #endif + +//########################################################################## +// EventQueue Functionality +// +public: + void + Post( + int priority, + Receiver *target, + Receiver::Message *message, + Time when=Time::Null + ); + void + SendEvent( + int priority, + HostID host_ID, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when=Time::Null + ); + void + BroadcastEvent( + int priority, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when=Time::Null + ); + void + ExclusiveBroadcastEvent( + int priority, + NetworkManager::ClientID client_id, + Receiver::Message *message, + Time when=Time::Null + ); + int + GetEventCount() + {return eventCount;} + + AbstractEvent* + PeekAtNextEvent(int min_priority=0); + Logical + IsPriorityEmpty(int priority); + + Logical + ProcessOneEvent(int min_priority=0); + void + ProcessAllEvents(int min_priority=0); + + void + FlushAllEvents(int max_priority=-1); + void + FlushMatchingEvents( + Receiver::MessageID target_message, + int max_priority=-1 + ); + + void + Enqueue( + int priority, + AbstractEvent *event + ); + +//########################################################################## +// Testing Support +// +public: + void + DumpEventQueue(); +}; + +//########################################################################## +//######################### EventQueue ############################### +//########################################################################## + +class EventQueue: + public GeneralEventQueue +{ +//########################################################################## +// EventQueue Allocation +// +public: + EventQueue(); + static EventQueue* + Make( + int priorities, + const char* trace_name=NULL + ); + ~EventQueue(); + +//########################################################################## +// EventQueue Posting & Processing +// +public: + Event* + PeekAtNextEvent(int min_priority=0) + { + return + (Event*)GeneralEventQueue::PeekAtNextEvent(min_priority); + } + + void + ProcessMatchingEvents( + Receiver *receiver, + Receiver::MessageID message_ID=Receiver::AnyMessageID + ); + +//########################################################################## +// Testing Support +// +public: + static Logical + TestClass(); +}; + +//########################################################################## +//##################### DeferredEventQueue ########################### +//########################################################################## +// +// NOTE: Do not create any static event queues! new must be used to allocate +// all event queue objects +// +class DeferredEventQueue: + public Node +{ + friend class Event; + +//########################################################################## +// Node Support +// +private: + void + ReleaseLinkHandler( + Socket *socket, + Plug *plug + ); + +//########################################################################## +// Deferred Queue Functionality +// +public: + DeferredEventQueue(Receiver *target); + ~DeferredEventQueue(); + + void + ProcessAllEvents() + {Check(this); deferredEvents->ProcessAllEvents();} + +private: + EventQueue + *deferredEvents; + SlotOf + waitingReceiver; +}; diff --git a/MUNGA/EVTSTAT.cpp b/MUNGA/EVTSTAT.cpp new file mode 100644 index 0000000..09e1305 --- /dev/null +++ b/MUNGA/EVTSTAT.cpp @@ -0,0 +1,143 @@ +#include "munga.h" +#pragma hdrstop + +#include "evtstat.h" +#include "app.h" +#include "registry.h" +#include "entity.h" + +//############################################################################# +//########################## EventStatistics ############################ +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +EventStatistics::EventStatistics( + ClassID class_ID, + Receiver::MessageID message_ID +): + classID(class_ID), + messageID(message_ID), + eventCount(0) +{ +} + +//############################################################################# +//######################## EventStatisticsManager ####################### +//############################################################################# + +EventStatisticsManager + event_statistics_manager; + +// +//############################################################################# +//############################################################################# +// +EventStatisticsManager::EventStatisticsManager(): + eventStatisticsSocket(NULL, True) +{ + printedReport = False; +} + +// +//############################################################################# +//############################################################################# +// +void + EventStatisticsManager::Maintain(Event *event) +{ + Check(this); + Check(event); + + // + // If the application is not running then it is not time to collect + // statistics yet + // + Check(application); + if (application->GetApplicationState() != Application::RunningMission) + return; + + // + // Add statistics for this event + // + ClassID + class_ID; + Receiver::MessageID + message_ID; + long + index_value; + EventStatistics + *event_statistics; + + message_ID = event->messageToSend->messageID; + class_ID = event->targetReceiver.GetCurrent()->GetClassID(); + index_value = class_ID * 1000 + message_ID; // HACK to create unique key + if ((event_statistics = eventStatisticsSocket.Find(index_value)) == NULL) + { + event_statistics = new EventStatistics(class_ID, message_ID); + eventStatisticsSocket.AddValue(event_statistics, index_value); + } + Check(event_statistics); + event_statistics->eventCount++; +} + +// +//############################################################################# +//############################################################################# +// +void + EventStatisticsManager::Report() +{ + Check(this); + + // + // Print Report + // + TableIteratorOf + iterator(&eventStatisticsSocket); + EventStatistics + *event_statistics; + + std::cout << "EventStatisticsManager::Report - event_count=" + << iterator.GetSize() << "\n"; + while ((event_statistics = iterator.ReadAndNext()) != NULL) + { + Check(event_statistics); + + Registry + *registry; + Entity::SharedData + *shared_data; + Derivation + *derivation; + Receiver::MessageHandlerSet + *handlers; + + std::cout << "EventStatisticsManager::Report -\t"; + std::cout << event_statistics->classID << "\t"; + std::cout << event_statistics->messageID << "\t"; + std::cout << event_statistics->eventCount << "\t"; + + Check(application); + if ((registry = application->GetRegistry()) != NULL) + { + Check(registry); + shared_data = registry->GetStaticData(event_statistics->classID); + if (shared_data != NULL) + { + Check(shared_data); + derivation = shared_data->derivedClasses; + Check(derivation); + handlers = shared_data->activeMessageHandlers; + Check(handlers); + + std::cout << derivation->className << "::" + << handlers->GetName(event_statistics->messageID) << "\t"; + } + } + std::cout << "\n"; + } + iterator.DeletePlugs(); +} diff --git a/MUNGA/EVTSTAT.h b/MUNGA/EVTSTAT.h new file mode 100644 index 0000000..f450236 --- /dev/null +++ b/MUNGA/EVTSTAT.h @@ -0,0 +1,58 @@ +#pragma once + +#include "style.h" +#include "receiver.h" + +//######################################################################### +//######################## EventStatistics ########################## +//######################################################################### + +class EventStatistics : public Plug +{ + friend class EventStatisticsManager; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction +// +public: + EventStatistics::EventStatistics(ClassID class_ID, Receiver::MessageID message_ID); + ~EventStatistics() {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + ClassID classID; + Receiver::MessageID messageID; + long eventCount; +}; + +//######################################################################### +//##################### EventStatisticsManager ###################### +//######################################################################### + +class EventStatisticsManager : public Node +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction +// +public: + EventStatisticsManager::EventStatisticsManager(); + ~EventStatisticsManager() {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Statistic collection and reporting +// +public: + void Maintain(Event *event); + void Report(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + TableOf eventStatisticsSocket; + Logical printedReport; +}; + +extern EventStatisticsManager event_statistics_manager; diff --git a/MUNGA/EXPLODE.cpp b/MUNGA/EXPLODE.cpp new file mode 100644 index 0000000..89adcde --- /dev/null +++ b/MUNGA/EXPLODE.cpp @@ -0,0 +1,773 @@ +#include "munga.h" +#pragma hdrstop + +#include "explode.h" +#include "mover.h" +#include "boxsolid.h" +#include "collasst.h" +#include "damage.h" +#include "random.h" +#include "app.h" +#include "objstrm.h" +#include "hostmgr.h" +#include "notation.h" +#include "namelist.h" + +//############################################################################# +//############################ Explosion ################################ +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Explosion::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(), "Explosion"); + return &classDerivations; +} + +Explosion::SharedData + Explosion::DefaultData( + Explosion::GetClassDerivations(), + Explosion::GetMessageHandlers(), + Explosion::GetAttributeIndex(), + Explosion::StateCount, + (Entity::MakeHandler)Explosion::Make + ); + +void + Explosion::ExplosionSimulation(Scalar) +{ + Check(application); + if ((Now() - creationTime) > explosionDuration) + { + CondemnToDeathRow(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void Explosion::SplashDamage +( EntityID inflicting, + Damage &damage, + Scalar collisionRadius, + Vector3D offset, + Entity * excluded) // Excluded should really be a set of entities! +{ + Check(this); + Check(entityHit); + if (excluded) + { + Check(excluded); + } + Check_Pointer(&damage); + Verify(0 < collisionRadius); + + + // + // The list of volumes we intersect + // + BoxedSolidCollisionList collision_list; + collision_list.Reset(); + + // + // Create the collision assistant to check movers against + // + CollisionAssistant *collision_assistant; + + collision_assistant = new CollisionAssistant(entityHit->GetInterestZoneID()); + Register_Object(collision_assistant); + Check(collision_assistant); + + BoxedSolidResource box; + Check_Pointer(&box); + box.solidType = BoxedSolid::YAxisCylinderType; + box.materialType = BoxedSolid::ConcreteMaterial; + const Vector3D min = Vector3D(-collisionRadius,-collisionRadius,-collisionRadius); + const Vector3D max = Vector3D(collisionRadius,collisionRadius,collisionRadius); + ExtentBox ext_box = ExtentBox(min,max); + box.solidExtents = ext_box; + box.sliceExtents = ext_box; + + BoxedSolidResource local_box; + local_box.Instance(box,localOrigin); + + BoxedSolid *splash_volume = BoxedSolid::MakeBoxedSolid(&local_box, this, NULL); + Register_Object(splash_volume); + + // + //--------------------------------- + // Test against the tangible movers + //--------------------------------- + // + Check(collision_assistant); + CollisionAssistant::MovingEntityIterator iterator(collision_assistant); + Entity *entity; + Mover *mover; + Check(splash_volume); + while ((entity = iterator.ReadAndNext()) != NULL) + { + // + //------------------------------------------------------------------ + // If we are checking against ourselves, skip it + //------------------------------------------------------------------ + // + Check(entity); + if (entity == this) + { + continue; + } + + // + //-------------------------------------------------- + // If we have a mover class object, check against it + //-------------------------------------------------- + // + if (entity->IsDerivedFrom(*Mover::GetClassDerivations())) + { + mover = Cast_Object(Mover *,entity); + Check(mover); + + mover->CheckVolumeAgainstBoxedSolidChain(&collision_list, splash_volume); + } + } + + // + //------------------------------------------------------------------------- + // Test against the static world + //------------------------------------------------------------------------- + // + InterestManager *interest_mgr = application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + tree->FindBoundingBoxesContaining( + splash_volume, + collision_list + ); + + Check_Fpu(); + Unregister_Object(collision_assistant); + delete collision_assistant; + Unregister_Object(splash_volume); + delete splash_volume; + + // + //------------------------------------------------------------------------- + // Make a sorted list of all the entities from the collision list, + // sorted by their distance from the explosion's origin. + //------------------------------------------------------------------------- + // + VChainOf radius_chain(NULL,False); + VChainIteratorOf radius_chain_iterator(radius_chain); + + Vector3D radius; + Entity *target_entity; + + + // + + for(int i = 0;i < collision_list.GetCollisionCount(); i++) + { + BoxedSolidCollision bsc = collision_list[i]; + Check(&bsc); + target_entity = (Entity*) ((bsc.GetTreeVolume())->GetOwningSimulation()); + Check(target_entity); + Verify(target_entity->IsDerivedFrom(Entity::GetClassDerivations())); + if ((target_entity != entityHit) && (target_entity != this) && (target_entity != excluded)) + { + radius = Vector3D::Identity; + radius.Subtract(target_entity->localOrigin.linearPosition,localOrigin.linearPosition); + radius_chain.AddValue(target_entity, radius); + } + } + + // While remaining_bursts > 0, advance through list, pick a number of bursts + // to inflict, and call SendDamage to the current entity. + + Damage some_damage = damage; + int possible_targets = 0; + int damageable_targets = 0; + radius_chain_iterator.First(); + while ((target_entity = (Entity*) radius_chain_iterator.GetCurrent()) != NULL) + { + Check(target_entity); + radius = radius_chain_iterator.GetValue(); + radius_chain_iterator.Next(); + possible_targets++; + if (target_entity->damageZones) + { + + damageable_targets++; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Set the damage data + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + some_damage.burstCount =damage.burstCount / (pow(radius.Length(), 1.2f)); + Min_Clamp(some_damage.burstCount,1); + #if DEBUG_LEVEL > 0 + DEBUG_STREAM << "At radius " << radius.Length() << ", applied burstCount is " << some_damage.burstCount << std::endl << std::flush; + DEBUG_STREAM << "Damage per burst is " << some_damage.damageAmount << std::endl << std::flush; + #endif + Vector3D force = Vector3D::Identity; + force.Multiply(radius,localToWorld); + some_damage.damageForce = force; + Point3D origin_point = Point3D::Identity; + origin_point.Add(localOrigin.linearPosition,offset); + some_damage.impactPoint = origin_point; + //some_damage.impactPoint.Add(origin_point,radius); + + // + //------------------------------------------ + // Send a damage message to the current target entity + //------------------------------------------ + // + + if (target_entity->GetEntityID() == inflicting) + { + DEBUG_STREAM << "Splash damage hurting inflicting entity." << std::endl << std::flush; + } + + if (excluded && target_entity->GetEntityID() == excluded->GetEntityID() ) + { + DEBUG_STREAM << "Splash damage hurting excluded entity!" << std::endl << std::flush; + } + + Entity::TakeDamageMessage take_damage( + Entity::TakeDamageMessageID, + sizeof(Entity::TakeDamageMessage), + inflicting, + -1, // We can't know what damage zone we hit + some_damage + ); + target_entity->Dispatch(&take_damage); + } + } + + #if DEBUG_LEVEL >0 + DEBUG_STREAM << "There were " << possible_targets << "entities within range, only " << damageable_targets << " had damage zones" << std::endl << std::flush; + #endif + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Explosion::Explosion( + Explosion::MakeMessage *creation_message, + Explosion::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // zero out any rotation + //~~~~~~~~~~~~~~~~~~~~~~~ + // + localOrigin.angularPosition = Quaternion::Identity; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the explosion model resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *resource_description; + ModelResource *model_resource; + + Check(application); + Check(application->GetResourceFile()); + resource_description = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(resource_description); + resource_description->Lock(); + model_resource = (ModelResource*)resource_description->resourceAddress; + Check_Pointer(model_resource); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the creating entity and entity hit by explosion + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application->GetHostManager()); + entityHit = + application->GetHostManager()->GetEntityPointer( + creation_message->entityHitID + ); + Check(entityHit); + + if (creation_message->creatingEntityID != EntityID::Null) + { + creatingEntity = + application->GetHostManager()->GetEntityPointer( + creation_message->creatingEntityID + ); + Check(creatingEntity); + } + else + { + creatingEntity = NULL; + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Calculate the localHitPosition in terms + // local coordinate system of the entityHit + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + localHitPosition.MultiplyByInverse( + localOrigin.linearPosition, + entityHit->localToWorld + ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the explosion duration + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + explosionDuration = model_resource->explosionDuration; + +#if 0 + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If an explosion resource table is being used then + // use it to set the resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (model_resource->resourceTableObjectID != NullObjectID) + { + // + // If the explosion hit us, set the material to our craft, + // If the explosion hit an opponent, set the material to other craft, + // If the explosion hit something else then get the material... + // + Enumeration material_type; + + Check(application); + Entity *viewpoint_entity = application->GetViewpointEntity(); + Check(viewpoint_entity); + Verify(creation_message->entityHitID != EntityID::Null); + + // ECH 8/25/95 - Is this the best way to get our vehicle? + if ( + creation_message->entityHitID == + viewpoint_entity->GetEntityID() + ) + { + material_type = BoxedSolid::OurCraftMaterial; + } + else + { + // ECH 8/25/95 - Is this the best way to identify other vehicles? + if ( + entityHit != NULL && + entityHit->GetPlayerLink() != NULL + ) + { + material_type = BoxedSolid::OtherCraftMaterial; + } + else + { + // ECH 8/25/95 - How to get material? Just use this for now. + material_type = BoxedSolid::ConcreteMaterial; + } + } + + // + // Get resource table pointer, + // Then set the appropriate resource ID + // + Plug *plug; + ExplosionResourceTable *resource_table; + ResourceDescription::ResourceID new_resource_ID; + + plug = PlugStreamManager::FindPlug(model_resource->resourceTableObjectID); + resource_table = Cast_Object(ExplosionResourceTable*, plug); + Check(resource_table); + new_resource_ID = resource_table->FindResourceID(material_type); + if (new_resource_ID != ResourceDescription::NullResourceID) + { + resourceID = new_resource_ID; + } + } +#else + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If an explosion resource table is being used then + // use it to set the resource + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (model_resource->resourceTableObjectID != NullObjectID) + { + // + // Get resource table pointer, + // Then set the appropriate resource ID + // + Plug *plug; + ExplosionResourceTable *resource_table; + ResourceDescription::ResourceID new_resource_ID; + + plug = PlugStreamManager::FindPlug(model_resource->resourceTableObjectID); + resource_table = Cast_Object(ExplosionResourceTable*, plug); + Check(resource_table); + new_resource_ID = resource_table->FindResourceID(entityHit); + if (new_resource_ID != ResourceDescription::NullResourceID) + { + resourceID = new_resource_ID; + } + } +#endif + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Set performance and entity validity + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + resource_description->Unlock(); + SetPerformance(&Explosion::ExplosionSimulation); + SetValidFlag(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Explosion* + Explosion::Make(Explosion::MakeMessage *creation_message) +{ + Check(application); + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + Entity *entity = host_mgr->GetEntityPointer(creation_message->entityHitID); + if (entity) + { + return new Explosion(creation_message); + } + Tell( + "Warning: Explosion ignored - entity " << creation_message->entityHitID + << " couldn't be found!\n" + ); + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Explosion::~Explosion() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Explosion::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateModelResource +// +ResourceDescription::ResourceID + Explosion::CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories* + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + ModelResource local_model; + if( + !model_file->GetEntry( + "gamedata", + "ExplosionDuration", + &local_model.explosionDuration + ) + ) + { + std::cerr<GetEntry( + "gamedata", + "ExplosionResourceTable", + &resource_table_name + ) + ) + { + // + // Get the object ID and set it in the model resource + // + local_model.resourceTableObjectID = + PlugStreamManager::FindPlugName(resource_table_name); + if (local_model.resourceTableObjectID == NullObjectID) + { + std::cout << "resource_table_name == " << resource_table_name << "\n"; + Fail("Explosion::CreateModelResource - ExplosionResourceTable not found"); + } + Verify(local_model.resourceTableObjectID != NullObjectID); + } + else + { + local_model.resourceTableObjectID = NullObjectID; + } + + ResourceDescription *resource_description = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + &local_model, + sizeof(ModelResource) + ); + Check(resource_description); + return resource_description->resourceID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Enumeration + Explosion::GetInterestPriority(Entity *linked_entity) +{ + Check(this); + Check(linked_entity); + + return + ( + (linked_entity == creatingEntity) ? + HighInterestPriority : + LowInterestPriority + ); +} + +//############################################################################# +//###################### ExplosionResourceTable ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +ExplosionResourceTable::ExplosionResourceTable(PlugStream *stream): + Plug(stream), + resourceIDSocket(NULL, True) +{ + Check(stream); + Check(&resourceIDSocket); + + CollectionSize table_size; + *stream >> table_size; + + for (CollectionSize i = 0; i < table_size; i++) + { + Enumeration material_type; + ResourceDescription::ResourceID resource_ID; + ResourceIDPlug *resource_ID_Plug; + + *stream >> material_type >> resource_ID; + + resource_ID_Plug = new ResourceIDPlug(resource_ID); + Register_Object(resource_ID_Plug); + resourceIDSocket.AddValue(resource_ID_Plug, material_type); + } +} + +// +//############################################################################# +//############################################################################# +// +ExplosionResourceTable::~ExplosionResourceTable() +{ + TableIteratorOf + iterator(&resourceIDSocket); + + Check(&iterator); + iterator.DeletePlugs(); +} + +// +//############################################################################# +//############################################################################# +// +void + ExplosionResourceTable::BuildFromPage( + ObjectStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Check(stream); + Check(name_list); + + Plug::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + //-------------------------------------------------------------------------- + // Write number of entries + //-------------------------------------------------------------------------- + // + CollectionSize table_size = 0; + NameList::Entry *entry; + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("table_entry")) + table_size++; + entry = entry->GetNextEntry(); + } + *stream << table_size; + + // + //-------------------------------------------------------------------------- + // Write entries + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + CollectionSize i = 0; + #endif + + Check(name_list); + entry = name_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("table_entry")) + { + CString table_entry, token; + Enumeration material_type; + ResourceDescription *resource_description; + ResourceDescription::ResourceID resource_ID; + + Check_Pointer(entry->GetChar()); + table_entry = entry->GetChar(); + + // + // Material + // + Check_Pointer(table_entry.GetNthToken(0)); + material_type = atol(table_entry.GetNthToken(0)); + + // + // Resource + // + Check_Pointer(table_entry.GetNthToken(1)); + Check(stream->GetResourceFile()); + resource_description = + stream->GetResourceFile()->FindResourceDescription( + table_entry.GetNthToken(1), + ResourceDescription::ModelListResourceType + ); + Check(resource_description); + resource_ID = resource_description->resourceID; + + *stream << material_type << resource_ID; + #if DEBUG_LEVEL>0 + i++; + #endif + } + entry = entry->GetNextEntry(); + } + #if DEBUG_LEVEL>0 + Verify(i == table_size); + #endif +} + +// +//############################################################################# +//############################################################################# +// +Logical + ExplosionResourceTable::TestInstance() const +{ + Plug::TestInstance(); + Check(&resourceIDSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +ResourceDescription::ResourceID + ExplosionResourceTable::FindResourceID(Enumeration material_type) +{ + Check(this); + + ResourceIDPlug *resource_ID_Plug; + if ((resource_ID_Plug = resourceIDSocket.Find(material_type)) != NULL) + { + Check(resource_ID_Plug); + return resource_ID_Plug->GetItem(); + } + return ResourceDescription::NullResourceID; +} + +// +//############################################################################# +//############################################################################# +// +ResourceDescription::ResourceID + ExplosionResourceTable::FindResourceID(Entity *entity_hit) +{ + Check(this); + Check(entity_hit); + + // + // If the explosion hit us, set the material to our craft, + // If the explosion hit an opponent, set the material to other craft, + // If the explosion hit something else then get the material... + // + Enumeration material_type; + Entity *viewpoint_entity; + + Check(application); + viewpoint_entity = application->GetViewpointEntity(); + Check(viewpoint_entity); + + // ECH 8/25/95 - Is this the best way to get our vehicle? + if (entity_hit->GetEntityID() == viewpoint_entity->GetEntityID()) + { + material_type = BoxedSolid::OurCraftMaterial; + } + // ECH 8/25/95 - Is this the best way to identify other vehicles? + else if (entity_hit->GetPlayerLink() != NULL) + { + material_type = BoxedSolid::OtherCraftMaterial; + } + else + { + // ECH 8/25/95 - How to get material? Just use this for now. + material_type = BoxedSolid::ConcreteMaterial; + } + + // + // Return the appropriate resource ID + // + return FindResourceID(material_type); +} diff --git a/MUNGA/EXPLODE.h b/MUNGA/EXPLODE.h new file mode 100644 index 0000000..8c8b6fd --- /dev/null +++ b/MUNGA/EXPLODE.h @@ -0,0 +1,187 @@ +#pragma once + +#include "entity.h" +#include "boxsolid.h" +#include "table.h" + +//########################################################################## +//##################### Explosion::ModelResource ##################### +//########################################################################## + +struct Explosion__ModelResource +{ + ObjectID resourceTableObjectID; + Scalar explosionDuration; +}; + +//########################################################################## +//########################### Explosion ############################## +//########################################################################## + +class Explosion__MakeMessage; + +class Damage; +class Mover; + +class Explosion : public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef Explosion__ModelResource + ModelResource; + + typedef void + (Explosion::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + ExplosionSimulation(Scalar time_slice); + + static ResourceDescription::ResourceID + Explosion::CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + + typedef ChainIteratorOf EntityIterator; + + void + SplashDamage( + EntityID inflicting, + Damage &damage, + Scalar collisionRadius, + Vector3D offset = Vector3D::Identity, + Entity *exludedEntities = NULL + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef Explosion__MakeMessage + MakeMessage; + + static Explosion* + Make(MakeMessage *creation_message); + + Explosion( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~Explosion(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + Enumeration + GetInterestPriority(Entity *linked_entity); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected Data +// +protected: + Scalar + explosionDuration; + Entity + *entityHit; + Entity + *creatingEntity; + Point3D + localHitPosition; +}; + +//########################################################################## +//##################### Explosion::MakeMessage ####################### +//########################################################################## + +class Explosion__MakeMessage: + public Entity::MakeMessage +{ +public: + EntityID + entityHitID; + EntityID + creatingEntityID; + + Explosion__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID + ): + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + entityHitID(entity_hit_ID), + creatingEntityID(creating_entity_ID) + {} +}; + +//########################################################################## +//###################### ExplosionResourceTable ###################### +//########################################################################## + +class ExplosionResourceTable: + public Plug +{ +public: + typedef PlugOf + ResourceIDPlug; + + ExplosionResourceTable(PlugStream *stream); + ~ExplosionResourceTable(); + + static void + BuildFromPage( + ObjectStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + Logical + TestInstance() const; + + ResourceDescription::ResourceID + FindResourceID(Enumeration material_type); + ResourceDescription::ResourceID + FindResourceID(Entity *entity_hit); + +private: + TableOf + resourceIDSocket; +}; diff --git a/MUNGA/EXPTBL.cpp b/MUNGA/EXPTBL.cpp new file mode 100644 index 0000000..b41c851 --- /dev/null +++ b/MUNGA/EXPTBL.cpp @@ -0,0 +1,605 @@ +#include "munga.h" +#pragma hdrstop + +#include "exptbl.h" +#include "namelist.h" +#include "registry.h" +#include "app.h" +#include "explode.h" +#include "damage.h" +#include "notation.h" +#include "fileutil.h" +#include "renderer.h" + +//############################################################################## +//###################### Class ExplosionTableEntry ######################## +//############################################################################## + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ExplosionTableEntry::CreateExplosion( + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + const Point3D &explode_position + ) +{ + Check(this); + Origin explode_origin(Origin::Identity); + explode_origin = explode_position; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the explosion MakeMessage + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Explosion::MakeMessage exp_message( + Explosion::MakeMessageID, + sizeof(Explosion::MakeMessage), + RegisteredClass::ExplosionClassID, + EntityID::Null, + explosionResourceID, + Explosion::DefaultFlags, + explode_origin, + entity_hit_ID, + creating_entity_ID + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Calculate actual time based on time_delay + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Time when = Now(); + when += timeDelay; + Check(application); + + Registry *registry; + registry = application->GetRegistry(); + Check_Pointer(registry); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a MakeEntityMessage + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Registry::MakeEntityMessage *registry_message; + registry_message = Registry::MakeEntityMessage::Make(&exp_message); + Register_Object(registry_message); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Post entity message to the registry + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + #if 0 // ECH 1/28/96 + application->Post( + DefaultEventPriority, + registry, + registry_message, + when + ); + #else + application->Post( + CreationEventPriority, + registry, + registry_message, + when + ); + #endif + Unregister_Object(registry_message); + delete registry_message; + + Check_Fpu(); +} +//############################################################################## +// Construction/Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExplosionTableEntry::ExplosionTableEntry(MemoryStream *exp_stream) +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the data from the stream + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + *exp_stream >> damageLevel >> explosionResourceID >> graphicState; + *exp_stream >> timeDelay; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExplosionTableEntry::~ExplosionTableEntry() +{ + +} + +//############################################################################## +// Tool Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExplosionTableEntry::CreateStreamedExplosion( + ResourceFile *resource_file, + CString exp_file_name, + NotationFile *exp_file, + CString exp_page_name, + MemoryStream *explosion_stream + ) +{ + Check(exp_file); + + // + //~~~~~~~~~~~~~~~~~~~~ + // Get the DamageLevel + //~~~~~~~~~~~~~~~~~~~~ + // + Scalar damage_level; + if (!exp_file->GetEntry( + exp_page_name, + "DamageLevel", + &damage_level + ) + ) + { + damage_level = -1.0f; + } + *explosion_stream << damage_level; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Explosion Model File + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char *explosion_model_file; + if (!exp_file->GetEntry( + exp_page_name, + "ExplosionModelFile", + &explosion_model_file + ) + ) + { + DEBUG_STREAM <FindResourceDescription( + explosion_model_file, + ResourceDescription::ModelListResourceType + ); + if (!res) + { + std::cout << exp_file_name << " cannot find " << explosion_model_file + << " in resource file!\n"; + return False; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write out the resourceID + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // + *explosion_stream << res->resourceID; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the Graphic State + //~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char *graphic_state_char; + Enumeration graphic_state; + if (exp_file->GetEntry( + exp_page_name, + "GraphicState", + &graphic_state_char + ) + ) + { + if (!strcmp(graphic_state_char, "Destroyed")) + { + graphic_state = DamageZone::DestroyedGraphicState; + } + else if (!strcmp(graphic_state_char, "Gone")) + { + graphic_state = DamageZone::GoneGraphicState; + } + } + else + { + graphic_state = DamageZone::ExistsGraphicState; + } + *explosion_stream << graphic_state; + // + //~~~~~~~~~~~~~~~~~~~~ + // Get the TimeDelay + //~~~~~~~~~~~~~~~~~~~~ + // + Scalar time_delay; + if (!exp_file->GetEntry( + exp_page_name, + "TimeDelay", + &time_delay + ) + ) + { + time_delay = 0.0f; + } + *explosion_stream << time_delay; + return True; +} + +//############################################################################## +//######################## Class ExplosionTable ########################### +//############################################################################## +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExplosionTable::CrossedDamageLevelThreshold( + Scalar old_value, + Scalar new_value + ) +{ + ExplosionTableIterator iterator(this); + ExplosionTableEntry *current_exp; + + while ((current_exp = iterator.ReadAndNext()) != NULL) + { + if ( + (old_value < current_exp->GetDamageLevel()) && + (new_value >= current_exp->GetDamageLevel()) + ) + { + return True; + } + } + return False; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExplosionTableEntry* + ExplosionTable::SelectDamageLevelEntry(Scalar damage_level) +{ + ExplosionTableIterator iterator(this); + ExplosionTableEntry *current_exp; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Choose ExplosionTableEntry by damage Level + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + while ((current_exp = iterator.ReadAndNext()) != NULL) + { + if (damage_level < current_exp->GetDamageLevel()) + { + Check_Fpu(); + return current_exp; + } + } + + Check_Fpu(); + return NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExplosionTableEntry* + ExplosionTable::SelectGraphicStateEntry(Enumeration graphic_state) +{ + ExplosionTableIterator iterator(this); + ExplosionTableEntry *current_entry; + while((current_entry = iterator.ReadAndNext() ) != NULL) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Display Explosion if an Entry Exists + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (current_entry->GetGraphicState() == graphic_state) + { + Check_Fpu(); + return current_entry; + } + } + Check_Fpu(); + return NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ExplosionTable::CreateExplosion( + ExplosionTableEntry *explosion_entry, + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + Point3D explode_position + ) +{ + Check(this); + Check(explosion_entry); + explosion_entry->CreateExplosion( + entity_hit_ID, + creating_entity_ID, + explode_position + ); +} + +//############################################################################## +// Construction/Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExplosionTable::ExplosionTable(MemoryStream *exp_stream): + TableOf(NULL, True) +{ + int entry_count; + *exp_stream >> entry_count; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create all of the ExplosionTableEntries + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ExplosionTableEntry *exp_entry; + + for(int ii=0;iiMakePageList(); + Register_Object(exp_namelist); + if (!exp_namelist->EntryCount()) + { + DEBUG_STREAM << exp_file << " is empty or missing \n"<EntryCount(); + *explosion_stream << entry_count; + + NameList::Entry *exp_entry = exp_namelist->GetFirstEntry(); + while(exp_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // While more pages Add ExplosionEntries to the stream + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ExplosionTableEntry::CreateStreamedExplosion( + resource_file, + exp_filename, + exp_file, + exp_entry->GetName(), + explosion_stream + ); + exp_entry = exp_entry->GetNextEntry(); + } + Unregister_Object(exp_namelist); + delete exp_namelist; + + return True; +} + +//########################################################################## +//###################### EntityEffectWatcher ######################### +//########################################################################## + +//############################################################################## +// Construction/Destruction +// + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityEffectWatcher::EntityEffectWatcher( + Entity *entity_watched +) +{ + entityWatched = entity_watched; + entityWatched->AddEffectWatcher(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Init array to hold previous damageLevel values + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Verify(entityWatched->damageZoneCount > 0); + oldDamageLevel = new Scalar[entityWatched->damageZoneCount]; + Register_Pointer(oldDamageLevel); + for(int ii=0;iidamageZoneCount;++ii) + { + oldDamageLevel[ii] = 0.0f; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +EntityEffectWatcher::~EntityEffectWatcher() +{ + Unregister_Pointer(oldDamageLevel); + delete[] oldDamageLevel; +} +//############################################################################## +// Execute +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void + EntityEffectWatcher::Execute() +{ + Check(this); + Check(entityWatched); + Check_Pointer(entityWatched->damageZones); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Check the flags to see if any damageZones + // have been modified since the last Execute was called + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + DamageZone *current_zone; + ExplosionTable *exp_table; + ExplosionTableEntry *exp_entry(NULL); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Traverse damageZones looking for Changes + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for (int ii=0;iidamageZoneCount; ++ii) + { + current_zone = entityWatched->damageZones[ii]; + Check(current_zone); + ResourceDescription::ResourceID exp_res; + exp_table = current_zone->GetExplosionTable(); + Check(exp_table); + // + //~~~~~~~~~~~~~~~~~~~ + // Check Damage Level + //~~~~~~~~~~~~~~~~~~~ + // + if (current_zone->DamageLevelChanged()) + { + exp_entry = exp_table->SelectDamageLevelEntry(current_zone->damageLevel); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If delta was large enough signal an update + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if ( + exp_table->CrossedDamageLevelThreshold( + oldDamageLevel[ii], + current_zone->damageLevel + ) && + (entityWatched->GetInstance() == Entity::MasterInstance) + ) + { + entityWatched->ForceUpdate(Entity::DamageZoneUpdateModelFlag); + } + oldDamageLevel[ii] = current_zone->damageLevel; + } + // + //~~~~~~~~~~~~~~~~~~~~ + // Check Graphic State + //~~~~~~~~~~~~~~~~~~~~ + // + if (current_zone->GraphicStateChanged()) + { + exp_entry = exp_table->SelectGraphicStateEntry( + current_zone->GetGraphicState() + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Always update for a graphic state change + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (entityWatched->GetInstance() == Entity::MasterInstance) + { + entityWatched->ForceUpdate(Entity::DamageZoneUpdateModelFlag); + } + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Notify RendererManager of Any Change + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (exp_entry) + { + Check(exp_entry); + exp_res = exp_entry->GetExplosionResourceID(); + + Check(application); + Check(application->GetRendererManager()); + application->GetRendererManager()->StartEntityEffect( + entityWatched, + current_zone, + exp_res + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Reset the DamageZone::changedFlags if + // I am a master and no update occurred OR + // if I am a replicant + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if ( + ( + (entityWatched->GetInstance() == Entity::MasterInstance) && + !entityWatched->DamageZoneUpdateModelFlagSet() + ) || + ( + (entityWatched->GetInstance() == Entity::ReplicantInstance) + ) + ) + { + current_zone->ResetChangedFlags(); + } + } + exp_entry = NULL; + } + Check_Fpu(); +} + +//############################################################################## +// Test Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityEffectWatcher::TestInstance() const +{ + Check(entityWatched); + return True; +} diff --git a/MUNGA/EXPTBL.h b/MUNGA/EXPTBL.h new file mode 100644 index 0000000..5b3e3b9 --- /dev/null +++ b/MUNGA/EXPTBL.h @@ -0,0 +1,209 @@ +#pragma once + +#include "plug.h" +#include "table.h" +#include "resource.h" +#include "entityid.h" +#include "cmpnnt.h" + +class Entity; +class NotationFile; +class Point3D; + +//############################################################################## +//###################### Class ExplosionTableEntry ######################## +//############################################################################## + +class ExplosionTableEntry : public Plug +{ + + protected: + + Scalar + damageLevel; + + Enumeration + graphicState; + + ResourceDescription::ResourceID + explosionResourceID; + + Scalar + timeDelay; + + public: + + ExplosionTableEntry(MemoryStream *exp_stream); + ~ExplosionTableEntry(); + + static Logical + CreateStreamedExplosion( + ResourceFile *resource_file, + CString exp_file_name, + NotationFile *exp_file, + CString exp_page_name, + MemoryStream *explosion_stream + ); + + ResourceDescription::ResourceID + GetExplosionResourceID() const + {Check(this); return explosionResourceID;} + + Scalar + GetDamageLevel() const + {Check(this); return damageLevel;} + + Enumeration + GetGraphicState() const + {Check(this); return graphicState;} + + Scalar + GetTimeDelay() const + {Check(this); return timeDelay;} + + void + CreateExplosion( + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + const Point3D &explode_position + ); +}; + +//############################################################################## +//######################## Class ExplosionTable ########################### +//############################################################################## + +// (Although sharing instance not fully implemented yet!) +// Note: Explosion tables specifically do not hold any references to any +// specific damage Zone as you will most likely be sharing instances of +// explosion tables across entity's, subsystem's, etc.. +// +class ExplosionTable : public TableOf +{ + protected: + + typedef + TableIteratorOf + ExplosionTableIterator; + + public: + + ExplosionTable(MemoryStream *exp_stream); + ~ExplosionTable(); + + ExplosionTableEntry* + SelectDamageLevelEntry(Scalar damage_level); + + ExplosionTableEntry* + SelectGraphicStateEntry(Enumeration graphic_state); + + void + DamageExplosion( + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + Scalar damage_level, + const Point3D &explode_position + ) + { + Check(this); + ExplosionTableEntry *exp_entry = SelectDamageLevelEntry(damage_level); + if (exp_entry) + { + CreateExplosion( + exp_entry, + entity_hit_ID, + creating_entity_ID, + explode_position + ); + } + #if DEBUG_LEVEL>0 + else + { + Tell("DamageLevel = "); + Tell(damage_level); + Warn("not valid for ExplosionTable, no Explosion being created !\n"); + } + #endif + } + + void + CreateExplosion( + ExplosionTableEntry *explosion_entry, + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + Point3D explode_position // world coordinates + ); + + void + GraphicStateExplosion( + const EntityID &entity_hit_ID, + const EntityID &creating_entity_ID, + const Point3D &explode_position, + Enumeration graphic_state + ) + { + Check(this); + ExplosionTableEntry *exp_entry = SelectGraphicStateEntry(graphic_state); + if (exp_entry) + { + CreateExplosion( + exp_entry, + entity_hit_ID, + creating_entity_ID, + explode_position + ); + } + #if DEBUG_LEVEL>0 + else + { + Tell("DamageZone::GraphicState = "); + Tell(graphic_state); + Warn("not valid for ExplosionTable, no Explosion being created !\n"); + } + #endif + } + + Logical + CrossedDamageLevelThreshold(Scalar old_value, Scalar new_value); + + static Logical + CreateStreamedExplosionTable( + ResourceFile *resource_file, + CString model_name, + NotationFile *exp_file, + CString exp_filename, + MemoryStream *explosion_stream + ); +}; + +//########################################################################## +//###################### EntityEffectWatcher ######################### +//########################################################################## + +class EntityEffectWatcher : + public Component +{ + protected: + + Scalar + *oldDamageLevel; + + Entity + *entityWatched; + + public: + + EntityEffectWatcher( + Entity *entity_watched + ); + + ~EntityEffectWatcher(); + + + Logical + TestInstance() const; + + void + Execute(); + +}; diff --git a/MUNGA/EXTNTBOX.cpp b/MUNGA/EXTNTBOX.cpp new file mode 100644 index 0000000..7320abf --- /dev/null +++ b/MUNGA/EXTNTBOX.cpp @@ -0,0 +1,251 @@ +#include "munga.h" +#include "windows.h" +#pragma hdrstop + +#include "extntbox.h" +#include "cstr.h" +#include "vector3d.h" +#include "notation.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile ExtentBox *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExtentBox::ExtentBox( + const Vector3D &min, + const Vector3D &max +) +{ + Check_Pointer(this); + Check(&min); + Check(&max); + + if (min.x <= max.x) + { + minX = min.x; + maxX = max.x; + } + else + { + minX = max.x; + maxX = min.x; + } + + if (min.y <= max.y) + { + minY = min.y; + maxY = max.y; + } + else + { + minY = max.y; + maxY = min.y; + } + + if (min.z <= max.z) + { + minZ = min.z; + maxZ = max.z; + } + else + { + minZ = max.z; + maxZ = min.z; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExtentBox::ExtentBox(const ExtentBox &box) +{ + Check_Pointer(this); + Check(&box); + + minX = box.minX; + maxX = box.maxX; + minY = box.minY; + maxY = box.maxY; + minZ = box.minZ; + maxZ = box.maxZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ExtentBox& + ExtentBox::Intersect( + const ExtentBox &box_1, + const ExtentBox &box_2 + ) +{ + Check_Pointer(this); + Check(&box_1); + Check(&box_2); + + Verify(box_1.minX <= box_2.maxX); + Verify(box_1.maxX >= box_2.minX); + Verify(box_1.minY <= box_2.maxY); + Verify(box_1.maxY >= box_2.minY); + Verify(box_1.minZ <= box_2.maxZ); + Verify(box_1.maxZ >= box_2.minZ); + + minX = Max(box_1.minX, box_2.minX); + maxX = Min(box_1.maxX, box_2.maxX); + minY = Max(box_1.minY, box_2.minY); + maxY = Min(box_1.maxY, box_2.maxY); + minZ = Max(box_1.minZ, box_2.minZ); + maxZ = Min(box_1.maxZ, box_2.maxZ); + + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Vector3D* + ExtentBox::Constrain(Vector3D *point) const +{ + Check(this); + Check(point); + + Clamp(point->x,minX,maxX); + Clamp(point->y,minY,maxY); + Clamp(point->z,minZ,maxZ); + return point; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::Contains(const Vector3D &point) const +{ + return + minX <= point.x && maxX >= point.x + && minY <= point.y && maxY >= point.y + && minZ <= point.z && maxZ >= point.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::Contains(const ExtentBox &box) const +{ + return + minX <= box.minX && maxX >= box.maxX + && minY <= box.minY && maxY >= box.maxY + && minZ <= box.minZ && maxZ >= box.maxZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::Intersects(const ExtentBox &box) const +{ + return + minX <= box.maxX && maxX >= box.minX + && minY <= box.maxY && maxY >= box.minY + && minZ <= box.maxZ && maxZ >= box.minZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ExtentBox::TestInstance() const +{ + return minX<=maxX && minY<=maxY && minZ<=maxZ; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +std::ostream& operator<<(std::ostream& stream, const ExtentBox& e) +{ + return stream << '[' << e.minX << ".." << e.maxX << "],[" << e.minY << ".." << e.maxY << "],[" << e.minZ << ".." << e.maxZ << ']'; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Convert_From_Ascii( + const char *str, + ExtentBox *extent_box + ) +{ + Check_Pointer(str); + Check_Signature(extent_box); + + CString parse_string(str); + Check(&parse_string); + + Check_Pointer(parse_string.GetNthToken(0)); + extent_box->minX = atof(parse_string.GetNthToken(0)); + + Check_Pointer(parse_string.GetNthToken(1)); + extent_box->minY = atof(parse_string.GetNthToken(1)); + + Check_Pointer(parse_string.GetNthToken(2)); + extent_box->minZ = atof(parse_string.GetNthToken(2)); + + Check_Pointer(parse_string.GetNthToken(3)); + extent_box->maxX = atof(parse_string.GetNthToken(3)); + + Check_Pointer(parse_string.GetNthToken(4)); + extent_box->maxY = atof(parse_string.GetNthToken(4)); + + Check_Pointer(parse_string.GetNthToken(5)); + extent_box->maxZ = atof(parse_string.GetNthToken(5)); + + Check(extent_box); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +ExtentBox * + MakeExistanceBoxStream( + NotationFile *notation_file, + int *size + ) +{ + + char page_name[50]; + + if (!notation_file->GetEntry("COLLISION", "extentcount", size)) + { + std::cerr << "No 'COLLISION' entry!!!!!" << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + ExtentBox *extents = new ExtentBox[*size]; + + for (int j=0; j < *size; ++j) + { + sprintf(page_name, "extent %d", j); + + int errorvalue = 0; + + errorvalue |= !notation_file->GetEntry(page_name, "extminX", &extents[j].minX); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxX", &extents[j].maxX); + errorvalue |= !notation_file->GetEntry(page_name, "extminY", &extents[j].minY); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxY", &extents[j].maxY); + errorvalue |= !notation_file->GetEntry(page_name, "extminZ", &extents[j].minZ); + errorvalue |= !notation_file->GetEntry(page_name, "extmaxZ", &extents[j].maxZ); + + if ( errorvalue ) + { + Tell("Extent number : " << j << " is does not have valid slice extents " << endl << std::flush); + PostQuitMessage(AbortExitCodeID); + } + + } + + return extents; + +} diff --git a/MUNGA/EXTNTBOX.h b/MUNGA/EXTNTBOX.h new file mode 100644 index 0000000..2566b6b --- /dev/null +++ b/MUNGA/EXTNTBOX.h @@ -0,0 +1,60 @@ +#pragma once + +#include "scalar.h" + +class Vector3D; +class NotationFile; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class ExtentBox +{ + public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile ExtentBox *); + #endif + + Scalar minX, maxX, minY, maxY, minZ, maxZ; + + ExtentBox() {} + ExtentBox(const Vector3D &min, const Vector3D &max); + ExtentBox(const ExtentBox &box); + + const Scalar& operator[](int index) const + { + Check(this); + return (&minX)[index]; + } + Scalar& operator[](int index) + { + Check(this); + return (&minX)[index]; + } + + ExtentBox& Intersect(const ExtentBox &box_1, const ExtentBox &box_2); + Vector3D* Constrain(Vector3D *point) const; + + Logical Contains(const Vector3D &point) const; + Logical Contains(const ExtentBox &box) const; + Logical Intersects(const ExtentBox &box) const; + + Logical TestInstance() const; + static Logical TestClass(); + friend std::ostream& operator<<(std::ostream& stream, const ExtentBox& e); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ ExtentBox functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void Convert_From_Ascii(const char *str, ExtentBox *extent_box); + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, ExtentBox *output) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const ExtentBox *input) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + +ExtentBox *MakeExistanceBoxStream(NotationFile *notation_file, int *size); \ No newline at end of file diff --git a/MUNGA/EYECANDY.cpp b/MUNGA/EYECANDY.cpp new file mode 100644 index 0000000..866f865 --- /dev/null +++ b/MUNGA/EYECANDY.cpp @@ -0,0 +1,236 @@ +#include "munga.h" +#pragma hdrstop + +#include "random.h" +#include "eyecandy.h" +#include "app.h" +#include "notation.h" + +//############################################################################# +// Shared Data Support +// +EyeCandy::SharedData + EyeCandy::DefaultData( + EyeCandy::GetClassDerivations(), + EyeCandy::GetMessageHandlers(), + EyeCandy::GetAttributeIndex(), + EyeCandy::StateCount, + (Entity::MakeHandler)EyeCandy::Make + ); + +Derivation* EyeCandy::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(), "EyeCandy"); + return &classDerivations; +} + +//############################################################################# +//############################### EyeCandy ################################# +//############################################################################# + +void + EyeCandy::EyeCandySimulation(Scalar) +{ + Check(application); + + if (simulationState.GetState() == effectOn) + { + simulationState.SetState(effectOff); + } + + Scalar now = Now(); + if ((now - lastTrigger) >= waitTime) + { + simulationState.SetState(effectOn); + lastTrigger = now; + + RandomGenerator random_number; + waitTime = minWaitTime + (maxWaitTime - minWaitTime) * random_number; + } +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EyeCandy::EyeCandy( + EyeCandy::MakeMessage *creation_message , + EyeCandy::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + SetPerformance(&EyeCandy::EyeCandySimulation); + SetValidFlag(); + + // + //------------------------------------------------- + // Find the EyeCandy in the resource + //------------------------------------------------- + // + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + ResourceDescription *res = + res_file->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + + ModelResource *eyecandy_res = (ModelResource*)res->resourceAddress; + maxWaitTime = eyecandy_res->maxWaitTime; + minWaitTime = eyecandy_res->minWaitTime; + res->Unlock(); + + waitTime = minWaitTime + (maxWaitTime - minWaitTime) * Random; + + simulationState.SetState(effectOff); + lastTrigger = Now(); + + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EyeCandy* + EyeCandy::Make(EyeCandy::MakeMessage *creation_message) +{ + return new EyeCandy(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EyeCandy::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->classToCreate = RegisteredClass::EyeCandyClassID; + creation_message->instanceFlags = HermitInstance|DynamicFlag|TrappedFlag; + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EyeCandy::~EyeCandy() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +ResourceDescription::ResourceID + EyeCandy::CreateModelResource( +#if DEBUG_LEVEL>0 + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model +#else + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *, + ModelResource *model +#endif + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check_Pointer(directories); + + // + // If we were not provided a buffer to write the model data into, we must + // create it ourselves. Then make sure that the model stuff is read in + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + //---------------------------------------- + // Read in the data from notation file + //---------------------------------------- + // + // Get PointValue assigned to this ScoreZone + // + + if( + !model_file->GetEntry( + "gamedata", + "MaxWaitTime", + &local_model->maxWaitTime + ) + ) + { + std::cerr << model_name << "Missing MaxWaitTime" << std::endl; +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + return -1; + } + + if( + !model_file->GetEntry( + "gamedata", + "MinWaitTime", + &local_model->minWaitTime + ) + ) + { + std::cerr << model_name << "Missing MinWaitTime" << std::endl; + goto Dump_And_Die; + } + + // + //--------------------------- + // Write out the new resource + //--------------------------- + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + return new_res->resourceID; + } + else + { + return 0; + } +} + +Logical + EyeCandy::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/EYECANDY.h b/MUNGA/EYECANDY.h new file mode 100644 index 0000000..7953fe7 --- /dev/null +++ b/MUNGA/EYECANDY.h @@ -0,0 +1,102 @@ +#pragma once + +#include "entity.h" + +//########################################################################## +//##################### EyeCandy::ModelResource ##################### +//########################################################################## + +struct EyeCandy__ModelResource +{ + Scalar + maxWaitTime; + Scalar + minWaitTime; + +}; + +//########################################################################## +//########################### EyeCandy ############################### +//########################################################################## + +class EyeCandy: + public Entity +{ +public: + enum { + effectOff = Entity::StateCount, + effectOn, + StateCount + }; + +private: + Scalar + maxWaitTime; + Scalar + minWaitTime; + Scalar + waitTime; + Scalar + lastTrigger; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (EyeCandy::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + EyeCandySimulation(Scalar time_slice); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + + typedef EyeCandy__ModelResource ModelResource; + + static EyeCandy* + Make(EyeCandy::MakeMessage *creation_message); + + EyeCandy( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~EyeCandy(); + + Logical + TestInstance() const; + + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static ResourceDescription::ResourceID + EyeCandy::CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model = NULL + ); + +}; diff --git a/MUNGA/FILESTRM.cpp b/MUNGA/FILESTRM.cpp new file mode 100644 index 0000000..4f92c8c --- /dev/null +++ b/MUNGA/FILESTRM.cpp @@ -0,0 +1,122 @@ +#include "munga.h" +#pragma hdrstop + +#include "filestrm.h" + +//############################################################################# +//########################### FileStream ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +FileStream::FileStream(const char* file_name, Logical writable) : MemoryStream(NULL, 0) +{ + Open(file_name, writable); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void FileStream::Open(const char* file_name, Logical writable) +{ + readOnly = !writable; + fileHandle = -1; + currentPosition = streamStart = NULL; + streamSize = 0; + if (file_name) + { + Check_Pointer(file_name); + fileHandle = OpenImplementation(file_name, readOnly); + } + + if (fileHandle != -1) + { + if (readOnly) + { + streamSize = SeekImplementation(fileHandle, 0, True); + SeekImplementation(fileHandle, 0); + } + else + streamSize = 0xFFFFFFFFU; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void FileStream::Close() +{ + Check(this); + + if (fileHandle != -1) + { + if (!readOnly) + FlushImplementation(fileHandle); + CloseImplementation(fileHandle); + } + fileHandle = -1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void FileStream::SetPointer(size_t index) +{ + Check(this); + Verify(fileHandle != -1); + + currentPosition = (char*)SeekImplementation(fileHandle, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& FileStream::AdvancePointer(size_t index) +{ + Check(this); + Verify(fileHandle != -1); + + currentPosition = (char*)SeekImplementation(fileHandle, (size_t)currentPosition + index); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& FileStream::RewindPointer(size_t index) +{ + Check(this); + Verify(fileHandle != -1); + + currentPosition = (char*)SeekImplementation(fileHandle, (size_t)currentPosition + index); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& FileStream::ReadBytes(void *ptr, size_t number_of_bytes) +{ + Check(this); + Verify(fileHandle != -1); + Verify(readOnly); + size_t read = ReadImplementation(fileHandle, ptr, number_of_bytes); + Verify(read == number_of_bytes); + currentPosition += read; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& FileStream::WriteBytes(const void *ptr, size_t number_of_bytes) +{ + Check(this); + Verify(fileHandle != -1); + Verify(!readOnly); + size_t written = WriteImplementation(fileHandle, ptr, number_of_bytes); + Verify(written == number_of_bytes); + currentPosition += written; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical FileStream::TestInstance() const +{ + return true; +} + diff --git a/MUNGA/FILESTRM.h b/MUNGA/FILESTRM.h new file mode 100644 index 0000000..0d08a3d --- /dev/null +++ b/MUNGA/FILESTRM.h @@ -0,0 +1,44 @@ +#pragma once + +#include "memstrm.h" + +class FileStream : public MemoryStream +{ +public: + FileStream(const char* file_name = NULL, Logical writable = false); + ~FileStream() { Close(); } + +public: + void* GetPointer() const + { + Fail("No implementation possible for FileStream::GetPointer()"); + return NULL; + } + + void SetPointer(void *new_pointer) { Fail("No implementation possible for FileStream::SetPointer(void*)"); } + void SetPointer(size_t index); + + MemoryStream& AdvancePointer(size_t count); + + MemoryStream& RewindPointer(size_t count); + + MemoryStream& ReadBytes(void *ptr, size_t number_of_bytes); + MemoryStream& WriteBytes(const void *ptr, size_t number_of_bytes); + + void Open(const char* file_name = NULL, Logical writable = False); + void Close(); + Logical IsFileOpened() { return fileHandle != -1; } + + Logical TestInstance() const; + +protected: + int fileHandle; + Logical readOnly; + + static int OpenImplementation(const char* file_name, Logical read_only); + static void FlushImplementation(int file_handle); + static void CloseImplementation(int file_handle); + static size_t SeekImplementation(int file_handle, size_t where, Logical from_end = false); + static size_t ReadImplementation(int file_handle, void *buffer, size_t length); + static size_t WriteImplementation(int file_handle, const void* buffer, size_t length); +}; \ No newline at end of file diff --git a/MUNGA/FILESTUB.cpp b/MUNGA/FILESTUB.cpp new file mode 100644 index 0000000..5bc168e --- /dev/null +++ b/MUNGA/FILESTUB.cpp @@ -0,0 +1,80 @@ +#include "munga.h" +#pragma hdrstop + +#include "filestrm.h" +#include +#include +#include + +//############################################################################# +//########################### FileStream ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + FileStream::OpenImplementation( + const char *file_name, + Logical read_only + ) +{ + if (read_only) + { + return _open(file_name, _O_BINARY | _O_RDONLY); + } + else + { + return _open(file_name, _O_BINARY | _O_CREAT | _O_TRUNC | _O_WRONLY, _S_IWRITE); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void FileStream::FlushImplementation(int file_handle) +{ + _commit(file_handle); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void FileStream::CloseImplementation(int file_handle) +{ + _close(file_handle); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::SeekImplementation( + int file_handle, + size_t where, + Logical from_end + ) +{ + return _lseek(file_handle, (long)where, (from_end) ? SEEK_END : SEEK_SET); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::ReadImplementation( + int file_handle, + void *buffer, + size_t length + ) +{ + return _read(file_handle, buffer, length); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +size_t + FileStream::WriteImplementation( + int file_handle, + const void *buffer, + size_t length + ) +{ + return _write(file_handle, buffer, length); +} + diff --git a/MUNGA/FILEUTIL.cpp b/MUNGA/FILEUTIL.cpp new file mode 100644 index 0000000..dc3777c --- /dev/null +++ b/MUNGA/FILEUTIL.cpp @@ -0,0 +1,825 @@ +#include "munga.h" +#include "windows.h" +#pragma hdrstop + +#include +#include "fileutil.h" +#include "notation.h" + +char *WorkingDirectory = NULL; + +//############################################################################# + +const char *White_Space = " \t\n"; + +//############################################################################# + +char + *SourceDirectory = NULL, + *ConfigDirectory = NULL, + *MaterialDirectory = NULL, + *TextureDirectory = NULL, + *AnimationDirectory = NULL, + *ProductionDirectory = NULL; +const char + *OutputDirectory = NULL; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SetSourceDirectory(const char *input_file) +{ + Check_Pointer(input_file); + + static const char + * const ARTTOOLS_FILENAME = ".arttoolsrc", + * const DIRECTORIES_PAGE = "directories", + * const CFG_DIR_ENTRY = "cfg_dir", + * const MTL_DIR_ENTRY = "mtl_dir", + * const TEX_DIR_ENTRY = "tex_dir", + * const KIN_DIR_ENTRY = "kin_dir", + * const PRD_DIR_ENTRY = "prd_dir"; + + NotationFile + *tools_info; + char + *cwd; + const char + *cp, + *contents; + + //------------------------------------------------ + // parse the source directory from the input file + //------------------------------------------------ + if ((cp = strrchr(input_file, '/')) == NULL) + { + //--------------------------------------------------- + // set source directory to current working directory + //--------------------------------------------------- + cwd = _getcwd(NULL, 256); + Verify( cwd ); + SourceDirectory = new char[strlen(cwd) + 2]; + Register_Pointer(SourceDirectory); + strcpy(SourceDirectory, cwd); + strcat(SourceDirectory, "/"); + free(cwd); + } + else + { + //------------------------------------------------------ + // set source directory to path specified in input file + //------------------------------------------------------ + ++cp; + SourceDirectory = new char[cp - input_file + 1]; + Register_Pointer(SourceDirectory); + *SourceDirectory = '\0'; + strncat(SourceDirectory, input_file, cp - input_file); + } + + //----------------------------------------------------------- + // set other directories from tools config file (if present) + //----------------------------------------------------------- + tools_info = new NotationFile(SourceFile(ARTTOOLS_FILENAME)); + Register_Object(tools_info); + + if (tools_info->GetEntry(DIRECTORIES_PAGE, CFG_DIR_ENTRY, &contents)) + { + ConfigDirectory = new char[strlen(contents) + 2]; + Register_Pointer(ConfigDirectory); + strcpy(ConfigDirectory, contents); + cp = strchr(contents, '\0'); + if (cp > contents && *--cp != '/') + { + strcat(ConfigDirectory, "/"); + } + } + else + { + ConfigDirectory = SourceDirectory; + } + + if (tools_info->GetEntry(DIRECTORIES_PAGE, MTL_DIR_ENTRY, &contents)) + { + MaterialDirectory = new char[strlen(contents) + 2]; + Register_Pointer(MaterialDirectory); + strcpy(MaterialDirectory, contents); + cp = strchr(contents, '\0'); + if (cp > contents && *--cp != '/') + { + strcat(MaterialDirectory, "/"); + } + } + else + { + MaterialDirectory = SourceDirectory; + } + + if (tools_info->GetEntry(DIRECTORIES_PAGE, TEX_DIR_ENTRY, &contents)) + { + TextureDirectory = new char[strlen(contents) + 2]; + Register_Pointer(TextureDirectory); + strcpy(TextureDirectory, contents); + cp = strchr(contents, '\0'); + if (cp > contents && *--cp != '/') + { + strcat(TextureDirectory, "/"); + } + } + else + { + TextureDirectory = MaterialDirectory; // this one is different! + } + + if (tools_info->GetEntry(DIRECTORIES_PAGE, KIN_DIR_ENTRY, &contents)) + { + AnimationDirectory = new char[strlen(contents) + 2]; + Register_Pointer(AnimationDirectory); + strcpy(AnimationDirectory, contents); + cp = strchr(contents, '\0'); + if (cp > contents && *--cp != '/') + { + strcat(AnimationDirectory, "/"); + } + } + else + { + AnimationDirectory = SourceDirectory; + } + + if (tools_info->GetEntry(DIRECTORIES_PAGE, PRD_DIR_ENTRY, &contents)) + { + ProductionDirectory = new char[strlen(contents) + 2]; + Register_Pointer(ProductionDirectory); + strcpy(ProductionDirectory, contents); + cp = strchr(contents, '\0'); + if (cp > contents && *--cp != '/') + { + strcat(ProductionDirectory, "/"); + } + } + else + { + ProductionDirectory = SourceDirectory; + } + + OutputDirectory = SourceDirectory; + + Unregister_Object(tools_info); + delete tools_info; + + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SetOutputDirectory(const char *directory) +{ + Check_Pointer(directory); + + OutputDirectory = directory; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + GetSourceDirectory() +{ + return SourceDirectory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + GetConfigDirectory() +{ + return ConfigDirectory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + GetMaterialDirectory() +{ + return MaterialDirectory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + GetTextureDirectory() +{ + return TextureDirectory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + GetAnimationDirectory() +{ + return AnimationDirectory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + GetProductionDirectory() +{ + return ProductionDirectory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + GetOutputDirectory() +{ + return OutputDirectory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ClearDirectories() +{ + //do not clear output directory + + if (ProductionDirectory && ProductionDirectory != SourceDirectory) + { + Unregister_Pointer(ProductionDirectory); + delete ProductionDirectory; + } + if (AnimationDirectory && AnimationDirectory != SourceDirectory) + { + Unregister_Pointer(AnimationDirectory); + delete AnimationDirectory; + } + if (TextureDirectory && TextureDirectory != MaterialDirectory) //different! + { + Unregister_Pointer(TextureDirectory); + delete TextureDirectory; + } + if (MaterialDirectory && MaterialDirectory != SourceDirectory) + { + Unregister_Pointer(MaterialDirectory); + delete MaterialDirectory; + } + if (ConfigDirectory && ConfigDirectory != SourceDirectory) + { + Unregister_Pointer(ConfigDirectory); + delete ConfigDirectory; + } + if (SourceDirectory) + { + Unregister_Pointer(SourceDirectory); + delete SourceDirectory; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + DirectoryPlusFilename( + const char *directory, + const char *filename, + const char *extension + ) +{ + //do not check directory here + Check_Pointer(filename); + //do not check extension here + + static char + buffer[512]; + int + length; + + if (!directory) { directory = "\0"; } + Check_Pointer(directory); + + length = strlen(directory); + if (extension) + { + Check_Pointer(extension); + length += strlen(StripExtension(StripDirectory(filename))); + length += *extension == '.'?0:1; + length += strlen(extension); + } + else + { + length += strlen(StripDirectory(filename)); + } + + if (length >= ELEMENTS(buffer)) + { + DEBUG_STREAM << + ": Program Error - buffer[] too small in DirectoryPlusFilename().\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + strcpy(buffer, directory); + if (extension) + { + strcat(buffer, StripExtension(StripDirectory(filename))); + if (*extension != '.') + { + strcat(buffer, "."); + } + strcat(buffer, extension); + } + else + { + strcat(buffer, StripDirectory(filename)); + } + return buffer; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + SourceFile( + const char *filename, + const char *extension + ) +{ + return DirectoryPlusFilename(SourceDirectory, filename, extension); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + ConfigFile( + const char *filename, + const char *extension + ) +{ + return DirectoryPlusFilename(ConfigDirectory, filename, extension); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + MaterialFile( + const char *filename, + const char *extension + ) +{ + return DirectoryPlusFilename(MaterialDirectory, filename, extension); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + TextureFile( + const char *filename, + const char *extension + ) +{ + return DirectoryPlusFilename(TextureDirectory, filename, extension); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + AnimationFile( + const char *filename, + const char *extension + ) +{ + return DirectoryPlusFilename(AnimationDirectory, filename, extension); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + OutputFile( + const char *filename, + const char *extension + ) +{ + return DirectoryPlusFilename(OutputDirectory, filename, extension); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +const char* + StripDirectory(const char *filename) +{ + Check_Pointer(filename); + + if (DirectoryIsSpecified(filename)) + { + const char + *p; + + //-------------------------------------- + // parse the filename from the filepath + //-------------------------------------- + p = strchr(filename, '\0'); + Verify( p ); + while (*p != '\\' && p != filename) + { + --p; + } + if (*p == '\\') + { + ++p; + } + filename = p; + } + return filename; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + StripExtension(const char *filename) +{ + Check_Pointer(filename); + + static char + buffer[512]; + char + *p; + + if (strlen(filename) >= sizeof(buffer)) + { + //DEBUG_STREAM << ProgName << + // ": Program Error - buffer[] too small in StripExtension()." << std::endl; + DEBUG_STREAM << + ": Program Error - buffer[] too small in StripExtension()." << std::endl << std::flush; + + PostQuitMessage(AbortExitCodeID); + } + strcpy(buffer, filename); + + //------------------------------------ + // remove the extension from filename + //------------------------------------ + p = strchr(buffer, '\0'); + Verify( p ); + while (*p != '.' && p != buffer) + { + --p; + } + if (*p == '.') + { + *p = '\0'; + } + + return buffer; +} + +//############################################################################# + +char* + Ind(int level) +{ + const int buf_len = 128; + static char buf[buf_len]; + + //--------------------------------------------------------- + // Return string of spaces used to indent an output stream + //--------------------------------------------------------- + buf[0] = '\0'; + if (level > 63) level = 63; // floor((buf_len - 1)/number of spaces per indent) + for (; level > 0; --level) + { + strcat(buf, " "); + } + return buf; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical GetLine(std::istream &stream, char *buffer, int size_of_buffer) +{ + static char temp_buffer[512]; + + //------------------------------------------------------------- + // read next line(s) from input stream automatically resolving + // lines with a continuation character '\' at the end + //------------------------------------------------------------- + if (stream.getline(buffer, size_of_buffer)) + { + char *p; + int i; + + while (True) + { + if ((i = strlen(buffer)) > (size_of_buffer - 2)) + { + //DEBUG_STREAM << ProgName << ": ERROR - Input line too long." << std::endl << std::flush; + + DEBUG_STREAM << ": ERROR - Input line too long." << std::endl << std::flush; + break; + } + + p = buffer + i; + while (p-- > buffer && isspace(*p)); // find last non-blank character + + if (p >= buffer && *p == '\\') + { + if (stream.getline(temp_buffer, sizeof(temp_buffer))) + { + *p = ' '; + ++p; + strncat(p, temp_buffer, size_of_buffer - (p - buffer)); + } + else + { + break; + } + } + else + { + break; + } + } + return True; + } + else + { + *buffer = '\0'; + return False; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if 0 +char* + stripname(char filename[]) +{ + + // Doesn't work + + char + file2[200]; + char + *filetosendback; + + int + wordlength, + count, + countbackward, + length; + + + length = strlen(filename); + + + count = 0; + countbackward = length-1; + + while (filename[countbackward-1] != '\\') + { + --countbackward; + } + + wordlength = length - countbackward; + + for (count = 0; count < wordlength; ++count) + { + file2[count] = filename[countbackward]; + ++countbackward; + } + + file2[count] = '\0'; + + filetosendback = strdup(file2); + + return filetosendback; +} +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Scalar + D2R(float degrees) +{ + return degrees*(3.14159259f/180.0f); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +char* + MakeWorkingDirectory( + const char *file + ) +{ + char *directory; + const char *p; + int size; + p = file; + + for (int i = (strlen(file) - 1 ); i >= 0; --i) + { + if ( (*p == '/') || (*p == '\\') ) + { + size = strlen(file) - i + 1; + + directory = new char[size]; + strncpy(directory, file, size); + + return directory; + } + ++p; + } + + // + // Else return local directory + // + #define BUFFER_SIZE (256) + char buffer[BUFFER_SIZE]; + getcwd(buffer, BUFFER_SIZE); + + #if 0 + directory = strdup(buffer); + strcat(directory, "\\"); // ECH 1/29/96 - This is an overwrite + #else + Str_Cat(buffer, "\\", BUFFER_SIZE); + size = strlen(buffer) + 1; + directory = new char[size]; + Str_Copy(directory, buffer, size); + #endif + + // + // This is "\\" for DOS + // + + return directory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Logical + DirectoryIsSpecified( + const char *file + ) +{ + return strchr(file,'/') || strchr(file,':') || strchr(file,'\\'); + +#if 0 + const char *p; + + p = file; + + for (int i = 0; i < strlen(file); ++i) + { + if ( (*p == '/') || (*p == '\\') ) + { + + return True; + + } + + ++p; + } + return False; +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +char* + MakePathedFilename( + const char *directory, + const char *name + ) +{ + char *filename; + + if (DirectoryIsSpecified(name)) + { + filename = new char[ strlen(name) + 1]; + strcpy(filename, name); + return filename; + } + + if (directory == NULL) + { + filename = new char[strlen(name) + 1]; + strcpy(filename, name); + } + else + { + filename = new char[strlen(directory) + strlen(name) + 1]; + + strcpy(filename, directory); + strcat(filename, name); + } + + return filename; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void OpenOutput(std::ofstream &stream, const char *directory, const char *filename) +{ + //do not check directory here + Check_Pointer(filename); + + char + *file_to_open; + + if (DirectoryIsSpecified(filename) || directory == NULL) + { + file_to_open = new char[strlen(filename) + 1]; + Register_Pointer(file_to_open); + strcpy(file_to_open, filename); + } + else + { + Check_Pointer(directory); + file_to_open = new char[strlen(directory) + strlen(filename) + 1]; + Register_Pointer(file_to_open); + strcpy(file_to_open, directory); + strcat(file_to_open, filename); + } + + stream.open(file_to_open); + Unregister_Pointer(file_to_open); + delete file_to_open; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void OpenInput(std::ifstream &stream, char *directory, const char *filename) +{ + char tempfile[100]; + + if (DirectoryIsSpecified(filename)) + { + strcpy(tempfile, filename); + } + else + { + if (directory != NULL) + { + strcpy(tempfile, directory); + strcat(tempfile, filename); + } + else + { + strcpy(tempfile, filename); + } + } + + stream.open(tempfile); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Logical + LabOnly( + NotationFile + *notation_file + ) +{ + + if (notation_file->PageExists("LAB_ONLY")) + { + std::cout << "WARNING: LAB_ONLY" << std::endl; + return True; + } + else + { + return False; + } + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void + AddLabOnly( + NotationFile + *notation_file + ) +{ + if (!notation_file->PageExists("LAB_ONLY")) + { + notation_file->AppendEntry("LAB_ONLY", NULL, NULL); + } + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Logical + DoesNotationFileExist( + NotationFile + *notation_file + ) +{ + Check(notation_file); + Check_Pointer(notation_file->GetFileName()); + std::ifstream notation_file_stream(notation_file->GetFileName()); + return (notation_file_stream) ? True : False; +} + +//============================================================================= diff --git a/MUNGA/FILEUTIL.h b/MUNGA/FILEUTIL.h new file mode 100644 index 0000000..5bf7cc4 --- /dev/null +++ b/MUNGA/FILEUTIL.h @@ -0,0 +1,76 @@ +#pragma once + +#include "style.h" +#include "scalar.h" + +class NotationFile; + +extern char *WorkingDirectory; + +extern const char *White_Space; + +inline char* NextToken() +{ + return strtok(NULL, White_Space); +} + +void SetSourceDirectory(const char *input_file); +void SetOutputDirectory(const char *directory); +const char* GetSourceDirectory(); +const char* GetConfigDirectory(); +const char* GetMaterialDirectory(); +const char* GetTextureDirectory(); +const char* GetAnimationDirectory(); +const char* GetProductionDirectory(); +const char* GetOutputDirectory(); +void ClearDirectories(); +const char* SourceFile(const char *filename, const char *extension = NULL); +const char* ConfigFile(const char *filename, const char *extension = NULL); +const char* MaterialFile(const char *filename, const char *extension = NULL); +const char* TextureFile(const char *filename, const char *extension = NULL); +const char* AnimationFile(const char *filename, const char *extension = NULL); +const char* OutputFile(const char *filename, const char *extension = NULL); +const char* StripDirectory(const char *filename); +const char* StripExtension(const char *filename); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +char* Ind(int level = 1); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Logical GetLine(std::istream &stream, char *buffer, int size_of_buffer); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if 0 + char* stripname(char filename[]); +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Scalar D2R(float degrees); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +char* MakeWorkingDirectory(const char *file); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Logical DirectoryIsSpecified(const char *file); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +char* MakePathedFilename(const char *directory, const char *name); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void OpenOutput(std::ofstream &stream, const char *directory, const char *filename); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void OpenInput(std::ifstream &stream, char *directory, const char *filename); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Logical DoesNotationFileExist(NotationFile *notation_file); \ No newline at end of file diff --git a/MUNGA/GAUGALRM.cpp b/MUNGA/GAUGALRM.cpp new file mode 100644 index 0000000..77e1542 --- /dev/null +++ b/MUNGA/GAUGALRM.cpp @@ -0,0 +1,406 @@ +#include "munga.h" +#pragma hdrstop + +#include "gaugalrm.h" +#include "app.h" +#include "notation.h" +#include "namelist.h" +#include "entity.h" +#include "subsystm.h" +#include + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) std::cout << n << std::flush +#else +# define Test_Tell(n) +#endif + +//####################################################################### +// GaugeAlarm +//####################################################################### +GaugeAlarm::GaugeAlarm( + Entity *the_entity, + Subsystem *the_subsystem, + Enumeration the_condition +) : + Node(RegisteredClass::GaugeAlarmClassID), + lampList(NULL) +{ + Check(the_entity); + Check(the_subsystem); + + Test_Tell( + "GaugeAlarm(" << the_entity << + ", " << the_subsystem << + ", " << the_condition << + ")\n" + ); + + entity = the_entity; + subsystem = the_subsystem; + conditionIndex = the_condition; + Check_Fpu(); +} + +GaugeAlarm::~GaugeAlarm() +{ + Test_Tell("~GaugeAlarm()"); + Check(this); + + ChainIteratorOf + i(lampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + Test_Tell("lamp "); + lamp_pointer->SetAlertState(False); + } + Test_Tell("\n"); + Check_Fpu(); +} + +Logical + GaugeAlarm::TestInstance() const +{ + return Node::TestInstance(); +} + + +//####################################################################### +// GaugeAlarmManager +//####################################################################### +Logical + GaugeAlarmManager::CreateGaugeAlarmStreamItem( + MemoryStream */*mem_stream*/, + const char */*alarm_name*/, + const char */*alarm_data*/ + ) +{ + Fail("GaugeAlarmManager::CreateGaugeAlarmStreamItem not overridden!"); + return False; +} + +void + GaugeAlarmManager::ReadGaugeAlarmStreamItem( + GaugeAlarm */*alarm*/, + Entity */*the_entity*/, + Subsystem */*the_subsystem*/, + Enumeration /*the_condition*/, + MemoryStream */*mem_stream*/ + ) +{ + Fail("GaugeAlarmManager::ReadGaugeAlarmStreamItem not overridden!"); +} + +ResourceDescription::ResourceID + GaugeAlarmManager::CreateModelGaugeAlarmStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories */*directories*/ + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + int + i; + ResourceDescription::ResourceID + res_id = ResourceDescription::NullResourceID; + + //------------------------------------------------------------- + // Make sure the notation file is in relaxed operation mode + //------------------------------------------------------------- + Enumeration + old_notation_file_mode = model_file->GetModes(); + + model_file->SetMode( + NotationFile::RelaxedOperationModes | NotationFile::SkipBlanksListMode + ); + //------------------------------------------------------------- + // Build a list of all the alarm entries for the gauge renderer + //------------------------------------------------------------- + NameList + *alarm_list = model_file->MakeEntryList("gaugeAlarm"); + + if (alarm_list != NULL) + { + Test_Tell( + "Processing model gauge alarm data for '" << model_name << "':" + ); + Register_Object(alarm_list); + //------------------------------------------------------------- + // Get the number of alarms + //------------------------------------------------------------- + Logical + built_ok = True; + int + alarm_count = alarm_list->EntryCount(); + + Test_Tell(alarm_count << " entries.\n"); + Verify(alarm_count > 0); + //------------------------------------------------------------- + // Create a dynamic memory stream + //------------------------------------------------------------- + DynamicMemoryStream + *alarm_stream = new DynamicMemoryStream(); + Register_Object(alarm_stream); + //------------------------------------------------------------- + // Write the number of alarms to the stream + //------------------------------------------------------------- + MemoryStream_Write(alarm_stream, &alarm_count); + //------------------------------------------------------------- + // Write the alarms to the stream + //------------------------------------------------------------- + NameList::Entry + *alarm_entry = alarm_list->GetFirstEntry(); + + for(i=0; iGetName(), + alarm_entry->GetChar() + ) + == False + ) + { + DEBUG_STREAM << + "Model file '" << model_name << + "' has undefined alarm type '" << alarm_entry->GetName() << + "' - resource not built.\n"; + built_ok = False; + break; + } + alarm_entry = alarm_entry->GetNextEntry(); + } + //------------------------------------------------------------- + // Create the resource description, assign an ID + //------------------------------------------------------------- + if (built_ok) + { + Test_Tell("Creating resource description for '"<AddResourceMemoryStream( + model_name, + ResourceDescription::GaugeAlarmStreamResourceType, + 1, // priority + ResourceDescription::Preload, + alarm_stream + ); + + Check(res_desc_stream); + res_id = res_desc_stream->resourceID; + } + + Unregister_Object(alarm_stream); + delete alarm_stream; + Test_Tell("Closed gauge alarm stream\n" << std::flush); + Test_Tell("res_id = " << res_id << "\n"); + } + //------------------------------------------------------------- + // Restore the notation file's previous operation mode + //------------------------------------------------------------- + model_file->PutModes(old_notation_file_mode); + //------------------------------------------------------------- + // Return the new ResourceID + //------------------------------------------------------------- + Check_Fpu(); + return res_id; +} + +GaugeAlarmManager::GaugeAlarmManager() : + gaugeAlarmList(NULL) +{ + Check_Fpu(); +} + +GaugeAlarmManager::~GaugeAlarmManager() +{ + Check(this); + Check_Fpu(); +} + +Logical + GaugeAlarmManager::TestInstance() const +{ + return True; +} + +void + GaugeAlarmManager::RemoveAllAlarms() +{ + Check(this); + + //------------------------------------------- + // Delete all GaugeAlarms + //------------------------------------------- + ChainIteratorOf + i(gaugeAlarmList); + GaugeAlarm + *alarm_pointer; + + while ((alarm_pointer=i.ReadAndNext()) != NULL) + { + Check(alarm_pointer); + Unregister_Object(alarm_pointer); + delete alarm_pointer; + } + Check_Fpu(); +} + +void + GaugeAlarmManager::Activate( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID new_resource_id + ) +{ + //Test_Tell( + // "GaugeAlarmManager::Activate(" << entity << + // ", " << subsystem << + // ", " << condition << + // ", " << new_resource_id << + // ")\n"; + //); + Check(this); + + Check(application); + Check(application->GetResourceFile()); + //------------------------------------------- + // Attempt to find the specified resource + //------------------------------------------- + ResourceDescription + *stream_resource_description = + application->GetResourceFile()->SearchList( + new_resource_id, + ResourceDescription::GaugeAlarmStreamResourceType + ); + + if (stream_resource_description == NULL) + { + Test_Tell( + "GaugeAlarmManager::Activate: resource ID '" << new_resource_id << + "' does not exist\n" + ); + } + else + { + //------------------------------------------- + // Lock the stream + //------------------------------------------- + stream_resource_description->Lock(); + //------------------------------------------- + // Found it, open a DynamicMemoryStream + //------------------------------------------- + DynamicMemoryStream + *dynamic_memory_stream = + new DynamicMemoryStream( + stream_resource_description->resourceAddress, + stream_resource_description->resourceSize + ); + if (dynamic_memory_stream == NULL) + { + Test_Tell("GaugeAlarmManager::Activate: couldn't open stream\n"); + } + else + { + Register_Object(dynamic_memory_stream); + //------------------------------------------- + // Create the object, add to alarm list + //------------------------------------------- + GaugeAlarm + *alarm = new GaugeAlarm( + entity, + subsystem, + condition + ); + Register_Object(alarm); + gaugeAlarmList.Add(alarm); + //------------------------------------------- + // Read the alarm items from the stream + //------------------------------------------- + int + alarm_count; + MemoryStream_Read(dynamic_memory_stream, &alarm_count); + Verify(alarm_count > 0); + + for(; alarm_count>0; --alarm_count) + { + ReadGaugeAlarmStreamItem( + alarm, + entity, + subsystem, + condition, + dynamic_memory_stream + ); + } + //------------------------------------------- + // Destroy the stream + //------------------------------------------- + Unregister_Object(dynamic_memory_stream); + delete dynamic_memory_stream; + } + //------------------------------------------- + // Unlock the stream + //------------------------------------------- + stream_resource_description->Unlock(); + } + Check_Fpu(); +} + +void + GaugeAlarmManager::Deactivate( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ) +{ + //Test_Tell( + // "GaugeAlarmManager::Deactivate(" << entity << + // ", " << subsystem << + // ", " << condition << + // ")\n"; + //); + Check(this); + //------------------------------------------- + // Find matching GaugeAlarm + //------------------------------------------- + ChainIteratorOf + i(gaugeAlarmList); + GaugeAlarm + *alarm_pointer; + + while ((alarm_pointer=i.ReadAndNext()) != NULL) + { + Check(alarm_pointer); + Test_Tell("pointer=" << alarm_pointer); + if (alarm_pointer->entity == entity) + { + if (alarm_pointer->subsystem == subsystem) + { + if (alarm_pointer->conditionIndex == condition) + { + Test_Tell("Found:"); + Unregister_Object(alarm_pointer); + delete alarm_pointer; + break; + } + } + } + Test_Tell("\n"); + } + Check_Fpu(); +} diff --git a/MUNGA/GAUGALRM.h b/MUNGA/GAUGALRM.h new file mode 100644 index 0000000..50a289b --- /dev/null +++ b/MUNGA/GAUGALRM.h @@ -0,0 +1,58 @@ +#pragma once + +#include "resource.h" +#include "chain.h" +#include "lamp.h" + +class Lamp; +//####################################################################### +// GaugeAlarm +//####################################################################### +class GaugeAlarm : public Node +{ + friend class GaugeAlarmManager; + +protected: + GaugeAlarm(Entity *entity, Subsystem *subsystem, Enumeration condition); + ~GaugeAlarm(); + +public: + Logical TestInstance() const; +protected: + Entity *entity; + Subsystem *subsystem; + int conditionIndex; +public: + ChainOf lampList; // descendants of GaugeAlarmManager need to see this +}; + +//####################################################################### +// GaugeAlarmManager +//####################################################################### +class GaugeAlarmManager SIGNATURED +{ + friend class GaugeAlarm; + friend class GaugeRenderer; +protected: + GaugeAlarmManager(); +public: + virtual ~GaugeAlarmManager(); + //-------------------------------------------------------------------- + // Resource methods + //-------------------------------------------------------------------- +public: + ResourceDescription::ResourceID CreateModelGaugeAlarmStreamResource(ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories * /*directories*/); + + virtual Logical CreateGaugeAlarmStreamItem(MemoryStream *mem_stream, const char *alarm_name, const char *alarm_data); + virtual void ReadGaugeAlarmStreamItem(GaugeAlarm *alarm, Entity *the_entity, Subsystem *the_subsystem, Enumeration the_condition, MemoryStream *mem_stream); + + void RemoveAllAlarms(); + void Activate(Entity *entity, Subsystem *subsystem, Enumeration condition, ResourceDescription::ResourceID resource_ID); + void Deactivate(Entity *entity, Subsystem *subsystem, Enumeration condition); + +public: + Logical TestInstance() const; + +protected: + ChainOf gaugeAlarmList; +}; \ No newline at end of file diff --git a/MUNGA/GAUGE.cpp b/MUNGA/GAUGE.cpp new file mode 100644 index 0000000..6c71a20 --- /dev/null +++ b/MUNGA/GAUGE.cpp @@ -0,0 +1,779 @@ +#include "munga.h" +#pragma hdrstop + +#include "gauge.h" +#include "gaugrend.h" + +extern void + indent(int level); // in graph2d.cc + +//######################################################################### +//############################# GaugeBase ################################# +//######################################################################### +GaugeBase::GaugeBase( + ModeMask mode_mask, + GaugeRenderer *new_renderer, + unsigned int owner_ID, + const char *identification_string +) : + Node(Gauge::GaugeClassID), + alreadyActivatedFlag(False) +{ + Check_Pointer(this); + + modeMask = mode_mask; + ownerID = owner_ID; + renderer = new_renderer; + identificationString = identification_string; + + stayInactive = True; // used by GaugeRenderer during activation + //--------------------------------------------------- + // If renderer exists, add to object list + // (Not having a renderer allows for independent testing) + //--------------------------------------------------- + if (renderer != NULL) + { + Check(renderer); + renderer->Add(this); + } + Check_Fpu(); +} + +GaugeBase::~GaugeBase() +{ + Check(this); + Check_Fpu(); +} + +Logical + GaugeBase::TestInstance() const +{ + return True; +} + +void + GaugeBase::BecameActive() +{ + Check(this); + //------------------------------------------------------ + // Default method immediately inactivates the gaugeBase + //------------------------------------------------------ + DEBUG_STREAM << + "BecameActive() has not been defined for '" << identificationString << + "'. About to call Inactivate()\n"; + Inactivate(); + Check_Fpu(); +} + +void + GaugeBase::BecameInactive() +{ + Check(this); + Check_Fpu(); +} + +void + GaugeBase::Inactivate() +{ + Check(this); + if (renderer != NULL) + { + Check(renderer); + renderer->Inactivate(this); + } + Check_Fpu(); +} + +Logical + GaugeBase::Update(GaugeRate /*rate_mask*/) +{ + Check(this); + //------------------------------------------------------ + // Default method immediately inactivates the gaugeBase + //------------------------------------------------------ + DEBUG_STREAM << + "Update() has not been defined for '" << identificationString << + "'. About to call Inactivate()\n"; + Inactivate(); + Check_Fpu(); + return False; +} + +void + GaugeBase::UpdateProfile(Scalar /*frame_percentage*/) +{ + Check(this); + Check_Fpu(); +} + +void + GaugeBase::ReportProfile() +{ + Check(this); + Check_Fpu(); +} + +void + GaugeBase::LinkToEntity(Entity */*entity*/) +{ + Check(this); + Check_Fpu(); +} + +void + GaugeBase::NotifyOfNewInterestingEntity(Entity */*entity*/) +{ + Check(this); + Check_Fpu(); +} + +void + GaugeBase::NotifyOfBecomingUninterestingEntity(Entity */*entity*/) +{ + Check(this); + Check_Fpu(); +} + + +int + GaugeBase::DiscernTier() +{ + Check(this); + Check_Fpu(); + return 0; +} + + +//######################################################################### +//########################## GaugeBackground ############################## +//######################################################################### +GaugeBackground::GaugeBackground( + ModeMask mode_mask, + GaugeRenderer *new_renderer, + unsigned int owner_ID, + const char *identification_string +) : + GaugeBase(mode_mask, new_renderer, owner_ID, identification_string) +{ + Check_Pointer(this); + Check_Fpu(); +} + +//######################################################################### +//######################## GraphicGaugeBackground ######################### +//######################################################################### +GraphicGaugeBackground::GraphicGaugeBackground( + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + const char *identification_string +) : + localView( + renderer == NULL ? + NULL : + renderer->GetGraphicsPort(graphics_port_number) + ), + GaugeBackground(mode_mask, renderer, owner_ID, identification_string) +{ + Check_Fpu(); +} + +//######################################################################### +//########################## GaugeConnection ############################## +//######################################################################### + +GaugeConnection::GaugeConnection(int parameter_id) +{ + Check_Pointer(this); + parameterID = parameter_id; + Check_Fpu(); +} + +GaugeConnection::~GaugeConnection() +{ + Check_Fpu(); +} + +Logical + GaugeConnection::TestInstance() const +{ + Check_Pointer(this); + + return True; +} + +void GaugeConnection::Update() +{ + Fail("GaugeConnection::Update should not be called!\n"); +} + +void + GaugeConnection::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "GaugeConnection:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + std::cout << temp << "parameterID=" << parameterID << "\n" << std::flush; + Check_Fpu(); +} + +//######################################################################### +//################################# Gauge ################################# +//######################################################################### + +//---------------------------------------------------------------------------- +// GaugeRate masks are used to spread out workload in a priority-based +// manner. Each GaugeRate refers to the branch of a binary tree as shown: +// +// A = every frame +// /--------------^--------------\ : +// FIRST TIER: B C = 1/2 +// /------^-------\ /------^-------\ : +// 2ND: D E F G = 1/4 +// /--^---\ /--^---\ /--^---\ /--^---\ : +// H I J K L M N O = 1/8 +// / \ / \ / \ / \ / \ / \ / \ / \ : +// P Q R S T U V W X Y Z Z0 Z1 Z2 Z3 Z4 = 1/16 +// +// Each 'tier' down indicates an update rate half that of the one above it. +// +// Note that rates Z0..Z4 cannot be specified through the gauge renderer's +// interpreter. They are available to automatically generated gauges, though. +//---------------------------------------------------------------------------- + +GaugeRate + Gauge::rateTable[31] = + { + gaugeRate_A, // every frame + + gaugeRate_B, // every other frame + gaugeRate_C, + + gaugeRate_D, // every 4th frame + gaugeRate_E, + gaugeRate_F, + gaugeRate_G, + + gaugeRate_H, // every 8th frame + gaugeRate_I, + gaugeRate_J, + gaugeRate_K, + gaugeRate_L, + gaugeRate_M, + gaugeRate_N, + gaugeRate_O, + + gaugeRate_P, // every 16th frame + gaugeRate_Q, + gaugeRate_R, + gaugeRate_S, + gaugeRate_T, + gaugeRate_U, + gaugeRate_V, + gaugeRate_W, + gaugeRate_X, + gaugeRate_Y, + gaugeRate_Z, + gaugeRate_Z0, + gaugeRate_Z1, + gaugeRate_Z2, + gaugeRate_Z3, + gaugeRate_Z4 + }; + +//------------------------------------------------------------------- +// Gauge::NextXXXTierGaugeRate() +// - These functions attempt to spead out workload by returning the +// next available 'GaugeRate' in a given 'tier'. +// +// The higher level tiers bump the lower level tier indices to +// attempt to avoid placing too much load on the same higher-order +// branch of the tree. +//------------------------------------------------------------------- + +static int + first_index = -1, + second_index = -1, + third_index = -1, + fourth_index = -1; + +GaugeRate + Gauge::NextFirstTierGaugeRate() +{ + //---------------------------------------- + // Generate first index + //---------------------------------------- + first_index = (++first_index) & 1; + //---------------------------------------- + // Bump other indices to avoid same branch + //---------------------------------------- + second_index += 2; + third_index += 4; + fourth_index += 8; + //---------------------------------------- + // Return rate mask + //---------------------------------------- + return rateTable[first_index + 1]; +} + +GaugeRate + Gauge::NextSecondTierGaugeRate() +{ + //---------------------------------------- + // Generate first index + //---------------------------------------- + second_index = (++second_index) & 3; + //---------------------------------------- + // Bump other indices to avoid same branch + //---------------------------------------- + third_index += 2; + fourth_index += 4; + //---------------------------------------- + // Return rate mask + //---------------------------------------- + return rateTable[second_index + 3]; +} + +GaugeRate + Gauge::NextThirdTierGaugeRate() +{ + //---------------------------------------- + // Generate first index + //---------------------------------------- + third_index = (++third_index) & 7; + //---------------------------------------- + // Bump other indices to avoid same branch + //---------------------------------------- + fourth_index += 2; + //---------------------------------------- + // Return rate mask + //---------------------------------------- + return rateTable[third_index + 7]; +} + +GaugeRate + Gauge::NextFourthTierGaugeRate() +{ + //---------------------------------------- + // Generate first index + //---------------------------------------- + fourth_index = (++fourth_index) & 15; + //---------------------------------------- + // Return rate mask + //---------------------------------------- + return rateTable[fourth_index + 15]; +} + +GaugeRate + Gauge::ConvertIndexToRate(int index) +{ + Verify(index >= 0); + Verify(index < 32); + + return rateTable[index]; +} + +Gauge::Gauge( + GaugeRate new_rate, + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + const char *identification_string +): + GaugeBase(mode_mask, renderer, owner_ID, identification_string), + instanceList(this) +{ + Check_Pointer(this); + + rate = new_rate; + oldRate = new_rate; + + stayInactive = False; + + profileFramePercentage = (Scalar) 0; + profileMaxFramePercentage = (Scalar) 0; + profileCycles = 0; + + Check_Fpu(); +} + +Gauge::~Gauge() +{ + Check(this); + RemoveAllConnections(); + Check_Fpu(); +} + +Logical + Gauge::TestInstance() const +{ + Check(&instanceList); +# if 0 + //-------------------------------------------------------------------- + // Check all owned GaugeConnections + //-------------------------------------------------------------------- + ChainIteratorOf + i(instanceList); + + GaugeConnection + *the_connection; + + while ((the_connection=i.ReadAndNext()) != NULL) + { + Check(the_connection); + } +# endif + //-------------------------------------------------------------------- + // Check the base object + //-------------------------------------------------------------------- + return GaugeBase::TestInstance(); +} + +void + Gauge::ShowInstance(char *indent) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + GaugeConnection + *the_connection; + + std::cout << indent << "Gauge:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "modeMask =" << modeMask << "\n"; + std::cout << temp << "renderer =" << renderer << "\n"; + std::cout << temp << "ownerID =" << ownerID << "\n"; + std::cout << temp << "InstanceList -\n" << std::flush; + + Str_Cat(temp,"...", 80); + + while ((the_connection=i.ReadAndNext()) != NULL) + { + Check(the_connection); + the_connection->ShowInstance(temp); + } + Check_Fpu(); +} + +void + Gauge::AddConnection(GaugeConnection *connection) +{ + Check(this); + Check(connection); + instanceList.Add(connection); + Check_Fpu(); +} + +void + Gauge::RemoveConnection(int parameter_ID) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + GaugeConnection + *gauge_connection; + + while ((gauge_connection=i.ReadAndNext()) != NULL) + { + Check(gauge_connection); + if (gauge_connection->parameterID == parameter_ID) + { + Unregister_Object(gauge_connection); + delete gauge_connection; + } + } + Check_Fpu(); +} + +void + Gauge::RemoveAllConnections() +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + GaugeConnection + *gauge_connection; + + while ((gauge_connection=i.ReadAndNext()) != NULL) + { + Check(gauge_connection); + Unregister_Object(gauge_connection); + delete gauge_connection; + } + Check_Fpu(); +} + +void + Gauge::Disable(Logical disable_state) +{ + Check(this); + if (disable_state) + { + rate = 0; + BecameInactive(); + } + else + { + rate = oldRate; + BecameActive(); + } + Check_Fpu(); +} + +Logical + Gauge::Update(GaugeRate rate_mask) +{ + Check(this); + + Logical + actually_ran = False; + //----------------------------------------- + // Update only if rate mask allows it + //----------------------------------------- + if (rate & rate_mask) + { + //----------------------------------------- + // Update parameters + //----------------------------------------- + ChainIteratorOf + i(instanceList); + + GaugeConnection + *gauge_connection; + + while ((gauge_connection=i.ReadAndNext()) != NULL) + { + Check(gauge_connection); + gauge_connection->Update(); + } + //----------------------------------------- + // Execute gauge code + //----------------------------------------- + Execute(); + actually_ran = True; + } + Check_Fpu(); + return actually_ran; +} + +void + Gauge::Execute() +{ + Fail("Gauge::Execute not overridden"); +} + +struct TierLookup +{ + GaugeRate rate; + int tier; +}; + +int + Gauge::DiscernTier() +{ + Check(this); + + TierLookup + *tier_pointer; + static TierLookup + tier_lookup[] = + { + {gaugeRate_A, 0 }, + + {gaugeRate_B, 1 }, + {gaugeRate_C, 1 }, + + {gaugeRate_D, 2 }, + {gaugeRate_E, 2 }, + {gaugeRate_F, 2 }, + {gaugeRate_G, 2 }, + + {gaugeRate_H, 3 }, + {gaugeRate_I, 3 }, + {gaugeRate_J, 3 }, + {gaugeRate_K, 3 }, + {gaugeRate_L, 3 }, + {gaugeRate_M, 3 }, + {gaugeRate_N, 3 }, + {gaugeRate_O, 3 }, + + {gaugeRate_P, 4 }, + {gaugeRate_Q, 4 }, + {gaugeRate_R, 4 }, + {gaugeRate_S, 4 }, + {gaugeRate_T, 4 }, + {gaugeRate_U, 4 }, + {gaugeRate_V, 4 }, + {gaugeRate_W, 4 }, + {gaugeRate_X, 4 }, + {gaugeRate_Y, 4 }, + {gaugeRate_Z, 4 }, + {gaugeRate_Z0,4 }, + {gaugeRate_Z1,4 }, + {gaugeRate_Z2,4 }, + {gaugeRate_Z3,4 }, + {gaugeRate_Z4,4 }, + {0,0} + }; + + for (tier_pointer=tier_lookup; tier_pointer->rate != 0; ++tier_pointer) + { + if (tier_pointer->rate == rate) + { + Check_Fpu(); + return tier_pointer->tier; + } + } + + Check_Fpu(); + return 0; +} + +void + Gauge::UpdateProfile(Scalar frame_percentage) +{ + Check(this); + + //--------------------------------------------- + // Keep worst case + //--------------------------------------------- + if (profileMaxFramePercentage < frame_percentage) + { + profileMaxFramePercentage = frame_percentage; + } + //--------------------------------------------- + // Keep running total + //--------------------------------------------- + profileFramePercentage += frame_percentage; + //--------------------------------------------- + // Prevent overflow + //--------------------------------------------- + if (++profileCycles > 16384) + { + profileFramePercentage /= (Scalar) 2; + profileCycles >>= 1; + } + + Check_Fpu(); +} + +void + Gauge::ReportProfile() +{ + Check(this); + + int + i; + + DEBUG_STREAM << identificationString << std::flush; + for(i=strlen(identificationString); i<32; ++i) + { + DEBUG_STREAM << "." << std::flush; + } + + if (profileCycles > 0) + { + Scalar + average = profileFramePercentage / (Scalar)profileCycles; + + char + buffer[80]; + + sprintf(buffer, "%6d %6.4f %6.4f\n", + profileCycles, + average, + profileMaxFramePercentage + ); + DEBUG_STREAM << buffer << std::flush; + } + else + { + DEBUG_STREAM << "never ran.\n" << std::flush; + } + + //---------------------------------------- + // Reset maximum percentage + //---------------------------------------- + profileMaxFramePercentage = (Scalar) 0; + + Check_Fpu(); +} + +//######################################################################### +//############################# GraphicGauge ############################# +//######################################################################### + +GraphicGauge::GraphicGauge( + GaugeRate new_rate, + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + const char *identification_string + ) : + Gauge(new_rate, mode_mask, renderer, owner_ID, identification_string), + localView( + renderer == NULL ? + NULL : + renderer->GetGraphicsPort(graphics_port_number) + ) +{ + Check_Fpu(); +} + + +GraphicGauge::~GraphicGauge() +{ + Check(this); + Check_Fpu(); +} + +Logical + GraphicGauge::TestInstance() const +{ + Check(&localView); + Check_Fpu(); + return Gauge::TestInstance(); +} + +void + GraphicGauge::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "GraphicGauge:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + localView.ShowInstance(temp); + Gauge::ShowInstance(temp); + Check_Fpu(); +} + + +#if defined(TEST_CLASS) +# include "gauge.tcp" +#endif diff --git a/MUNGA/GAUGE.h b/MUNGA/GAUGE.h new file mode 100644 index 0000000..49ae18f --- /dev/null +++ b/MUNGA/GAUGE.h @@ -0,0 +1,403 @@ +#pragma once + +#include "style.h" + +typedef unsigned int GaugeRate; +class GaugeRenderer; +class GaugeBase; +class GraphicGaugeBackground; +class Gauge; +class GraphicGauge; +class GaugeConnection; +class Entity; +class GaugeAlarmManager; + +#include "mode.h" +#include "slot.h" +#include "chain.h" +#include "receiver.h" +#include "graph2d.h" + +//######################################################################### +//############################# GaugeBase ################################# +//######################################################################### +class GaugeBase : + public Node +{ + friend class GaugeRenderer; + //---------------------------------------------------------------------- + // Constructor + //---------------------------------------------------------------------- +protected: + GaugeBase( + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + const char *identification_string + ); + //---------------------------------------------------------------------- + // Destructor + //---------------------------------------------------------------------- +public: + virtual ~GaugeBase(); + //---------------------------------------------------------------------- + // Test methods + //---------------------------------------------------------------------- + Logical + TestInstance() const; + //---------------------------------------------------------------------- + // Update methods + //---------------------------------------------------------------------- + virtual void + BecameActive(), + BecameInactive(), + Inactivate(), + UpdateProfile(Scalar frame_percentage), + ReportProfile(); + + virtual Logical + Update(GaugeRate rate_mask); + + virtual void + LinkToEntity(Entity *entity), + NotifyOfNewInterestingEntity(Entity *entity), + NotifyOfBecomingUninterestingEntity(Entity *entity); + + virtual int + DiscernTier(); + + //---------------------------------------------------------------------- + // Public data + //---------------------------------------------------------------------- +public: + Logical + alreadyActivatedFlag; // This is really a visibility flag. + // Active/inactive lists are more like + // "should get redrawn" lists + + + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- +protected: + Logical + stayInactive; // used by GaugeRenderer during activation + unsigned int + ownerID; + ModeMask + modeMask; + GaugeRenderer + *renderer; + const char + *identificationString; +}; + +//######################################################################### +//########################### GaugeBackground ############################# +//######################################################################### +class GaugeBackground : + public GaugeBase +{ +protected: +GaugeBackground( + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + const char *identification_string = "GraphicGaugeBackground" + ); +}; + +//######################################################################### +//######################## GraphicGaugeBackground ######################### +//######################################################################### +class GraphicGaugeBackground : + public GaugeBackground +{ +protected: + GraphicGaugeBackground( + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + const char *identification_string = "GraphicGaugeBackground" + ); + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- + GraphicsView + localView; +}; + +//######################################################################### +//########################## GaugeConnection ############################## +//######################################################################### + +// The GaugeConnection object maintains one instance of a mapping from +// a value in some location to a parameter for a gauge. + +class GaugeConnection : + public Plug +{ + friend class Gauge; + +public: + GaugeConnection(int parameter_ID); + ~GaugeConnection(); + + Logical + TestInstance() const; + +protected: + virtual void ShowInstance(char *indent); + virtual void Update(); + + int parameterID; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ GaugeConnectionDirectOf ~~~~~~~~~~~~~~~~~~ + +template class GaugeConnectionDirectOf: + public GaugeConnection +{ + friend class Gauge; + +public: + GaugeConnectionDirectOf( + int parameter_ID, + T* data_destination, + T* data_source + ); + ~GaugeConnectionDirectOf(); + Logical + TestInstance() const; + +protected: + void + Update(); + + void + ShowInstance(char *indent); + + T *dataSource; + T *dataDestination; +}; + +template GaugeConnectionDirectOf::GaugeConnectionDirectOf( + int parameter_ID, + T* data_destination, + T* data_source +): + GaugeConnection(parameter_ID), + dataSource(data_source), + dataDestination(data_destination) +{ + Check_Pointer(this); + Check_Pointer(data_destination); + Check_Pointer(data_source); + + *dataDestination = *dataSource; + Verify(*dataDestination == *dataSource); + Check(this); +} + +template GaugeConnectionDirectOf::~GaugeConnectionDirectOf() + {} + +template void + GaugeConnectionDirectOf::Update() +{ + Check(this); + Check_Pointer(dataSource); + Check_Pointer(dataDestination); + *dataDestination = *dataSource; + Verify(*dataDestination == *dataSource); + Check(this); +} + +template void + GaugeConnectionDirectOf::ShowInstance(char *indent) +{ + Check(this); + Check_Pointer(dataSource); + Check_Pointer(dataDestination); + std::cout << indent << "GaugeConnectionDirectOf:\n"; + + std::cout << indent << "...dataSource at" << + dataSource << "=" << *dataSource << "\n"; + std::cout << indent << "...dataDestination at" << + dataSource << "\n" << std::flush; + GaugeConnection::ShowInstance(indent); +} + +template Logical + GaugeConnectionDirectOf::TestInstance() const +{ + Check_Pointer(this); + Check_Pointer(dataSource); + Check_Pointer(dataDestination); + return Plug::TestInstance(); +} + + +//######################################################################### +//################################# Gauge ################################# +//######################################################################### + +class Gauge : + public GaugeBase +{ +public: + enum + { + gaugeRate_A=0xFFFF, // every frame + + gaugeRate_B=0xAAAA, // every other frame + gaugeRate_C=0x5555, + + gaugeRate_D=0x8888, // every 4th frame + gaugeRate_E=0x4444, + gaugeRate_F=0x2222, + gaugeRate_G=0x1111, + + gaugeRate_H=0x8080, // every 8th frame + gaugeRate_I=0x4040, + gaugeRate_J=0x2020, + gaugeRate_K=0x1010, + gaugeRate_L=0x0808, + gaugeRate_M=0x0404, + gaugeRate_N=0x0202, + gaugeRate_O=0x0101, + + gaugeRate_P=0x8000, // every 16th frame + gaugeRate_Q=0x4000, + gaugeRate_R=0x2000, + gaugeRate_S=0x1000, + gaugeRate_T=0x0800, + gaugeRate_U=0x0400, + gaugeRate_V=0x0200, + gaugeRate_W=0x0100, + gaugeRate_X=0x0080, + gaugeRate_Y=0x0040, + gaugeRate_Z=0x0020, + gaugeRate_Z0=0x0010, + gaugeRate_Z1=0x0008, + gaugeRate_Z2=0x0004, + gaugeRate_Z3=0x0002, + gaugeRate_Z4=0x0001 + }; + + //---------------------------------------------------------------------- + // Public static methods and data + //---------------------------------------------------------------------- + static GaugeRate + rateTable[31]; + + static GaugeRate + NextFirstTierGaugeRate(), // returns either B,C + NextSecondTierGaugeRate(), // returns DEFG + NextThirdTierGaugeRate(), // returns HIJKLMNO + NextFourthTierGaugeRate(); // returns PQRSTUVWXYZ + + static GaugeRate + ConvertIndexToRate(int index); + + //---------------------------------------------------------------------- + // Constructor method + //---------------------------------------------------------------------- + Gauge( + GaugeRate new_rate, + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + const char *identification_string = "Gauge" + ); + //---------------------------------------------------------------------- + // Destructor method + //---------------------------------------------------------------------- + ~Gauge(); + //---------------------------------------------------------------------- + // Test methods + //---------------------------------------------------------------------- + Logical + TestInstance() const; + void + ShowInstance(char *indent); + int + DiscernTier(); + static Logical + TestClass(); + //---------------------------------------------------------------------- + // Connection methods + //---------------------------------------------------------------------- + virtual void + AddConnection(GaugeConnection *connection), + RemoveConnection(int parameter_ID), + RemoveAllConnections(); + + //---------------------------------------------------------------------- + // Update methods + //---------------------------------------------------------------------- + void + Disable(Logical disable_state); + Logical + Update(GaugeRate rate_mask); +protected: + virtual void + Execute(); // Execute internal processes to display the gauge + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- +protected: + GaugeRate + rate, + oldRate; + ChainOf + instanceList; + //--------------------------------------- + // Profiling data + //--------------------------------------- + void + UpdateProfile(Scalar frame_percentage), + ReportProfile(); + + Scalar + profileFramePercentage, + profileMaxFramePercentage; + int + profileCycles; +}; + +//######################################################################### +//############################# GraphicGauge ############################## +//######################################################################### + +class GraphicGauge : + public Gauge +{ +public: + // + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- + // + GraphicGauge( + GaugeRate new_rate, + ModeMask mode_mask, + GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + const char *identification_string = "GraphicGauge" + ); + ~GraphicGauge(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + //---------------------------------------------------------------------- + // Public data + //---------------------------------------------------------------------- + GraphicsView + localView; +}; diff --git a/MUNGA/GAUGMAP.cpp b/MUNGA/GAUGMAP.cpp new file mode 100644 index 0000000..16fbc3d --- /dev/null +++ b/MUNGA/GAUGMAP.cpp @@ -0,0 +1,736 @@ +#include "munga.h" +#pragma hdrstop + +#include "gaugmap.h" +#include "point3d.h" +#include "entity.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) std::cout << n +#else +# define Test_Tell(n) +#endif + +// 'FULL_EXTENT' is a value representing the total extent +// of the world in meters. +#define FULL_EXTENT 32767.0 +#define HALF_EXTENT (FULL_EXTENT/2.0) + +// 'LARGEST_RADIUS' defines a radius encompassing the largest existing entity +#define LARGEST_RADIUS 500.0 // HACK - this is a guess + + +//############################################################################# +// approximateDistance +// ...accurate to about 13% +// Graphics Gems, p.432, "A Fast Approximation To 3D Euclidean Distance" +//############################################################################# +Scalar + approximateDistance(Point3D *point1, Point3D *point2) +{ + Check_Pointer(point1); + Check_Pointer(point2); + + Scalar + max, mid, min, temp; + //----------------------------------------------- + // Get the three components in arbitrary order + //----------------------------------------------- + max = abs(point2->x - point1->x); + mid = abs(point2->y - point1->y); + min = abs(point2->z - point1->z); + //----------------------------------------------- + // Sort only the largest value to the top. + // We don't need to completely sort the values, + // as we weight the middle and smallest equally. + //----------------------------------------------- + if (max < mid) + { + temp=max; max=mid; mid=temp; // swap max, mid + } + + if (max < min) + { + temp=max; max=min; min=temp; // swap max, min + } + + //----------------------------------------------- + // return largest + 1/4 middle + 1/4 smallest + //----------------------------------------------- + Check_Fpu(); + return max + ((mid+min)*.25); +} + + +//############################################################################# +// GaugeEntityList +//############################################################################# + +//============================================================================ +// Creator +//============================================================================ +GaugeEntityList::GaugeEntityList() : + Node(GaugeEntityList::GaugeEntityListClassID), + instanceList(this) +{ + Check_Fpu(); +} + +//============================================================================ +// Destructor +//============================================================================ +GaugeEntityList::~GaugeEntityList() +{ + Check(this); + Clear(); // is this necessary, or are nodes automatically deleted? + Check_Fpu(); +} + +//============================================================================ +// TestInstance +//============================================================================ +Logical + GaugeEntityList::TestInstance() const +{ + return Node::TestInstance(); +} + +//============================================================================ +// Add +//============================================================================ +void + GaugeEntityList::Add(Entity *entity) +{ + Check(this); + Check(entity); + Check(&instanceList); + instanceList.Add(entity); + Check_Fpu(); +} + +//============================================================================ +// Remove +//============================================================================ +void + GaugeEntityList::Remove(Entity *search_entity) +{ + Check(this); + + Test_Tell( + "GaugeEntityList::Remove(" << search_entity << + ")\n" + ); + Check(&instanceList); + ChainIteratorOf + i(instanceList); + + Entity + *entity; + + //----------------------------------------------------- + // Search the list for the given entity + //----------------------------------------------------- + while((entity=i.GetCurrent()) != NULL) + { + Check(entity); + + //----------------------------------------------------- + // If we find it, remove it and exit + //----------------------------------------------------- + if (entity == search_entity) + { + Test_Tell("Found!\n"); + i.Remove(); + break; + } + else + { + i.Next(); + } + } + Check_Fpu(); +} + +//============================================================================ +// NumberOfItems +//============================================================================ +int + GaugeEntityList::NumberOfItems() +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + Check_Fpu(); + return i.GetSize(); +} + +//============================================================================ +// Clear +//============================================================================ +void + GaugeEntityList::Clear() +{ +// Test_Tell("GaugeEntityList::Clear()\n"); + Check(this); + + ChainIteratorOf + i(instanceList); + + //----------------------------------------------------- + // Remove all objects from the list + //----------------------------------------------------- + while(i.GetCurrent() != NULL) + { + Check(i.GetCurrent()); + i.Remove(); + } + Check_Fpu(); +} + +//============================================================================ +// CopyEntities +// +// This method will create a reference in the destination list to +// all entities in the list +//============================================================================ +int + GaugeEntityList::CopyEntities( + GaugeEntityList *destination, + Derivation *derivation_type + ) +{ + Test_Tell("GaugeEntityList::CopyEntities(" << destination << ")\n"); + Check(this); + Check(destination); + + ChainIteratorOf + i(instanceList); + Entity + *entity; + int + count(0); + + //----------------------------------------------------- + // Return all items in the list + //----------------------------------------------------- + while ((entity=i.ReadAndNext()) != NULL) + { + Check(entity); + //----------------------------------------------------- + // Discard if wrong type + //----------------------------------------------------- + if (derivation_type != NULL) + { + if (! entity->IsDerivedFrom(*derivation_type)) + { + continue; + } + } + //----------------------------------------------------- + // Add to the new list + //----------------------------------------------------- + destination->Add(entity); + ++count; + } + Test_Tell("Found " << count << " items.\n"); + Check_Fpu(); + return count; +} + +//============================================================================ +// CopyEntitiesWithinBounds +// +// This method will create a reference in the destination list to +// all entities in the list that are within the given bounds (if supplied). +//============================================================================ +int + GaugeEntityList::CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Scalar min_x, + Scalar /*min_y*/, + Scalar min_z, + Scalar max_x, + Scalar /*max_y*/, + Scalar max_z, + Derivation *derivation_type + ) +{ + Test_Tell( + "GaugeEntityList::CopyEntitiesWithinBounds(" << destination << + ", " << min_x << + "... , " << min_z << + ", " << max_x << + "... , " << max_z << + ")\n" + ); + Check(this); + Check(destination); + + ChainIteratorOf + i(instanceList); + + Entity + *entity; + + Point3D + pos; + + int + count(0); + + //----------------------------------------------------- + // Check all items in the list + //----------------------------------------------------- + while ((entity=i.ReadAndNext()) != NULL) + { + Check(entity); + //----------------------------------------------------- + // Discard if wrong type + //----------------------------------------------------- + if (derivation_type != NULL) + { + if (! entity->IsDerivedFrom(*derivation_type)) + { + continue; + } + } + //----------------------------------------------------- + // Get the item's position and radius + //----------------------------------------------------- + pos = entity->localOrigin.linearPosition; + + //----------------------------------------------------- + // Add to the new list only if inside the bounds + //----------------------------------------------------- + Test_Tell( + "Testing (" << pos.x << + ", " << pos.y << + ", " << pos.z << + ")\n" + ); + //if (pos.z >= min_z) + //{ + // if (pos.z <= max_z) + // { + // if (pos.x >= min_x) + // { + // if (pos.x <= max_x) + { + Test_Tell("Accepted\n"); + destination->Add(entity); + ++count; + } + // } + // } + //} + } + Test_Tell("Found " << count << " items.\n"); + Check_Fpu(); + return count; +} + +//############################################################################# +// GaugeEntityArray +//############################################################################# + +//============================================================================ +// Creator +//============================================================================ +GaugeEntityArray::GaugeEntityArray() +{ + minimumX= 0.0; + minimumY= 0.0; + minimumZ= 0.0; + maximumX= 0.0; + maximumY= 0.0; + maximumZ= 0.0; + Check_Fpu(); +} + +//============================================================================ +// Destructor +//============================================================================ +GaugeEntityArray::~GaugeEntityArray() +{ + Check(this); + Clear(); + Check_Fpu(); +} + +//============================================================================ +// TestInstance +//============================================================================ +Logical + GaugeEntityArray::TestInstance() const +{ + return True; +} + +//============================================================================ +// Add +//============================================================================ +void + GaugeEntityArray::Add(Entity *entity) +{ + Test_Tell( + "GaugeEntityArray::Add(" << entity << + ")\n" + ); + Check(this); + Check(entity); + + //----------------------------------------------------- + // Add to the proper grid list + //----------------------------------------------------- + Point3D + pos(entity->localOrigin.linearPosition); + + grid[ArrayOffset(pos.x)][ArrayOffset(pos.z)].Add(entity); + //----------------------------------------------------- + // Keep track of the total extents + //----------------------------------------------------- + if (pos.x < minimumX) + { + minimumX = pos.x; + } + if (pos.y < minimumY) + { + minimumY = pos.y; + } + if (pos.z < minimumZ) + { + minimumZ = pos.z; + } + if (pos.x > maximumX) + { + maximumX = pos.x; + } + if (pos.y > maximumY) + { + maximumY = pos.y; + } + if (pos.z > maximumZ) + { + maximumZ = pos.z; + } + Check_Fpu(); +} + +//============================================================================ +// Remove +//============================================================================ +void + GaugeEntityArray::Remove(Entity *entity) +{ + Test_Tell( + "GaugeEntityArray::Remove(" << entity << + ")\n" + ); + Check(this); + Check(entity); + + Point3D + pos(entity->localOrigin.linearPosition); + + //----------------------------------------------------- + // Remove from the proper grid list + //----------------------------------------------------- + grid[ArrayOffset(pos.x)][ArrayOffset(pos.z)].Remove(entity); + Check_Fpu(); +} + +//============================================================================ +// Clear +//============================================================================ +void + GaugeEntityArray::Clear() +{ + Check(this); + + int + x, + z; + + //----------------------------------------------------- + // Clear all grid lists + //----------------------------------------------------- + for(z=0; z= gaugeMapArraySize) + { + z = gaugeMapArraySize - 1; + } + if (high_z < 0) + { + high_z = 0; + } + else if (high_z >= gaugeMapArraySize) + { + high_z = gaugeMapArraySize - 1; + } + + //----------------------------------------------------- + // Generate the x search limits + //----------------------------------------------------- + low_x = ArrayOffset(min_x - LARGEST_RADIUS); + high_x = ArrayOffset(max_x + LARGEST_RADIUS); + + if (low_x < 0) + { + low_x = 0; + } + else if (low_x >= gaugeMapArraySize) + { + low_x = gaugeMapArraySize - 1; + } + if (high_x < 0) + { + high_x = 0; + } + else if (high_x >= gaugeMapArraySize) + { + high_x = gaugeMapArraySize - 1; + } + + Test_Tell("Search x=(" << low_x << "..." << high_x << ")\n"); + Test_Tell("Search z=(" << z << "..." << high_z << ")\n"); + //------------------------------------------------------- + // Search the (limited) grid for items within the bounds + //------------------------------------------------------- + for( ; z>1); + + if (q < 0) + { + q = 0; + } + if (q >= gaugeMapArraySize) + { + q = (gaugeMapArraySize-1); + } + + Check_Fpu(); + return q; +} diff --git a/MUNGA/GAUGMAP.h b/MUNGA/GAUGMAP.h new file mode 100644 index 0000000..4282643 --- /dev/null +++ b/MUNGA/GAUGMAP.h @@ -0,0 +1,137 @@ +#pragma once + +#include "resource.h" +#include "node.h" +#include "scalar.h" +#include "chain.h" + +class Entity; +class GaugeEntityList; +class GaugeEntityArray; +class Derivation; +class Point3D; + +//####################################################################### +// GaugeEntityList +//####################################################################### +class GaugeEntityList : + public Node +{ +public: + GaugeEntityList(); + ~GaugeEntityList(); + Logical + TestInstance() const; + void + Add(Entity *entity); + void + Remove(Entity *entity); + void + Clear(); + int + NumberOfItems(); + int + CopyEntities( + GaugeEntityList *destination, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Scalar min_x, + Scalar min_y, + Scalar min_z, + Scalar max_x, + Scalar max_y, + Scalar max_z, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Point3D *center, + Scalar radius, + Derivation *derivation_type = NULL + ); + + ChainOf * const + GetInstanceList() + { + return &instanceList; + } +protected: + ChainOf + instanceList; +}; + +//####################################################################### +// GaugeEntityArray +//####################################################################### +class GaugeEntityArray SIGNATURED +{ +public: + GaugeEntityArray(); + ~GaugeEntityArray(); + Logical + TestInstance() const; + void + Add(Entity *entity); + void + Remove(Entity *entity); + void + Clear(); + void + PrintStatistics(); + int + CopyEntities( + GaugeEntityList *destination, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Scalar min_x, + Scalar min_y, + Scalar min_z, + Scalar max_x, + Scalar max_y, + Scalar max_z, + Derivation *derivation_type = NULL + ); + int + CopyEntitiesWithinBounds( + GaugeEntityList *destination, + Point3D *center, + Scalar radius, + Derivation *derivation_type = NULL + ); + void + GetBounds( + Scalar *min_x, + Scalar *min_y, + Scalar *min_z, + Scalar *max_x, + Scalar *max_y, + Scalar *max_z + ); + +protected: + enum + { + gaugeMapArraySize=64 + }; + + int + ArrayOffset(Scalar n); + + Scalar + minimumX, + minimumY, + minimumZ, + maximumX, + maximumY, + maximumZ; + + GaugeEntityList + grid[gaugeMapArraySize][gaugeMapArraySize]; +}; diff --git a/MUNGA/GAUGREND.cpp b/MUNGA/GAUGREND.cpp new file mode 100644 index 0000000..1daa82e --- /dev/null +++ b/MUNGA/GAUGREND.cpp @@ -0,0 +1,4196 @@ +#include "munga.h" +#pragma hdrstop + +#include "gaugrend.h" +#include "lamp.h" +#include "mover.h" +#include "terrain.h" +#include "app.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + + #define PROFILE_GAUGES + +#if defined(TRACE_GAUGE_RENDERER) + BitTrace Gauge_Renderer("Gauge Renderer"); +#endif + +//####################################################################### +// Miscellaneous utilities +//####################################################################### +int + LookupTable::Search(const char *string) +{ + Check_Pointer(this); + Verify(string != NULL); + + LookupTable + *table = this; + + for(; table->typeString!=NULL; ++table) + { + if (stricmp(string, table->typeString) == 0) + { + break; + } + } + Check_Fpu(); + return table->value; +} + + +//####################################################################### +// GaugeSymbol +//####################################################################### + +GaugeSymbol::GaugeSymbol( + GaugeSymbol **head_pointer, + const char *new_label, + GaugeInterpreterOffset new_offset, + Logical new_resolved +) +{ + Check(this); + Check_Pointer(head_pointer); + Check_Pointer(new_label); + Test_Tell( + "GaugeSymbol::GaugeSymbol(" << head_pointer << + "," << new_label << + "," << new_offset << + "," << new_resolved << + ")\n" + ); + + nextSymbol = *head_pointer; + *head_pointer = this; + + Str_Copy(label, new_label, sizeof(label)); + offset = new_offset; + resolved = new_resolved; + Check_Fpu(); +} + +GaugeSymbol::~GaugeSymbol() +{ + Check(this); + Check_Fpu(); +} + +Logical + GaugeSymbol::TestInstance() const +{ + return True; +} + +//####################################################################### +// GaugeSymbolTable +//####################################################################### +GaugeSymbolTable::GaugeSymbolTable(char *table_pointer) +{ + Test_Tell( + "GaugeSymbolTable::GaugeSymbolTable(" << ((void *) table_pointer) << + ")\n" + ); + Check_Pointer(this); + + head = NULL; + tablePointer = table_pointer; + Check_Fpu(); +} + +GaugeSymbolTable::~GaugeSymbolTable() +{ + Test_Tell( + "GaugeSymbolTable::~GaugeSymbolTable()\n" + ); + Check(this); + + GaugeSymbol + *symbol, + *next_symbol; + + for(symbol=head; symbol!=NULL; symbol=next_symbol) + { + Check(symbol); + + next_symbol = symbol->nextSymbol; + Unregister_Object(symbol); + delete symbol; + } + head = NULL; + Check_Fpu(); +} + +Logical + GaugeSymbolTable::TestInstance() const +{ + return True; +} + +void + GaugeSymbolTable::Add(const char *label, GaugeInterpreterOffset new_offset) +{ + Check(this); + Check_Pointer(label); + + Test_Tell( + "GaugeSymbolTable::Add(" << label << + "," << new_offset << + ")\n" + ); + + GaugeSymbol + *symbol; + + //------------------------------------------------- + // Check to see if this label already exists + //------------------------------------------------- + for(symbol=head; symbol!=NULL; symbol=symbol->nextSymbol) + { + Check(symbol); + + if (stricmp(label, symbol->label) == 0) + { + Test_Tell("Exists.\n"); + //------------------------------------------------- + // It DOES exist. Has it already been resolved? + //------------------------------------------------- + if (!symbol->resolved) + { + Test_Tell("Unresolved.\n"); + //------------------------------------------------- + // No, resolve all forward references to it + //------------------------------------------------- + // Forward references (references to undefined + // labels) are saved as a singly-linked list + // of offsets within the table itself: each + // reference to the label contains an offset to + // the previous reference. The list is + // terminated by an offset of -1. + //------------------------------------------------- + GaugeInterpreterOffset + table_offset, + next_offset, + *offset_pointer; + + for ( + table_offset=symbol->offset; + table_offset>=0; + table_offset = next_offset) + { + Test_Tell("Resolving " << table_offset << "\n"); + + offset_pointer = + (GaugeInterpreterOffset *) &tablePointer[table_offset]; + + next_offset = *offset_pointer; + *offset_pointer = (GaugeInterpreterOffset) new_offset; + } + symbol->offset = new_offset; + symbol->resolved = True; + Test_Tell("Done!\n"); + Check_Fpu(); + return; + } + else + { + Test_Tell("Resolved?!?!?.\n"); + //------------------------------------------------- + // Yes, this is an error. Throw a fit. + //------------------------------------------------- + DEBUG_STREAM << "label =" << label << "\n" << std::flush; + Fail("Already resolved"); + } + } + } + //------------------------------------------------- + // This is a new, resolved definition: just add it + //------------------------------------------------- + Test_Tell("New.\n"); +# if DEBUG_LEVEL > 0 + symbol = new GaugeSymbol(&head, label, new_offset, True); + Check(symbol); + Register_Object(symbol); +# else + new GaugeSymbol(&head, label, new_offset, True); +# endif + Check_Fpu(); +} + +GaugeInterpreterOffset + GaugeSymbolTable::Refer( + const char *label, + GaugeInterpreterOffset new_offset + ) +{ + Check(this); + Check_Pointer(label); + + Test_Tell( + "GaugeSymbolTable::Refer(" << label << + "," << new_offset << + ")\n" + ); + + GaugeSymbol + *symbol; + + //------------------------------------------------- + // Check to see if this label already exists + //------------------------------------------------- + for(symbol=head; symbol!=NULL; symbol=symbol->nextSymbol) + { + Check(symbol); + + if (stricmp(label, symbol->label) == 0) + { + Test_Tell("Exists.\n"); + //------------------------------------------------- + // It DOES exist. Is it resolved? + //------------------------------------------------- + if (symbol->resolved) + { + Test_Tell("Resolved.\n"); + //------------------------------------------------- + // Yes, return the value. + //------------------------------------------------- + Check_Fpu(); + return symbol->offset; + } + else + { + Test_Tell("Unresolved.\n"); + //------------------------------------------------- + // No, add to the list of forward references. + //------------------------------------------------- + GaugeInterpreterOffset + previous_offset = symbol->offset; + + Test_Tell("Returning previous " << previous_offset << ".\n"); + symbol->offset = new_offset; + Check_Fpu(); + return previous_offset; + } + } + } + //------------------------------------------------- + // This is a new forward reference. + // A (-1) is returned to mark the end of + // the reference chain. + // + // IT IS NOT AN ERROR! + //------------------------------------------------- + Test_Tell("New.\n"); +# if DEBUG_LEVEL > 0 + symbol = new GaugeSymbol(&head, label, new_offset, False); + Check(symbol); + Register_Object(symbol); +# else + new GaugeSymbol(&head, label, new_offset, False); +# endif + Check_Fpu(); + return -1; +} + +GaugeInterpreterOffset + GaugeSymbolTable::Get(const char *label) +{ + Test_Tell( + "GaugeSymbolTable::Get(" << label << + ")\n" + ); + Check(this); + Check_Pointer(label); + + GaugeSymbol + *symbol; + + //------------------------------------------------- + // Check to see if this label exists + //------------------------------------------------- + for(symbol=head; symbol!=NULL; symbol=symbol->nextSymbol) + { + Check(symbol); + + if (stricmp(label, symbol->label) == 0) + { + Test_Tell("Exists.\n"); + //------------------------------------------------- + // It DOES exist. Is it resolved? + //------------------------------------------------- + if (symbol->resolved) + { + Test_Tell("Resolved.\n"); + //------------------------------------------------- + // Yes, return the value. + //------------------------------------------------- + Check_Fpu(); + return symbol->offset; + } + else + { + Test_Tell("Unresolved (error).\n"); + //------------------------------------------------- + // Return error. + //------------------------------------------------- + Check_Fpu(); + return errUnresolvedForwardReference; + } + } + } + //------------------------------------------------- + // Undefined, return error. + //------------------------------------------------- + Test_Tell("Undefined (error).\n"); + Check_Fpu(); + return errUndefinedSymbol; +} + +const char * + GaugeSymbolTable::LabelFromValue(GaugeInterpreterOffset value) +{ +# if defined SHOW_EVERYTHING + Test_Tell( + "GaugeSymbolTable::LabelFromValue(" << value << + ")\n" + ); +# endif + Check(this); + + GaugeSymbol + *symbol; + + //------------------------------------------------- + // Check to see if this label exists + //------------------------------------------------- + for(symbol=head; symbol!=NULL; symbol=symbol->nextSymbol) + { + Check(symbol); + + if (symbol->offset == value) + { + //------------------------------------------------- + // It DOES exist. Is it resolved? + //------------------------------------------------- + if (symbol->resolved) + { + //------------------------------------------------- + // Yes, return the value. + //------------------------------------------------- + Check_Fpu(); + return symbol->label; + } + else + { + //------------------------------------------------- + // Return error. + //------------------------------------------------- + Check_Fpu(); + return NULL; + } + } + } + //------------------------------------------------- + // Undefined, return error. + //------------------------------------------------- + Check_Fpu(); + return NULL; +} + +Logical + GaugeSymbolTable::UnresolvedForwardReferences() +{ + Test_Tell( + "GaugeSymbolTable::UnresolvedForwardReferences()\n" + ); + Check(this); + + GaugeSymbol + *symbol; + + //------------------------------------------------- + // Check for unrersolved symbols + //------------------------------------------------- + for(symbol=head; symbol!=NULL; symbol=symbol->nextSymbol) + { + Test_Tell("Symbol '" << symbol->label << "' at " << symbol << "\n"); + Check(symbol); + + if (!symbol->resolved) + { + Test_Tell("Unresolved!\n"); + Check_Fpu(); + return True; + } + } + //------------------------------------------------- + // Everything is resolved! + //------------------------------------------------- + Test_Tell("All is resolved.\n"); + Check_Fpu(); + return False; +} + +//####################################################################### +// GaugeInterpreter +//####################################################################### +GaugeInterpreter::GaugeInterpreter() +{ + Test_Tell("GaugeInterpreter::GaugeInterpreter()\n"); + Check_Pointer(this); + //------------------------------------------------- + // Create interpreter table + //------------------------------------------------- + interpreterTable = new char[interpreterTableSize]; + Check_Pointer(interpreterTable); + Register_Pointer(interpreterTable); + //------------------------------------------------- + // Clear attribute variable array + //------------------------------------------------- + for (int i=0; i= sizeof(currentToken)) + { + Fail("Token too large"); + return NULL; + } + + if (c < 0) + { + if (char_pointer == currentToken) + { +# if defined(SHOW_EVERYTHING) + Test_Tell("EOF, NULL\n"); +# endif + return NULL; + } + else + { + *char_pointer = '\0'; +# if defined(SHOW_EVERYTHING) + Test_Tell("EOF, token=<" << currentToken << ">\n"); +# endif + return currentToken; + } + } + + if (c == '\n') + { +# if defined(SHOW_EVERYTHING) + Test_Tell("newline\n"); +# endif + ++lineNumber; + } + + switch(parsingState) + { + case parsingWhiteSpace: + switch(c) + { + case ' ': + case '\t': + case '\r': + case '\n': + case '\0': + file.stossc(); // discard character + break; + + case '#': + file.stossc(); // discard character +# if defined(SHOW_EVERYTHING) + Test_Tell("start comment\n"); +# endif + parsingState = parsingComment; + break; + + default: +# if defined(SHOW_EVERYTHING) + Test_Tell("non-white\n"); +# endif + parsingState = parsingToken; + break; + } + break; + + case parsingToken: + switch(c) + { + default: + file.stossc(); // discard character + *char_pointer++ = (char) c; + break; + + case '"': + file.stossc(); // discard character + if (char_pointer == currentToken) + { +# if defined(SHOW_EVERYTHING) + Test_Tell("start string\n"); +# endif + parsingState = parsingString; + } + else + { + *char_pointer = '\0'; +# if defined(SHOW_EVERYTHING) + Test_Tell("start string, token=<" << currentToken << ">\n"); +# endif + return currentToken; + } + break; + + case '{': + case '}': + case '(': + case ')': + case ',': + case '=': + case ';': + if (char_pointer == currentToken) + { + file.stossc(); // discard character + *char_pointer++ = (char) c; + } + *char_pointer = '\0'; +# if defined(SHOW_EVERYTHING) + Test_Tell("punctuation, token=<" << currentToken << ">\n"); +# endif + return currentToken; + + case '#': + file.stossc(); // discard character +# if defined(SHOW_EVERYTHING) + Test_Tell("start comment\n"); +# endif + parsingState = parsingComment; + break; + + case ' ': + case '\t': + case '\r': + case '\n': + case '\0': + file.stossc(); // discard character + *char_pointer = '\0'; +# if defined(SHOW_EVERYTHING) + Test_Tell("trailing white, token=<" << currentToken << ">\n"); +# endif + return currentToken; + } + break; + + case parsingComment: + file.stossc(); // discard character + switch(c) + { + case '\n': + case '\r': + if (char_pointer == currentToken) + { +# if defined(SHOW_EVERYTHING) + Test_Tell("end of comment\n"); +# endif + parsingState = parsingWhiteSpace; + } + else + { + *char_pointer = '\0'; +# if defined(SHOW_EVERYTHING) + Test_Tell("end of comment, token=<" <\n"); +# endif + return currentToken; + } + break; + } + break; + + case parsingString: + file.stossc(); // discard character + if (c == '"') + { + *char_pointer = '\0'; +# if defined(SHOW_EVERYTHING) + Test_Tell("end of string, token=<" << currentToken << ">\n"); +# endif + return currentToken; + } + else + { + *char_pointer++ = (char) c; + } + break; + } + } + Fail("Unintended exit"); + Check_Fpu(); + return NULL; +} + +void + GaugeInterpreter::UngetPreviousToken() +{ + Check(this); + tokenNotTaken = True; + Check_Fpu(); +} + +Logical + GaugeInterpreter::GetInteger(int *int_pointer) +{ + Test_Tell( + "GaugeInterpreter::GetInteger(" << ((void *) int_pointer) << + ")..." + ); + Check(this); + Check_Pointer(int_pointer); + + const char + *token = GetToken(); + Check_Pointer(token); + Test_Tell("token=" << token << "..."); + + int + c, + value = 0; + Logical + result, + is_negative = False; + + if (*token == '-') + { + is_negative = True; + ++token; + } + + if (*token == '0') + { + ++token; + if (*token == '\0') + { + Test_Tell("found zero value\n"); + *int_pointer = 0; + return True; + } + } + + if (*token == 'x' || *token == 'X') + { + for(++token; *token != '\0'; ++token) + { + c = toupper(*token); + + if (!isxdigit(c)) + { + return False; + } + + if (c > '9') + { + c -= ('A'-':'); + } + value = (value << 4) + (c - '0'); + } + result = True; + } + else + { + for( ; *token != '\0'; ++token) + { + c = *token; + if (!isdigit(c)) + { + return False; + } + value = (value*10) + (c - '0'); + } + result = True; + } + + if (result == True) + { + if (is_negative) + { + value = - value; + } + Test_Tell("found value " << value << "\n"); + *int_pointer = value; + } +# if defined(LOCAL_TEST) + else + { + Test_Tell("FAILED\n"); + } +# endif + Check_Fpu(); + return result; +} + +Logical + GaugeInterpreter::GetScalar(Scalar *scalar_pointer) +{ + Test_Tell( + "GaugeInterpreter::GetScalar(" << ((void *) scalar_pointer) << + ")..." + ); + Check(this); + Check_Pointer(scalar_pointer); + + const char + *token = GetToken(); + Check_Pointer(token); + Test_Tell("token=" << token << "\n"); + + float // HACK - I don't know how to avoid an explicit 'float'... + value; + Logical + is_negative = False; + + if (*token == '-') + { + is_negative = True; + ++token; + } + + if (sscanf(token, "%f", &value) > 0) + { + Test_Tell("found " << value << "\n"); + + if (is_negative) + { + value = - value; + } + *scalar_pointer = (Scalar) value; + return True; + } + ReportParsingError("Token not a scalar value"); + Check_Fpu(); + return False; +} + +Logical + GaugeInterpreter::GetVector(Vector2DOf *vector) +{ + Test_Tell("GaugeInterpreter::GetVector(" << ((void *) vector) << ")..."); + Check(this); + Check_Pointer(vector); + + Vector2DOf + local_vector; + + if (strcmp(GetToken(), "(") != 0) + { + ReportParsingError("Missing leading '(' for 2D vector"); + return False; + } + if (!GetInteger(&local_vector.x)) + { + return False; + } + if (strcmp(GetToken(), ",") != 0) + { + ReportParsingError("Missing ',' for 2D vector"); + return False; + } + if (!GetInteger(&local_vector.y)) + { + return False; + } + if (strcmp(GetToken(), ")") != 0) + { + ReportParsingError("Missing trailing ')' for 2D vector"); + return False; + } + + *vector = local_vector; + Check_Fpu(); + return True; +} + +Logical + GaugeInterpreter::GetRate(GaugeRate *rate) +{ + Test_Tell("GaugeInterpreter::GetRate(" << ((void *) rate) << ")..."); + Check(this); + const char + *text = GetToken(); + Test_Tell("token='" << text << "'\n"); + Check_Pointer(text); + Check_Pointer(rate); + + int + c; + //----------------------------------------------- + // Get rate (A..P) + //----------------------------------------------- + c = *text; + if (!isalpha(c)) + { + ReportParsingError("Token is not a valid rate"); + } + else + { + c = toupper(c); + if ((c >= 'A') && (c <= 'Z')) + { + *rate = Gauge::ConvertIndexToRate(c -'A'); + Check_Fpu(); + return True; + } + else + { + ReportParsingError("Token is not a valid rate"); + } + } + Check_Fpu(); + return False; +} + +Logical + GaugeInterpreter::GetModeMask(ModeMask *mask_pointer) +{ + Test_Tell( + "GaugeInterpreter::GetLong(" << ((void *) mask_pointer) << + ")..." + ); + Check(this); + Check_Pointer(mask_pointer); + + const char + *token = GetToken(); + Check_Pointer(token); + Test_Tell("token=" << token << "..."); + + int + c; + ModeMask + value = (ModeMask) 0; + Logical + result = False, + is_negative = False; + + //------------------------------------------------------ + // Deal with negative sign here + //------------------------------------------------------ + if (*token == '-') + { + is_negative = True; + ++token; + } + + if (isalpha(*token)) + { + //------------------------------------------------------ + // Check for a named constant + //------------------------------------------------------ + Check(application); + Check(application->GetModeManager()); + + result = application->GetModeManager()->ModeStringLookup(token, &value); + } + else + { + //-------------------------------------------------------- + // Not a named constant. must be either number or an error + //-------------------------------------------------------- + if (*token == '0') + { + ++token; + result = True; // might be a single lonely zero (which is legit) + } + + if (*token == 'x' || *token == 'X') + { + //-------------------------------------------------------- + // Process hex value + //-------------------------------------------------------- + for(++token; *token != '\0'; ++token) + { + c = toupper(*token); + + if (!isxdigit(c)) + { + return False; + } + + if (c > '9') + { + c -= ('A'-':'); + } + value = (value << 4) + (ModeMask) (c - '0'); + } + result = True; + } + else + { + //-------------------------------------------------------- + // Process decimal value + //-------------------------------------------------------- + for( ; *token != '\0'; ++token) + { + c = *token; + if (!isdigit(c)) + { + Check_Fpu(); + return result; + } + value = (value*10) + (ModeMask) (c - '0'); + } + result = True; + } + } + + if (result == True) + { + if (is_negative) + { + value = - value; + } + Test_Tell("found value " << value << "\n"); + *mask_pointer = value; + } +# if defined(LOCAL_TEST) + else + { + Test_Tell("FAILED\n"); + } +# endif + Check_Fpu(); + return result; +} + +void + GaugeInterpreter::ReportParsingError( + const char *string + ) +{ + Check(this); + Check_Pointer(string); + + DEBUG_STREAM << + "Interpreter parsing error:" << string << + " in line " << lineNumber << + "\n"; + Fail("Parsing error"); +} + +void + GaugeInterpreter::Initialize( + const char *file_name, + MethodDescription **method_list, + Warehouse *warehouse_pointer + ) +{ + Check(this); + Check_Pointer(file_name); + Check_Pointer(method_list); + Check(warehouse_pointer); + //------------------------------------------------------------------------ + // Determine the number of primitives + //------------------------------------------------------------------------ + MethodDescription + *method_entry, + **list; + + primitiveCount = 0; + list = method_list; + while(list != NULL) + { + Check_Pointer(list); + method_entry = *list++; + Check_Pointer(method_entry); + if (method_entry->name == NULL) + { + //------------------------------------------------------------- + // Attempt to chain to next list: if NULL, we're done. + //------------------------------------------------------------- + list = method_entry->parameterList[0].data.nextMethodList; + } + else + { + //------------------------------------------------------------- + // Increment the primitive count + //------------------------------------------------------------- + ++primitiveCount; + } + } + //------------------------------------------------------------------------ + // Allocate the primitive table + //------------------------------------------------------------------------ + primitiveTable = new MethodDescription*[primitiveCount]; + Register_Pointer(primitiveTable); + //------------------------------------------------------------------------ + // Fill in the primitiveTable + //------------------------------------------------------------------------ + MethodDescription + **method_pointer = primitiveTable; + + list = method_list; + while(list != NULL) + { + Check_Pointer(list); + method_entry = *list++; + Check_Pointer(method_entry); + if (method_entry->name == NULL) + { + //------------------------------------------------------------- + // Attempt to chain to next list: if NULL, we're done. + //------------------------------------------------------------- + list = method_entry->parameterList[0].data.nextMethodList; + } + else + { + //------------------------------------------------------------- + // Save a pointer to the method description + //------------------------------------------------------------- + Verify((method_pointer-primitiveTable) < primitiveCount); + *(method_pointer++) = method_entry; + } + } + //------------------------------------------------------------------------ + // Parse the text file to build the interpreter table + //------------------------------------------------------------------------ + //file.open(file_name, std::ios::in|std::ios::nocreate, std::filebuf::openprot); + // alternate line added by RB 1/6/2007 + file.open(file_name, std::ios::in, std::ios::_Openprot); + + if (!file.is_open()) + { + DEBUG_STREAM << "Cannot open interpreter file '" << file_name << "'\n" << std::flush; + } + else + { + lineNumber = 1; + tokenNotTaken = False; + + const char + *name; + char + local_name[32]; + //---------------------------------------------------- + // Parse the statement: + // { } + //---------------------------------------------------- + // + + while((name = GetToken()) != NULL ) + { + Str_Copy(local_name, name, sizeof(local_name)); + + if (stricmp(GetToken(), "{") != 0) + { + ReportParsingError("Missing '{'"); + } + symbolTable->Add(local_name, currentOffset); + GetProcedureBody(method_list, warehouse_pointer); + } + if (symbolTable->UnresolvedForwardReferences()) + { + ReportParsingError("Unresolved forward references"); + } + file.close(); + + { + GaugeInterpreterCommand + command = endMarker; + Insert(&command, sizeof(GaugeInterpreterCommand)); +# if defined(LOCAL_TEST) + DumpTable(); +# endif + }; + } + //------------------------------------------------------------------------ + // All done! + //------------------------------------------------------------------------ + Check_Fpu(); +} + +void + GaugeInterpreter::GetProcedureBody( + MethodDescription **method_list, + Warehouse *warehouse_pointer + ) +{ + Check(this); + Check_Pointer(method_list); + Check(warehouse_pointer); + + int + running = 1; + GaugeInterpreterCommand + command; + const char + *name; + char + local_name[32]; + + while (running) + { + name = GetToken(); + if (name == NULL) + { + ReportParsingError("Internal error (NULL token)"); + } + + Str_Copy(local_name, name, sizeof(local_name)); + + if (stricmp(name, "}") == 0) + { + Test_Tell("End\n"); + command = returnCommand; + Insert(&command, sizeof(GaugeInterpreterCommand)); + break; + } + else if (*name == '@') // example: @1 = ppc/reloadtime; + { + if (strlen(name) != 2) + { + ReportParsingError("Ill-formed attribute variable index"); + } + unsigned char + index = (unsigned char) ((*(name+1)) - '0'); + + if (index > maxVariableNameArrayIndex) + { + ReportParsingError("Illegal attribute variable index"); + } + + if (strcmp(GetToken(), "=") != 0) + { + ReportParsingError("Missing '='"); + } + Test_Tell("Attribute variable\n"); + command = attributeVariableCommand; + Insert(&command, sizeof(GaugeInterpreterCommand)); + Insert(&index, sizeof(unsigned char)); + InsertString(GetToken()); + } + else if (stricmp(name, "enable") == 0) + { + if (strcmp(GetToken(), "=") != 0) + { + ReportParsingError("Missing '='"); + } + + ModeMask + mode_mask; + GetModeMask(&mode_mask); // fails to debugger if bad input + + Test_Tell("Enable\n"); + command = enableCommand; + Insert(&command, sizeof(GaugeInterpreterCommand)); + Insert(&mode_mask, sizeof(ModeMask)); + } + else if (stricmp(name, "disable") == 0) + { + if (strcmp(GetToken(), "=") != 0) + { + ReportParsingError("Missing '='"); + } + + ModeMask + mode_mask; + GetModeMask(&mode_mask); // fails to debugger if bad input + + Test_Tell("Disable\n"); + command = disableCommand; + Insert(&command, sizeof(GaugeInterpreterCommand)); + Insert(&mode_mask, sizeof(ModeMask)); + } + else if (stricmp(name, "offset") == 0) + { + if (strcmp(GetToken(), "=") != 0) + { + ReportParsingError("Missing '='"); + } + + Vector2DOf + offset; + + GetVector(&offset); // fails to debugger if input bad + + Test_Tell("offset\n"); + command = addOffsetCommand; + Insert(&command, sizeof(GaugeInterpreterCommand)); + Insert(&offset, sizeof(Vector2DOf)); + } + else if (stricmp(name, "port") == 0) + { + if (strcmp(GetToken(), "=") != 0) + { + ReportParsingError("Missing '='"); + } + + command = setPortIndexCommand; + Insert(&command, sizeof(GaugeInterpreterCommand)); + InsertString(GetToken()); + } + else // must be either call or primitive + { + const char + *token = GetToken(); + if (stricmp(token, "(") == 0) + { + if ( + ParsePrimitive( + local_name, + method_list, + warehouse_pointer + ) == False + ) + { + ReportParsingError("Undefined primitive"); + } + if (stricmp(GetToken(), ")") != 0) + { + ReportParsingError("Missing ')'"); + } + } + else + { + UngetPreviousToken(); + + Test_Tell("Call to '" << local_name << "'\n"); + + command = callCommand; + Insert(&command, sizeof(GaugeInterpreterCommand)); + + Check(symbolTable); + GaugeInterpreterOffset + offset = symbolTable->Refer(local_name, currentOffset); + Insert(&offset, sizeof(GaugeInterpreterOffset)); + } + } + + if (stricmp(GetToken(), ";") != 0) + { + ReportParsingError("Missing ';'"); + } + } + Check_Fpu(); +} + +Logical + GaugeInterpreter::ParsePrimitive( + const char *name, + MethodDescription **method_list, + Warehouse *warehouse_pointer + ) +{ + Test_Tell( + "GaugeInterpreter::ParsePrimitive(" << name << + ", " << method_list << + ", " << warehouse_pointer << + ")\n" + ); + Check(this); + Check_Pointer(name); + Check_Pointer(method_list); + Check(warehouse_pointer); + + MethodDescription + *method_entry, + **list; + GaugeInterpreterCommand + command_number = nextAvailableCommand; + int + i; + Logical + first_parameter = True; + + list = method_list; + while(list != NULL) + { + Check_Pointer(list); + method_entry = *list++; + Check_Pointer(method_entry); + if (method_entry->name == NULL) + { + //------------------------------------------------------------- + // Attempt to chain to next list: if NULL, we didn't match. + //------------------------------------------------------------- + list = method_entry->parameterList[0].data.nextMethodList; + } + else + { + //------------------------------------------------------------- + // Attempt to match this entry + //------------------------------------------------------------- + Test_Tell("<" << method_entry->name << ">\n"); + if (stricmp(method_entry->name, name) != 0) + { + command_number = (GaugeInterpreterCommand) (command_number + 1); + } + else + { + //------------------------------------------------------- + // Name found, attempt to procure parameters + //------------------------------------------------------- + Test_Tell("Found, attempt to match parameters\n"); + for ( + i=0; + method_entry->parameterList[i].type != + ParameterDescription::typeEmpty; + ++i + ) + { + //------------------------------------------------------- + // Eat commas (after first parameter) + //------------------------------------------------------- + if (first_parameter) + { + first_parameter = False; + } + else + { + if (stricmp(GetToken(), ",") != 0) + { + ReportParsingError("Missing ','"); + return False; + } + } + //------------------------------------------------------- + // Read a parameter + //------------------------------------------------------- + if (method_entry->parameterList[i]. + Extract(this, warehouse_pointer) == False + ) + { + //---------------------------------------------- + // Not found, error + //---------------------------------------------- + ReportParsingError("Wrong or missing parameter"); + return False; + } + } + //------------------------------------------------------- + // All parameters found, write to the interpreter table + //------------------------------------------------------- + Test_Tell("All parameters matched\n"); + + Check_Pointer(method_entry->execute); // make sure it's executable + Verify((command_number-nextAvailableCommand) >= 0); + Verify((command_number-nextAvailableCommand) < primitiveCount); + + Insert(&command_number, sizeof(GaugeInterpreterCommand)); + + for ( + i=0; + method_entry->parameterList[i].type != + ParameterDescription::typeEmpty; + ++i + ) + { + method_entry->parameterList[i].Save(this); + } + Test_Tell("All done\n"); + Check_Fpu(); + return True; + } + } + } + //------------------------------------------------------------- + // Name not matched, return error + //------------------------------------------------------------- + Test_Tell("Not found!\n"); + Check_Fpu(); + return False; +} + +void + GaugeInterpreter::Insert(const void *value_pointer, int size_in_chars) +{ +# if defined(SHOW_EVERYTHING) + Test_Tell( + "GaugeInterpreter::Insert(" << ((void *) value_pointer) << + "," << size_in_chars << + ")\n" + ); +# endif + Check(this); + Check_Pointer(value_pointer); + Verify(size_in_chars > 0); + + Verify((currentOffset+size_in_chars) < interpreterTableSize); + + char + *source; + + for( + source= (char *) value_pointer; + size_in_chars!=0; + ++source, --size_in_chars + ) + { + interpreterTable[currentOffset++] = *source; + } + Check_Fpu(); +} + +void * + GaugeInterpreter::Retrieve(int size_in_chars) +{ +# if defined(SHOW_EVERYTHING) + Test_Tell( + "GaugeInterpreter::Retrieve(" << size_in_chars << ")\n" + ); +# endif + Check(this); + + Verify(size_in_chars > 0); + + Verify(currentOffset >= 0); + Verify(currentOffset < interpreterTableSize); + + void + *here = &interpreterTable[currentOffset]; + + currentOffset = (GaugeInterpreterOffset) (currentOffset + size_in_chars); + Verify(currentOffset < interpreterTableSize); + + Check_Fpu(); + return here; +} + +void + GaugeInterpreter::InsertString(const char *string) +{ + Check(this); + Check_Pointer(string); + + unsigned short + length = (unsigned short) (strlen(string)+1); + + Test_Tell( + "GaugeInterpreter::InsertString(" << string << + "), len=" << length << "\n" + ); + + Verify(length < ParameterDescription::maxStringLength); + + Insert(&length, sizeof(unsigned short)); + Insert(string, length); + Check_Fpu(); +} + +const char * + GaugeInterpreter::RetrieveString() +{ +# if defined(SHOW_EVERYTHING) + Test_Tell( + "GaugeInterpreter::RetrieveString()='" + ); +# endif + Check(this); + + const char + *pointer; + + unsigned short + length = *(unsigned short *) Retrieve(sizeof(unsigned short)); + + Verify(length < ParameterDescription::maxStringLength); + + pointer = (const char *) &interpreterTable[currentOffset]; + Check_Pointer(pointer); + + currentOffset = (GaugeInterpreterOffset) (currentOffset + length); + +# if defined(SHOW_EVERYTHING) + Test_Tell( pointer << "', len=" << length << "\n"); +# endif + Check_Fpu(); + return pointer; +} + + +void + GaugeInterpreter::Interpret( + const char *label, + GaugeRenderer *renderer, + int display_port_index, + Vector2DOf position, + Entity *entity + ) +{ + Test_Tell( + "GaugeInterpreter::Interpret('" << label << + "'," << renderer << + "," << display_port_index << + "," << position << + "," << entity << + "\n" + ); + Check(this); + Check_Pointer(label); + Check(renderer); + // 'entity' is allowed to be NULL + + Check(symbolTable); + Check_Pointer(interpreterTable); + + GaugeInterpreterOffset + offset = symbolTable->Get(label); + if (offset < 0) + { + DEBUG_STREAM << "GaugeInterpreter: undefined label '" << label << "'\n" << std::flush; + } + else + { + InterpretFromOffset( + offset, + renderer, + display_port_index, + position, + entity + ); + } + Check_Fpu(); +} + +void + GaugeInterpreter::InterpretFromOffset( + GaugeInterpreterOffset offset, + GaugeRenderer *renderer, + int display_port_index, + Vector2DOf original_position, + Entity *entity + ) +{ + Test_Tell( + "GaugeInterpreter::InterpretFromOffset(" << offset << + "," << renderer << + "," << display_port_index << + "," << original_position << + "," << entity << + "\n" + ); + Check(this); + Check(renderer); + Verify(offset >= 0); + // 'entity' is allowed to be NULL + Check_Pointer(interpreterTable); + + currentOffset = offset; + + GaugeInterpreterCommand + command; + + int + running = 1; + Vector2DOf + position; + + position = original_position; + + while(running) + { + command = *(GaugeInterpreterCommand *) + Retrieve(sizeof(GaugeInterpreterCommand)); + switch(command) + { + case endMarker: + case returnCommand: + Test_Tell("Return\n"); + running = 0; + break; + + case setPortIndexCommand: + { + const char + *port_name = RetrieveString(); + Test_Tell("Set port=" << port_name << "\n"); + //------------------------------------------ + // Replace variable if needed + //------------------------------------------ + port_name = ReplaceVariable(port_name); + + int + port = renderer->FindGraphicsPort(port_name); + + if (port >= 0) + { + display_port_index = port; + } + else + { + Tell( + "GaugeInterpreter::InterpretFromOffset: port '"<< + port_name << "' not found!\n" + ); + } + } + break; + + case addOffsetCommand: + { + Vector2DOf + temp; + + temp = *(Vector2DOf *) Retrieve(sizeof(Vector2DOf)); + Test_Tell("Add offset " << std::dec << temp); + position.x = original_position.x + temp.x; + position.y = original_position.y + temp.y; + Test_Tell(" to " << position << "\n"); + } + break; + + case attributeVariableCommand: + { + unsigned char + index = *(unsigned char *)Retrieve(sizeof(unsigned char)); + const char + *attribute_name = RetrieveString(); + Test_Tell( + "attribute variable #" << index << "=" << attribute_name << "\n" + ); + + Verify(index < maxVariableNameArrayIndex); + attributeNameArray[index] = attribute_name; + } + break; + case callCommand: + { + GaugeInterpreterOffset + new_offset = + *(GaugeInterpreterOffset *) + Retrieve(sizeof(GaugeInterpreterOffset)); + + Test_Tell("Call " << std::hex << new_offset << std::dec << "\n"); + offset = currentOffset; // save for call + + InterpretFromOffset( + new_offset, + renderer, + display_port_index, + position, + entity + ); + currentOffset = offset; // restore offset + } + break; + + case enableCommand: + Test_Tell("Enable\n"); + { + Check(application); + Check(application->GetModeManager()); + + application->GetModeManager()->AddModeMask( + *(ModeMask*)Retrieve(sizeof(ModeMask)) + ); + } + break; + + case disableCommand: + Test_Tell("Disable\n"); + { + Check(application); + Check(application->GetModeManager()); + + application->GetModeManager()->RemoveModeMask( + *(ModeMask*)Retrieve(sizeof(ModeMask)) + ); + } + break; + + default: + command = (GaugeInterpreterCommand) (command - nextAvailableCommand); + Verify(command < primitiveCount); + Check_Pointer(primitiveTable); + + Test_Tell("****" << primitiveTable[command]->name<< "\n"); + primitiveTable[command]->Execute( + display_port_index, + position, + entity, + renderer + ); + break; + } + } + Check_Fpu(); +} + +const char * + GaugeInterpreter::ReplaceVariable(const char *string) +{ + Check(this); + Verify(string != NULL); + if (*string == '@') + { + unsigned char + index = *(string+1); + if ((index >= '0') && (index <= '9')) + { + string = attributeNameArray[index - '0']; + Verify(string != NULL); + Test_Tell( + "Variable @" << index << " replaced with '" << string <<"'\n" + ); + } + } + Check_Fpu(); + return string; +} + +void + GaugeInterpreter::DumpTable() +{ + Test_Tell("GaugeInterpreter::DumpTable\n"); + Check(this); + + GaugeInterpreterCommand + command; + + const char + *label; + + currentOffset = 0; + do + { + label = symbolTable->LabelFromValue(currentOffset); + if (label != NULL) + { + DEBUG_STREAM << label << ":\n" << std::flush; + } + + DEBUG_STREAM << " " << std::hex << currentOffset << ":" << std::flush; + + command = *(GaugeInterpreterCommand *) + Retrieve(sizeof(GaugeInterpreterCommand)); + switch(command) + { + case endMarker: + DEBUG_STREAM << "---------End of table---------\n" << std::flush; + break; + + case returnCommand: + DEBUG_STREAM <<"return\n" << std::flush; + break; + + case setPortIndexCommand: + { + const char + *port_name = RetrieveString(); + DEBUG_STREAM << "setport '" << port_name << "'\n" << std::flush; + } + break; + + case addOffsetCommand: + { + Vector2DOf + offset = *(Vector2DOf *) Retrieve(sizeof(Vector2DOf)); + + DEBUG_STREAM << "offset " << std::dec << offset << "\n" << std::flush; + } + break; + + case callCommand: + { + GaugeInterpreterOffset + new_offset = + *(GaugeInterpreterOffset *) + Retrieve(sizeof(GaugeInterpreterOffset)); + + DEBUG_STREAM << "call 0x" << new_offset << " (" << std::flush; + + const char + *name = symbolTable->LabelFromValue(new_offset); + + if (name == NULL) + { + DEBUG_STREAM << "UNDEFINED!!!)\n" << std::flush; + } + else + { + DEBUG_STREAM << name << ")\n" << std::flush; + } + } + break; + + case enableCommand: + { + ModeMask + mask = *(ModeMask*)Retrieve(sizeof(ModeMask)); + DEBUG_STREAM << "enable 0x" << mask << "\n" << std::flush; + } + break; + + case disableCommand: + { + ModeMask + mask = *(ModeMask*)Retrieve(sizeof(ModeMask)); + DEBUG_STREAM << "disable 0x" << mask << "\n" << std::flush; + } + break; + + default: + { + MethodDescription + *method_entry = primitiveTable[command-nextAvailableCommand]; + DEBUG_STREAM << method_entry->name << ":\n" << std::flush; + + int + i; + for ( + i=0; + method_entry->parameterList[i].type != + ParameterDescription::typeEmpty; + ++i + ) + { + //------------------------------------------------------- + // Show a parameter + //------------------------------------------------------- + method_entry->parameterList[i].DumpInterpreterEntry( + this, + " " + ); + } + } + break; + } + } + while(command != endMarker); + Check_Fpu(); +} + +//############################################################################# +// ParameterDescription +//############################################################################# +ParameterDescription::~ParameterDescription() +{ + Check_Fpu(); +} + +#if DEBUG_LEVEL <= 0 +void + ParameterDescription::CheckIt(int /*this_type*/) +{ +} +#else +void + ParameterDescription::CheckIt(int this_type) +{ + Check_Pointer(this); + Verify(type == this_type); + + switch(type) + { + case typeEmpty: + case typeRate: + case typeModeMask: + case typeInteger: + case typeColor: + case typeScalar: + case typeVector: + case typeRectangle: + break; + + case typeAttribute: + case typeString: + if (data.string != NULL) + { + Check_Pointer(data.string); + } + break; + + default: + Fail("Illegal parameter type!"); + } + Check_Fpu(); +} +#endif + +void + ParameterDescription::ShowInstance( + char *indent + ) +{ + Check_Pointer(this); + DEBUG_STREAM << indent << "ParameterDescription:" << std::dec << std::flush; + switch(type) + { + case typeEmpty: + DEBUG_STREAM << "empty" << std::flush; + break; + + case typeRate: + DEBUG_STREAM << "rate=" << std::flush; + { + int + i,j; + + for(i='A',j=0x10000; i<'Q'; ++i, j<<=1) + { + if (data.rate & j) + { + DEBUG_STREAM << (char) i << std::flush; + } + } + } + break; + + case typeModeMask: + DEBUG_STREAM << std::hex << "modeMask=" << data.modeMask << std::dec << std::flush; + break; + + case typeInteger: + DEBUG_STREAM << "integer=" << data.integer << std::flush; + break; + + case typeColor: + DEBUG_STREAM << "color=0x" << std::hex << data.color << std::dec << std::flush; + break; + + case typeScalar: + DEBUG_STREAM << "scalar=" << data.scalar << std::flush; + break; + + case typeVector: + DEBUG_STREAM << + "vector= (" << data.vector.x << + ", " << data.vector.y << + ")"; + break; + + case typeRectangle: + DEBUG_STREAM << + "rectangle= ((" << data.rectangle.bottomLeft.x << + ", " << data.rectangle.bottomLeft.y << + "),(" << data.rectangle.topRight.x << + ", " << data.rectangle.topRight.y << + ")"; + break; + + case typeAttribute: + if (data.string == NULL) + { + DEBUG_STREAM << "attribute=NULL\n" << std::flush; + } + else + { + DEBUG_STREAM << "attribute=<" << data.string << ">" << std::flush; + } + break; + + case typeString: + if (data.string == NULL) + { + DEBUG_STREAM << "string=NULL\n" << std::flush; + } + else + { + DEBUG_STREAM << "string=<" << data.string << ">" << std::flush; + } + break; + + default: + DEBUG_STREAM << "ILLEGAL TYPE=" << type << std::flush; + } + DEBUG_STREAM << "\n" << std::flush; + Check_Fpu(); +} + +void * + ParameterDescription::ParseAttribute( + const char *string_pointer, + Entity *entity + ) +{ + Test_Tell( + "ParameterDescription::ParseAttribute('" << string_pointer << + "', " << entity << + ")\n" + ); + Check_Pointer(this); + Check_Pointer(string_pointer); + Check(entity); + + Simulation* + simulation; + + char + temp_string[80], + *source, + *temp_ptr; + + Verify(type == typeAttribute); + + Str_Copy(temp_string, string_pointer, sizeof(temp_string)); + + source = temp_string; + for(temp_ptr = source; *temp_ptr != '\0'; ++temp_ptr) + { + if (*temp_ptr == '/') + { + *temp_ptr = '\0'; + + Test_Tell("Subsystem name=" << source << "\n"); + + simulation = (Simulation *) entity->FindSubsystem(source); + if (simulation == NULL) + { + Tell("parseAttribute - subsystem '" << source << "' not found\n"); + Check_Fpu(); + return NULL; + } + else + { + source = temp_ptr+1; + Test_Tell("Subsystem attribute name=" << source << "\n"); + + void + *attribute_pointer = simulation->GetAttributePointer(source); + + if (attribute_pointer == NULL) + { + Tell( + "parseAttribute - attribute '" << + string_pointer << "' not found\n" + ); + } + Check_Fpu(); + return attribute_pointer; + } + } + } + + Test_Tell("Entity attribute name=" << source << "\n"); + + void + *attribute_pointer = ((Simulation *)entity)->GetAttributePointer(source); + + if (attribute_pointer == NULL) + { + Tell( + "parseAttribute - attribute '" << + source << "' not found\n" + ); + } + Check_Fpu(); + return attribute_pointer; +} + +Logical + ParameterDescription::Extract( + GaugeInterpreter *interpreter, + Warehouse *warehouse_pointer + ) +{ + Test_Tell( + "ParameterDescription::Extract(" << interpreter << + ", " << warehouse_pointer << + ")\n" + ); + Check_Pointer(this); + Check(interpreter); + // + //---------------------------------------------------------------- + // Choose the appropriate parameter type, attempt to create it + //---------------------------------------------------------------- + // + switch(type) + { + case typeEmpty: + Fail("type == empty!"); + break; + + case typeRate: + Test_Tell("rate? "); + if (interpreter->GetRate(&data.rate)) + { + Test_Tell("yes.\n"); + Check_Fpu(); + return True; + } + break; + + case typeModeMask: + Test_Tell("modeMask? "); + if (interpreter->GetModeMask(&data.modeMask)) + { + Test_Tell("yes.\n"); + Check_Fpu(); + return True; + } + break; + + case typeInteger: + Test_Tell("integer? "); + if (interpreter->GetInteger(&data.integer)) + { + Test_Tell("yes.\n"); + Check_Fpu(); + return True; + } + break; + + case typeColor: + Test_Tell("color? "); + if (interpreter->GetInteger(&data.color)) + { + if (data.color <= 0xFF && data.color >= 0) + { + Test_Tell("yes.\n"); + Check_Fpu(); + return True; + } + } + break; + + case typeScalar: + Test_Tell("scalar? "); + if (interpreter->GetScalar(&data.scalar)) + { + Test_Tell("yes.\n"); + Check_Fpu(); + return True; + } + break; + + case typeVector: + Test_Tell("vector? "); + { + Vector2DOf + temp_vector; + + if (interpreter->GetVector(&temp_vector)) + { + data.vector.x = temp_vector.x; + data.vector.y = temp_vector.y; + Test_Tell("yes.\n"); + Check_Fpu(); + return True; + } + } + break; + + case typeRectangle: + Test_Tell("rectangle? "); + { + int + success; + + success = (strcmp(interpreter->GetToken(), "(") == 0); + success &= interpreter->GetInteger(&data.rectangle.bottomLeft.x); + success &= (strcmp(interpreter->GetToken(), ",") == 0); + success &= interpreter->GetInteger(&data.rectangle.bottomLeft.y); + success &= (strcmp(interpreter->GetToken(), ",") == 0); + success &= interpreter->GetInteger(&data.rectangle.topRight.x); + success &= (strcmp(interpreter->GetToken(), ",") == 0); + success &= interpreter->GetInteger(&data.rectangle.topRight.y); + success &= (strcmp(interpreter->GetToken(), ")") == 0); + + if (success) + { + Test_Tell("yes.\n"); + Check_Fpu(); + return True; + } + } + break; + + case typeAttribute: + { + const char + *token = interpreter->GetToken(); + Test_Tell("attribute='"); + Str_Copy(data.string, token, maxStringLength-1); + Test_Tell(data.string << "'\n"); + Check_Fpu(); + } + return True; + + case typeString: + { + const char + *token = interpreter->GetToken(); + Test_Tell("string='"); + Str_Copy(data.string, token, maxStringLength-1); + Test_Tell(data.string << "'\n"); + Check_Fpu(); + } + return True; + + default: + Fail("Illegal type"); + return False; + } + + Test_Tell("NO!\n"); + Check_Fpu(); + return False; +} + +void + ParameterDescription::Save(GaugeInterpreter *interpreter) +{ + Test_Tell("ParameterDescription::Save(" << interpreter << ")\n"); + Check_Pointer(this); + Check(interpreter); + + // + //---------------------------------------------------------------- + // Choose the appropriate type, write to interpreter table + //---------------------------------------------------------------- + // + switch(type) + { + case typeEmpty: + Fail("type == empty!"); + break; + + case typeRate: + Test_Tell("rate\n"); + interpreter->Insert(&data.rate, sizeof(GaugeRate)); + break; + + case typeModeMask: + Test_Tell("modeMask\n"); + interpreter->Insert(&data.modeMask, sizeof(ModeMask)); + break; + + case typeInteger: + Test_Tell("integer\n"); + interpreter->Insert(&data.integer, sizeof(int)); + break; + + case typeColor: + Test_Tell("color\n"); + interpreter->Insert(&data.color, sizeof(int)); + break; + + case typeScalar: + Test_Tell("scalar\n"); + interpreter->Insert(&data.scalar, sizeof(Scalar)); + break; + + case typeVector: + Test_Tell("vector\n"); + interpreter->Insert(&data.vector.x, sizeof(int)); + interpreter->Insert(&data.vector.y, sizeof(int)); + break; + + case typeRectangle: + Test_Tell("rectangle\n"); + interpreter->Insert(&data.rectangle.bottomLeft.x, sizeof(int)); + interpreter->Insert(&data.rectangle.bottomLeft.y, sizeof(int)); + interpreter->Insert(&data.rectangle.topRight.x, sizeof(int)); + interpreter->Insert(&data.rectangle.topRight.y, sizeof(int)); + break; + + case typeAttribute: + Test_Tell("attribute\n"); + Check_Pointer(data.string); + interpreter->InsertString(data.string); + break; + + case typeString: + Test_Tell("string\n"); + interpreter->InsertString(data.string); + break; + + default: + Fail("Illegal type"); + break; + } + Check_Fpu(); +} + +void + ParameterDescription::Restore( + GaugeInterpreter *interpreter, + Entity *entity + ) +{ + Check_Pointer(this); + Check(interpreter); + + Test_Tell("\nParameterDescription::Restore-"); + // + //---------------------------------------------------------------- + // Choose the appropriate type, read from interpreter table + //---------------------------------------------------------------- + // + switch(type) + { + case typeEmpty: + Fail("type == empty!"); + break; + + case typeRate: + data.rate = *(GaugeRate *)interpreter->Retrieve(sizeof(GaugeRate)); + Test_Tell("rate=" << std::hex << data.rate << std::dec << "\n"); + break; + + case typeModeMask: + data.modeMask = *(ModeMask *) + interpreter->Retrieve(sizeof(ModeMask)); + Test_Tell("modeMask=" << std::hex << data.modeMask << std::dec << "\n"); + break; + + case typeInteger: + data.integer = *(int *) (interpreter->Retrieve(sizeof(int))); + Test_Tell("integer=" << data.integer << "\n"); + break; + + case typeColor: + data.color = *(int *) (interpreter->Retrieve(sizeof(int))); + Test_Tell("color=" << data.color << "\n"); + break; + + case typeScalar: + data.scalar = *(Scalar *) (interpreter->Retrieve(sizeof(Scalar))); + Test_Tell("scalar=" << data.scalar << "\n"); + break; + + case typeVector: + data.vector.x = *(int*) interpreter->Retrieve(sizeof(int)); + data.vector.y = *(int*) interpreter->Retrieve(sizeof(int)); + Test_Tell("vector=(" << data.vector.x << "," << data.vector.y << ")\n"); + break; + + case typeRectangle: + data.rectangle.bottomLeft.x = *(int*) interpreter->Retrieve(sizeof(int)); + data.rectangle.bottomLeft.y = *(int*) interpreter->Retrieve(sizeof(int)); + data.rectangle.topRight.x = *(int*) interpreter->Retrieve(sizeof(int)); + data.rectangle.topRight.y = *(int*) interpreter->Retrieve(sizeof(int)); + Test_Tell( + "rectangle=((" << data.rectangle.bottomLeft.x << + "," << data.rectangle.bottomLeft.y << + "),(" << data.rectangle.topRight.x << + "," << data.rectangle.topRight.y << + "))\n" + ); + break; + + case typeAttribute: + { + const char + *string_pointer = interpreter->RetrieveString(); + + Verify(string_pointer != NULL); + Test_Tell("attribute=" << string_pointer << "\n"); + //-------------------------------------- + // Replace if variable name + //-------------------------------------- + string_pointer = interpreter->ReplaceVariable(string_pointer); + //-------------------------------------- + // Change into true attribute pointer + //-------------------------------------- + Check(entity); + data.attributePointer = ParseAttribute(string_pointer, entity); + Verify(data.attributePointer != NULL); + } + break; + + case typeString: + Test_Tell("string\n"); + { + // Get the string here INSTEAD of inside Str_Copy() because + // of side effects! (string_pointer is referenced multiple times) + const char + *string_pointer = interpreter->RetrieveString(); + //-------------------------------------- + // Replace if variable name + //-------------------------------------- + string_pointer = interpreter->ReplaceVariable(string_pointer); + + Test_Tell("string=" << string_pointer << "\n"); + Str_Copy( + data.string, + string_pointer, + maxStringLength-1 + ); + } + break; + + default: + Fail("Illegal type"); + break; + } + Check_Fpu(); +} + +void + ParameterDescription::DumpInterpreterEntry( + GaugeInterpreter *interpreter, + const char *indent + ) +{ + Check_Pointer(this); + Check(interpreter); + //---------------------------------------------------------------- + // Choose the appropriate type, read from interpreter table + //---------------------------------------------------------------- + DEBUG_STREAM << indent << std::flush; + + switch(type) + { + case typeEmpty: + DEBUG_STREAM << "***EMPTY***\n" << std::flush; + break; + + case typeRate: + { + GaugeRate + rate = *(GaugeRate *) + interpreter->Retrieve(sizeof(GaugeRate)); + DEBUG_STREAM << "rate " << rate << "\n" << std::flush; + } + break; + + case typeModeMask: + { + ModeMask + mask = *(ModeMask *) + interpreter->Retrieve(sizeof(ModeMask)); + DEBUG_STREAM << "mask " << mask << "\n" << std::flush; + } + break; + + case typeInteger: + { + int + i = *(int *) (interpreter->Retrieve(sizeof(int))); + DEBUG_STREAM << std::dec << "int " << i << "\n" << std::flush; + } + break; + + case typeColor: + { + int + i = *(int *) (interpreter->Retrieve(sizeof(int))); + DEBUG_STREAM << "color 0x" << i << "\n" << std::flush; + } + break; + + case typeScalar: + { + Scalar + s = *(int *) (interpreter->Retrieve(sizeof(Scalar))); + DEBUG_STREAM << std::dec << "scalar " << s << "\n" << std::flush; + } + break; + + case typeVector: + { + Vector2DOf + v; + + v.x = *(int *) (interpreter->Retrieve(sizeof(int))); + v.y = *(int *) (interpreter->Retrieve(sizeof(int))); + DEBUG_STREAM << std::dec << "vector " << v << "\n" << std::flush; + } + break; + + case typeRectangle: + { + Rectangle2D + r; + + r.bottomLeft.x = *(int *) (interpreter->Retrieve(sizeof(int))); + r.bottomLeft.y = *(int *) (interpreter->Retrieve(sizeof(int))); + r.topRight.x = *(int *) (interpreter->Retrieve(sizeof(int))); + r.topRight.y = *(int *) (interpreter->Retrieve(sizeof(int))); + DEBUG_STREAM << std::dec << "rectangle " << r << "\n" << std::flush; + } + break; + + case typeAttribute: + DEBUG_STREAM << "attribute '" << interpreter->RetrieveString() << "'\n" << std::flush; + break; + + case typeString: + DEBUG_STREAM << "string '" << interpreter->RetrieveString() << "'\n" << std::flush; + break; + + default: + DEBUG_STREAM << "ILLEGAL TYPE=" << type << "!!\n" << std::flush; + break; + } + Check_Fpu(); +} + +//############################################################################# +// MethodDescription +//############################################################################# +void + MethodDescription::ShowInstance(char *indent) +{ + Check_Pointer(this); + + DEBUG_STREAM << indent << "MethodDescription:\n" << std::flush; + + char + temp[80]; + int + i; + + DEBUG_STREAM << indent << "name =" << name << "\n" << std::flush; + DEBUG_STREAM << indent << "execute=" << execute << "\n" << std::flush; + + for(i=0; i position, + Entity *entity, + GaugeRenderer *renderer + ) +{ + Check_Pointer(this); + Check(renderer); + Check(renderer->interpreter); + int + i; + //------------------------------------------------------------- + // Restore the parameters from the interpreter table + //------------------------------------------------------------- + for (i=0; parameterList[i].type != ParameterDescription::typeEmpty; ++i) + { + parameterList[i].Restore(renderer->interpreter, entity); + } + //------------------------------------------------------------- + // Execute the call + //------------------------------------------------------------- + Check_Pointer(execute); +# if DEBUG_LEVEL > 0 + Logical + result = + (*execute)( + display_port_index, + position, + entity, + renderer + ); + Verify(result == True); +# else + (*execute)( + display_port_index, + position, + entity, + renderer + ); +# endif + Check_Fpu(); +} + +//####################################################################### +// GaugeRendererStatistics +//####################################################################### +void + GaugeRendererStatistics::Clear() +{ + sampleCount = 0; + sum = (Scalar) 0; + maximum = (Scalar) 0; + Check_Fpu(); +} + +void + GaugeRendererStatistics::Update(Scalar delta) +{ + ++sampleCount; + sum += delta; + if (maximum < delta) + { + maximum = delta; + } + Check_Fpu(); +} + +Scalar + GaugeRendererStatistics::CalculateAverage() +{ + Scalar + average; + + if (sampleCount <= 0) + { + average = (Scalar) 0; + } + else + { + average = (Scalar) (sum/sampleCount); + } + + Check_Fpu(); + return average; +} + +//############################################################################# +// GaugeRenderer +//############################################################################# +GaugeRenderer + *GaugeRenderer::headGaugeRenderer = NULL; + +GaugeRenderer::GaugeRenderer(): + Renderer( + application->GetApplicationLoopFrameRate(), + MaxRendererComplexity, // in renderer.cc (3.0f) + DefaultRendererPriority, // in renderer.hh (1) + GaugeInterestType, // in interest.hh + DefaultInterestDepth, // in interest.hh (1) + GaugeRendererClassID // in vdata.hh + ), + newList(NULL), + activeList(NULL), + inactiveList(NULL), + lampManager(NULL) // instantiated at topmost level only +{ + Test_Tell("GaugeRenderer::GaugeRenderer()\n"); + Check_Pointer(this); + + int + i; + + suspended = False; + previousModeMask = (ModeMask) 0; + //--------------------------------------------------------------------- + // Ensure that graphicsPort pointers are NULL + //--------------------------------------------------------------------- + for (i=0; i(activeList); + Register_Object(activeIterator); + //---------------------------------------------------- + // Clear load-balancing data + //---------------------------------------------------- + for(i=0; inextGaugeRenderer + ) + { + if (gauge_renderer == this) + { + // + // Found! head of list? + // + if (previous_gauge_renderer == NULL) + { + headGaugeRenderer = nextGaugeRenderer; + } + // + // Not head, remove from chain + // + else + { + previous_gauge_renderer->nextGaugeRenderer = + nextGaugeRenderer; + } + break; + } + // + // Keep track of 'previous' object + // + previous_gauge_renderer = gauge_renderer; + } + + Check_Fpu(); +} + +//=========================================================================== +// EmergencyShutdown +//=========================================================================== +void + GaugeRenderer::EmergencyShutdown() +{ + Test_Tell("GaugeRenderer::EmergencyShutdown()\n"); + + GaugeRenderer + *gauge_renderer; + + for( + gauge_renderer = headGaugeRenderer; + gauge_renderer != NULL; + gauge_renderer = gauge_renderer->nextGaugeRenderer + ) + { + gauge_renderer->LocalEmergencyShutdown(); + } +} + +//=========================================================================== +// LocalEmergencyShutdown +//=========================================================================== +void + GaugeRenderer::LocalEmergencyShutdown() +{ +} + +// +//=========================================================================== +// TestInstance +//=========================================================================== +// +Logical + GaugeRenderer::TestInstance() const +{ + //-------------------------------------------------------------------- + // Check the base renderer + //-------------------------------------------------------------------- + return Renderer::TestInstance(); +} + +// +//=========================================================================== +// LinkToEntity +//=========================================================================== +// +void + GaugeRenderer::LinkToEntity(Entity *entity) +{ + Check(this); + Check(entity); + + Test_Tell("GaugeRenderer::LinkToEntity(" << entity << ")\n"); + + // + //-------------------------------------------------------------------- + // Inform all gauges + //-------------------------------------------------------------------- + // + GaugeBase + *base_pointer; + + if (! suspended) + { + { + SChainIteratorOf + i(newList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->LinkToEntity(entity); + } + } + { + SChainIteratorOf + i(activeList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->LinkToEntity(entity); + } + } + { + SChainIteratorOf + i(inactiveList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->LinkToEntity(entity); + } + } + } + // + //-------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------- + // + Renderer::LinkToEntity(entity); + Check_Fpu(); +} + +// +//=========================================================================== +// NotifyOfNewInterestingEntity +//=========================================================================== +// +void + GaugeRenderer::NotifyOfNewInterestingEntity(Entity *entity) +{ + Test_Tell("GaugeRenderer::NotifyOfNewInterestingEntity\n"); + Check(this); + Check(entity); + + //------------------------------------------------------ + // This method used to update both the movingEntities + // and staticEntities records. That functionality has + // been moved up to the game-specific level (e.g., + // RPL4GaugeRenderer) to allow the game to determine + // what to show. Note that all descendents MUST chain + // back to this base method... + //------------------------------------------------------ + // + //-------------------------------------------------------------------- + // Inform all gauges + //-------------------------------------------------------------------- + // + GaugeBase + *base_pointer; + + if (! suspended) + { + { + SChainIteratorOf + i(newList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->NotifyOfNewInterestingEntity(entity); + } + } + { + SChainIteratorOf + i(activeList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->NotifyOfNewInterestingEntity(entity); + } + } + { + SChainIteratorOf + i(inactiveList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->NotifyOfNewInterestingEntity(entity); + } + } + } + Check_Fpu(); +} + + +// +//=========================================================================== +// NotifyOfBecomingUninterestingEntity +//=========================================================================== +// +void + GaugeRenderer::NotifyOfBecomingUninterestingEntity(Entity *entity) +{ + Test_Tell("GaugeRenderer::NotifyOfBecomingUninterestingEntity\n"); + Check(this); + Check(entity); + //------------------------------------------------------ + // This method used to update both the movingEntities + // and staticEntities records. That functionality has + // been moved up to the game-specific level (e.g., + // RPL4GaugeRenderer) to allow the game to determine + // what to show. Note that all descendents MUST chain + // back to this base method... + //------------------------------------------------------ + // + //-------------------------------------------------------------------- + // Inform all gauges + //-------------------------------------------------------------------- + // + GaugeBase + *base_pointer; + + if (! suspended) + { + { + SChainIteratorOf + i(newList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->NotifyOfBecomingUninterestingEntity(entity); + } + } + { + SChainIteratorOf + i(activeList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->NotifyOfBecomingUninterestingEntity(entity); + } + } + { + SChainIteratorOf + i(inactiveList); + + while ((base_pointer=i.ReadAndNext()) != NULL) + { + Check(base_pointer); + base_pointer->NotifyOfBecomingUninterestingEntity(entity); + } + } + } + Check_Fpu(); +} + +// +//=========================================================================== +// Entity alarms +//=========================================================================== +// +void + GaugeRenderer::StartEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID resource_ID + ) +{ + Check(this); + + Check(gaugeAlarmManager); + gaugeAlarmManager->Activate( + entity, + subsystem, + condition, + resource_ID + ); + Check_Fpu(); +} +void + GaugeRenderer::StopEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ) +{ + Check(this); + + Check(gaugeAlarmManager); + gaugeAlarmManager->Deactivate( + entity, + subsystem, + condition + ); + Check_Fpu(); +} + +// +//=========================================================================== +// LoadMissionImplementation +//=========================================================================== +// +void + GaugeRenderer::LoadMissionImplementation(Mission */*mission*/) +{ + Tell("GaugeRenderer::LoadMissionImplementation()\n"); + Check(this); + + +//DEBUG_STREAM << "Mover list has " << +// movingGaugeImages.NumberOfItems() << "items.\n"; +//staticGaugeImages.PrintStatistics(); + + + Check_Fpu(); +} + +// +//=========================================================================== +// ShutdownImplementation +//=========================================================================== +// +void + GaugeRenderer::ShutdownImplementation() +{ + Tell("GaugeRenderer::ShutdownImplementation()\n"); + Check(this); + + //-------------------------------------------------------------------- + // Turn off all gauge alarms + //-------------------------------------------------------------------- + if (gaugeAlarmManager != NULL) + { + Check(gaugeAlarmManager); + gaugeAlarmManager->RemoveAllAlarms(); + } + //-------------------------------------------------------------------- + // Delete all remaining gauges BEFORE clearing out the warehouse! + // ...otherwise the gauges will attempt to reference items which + // no longer exist in the warehouse... + //-------------------------------------------------------------------- + Remove(0); + //-------------------------------------------------------------------- + // Remove all lamps + //-------------------------------------------------------------------- + if (lampManager != NULL) + { + Check(lampManager); + lampManager->RemoveAllLamps(); + } + //-------------------------------------------------------------------- + // Clear out the warehouse + //-------------------------------------------------------------------- + if (warehousePointer != NULL) + { + Check(warehousePointer); + warehousePointer->Purge(); + } + //-------------------------------------------------------------------- + // Clear auxiliary data structures + //-------------------------------------------------------------------- + movingEntities.Clear(); + staticEntities.Clear(); + //--------------------------------------------------------------------- + // Destroy all graphicsPort objects + //--------------------------------------------------------------------- + int + i; + + for (i=0; iname << " "); + if (stricmp(graphicsPort[i]->name, port_name) == 0) + { + Test_Tell("<-Found\n"); + Check_Fpu(); + return i; + } + } + } + } + Check_Fpu(); + return -1; +} + +// +//=========================================================================== +// GetGraphicsPort +//=========================================================================== +// +GraphicsPort + *GaugeRenderer::GetGraphicsPort(const char * port_name) +{ + int i(FindGraphicsPort(port_name)); + + Check_Fpu(); + if (i >= 0) + { + return graphicsPort[i]; + } + return NULL; +} + +GraphicsPort + *GaugeRenderer::GetGraphicsPort(int port_number) +{ + Check_Fpu(); + if ((port_number >= 0) && (port_number < maximumGraphicsPorts)) + { + return graphicsPort[port_number]; + } + else + { + return NULL; + } +} + +// +//=========================================================================== +// Add +//=========================================================================== +// +void + GaugeRenderer::Add(GaugeBase *new_gauge) +{ + Tell("GaugeRenderer::Add(" << std::hex << new_gauge << std::dec << ")\n"); + Check(this); + // + // Don't call Check(new_gauge) here! + // The Gauge creator calls AddGauge before the gauge is fully built! + // + Check_Pointer(new_gauge); + //------------------------------------------------------------------------- + // Add to 'new' list + //------------------------------------------------------------------------- + newList.Add(new_gauge); + Check_Fpu(); +} + +// +//=========================================================================== +// Remove +//=========================================================================== +// +void + GaugeRenderer::Remove(unsigned int owner_ID) +{ + Tell("GaugeRenderer::Remove(" << owner_ID << ")\n"); + Check(this); + + GaugeBase + *the_base; + + //-------------------------------------------------- + // Search active list first + //-------------------------------------------------- + { + SChainIteratorOf + i(activeList); + //-------------------------------------------------- + // Process all matching gauges + //-------------------------------------------------- + while ((the_base=i.GetCurrent()) != NULL) + { + Check(the_base); + + if ((owner_ID == 0) || (the_base->ownerID == owner_ID)) + { + //----------------------------------------------- + // 'Flush' the gauge before deleting it + //----------------------------------------------- + the_base->Update(Gauge::gaugeRate_A); + //----------------------------------------------- + // Delete it + //----------------------------------------------- + i.Remove(); + Tell(the_base->identificationString << "\n" << flush); + Unregister_Object(the_base); + delete the_base; + } + else + { + i.Next(); + } + } + } + //-------------------------------------------------- + // Search inactive list second + //-------------------------------------------------- + { + SChainIteratorOf + i(inactiveList); + //-------------------------------------------------- + // Process all matching gauges + //-------------------------------------------------- + while ((the_base=i.GetCurrent()) != NULL) + { + Check(the_base); + + if ((owner_ID == 0) || (the_base->ownerID == owner_ID)) + { + //----------------------------------------------- + // Delete it + //----------------------------------------------- + i.Remove(); + Tell(the_base->identificationString << "\n" << flush); + Unregister_Object(the_base); + delete the_base; + } + else + { + i.Next(); + } + } + } + Check_Fpu(); +} + +// +//=========================================================================== +// Remove +//=========================================================================== +// +void + GaugeRenderer::Inactivate(GaugeBase *the_base) +{ + Tell("GaugeRenderer::Inactivate(" << std::hex << the_base << std::dec << ")\n"); + Check(this); + + GaugeBase + *the_other_base; + + //-------------------------------------------------- + // Search active list for the base + //-------------------------------------------------- + SChainIteratorOf + i(activeList); + + while ((the_other_base=i.GetCurrent()) != NULL) + { + Check(the_other_base); + + if (the_base == the_other_base) + { + //----------------------------------------------- + // Remove from this list, place in inactive list + //----------------------------------------------- + i.Remove(); + inactiveList.Add(the_base); + the_base->BecameInactive(); + break; + } + else + { + i.Next(); + } + } + Check_Fpu(); +} + +GaugeRate + GaugeRenderer::FindBestFirstTierRate() +{ + return Gauge::gaugeRate_B; // HACK -stubbed in +} + +GaugeRate + GaugeRenderer::FindBestSecondTierRate() +{ + return Gauge::gaugeRate_D; // HACK -stubbed in +} + +GaugeRate + GaugeRenderer::FindBestThirdTierRate() +{ + return Gauge::gaugeRate_H; // HACK -stubbed in +} + +GaugeRate + GaugeRenderer::FindBestFourthTierRate() +{ + return Gauge::gaugeRate_P; // HACK -stubbed in +} + +// +//=========================================================================== +// ExecuteImplementation +//=========================================================================== +// +void + GaugeRenderer::ExecuteImplementation( + RendererComplexity /*complexity*/, + RendererOrigin::InterestingEntityIterator */*iterator*/ + ) +{ + SET_GAUGE_RENDERER(); + Check(this); + + if (! suspended) + { + if (taskMode == foreground) + { + ExecuteForeground(); + } + } + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); +} + +void + GaugeRenderer::ExecuteForeground() +{ + + Check(this); + Check(activeIterator); + + //------------------------------------------------------------------- + // Get the current mode mask + //------------------------------------------------------------------- + Check(application); + Check(application->GetModeManager()); + ModeMask + current_mode_mask = application->GetModeManager()->GetModeMask(); + ModeMask + previous_mode_mask = application->GetModeManager()->GetPreviousModeMask(); + ModeMask + change_mode_mask = current_mode_mask ^ previous_mode_mask; // xor tells me what has changed + //------------------------------------------------------------------- + // Update lamp manager + //------------------------------------------------------------------- + if (lampManager != NULL) + { + Check(lampManager); + lampManager->Update(current_mode_mask); + } + //------------------------------------------------------------------- + // Move new gauges to active/inactive lists + //------------------------------------------------------------------- + { + SChainIteratorOf + i(newList); + GaugeBase + *base_pointer; + + while ((base_pointer=i.GetCurrent()) != NULL) + { + //------------------------------------- + // Always remove from 'new' list + //------------------------------------- + i.Remove(); + //------------------------------------- + // Place in appropriate list + //------------------------------------- + Check(base_pointer); + if (base_pointer->modeMask & current_mode_mask) + { + + // If not already flagged, or gauge's mode mask is always active, + // or the mode change affects us, place into active list + if (!(base_pointer->alreadyActivatedFlag) + // || (base_pointer->modeMask == ModeManager::ModeAlwaysActive) + || (base_pointer->modeMask & change_mode_mask)) + { + base_pointer->alreadyActivatedFlag = True; + //------------------------------------- + // Announce new status + //------------------------------------- + base_pointer->BecameActive(); + //------------------------------------- + // Place in active list only if legal + //------------------------------------- + if (base_pointer->stayInactive) + { + inactiveList.Add(base_pointer); + } + else + { + activeList.Add(base_pointer); + } + } + } + else + { + inactiveList.Add(base_pointer); + } + } + } + //--------------------------------------------------------------- + // If the modeMask has changed, update the active/inactive lists. + //--------------------------------------------------------------- + if (previousModeMask != current_mode_mask) + { + previousModeMask = current_mode_mask; + + ActivateGaugeBases(current_mode_mask,change_mode_mask); + DeactivateGaugeBases(current_mode_mask); + } + //--------------------------------------------------------------- + // Restart background processing + //--------------------------------------------------------------- + taskMode = background; + activeIterator->First(); + //-------------------------------- + // Reset rate bit mask if needed + //-------------------------------- + if (rateBitMask == 0) + { + rateBitMask = 0x8000; +# if defined (PROFILE_GAUGES) + rateProfileIndex = 0; +# endif + } + Check_Fpu(); +} + +// +//=========================================================================== +// ExecuteBackground +//=========================================================================== +// +Logical + GaugeRenderer::ExecuteBackground() +{ + SET_GAUGE_RENDERER(); + Check(this); + + Logical + result; + + Time start, end; + int oldTaskMode = taskMode; + + switch(taskMode) + { + case foreground: + result = ExecuteBackgroundDisplayUpdate(); // might as well update + break; + + case background: + { + result = ProcessOneActiveGauge(); + break; + } + + case copy: + result = ExecuteBackgroundDisplayUpdate(); + break; + } + + if (end.ticks - start.ticks > 100) + { + end = start; + } + + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); + return result; +} + +Logical + GaugeRenderer::ExecuteBackgroundDisplayUpdate() +{ + Check(this); + return False; +} + +// +//=========================================================================== +// ActivateGaugeBases +//=========================================================================== +// +void + GaugeRenderer::ActivateGaugeBases(ModeMask current_mode_mask, ModeMask change_mode_mask) +{ + Check(this); + //----------------------------------------------------------- + // Test the objects in the 'inactive' list. If any of them + // have bits in their modeMask corresponding to the + // new mode mask, move them to the 'active' list. + //----------------------------------------------------------- + SChainIteratorOf + i(inactiveList); + GaugeBase + *base_pointer; + + while ((base_pointer=i.GetCurrent()) != NULL) + { + Check(base_pointer); + //----------------------------------- + // Became active? + //----------------------------------- + if (base_pointer->modeMask & current_mode_mask) + { + if (!(base_pointer->alreadyActivatedFlag) + // || (base_pointer->modeMask == ModeManager::ModeAlwaysActive) + || (base_pointer->modeMask & change_mode_mask)) + { + #if 0 + DEBUG_STREAM << "Activating an inactive (not visible) gauge on inactive list" << endl << std::flush; + #endif + //----------------------------------- + // Inform object of new status + //----------------------------------- + base_pointer->BecameActive(); + base_pointer->alreadyActivatedFlag = True; + + + //----------------------------------- + // Move to 'active' list if allowed + //----------------------------------- + if (base_pointer->stayInactive) + { + i.Next(); + } + else + { + i.Remove(); + activeList.Add(base_pointer); + } + } + else + { + i.Next(); + } + } + else + { + //----------------------------------- + // No, try the next one + //----------------------------------- + i.Next(); + } + } + Check_Fpu(); +} + +// +//=========================================================================== +// DeactivateGaugeBases +//=========================================================================== +// +void + GaugeRenderer::DeactivateGaugeBases(ModeMask current_mode_mask) +{ + Check(this); + //--------------------------------------------------------------- + // Test the objects in the 'active' list. If any of them do NOT + // have bits in their modeMask corresponding to the new mode + // mask, move them to the 'inactive' list. + //--------------------------------------------------------------- + SChainIteratorOf + i(activeList); + GaugeBase + *base_pointer; + + while ((base_pointer=i.GetCurrent()) != NULL) + { + Check(base_pointer); + //----------------------------------- + // Became inactive? + //----------------------------------- + if (!(base_pointer->modeMask & current_mode_mask)) + { + base_pointer->alreadyActivatedFlag = False; + //----------------------------------- + // Yes, move to 'inactive' list + //----------------------------------- + i.Remove(); + inactiveList.Add(base_pointer); + + base_pointer->BecameInactive(); + + } + else + { + //----------------------------------- + // No, try the next one + //----------------------------------- + i.Next(); + } + } + Check_Fpu(); +} + +// +//=========================================================================== +// ProcessOneActiveGauge +//=========================================================================== +// +Logical + GaugeRenderer::ProcessOneActiveGauge() +{ + Check(this); + Check(activeIterator); + + Logical + result; + GaugeBase + *base_pointer = activeIterator->ReadAndNext(); + + if (base_pointer == NULL) + { + //-------------------------------------------------- + // We're done! + // Bump the bit mask and index for the next pass + //-------------------------------------------------- + rateBitMask >>= 1; +# if defined (PROFILE_GAUGES) + ++rateProfileIndex; +# endif + //-------------------------------------------------- + // Inform system that we are finished + //-------------------------------------------------- + taskMode = copy; + result = True; // Don't stop just yet! Go into third phase! + } + else + { + //-------------------------------------------------- + // Process one gauge + //-------------------------------------------------- + Check(base_pointer); +# if defined (PROFILE_GAUGES) + Scalar + delta = GetCurrentFramePercentage(); + + Logical + actually_ran = +# endif + base_pointer->Update(rateBitMask); + +# if defined (PROFILE_GAUGES) + delta = GetCurrentFramePercentage() - delta; + if (delta < (Scalar) 0) + { + // Hack - what does it REALLY mean when it's negative?!? + delta = - delta; + } + + if (actually_ran) + { + base_pointer->UpdateProfile(delta); + } + statistics[rateProfileIndex][base_pointer->DiscernTier()] + .Update(delta); +# endif + //-------------------------------------------------- + // Tell renderer manager that we have more to do + //-------------------------------------------------- + result = True; + } + return result; +} + +// +//=========================================================================== +// GetCurrentFramePercentage +//=========================================================================== +// +Scalar + GaugeRenderer::GetCurrentFramePercentage() +{ + Check(this); + return (Scalar) 0; +} + +enum +{ + average_bar, + maximum_bar +}; + +#if defined (PROFILE_GAUGES) + static Scalar + draw_bar( + GaugeRenderer *renderer, + int bar_width, + int slot_index, + int bar_type + ) + { + Check(renderer); + //------------------------------------ + // Show individual tier contributors + //------------------------------------ + Scalar + value, + total_value = (Scalar) 0; + Scalar + position = (Scalar) 0; + int + tier_index, + char_position = 0, + next_char_position; + + for(tier_index=0; tier_indexstatistics[slot_index][tier_index].CalculateAverage(); + break; + + case maximum_bar: + value= + renderer->statistics[slot_index][tier_index].maximum; + break; + } + //------------------------------------ + // Add to total + // Calculate next bar position + //------------------------------------ + total_value += value; + position += bar_width * value; + //------------------------------------ + // Limit it in case of overflow + //------------------------------------ + if (position > (Scalar) bar_width) + { + position = (Scalar) bar_width; + } + //------------------------------------ + // Draw with marker to next position + //------------------------------------ + next_char_position = (int) position; + + for( ; char_position < next_char_position; ++char_position) + { + DEBUG_STREAM << tier_marker << std::flush; + } + } + //------------------------------------ + // Fill unused space in bar + //------------------------------------ + for( ; char_position < bar_width; ++char_position) + { + DEBUG_STREAM << "." << std::flush; + } + + Check_Fpu(); + return total_value; + } +#endif + + +void + GaugeRenderer::ProfileReport() +{ + Check(this); + +# if defined (PROFILE_GAUGES) + //-------------------------------------------------------------- + // Show all gauges + //-------------------------------------------------------------- + { + SChainIteratorOf + i(activeList); + GaugeBase + *the_base; + + DEBUG_STREAM <<"Active name count avg worst\n" << std::flush; + DEBUG_STREAM <<"-------------------------------- ----- ------ -----\n" << std::flush; + while ((the_base=i.ReadAndNext()) != NULL) + { + Check(the_base); + the_base->ReportProfile(); + } + } + { + SChainIteratorOf + i(inactiveList); + GaugeBase + *the_base; + + DEBUG_STREAM <<"Inactive name count avg worst\n" << std::flush; + DEBUG_STREAM <<"-------------------------------- ----- ------ -----\n" << std::flush; + while ((the_base=i.ReadAndNext()) != NULL) + { + Check(the_base); + the_base->ReportProfile(); + } + } + //-------------------------------------------------------------------- + // Dump profiling data + //-------------------------------------------------------------------- + int + slot_index, + tier_index, + bar_width = 40; // total width of bar graph + char + buffer[80]; + //------------------------------------ + // Print header bar + //------------------------------------ + DEBUG_STREAM << "\nSlot|Count|Tier values " << std::flush; + DEBUG_STREAM << "|Total %\n" << std::flush; + DEBUG_STREAM << "----+-----+" << std::flush; + { + for(int i=0; iInitialize(file_name, method_description, warehousePointer); + //----------------------------------------------- + // Execute app initialization call, if it exists + //----------------------------------------------- + Configure("Initialization", NULL); + Check_Fpu(); +} + +void + GaugeRenderer::Configure( + const char *label, + Entity *entity + ) +{ + Test_Tell( + "GaugeRenderer::Configure('" << label << + "', " << entity << + ")\n" + ); + Check(this); + Check_Pointer(label); + + Vector2DOf + position; + + position.x = 0; + position.y = 0; + Check(interpreter); + interpreter->Interpret(label, this, 0, position, entity); + + Check_Fpu(); +} diff --git a/MUNGA/GAUGREND.h b/MUNGA/GAUGREND.h new file mode 100644 index 0000000..e433c37 --- /dev/null +++ b/MUNGA/GAUGREND.h @@ -0,0 +1,710 @@ +#pragma once + +#if defined(TRACE_GUAUGE_RENDERER) + extern BitTrace Gauge_Renderer; + #define SET_GUAGE_RENDERER() Gauge_Renderer.Set() + #define CLEAR_GUAGE_RENDERER() Gauge_Renderer.Clear() +#else + #define SET_GAUGE_RENDERER() + #define CLEAR_GAUGE_RENDERER() +#endif + +class GaugeSymbol; +class GaugeSymbolTable; +class GaugeInterpreter; +struct ParameterDescription; +struct MethodDescription; +class GaugeRenderer; +class LampManager; + +#include +#include "renderer.h" +#include "gaugalrm.h" +#include "resource.h" +#include "gaugmap.h" +#include "gauge.h" +#include "lamp.h" +#include "wrhous.h" + +struct LookupTable +{ + const + char *typeString; + int + value; + + int + Search(const char *string); +}; + +//####################################################################### +// Interpreter +//####################################################################### +typedef unsigned char GaugeInterpreterCommand; +typedef int GaugeInterpreterOffset; + +class GaugeSymbol SIGNATURED +{ + friend class GaugeSymbolTable; + friend class GaugeInterpreter; +public: + ~GaugeSymbol(); // WARNING - do NOT destroy individual entries! + // This implementation assumes that once a symbol + // is defined, it exists until ALL symbols are + // destroyed: this allows a very simple singly- + // linked-list structure. + // Deleting an entry WILL corrupt the list. + Logical + TestInstance() const; +protected: + GaugeSymbol( + GaugeSymbol **head_pointer, + const char *label, + GaugeInterpreterOffset offset, + Logical resolved + ); + + char + label[32]; + GaugeInterpreterOffset + offset; + Logical + resolved; + GaugeSymbol + *nextSymbol; +}; + +class GaugeSymbolTable SIGNATURED +{ + friend class GaugeInterpreter; +public: + enum + { + errUnresolvedForwardReference = -2, + errUndefinedSymbol = -3 + }; + + ~GaugeSymbolTable(); + Logical + TestInstance() const; +protected: + GaugeSymbolTable(char *table_pointer); + + void + Add(const char *label, GaugeInterpreterOffset offset); + GaugeInterpreterOffset + Refer(const char *label, GaugeInterpreterOffset offset); + GaugeInterpreterOffset + Get(const char *label); + const char * + LabelFromValue(GaugeInterpreterOffset offset); + Logical + UnresolvedForwardReferences(); + + GaugeSymbol + *head; + char + *tablePointer; +}; + +class GaugeInterpreter SIGNATURED +{ + friend struct MethodDescription; + friend class GaugeRenderer; +public: + ~GaugeInterpreter(); + Logical + TestInstance() const; + const char * + GetToken(); + void + UngetPreviousToken(); + Logical + GetInteger(int *int_pointer); + Logical + GetScalar(Scalar *scalar_pointer); + Logical + GetVector(Vector2DOf *vector); + Logical + GetRate(GaugeRate *rate); + Logical + GetModeMask(ModeMask *mode_mask_pointer); + const char * + ReplaceVariable(const char *possible_variable_name); + void + DumpTable(); + +protected: + GaugeInterpreter(); + + void + Initialize( + const char *file_name, + MethodDescription **method_list, + Warehouse *warehouse_pointer + ); + + void + GetProcedureBody( + MethodDescription **method_list, + Warehouse *warehouse_pointer + ); + + void + ReportParsingError( + const char *string + ); + + Logical + ParsePrimitive( + const char *name, + MethodDescription **method_list, + Warehouse *warehouse_pointer + ); + +public: + void + Insert(const void *value, int size_in_chars); + void * + Retrieve(int size_in_chars); + void + InsertString(const char *string); + const char * + RetrieveString(); + +protected: + void + Interpret( + const char *label, + GaugeRenderer *renderer, + int display_port_index, + Vector2DOf position, + Entity *entity + ); + + void + InterpretFromOffset( + GaugeInterpreterOffset offset, + GaugeRenderer *renderer, + int display_port_index, + Vector2DOf position, + Entity *entity + ); + + enum + { + endMarker=0, + returnCommand, + setPortIndexCommand, + addOffsetCommand, + callCommand, + enableCommand, + disableCommand, + attributeVariableCommand, + nextAvailableCommand + }; + + enum + { + interpreterTableSize = 46864 + }; + + enum + { + maxVariableNameArrayIndex = 10 + }; + + std::filebuf file; + char currentToken[64]; + Logical tokenNotTaken; + int lineNumber; + + GaugeSymbolTable *symbolTable; + MethodDescription **primitiveTable; + int primitiveCount; + char *interpreterTable; + GaugeInterpreterOffset currentOffset; + const char *attributeNameArray[maxVariableNameArrayIndex]; +}; + +//####################################################################### +// ParameterDescription +//####################################################################### +# define PARAMETER_DESCRIPTION_END \ + { ParameterDescription::typeEmpty, NULL } +struct ParameterDescription +{ + enum ParameterType + { + typeEmpty = 0, + typeRate, + typeModeMask, + typeInteger, + typeColor, + typeScalar, + typeVector, + typeRectangle, + typeAttribute, + typeString + }; + + ParameterType + type; + enum + { + maxStringLength=64 + }; + + union + { + // 'nextMethodList' is used to chain to the next method list... + MethodDescription **nextMethodList; + GaugeRate rate; + ModeMask modeMask; + int integer; + int color; + Scalar scalar; + BitMap *bitmap; + PixelMap8 *pixelmap; + Palette8 *palette; + void *attributePointer; + + // can't use Vector2DOf because constructor not allowed here! + struct + { + int x, y; + } + vector; + + // can't use Rectangle2D because constructor not allowed here! + struct + { + struct + { + int x, y; + } + bottomLeft; + + struct + { + int x, y; + } + topRight; + } + rectangle; + + char string[maxStringLength]; + } + data; + + ~ParameterDescription(); + + void + ShowInstance(char *indent); + void + CheckIt(int type); + void + Save(GaugeInterpreter *interpreter); + void + Restore( + GaugeInterpreter *interpreter, + Entity *entity + ); + void + DumpInterpreterEntry( + GaugeInterpreter *interpreter, + const char *indent + ); + void * + ParseAttribute(const char *string_pointer, Entity *entity); + Logical + Extract( + GaugeInterpreter *interpreter, + Warehouse *warehouse_pointer + ); +}; + +//####################################################################### +// MethodDescription +//####################################################################### +# define METHOD_DESCRIPTION_CHAIN(pointer) \ + {NULL, NULL, {{ ParameterDescription::typeEmpty, pointer }}} + +struct MethodDescription +{ + enum + { + MaximumParameters = 16 + }; + + char + *name; + + Logical + (*execute)( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer *renderer + ); + + ParameterDescription + parameterList[MaximumParameters]; + + void + ShowInstance(char *indent); + void + Execute( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer *renderer + ); +}; + +//####################################################################### +// GaugeRenderer +//####################################################################### +struct GaugeRendererStatistics +{ + int + sampleCount; + Scalar + sum, + maximum; + + void + Clear(), + Update(Scalar delta); + Scalar + CalculateAverage(); +}; + + +class GaugeRenderer: + public Renderer +{ + friend class Gauge; + friend class GaugeInterpreter; + friend Scalar draw_bar( + GaugeRenderer *renderer, + int bar_width, + int slot_index, + int bar_type + ); +public: + enum + { + maximumGraphicsPorts = 16 + }; + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + GaugeRenderer(); + ~GaugeRenderer(); + + static void + EmergencyShutdown(); + + virtual void + LocalEmergencyShutdown(); + + Logical + TestInstance() const; + + LampManager* + GetLampManager() + { + Check(this); + Check_Fpu(); + return lampManager; + } + + //-------------------------------------------------------------------- + // Entity-related methods + // + // These are virtual functions defined by the Renderer class. + // Derived classes call these methods if the derived class + // doesn't do anything special about the entity. + //-------------------------------------------------------------------- + void + LinkToEntity(Entity *entity); + void + NotifyOfNewInterestingEntity(Entity *entity); + void + NotifyOfBecomingUninterestingEntity(Entity *entity); + void + StartEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID resource_ID + ); + void + StopEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ); + //-------------------------------------------------------------------- + // LoadMissionImplementation + // ShutdownImplementation + // SuspendImplementation + // ResumeImplementation + // + // These are virtual functions defined by the Renderer class. + // Derived classes must call these methods. + //-------------------------------------------------------------------- + void + LoadMissionImplementation(Mission *mission); + void + ShutdownImplementation(); + void + SuspendImplementation(); + void + ResumeImplementation(); + + + //-------------------------------------------------------------------- + // Video effects + // HACK!!!!!!!! + // Quick and dirty hack to allow calling L4GaugeRenderer::SpecialEffect + // from non L4 level. GDU 2/28/96 + //-------------------------------------------------------------------- +public: + enum VideoEffectType + { + scrambleVideo + }; + + virtual void + SpecialEffect(VideoEffectType type, Scalar duration) {}; + + // + //-------------------------------------------------------------------- + // GetGraphicsPort + //-------------------------------------------------------------------- + // + int + FindGraphicsPort(const char * port_name); + + GraphicsPort + *GetGraphicsPort(const char *port_name); + + GraphicsPort + *GetGraphicsPort(int port_number); + + // + //-------------------------------------------------------------------- + // GaugeEntityList operations + //-------------------------------------------------------------------- + // + int + GetMovingEntities( + GaugeEntityList *destination_list + ) + { + return movingEntities.CopyEntities( + destination_list + ); + } + + int + GetMovingEntitiesWithinBounds( + GaugeEntityList *destination_list, + Scalar minX, + Scalar minY, + Scalar minZ, + Scalar maxX, + Scalar maxY, + Scalar maxZ + ) + { + return movingEntities.CopyEntitiesWithinBounds( + destination_list, + minX, minY, minZ, + maxX, maxY, maxZ + ); + } + + int + GetStaticEntities( + GaugeEntityList *destination_list + ) + { + return staticEntities.CopyEntities( + destination_list + ); + } + int + GetStaticEntitiesWithinBounds( + GaugeEntityList *destination_list, + Scalar minX, + Scalar minY, + Scalar minZ, + Scalar maxX, + Scalar maxY, + Scalar maxZ + ) + { + return staticEntities.CopyEntitiesWithinBounds( + destination_list, + minX, minY, minZ, + maxX, maxY, maxZ + ); + } + void + GetStaticBounds( + Scalar *min_x, + Scalar *min_y, + Scalar *min_z, + Scalar *max_x, + Scalar *max_y, + Scalar *max_z + ) + { + staticEntities.GetBounds( + min_x, min_y, min_z, + max_x, max_y, max_z + ); + } + // + //-------------------------------------------------------------------- + // Configure + //-------------------------------------------------------------------- + // + virtual void + Configure( + const char *configuration_name, + Entity *entity + ); + + int + parseConfigurationLine( + const char *entry, + char *buffer, + char **item_pointer, + int max_items + ); + + //-------------------------------------------------------------------- + // Gauge methods + //-------------------------------------------------------------------- + void + Add(GaugeBase *new_base), + Remove(unsigned int ownerID), + Inactivate(GaugeBase *the_base); + + GaugeRate + FindBestFirstTierRate(), + FindBestSecondTierRate(), + FindBestThirdTierRate(), + FindBestFourthTierRate(); + //-------------------------------------------------------------------- + // ExecuteImplementation + //-------------------------------------------------------------------- +protected: + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + +public: + Logical + ExecuteBackground(); + +protected: + void + ActivateGaugeBases(ModeMask current_mode_mask, ModeMask change_mode_mask), + DeactivateGaugeBases(ModeMask current_mode_mask); + Logical + ProcessOneActiveGauge(); + virtual void + ExecuteForeground(); + virtual Logical + ExecuteBackgroundDisplayUpdate(); + //-------------------------------------------------------------------- + // Profiling support + //-------------------------------------------------------------------- +protected: + virtual Scalar + GetCurrentFramePercentage(); +public: + void + ProfileReport(); + //-------------------------------------------------------------------- + // Configuration parsing methods + //-------------------------------------------------------------------- +protected: + void + BuildConfigurationFile( + const char *file_name, + MethodDescription **method_description + ); + //-------------------------------------------------------------------- + // Public data + //-------------------------------------------------------------------- +public: + Warehouse + *warehousePointer; + GaugeInterpreter + *interpreter; + + int GetTaskMode() { return taskMode; } + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- +protected: + GraphicsPort *graphicsPort[maximumGraphicsPorts]; + GaugeEntityList movingEntities; + GaugeEntityArray staticEntities; + LampManager *lampManager; + GaugeAlarmManager *gaugeAlarmManager; + + enum + { + foreground, + background, + copy + } + taskMode; + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + ModeMask + previousModeMask; + SChainOf + newList, + activeList, + inactiveList; + SChainIteratorOf + *activeIterator; + Logical + suspended; + GaugeRate + rateBitMask; + int + rateProfileIndex; + static GaugeRenderer + *headGaugeRenderer; + GaugeRenderer + *nextGaugeRenderer; + //----------------------------------- + // Load-balancing data and profiling + //----------------------------------- + enum + { + slotCount = 16, + tierCount=5 + }; + + Scalar + load[slotCount]; + GaugeRendererStatistics + statistics[slotCount][tierCount]; +}; diff --git a/MUNGA/GRAPH2D.cpp b/MUNGA/GRAPH2D.cpp new file mode 100644 index 0000000..7a40d6e --- /dev/null +++ b/MUNGA/GRAPH2D.cpp @@ -0,0 +1,3103 @@ +#include "munga.h" +#pragma hdrstop + +#include "graph2d.h" +#include "notation.h" +#include "namelist.h" + +//#define DEBUG + +struct PCXHeader +{ + Byte manufacturer; + Byte version; + Byte encoding; + Byte bitsPerPixel; + Word xMin, yMin; + Word xMax, yMax; + Word hRes, vRes; + Byte palette16[48]; + Byte reserved; + Byte colorPlanes; + Word bytesPerLine; + Word paletteType; + Byte filler[58]; +}; + +Logical + PCXRead( + const char *file_name, + PCXHeader *header, + Byte **body_ptr, + Byte *palette_ptr + ) +{ + FILE + *fp; + + Check_Pointer(file_name); + Verify(header != NULL); + + fp = fopen(file_name, "rb"); + if (fp == NULL) + { + Tell( "PCXRead: Cannot open file '" << file_name << "'\n"); + return False; + } + if (fread (header, sizeof(PCXHeader), 1, fp) != 1) + { + Tell("PCXRead: Cannot read header from '" << file_name << "'\n"); + fclose(fp); + return False; + } + if ( + (header->manufacturer != 0x0A) || // flags 'PCX'-type file + (header->bitsPerPixel != 8) || // we require standard 8-bit + (header->encoding != 1) || // PCX is always encoded + (header->colorPlanes != 1) // 256-color ONLY!!! + ) + { + Tell("PCXRead: '" << file_name << + " 'either not a PCX file, or the wrong type!\n"); + fclose(fp); + return False; + } + + int + data_width(header->bytesPerLine), + width(header->xMax-header->xMin+1), + height(header->yMax-header->yMin+1), + x, + x2, + y, + count; + + Byte + *dest; + + Byte + c; + + + if (body_ptr == NULL) + { + fseek(fp, -769, SEEK_END); // seek to beginning of palette + } + else + { + if (*body_ptr != NULL) + { + Unregister_Pointer(*body_ptr); + delete *body_ptr; + *body_ptr = NULL; + } + *body_ptr = new Byte[width*height]; + Register_Pointer(*body_ptr); + + dest = *body_ptr; + for(y=height; y>0; --y) + { + x2 = width; + for (x=data_width; x > 0; ) + { + c = (Byte) fgetc(fp); + + if (ferror(fp)) + { + Tell("PCXRead: File error reading '" << file_name << "'\n"); + fclose(fp); + Unregister_Pointer(*body_ptr); + delete *body_ptr; + *body_ptr = NULL; + return False; + } + + if ((c & 0xC0) == 0xC0) + { + count = c & 0x3F; + x -= count; + c = (Byte) fgetc(fp); + + while (count--) + { + if (x2 > 0) + { + --x2; + *dest++ = c; + } + } + } + else + { + if (x2 > 0) + { + --x2; + *dest++ = c; + } + --x; + } + } + } + } + + if (palette_ptr != NULL) + { + Byte + identifier; + + if (fread (&identifier, 1, 1, fp) != 1) + { + Tell("PCXRead: Cannot read palette from '" << file_name << "'\n"); + fclose(fp); + return False; + } + + if (identifier != 0x0C) + { + Tell("PCXRead: Invalid palette in '" << file_name << "'\n"); + fclose(fp); + return False; + } + + if (fread (palette_ptr, (256*3), 1, fp) != 1) + { + Tell("PCXRead: Cannot read palette from '" << file_name << "'\n"); + fclose(fp); + Check_Fpu(); + return False; + } + } + + fclose(fp); + Check_Fpu(); + return True; +} + + +//######################################################################## +//################################ BitMap ################################ +//######################################################################## +BitMap * + BitMap::Make(const char *name) +{ + Check_Pointer(name); + + char + file_name[80]; + + Str_Copy(file_name, "gauge\\", sizeof(file_name)); + Str_Cat(file_name, name, sizeof(file_name)); + + BitMap + *bitmap = new BitMap(file_name); + Check_Pointer(bitmap); + if (bitmap->Data.MapPointer == NULL) + { + delete bitmap; + bitmap = NULL; + } + else + { + Check(bitmap); + } + Check_Fpu(); + return bitmap; +} + +BitMap * + BitMap::Make(ResourceDescription::ResourceID /*new_resource_id*/) +{ + Check_Fpu(); + return NULL; // not yet 'resourcified' +} + +BitMap::BitMap(int width, int height) +{ + Check_Pointer(this); + Verify(width >0); + Verify(height >0); + + Data.WidthInWords = (width+15)>>4; + + Data.MapPointer = new Word[Data.WidthInWords*height]; + Register_Pointer(Data.MapPointer); + Data.Size.x = width; + Data.Size.y = height; + Check_Fpu(); +} + +BitMap::BitMap(int width, int height, Word *body) +{ + Check_Pointer(this); + Check_Pointer(body); + + Data.WidthInWords = 0; + Data.Size.x = 0; + Data.Size.y = 0; + + if (width > 0) + { + if (height > 0) + { + int + word_width = (width+15)>>4; + + Data.MapPointer = new Word[word_width * height]; + Register_Pointer(Data.MapPointer); + Data.WidthInWords = word_width; + Data.Size.x = width; + Data.Size.y = height; + + Mem_Copy( + Data.MapPointer, + body, + word_width * height * sizeof(Word), + word_width * height * sizeof(Word) + ); + } +# if DEBUG_LEVEL > 0 + else + { + Warn("BitMap::BitMap has illicit height"); + } +# endif + } +# if DEBUG_LEVEL > 0 + else + { + Warn("BitMap::BitMap has illicit width"); + } +# endif + Check_Fpu(); +} + +BitMap::BitMap(const char *file_name) +{ + Check_Pointer(file_name); + + PCXHeader + header; + Byte + *temp(NULL); + + Data.WidthInWords = 0; + Data.Size.x = 0; + Data.Size.y = 0; + Data.MapPointer = NULL; + + if (PCXRead(file_name, &header, &temp, NULL) == True) + { + if (temp != NULL) + { + Data.Size.x = header.xMax - header.xMin + 1; + Data.Size.y = header.yMax - header.yMin + 1; + Data.WidthInWords = (Data.Size.x + 15) >> 4; + Data.MapPointer = new Word[Data.WidthInWords * Data.Size.y]; + Check_Pointer(Data.MapPointer); + Register_Pointer(Data.MapPointer); + + Byte + *source(temp); + Word + *dest(Data.MapPointer); + Word + bits(0), + bitmask(0x8000); + int + x, + y; + for (y=Data.Size.y; y>0; --y) + { + for (x=Data.Size.x; x>0; --x) + { + if (*source++ != 0) + { + bits |= bitmask; + } + bitmask >>= 1; + if (bitmask == 0) + { + *dest++ = bits; + bitmask = 0x8000; + bits = 0; + } + } + + if (bitmask != 0x8000) + { + *dest++ = bits; + bitmask = 0x8000; + bits = 0; + } + } + Unregister_Pointer(temp); + delete temp; + } + } + Check_Fpu(); +} + +BitMap::BitMap(NotationFile *notation_file, const char *page_name) +{ + Check_Pointer(this); + Check(notation_file); + Check_Pointer(page_name); + + int + x, + y, + width_in_words; + + //----------------------------------------- + // Render bitmap benign in case of failure + //----------------------------------------- + Data.Size.x = 0; + Data.Size.y = 0; + Data.WidthInWords = 0; + Data.MapPointer = NULL; + //-------------------------------------------- + // Attempt to read the x, y, and width values + //-------------------------------------------- + if (!notation_file->GetEntry(page_name, "x", &x)) + { + Warn("BitMap::BitMap notation file: 'x' not found!\n"); + return; + } + Verify(x > 0); + + if (!notation_file->GetEntry(page_name, "y", &y)) + { + Warn("BitMap::BitMap notation file: 'y' not found!\n"); + return; + } + Verify(y > 0); + + if (!notation_file->GetEntry(page_name, "width", &width_in_words)) + { + Warn("BitMap::BitMap notation file: 'width' not found!\n"); + return; + } + //Tell("BitMap::BitMap x=" << x << ", y=" << y << ", width_in_words=" << width_in_words << "\n"); + Verify(x <= (width_in_words << 4)); + + //-------------------------------------------- + // Attempt to allocate the map + //-------------------------------------------- + Data.MapPointer = new Word[width_in_words * y]; + Register_Pointer(Data.MapPointer); + //-------------------------------------------- + // So far, so good! Save the values + //-------------------------------------------- + Data.Size.x = x; + Data.Size.y = y; + Data.WidthInWords = width_in_words; + //-------------------------------------------- + // Read the map data + //-------------------------------------------- + NameList *lines = + notation_file->MakeEntryList(page_name); + Check(lines); + Register_Object(lines); + + NameList::Entry + *line_entry; + const char + *text; + int + collect = 0, + nybble, + nybble_count = 4; + Word + *destination = Data.MapPointer; + + //-------------------------------------------- + // Collect all the entries in the page + //-------------------------------------------- + for ( + line_entry = lines->GetFirstEntry(); + line_entry != NULL; + line_entry = line_entry->GetNextEntry() + ) + { + //-------------------------------------------- + // Get the entry name + //-------------------------------------------- + if ((text=line_entry->GetName()) != NULL) + { + //-------------------------------------------- + // Process only if it's a 'bitmap' entry + //-------------------------------------------- + if (strcmp(text, "bitmap") == 0) + { + //-------------------------------------------- + // Get the entry text + //-------------------------------------------- + text=line_entry->GetChar(); + Verify(text != NULL); + //-------------------------------------------- + // Parse the 'bitmap' entry + //-------------------------------------------- + for ( ; *text != '\0'; ++text) + { + //-------------------------------------------- + // Convert char to hex nybble + //-------------------------------------------- + nybble = toupper(*text); + Verify(isxdigit(nybble)); + + if (nybble > '9') + { + nybble -= ('A' - '9' - 1); + } + nybble -= '0'; + //-------------------------------------------- + // Collect in a word + //-------------------------------------------- + collect = (collect << 4) + nybble; + //-------------------------------------------- + // If a full word is collected, save it + //-------------------------------------------- + --nybble_count; + if (nybble_count <= 0) + { + //-------------------------------------------- + // Verify that we've not gone too far + //-------------------------------------------- + if ((destination-Data.MapPointer) >= (width_in_words*y)) + { + Tell("BitMap::BitMap(notation file) attempted overrun"); + break; + } + //-------------------------------------------- + // Save it, set up for next word + //-------------------------------------------- + *destination++ = (Word) collect; + nybble_count = 4; + collect = 0; + } + } + } + } + } + Unregister_Object(lines); + delete lines; + //-------------------------------------------- + // Make sure we collected the proper + // amount of data- + //-------------------------------------------- +// Verify(nybble_count == 4); +// Verify(word_count == 0); + Check_Fpu(); +} + +BitMap::~BitMap() +{ + Check(this); + + if (Data.MapPointer != NULL) + { + Unregister_Pointer(Data.MapPointer); + delete Data.MapPointer; + Data.Size.x = 0; // safety code + Data.Size.y = 0; + Data.MapPointer = NULL; + } + Check_Fpu(); +} + +Logical + BitMap::TestInstance() const +{ + Verify(Data.Size.x > 0); + Verify(Data.Size.x < 8192); // unreasonably large + Verify(Data.Size.y > 0); + Verify(Data.Size.y < 8192); // unreasonably large + Verify(Data.WidthInWords == ((Data.Size.x + 15) >> 4)); + Check_Pointer(Data.MapPointer); + Check_Fpu(); + return True; +} + +void + BitMap::ShowInstance(char * indent) +{ + Check(this); + + std::cout << indent << "BitMap:\n"; + char + temp[80]; + + Str_Copy(temp, indent, 80); + Str_Cat(temp, "...", 80); + + std::cout << temp << "Size =" << Data.Size << "\n"; + std::cout << temp << "WidthInWords=" << Data.WidthInWords << "\n"; + std::cout << temp << "MapPointer =" << (void *) Data.MapPointer << "\n"; + std::cout << std::flush; + + if (Data.MapPointer != NULL) + { + int + x, + y, + bits, + bitmask, + bitwidth; + + Word + *source((Word *) Data.MapPointer); + + for(y=Data.Size.y; y>0; y--) + { + std::cout << temp; + bitwidth=0; + for(x=Data.WidthInWords; x>0; --x) + { + bits = *source++; + + for(bitmask=0x8000; bitmask!=0; bitmask>>=1) + { + if (++bitwidth > Data.Size.x) + { + std::cout << "-"; + } + else if (bits & bitmask) + { + std::cout <<"#"; + } + else + { + std::cout <<" "; + } + } + } + std::cout << "\n"; + } + std::cout << "\n"; + } + Check_Fpu(); +} + +//######################################################################## +//############################### Palette8 ############################### +//######################################################################## + +// +//------------------------------------------------------------------------ +// Output stream operator +//------------------------------------------------------------------------ +// +std::ostream& operator<<(std::ostream& Stream, const PaletteTriplet& p) +{ + Check_Fpu(); + return Stream << std::hex << + (((int) p.Red) & 0xFF) << ':' << + (((int) p.Green) & 0xFF) << ':' << + (((int) p.Blue) & 0xFF) << std::dec; +} + +Palette8::Palette8() +{ + Check_Pointer(this); + Valid = False; + Check_Fpu(); +} + +Palette8 * + Palette8::Make(const char *name) +{ + Check_Pointer(name); + + char + file_name[80]; + + Str_Copy(file_name, "gauge\\", sizeof(file_name)); + Str_Cat(file_name, name, sizeof(file_name)); + + + Palette8 + *palette = new Palette8(file_name); + Check_Pointer(palette); + if (!palette->Valid) + { + delete palette; + palette = NULL; + } + Check_Fpu(); + return palette; +} + +Palette8 * + Palette8::Make(ResourceDescription::ResourceID /*new_resource_id*/) +{ + Check_Fpu(); + return NULL; // not yet 'resourcified' +} + + + +Palette8::Palette8(int count, PaletteTriplet *source) +{ + Check_Pointer(this); + + int + i; + + Check_Pointer(source); + Verify(count > 0); + Verify(count <= 256); + + for(i=0; i= 0); + Verify(end < 256); + Verify(start <= end); + + for( ; start <= end; ++start) + { + Color[start] = new_color; + } + Check_Fpu(); +} + +void + Palette8::BuildColorRange( + int start, + int end, + PaletteTriplet first_color, + PaletteTriplet last_color + ) +{ + Check(this); + + int + range, + rate_red, + rate_green, + rate_blue, + accum_red, + accum_green, + accum_blue; + + Verify(start >= 0); + Verify(end < 256); + Verify(start <= end); + + range = end - start; + + if (range == 0) + { + Color[start] = first_color; + } + else + { + rate_red = (((int)(last_color.Red - first_color.Red) ) << 5)/range; + rate_green = (((int)(last_color.Green - first_color.Green)) << 5)/range; + rate_blue = (((int)(last_color.Blue - first_color.Blue) ) << 5)/range; + + accum_red = ((int)first_color.Red) << 5; + accum_green = ((int)first_color.Green) << 5; + accum_blue = ((int)first_color.Blue) << 5; + + for( ; start<=end; ++start) + { + Color[start].Red = (Byte) (accum_red >> 5); + Color[start].Green = (Byte) (accum_green >> 5); + Color[start].Blue = (Byte) (accum_blue >> 5); + + accum_red += rate_red; + accum_green += rate_green; + accum_blue += rate_blue; + } + } + Check_Fpu(); +} + +Logical + Palette8::TestInstance() const +{ + return True; +} + +void + Palette8::ShowInstance(char *indent) +{ + Check(this); + + char + temp[80], + buffer[32]; + PaletteTriplet + *source; + int + x, + y; + + std::cout << indent << "Palette8:\n"; + + Str_Copy(temp, indent, 80); + Str_Cat(temp, "...", 80); + + std::cout << temp << "Valid =" << Valid << "\n"; + + if (Valid) + { + source = Color; + for(y=0; y<256; y+=4) + { + sprintf(buffer, "%02X= ", y); + std::cout << temp << buffer; + + for(x=4; x>0; --x) + { + std::cout << *source++ << " "; + } + std::cout << "\n"; + } + } + Check_Fpu(); +} + +//######################################################################## +//############################## PixelMap8 ############################### +//######################################################################## +PixelMap8 * + PixelMap8::Make(const char *name) +{ + Check_Pointer(name); + + char + file_name[80]; + + Str_Copy(file_name, "gauge\\", sizeof(file_name)); + Str_Cat(file_name, name, sizeof(file_name)); + + PixelMap8 + *pixelmap = new PixelMap8(file_name); + Check_Pointer(pixelmap); + if (pixelmap->Data.MapPointer == NULL) + { + delete pixelmap; + pixelmap = NULL; + } + else + { + Check(pixelmap); + } + Check_Fpu(); + return pixelmap; +} + +PixelMap8 * + PixelMap8::Make(ResourceDescription::ResourceID /*new_resource_id*/) +{ + Check_Fpu(); + return NULL; // not yet 'resourcified' +} + +PixelMap8::PixelMap8(int width, int height) +{ + Check_Pointer(this); + Verify(width >0); + Verify(height >0); + + Data.Size.x = width; + Data.Size.y = height; + Data.MapPointer = new Byte[width*height]; + Register_Pointer(Data.MapPointer); + Check_Fpu(); +} + +PixelMap8::PixelMap8(const char *file_name) +{ + Check_Pointer(file_name); + PCXHeader + header; + + Data.MapPointer = NULL; + + if (PCXRead(file_name, &header, &Data.MapPointer, NULL) == True) + { + if (Data.MapPointer == NULL) + { + Data.Size.x = 0; + Data.Size.y = 0; + } + else + { + //Data.MapPointer already registered by PCXRead() + Data.Size.x = header.xMax - header.xMin + 1; + Data.Size.y = header.yMax - header.yMin + 1; + } + } + Check_Fpu(); +} + +PixelMap8::~PixelMap8() +{ + Check(this); + + if (Data.MapPointer != NULL) + { + Unregister_Pointer(Data.MapPointer); + delete Data.MapPointer; + Data.Size.x = 0; // safety code + Data.Size.y = 0; + Data.MapPointer = NULL; + } + Check_Fpu(); +} + +Logical + PixelMap8::TestInstance() const +{ + Verify (Data.Size.x >0); + Verify (Data.Size.x < 8192); // an unreasonably large image! + Verify (Data.Size.y >0); + Verify (Data.Size.y < 8192); // an unreasonably large image! + Check_Pointer(Data.MapPointer); + Check_Fpu(); + return True; +} + +void + PixelMap8::ShowInstance(char *indent) +{ + Check(this); + + char + temp[80], + buffer[32]; + Byte + *source; + int + x, + y; + + std::cout << indent << "PixelMap8:\n"; + + Str_Copy(temp, indent, 80); + Str_Cat(temp, "...", 80); + + std::cout << temp << "Size =" << Data.Size << "\n"; + std::cout << temp << "MapPointer =" << (void *) Data.MapPointer << "\n"; + + source = Data.MapPointer; + if (source != NULL) + { + for(y=Data.Size.y; y>0; --y) + { + std::cout << temp; + for(x=Data.Size.x; x>0; --x) + { + sprintf(buffer, "%02X ",*source++); + std::cout << buffer; + } + std::cout << "\n"; + } + } + Check_Fpu(); +} + +//######################################################################## +//############################## PixelMap16 ############################## +//######################################################################## +PixelMap16::PixelMap16(int width, int height) +{ + Check_Pointer(this); + Verify(width >0); + Verify(height >0); + + Data.Size.x = width; + Data.Size.y = height; + Data.MapPointer = new Word[width*height]; + Register_Pointer(Data.MapPointer); + + Check_Fpu(); +} + +PixelMap16::PixelMap16(char *) +{ + Fail("PixelMap16::PixelMap16(char *) UNIMPLEMENTED\n"); + Data.MapPointer = NULL; + Data.Size.x = 0; + Data.Size.y = 0; + Check_Fpu(); +} + +PixelMap16::~PixelMap16() +{ + Check(this); + + if (Data.MapPointer != NULL) + { + Unregister_Pointer(Data.MapPointer); + delete Data.MapPointer; + Data.Size.x = 0; // safety code + Data.Size.y = 0; + Data.MapPointer = NULL; + } + Check_Fpu(); +} + +Logical + PixelMap16::TestInstance() const +{ + return True; +} + +void + PixelMap16::ShowInstance(char *indent) +{ + Check(this); + + char + temp[80]; + + std::cout << indent << "PixelMap16:\n"; + + Str_Copy(temp, indent, 80); + Str_Cat(temp, "...", 80); + + std::cout << temp << "Size =" << Data.Size << "\n"; + std::cout << temp << "MapPointer =" << (void *) Data.MapPointer << "\n"; + Check_Fpu(); +} + +//######################################################################## +//########################### GraphicsDisplay ############################ +//######################################################################## +GraphicsDisplay::GraphicsDisplay(int x, int y) +{ + Check_Pointer(this); + Verify(x >0); + Verify(y >0); + + bounds.bottomLeft.x = 0; + bounds.bottomLeft.y = 0; + bounds.topRight.x = x-1; + bounds.topRight.y = y-1; + Check_Fpu(); +} + +GraphicsDisplay::~GraphicsDisplay() +{ + Check(this); + Check_Fpu(); +} + +void + GraphicsDisplay::ShowInstance(char *indent) +{ + Check(this); + std::cout << indent << "GraphicsDisplay:\n"; + + char + temp[80]; + + Str_Copy(temp, indent, 80); + Str_Cat(temp, "...", 80); + + std::cout << temp << "bounds =" << bounds << "\n"; + Check_Fpu(); +} + +Logical + GraphicsDisplay::TestInstance() const +{ + return True; +} + +Logical + GraphicsDisplay::Update(Logical) +{ + // no-op for base class + return False; // always returns 'all done' +} + +void + GraphicsDisplay::WaitForUpdate() +{ + // no-op for base class: immediately returns +} + +Rectangle2D + GraphicsDisplay::TextBounds( + Enumeration, + Logical, + GraphicsDisplay::Justification, + char * + ) +{ + Fail("GraphicsDisplay::TextBounds(...) is UNIMPLEMENTED\n"); + + Rectangle2D + r; + Check_Fpu(); + return r; +} + +void + GraphicsDisplay::DrawPoint( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + int /*x*/, + int /*y*/ + ) +{ + Fail("GraphicsDisplay::DrawPoint not overridden"); +} + +void + GraphicsDisplay::DrawLine( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + int /*x1*/, + int /*y1*/, + int /*x2*/, + int /*y2*/, + Logical /*include_last_pixel*/ + ) +{ + Fail("GraphicsDisplay::DrawLine not overridden"); +} + +void + GraphicsDisplay::DrawFilledRectangle( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + int /*x1*/, + int /*y1*/, + int /*x2*/, + int /*y2*/ + ) +{ + Fail("GraphicsDisplay::DrawFilledRectangle not overridden"); +} + +void + GraphicsDisplay::DrawText( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D * /*clippingRectanglePtr*/, + char * /*stringPointer*/ + ) +{ + Fail("GraphicsDisplay::DrawText not overridden"); +} + +void + GraphicsDisplay::DrawBitMap( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + BitMap * /*bitmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsDisplay::DrawBitMap not overridden"); +} + +void + GraphicsDisplay::DrawBitMapOpaque( + int /*color*/, + int /*background*/, + int /*bitmask*/, + Enumeration /*operation*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + BitMap * /*bitmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsDisplay::DrawBitMapOpaque not overridden"); +} + +void + GraphicsDisplay::DrawPixelMap8( + int * /*translation_table*/, + int /*bitmask*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + PixelMap8 * /*pixelmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsDisplay::DrawPixelMap8 not overridden"); +} + +void + GraphicsDisplay::DrawPixelMap8SingleColor( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + PixelMap8 * /*pixelmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsDisplay::DrawPixelMap8SingleColor not overridden"); +} + +//######################################################################## +//############################ GraphicsPort ############################## +//######################################################################## +GraphicsPort::GraphicsPort( + GraphicsDisplay *graphics_display, + const char *new_name +) +{ + Check_Pointer(this); + + if (graphics_display != NULL) + { + Check(graphics_display); + bounds = graphics_display->bounds; + } + else + { + bounds.bottomLeft.x = 0; + bounds.bottomLeft.y = 0; + bounds.topRight.x = 0; + bounds.topRight.y = 0; + } + graphicsDisplay = graphics_display; + + Str_Copy(name, new_name, sizeof(name)); + Check_Fpu(); +} + +GraphicsPort::~GraphicsPort() +{ + Check(this); + Check_Fpu(); +} + +Logical + GraphicsPort::TestInstance() const +{ + return True; +} + +void + GraphicsPort::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "GraphicsPort:\n"; + + char + temp[80]; + + Str_Copy(temp, indent, 80); + Str_Cat(temp, "...", 80); + + std::cout << temp << "bounds =" << bounds << "\n"; + std::cout << temp << "graphicsDisplay=" << graphicsDisplay << "\n"; + std::cout << std::flush; + Check_Fpu(); +} + +Rectangle2D + GraphicsPort::TextBounds( + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + char *stringPointer + ) +{ + Check(this); + Check(graphicsDisplay); // HACK!!!! Check for NULL! + + Check_Fpu(); + return + graphicsDisplay-> + TextBounds( + fontNumber, + vertical, + justification, + stringPointer + ); +} + +void + GraphicsPort::SetColor( + PaletteTriplet * /*source_color*/, + int /*color_index*/ + ) +{ + Fail("GraphicsPort::SetColor not overridden"); +} + +void + GraphicsPort::DrawPoint( + int /*color*/, + Enumeration /*operation*/, + int /*x*/, + int /*y*/ + ) +{ + Fail("GraphicsPort::DrawPoint not overridden"); +} + +void + GraphicsPort::DrawLine( + int /*color*/, + Enumeration /*operation*/, + int /*x1*/, + int /*y1*/, + int /*x2*/, + int /*y2*/, + Logical /*include_last_pixel*/ + ) +{ + Fail("GraphicsPort::DrawLine not overridden"); +} + +void + GraphicsPort::DrawFilledRectangle( + int /*color*/, + Enumeration /*operation*/, + int /*x1*/, + int /*y1*/, + int /*x2*/, + int /*y2*/ + ) +{ + Fail("GraphicsPort::DrawFilledRectangle not overridden"); +} + +void + GraphicsPort::DrawText( + int /*color*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D * /*clippingRectanglePtr*/, + char * /*stringPointer*/ + ) +{ + Fail("GraphicsPort::DrawText not overridden"); +} + +void + GraphicsPort::DrawBitMap( + int /*color*/, + Enumeration /*operation*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + BitMap * /*bitmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsPort::DrawBitMap not overridden"); +} + +void + GraphicsPort::DrawBitMapOpaque( + int /*color*/, + int /*background*/, + Enumeration /*operation*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + BitMap * /*bitmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsPort::DrawBitMapOpaque not overridden"); +} + +void + GraphicsPort::DrawPixelMap8( + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + PixelMap8 * /*pixelmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsPort::DrawPixelMap8 not overridden"); +} + +void + GraphicsPort::DrawPixelMap8SingleColor( + int /*color*/, + Enumeration /*operation*/, + int /*rotation*/, + int /*x*/, + int /*y*/, + PixelMap8 * /*pixelmap*/, + int /*sx1*/, + int /*sy1*/, + int /*sx2*/, + int /*sy2*/ // these are SOURCE coordinates + ) +{ + Fail("GraphicsPort::DrawPixelMap8SingleColor not overridden"); +} + +//######################################################################## +//######################### GraphicsViewRecord ########################### +//######################################################################## +GraphicsViewRecord::GraphicsViewRecord() +{ + Check_Pointer(this); + + commandListLength = 4096; + commandListIndex = 0; + commandList = new char[commandListLength]; + Register_Pointer(commandList); + link = NULL; + Check_Fpu(); +} + +GraphicsViewRecord::~GraphicsViewRecord() +{ + Check(this); + + if (link != NULL) + { + Check(link); + Unregister_Object(link); + delete link; + link = NULL; // safety code + } + + if (commandList != NULL) + { + Unregister_Pointer(commandList); + delete commandList; + commandList = NULL; // safety code + } + Check_Fpu(); +} + +Logical + GraphicsViewRecord::TestInstance() const +{ + return True; +} + +void + GraphicsViewRecord::Clear() +{ + Check(this); + + if (link != NULL) + { + Check(link); + link->Clear(); + } + + commandListIndex = 0; + Check_Fpu(); +} + +void + GraphicsViewRecord::Draw(GraphicsView *graphics_view, int forced_color) +{ + Check(this); + + GraphicsPort + *graphics_port(graphics_view->graphicsPort); + if (graphics_port == NULL) + { + Clear(); + return; + } + + PixelMap8 + *pixelmap_pointer; + BitMap + *bitmap_pointer; + + int + running=1, + color, bg, + op, + x1, y1, x2, y2, + sx1, sy1, sx2, sy2, + rot, q; + + //-------------------------------------------------------------- + // Mark end of list, rewind to beginning + //-------------------------------------------------------------- + PutChar(GraphicsViewRecord::endCommand); + Clear(); + //-------------------------------------------------------------- + // Parse the command stream + //-------------------------------------------------------------- + while(running) + { + switch(GetChar()) + { + case endCommand: + running = 0; + break; + +#define RECORDER_POINT(recorder, color, op, x1, y1) \ + if (recorder != NULL) \ + { \ + recorder->PutChar(GraphicsViewRecord::pointCommand); \ + recorder->PutShort(color); \ + recorder->PutChar(op); \ + recorder->PutShort(x1); \ + recorder->PutShort(y1); \ + } + case pointCommand: + color = GetShort(); + op = GetChar(); + x1 = GetShort(); + y1 = GetShort(); + + if (forced_color != -1) + { + color = forced_color; + } + graphics_port->DrawPoint(color, op, x1, y1); + break; + +#define RECORDER_LINE(recorder, color, op, x1, y1, x2, y2, endpoint) \ + if (recorder != NULL) \ + { \ + recorder->PutChar(GraphicsViewRecord::lineCommand); \ + recorder->PutShort(color); \ + recorder->PutChar(op); \ + recorder->PutShort(x1); \ + recorder->PutShort(y1); \ + recorder->PutShort(x2); \ + recorder->PutShort(y2); \ + recorder->PutLogical(endpoint); \ + } + case lineCommand: + color = GetShort(); + op = GetChar(); + x1 = GetShort(); + y1 = GetShort(); + x2 = GetShort(); + y2 = GetShort(); + q = GetLogical(); + + if (forced_color != -1) + { + color = forced_color; + } + graphics_port->DrawLine(color, op, x1, y1, x2, y2, q); + break; + +#define RECORDER_FRECT(recorder, color, op, x1, y1, x2, y2) \ + if (recorder != NULL) \ + { \ + recorder->PutChar(GraphicsViewRecord::frectCommand); \ + recorder->PutShort(color); \ + recorder->PutChar(op); \ + recorder->PutShort(x1); \ + recorder->PutShort(y1); \ + recorder->PutShort(x2); \ + recorder->PutShort(y2); \ + } + case frectCommand: + color = GetShort(); + op = GetChar(); + x1 = GetShort(); + y1 = GetShort(); + x2 = GetShort(); + y2 = GetShort(); + + if (forced_color != -1) + { + color = forced_color; + } + graphics_port->DrawFilledRectangle(color, op, x1, y1, x2, y2); + break; + +#define RECORDER_BITMAP(r, color, op, rot, x1, y1, p, sx1, sy1, sx2, sy2) \ + if (r != NULL) \ + { \ + r->PutChar(GraphicsViewRecord::bitmapCommand); \ + r->PutShort(color); \ + r->PutChar(op); \ + r->PutShort(rot); \ + r->PutShort(x1); \ + r->PutShort(y1); \ + r->PutPointer(p); \ + r->PutShort(sx1); \ + r->PutShort(sy1); \ + r->PutShort(sx2); \ + r->PutShort(sy2); \ + } + case bitmapCommand: + color = GetShort(); + op = GetChar(); + rot = GetShort(); + x1 = GetShort(); + y1 = GetShort(); + bitmap_pointer = (BitMap *) GetPointer(); + sx1 = GetShort(); + sy1 = GetShort(); + sx2 = GetShort(); + sy2 = GetShort(); + + Check(bitmap_pointer); + + if (forced_color != -1) + { + color = forced_color; + } + graphics_port->DrawBitMap( + color, + op, + rot, + x1, y1, + bitmap_pointer, + sx1, sy1, sx2, sy2 + ); + break; + +#define RECORDER_BITMAP_OPAQUE( \ + r, fg, bg, op, rot, x1, y1, p, sx1, sy1, sx2, sy2) \ + if (r != NULL) \ + { \ + r->PutChar(GraphicsViewRecord::bitmapOpaqueCommand); \ + r->PutShort(fg); \ + r->PutShort(bg); \ + r->PutChar(op); \ + r->PutShort(rot); \ + r->PutShort(x1); \ + r->PutShort(y1); \ + r->PutPointer(p); \ + r->PutShort(sx1); \ + r->PutShort(sy1); \ + r->PutShort(sx2); \ + r->PutShort(sy2); \ + } + case bitmapOpaqueCommand: + color = GetShort(); + bg = GetShort(); + op = GetChar(); + rot = GetShort(); + x1 = GetShort(); + y1 = GetShort(); + bitmap_pointer = (BitMap *) GetPointer(); + sx1 = GetShort(); + sy1 = GetShort(); + sx2 = GetShort(); + sy2 = GetShort(); + + Check(bitmap_pointer); + + if (forced_color != -1) + { + color = forced_color; + } + graphics_port->DrawBitMapOpaque( + color, + bg, + op, + rot, + x1, y1, + bitmap_pointer, + sx1, sy1, sx2, sy2 + ); + break; + +#define RECORDER_PIXELMAP( \ + r, op, q, rot, x1, y1, p, sx1, sy1, sx2, sy2) \ + if (r != NULL) \ + { \ + r->PutChar(GraphicsViewRecord::pixelmap8Command); \ + r->PutChar(op); \ + r->PutShort(q); \ + r->PutShort(rot); \ + r->PutShort(x1); \ + r->PutShort(y1); \ + r->PutPointer(p); \ + r->PutShort(sx1); \ + r->PutShort(sy1); \ + r->PutShort(sx2); \ + r->PutShort(sy2); \ + } + case pixelmap8Command: + op = GetChar(); + q = GetShort(); + rot = GetShort(); + x1 = GetShort(); + y1 = GetShort(); + pixelmap_pointer = (PixelMap8 *) GetPointer(); + sx1 = GetShort(); + sy1 = GetShort(); + sx2 = GetShort(); + sy2 = GetShort(); + + Check(pixelmap_pointer); + + if (forced_color != -1) + { + graphics_port->DrawPixelMap8SingleColor( + forced_color, + op, + rot, + x1, y1, + pixelmap_pointer, + sx1, sy1, sx2, sy2 + ); + } + else + { + graphics_port->DrawPixelMap8( + op, + q, + rot, + x1, y1, + pixelmap_pointer, + sx1, sy1, sx2, sy2 + ); + } + break; + +#define RECORDER_PIXELMAP_SINGLE_COLOR( \ + r, color, op, rot, x1, y1, p, sx1, sy1, sx2, sy2) \ + if (r != NULL) \ + { \ + r->PutChar(GraphicsViewRecord::pixelmap8SolidCommand); \ + r->PutShort(color); \ + r->PutChar(op); \ + r->PutShort(rot); \ + r->PutShort(x1); \ + r->PutShort(y1); \ + r->PutPointer(p); \ + r->PutShort(sx1); \ + r->PutShort(sy1); \ + r->PutShort(sx2); \ + r->PutShort(sy2); \ + } + case pixelmap8SolidCommand: + color = GetShort(); + op = GetChar(); + rot = GetShort(); + x1 = GetShort(); + y1 = GetShort(); + pixelmap_pointer = (PixelMap8 *) GetPointer(); + sx1 = GetShort(); + sy1 = GetShort(); + sx2 = GetShort(); + sy2 = GetShort(); + + Check(pixelmap_pointer); + + if (forced_color != -1) + { + color = forced_color; + } + graphics_port->DrawPixelMap8SingleColor( + color, + op, + rot, + x1, y1, + pixelmap_pointer, + sx1, sy1, sx2, sy2 + ); + break; + } + } + Check_Fpu(); +} + +void + GraphicsViewRecord::PutChar(int value) +{ + Check(this); + //-------------------------------------------------------------- + // If the buffer is not full, jam it in + //-------------------------------------------------------------- + if (commandListIndex < commandListLength) + { + commandList[commandListIndex++] = (char) value; + } + //-------------------------------------------------------------- + // If the buffer IS full, put it in the 'next' linked buffer + //-------------------------------------------------------------- + else + { + //-------------------------------------------------------------- + // If there is no linked buffer, create one + //-------------------------------------------------------------- + if (link == NULL) + { + link = new GraphicsViewRecord(); + Check(link); + Register_Object(link); + } + //-------------------------------------------------------------- + // Give it to the linked buffer + //-------------------------------------------------------------- + link->PutChar(value); + } + Check_Fpu(); +} + +int + GraphicsViewRecord::GetChar() +{ + Check(this); + //-------------------------------------------------------------- + // If the buffer is not empty, pull the char out + //-------------------------------------------------------------- + if (commandListIndex < commandListLength) + { + Check_Fpu(); + return (int) commandList[commandListIndex++]; + } + //-------------------------------------------------------------- + // If the buffer IS empty, get char from the 'next' linked buffer + //-------------------------------------------------------------- + else + { + //-------------------------------------------------------------- + // If there is no linked buffer, it's a catastrophe + //-------------------------------------------------------------- + if (link == NULL) + { + Fail("GraphicsViewRecord::GetChar() has no link"); + Check_Fpu(); + return GraphicsViewRecord::endCommand; + } + //-------------------------------------------------------------- + // Read from the linked buffer + //-------------------------------------------------------------- + Check(link); + Check_Fpu(); + return link->GetChar(); + } +} + +void + GraphicsViewRecord::PutLogical(Logical value) +{ + Check(this); + if (value) + { + PutChar(1); + } + else + { + PutChar(0); + } + Check_Fpu(); +} + +Logical + GraphicsViewRecord::GetLogical() +{ + Check(this); + Check_Fpu(); + if (GetChar()) + { + return True; + } + else + { + return False; + } +} + +void + GraphicsViewRecord::PutShort(int value) +{ + Check(this); + PutChar(value >> 8); + PutChar(value); + Check_Fpu(); +} + +int + GraphicsViewRecord::GetShort() +{ + Check(this); + int + q; + + q = GetChar() << 8; + q |= GetChar() & 0xFF; + + if (q & 0x8000) // extend sign + { + q |= 0xFFFF0000; + } + + Check_Fpu(); + return q; +} + +void + GraphicsViewRecord::PutPointer(void *pointer) +{ + Check(this); + Verify(pointer != NULL); + union + { + void *pointer; + int value; // assumes 32-bit integer! + } + faker; + + faker.pointer = pointer; + + PutChar(faker.value >> 24); + PutChar(faker.value >> 16); + PutChar(faker.value >> 8); + PutChar(faker.value); + Check_Fpu(); +} + + +void * + GraphicsViewRecord::GetPointer() +{ + Check(this); + union + { + void *pointer; + int value; // assumes 32-bit integer! + } + faker; + + faker.value = GetChar() << 24; + faker.value |= (GetChar() & 0xFF) << 16; + faker.value |= (GetChar() & 0xFF) << 8; + faker.value |= GetChar() & 0xFF; + + Verify(faker.pointer != NULL); + Check_Fpu(); + return faker.pointer; +} + +//######################################################################## +//############################ GraphicsView ############################## +//######################################################################## +GraphicsView::GraphicsView( + GraphicsPort *graphics_port, + int x1, int y1, int x2, int y2 +) +{ + Check_Pointer(this); + // NOTE: graphics_port may be NULL! + + //-------------------------------------------------------------- + // Initialize values + //-------------------------------------------------------------- + graphicsPort = graphics_port; + + currentPosition.x = 0; + currentPosition.y = 0; + currentFontID = 0; + currentColor = 1; + currentOperation = GraphicsDisplay::Replace; + + //-------------------------------------------------------------- + // Set areaWithinPort + //-------------------------------------------------------------- + if (graphics_port == NULL) + { + //-------------------------------------------------------------- + // GraphicsPort doesn't exist, set areaWithinPort to safe value + //-------------------------------------------------------------- + areaWithinPort.bottomLeft.x = 0; + areaWithinPort.bottomLeft.y = 0; + areaWithinPort.topRight.x = 0; + areaWithinPort.topRight.y = 0; + + origin = areaWithinPort.bottomLeft; + } + else + { + //-------------------------------------------------------------- + // Set areaWithinPort to given size + //-------------------------------------------------------------- + areaWithinPort.bottomLeft.x = x1; + areaWithinPort.bottomLeft.y = y1; + areaWithinPort.topRight.x = x2; + areaWithinPort.topRight.y = y2; + //-------------------------------------------------------------- + // Adjust area according to graphicsPort offset + //-------------------------------------------------------------- + areaWithinPort.bottomLeft += graphicsPort->bounds.bottomLeft; + areaWithinPort.topRight += graphicsPort->bounds.bottomLeft; + //-------------------------------------------------------------- + // Set origin to bottom left corner of area + //-------------------------------------------------------------- + origin = areaWithinPort.bottomLeft; + //-------------------------------------------------------------- + // Clip to graphicsPort bounds + //-------------------------------------------------------------- + areaWithinPort.Intersection(areaWithinPort, graphicsPort->bounds); + } + //-------------------------------------------------------------- + // Set clipping rectangle to size of view + //-------------------------------------------------------------- + clippingRectangle = areaWithinPort; + //-------------------------------------------------------------- + // Clear recorder pointer + //-------------------------------------------------------------- + recorder = (GraphicsViewRecord *) NULL; + Check_Fpu(); +} + +GraphicsView::GraphicsView(GraphicsPort *graphics_port) +{ + Check_Pointer(this); + + // NOTE: graphics_port may be NULL! + //-------------------------------------------------------------- + // Initialize values + //-------------------------------------------------------------- + graphicsPort = graphics_port; + + currentPosition.x = 0; + currentPosition.y = 0; + currentFontID = 0; + currentColor = 1; + currentOperation = GraphicsDisplay::Replace; + //-------------------------------------------------------------- + // Set areaWithinPort + //-------------------------------------------------------------- + if (graphics_port == NULL) + { + //-------------------------------------------------------------- + // GraphicsPort doesn't exist, set areaWithinPort to safe value + //-------------------------------------------------------------- + areaWithinPort.bottomLeft.x = 0; + areaWithinPort.bottomLeft.y = 0; + areaWithinPort.topRight.x = 0; + areaWithinPort.topRight.y = 0; + } + else + { + //-------------------------------------------------------------- + // Set areaWithinPort to size of graphicsPort + //-------------------------------------------------------------- + areaWithinPort = graphics_port->bounds; + } + //-------------------------------------------------------------- + // Set origin to bottom left corner of area + //-------------------------------------------------------------- + origin = areaWithinPort.bottomLeft; + //-------------------------------------------------------------- + // Set clipping rectangle to size of view + //-------------------------------------------------------------- + clippingRectangle = areaWithinPort; + //-------------------------------------------------------------- + // Clear recorder pointer + //-------------------------------------------------------------- + recorder = (GraphicsViewRecord *) NULL; + Check_Fpu(); +} + +GraphicsView::~GraphicsView() +{ + Check(this); + Check_Fpu(); +} + +void + GraphicsView::SetPositionWithinPort(int x1, int y1, int x2, int y2) +{ +# if defined(DEBUG) + Tell( + "GraphicsView::SetPositionWithinPort(" << x1 << + "," << y1 << + ", " << x2 << + "," << y2 << + "\n" + ); +# endif + Check(this); + Verify (x2 > x1); + Verify (y2 > y1); + + if (graphicsPort != NULL) + { + //-------------------------------------------------------------- + // Set the new area + //-------------------------------------------------------------- + areaWithinPort.bottomLeft.x = x1; + areaWithinPort.bottomLeft.y = y1; + areaWithinPort.topRight.x = x2-1; + areaWithinPort.topRight.y = y2-1; + //-------------------------------------------------------------- + // Adjust area according to graphicsPort offset + //-------------------------------------------------------------- + areaWithinPort.bottomLeft += graphicsPort->bounds.bottomLeft; + areaWithinPort.topRight += graphicsPort->bounds.bottomLeft; + //-------------------------------------------------------------- + // Set new origin + //-------------------------------------------------------------- + origin = areaWithinPort.bottomLeft; + //-------------------------------------------------------------- + // Clip to graphicsPort bounds + //-------------------------------------------------------------- + areaWithinPort.Intersection(areaWithinPort, graphicsPort->bounds); + //-------------------------------------------------------------- + // Set clipping rectangle to size of view + //-------------------------------------------------------------- + clippingRectangle = areaWithinPort; + } +# if defined(DEBUG) + Tell( + "areaWithinPort=" << areaWithinPort << + "\n" + ); +# endif + Check_Fpu(); +} + +Logical + GraphicsView::TestInstance() const +{ + return True; +} + +void + GraphicsView::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "GraphicsView:\n"; + + char + temp[80]; + + Str_Copy(temp, indent, 80); + Str_Cat(temp, "...", 80); + + std::cout << temp << "areaWithinPort =" << areaWithinPort << "\n"; + std::cout << temp << "origin =" << origin << "\n"; + std::cout << temp << "currentPosition =" << currentPosition << "\n"; + std::cout << temp << "currentFontID =" << currentFontID << "\n"; + std::cout << temp << "currentColor =" << currentColor << "\n"; + std::cout << temp << "clippingRectangle =" << clippingRectangle << "\n"; + std::cout << temp << "currentOperation ="; + switch(currentOperation) + { + case GraphicsDisplay::And: std::cout << "AND\n"; break; + case GraphicsDisplay::Or: std::cout << "OR\n"; break; + case GraphicsDisplay::Replace: std::cout << "REPLACE\n"; break; + default: std::cout << "Unsupported type:" << currentOperation << "\n"; break; + } + std::cout << temp << "graphicsPort =" << graphicsPort << "\n"; + Check_Fpu(); +} + +void + GraphicsView::SetOperation(GraphicsDisplay::Operation new_operation) +{ + Check(this); + currentOperation = new_operation; + Check_Fpu(); +} + +void + GraphicsView::SetOrigin(int x, int y) +{ +# if defined(DEBUG) + Tell( + "GraphicsView::SetOrigin(" << x << + "," << y << + "\n" + ); +# endif + Check(this); + //-------------------------------------------------------------- + // Adjust the current position + //-------------------------------------------------------------- + currentPosition -= origin; + //-------------------------------------------------------------- + // Set the new origin + //-------------------------------------------------------------- + origin.x = x + areaWithinPort.bottomLeft.x; + origin.y = y + areaWithinPort.bottomLeft.y; + //-------------------------------------------------------------- + // Adjust the current position to the new location + //-------------------------------------------------------------- + currentPosition += origin; +# if defined(DEBUG) + Tell( + "origin=" << origin << + ", currentPosition=" << currentPosition << + "\n" + ); +# endif + Check_Fpu(); +} + +void + GraphicsView::SetFont(Enumeration new_font_ID) +{ + Check(this); + + currentFontID = new_font_ID; + Check_Fpu(); +} + +void + GraphicsView::SetColor(int new_color) +{ + Check(this); + + currentColor = new_color; + Check_Fpu(); +} + +void + GraphicsView::SetClippingRectangle(Rectangle2D *clippingRectanglePtr) +{ + Check(this); + Check(clippingRectanglePtr); + + Rectangle2D r; + //-------------------------------------------------------------- + // Get a copy of the requested clipping rectangle, + // add origin offset + //-------------------------------------------------------------- + r = *clippingRectanglePtr; + r.bottomLeft += origin; + r.topRight += origin; + //-------------------------------------------------------------- + // Limit it to the graphicsPort bounds, save the result + //-------------------------------------------------------------- + if (graphicsPort != NULL) + { + clippingRectangle.Intersection(graphicsPort->bounds, r); + } + else + { + clippingRectangle.MakeEmpty(); + } + Check_Fpu(); +} + +void + GraphicsView::ClearClippingRectangle() +{ + Check(this); + + clippingRectangle = areaWithinPort; + Check_Fpu(); +} + +void + GraphicsView::MoveToAbsolute(int x, int y) +{ + Check(this); + + currentPosition.x = origin.x + x; + currentPosition.y = origin.y + y; + Check_Fpu(); +} + +void + GraphicsView::MoveToRelative(int x, int y) +{ + Check(this); + + currentPosition.x += x; + currentPosition.y += y; + Check_Fpu(); +} + +void + GraphicsView::DrawPoint() +{ + Check(this); + + int code(BuildPointCode(currentPosition)); + + if (graphicsPort != NULL) + { + if (code == GraphicsView::IsWithin) + { + graphicsPort-> + DrawPoint( + currentColor, + currentOperation, + currentPosition.x, currentPosition.y + ); + + RECORDER_POINT( + recorder, + currentColor, + currentOperation, + currentPosition.x, currentPosition.y + ); + } + } + Check_Fpu(); +} + +void + GraphicsView::DrawLineToAbsolute(int x, int y) +{ + Check(this); + + Vector2DOf + end; + + end.x = origin.x + x; + end.y = origin.y + y; + DrawLine(currentPosition, end, True); + currentPosition = end; + Check_Fpu(); +} + +void + GraphicsView::DrawLineToRelative(int x, int y) +{ + Check(this); + + Vector2DOf + end; + + end.x = currentPosition.x + x; + end.y = currentPosition.y + y; + DrawLine(currentPosition, end, True); + currentPosition = end; + Check_Fpu(); +} + +void + GraphicsView::DrawThickLineToAbsolute(int x, int y) +{ + Check(this); + + Vector2DOf + end, + start, + stop; + + end.x = origin.x + x; + end.y = origin.y + y; + + start.x = currentPosition.x; + start.y = currentPosition.y; + stop.x = end.x; + stop.y = end.y; + DrawThickLine(start, stop); + + currentPosition = end; + Check_Fpu(); +} + +void + GraphicsView::DrawThickLineToRelative(int x, int y) +{ + Check(this); + + Vector2DOf + end, + start, + stop; + + end.x = currentPosition.x + x; + end.y = currentPosition.y + y; + + start.x = currentPosition.x; + start.y = currentPosition.y; + stop.x = end.x; + stop.y = end.y; + DrawThickLine(start, stop); + + currentPosition = end; + Check_Fpu(); +} + +void + GraphicsView::DrawRectangleToAbsolute(int x, int y) +{ + Check(this); + + Vector2DOf + home; + + home = currentPosition; + home -= origin; + DrawLineToAbsolute(home.x, y); + DrawLineToAbsolute(x, y); + DrawLineToAbsolute(x, home.y); + DrawLineToAbsolute(home.x, home.y); + + currentPosition.x = x; + currentPosition.y = y; + Check_Fpu(); +} + +void + GraphicsView::DrawRectangleToRelative(int x, int y) +{ + Check(this); + + Vector2DOf + home; + + home = currentPosition; + home -= origin; + DrawLineToRelative(0, y); + DrawLineToRelative(x, 0); + DrawLineToRelative(0, -y); + DrawLineToRelative(-x, 0); + + currentPosition.x = home.x + x; + currentPosition.y = home.y + y; + Check_Fpu(); +} + +void + GraphicsView::DrawFilledRectangleToAbsolute(int x, int y) +{ + Check(this); + + Rectangle2D r; + + r.bottomLeft = currentPosition; + r.topRight.x = origin.x + x; + r.topRight.y = origin.y + y; + + DrawFilledRectangle(r); + + currentPosition = r.topRight; + Check_Fpu(); +} + +void + GraphicsView::DrawFilledRectangleToRelative(int x, int y) +{ + Check(this); + + Rectangle2D r; + + r.bottomLeft = currentPosition; + r.topRight.x = currentPosition.x + x; + r.topRight.y = currentPosition.y + y; + + DrawFilledRectangle(r); + + currentPosition = r.topRight; + Check_Fpu(); +} + +void + GraphicsView::DrawText( + Logical , + Logical , + GraphicsDisplay::Justification , + Rectangle2D *, + char * + ) +{ + Check(this); + Check_Fpu(); +} + +void + GraphicsView::DrawBitMap( + int rotation, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ) +{ + Check(this); + + Rectangle2D sourceBounds(sx1, sy1, sx2, sy2); + Vector2DOf position; + + if (bitmap != NULL) + { + Check(bitmap); + + if (ClipImage(&sourceBounds, &position, bitmap->Data.Size)) + { + graphicsPort-> + DrawBitMap( + currentColor, + currentOperation, + rotation, + position.x, position.y, + bitmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + RECORDER_BITMAP( + recorder, + currentColor, + currentOperation, + rotation, + position.x, position.y, + bitmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + } + } + Check_Fpu(); +} + +void + GraphicsView::DrawBitMapOpaque( + int background, + int rotation, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ) +{ + Check(this); + + Rectangle2D sourceBounds(sx1, sy1, sx2, sy2); + Vector2DOf position; + + if (bitmap != NULL) + { + Check(bitmap); + + if (ClipImage(&sourceBounds, &position, bitmap->Data.Size)) + { + graphicsPort-> + DrawBitMapOpaque( + currentColor, + background, + currentOperation, + rotation, + position.x, position.y, + bitmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + RECORDER_BITMAP_OPAQUE( + recorder, + currentColor, + background, + currentOperation, + rotation, + position.x, position.y, + bitmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + } + } + Check_Fpu(); +} + +void + GraphicsView::DrawPixelMap8( + Logical opaque, + int rotation, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ) +{ + Check(this); + + Rectangle2D sourceBounds(sx1, sy1, sx2, sy2); + Vector2DOf position; + + if (pixelmap != NULL) + { + Check(pixelmap); + + if (ClipImage(&sourceBounds, &position, pixelmap->Data.Size)) + { + graphicsPort-> + DrawPixelMap8( + currentOperation, + opaque, + rotation, + position.x, position.y, + pixelmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + RECORDER_PIXELMAP( + recorder, + currentOperation, + opaque, + rotation, + position.x, position.y, + pixelmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + } + } + Check_Fpu(); +} + +void + GraphicsView::DrawPixelMap8SingleColor( + int rotation, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ) +{ + Check(this); + + Rectangle2D sourceBounds(sx1, sy1, sx2, sy2); + Vector2DOf position; + + if (pixelmap != NULL) + { + Check(pixelmap); + + if (ClipImage(&sourceBounds, &position, pixelmap->Data.Size)) + { + graphicsPort-> + DrawPixelMap8SingleColor( + currentColor, + currentOperation, + rotation, + position.x, position.y, + pixelmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + RECORDER_PIXELMAP_SINGLE_COLOR( + recorder, + currentColor, + currentOperation, + rotation, + position.x, position.y, + pixelmap, + sourceBounds.bottomLeft.x, sourceBounds.bottomLeft.y, + sourceBounds.topRight.x, sourceBounds.topRight.y + ); + } + } + Check_Fpu(); +} + +void + GraphicsView::SetColor( + PaletteTriplet *source_color, + int color_index + ) +{ + Check(this); + Check_Pointer(source_color); + + if (graphicsPort != NULL) + { + graphicsPort->SetColor(source_color, color_index); + } + Check_Fpu(); +} + +void + GraphicsView::AttachRecorder(GraphicsViewRecord *graphics_view_record) +{ + Check(this); + Verify(recorder == NULL); + Check(graphics_view_record); + recorder = graphics_view_record; + Check_Fpu(); +} + +void + GraphicsView::DetachRecorder() +{ + Check(this); + recorder = NULL; + Check_Fpu(); +} + +int + GraphicsView::BuildPointCode(Vector2DOf vector) +{ + // This is static. Don't attempt to check for signature! + + int result(0); + + if (vector.x < clippingRectangle.bottomLeft.x) + { + result |= GraphicsView::IsLeft; + } + else if (vector.x > clippingRectangle.topRight.x) + { + result |= GraphicsView::IsRight; + } + + if (vector.y < clippingRectangle.bottomLeft.y) + { + result |= GraphicsView::IsBelow; + } + else if (vector.y > clippingRectangle.topRight.y) + { + result |= GraphicsView::IsAbove; + } + Check_Fpu(); + return result; +} + +void + GraphicsView::DrawThickLine( + Vector2DOf start, + Vector2DOf stop + ) +{ + Check(this); + + DrawLine(start, stop, True); + --start.x; + --stop.x; + DrawLine(start, stop, True); + ++start.x; + ++stop.x; + ++start.y; + ++stop.y; + DrawLine(start, stop, True); + ++start.x; + ++stop.x; + --start.y; + --stop.y; + DrawLine(start, stop, True); + --start.x; + --stop.x; + --start.y; + --stop.y; + DrawLine(start, stop, True); + + Check_Fpu(); +} + +void + GraphicsView::DrawLine( + Vector2DOf start, + Vector2DOf end, + Logical include_last_pixel + ) +{ +# if defined(DEBUG) + Tell( + "DrawLine(=" << start << + ", " << end << + ", " << include_last_pixel << + ")\n" + ); + Tell( + "clippingRectangle=" << clippingRectangle << + "\n" + ); +# endif + Check(this); + + int + start_code, + end_code; + + Logical + swapped(False), + start_clipped(False), + end_clipped(False); + + if (graphicsPort != NULL) + { + //---------------------------------------------------- + // Generate endpoint codes + //---------------------------------------------------- + start_code = BuildPointCode(start); + end_code = BuildPointCode(end); +# if defined(DEBUG) + Tell( + "start code=" << start_code << + ", end_code=" << end_code << + "\n" + ); +# endif + + //---------------------------------------------------- + // Loop until either both codes are zero + // or it's completely out of the display + //---------------------------------------------------- + while(start_code | end_code) + { +# if defined(DEBUG) + Tell( + "Clipping, start=" << start << + ", end=" << end << + "\n" + ); +# endif + //---------------------------------------------------- + // If the line is totally off the display, abandon it + //---------------------------------------------------- + if ((start_code & end_code) != 0) + { +# if defined(DEBUG) + Tell("Abandoned\n"); +# endif + return; + } + //---------------------------------------------------- + // Make sure an out-of-bounds point is being clipped + //---------------------------------------------------- + if (start_code == GraphicsView::IsWithin) + { +# if defined(DEBUG) + Tell("Swapping endpoints\n"); +# endif + + Vector2DOf + temp_vector; + temp_vector = start; + start = end; + end = temp_vector; + + int temp_code; + temp_code = start_code; + start_code = end_code; + end_code = temp_code; + + Logical temp_flag; + temp_flag = start_clipped; + start_clipped = end_clipped; + end_clipped = temp_flag; + + swapped ^= True; + } + //---------------------------------------------------- + // Clip the starting segment + //---------------------------------------------------- + if (start_code & GraphicsView::IsLeft) + { +# if defined(DEBUG) + Tell("Clip left\n"); +# endif + Verify(end.x != start.x); + start.y += (end.y - start.y) * + (clippingRectangle.bottomLeft.x-start.x) / (end.x-start.x); + Check_Fpu(); + start.x = clippingRectangle.bottomLeft.x; + + start_clipped = True; + } + else if (start_code & GraphicsView::IsRight) + { +# if defined(DEBUG) + Tell("Clip right\n"); +# endif + Verify(end.x != start.x); + start.y += (end.y - start.y) * + (clippingRectangle.topRight.x-start.x) / (end.x-start.x); + Check_Fpu(); + start.x = clippingRectangle.topRight.x; + + start_clipped = True; + } + else if (start_code & GraphicsView::IsAbove) + { +# if defined(DEBUG) + Tell("Clip above\n"); +# endif + Verify(end.y != start.y); + start.x += (end.x - start.x) * + (clippingRectangle.topRight.y-start.y) / (end.y-start.y); + Check_Fpu(); + start.y = clippingRectangle.topRight.y; + + start_clipped = True; + } + else if (start_code & GraphicsView::IsBelow) + { +# if defined(DEBUG) + Tell("Clip below\n"); +# endif + Verify(end.y != start.y); + start.x += (end.x - start.x) * + (clippingRectangle.bottomLeft.y-start.y) / (end.y-start.y); + Check_Fpu(); + start.y = clippingRectangle.bottomLeft.y; + + start_clipped = True; + } + //---------------------------------------------------- + // Build a new point code for the starting point, + // loop until line is either in or out. + //---------------------------------------------------- + start_code = BuildPointCode(start); + } +# if defined(DEBUG) + Tell( + "Clipping done, start=" << start << + ", end=" << end << + "\n" + ); +# endif + //---------------------------------------------------- + // If swapped, flip them back + //---------------------------------------------------- + if (swapped) + { +# if defined(DEBUG) + Tell("Swapping back\n"); +# endif + Vector2DOf + temp_vector; + temp_vector = start; + start = end; + end = temp_vector; + + Logical temp_flag; + temp_flag = start_clipped; + start_clipped = end_clipped; + end_clipped = temp_flag; + } + //---------------------------------------------------- + // If the endpoint was clipped, include the final pixel + //---------------------------------------------------- + if (end_clipped) + { +# if defined(DEBUG) + Tell("End was clipped, including last pixel\n"); +# endif + include_last_pixel = True; + } + //---------------------------------------------------- + // Finally, draw the line! + //---------------------------------------------------- +# if defined(DEBUG) + Tell( + "All done, start=" << start << + ", end=" << end << + "\n" + ); +# endif + + Verify(BuildPointCode(start) == 0); + Verify(BuildPointCode(end) == 0); + + graphicsPort->DrawLine( + currentColor, + currentOperation, + start.x, start.y, + end.x, end.y, + include_last_pixel + ); + + RECORDER_LINE( + recorder, + currentColor, + currentOperation, + start.x, start.y, + end.x, end.y, + include_last_pixel + ); + } + Check_Fpu(); +} + +void + GraphicsView::DrawFilledRectangle(Rectangle2D r) +{ + Check(this); + if (graphicsPort != NULL) + { + // + // Swap X positions if needed + // + if (r.bottomLeft.x > r.topRight.x) + { + int temp; + + temp = r.bottomLeft.x; + r.bottomLeft.x = r.topRight.x; + r.topRight.x = temp; + } + // + // Swap Y positions if needed + // + if (r.bottomLeft.y > r.topRight.y) + { + int temp; + + temp = r.bottomLeft.y; + r.bottomLeft.y = r.topRight.y; + r.topRight.y = temp; + } + // + // Clip to clipping rectangle + // + r.Intersection(clippingRectangle, r); + // + // Draw if non-empty + // + if (! r.IsEmpty()) + { + graphicsPort-> + DrawFilledRectangle( + currentColor, + currentOperation, + r.bottomLeft.x, r.bottomLeft.y, r.topRight.x, r.topRight.y + ); + RECORDER_FRECT( + recorder, + currentColor, + currentOperation, + r.bottomLeft.x, r.bottomLeft.y, r.topRight.x, r.topRight.y + ); + } + } + Check_Fpu(); +} + +Logical + GraphicsView::ClipImage( + Rectangle2D *sourceRect, + Vector2DOf *position, + Vector2DOf imageLimits + ) +{ + Check(this); + + if (graphicsPort != NULL) + { + Rectangle2D + destRect; + + Vector2DOf + source_origin, + source_size; + + // + // clip sourceRect to image limits + // + if (sourceRect->bottomLeft.x < 0) + { + sourceRect->bottomLeft.x = 0; + } + if (sourceRect->topRight.x >= imageLimits.x) + { + sourceRect->topRight.x = imageLimits.x-1; + } + + if (sourceRect->bottomLeft.y < 0) + { + sourceRect->bottomLeft.y = 0; + } + if (sourceRect->topRight.y >= imageLimits.y) + { + sourceRect->topRight.y = imageLimits.y-1; + } + + source_origin = sourceRect->bottomLeft; + source_size = sourceRect->topRight; + source_size -= sourceRect->bottomLeft; + + // + // build corresponding rectangle in port space + // + destRect.bottomLeft = currentPosition; + destRect.topRight = currentPosition; + destRect.topRight += source_size; + // + // now, clip the rectangle + // + Rectangle2D r; + r = destRect; + destRect.Intersection(r, clippingRectangle); + // + // draw if non-empty + // + if (! destRect.IsEmpty()) + { + // + // Set position + // + *position = destRect.bottomLeft; + // + // return rectangle to image space + // + source_size = destRect.topRight; + source_size -= destRect.bottomLeft; + + sourceRect->bottomLeft = source_origin; + sourceRect->topRight = source_origin; + sourceRect->topRight += source_size; + Check_Fpu(); + return True; + } + } + Check_Fpu(); + return False; +} diff --git a/MUNGA/GRAPH2D.h b/MUNGA/GRAPH2D.h new file mode 100644 index 0000000..e8272c5 --- /dev/null +++ b/MUNGA/GRAPH2D.h @@ -0,0 +1,772 @@ +#pragma once + +#include "style.h" +#include "vector2d.h" +#include "rect2d.h" +#include "resource.h" +#include "plug.h" + +class BitMap; +class PixelMap; +class GraphicsDisplay; +class GraphicsPort; +class GraphicsViewRecord; +class GraphicsView; +class NotationFile; + +//######################################################################## +//################################ BitMap ################################ +//######################################################################## +// +// The "raw" bit map is used by assembly-language routines. +// It must not be burdened with signatures, etc. +// +struct RawBitMap +{ + Vector2DOf Size; + int WidthInWords; + Word *MapPointer; +}; + +class BitMap : +public Plug +{ +public: + BitMap(int width, int height); + BitMap(int width, int height, Word *body); + BitMap(const char *filename); + BitMap(NotationFile *notation_file, const char *page_name); + ~BitMap(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + static BitMap * + Make(const char *file_name); + static BitMap * + Make(ResourceDescription::ResourceID new_resource_id); + + RawBitMap + Data; +}; + +//######################################################################## +//############################### Palette8 ############################### +//######################################################################## + +struct PaletteTriplet +{ + Byte Red; //0..255 + Byte Green; //0..255 + Byte Blue; //0..255 + + friend std::ostream& operator<<(std::ostream& stream, const PaletteTriplet& p); + + PaletteTriplet& + operator=(PaletteTriplet& t) + { + Red = t.Red; + Green = t.Green; + Blue = t.Blue; + return t; + } + Logical + operator==(const PaletteTriplet& t) const + { + return ((Red==t.Red) && (Green==t.Green) && (Blue==t.Blue)); + } + Logical + operator!=(const PaletteTriplet& t) const + { + return ((Red!=t.Red) || (Green!=t.Green) || (Blue!=t.Blue)); + } +}; + +class Palette8 SIGNATURED +{ + friend class GraphicsPort; + +public: + Palette8(); + Palette8(int count, PaletteTriplet *source); + Palette8(const char *filename); + ~Palette8(); + + void + SetColorRange( + int start, + int end, + PaletteTriplet new_color + ); + void + BuildColorRange( + int start, + int end, + PaletteTriplet first_color, + PaletteTriplet last_color + ); + Logical + TestInstance() const; + void + ShowInstance(char *indent); + static Palette8 * + Make(const char *file_name); + static Palette8 * + Make(ResourceDescription::ResourceID new_resource_id); + + Logical + Valid; + + PaletteTriplet + Color[256]; +}; + +//######################################################################## +//############################## PixelMap8 ############################### +//######################################################################## + +// +// The "raw" pixel map is used by assembly-language routines. +// It must not be burdened with signatures, etc. +// +struct RawPixelMap8 +{ + Vector2DOf Size; + Byte *MapPointer; +}; + +class PixelMap8 SIGNATURED +{ + friend class GraphicsPort; + +public: + PixelMap8(int width, int height); + PixelMap8(Vector2DOf size); +// {PixelMap(size.x, size.y);} + PixelMap8(const char *filename); + PixelMap8() + { + Data.Size.x = 0; + Data.Size.y = 0; + Data.MapPointer = NULL; + } + ~PixelMap8(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + static PixelMap8 * + Make(const char *file_name); + static PixelMap8 * + Make(ResourceDescription::ResourceID new_resource_id); + + RawPixelMap8 + Data; +}; + +//######################################################################## +//############################## PixelMap16 ############################## +//######################################################################## + +// +// The "raw" pixel map is used by assembly-language routines. +// It must not be burdened with signatures, etc. +// +struct RawPixelMap16 +{ + Vector2DOf Size; + Word *MapPointer; +}; + +class PixelMap16 SIGNATURED +{ + friend class GraphicsPort; + +public: + PixelMap16(int width, int height); + PixelMap16(Vector2DOf size); +// {PixelMap(size.x, size.y);} + PixelMap16(char *filename); + PixelMap16() + { + Data.Size.x = 0; + Data.Size.y = 0; + Data.MapPointer = NULL; + } + ~PixelMap16(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + RawPixelMap16 + Data; +}; + +//######################################################################## +//########################### GraphicsDisplay ############################ +//######################################################################## +class GraphicsDisplay SIGNATURED +{ +public: + enum Operation { + Replace=0, And, Or, Xor, NextOperation + }; + + enum FontNumber { + SystemFont=0, NextFontNumber + }; + + enum Justification { + Normal=0, + Left=0x00, Horizontal=0x01, Right=0x02, + Top=0x00, Vertical=0x04, Bottom=0x08 + }; + +public: + GraphicsDisplay(int x, int y); + + virtual ~GraphicsDisplay(); + + Logical + TestInstance() const; + + virtual void + ShowInstance(char *indent); + + virtual Logical + Update(Logical forceAll); + + virtual void + WaitForUpdate(); + + virtual Rectangle2D + TextBounds( + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + char *stringPointer + ); + + virtual void + DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ); + + virtual void + DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + virtual void + DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + virtual void + DrawText( + int color, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + virtual void + DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawBitMapOpaque( + int color, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + +public: + Rectangle2D bounds; +}; + +//######################################################################## +//############################ GraphicsPort ############################## +//######################################################################## +class GraphicsPort SIGNATURED +{ +public: + GraphicsPort( + GraphicsDisplay *graphics_display, + const char *name + ); + + virtual ~GraphicsPort(); + + Logical + TestInstance() const; + + virtual void + ShowInstance(char *indent); + + virtual Rectangle2D + TextBounds( + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + char *stringPointer + ); + + virtual void + SetColor( + PaletteTriplet *source_color, + int color_index + ); + + virtual void + DrawPoint( + int color, + Enumeration operation, + int x, int y + ); + + virtual void + DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + virtual void + DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + virtual void + DrawText( + int color, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + virtual void + DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + virtual void + DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + +public: + Rectangle2D + bounds; + GraphicsDisplay + *graphicsDisplay; + + char + name[16]; +}; + +//######################################################################## +//######################### GraphicsViewRecord ########################### +//######################################################################## +class GraphicsViewRecord SIGNATURED +{ + friend class GraphicsView; +public: + GraphicsViewRecord(); + ~GraphicsViewRecord(); + Logical + TestInstance() const; + void + Clear(); + void + Draw(GraphicsView *graphics_view, int forced_color=-1); +protected: + enum + { + endCommand=0, + pointCommand, + lineCommand, + frectCommand, + bitmapCommand, + bitmapOpaqueCommand, + pixelmap8Command, + pixelmap8SolidCommand, + }; + + void + PutChar(int value); + int + GetChar(); + void + PutLogical(Logical value); + Logical + GetLogical(); + void + PutShort(int value); + int + GetShort(); + void + PutPointer(void *pointer); + void * + GetPointer(); + + int + commandListLength, + commandListIndex; + char + *commandList; + GraphicsViewRecord + *link; +}; + +//######################################################################## +//############################ GraphicsView ############################## +//######################################################################## +class GraphicsView SIGNATURED +{ +friend class GraphicsViewRecord; +public: + GraphicsView( + GraphicsPort *graphics_port, + int x1, int y1, int x2, int y2 + ); + + GraphicsView( + GraphicsPort *graphics_port + ); + + virtual ~GraphicsView(); + + Logical + TestInstance() const; + + virtual void + ShowInstance(char *indent); + + virtual void + SetPositionWithinPort( + int left, + int bottom, + int right, + int top + ); + + virtual void + SetOperation(GraphicsDisplay::Operation operation); + + virtual void + SetOrigin( + int x, + int y + ); + + virtual void + SetFont( + Enumeration new_font_ID + ); + + virtual void + SetColor( + int new_color + ); + + virtual void + SetClippingRectangle( + Rectangle2D *clippingRectangle + ); + + virtual void + ClearClippingRectangle(); + + virtual void + MoveToAbsolute( + int x, + int y + ); + + virtual void + MoveToRelative( + int x, + int y + ); + // + //----------------------------------------------------- + // These routines first clip the operation according to + // clippingRectangle of the GraphicsView. + // The clipped results are then passed on to the + // corresponding routine in the GraphicsPort object. + //----------------------------------------------------- + // + virtual void + DrawPoint(); + + virtual void + DrawLineToAbsolute(int x, int y); + + virtual void + DrawLineToRelative(int x, int y); + + virtual void + DrawThickLineToAbsolute(int x, int y); + + virtual void + DrawThickLineToRelative(int x, int y); + + virtual void + DrawRectangleToAbsolute(int x, int y); + + virtual void + DrawRectangleToRelative(int x, int y); + + virtual void + DrawFilledRectangleToAbsolute(int x, int y); + + virtual void + DrawFilledRectangleToRelative(int x, int y); + + virtual void + DrawText( + Logical opaque, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + virtual void + DrawBitMap( + int rotation, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMap( + int rotation, + BitMap *bitmap + ) + { + DrawBitMap( + rotation, + bitmap, + 0, 0, bitmap->Data.Size.x-1, bitmap->Data.Size.y-1 + ); + } + + virtual void + DrawBitMapOpaque( + int background, + int rotation, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int background, + int rotation, + BitMap *bitmap + ) + { + DrawBitMapOpaque( + background, + rotation, + bitmap, + 0, 0, bitmap->Data.Size.x-1, bitmap->Data.Size.y-1 + ); + } + + virtual void + DrawPixelMap8( + Logical opaque, + int rotation, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + Logical opaque, + int rotation, + PixelMap8 *pixelmap + ) + { + DrawPixelMap8( + opaque, + rotation, + pixelmap, + 0, 0, pixelmap->Data.Size.x-1, pixelmap->Data.Size.y-1 + ); + } + + virtual void + DrawPixelMap8SingleColor( + int rotation, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int rotation, + PixelMap8 *pixelmap + ) + { + DrawPixelMap8SingleColor( + rotation, + pixelmap, + 0, 0, pixelmap->Data.Size.x-1, pixelmap->Data.Size.y-1 + ); + } + + virtual void + AttachRecorder(GraphicsViewRecord *graphics_view_record); + virtual void + DetachRecorder(); + + enum PointCode{ + IsWithin=0, IsLeft=0x01, IsRight=0x02, IsBelow=0x04, IsAbove=0x08 + }; + + virtual int + BuildPointCode(Vector2DOf vector); + + Logical + ClipImage( + Rectangle2D *sourceRect, + Vector2DOf *position, + Vector2DOf imageLimits + ); + + virtual void + SetColor( + PaletteTriplet *source_color, + int color_index + ); + +protected: + void + DrawThickLine( + Vector2DOf start, + Vector2DOf end + ); + + void + DrawLine( + Vector2DOf start, + Vector2DOf end, + Logical include_last_pixel + ); + + void + DrawFilledRectangle(Rectangle2D r); + + Rectangle2D areaWithinPort; + Vector2DOf origin; + Vector2DOf currentPosition; + Enumeration currentFontID; + int currentColor; + Rectangle2D clippingRectangle; + GraphicsDisplay::Operation currentOperation; + GraphicsPort *graphicsPort; + GraphicsViewRecord *recorder; +}; diff --git a/MUNGA/HASH.cpp b/MUNGA/HASH.cpp new file mode 100644 index 0000000..f149bb9 --- /dev/null +++ b/MUNGA/HASH.cpp @@ -0,0 +1,531 @@ +#include "munga.h" +#pragma hdrstop + +#include "hash.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Hash ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define Verify_Index(x) Verify(0 <= (x) && (x) < hashTableSize) + +// +//########################################################################### +// Hash +//########################################################################### +// +Hash::Hash( + CollectionSize size, + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + hashTableSize = size; + BuildHashTable(); +} + +void + Hash::BuildHashTable() +{ + int i; + +#if 0 + hashTable = (VChain**)malloc(hashTableSize * sizeof(VChain*)); +#else + hashTable = new VChain*[hashTableSize]; +#endif + Register_Pointer(hashTable); + + for (i = 0; i < hashTableSize; i++) + { + Check_Pointer(hashTable); + Verify_Index(i); + hashTable[i] = NULL; + } +} + +// +//########################################################################### +// ~Hash +//########################################################################### +// +Hash::~Hash() +{ + int i; + + for (i = 0; i < hashTableSize; i++) + { + Check_Pointer(hashTable); + Verify_Index(i); + if (hashTable[i] != NULL) + { + Unregister_Object(hashTable[i]); + delete hashTable[i]; + } + } + + Unregister_Pointer(hashTable); +#if 0 + free(hashTable); +#else + delete[] hashTable; +#endif + hashTable = NULL; + hashTableSize = 0; +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Hash::TestInstance() const +{ + SortedSocket::TestInstance(); + + Check_Pointer(hashTable); + Verify(hashTableSize > 0); + + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Hash::AddImplementation(Plug *plug) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + Hash::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + Check(this); + Check(plug); + Check_Pointer(value); + + // + //------------------------------------------------------------- + // Verify that value has not been added + //------------------------------------------------------------- + // + Verify(HasUniqueEntries() ? (FindImplementation(value) == NULL) : (Logical)True); + + // + //------------------------------------------------------------- + // Find hash entry + //------------------------------------------------------------- + // + IteratorPosition index; + + index = GetHashIndex(value); + + // + //------------------------------------------------------------- + // Get vchain for this index + //------------------------------------------------------------- + // + VChain *vchain; + + Check_Pointer(hashTable); + Verify_Index(index); + if ((vchain = hashTable[index]) == NULL) + { + vchain = MakeVChain(); + Register_Object(vchain); + hashTable[index] = vchain; + } + + // + //------------------------------------------------------------- + // Add to the vchain + //------------------------------------------------------------- + // + Check(vchain); + vchain->AddValuePlug(plug, value); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + Hash::FindImplementation( + const void *value + ) +{ + Check(this); + Check_Pointer(value); + + // + //------------------------------------------------------------- + // Find hash entry + //------------------------------------------------------------- + // + IteratorPosition index; + + index = GetHashIndex(value); + + // + //------------------------------------------------------------- + // Get vchain for this index + //------------------------------------------------------------- + // + VChain *vchain; + + Check_Pointer(hashTable); + Verify_Index(index); + if ((vchain = hashTable[index]) == NULL) + { + return NULL; + } + + // + //------------------------------------------------------------- + // Find in vchain + //------------------------------------------------------------- + // + Check(vchain); + return vchain->FindPlug(value); +} + +// +//########################################################################### +// MakeVChain +//########################################################################### +// +VChain* + Hash::MakeVChain() +{ + Fail("Hash::MakeVChain - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// MakeVChain +//########################################################################### +// +IteratorPosition + Hash::GetHashIndex(const void*) +{ + Fail("Hash::GetHashIndex - Should never reach here"); + return 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ HashIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const IteratorPosition HashIteratorNullPosition = -1; + +// +//########################################################################### +// HashIterator +//########################################################################### +// +HashIterator::HashIterator(Hash *hash): + SortedIterator(hash) +{ + hashTable = hash->hashTable; + hashTableSize = hash->hashTableSize; + currentPosition = HashIteratorNullPosition; + vchainIterator = NULL; + First(); +} + +HashIterator::~HashIterator() +{ + hashTable = NULL; + hashTableSize = 0; + currentPosition = HashIteratorNullPosition; + DeleteVChainIterator(); +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + HashIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + Check_Pointer(hashTable); + Verify(hashTableSize > 0); + + if (vchainIterator != NULL) + { + Check(vchainIterator); + } + + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + HashIterator::First() +{ + NextVChainIterator(0); +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + HashIterator::Last() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + HashIterator::Next() +{ + if (vchainIterator != NULL) + { + Check(vchainIterator); + + if (vchainIterator->GetCurrentPlug() != NULL) + { + // + // Try to step to the next item in this list + // + vchainIterator->Next(); + } + if (vchainIterator->GetCurrentPlug() == NULL) + { + // + // At end of list, step to the next list + // + NextVChainIterator(currentPosition+1); + } + } +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + HashIterator::Previous() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *HashIterator::GetCurrentImplementation() +{ + if (vchainIterator != NULL) + { + Check(vchainIterator); + + if (vchainIterator->GetCurrentPlug() != NULL) + { + return vchainIterator->GetCurrentPlug(); + } + + // + // List was emptied, step to next list + // + NextVChainIterator(currentPosition+1); + + if (vchainIterator != NULL) + { + Check(vchainIterator); + Verify(vchainIterator->GetCurrentPlug() != NULL); + return vchainIterator->GetCurrentPlug(); + } + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + HashIterator::GetSize() +{ + HashIterator iterator(Cast_Object(Hash*, socket)); + CollectionSize i = 0; + + while (iterator.ReadAndNextImplementation() != NULL) + { + i++; + } + return(i); +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + HashIterator::Remove() +{ + if (vchainIterator != NULL) + { + Check(vchainIterator); + + if (vchainIterator->GetCurrentPlug() != NULL) + { + vchainIterator->Remove(); + return; + } + + // + // List was emptied, step to next list + // + NextVChainIterator(currentPosition+1); + + if (vchainIterator != NULL) + { + Check(vchainIterator); + vchainIterator->Remove(); + return; + } + } +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug + *HashIterator::FindImplementation( + const void* + ) +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + HashIterator::ReceiveMemo( + IteratorMemo, + void* + ) +{ +} + +// +//########################################################################### +//########################################################################### +// +void + HashIterator::DeleteVChainIterator() +{ + if (vchainIterator != NULL) + { + Unregister_Object(vchainIterator); + delete vchainIterator; + vchainIterator = NULL; + } +} + +// +//########################################################################### +//########################################################################### +// +void + HashIterator::NextVChainIterator(IteratorPosition index) +{ + int i; + + DeleteVChainIterator(); + currentPosition = HashIteratorNullPosition; + + for (i = index; i < hashTableSize; i++) + { + Check_Pointer(hashTable); + Verify_Index(i); + + if (hashTable[i] != NULL) + { + // + // This index contains a vchain + // + Check(hashTable[i]); + + // + // Create a vchain iterator + // + vchainIterator = new VChainIterator(hashTable[i]); + Register_Object(vchainIterator); + if (vchainIterator->GetCurrentPlug() != NULL) + { + // + // The vchain contains items + // + currentPosition = i; + return; + } + + // + // Destroy the vchain iterator + // + DeleteVChainIterator(); + } + } +} + +#if defined(TEST_CLASS) +# include "hash.tcp" +#endif diff --git a/MUNGA/HASH.h b/MUNGA/HASH.h new file mode 100644 index 0000000..df10779 --- /dev/null +++ b/MUNGA/HASH.h @@ -0,0 +1,132 @@ +#pragma once + +#include "srtskt.h" +#include "vchain.h" + +class Hash : public SortedSocket +{ + friend class HashIterator; + +public: + Hash(CollectionSize size, Node *node, Logical has_unique_entries); + ~Hash(); + + Logical TestInstance() const; + static Logical TestClass(); + static Logical ProfileClass(); + +protected: + void AddImplementation(Plug *plug); + void AddValueImplementation(Plug *plug, const void *value); + Plug *FindImplementation(const void *value); + + VChain **hashTable; + CollectionSize hashTableSize; + +private: + virtual VChain* MakeVChain(); + + virtual IteratorPosition GetHashIndex(const void *value); + + void BuildHashTable(); +}; + +template class HashOf : public Hash +{ +public: + HashOf(CollectionSize size, Node *node, Logical has_unique_entries); + ~HashOf(); + + void AddValue(T plug, const V &value) { AddValueImplementation(Cast_Object(Plug*, plug), &value); } + + T Find(const V &value) { return (T)FindImplementation(&value); } + +private: + VChain *MakeVChain(); + + IteratorPosition GetHashIndex(const void *value); +}; + +template HashOf::HashOf(CollectionSize size, Node *node, Logical has_unique_entries) : Hash(size, node, has_unique_entries) +{ +} + +template HashOf::~HashOf() +{ +} + +template VChain *HashOf::MakeVChain() +{ + return new VChainOf(GetReleaseNode(), HasUniqueEntries()); +} + +template IteratorPosition HashOf::GetHashIndex(const void *value) +{ + Check_Pointer(value); + return (IteratorPosition(*(V*)value) % hashTableSize); + // return ((IteratorPosition)*(V*)value % hashTableSize); +} + +class HashIterator : public SortedIterator +{ +public: + HashIterator(Hash *hash); + ~HashIterator(); + Logical TestInstance() const; + + void First(); + void Last(); + void Next(); + void Previous(); + CollectionSize GetSize(); + void Remove(); + +protected: +#if 0 + void *ReadAndNextImplementation(); + void *ReadAndPreviousImplementation(); +#endif + void *GetCurrentImplementation(); +#if 0 + void *GetNthImplementation(CollectionSize index); +#endif + Plug *FindImplementation(const void *value); + +private: + void ReceiveMemo(IteratorMemo memo, void *content); + + void DeleteVChainIterator(); + + void NextVChainIterator(IteratorPosition index); + + VChain **hashTable; + CollectionSize hashTableSize; + IteratorPosition currentPosition; + VChainIterator *vchainIterator; +}; + +template class HashIteratorOf : public HashIterator +{ +public: + HashIteratorOf(HashOf *hash); + HashIteratorOf(HashOf &hash); + ~HashIteratorOf(); + + T ReadAndNext() { return (T)ReadAndNextImplementation(); } + T ReadAndPrevious() { return (T)ReadAndPreviousImplementation(); } + T GetCurrent() { return (T)GetCurrentImplementation(); } + T GetNth(CollectionSize index) { return (T)GetNthImplementation(index); } + T Find(const V &value) { return (T)FindImplementation(&value); } +}; + +template HashIteratorOf::HashIteratorOf(HashOf *hash) : HashIterator(hash) +{ +} + +template HashIteratorOf::HashIteratorOf(HashOf &hash) : HashIterator(&hash) +{ +} + +template HashIteratorOf::~HashIteratorOf() +{ +} \ No newline at end of file diff --git a/MUNGA/HOST.cpp b/MUNGA/HOST.cpp new file mode 100644 index 0000000..f36ee6f --- /dev/null +++ b/MUNGA/HOST.cpp @@ -0,0 +1,139 @@ +#include "munga.h" +#pragma hdrstop + +#include "host.h" +#include "entity.h" + +//############################################################################# +//################################ Host ################################# +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +Host::Host( + HostID host_ID, + HostType host_type, + const SOCKADDR_IN *network_address +): + hostType(host_type), + allEntitySocket(NULL), + dynamicMasterEntitySocket(NULL), + dynamicReplicantEntitySocket(NULL) +{ + Verify(host_ID >= FirstLegalHostID); + hostID = host_ID; + if (network_address) + networkAddress = *network_address; + else + memset(&networkAddress, 0, sizeof(networkAddress)); + currentConnectStatus = NoNetworkConnectionStatus; +} + +// +//############################################################################# +//############################################################################# +// +Host::~Host() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Host::TestInstance() const +{ + Node::TestInstance(); + + Verify(hostID >= FirstLegalHostID); + Verify( + hostType == GameMachineHostType || + hostType == MissionReviewHostType || + hostType == ConsoleHostType + ); + Check(&allEntitySocket); + Check(&dynamicMasterEntitySocket); + Check(&dynamicReplicantEntitySocket); + + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + Host::AddEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + // Add entity to all socket + // + allEntitySocket.Add(entity); + + // + // Conditionally add entity to aux sockets + // + switch (entity->GetInstance()) + { + case Entity::MasterInstance: + case Entity::IndependantInstance: + case Entity::HermitInstance: + if (entity->IsDynamic()) + { + dynamicMasterEntitySocket.Add(entity); + } + break; + + case Entity::ReplicantInstance: + if (entity->IsDynamic()) + { + dynamicReplicantEntitySocket.Add(entity); + } + break; + + default: + Fail("Host::AddEntity - Should never reach here"); + break; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~ Host__AllEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Host__AllEntityIterator::Host__AllEntityIterator(Host *host): + SChainIteratorOf(&host->allEntitySocket) +{ +} + +Host__AllEntityIterator::~Host__AllEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~ Host__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~~~~~~~ + +Host__DynamicMasterEntityIterator:: + Host__DynamicMasterEntityIterator(Host *host): + SChainIteratorOf(&host->dynamicMasterEntitySocket) +{ +} + +Host__DynamicMasterEntityIterator::~Host__DynamicMasterEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~ Host__DynamicReplicantEntityIterator ~~~~~~~~~~~~~~~~~~~ + +Host__DynamicReplicantEntityIterator:: + Host__DynamicReplicantEntityIterator(Host *host): + SChainIteratorOf(&host->dynamicReplicantEntitySocket) +{ +} + +Host__DynamicReplicantEntityIterator::~Host__DynamicReplicantEntityIterator() +{ +} diff --git a/MUNGA/HOST.h b/MUNGA/HOST.h new file mode 100644 index 0000000..aa67f56 --- /dev/null +++ b/MUNGA/HOST.h @@ -0,0 +1,186 @@ +#pragma once + +#include "node.h" +#include "hostid.h" +#include "schain.h" +#include "network.h" + +class Entity; + +//########################################################################## +//####### Support types for entity identity and host manager ######### +//########################################################################## + +enum HostType +{ + GameMachineHostType, + CameraShipHostType, + MissionReviewHostType, + ConsoleHostType +}; + +//########################################################################## +//############################ Host ################################## +//########################################################################## + +class Host: + public Node +{ + friend class HostManager; + + friend class Host__AllEntityIterator; + friend class Host__DynamicMasterEntityIterator; + friend class Host__DynamicReplicantEntityIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public types +// +public: + typedef Host__AllEntityIterator + AllEntityIterator; + + // + // NoNetworkConnectionStatus - + // Initial state, host just created with no net link + // OpeningConnectionStatus - + // Waiting for completion of an active open to this host + // ListeningConnectionStatus - + // Waiting for this host to connect to us + // OnLineConnectionStatus - + // Host is on-line and ready + // + enum ConnectionStatus + { + NoNetworkConnectionStatus, + OpeningConnectionStatus, + ListeningConnectionStatus, + OnLineConnectionStatus + }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and testing +// +public: + Host( + HostID host_ID, + HostType host_type, + const SOCKADDR_IN *network_address + ); + ~Host(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +public: + HostType + GetHostType(); + HostID + GetHostID(); + + inline SOCKADDR_IN *GetNetworkAddress() { return &networkAddress; } + inline void SetNetworkAddress(const SOCKADDR_IN *network_address) { networkAddress = *network_address; } + + ConnectionStatus + GetConnectStatus(); + void + SetConnectStatus(ConnectionStatus new_status); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Host Manager support +// +private: + void + AddEntity(Entity *entity); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + HostID hostID; + HostType hostType; + SOCKADDR_IN networkAddress; + ConnectionStatus currentConnectStatus; + + // + // The all entity socket contains all entities that are on this host. + // + SChainOf + allEntitySocket; + + // + // The dynamic master entity socket contains all entities that are + // masters and dynamic + // + SChainOf + dynamicMasterEntitySocket; + + // + // The dynamic replicant entity socket contains all entities that are + // replicants and dynamic + // + SChainOf + dynamicReplicantEntitySocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Host inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline HostType + Host::GetHostType() +{ + Check(this); + return hostType; +} + +inline HostID + Host::GetHostID() +{ + Check(this); + return hostID; +} + +inline Host::ConnectionStatus + Host::GetConnectStatus() +{ + Check(this); + return currentConnectStatus; +} + +inline void + Host::SetConnectStatus(ConnectionStatus new_status) +{ + Check(this); + currentConnectStatus = new_status; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ Host__AllEntityIterator ~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Host__AllEntityIterator: + public SChainIteratorOf +{ +public: + Host__AllEntityIterator(Host *host); + ~Host__AllEntityIterator(); +}; + +//~~~~~~~~~~~~~~~~~~~~ Host__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~~~~~ + +class Host__DynamicMasterEntityIterator: + public SChainIteratorOf +{ +public: + Host__DynamicMasterEntityIterator(Host *host); + ~Host__DynamicMasterEntityIterator(); +}; + +//~~~~~~~~~~~~~~~~~~~ Host__DynamicReplicantEntityIterator ~~~~~~~~~~~~~~~~~ + +class Host__DynamicReplicantEntityIterator: + public SChainIteratorOf +{ +public: + Host__DynamicReplicantEntityIterator(Host *host); + ~Host__DynamicReplicantEntityIterator(); +}; diff --git a/MUNGA/HOSTID.h b/MUNGA/HOSTID.h new file mode 100644 index 0000000..f5f7b39 --- /dev/null +++ b/MUNGA/HOSTID.h @@ -0,0 +1,9 @@ +#pragma once + +#include "style.h" + +typedef Enumeration HostID; + +const HostID NullHostID = 0; +const HostID MapHostID = -1; +const HostID FirstLegalHostID = 1; \ No newline at end of file diff --git a/MUNGA/HOSTMGR.cpp b/MUNGA/HOSTMGR.cpp new file mode 100644 index 0000000..48bde48 --- /dev/null +++ b/MUNGA/HOSTMGR.cpp @@ -0,0 +1,697 @@ +#include "munga.h" +#pragma hdrstop + +#include "hostmgr.h" +#include "interest.h" +#include "app.h" +#include "entity.h" + +//############################################################################# +//######################### HostManager ################################# +//############################################################################# + +// +// HACK - EntitySocketHashSize should come from somewhere else +// +const CollectionSize EntitySocketHashSize = 500; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HostManager data +// +HostManager::SharedData + HostManager::DefaultData( + HostManager::GetClassDerivations(), + HostManager::GetMessageHandlers() + ); + +Derivation* HostManager::GetClassDerivations() +{ + static Derivation classDerivations(NetworkClient::GetClassDerivations(), "HostManager"); + return &classDerivations; +} + +const Receiver::HandlerEntry + HostManager::MessageHandlerEntries[]= +{ + { + HostManager::NewHostMessageID, + "NewHost", + (HostManager::Handler)&Receiver::DefaultMessageHandler // HACK + }, + { + HostManager::HostUpdateMessageID, + "HostUpdate", + (HostManager::Handler)&Receiver::DefaultMessageHandler // HACK + }, + { + HostManager::EntityTransferOwnershipMessageID, + "EntityTransferOwnership", + (HostManager::Handler)&HostManager::EntityTransferOwnershipHandler + }, + { + HostManager::EntityNewOwnershipMessageID, + "EntityNewOwnership", + (HostManager::Handler)&HostManager::EntityNewOwnershipHandler + } +}; + +Receiver::MessageHandlerSet& HostManager::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(HostManager::MessageHandlerEntries), HostManager::MessageHandlerEntries, Receiver::GetMessageHandlers()); + return messageHandlers; +} + +// +//############################################################################# +// HostManager +//############################################################################# +// +HostManager::HostManager(): + NetworkClient(HostManagerClassID, DefaultData, HostManagerClientID), + remoteHostSocket(NULL, True), + allHostSocket(NULL, True), + entityIndexSocket(EntitySocketHashSize, NULL, True) +{ + localHost = NULL; + allHostIterator = NULL; +} + +// +//############################################################################# +//############################################################################# +// +HostManager::~HostManager() +{ + if (allHostIterator != NULL) + { + Unregister_Object(allHostIterator); + delete allHostIterator; + allHostIterator = NULL; + } + + Verify(localHost == NULL); + + #if DEBUG_LEVEL>0 + { + TableIteratorOf iterator(&remoteHostSocket); + Check(&iterator); + Verify(iterator.GetSize() == 0); + } + #endif + + #if DEBUG_LEVEL>0 + { + HashIteratorOf iterator(&entityIndexSocket); + Check(&iterator); + Verify(iterator.GetSize() == 0); + } + #endif +} + +// +//############################################################################# +//############################################################################# +// +Logical + HostManager::TestInstance() const +{ + if (!IsDerivedFrom(*GetClassDerivations())) + { + return False; + } + + if (localHost != NULL) + { + Check(localHost) + } + if (allHostIterator != NULL) + { + Check(allHostIterator) + } + Check(&remoteHostSocket); + Check(&allHostSocket); + Check(&lastEntityID); + Check(&entityIndexSocket); + return True; +} + +// +//############################################################################# +// Shutdown +//############################################################################# +// +void + HostManager::Shutdown() +{ + Check(this); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // For (each transferrable entity) + //-------------------------------------------------------------------------- + // + // + // Find new host for ownership + // + + // + // Send transfer entity ownership to that host + // + #else + // + //-------------------------------------------------------------------------- + // Delete all of the entities + //-------------------------------------------------------------------------- + // + if (localHost != NULL) + { + Check(localHost); + Host::AllEntityIterator iterator(localHost); + Check(&iterator); + iterator.DeletePlugs(); + } + #endif +} + +// +//############################################################################# +// AdoptLocalHost +//############################################################################# +// +void + HostManager::AdoptLocalHost(Host *local_host) +{ + Check(this); + Check(local_host); + + // + //-------------------------------------------------------------------------- + // Verify that the local host is currently unassigned and then assign it + //-------------------------------------------------------------------------- + // + Verify(lastEntityID == EntityID::Null); + Verify(localHost == NULL); + localHost = local_host; + + EntityID entity_ID(local_host->GetHostID()); + lastEntityID = entity_ID; + + // + //-------------------------------------------------------------------------- + // Add the local host to the all host socket + //-------------------------------------------------------------------------- + // + allHostSocket.AddValue(local_host, local_host->GetHostID()); +} + +// +//############################################################################# +// OrphanLocalHost +//############################################################################# +// +Host* + HostManager::OrphanLocalHost() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Unassign the local host + //-------------------------------------------------------------------------- + // + Host *local_host = localHost; + localHost = NULL; + lastEntityID = EntityID::Null; + + // + //-------------------------------------------------------------------------- + // Remove the local host from the all host socket + //-------------------------------------------------------------------------- + // + if (local_host != NULL) + { + Check(local_host); + PlugIterator remover(local_host); + remover.RemoveSocket(&allHostSocket); + } + return local_host; +} + +// +//############################################################################# +// AdoptRemoteHost +//############################################################################# +// +void + HostManager::AdoptRemoteHost(Host *remote_host) +{ + Check(this); + Check(remote_host); + + // + //-------------------------------------------------------------------------- + // Add to the remote and all host socket + //-------------------------------------------------------------------------- + // + remoteHostSocket.AddValue(remote_host, remote_host->GetHostID()); + allHostSocket.AddValue(remote_host, remote_host->GetHostID()); +} + +// +//############################################################################# +// OrphanRemoteHost +//############################################################################# +// +void + HostManager::OrphanRemoteHost(Host *remote_host) +{ + Check(this); + Check(remote_host); + + // + //-------------------------------------------------------------------------- + // Remove from the remote and all host socket + //-------------------------------------------------------------------------- + // + { + PlugIterator remover(remote_host); + remover.RemoveSocket(&remoteHostSocket); + } + { + PlugIterator remover(remote_host); + remover.RemoveSocket(&allHostSocket); + } +} + +// +//############################################################################# +// GetLocalHostID +//############################################################################# +// +HostID + HostManager::GetLocalHostID() +{ + Check(this); + Check(localHost); + return localHost->GetHostID(); +} + +// +//############################################################################# +// GetRemoteHost +//############################################################################# +// +Host* + HostManager::GetRemoteHost(HostID host_ID) +{ + Check(this); + Verify(host_ID >= FirstLegalHostID); + + return remoteHostSocket.Find(host_ID); +} + +// +//############################################################################# +// GetConsoleHost +//############################################################################# +// +Host* + HostManager::GetConsoleHost() +{ + Check(this); + + Host *host; + TableIteratorOf iterator(&remoteHostSocket); + + Check(&iterator); + while ((host = iterator.ReadAndNext()) != NULL) + { + Check(host); + if (host->GetHostType() == ConsoleHostType) + return host; + } + return NULL; +} + +// +//############################################################################# +// FindHost +//############################################################################# +// +Host* HostManager::FindHost(SOCKADDR_IN &net_address) +{ + Host *host; + TableIteratorOf iterator(&allHostSocket); + + while ((host = iterator.ReadAndNext()) != NULL) + if (*host->GetNetworkAddress() == net_address) + return host; + + return NULL; +} + +// +//############################################################################# +// MakeUniqueEntityID +//############################################################################# +// +EntityID + HostManager::MakeUniqueEntityID() +{ + Check(this); + Verify(lastEntityID != EntityID::Null); + + return (lastEntityID += 1); +} + +// +//############################################################################# +// NotifyOfEntityCreation +//############################################################################# +// +void + HostManager::NotifyOfEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // The host keeps track of all entities + //-------------------------------------------------------------------------- + // + Check(localHost); + localHost->AddEntity(entity); + + // + //-------------------------------------------------------------------------- + // Link the entity to our index + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Check(&entityIndexSocket); + entityIndexSocket.AddValue(entity, entity->GetEntityID()); + + // + //-------------------------------------------------------------------------- + // Call interest manager + //-------------------------------------------------------------------------- + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->NotifyOfEntityCreation( + entity, + creation_message + ); +} + +// +//############################################################################# +// NotifyOfReplacementEntityCreation +//############################################################################# +// +void + HostManager::NotifyOfReplacementEntityCreation( + Entity*, + EntityID, + ClassID, + LWord + ) +{ + Fail("HostManager::NotifyOfReplacementEntityCreation - under construction"); +} + +// +//############################################################################# +// NotifyOfEntityDestruction +//############################################################################# +// +void + HostManager::NotifyOfEntityDestruction(Entity *entity) +{ + // + //-------------------------------------------------------------------------- + // Perform any additional processing here... + //-------------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------------- + // Notify interest manager of the destruction + //-------------------------------------------------------------------------- + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->NotifyOfEntityDestruction(entity); +} + +// +//############################################################################# +// IdentifyNewMapEntityHost +//############################################################################# +// +HostID + HostManager::IdentifyNewMapEntityHost( + EntityID + ) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // HACK - Partial Implementation, since the entity IDs are not yet + // precomputed several assumptions are made. 1) The map stream read by each + // pilot is identical. 2) All of the hosts are connected at the point that + // the stream is read. => Therefore, it is easy to allocate the entities to + // each host. + //-------------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------------- + // Verify that legal map entity hosts exist + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + { + TableIteratorOf iterator(&allHostSocket); + Host *host; + CollectionSize legal_map_entity_hosts = 0; + + while ((host = iterator.ReadAndNext()) != NULL) + { + if (host->GetHostType() == GameMachineHostType) + { + legal_map_entity_hosts++; + } + } + Verify(legal_map_entity_hosts > 0); + } + #endif + + // + //-------------------------------------------------------------------------- + // Check the host iterator + //-------------------------------------------------------------------------- + // + if (allHostIterator == NULL) + { + allHostIterator = new TableIteratorOf(&allHostSocket); + Register_Object(allHostIterator); + } + Check(allHostIterator); + + // + //-------------------------------------------------------------------------- + // Get a legal map entity host + //-------------------------------------------------------------------------- + // + Host *map_entity_host; + Logical is_legal_map_entity_host = False; + + do + { + if ((map_entity_host = allHostIterator->GetCurrent()) == NULL) + { + allHostIterator->First(); + map_entity_host = allHostIterator->GetCurrent(); + } + Check(map_entity_host); + if (map_entity_host->GetHostType() == GameMachineHostType) + { + is_legal_map_entity_host = True; + } + else + { + allHostIterator->Next(); + } + } + while (!is_legal_map_entity_host); + + // + //-------------------------------------------------------------------------- + // Move to the next host + //-------------------------------------------------------------------------- + // + allHostIterator->Next(); + + // + //-------------------------------------------------------------------------- + // Return the map entity host ID + //-------------------------------------------------------------------------- + // + Check(map_entity_host); + Verify(map_entity_host->GetHostType() == GameMachineHostType); + Verify(map_entity_host->GetHostID() != NullHostID); + + return map_entity_host->GetHostID(); +} + +// +//############################################################################# +// EntityTransferOwnership +//############################################################################# +// +void + HostManager::EntityTransferOwnershipHandler( + EntityTransferOwnershipMessage* + ) +{ + #if 0 + // + // Find replicant for this entity + // + + // + // If (replicant found) + // + // + // Morph the replicant into the master replicant + // + + // + // If (the replicant was not found) + // + // + // Make a transferred master entity + // + + // + // Broadcast new entity ownership + // + #else + Fail("HostManager::EntityTransferOwnershipHandler - under construction"); + #endif +} + +// +//############################################################################# +// EntityNewOwnership +//############################################################################# +// +void + HostManager::EntityNewOwnershipHandler( + EntityNewOwnershipMessage* + ) +{ + #if 0 + // + // If (this host is the owner host) + // + // + // Return + // + + // + // Find the replicant for this entity + // + // + // If (found the replicant) + // + // + // Point it at the new owner + // + #else + Fail("HostManager::EntityNewOwnershipHandler - under construction"); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllEntityIterator ~~~~~~~~~~~~~~~~~~~~~ + +HostManager__AllEntityIterator::HostManager__AllEntityIterator( + HostManager *host_manager +): + Host__AllEntityIterator(host_manager->localHost) +{ +} + +HostManager__AllEntityIterator::~HostManager__AllEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~ HostManager__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~~~ + +HostManager__DynamicMasterEntityIterator:: + HostManager__DynamicMasterEntityIterator( + HostManager *host_manager + ): + Host__DynamicMasterEntityIterator(host_manager->localHost) +{ +} + +HostManager__DynamicMasterEntityIterator:: + ~HostManager__DynamicMasterEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~ HostManager__DynamicReplicantEntityIterator ~~~~~~~~~~~~~~~ + +HostManager__DynamicReplicantEntityIterator:: + HostManager__DynamicReplicantEntityIterator( + HostManager *host_manager + ): + Host__DynamicReplicantEntityIterator(host_manager->localHost) +{ +} + +HostManager__DynamicReplicantEntityIterator:: + ~HostManager__DynamicReplicantEntityIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__RemoteHostIterator ~~~~~~~~~~~~~~~~~~~~ + +HostManager__RemoteHostIterator::HostManager__RemoteHostIterator( + HostManager *host_manager +): + TableIteratorOf(&host_manager->remoteHostSocket) +{ +} + +HostManager__RemoteHostIterator::~HostManager__RemoteHostIterator() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllHostIterator ~~~~~~~~~~~~~~~~~~~~~~~ + +HostManager__AllHostIterator::HostManager__AllHostIterator( + HostManager *host_manager +): + TableIteratorOf(&host_manager->allHostSocket) +{ +} + +HostManager__AllHostIterator::~HostManager__AllHostIterator() +{ +} + +#if 0 + #if defined(TEST_CLASS) + #include "host.tcp" + #endif +#endif diff --git a/MUNGA/HOSTMGR.h b/MUNGA/HOSTMGR.h new file mode 100644 index 0000000..04fda8b --- /dev/null +++ b/MUNGA/HOSTMGR.h @@ -0,0 +1,367 @@ +#pragma once + +#include "network.h" +#include "host.h" +#include "table.h" +#include "hash.h" +#include "entityid.h" + +class Entity; +class Entity__MakeMessage; + +//########################################################################## +//######################### HostManager ############################## +//########################################################################## + +class HostManager__EntityTransferOwnershipMessage; +class HostManager__EntityNewOwnershipMessage; + +class HostManager: + public NetworkClient +{ + friend class HostManager__AllEntityIterator; + friend class HostManager__DynamicMasterEntityIterator; + friend class HostManager__DynamicReplicantEntityIterator; + + friend class HostManager__RemoteHostIterator; + friend class HostManager__AllHostIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public types +// +public: + typedef HostManager__AllEntityIterator + AllEntityIterator; + typedef HostManager__DynamicMasterEntityIterator + DynamicMasterEntityIterator; + typedef HostManager__DynamicReplicantEntityIterator + DynamicReplicantEntityIterator; + + typedef HostManager__RemoteHostIterator + RemoteHostIterator; + typedef HostManager__AllHostIterator + AllHostIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and testing +// +public: + HostManager(); + ~HostManager(); + + Logical + TestInstance() const; + static void + TestClass(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execution control +// +public: + void + Shutdown(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local and remote host methods +// +public: + // + //----------------------------------------------------------------------- + // AdoptLocalHost, OrphanLocalHost + //----------------------------------------------------------------------- + // + void + AdoptLocalHost(Host *local_host); + Host* + OrphanLocalHost(); + + // + //----------------------------------------------------------------------- + // GetLocalHostID, GetLocalHost + //----------------------------------------------------------------------- + // + HostID + GetLocalHostID(); + Host* + GetLocalHost(); + + // + //----------------------------------------------------------------------- + // AdoptRemoteHost, OrphanRemoteHost + //----------------------------------------------------------------------- + // + void + AdoptRemoteHost(Host *remote_host); + void + OrphanRemoteHost(Host *remote_host); + + // + //----------------------------------------------------------------------- + // GetRemoteHost, GetConsoleHost, FindHost + //----------------------------------------------------------------------- + // + Host* GetRemoteHost(HostID host_ID); + Host* GetConsoleHost(); + Host* FindHost(SOCKADDR_IN &net_address); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Entity methods +// +public: + // + //----------------------------------------------------------------------- + // MakeUniqueEntityID + // + // Returns a unique entity indentity + //----------------------------------------------------------------------- + // + EntityID + MakeUniqueEntityID(); + + // + //----------------------------------------------------------------------- + // NotifyOfEntityCreation + // + // This method is called to notify the host manager that a new entity + // has been created on this host. + //----------------------------------------------------------------------- + // + void + NotifyOfEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + + // + //----------------------------------------------------------------------- + // NotifyOfEntityDestruction + // + // This method is called to notify the host manager that a entity is + // being destroyed. + //----------------------------------------------------------------------- + // + void + NotifyOfEntityDestruction(Entity *entity); + + // + //----------------------------------------------------------------------- + // NotifyOfReplacementEntityCreation + // + // This method is called by the registry manager to notify the + // host manager that a new replacement entity has been + // created on this host. + //----------------------------------------------------------------------- + // + void + NotifyOfReplacementEntityCreation( + Entity *entity, + EntityID entity_ID, + ClassID entity_class, + LWord entity_type + ); + + // + //----------------------------------------------------------------------- + // GetEntityPointer + // + // Returns a pointer to the entity specified by entityID. + //----------------------------------------------------------------------- + // + Entity* + GetEntityPointer(const EntityID &entityID); + + // + //----------------------------------------------------------------------- + // IdentifyNewMapEntityHost + // + // For LAN specific solutions the host manager can return the + // host id of a new map entity prior to its creation. This + // method uses an algorithm to determine this value and returns + // it. + //----------------------------------------------------------------------- + // + HostID + IdentifyNewMapEntityHost(EntityID entity_ID); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + // + // Message IDs + // + enum + { + NewHostMessageID = NetworkClient::NextMessageID, + HostUpdateMessageID, + EntityTransferOwnershipMessageID, + EntityNewOwnershipMessageID, + NextMessageID + }; + + // + // Message types + // + typedef HostManager__EntityTransferOwnershipMessage + EntityTransferOwnershipMessage; + typedef HostManager__EntityNewOwnershipMessage + EntityNewOwnershipMessage; + + // + //----------------------------------------------------------------------- + // EntityTransferOwnership + //----------------------------------------------------------------------- + // + void + EntityTransferOwnershipHandler(EntityTransferOwnershipMessage*); + + // + //----------------------------------------------------------------------- + // EntityNewOwnership + //----------------------------------------------------------------------- + // + void + EntityNewOwnershipHandler(EntityNewOwnershipMessage*); + + // + //----------------------------------------------------------------------- + // Message table, Shared data + //----------------------------------------------------------------------- + // + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + static Derivation *GetClassDerivations(); + static SharedData + DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + Host + *localHost; + TableOf + remoteHostSocket; + TableOf + allHostSocket; + TableIteratorOf + *allHostIterator; + + // + // The last entity id to be allocated, used to allocate a new one + // + EntityID + lastEntityID; + + // + // The entity index socket holds all entities, static, dynamic, + // replicant, etc... + // + HashOf + entityIndexSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ HostManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline Entity* + HostManager::GetEntityPointer(const EntityID &entity_ID) +{ + Check(this); + return entityIndexSocket.Find(entity_ID); +} + +inline Host* + HostManager::GetLocalHost() +{ + Check(this); + + // + // GAC removed this so we can use the call to see if a + // local host exists or not, there doesn't seem to be + // any call for this. Host Manager initializes localHost + // to NULL and all routines check it before use so this + // shouldn't cause any problems. + // + // Check(localHost); + + return localHost; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ HostManager messages ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class HostManager__EntityTransferOwnershipMessage: + public NetworkClient::Message +{ +public: + HostManager__EntityTransferOwnershipMessage(): + NetworkClient::Message( + HostManager::EntityTransferOwnershipMessageID, + sizeof(HostManager__EntityTransferOwnershipMessage) + ) + {} +}; + +class HostManager__EntityNewOwnershipMessage: + public NetworkClient::Message +{ +public: + HostManager__EntityNewOwnershipMessage(): + NetworkClient::Message( + HostManager::EntityNewOwnershipMessageID, + sizeof(HostManager__EntityNewOwnershipMessage) + ) + {} +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllEntityIterator ~~~~~~~~~~~~~~~~~~ + +class HostManager__AllEntityIterator: + public Host__AllEntityIterator +{ +public: + HostManager__AllEntityIterator(HostManager *host_manager); + ~HostManager__AllEntityIterator(); +}; + +//~~~~~~~~~~~~~~~~~ HostManager__DynamicMasterEntityIterator ~~~~~~~~~~~~~~~ + +class HostManager__DynamicMasterEntityIterator: + public Host__DynamicMasterEntityIterator +{ +public: + HostManager__DynamicMasterEntityIterator(HostManager *host_manager); + ~HostManager__DynamicMasterEntityIterator(); +}; + +//~~~~~~~~~~~~~~~~~ HostManager__DynamicReplicantEntityIterator ~~~~~~~~~~~~ + +class HostManager__DynamicReplicantEntityIterator: + public Host__DynamicReplicantEntityIterator +{ +public: + HostManager__DynamicReplicantEntityIterator(HostManager *host_manager); + ~HostManager__DynamicReplicantEntityIterator(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__RemoteHostIterator ~~~~~~~~~~~~~~~~~ + +class HostManager__RemoteHostIterator: + public TableIteratorOf +{ +public: + HostManager__RemoteHostIterator(HostManager *host_manager); + ~HostManager__RemoteHostIterator(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ HostManager__AllHostIterator ~~~~~~~~~~~~~~~~~~~~ + +class HostManager__AllHostIterator: + public TableIteratorOf +{ +public: + HostManager__AllHostIterator(HostManager *host_manager); + ~HostManager__AllHostIterator(); +}; diff --git a/MUNGA/ICOM.cpp b/MUNGA/ICOM.cpp new file mode 100644 index 0000000..6ca0d40 --- /dev/null +++ b/MUNGA/ICOM.cpp @@ -0,0 +1,475 @@ +#include "munga.h" +#pragma hdrstop + +#include "icom.h" +#include "app.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) Tell(n << flush); +#else +# define Test_Tell(n) +#endif + +//########################################################################## +//############################# Icom ################################# +//########################################################################## +Icom::Icom( + HostID host_id, + int unit_number +): +Plug(IcomClassID) +{ + Test_Tell("Icom::Icom(" << host_id << ", " << unit_number << ")\n"); + Check_Pointer(this); + //-------------------------------------- + // Initialize values + //-------------------------------------- + hostID = host_id; + unitNumber = unit_number; + channel = undefinedChannel; + channelBeforePA = undefinedChannel; + PTTStatus = False; + PACaptive = False; + + Check_Fpu(); +} + +Icom::~Icom() +{ + Test_Tell("Icom::~Icom()\n"); + Check(this); + //-------------------------------------- + // Cleanup before deletion + //-------------------------------------- + SetPTTStatusValue(False); + SetChannelValue(undefinedChannel); + //-------------------------------------- + // The plug automatically unlinks + // from the Icom Manager upon deletion. + //-------------------------------------- + Check_Fpu(); +} + +Logical + Icom::TestInstance() const +{ + Plug::TestInstance(); + Check_Fpu(); + return True; +} + +//-------------------------------------------------------------------------- +void + Icom::SetChannel(int new_channel) +{ + Test_Tell("Icom::SetChannel(" << new_channel << ")\n"); + Check(this); + //-------------------------------------- + // Broadcast the change + // (nonexclusive broadcast: we receive + // and process this msg locally) + //-------------------------------------- + IcomManager::IMMessage + message; + + message.BuildChannelMessage( + IcomManager::ChannelMessageID, + hostID, + unitNumber, + new_channel + ); + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + NetworkClient::IcomManagerClientID, + &message + ); + + Check_Fpu(); +} + +void + Icom::SetChannelValue(int new_channel) +{ + Test_Tell("Icom::SetChannelValue(" << new_channel << ")\n"); + Check(this); + //-------------------------------------- + // Set local value + //-------------------------------------- + channel = new_channel; + Check_Fpu(); +} + +int + Icom::GetChannel() +{ + Check(this); + Check_Fpu(); + return channel; +} + +//-------------------------------------------------------------------------- +void + Icom::SetPTTStatus(Logical new_ptt) +{ + Test_Tell("Icom::SetPTTStatus(" << new_ptt << ")\n"); + Check(this); + + //--------------------------------------- + // Disallow talking during public address + //--------------------------------------- + if (!PACaptive) + { + //-------------------------------------- + // Broadcast change + // (nonexclusive broadcast: we receive + // and process this msg locally) + //-------------------------------------- + IcomManager::IMMessage + message; + + message.BuildPTTMessage( + IcomManager::PTTMessageID, + hostID, + unitNumber, + new_ptt + ); + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + NetworkClient::IcomManagerClientID, + &message + ); + } + + Check_Fpu(); +} + +void + Icom::SetPTTStatusValue(Logical new_ptt) +{ + Test_Tell("Icom::SetPTTStatusValue(" << new_ptt << ")\n"); + Check(this); + //--------------------------------------- + // Disallow talking during public address + //--------------------------------------- + if (!PACaptive) + { + PTTStatus = new_ptt; + } + Check_Fpu(); +} + +Logical + Icom::GetPTTStatus() +{ + Check(this); + Check_Fpu(); + return PTTStatus; +} + +//-------------------------------------------------------------------------- +void + Icom::SetPACaptive(Logical new_pa) +{ + Test_Tell("Icom::SetPACaptive(" << new_pa << ")\n"); + Check(this); + + //-------------------------------------- + // Broadcast the change + // (nonexclusive broadcast: we receive + // and process this msg locally) + //-------------------------------------- + IcomManager::IMMessage + message; + + message.BuildPAMessage( + IcomManager::PAMessageID, + hostID, + unitNumber, + new_pa + ); + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + NetworkClient::IcomManagerClientID, + &message + ); + + Check_Fpu(); +} + +void + Icom::SetPACaptiveValue(Logical new_pa) +{ + Test_Tell("Icom::SetPACaptiveValue(" << new_pa << ")\n"); + Check(this); + + if (new_pa == True) + { + if (PACaptive == False) + { + channelBeforePA = channel; + } + //-------------------------------------- + // Force PTT off during public address + //-------------------------------------- + if (PTTStatus == True) + { + SetPTTStatusValue(False); + } + } + else + { + //-------------------------------------- + // Return to previous channel + //-------------------------------------- + SetChannelValue(channelBeforePA); + } + PACaptive = new_pa; + Check_Fpu(); +} + +Logical + Icom::GetPACaptive() +{ + Check(this); + Check_Fpu(); + return PACaptive; +} + +//########################################################################## +//######################### IcomManager ############################## +//########################################################################## + +//-------------------------------------------------------------------------- +// Virtual Data support +// + +Derivation* IcomManager::GetClassDerivations() +{ + static Derivation classDerivations(NetworkClient::GetClassDerivations(), "IcomManager"); + return &classDerivations; +} + +IcomManager::SharedData + IcomManager::DefaultData( + IcomManager::GetClassDerivations(), + IcomManager::GetMessageHandlers() + ); + +//-------------------------------------------------------------------------- +// Creator +// +IcomManager::IcomManager( + SharedData &shared_data +): +NetworkClient(IcomManagerClassID, shared_data, IcomManagerClientID), +instanceList(this) +{ + Test_Tell("IcomManager::IcomManager()\n"); + Check_Pointer(this); + + //-------------------------------- + // Initialize unit number service + //-------------------------------- + nextUnitNumber = 0; + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +// Destructor +// +IcomManager::~IcomManager() +{ + Test_Tell("IcomManager::~IcomManager()\n"); + Check(this); + + Shutdown(); + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +Logical + IcomManager::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//-------------------------------------------------------------------------- +void + IcomManager::LoadMission(Mission */*mission*/) +{ + Check(this); + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + IcomManager::Shutdown() +{ + Check(this); + + Icom + *icom; + ChainIteratorOf + i(instanceList); + + //------------------------------------------ + // Delete all icom objects + //------------------------------------------ + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + Unregister_Object(icom); + delete icom; + } + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + IcomManager::Execute() +{ + Check(this); + Fail("IcomManager::Execute() should not be called directly!\n"); +} + +//-------------------------------------------------------------------------- +Icom * + IcomManager::MakeIcom(HostID host_id, int unit_number) +{ + Test_Tell( + "IcomManager::MakeIcom(" << host_id << + ", " << unit_number << + ")\n" + ); + Check(this); + + //------------------------------------------ + // Create, register icom object + //------------------------------------------ + Icom + *icom = new Icom(host_id, unit_number); + Check(icom); + Register_Object(icom); + //------------------------------------------ + // Add to global list + //------------------------------------------ + instanceList.Add(icom); + + Check_Fpu(); + return icom; +} + +//------------------------------------------------------------------------ +void + IcomManager::SetPAState(int pa_channel) +{ + Test_Tell("IcomManager::SetPAState(" << pa_channel << ")\n"); + Check(this); + + Icom + *icom; + + ChainIteratorOf + i(instanceList); + + if (pa_channel == Icom::undefinedChannel) + { + //------------------------------------------ + // Release all icom objects from PA state + //------------------------------------------ + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + icom->SetPACaptive(False); + } + } + else + { + //------------------------------------------ + // Force all icom objects to PA state + //------------------------------------------ + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + icom->SetPACaptive(True); + icom->SetChannel(pa_channel); + } + } + Check_Fpu(); +} + +//------------------------------------------------------------------------ +Icom* + IcomManager::FindIcom(HostID host_id, int unit_number) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + Icom + *icom; + + while ((icom=i.ReadAndNext()) != NULL) + { + Check(icom); + if (icom->hostID == host_id) + { + if (icom->unitNumber == unit_number) + { + Check_Fpu(); + return icom; + } + } + } + + Check_Fpu(); + return NULL; +} + + +void + IcomManager::ReceiveNetworkPacket( + NetworkPacket */*packet*/, + Receiver::Message *packet_message + ) +{ + Test_Tell("IcomManager::ReceiveNetworkPacket(...)\n"); + Check(this); + Check(packet_message); + Verify(packet_message->messageID >= 0); + Verify(packet_message->messageID < NextMessageID); + + IMMessage + *message = (IMMessage *) packet_message; + + Icom + *icom = FindIcom(message->hostID, message->unitNumber); + + if (icom != NULL) + { + Check(icom); + switch (message->messageID) + { + case ChannelMessageID: + icom->SetChannelValue(message->data.channelNumber); + break; + + case PTTMessageID: + icom->SetPTTStatusValue(message->data.PTTStatus); + break; + + case PAMessageID: + icom->SetPACaptiveValue(message->data.PAStatus); + break; + } + } + + Check_Fpu(); +} diff --git a/MUNGA/ICOM.h b/MUNGA/ICOM.h new file mode 100644 index 0000000..82a51fd --- /dev/null +++ b/MUNGA/ICOM.h @@ -0,0 +1,179 @@ +#pragma once + +#include "entity.h" +#include "network.h" + +class Mission; + +//########################################################################## +//############################# Icom ################################# +//########################################################################## +class Icom : public Plug +{ + friend class IcomManager; + +public: +// constructor is protected: only the IcomManager should call it. + + virtual ~Icom(); + + Logical TestInstance() const; + + //-------------------------------------------------- + // These methods are used to set the channel, PTT, + // and PA status globally across all the cockpits. + // + // They invoke the protected 'set value' methods + // defined below. + //-------------------------------------------------- + void SetChannel(int new_channel); + void SetPTTStatus(Logical new_ptt); + void SetPACaptive(Logical new_pa); + //-------------------------------------------------- + // These methods allow access to the values + //-------------------------------------------------- + int GetChannel(); + Logical GetPTTStatus(); + Logical GetPACaptive(); + + enum + { + undefinedChannel = -1 + }; + +protected: + Icom(HostID host_id, int unit_number = 0); + //-------------------------------------------------- + // These methods are used to locally set the value + // for the channel, PTT, and PA status. + // + // The difference between these methods and the + // public methods defined above is that these + // methods are called by both the public routines + // above and the event receiver to actually + // set the values involved. Making them virtual + // allows derived classes to be notified of changes + // (but also requires that all derived classes + // explicitly call the overridden methods!) + //-------------------------------------------------- + virtual void SetChannelValue(int new_channel); + virtual void SetPTTStatusValue(Logical new_ptt); + virtual void SetPACaptiveValue(Logical new_pa); + + HostID hostID; + int unitNumber; + int channel, channelBeforePA; + Logical PTTStatus; + Logical PACaptive; // held by operator +}; + +//########################################################################## +//##################### IcomManager::Message ########################### +//########################################################################## + +class IcomManager__Message : public Receiver::Message +{ +public: + HostID hostID; + int unitNumber; + + union + { + int channelNumber; + Logical PTTStatus; + Logical PAStatus; + } + data; + + IcomManager__Message() : Receiver::Message(Receiver::AnyMessageID, sizeof(*this)) {} + + // Message ID's must be passed in as parameters + // to avoid circular reference (ID's not defined yet) + void BuildChannelMessage(Receiver::MessageID message_id, HostID host_id, int unit_number, int new_channel) + { + messageLength = sizeof(IcomManager__Message); + messageID = message_id; + hostID = host_id; + unitNumber = unit_number; + data.channelNumber = new_channel; + } + + void BuildPTTMessage(Receiver::MessageID message_id, HostID host_id, int unit_number, Logical new_status) + { + messageLength = sizeof(IcomManager__Message); + messageID = message_id; + hostID = host_id; + unitNumber = unit_number; + data.PTTStatus = new_status; + } + + void BuildPAMessage(Receiver::MessageID message_id, HostID host_id, int unit_number, Logical new_status) + { + messageLength = sizeof(IcomManager__Message); + messageID = message_id; + hostID = host_id; + unitNumber = unit_number; + data.PAStatus = new_status; + } +}; + +//########################################################################## +//######################### IcomManager ############################## +//########################################################################## +class IcomManager : public NetworkClient +{ + friend class Icom; +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +public: + enum + { + ChannelMessageID = NetworkClient::NextMessageID, + PTTMessageID, + PAMessageID, + NextMessageID + }; + + void ReceiveNetworkPacket(NetworkPacket *packet, Receiver::Message *packet_message); + + typedef IcomManager__Message IMMessage; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + IcomManager(SharedData &shared_data = DefaultData); + virtual ~IcomManager(); + + Logical TestInstance() const; + + virtual Icom *MakeIcom(HostID host_id, int unit_number=0); + int AllocateUnitNumber(); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LoadMission, Shutdown methods +// +public: + virtual void LoadMission(Mission *mission); + virtual void Shutdown(); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Periodic update method +// +public: + virtual void Execute(); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public address (force all intercoms to listen to common channel) +// + virtual void SetPAState(int channel); // use Icom::undefinedChannel to release +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Icom object support routines +// +protected: + Icom *FindIcom(HostID host_id, int unit_number); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// protected data +// +protected: + int nextUnitNumber; + ChainOf instanceList; // list of all Icom objects +}; diff --git a/MUNGA/INTEREST.cpp b/MUNGA/INTEREST.cpp new file mode 100644 index 0000000..e23ea1e --- /dev/null +++ b/MUNGA/INTEREST.cpp @@ -0,0 +1,2587 @@ +#include "munga.h" +#pragma hdrstop + +#include "interest.h" +#include "registry.h" +#include "mission.h" +#include "boxtree.h" +#include "renderer.h" +#include "cultural.h" +#include "app.h" +#include "hostmgr.h" + +//############################################################################# +//####################### InterestManager ############################### +//############################################################################# + +// +//-------------------------------------------------------------------- +// InterestManager data +//-------------------------------------------------------------------- +// +unsigned char + InterestManager::messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE]; + +InterestManager::SharedData + InterestManager::DefaultData( + InterestManager::GetClassDerivations(), + InterestManager::GetMessageHandlers() + ); + +Derivation* InterestManager::GetClassDerivations() +{ + static Derivation classDerivations(NetworkClient::GetClassDerivations(), "InterestManager"); + return &classDerivations; +} + +const Receiver::HandlerEntry + InterestManager::MessageHandlerEntries[]= +{ + // + // NewDynamicEntityMessageID + // + { + InterestManager::NewDynamicEntityMessageID, + "NewDynamicEntity", + (InterestManager::Handler)&InterestManager::NewDynamicEntityHandler + }, + // + // DestroyDynamicEntityMessageID + // + { + InterestManager::DestroyDynamicEntityMessageID, + "DestroyDynamicEntity", + (InterestManager::Handler)&InterestManager::DestroyDynamicEntityHandler + }, + // + // EntitySubscribeToUpdatesMessageID + // + { + InterestManager::EntitySubscribeToUpdatesMessageID, + "EntitySubscribeToUpdates", + (InterestManager::Handler)&InterestManager::EntitySubscribeToUpdatesHandler + }, + // + // EntityUpdateReplicantsMessageID + // + { + InterestManager::EntityUpdateReplicantsMessageID, + "EntityUpdateReplicants", + (InterestManager::Handler)&InterestManager::EntityUpdateReplicantsHandler + }, + // + // EntityBroadcastToReplicantsMessageID + // + { + InterestManager::EntityBroadcastToReplicantsMessageID, + "EntityBroadcastToReplicants", + (InterestManager::Handler)&InterestManager::EntityBroadcastToReplicantsHandler + }, + // + // EntityNewInterestZoneMessageID + // + { + InterestManager::EntityNewInterestZoneMessageID, + "EntityNewInterestZone", + (InterestManager::Handler)&InterestManager::EntityNewInterestZoneHandler + }, + // + // HostInterestArenaChangedMessageID + // + { + InterestManager::HostInterestArenaChangedMessageID, + "HostInterestArenaChanged", + (InterestManager::Handler)&InterestManager::HostInterestArenaChangedHandler + }, + // + // InterestZoneDeltaMessageID + // + { + InterestManager::InterestZoneDeltaMessageID, + "InterestZoneDelta", + (InterestManager::Handler)&InterestManager::InterestZoneDeltaHandler + }, + // + // LoadResourceFinishedMessageID + // + { + Receiver::LoadResourceFinishedMessageID, + "LoadResourceFinished", + (InterestManager::Handler)&InterestManager::LoadResourceFinishedHandler + } +}; + +Receiver::MessageHandlerSet& InterestManager::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(InterestManager::MessageHandlerEntries), InterestManager::MessageHandlerEntries, NetworkClient::GetMessageHandlers()); + return messageHandlers; +} + +// +//############################################################################# +// InterestManager +//############################################################################# +// +InterestManager::InterestManager(): + NetworkClient(InterestManagerClassID, DefaultData, InterestManagerClientID), + interestOriginSocket(NULL) +{ + interestArena = NULL; +} + +// +//############################################################################# +// ~InterestManager +//############################################################################# +// +InterestManager::~InterestManager() +{ + if (interestArena != NULL) + { + Unregister_Object(interestArena); + delete interestArena; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + InterestManager::TestInstance() const +{ + if (!IsDerivedFrom(*GetClassDerivations())) + { + return False; + } + Check(&interestLatticeManager); + return True; +} + +// +//############################################################################# +// LoadMission +//############################################################################# +// +void + InterestManager::LoadInterestArenas(Mission*) +{ + Check(this); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Load the interest zones that are accessed by the pilot's drop zone + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Make one interest arena manually + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + { + Check(&interestOriginSocket); + SChainIteratorOf iterator(&interestOriginSocket); + Check(&iterator); + Verify(iterator.GetSize() == 0); + } + #endif + Verify(interestArena == NULL); + interestArena = interestLatticeManager.MakeInterestArena( + (InterestZoneID)0, + (InterestType)0, + (InterestDepth)0 + ); + Register_Object(interestArena); + #endif +} + +// +//############################################################################# +// LoadMission +//############################################################################# +// +void + InterestManager::LoadMission(Mission *mission) +{ + Check(this); + Check(mission); + + // + //-------------------------------------------------------------------------- + // Return if the map ID is not valid + //-------------------------------------------------------------------------- + // + if (mission->GetMapID() == ResourceDescription::NullResourceID) + return; + + // + //-------------------------------------------------------------------------- + // Get the resource description + //-------------------------------------------------------------------------- + // + ResourceFile *resource_file; + ResourceDescription *resource_description; + + Check(application); + resource_file = application->GetResourceFile(); + Check(resource_file); + resource_description = + resource_file->FindResourceDescription(mission->GetMapID()); + Check(resource_description); + resource_description->Lock(); + + // + //-------------------------------------------------------------------------- + // Create the map stream and load + //-------------------------------------------------------------------------- + // + MemoryStream + map_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + + Check(&map_stream); + EntityID last_entity_id(MapHostID); + int landmark_id=0; + LoadMapStream(&map_stream, Origin::Identity, last_entity_id, landmark_id); + resource_description->Unlock(); + + // + //-------------------------------------------------------------------------- + // HACK - load in the collision resources into the tree pointed to by + // this resource + //-------------------------------------------------------------------------- + // + resource_description = + resource_file->FindResourceDescription(mission->GetExistanceMapID()); + + if (resource_description) + { + Check(resource_description); + resource_description->Lock(); + + InterestZone *zone = + GetInterestZone(interestArena->GetInterestZoneID()); + Check(zone); + BoundingBoxTree* tree = zone->GetExistanceRoot(); + Check(tree); + ExtentBox* zones = (ExtentBox*)resource_description->resourceAddress; + int size = resource_description->resourceSize / sizeof(ExtentBox); + while (size--) + { + BoundingBox *box; + box = new BoundingBox(*zones); + Register_Object(box); + tree->Add(box, *box); + ++zones; + } + resource_description->Unlock(); + } + resource_file->ReleaseUnlockedResources(); +} + +// +//############################################################################# +// LoadMapStream +//############################################################################# +// +void + InterestManager::LoadMapStream( + MemoryStream *map_stream, + const Origin &root, + EntityID &last_entity_id, + int &landmark_id + ) +{ + Check(this); + Check(map_stream); + + // + //-------------------------------------------------------------------------- + // Read the map stream and post creation messages + //-------------------------------------------------------------------------- + // + int map_count; + *map_stream >> map_count; + + for (int i=0; iGetPointer()); + Check(message); + + // + //----------------------------------------------------------- + // If this is an include message, recurse into a new map load + //----------------------------------------------------------- + // + if (message->messageFlags & Entity::MakeMessage::MapStreamMarkerFlag) + { + if (message->messageID == Entity::MakeMessageID) + { + Verify(message->messageLength == sizeof(Entity::MakeMapMessage)); + + Entity::MakeMapMessage *map_message = + Cast_Object(Entity::MakeMapMessage*, message); + Check(map_message); + + // + // + //----------------------------- + // Get the resource description + //----------------------------- + // + Check(application); + ResourceFile *resource_file = application->GetResourceFile(); + Check(resource_file); + ResourceDescription *resource_description = + resource_file->FindResourceDescription( + map_message->resourceID + ); + Check(resource_description); + resource_description->Lock(); + + // + //-------------------------------------------------- + // Figure out the origin to use for this map include + // HACK - map rotation is not supported + //-------------------------------------------------- + // + Origin local = map_message->localOrigin; + local.linearPosition += root.linearPosition; + + // + //------------------------------- + // Create the map stream and load + //------------------------------- + // + MemoryStream + map_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + Check(&map_stream); + LoadMapStream(&map_stream, local, last_entity_id, landmark_id); + resource_description->Unlock(); + } + else + { + Fail("Unknown message marker in map stream!\n"); + } + map_stream->AdvancePointer((message->messageLength+3)&~3); + continue; + } + + // + //------------------- + // Verify the message + //------------------- + // + #if DEBUG_LEVEL>0 + // + //---------------------------------------------------------- + // These classes should be stored in the map as map entities + //---------------------------------------------------------- + // + switch (message->classToCreate) + { + case DropZoneClassID: + case ScoreZoneClassID: + case DoorFrameClassID: + case CulturalIconClassID: + case LandmarkClassID: + if ((message->instanceFlags & Entity::MapFlag) == 0) + { + Fail("InterestManager::LoadMapStream - MapFlag disabled"); + } + break; + default: + break; + } + #endif + + // + //--------------------------------------------------------------------- + // If the message id is for a map entity, only make the thing if we are + // supposed to + //--------------------------------------------------------------------- + // + Logical post_make_message = True; + if (Entity::EntityFlagsIsMap(message->instanceFlags)) + { + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + + if ( + host_manager->GetLocalHostID() != + host_manager->IdentifyNewMapEntityHost(message->entityID) + ) + { + post_make_message = False; + } + } + + // + //----------------------------------------------------- + // Make a MakeEntityMessage and post it to the registry + //----------------------------------------------------- + // + if (post_make_message) + { + // + //-------------------------------------------------------------- + // Make a copy of the message for modification by the map origin + // HACK - map rotation is not supported + //-------------------------------------------------------------- + // + Entity::MakeMessage *local_msg = + (Entity::MakeMessage*)new char[message->messageLength]; + Register_Pointer(local_msg); + Mem_Copy( + local_msg, + message, + message->messageLength, + message->messageLength + ); + local_msg->localOrigin.linearPosition += root.linearPosition; + + // + //--------------------------------------------------- + // If this is a landmark, assign the next landmark ID + //--------------------------------------------------- + // + if (local_msg->classToCreate == LandmarkClassID) + { + Landmark::MakeMessage *land_msg = + (Landmark::MakeMessage*)local_msg; + land_msg->landmarkID = landmark_id++; + } + + // + //-------------------------------------------------------- + // If this is not a dynamic object, assign it an entity ID + //-------------------------------------------------------- + // + if (!(local_msg->instanceFlags & Entity::DynamicFlag)) + { + last_entity_id += 1; + local_msg->entityID = last_entity_id; + } + + Registry::MakeEntityMessage + *make_entity_message = + Registry::MakeEntityMessage::Make(local_msg); + Register_Object(make_entity_message); + + Check(application); + // ECH 1/28/96 - application->PostCreationEvent(make_entity_message); + PostCreationEvent(make_entity_message); + #if 0 + Tell( + "InterestManager::LoadMapStream - Posted creation event: " << + "class=" << message->classToCreate << "; " << + "entityID=" << message->entityID << "\n" + ); + #endif + + Unregister_Object(make_entity_message); + delete make_entity_message; + Unregister_Pointer(local_msg); + delete (char*)local_msg; + } + + // + //----------------------------------------------------------------------- + // Advance to the next message + //----------------------------------------------------------------------- + // + map_stream->AdvancePointer((message->messageLength+3)&~3); + } + Check_Fpu(); +} + +// +//############################################################################# +// Shutdown +//############################################################################# +// +void + InterestManager::Shutdown() +{ + Check(this); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Delete interest zones + //-------------------------------------------------------------------------- + // + #else + // + // Delete the one interest arena + // + if (interestArena) + { + Unregister_Object(interestArena); + delete interestArena; + interestArena = NULL; + } + #endif +} + +// +//############################################################################# +// Execute +//############################################################################# +// +void + InterestManager::Execute() +{ + #if 0 + // + // If (the changed origin list is empty) + // + // + // return + // + + // + // Update the net interest arena with the changes from the + // changed interest origin list + // + + // + // Calculate which interest zones should be released and which + // interest zones should be loaded + // + + // + // For (the interest zones which should be released) + // + // + // For (the static entities in the interest zones to be released) + // + // + // Send a becoming uninteresting event to the entity + // + + // + // For (the dynamic master entities in the interest zones to be released) + // + // + // Send a becoming uninteresting event to the entity + // + + // + // For (the dynamic map entities in the interest zones to be released) + // + // + // Send a becoming uninteresting event to the entity + // + + // + // For (the replicants in the interest zones to be released) + // + // + // Unsubscribe the replicants from changes + // + + // + // Send a becoming uninteresting event to the entity + // + + // + // Call the resource manager releasing the interest zone + // + + // + // For (the interest zones which should be loaded) + // + // + // Call the resource manager, requesting the interest zones + // + + // + // Broadcast the interest arena change + // + { + HostInterestArenaChangedMessage message; + + // + // Send at the end of the current frame + // + Check(application); + application->BroadcastEvent( + DefaultEventPriority, + InterestManagerID, + &message + ); + } + #endif +} + +// +//############################################################################# +// AdoptInterestOrigin +//############################################################################# +// +void + InterestManager::AdoptInterestOrigin(InterestOrigin *interest_origin) +{ + Check(this); + Check(interest_origin); + + // + //-------------------------------------------------------------------------- + // Add the interest origin to managers socket + //-------------------------------------------------------------------------- + // + Check(&interestOriginSocket); + interestOriginSocket.Add(interest_origin); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Add to net interest arena... + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // HACK - add interesting entities to the interest origin manually + //-------------------------------------------------------------------------- + // + interest_origin->Update(interest_origin->GetInterestZoneID()); + AddInterestingEntitiesToInterestOrigin(interest_origin); + #endif +} + +// +//############################################################################# +// OrphanInterestOrigin +//############################################################################# +// +void + InterestManager::OrphanInterestOrigin(InterestOrigin *interest_origin) +{ + Check(this); + Check(interest_origin); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // Remove from net interest arena + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // HACK - remove interesting entities manually + //-------------------------------------------------------------------------- + // + RemoveUninterestingEntitiesFromInterestOrigin(interest_origin); + #endif +} + +// +//############################################################################# +// NotifyOfEntityCreation +//############################################################################# +// +void + InterestManager::NotifyOfEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + #if 0 + Tell( + "InterestManager::NotifyOfEntityCreation - " << + "class=" << entity->GetClassID() << "; " << + "entityID=" << entity->GetEntityID() << "\n" + ); + #endif + + // + //-------------------------------------------------------------------------- + // Call appropriate service routine + //-------------------------------------------------------------------------- + // + switch (entity->GetInstance()) + { + case Entity::IndependantInstance: + { + Check(application); + Check(application->GetHostManager()); + if ( + entity->GetOwnerID() == + application->GetHostManager()->GetLocalHostID() + ) + { + DynamicEntityCreation(entity, creation_message); + } + else + { + ReplicantEntityCreation(entity, creation_message); + } + } + break; + + case Entity::MasterInstance: + DynamicEntityCreation(entity, creation_message); + break; + + case Entity::HermitInstance: + if (entity->IsDynamic()) + { + DynamicEntityCreation(entity, creation_message); + } + else + { + StaticEntityCreation(entity, creation_message); + } + break; + + case Entity::ReplicantInstance: + ReplicantEntityCreation(entity, creation_message); + break; + + default: + Fail("InterestManager::NotifyOfEntityCreation - should never reach here"); + break; + } +} + +// +//############################################################################# +// StaticEntityCreation +//############################################################################# +// +void + InterestManager::StaticEntityCreation( + #if DEBUG_LEVEL>0 + Entity *entity, + Entity::MakeMessage *creation_message + #else + Entity *entity, + Entity::MakeMessage * + #endif + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Verify( + entity->GetInstance() == Entity::MasterInstance || + entity->GetInstance() == Entity::HermitInstance + ); + // Verify(entity->IsStatic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // The interest zone of the static entity should already be calculated + // correctly + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Find the interest zone for the static entity and set the interest zone + //-------------------------------------------------------------------------- + // + InterestZoneID interest_zone_ID; + + interest_zone_ID = + interestLatticeManager.SearchForEntityInterestZone( + (InterestZoneID)0, + entity->GetEntityID() + ); + entity->SetInterestZoneID(interest_zone_ID); + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If within any existing interest arenas, then add to the interest origin + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // HACK - Manually add to all interest origins + //-------------------------------------------------------------------------- + // + AddInterestingEntityToInterestOrigins(entity); + #endif +} + +// +//############################################################################# +// DynamicEntityCreation +//############################################################################# +// +void + InterestManager::DynamicEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + Verify(entity->GetEntityID() != EntityID::Null); + Verify( + entity->GetInstance() == Entity::MasterInstance || + entity->GetInstance() == Entity::IndependantInstance || + entity->GetInstance() == Entity::HermitInstance + ); + // Verify(entity->IsDynamic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + if (entity->GetInstance() == Entity::IndependantInstance) + { + Check(application); + Check(application->GetHostManager()); + Verify( + entity->GetOwnerID() == + application->GetHostManager()->GetLocalHostID() + ); + } + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // Set the interest zone id of the entity. Use the spatializer to locate + // the interest zone that the entity is located in + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Find the interest zone for the static entity and set the interest zone + //-------------------------------------------------------------------------- + // + InterestZoneID interest_zone_ID; + + interest_zone_ID = + interestLatticeManager.SearchForEntityInterestZone( + (InterestZoneID)0, + entity->GetEntityID() + ); + entity->SetInterestZoneID(interest_zone_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Send new dynamic entity message + //-------------------------------------------------------------------------- + // + + // + // Setup and verify network fields in creation message + // + entity->SetupNetworkMessage(creation_message); + #if DEBUG_LEVEL>0 + Check(&creation_message->entityID); + Verify(creation_message->entityID != EntityID::Null); + Verify(creation_message->interestZoneID != NullInterestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + creation_message->ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + // HACK - Spoof the make entity message into a NewDynamicEntityMessageID + // for the purposes of sending to interest managers + // + Verify(creation_message->messageID == Entity::MakeMessageID); + creation_message->messageID = NewDynamicEntityMessageID; + + // + //-------------------------------------------------------------------------- + // If the entity is replicated + //-------------------------------------------------------------------------- + // + if ( + entity->GetInstance() == Entity::MasterInstance || + entity->GetInstance() == Entity::IndependantInstance + ) + { + // + // Broadcast the message + // + Check(application); + application->BroadcastMessage(InterestManagerClientID, creation_message); + } + + // + //-------------------------------------------------------------------------- + // Else (the entity is not replicated) + //-------------------------------------------------------------------------- + // + else + { + Verify(entity->GetInstance() == Entity::HermitInstance); + + // + // Post the message to ourselves + // + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, this, creation_message); + Dispatch(creation_message); + } +} + +// +//############################################################################# +// NewDynamicEntityHandler +//############################################################################# +// +void + InterestManager::NewDynamicEntityHandler( + NewDynamicEntityMessage *creation_message + ) +{ + Check(this); + Check(creation_message); + + // + // Verify the creation message + // + Check(&creation_message->entityID); + Verify(creation_message->entityID != EntityID::Null); + Verify(creation_message->interestZoneID != NullInterestZoneID); + Verify(creation_message->ownerID >= FirstLegalHostID); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (the new entity is not in any of the interest arenas) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Get the local host id + //-------------------------------------------------------------------------- + // + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + + // + //-------------------------------------------------------------------------- + // If (this host is not the owner host) + //-------------------------------------------------------------------------- + // + if (local_host_ID != creation_message->ownerID) + { + // + //----------------------------------------------------------------------- + // Make the replicant + //----------------------------------------------------------------------- + // + + // + // HACK - Message was spoofed as NewDynamicEntityMessageID, now + // turn back to make entity message ID + // + Verify(creation_message->messageID == NewDynamicEntityMessageID); + creation_message->messageID = Entity::MakeMessageID; + + // + // Turn on the replicant flag if this is a master instance, + // otherwise, the instance should be an independant + // + if ( + Entity::EntityFlagsGetInstance(creation_message->instanceFlags) == + Entity::MasterInstance + ) + { + creation_message->instanceFlags = Entity::EntityFlagsSetInstance( + creation_message->instanceFlags, + Entity::ReplicantInstance + ); + } + else + { + Verify( + Entity::EntityFlagsGetInstance(creation_message->instanceFlags) == + Entity::IndependantInstance + ); + } + + // + //----------------------------------------------------------------------- + // Make a MakeEntityMessage and post it to the registry + //----------------------------------------------------------------------- + // + Registry::MakeEntityMessage *make_entity_message; + + make_entity_message = Registry::MakeEntityMessage::Make(creation_message); + Register_Object(make_entity_message); + + Check(application); + // + // Implicit assumption that this will be a higher + // priority and/or earlier sequence than any update message + // + Check(application->GetRegistry()); + application->GetRegistry()->Dispatch(make_entity_message); + + Unregister_Object(make_entity_message); + delete make_entity_message; + } + + // + //-------------------------------------------------------------------------- + // If (this host is the owner host) + //-------------------------------------------------------------------------- + // + else + { + // + //----------------------------------------------------------------------- + // Get the entity pointer + //----------------------------------------------------------------------- + // + Entity *entity; + + Check(application); + Check(application->GetHostManager()); + entity = application->GetHostManager()->GetEntityPointer( + creation_message->entityID + ); + Check(entity); + + // + //----------------------------------------------------------------------- + // Tell the master that it is interesting + // Should this wait until next interest frame? + //----------------------------------------------------------------------- + // + entity->BecomeInteresting(); + + // + //----------------------------------------------------------------------- + // HACK - Manually add to all interest origins + //----------------------------------------------------------------------- + // + AddInterestingEntityToInterestOrigins(entity); + } +} + +#if 0 // HACK - Partial Implementation +// +//############################################################################# +// NotifyOfMapEntityCreation +//############################################################################# +// +void + InterestManager::NotifyOfMapEntityCreation( + Entity *entity, + Entity::MakeMessage *creation_message, + Time + ) +{ + Check(this); + Check(entity); + Check(creation_message); + Verify(creation_message->entityID != EntityID::Null); + Verify(creation_message->interestZoneID != NullInterestZoneID); + + // + // Verify instance type, and interest characterisitics + // + Verify(entity->GetInstance() == Entity::MasterInstance); + Verify(entity->IsDynamic()); + Verify(entity->IsMap()); + + #if 0 + // + // Call the resource manager, storing the interest zone delta + // + + // + // Broadcast the interest zone delta + // + { + InterestZoneDeltaMessage message; + + Check(application); + application->SendMessage( + DefaultEventPriority, + InterestManagerID, + &message + ); + } + + // + // Broadcast the new map entity message + // + { + Verify(creation_message->messageID == Entity::MakeMessageID); + creation_message->messageID = NewMapEntityMessageID; + + Check(application); + application->SendMessage( + DefaultEventPriority, + InterestManagerID, + creation_message + ); + } + #else + Fail("InterestManager::NotifyOfMapEntityCreation - under construction"); + #endif +} +#endif + +#if 0 // HACK - Partial Implementation +// +//############################################################################# +// NewMapEntityHandler +//############################################################################# +// +void + InterestManager::NewMapEntityHandler( + NewMapEntityMessage *message + ) +{ + Check(this); + Check(message); + + #if 0 + // + // If (the entity is outside of the interest arena) + // + // + // Return + // + + // + // If (this is the owner host) + // + // + // Tell the entity that it is interesting + // + + // + // If (this host is not the owner host) + // + // + // Find the replicant or local master entity + // + + // + // If (the entity does not exist) + // + // + // Make the replicant + // + + // + // Tell the replicant that it is interesting + // + + // + // Subscribe the replicant to updates from the master + // + + // + // If (the entity does exist) + // + // + // If (the entity is a replicant) + // + // + // Point it at the new owner + // + + // + // If (the entity is a master) + // + // + // If (creation time of new master > creation time of local master) + // + // + // Morph the local master into a replicant pointing at new master + // + + // + // Tell the replicant that it is interesting + // + + // + // Subscribe the replicant to updates from the master + // + #else + Fail("InterestManager::NewMapEntityHandler - under construction"); + #endif +} +#endif + +// +//############################################################################# +// ReplicantEntityCreation +//############################################################################# +// +void + InterestManager::ReplicantEntityCreation( + #if DEBUG_LEVEL>0 + Entity *entity, + Entity::MakeMessage *creation_message + #else + Entity *entity, + Entity::MakeMessage * + #endif + ) +{ + Check(this); + Check(entity); + Check(creation_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + Verify(entity->GetEntityID() != EntityID::Null); + Verify( + entity->GetInstance() == Entity::ReplicantInstance || + entity->GetInstance() == Entity::IndependantInstance + ); + // Verify(entity->IsDynamic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + if (entity->GetInstance() == Entity::IndependantInstance) + { + Check(application); + Check(application->GetHostManager()); + Verify( + entity->GetOwnerID() != + application->GetHostManager()->GetLocalHostID() + ); + } + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // The interest zone of the static entity should already be calculated + // correctly + //-------------------------------------------------------------------------- + // + #endif + + // + //-------------------------------------------------------------------------- + // Get the local host id + //-------------------------------------------------------------------------- + // + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + + // + //-------------------------------------------------------------------------- + // Subscribe the replicant to updates from the master + //-------------------------------------------------------------------------- + // + EntitySubscribeToUpdates( + entity->GetEntityID(), + entity->GetOwnerID(), + local_host_ID + ); + + // + //-------------------------------------------------------------------------- + // Tell the replicant that it is interesting + //-------------------------------------------------------------------------- + // + entity->BecomeInteresting(); + + // + //-------------------------------------------------------------------------- + // HACK - Manually add to all interest origins + //-------------------------------------------------------------------------- + // + AddInterestingEntityToInterestOrigins(entity); +} + +// +//############################################################################# +// NotifyOfEntityDestruction +//############################################################################# +// +void + InterestManager::NotifyOfEntityDestruction(Entity *entity) +{ + Check(this); + Check(entity); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (this is a map entity) + //-------------------------------------------------------------------------- + // + // + // Store an interest zone delta with the owner set to MapHostID + // + + // + // Broadcast an interest zone delta + // + #endif + + // + //-------------------------------------------------------------------------- + // HACK - Manually remove from all interest origins + //-------------------------------------------------------------------------- + // + RemoveUninterestingEntityFromInterestOrigins(entity); + + // + //-------------------------------------------------------------------------- + // Broadcast delete entity message for master entities that have replicants + //-------------------------------------------------------------------------- + // + if ( + entity->GetInstance() == Entity::MasterInstance // && // HACK - Partial Implementation + // entity->IsDynamic() // HACK - Partial Implementation + ) + { + // + // Create destruction message + // + DestroyDynamicEntityMessage + destroy_message( + DestroyDynamicEntityMessageID, + sizeof(DestroyDynamicEntityMessage) + ); + Check(&destroy_message); + + // + // Setup and verify network fields in destruction message + // + entity->SetupNetworkMessage(&destroy_message); + #if DEBUG_LEVEL>0 + Check(&destroy_message.entityID); + Verify(destroy_message.entityID == entity->entityID); + Verify(destroy_message.interestZoneID == entity->interestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + destroy_message.ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + // Broadcast destruction message + // + Check(application); + application->ExclusiveBroadcastMessage( + InterestManagerClientID, + &destroy_message + ); + } +} + +// +//############################################################################# +// DestroyDynamicEntityHandler +//############################################################################# +// +void + InterestManager::DestroyDynamicEntityHandler( + DestroyDynamicEntityMessage *destroy_message + ) +{ + Check(this); + Check(destroy_message); + + // + // Verify destruction message + // + Check(&destroy_message->entityID); + Verify(destroy_message->entityID != EntityID::Null); + Verify(destroy_message->interestZoneID != NullInterestZoneID); + Verify(destroy_message->ownerID >= FirstLegalHostID); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If entity is not within interest zone + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Verify the local host id + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + Verify(destroy_message->ownerID != local_host_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Find the replicant to destroy + //-------------------------------------------------------------------------- + // + Entity *replicant; + + Check(application); + Check(application->GetHostManager()); + replicant = application->GetHostManager()->GetEntityPointer( + destroy_message->entityID + ); + + // + //-------------------------------------------------------------------------- + // If (the replicant exists) + //-------------------------------------------------------------------------- + // + if (replicant != NULL) + { + Check(replicant); + Verify(replicant->GetInstance() == Entity::ReplicantInstance); + + // + // HACK - Message was spoofed as DestroyDynamicEntityMessage, now + // turn back to DestroyEntityMessage + // + Verify(destroy_message->messageID == DestroyDynamicEntityMessageID); + destroy_message->messageID = Entity::DestroyEntityMessageID; + + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, destroy_message); + PostDestructionEvent(replicant, destroy_message); + } +} + +// +//############################################################################# +// EntityUpdateInterestZone +//############################################################################# +// +void + InterestManager::EntityUpdateInterestZone( +#if DEBUG_LEVEL>0 + Entity *entity +#else + Entity * +#endif + ) +{ + Check(this); + Check(entity); + Verify(entity->IsDynamic()); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------- + // Update the interest zone id if the entity is not trapped + //-------------------------------------------------------------------- + // + if (entity->IsTrapped()) + return; + + // + //-------------------------------------------------------------------- + // Find the entities new interest zone + //-------------------------------------------------------------------- + // + InterestZoneID + old_interest_zone_ID, + new_interest_zone_ID; + + old_interest_zone_ID = entity->GetInterestZoneID(); + new_interest_zone_ID = + interestLatticeManager.SearchForEntityInterestZone( + old_interest_zone_ID, + entity->GetEntityID() + ); + + // + //-------------------------------------------------------------------- + // If the interest zone has changed, then update the entity + // and broadcast the change + //-------------------------------------------------------------------- + // + if (old_interest_zone_ID != new_interest_zone_ID) + { + entity->SetInterestZoneID(new_interest_zone_ID); + + // + // HACK - a way is needed to get from the entity the information + // required for another host to create the replicant + // + EntityNewInterestZoneMessage + message(entity->GetEntityID(),new_interest_zone_ID); + + // + // This message should be handled locally before the end of + // the current render frame? + // + #if 0 + Check(application); + application->SendEvent( + DefaultEventPriority, + InterestManagerID, + &message + ); + #else + Check(application); + application->BroadcastMessage( + InterestManagerClientID, + &message + ); + #endif + } + #endif +} + +// +//############################################################################# +// EntityNewInterestZoneHandler +//############################################################################# +// +void + InterestManager::EntityNewInterestZoneHandler( + EntityNewInterestZoneMessage* + ) +{ + #if 0 + // + // If (the master entity is on this host) + // + // + // Determine if the entity is interesting given its new + // interest zone + // + + // + // If (the entity was and still is interesting) + // then (do nothing) + // + + // + // If (the entity was not interesting and still is not interesting) + // then (do nothing) + // + + // + // If (the entity was interesting and now is not interesting) + // + // + // Send BecomeUninteresting message to the entity + // + + // + // If (the entity was not interesting and now is interesting) + // + // + // Send BecomeInteresting message to the entity + // + + // + // If (the master entity is not on this host) + // + // + // Determine if the entity is interesting given its new + // interest zone + // + + // + // If (the entity was and still is interesting) + // then (do nothing) + // + + // + // If (the entity was not interesting and still is not interesting) + // then (do nothing) + // + + // + // If (the entity was interesting and now is not interesting) + // + // + // Unsubscribe the replicant entity from updates + // + + // + // Send BecomeUninteresting message to the entity + // + + // + // If (the entity was not interesting and now is interesting) + // + // + // If (the replicant does not exist) + // + // + // Create the replicant + // + + // + // Send BecomeInteresting message to the entity + // + + // + // Subscribe the replicant to updates + // + #else + Fail("InterestManager::EntityNewInterestZoneHandler - under construction"); + #endif +} + +// +//############################################################################# +// LoadResourceFinishedHandler +//############################################################################# +// +void + InterestManager::LoadResourceFinishedHandler(Receiver::Message*) +{ + #if 0 + // + // If (an interest origin request for interest zone finished) + // + // + // For (the static entities in the interest zone) + // + // + // If (the static entity does not exist) + // + // + // Make the static entity + // + + // + // For (the map entities in the interest zone) + // + // + // If (the owner of the map entity is MapHostID) + // + // + // This entity has not been created by any other hosts, + // so create it with this host as owner + // + + // + // Need to somehow put in a small random delay for map + // entity creation resolution between two hosts? + // + + // + // Make the map entity + // + #if 0 + { + Entity entity_ID; // From the interest zone + ClassID class_ID; // From the interest zone + HostID owner_ID; // From this host + + application->registry->MakeEntity(entity_ID, class_ID); + } + #endif + #else + Fail("InterestManager::LoadResourceFinishedHandler - under construction"); + #endif +} + +// +//############################################################################# +// EntitySubscribeToUpdates +//############################################################################# +// +void + InterestManager::EntitySubscribeToUpdates( + EntityID, + HostID, + HostID + ) +{ + // HACK - Partial implementation +} + +// +//############################################################################# +// EntitySubscribeToUpdatesHandler +//############################################################################# +// +void + InterestManager::EntitySubscribeToUpdatesHandler( + EntitySubscribeToUpdatesMessage* + ) +{ + // HACK - Partial implementation +} + +// +//############################################################################# +// EntityUpdateReplicants +//############################################################################# +// +void + InterestManager::EntityUpdateReplicants( + Entity *entity, + Entity::UpdateMessage *update_message + ) +{ + Check(this); + Check(entity); + Check(update_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Verify(entity->GetInstance() == Entity::MasterInstance); + Verify(entity->IsDynamic()); + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (no replicants are subscribed to this entity) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // Send it to the subscribed replicants + // + // LAN Solution: + // If (subscriber list is not empty) + // Broadcast the update + // + // WAN Solution: + // If (subscriber list is not empty) + // Send the update via point-to-point messages + // + // A way is needed to get from the entity the information + // required for another host to create the replicant + //-------------------------------------------------------------------------- + // + #else + // + // Setup and verify network fields in message + // + entity->SetupNetworkMessage(update_message); + #if DEBUG_LEVEL>0 + Check(&update_message->entityID); + Verify(update_message->entityID != EntityID::Null); + Verify(update_message->interestZoneID != NullInterestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + update_message->ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + // HACK - Spoof the update message into EntityUpdateReplicantsMessageID + // + Verify(update_message->messageID == Entity::UpdateMessageID); + update_message->messageID = EntityUpdateReplicantsMessageID; + + // + // Broadcast update message + // + Check(application); + application->ExclusiveBroadcastMessage( + InterestManagerClientID, + update_message + ); + #endif +} + +// +//############################################################################# +// EntityUpdateReplicantsHandler +//############################################################################# +// +void + InterestManager::EntityUpdateReplicantsHandler( + EntityUpdateReplicantsMessage *update_message + ) +{ + Check(this); + Check(update_message); + + // + // Verify update message + // + Check(&update_message->entityID); + Verify(update_message->entityID != EntityID::Null); + Verify(update_message->interestZoneID != NullInterestZoneID); + Verify(update_message->ownerID >= FirstLegalHostID); + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (interest zone id is outside of our interest arenas) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Verify the local host id + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + Verify(update_message->ownerID != local_host_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Find the replicant to update + //-------------------------------------------------------------------------- + // + Entity *replicant; + + Check(application); + Check(application->GetHostManager()); + replicant = application->GetHostManager()->GetEntityPointer( + update_message->entityID + ); + + // + //-------------------------------------------------------------------------- + // If (the replicant exists) + //-------------------------------------------------------------------------- + // + if (replicant) + { + // + // Update the replicant + // + Check(replicant); + Verify(replicant->GetInstance() == Entity::ReplicantInstance); + Verify(replicant->IsDynamic()); + + // + // HACK - Message was spoofed as EntityUpdateReplicantsMessageID, now + // turn back to update entity message ID + // + Verify(update_message->messageID == EntityUpdateReplicantsMessageID); + update_message->messageID = Entity::UpdateMessageID; + + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, update_message); + PostUpdateEvent(replicant, update_message); + } + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (the replicant does not exist) + //-------------------------------------------------------------------------- + // + // + // Create the replicant + // + + // + // Send BecomeInteresting message to the entity + // + + // + // Subscribe the replicant to updates + // + #endif +} + +// +//############################################################################# +// EntityBroadcastToReplicants +//############################################################################# +// +void + InterestManager::EntityBroadcastToReplicants( + Entity *entity, + Entity::Message *broadcast_message + ) +{ + Check(this); + Check(entity); + Check(broadcast_message); + + // + //-------------------------------------------------------------------------- + // Verify entityID, instance, and flags + //-------------------------------------------------------------------------- + // + Verify(entity->GetEntityID() != EntityID::Null); + Verify(entity->GetInstance() == Entity::MasterInstance); + // Verify(entity->IsDynamic()); // HACK - Partial Implementation + // Verify(!entity->IsMap()); // HACK - Partial Implementation allows map entities + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (no replicants are subscribed to this entity) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // Send it to the subscribed replicants + // + // LAN Solution: + // If (subscriber list is not empty) + // Broadcast the update + // + // WAN Solution: + // If (subscriber list is not empty) + // Send the update via point-to-point messages + // + // A way is needed to get from the entity the information + // required for another host to create the replicant + // + //-------------------------------------------------------------------------- + // + #else + // + //-------------------------------------------------------------------------- + // Setup and verify network fields in message + //-------------------------------------------------------------------------- + // + entity->SetupNetworkMessage(broadcast_message); + #if DEBUG_LEVEL>0 + Check(&broadcast_message->entityID); + Verify(broadcast_message->entityID != EntityID::Null); + Verify(broadcast_message->interestZoneID != NullInterestZoneID); + Check(application); + Check(application->GetHostManager()); + Verify( + broadcast_message->ownerID == + application->GetHostManager()->GetLocalHostID() + ); + #endif + + // + //-------------------------------------------------------------------------- + // Build the interest manager message + //-------------------------------------------------------------------------- + // + MemoryStream + memory_stream(messageBuildBuffer, INTERESTMANAGER_MESSAGE_BUFFER_SIZE); + EntityBroadcastToReplicantsMessage + *interest_manager_message; + size_t + total_length; + + total_length = + sizeof (EntityBroadcastToReplicantsMessage) + + broadcast_message->messageLength; + Verify(total_length < memory_stream.GetBytesRemaining()); + + Check_Pointer(memory_stream.GetPointer()); + interest_manager_message = + new (memory_stream.GetPointer()) EntityBroadcastToReplicantsMessage( + total_length + ); + Check(interest_manager_message); + + memory_stream.AdvancePointer(sizeof(EntityBroadcastToReplicantsMessage)); + Mem_Copy( + memory_stream.GetPointer(), + broadcast_message, + broadcast_message->messageLength, + memory_stream.GetBytesRemaining() + ); + + // + //-------------------------------------------------------------------------- + // Broadcast update message + //-------------------------------------------------------------------------- + // + #if 0 + Tell( + "InterestManager::EntityBroadcastToReplicants - Send entity message ID " << + broadcast_message->messageID << "\n" + ); + #endif + + Check(application); + application->ExclusiveBroadcastMessage( + InterestManagerClientID, + interest_manager_message + ); + #endif +} + +// +//############################################################################# +// EntityBroadcastToReplicantsHandler +//############################################################################# +// +void + InterestManager::EntityBroadcastToReplicantsHandler( + EntityBroadcastToReplicantsMessage *interest_manager_message + ) +{ + Check(this); + Check(interest_manager_message); + + #if 0 // HACK - Partial Implementation + // + //-------------------------------------------------------------------------- + // If (interest zone id is outside of our interest arenas) + //-------------------------------------------------------------------------- + // + // + // return + // + #endif + + // + //-------------------------------------------------------------------------- + // Parse broadcast message + //-------------------------------------------------------------------------- + // + MemoryStream + memory_stream( + interest_manager_message, + interest_manager_message->messageLength + ); + Entity::Message *broadcast_message; + + memory_stream.AdvancePointer(sizeof(EntityBroadcastToReplicantsMessage)); + broadcast_message = Cast_Object(Entity::Message*, memory_stream.GetPointer()); + Check(broadcast_message); + + Check(&broadcast_message->entityID); + Verify(broadcast_message->entityID != EntityID::Null); + Verify(broadcast_message->interestZoneID != NullInterestZoneID); + Verify(broadcast_message->ownerID >= FirstLegalHostID); + + #if 0 + Tell( + "InterestManager::EntityBroadcastToReplicantsHandler - Receive entity message ID " << + broadcast_message->messageID << "\n" + ); + #endif + + // + //-------------------------------------------------------------------------- + // Verify the local host id + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + HostID local_host_ID; + + Check(application); + Check(application->GetHostManager()); + local_host_ID = application->GetHostManager()->GetLocalHostID(); + Verify(broadcast_message->ownerID != local_host_ID); + #endif + + // + //-------------------------------------------------------------------------- + // Find the replicant to update + //-------------------------------------------------------------------------- + // + Entity *replicant; + + Check(application); + Check(application->GetHostManager()); + replicant = application->GetHostManager()->GetEntityPointer( + broadcast_message->entityID + ); + + #if 0 + Tell( + "InterestManager::EntityBroadcastToReplicantsHandler - Replicant=" << + (long)replicant << "\n" + ); + #endif + + // + //-------------------------------------------------------------------------- + // If the replicant exists, update it + //-------------------------------------------------------------------------- + // + if (replicant) + { + Check(replicant); + Verify(replicant->GetInstance() == Entity::ReplicantInstance); + + Check(application); + // ECH 1/28/96 - application->Post(DefaultEventPriority, replicant, broadcast_message); + PostUpdateEvent(replicant, broadcast_message); + } + + #if 0 // HACK - Partial implementation + // + //-------------------------------------------------------------------------- + // If (the replicant does not exist) + //-------------------------------------------------------------------------- + // + else + { + // + // Create the replicant + // + + // + // Send BecomeInteresting message to the entity + // + + // + // Subscribe the replicant to updates + // + #if 0 + Tell("Unknown replicant " << broadcast_message->entityID << endl); + #endif + } + #endif +} + +// +//############################################################################# +// HostInterestArenaChangedHandler +//############################################################################# +// +void + InterestManager::HostInterestArenaChangedHandler( + HostInterestArenaChangedMessage* + ) +{ + #if 0 + // + // Get all hosted dynamic entities + // + + // + // For (each entity within the given interest arena) + // + { + // + // HACK - need someway of doing the following point-to-point, + // potentially to ourselves + // + Entity::UpdateMessage + *update_message = NULL; + + Check(update_message); + + Check(application); + application->interestManager.EntityUpdateReplicants( + entity, + update_message + ); + } + #else + Fail("InterestManager::HostInterestArenaChangedHandler - under construction"); + #endif +} + +// +//############################################################################# +// InterestZoneDeltaHandler +//############################################################################# +// +void + InterestManager::InterestZoneDeltaHandler( + InterestZoneDeltaMessage* + ) +{ + #if 0 + // + // If (a delta already exists for this interest zone) + // + // + // Get the timestamp of the existing delta + // + + // + // If (the timestamp of the incoming delta is > then current delta) + // + // + // Store the incoming delta + // + + // + // If (a delta does not exist for this interest zone) + // + // + // Store the incoming data + // + #else + Fail("InterestManager::InterestZoneDeltaHandler - under construction"); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::AddInterestingEntityToInterestOrigins(Entity *new_entity) +{ + Check(this); + Check(new_entity); + Check(&interestOriginSocket); + + InterestOrigin + *interest_origin; + SChainIteratorOf + iterator(&interestOriginSocket); + + Check(&iterator); + while((interest_origin = iterator.ReadAndNext()) != NULL) + { + Check(interest_origin); + interest_origin->AddInterestingEntity(new_entity); + } +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::RemoveUninterestingEntityFromInterestOrigins(Entity *entity) +{ + Check(this); + Check(entity); + Check(&interestOriginSocket); + + InterestOrigin + *interest_origin; + SChainIteratorOf + iterator(&interestOriginSocket); + + Check(&iterator); + while((interest_origin = iterator.ReadAndNext()) != NULL) + { + Check(interest_origin); + interest_origin->RemoveUninterestingEntity(entity); + } +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::AddInterestingEntitiesToInterestOrigin( + InterestOrigin *interest_origin + ) +{ + Check(this); + Check(interest_origin); + + // + // Get an iterator for all the entities on this host + // + Check(application); + Check(application->GetHostManager()); + + HostManager::AllEntityIterator + iterator(application->GetHostManager()); + Entity + *entity; + + Check(&iterator); + while((entity = iterator.ReadAndNext()) != NULL) + { + Check(entity); + interest_origin->AddInterestingEntity(entity); + } +} + +// +//############################################################################# +// PostCreationEvent +//############################################################################# +// +void + InterestManager::PostCreationEvent(Receiver::Message *make_entity_message) +{ + Check(this); + Check(make_entity_message); + + Check(application); + + #if 0 // ECH 1/28/96 + EventPriorities priority = + (application->GetApplicationState() != Application::RunningMission) ? + LowEventPriority : + DefaultEventPriority; + #else + EventPriorities priority = + (application->GetApplicationState() != Application::RunningMission) ? + LowEventPriority : + CreationEventPriority; + #endif + + Check(application); + Registry *registry = application->GetRegistry(); + Check(registry); + application->Post(priority, registry, make_entity_message); +} + +// +//############################################################################# +// PostRendererEvent +//############################################################################# +// +void + InterestManager::PostRendererEvent( + Entity *entity, + Renderer *renderer, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(renderer); + + #if 0 // ECH 1/26/96 + EventPriorities priority = + (applicationState.GetState() != Application::RunningMission) ? + MinEventPriority : + DefaultEventPriority; + #endif + + EventPriorities priority; + + switch (entity->GetInterestPriority(renderer->GetLinkedEntity())) + { + case LowInterestPriority: + priority = + (application->GetApplicationState() != Application::RunningMission) ? + MinEventPriority : + LowInterestEventPriority; + break; + + case HighInterestPriority: + priority = + (application->GetApplicationState() != Application::RunningMission) ? + MinEventPriority : + HighInterestEventPriority; + break; + + default: + Fail("Application::PostInterestEvent - Should never reach here"); + break; + } + + application->Post(priority, renderer, message); +} + +// +//############################################################################# +// PostUpdateEvent +//############################################################################# +// +void + InterestManager::PostUpdateEvent( + Entity *entity, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(message); + + // + // Note that the priority of the update can be greater than the + // creation priority since the replicants are created via dispatch + // in the interest manager. + // + EventPriorities priority = + (application->GetApplicationState() != Application::RunningMission) ? + DefaultEventPriority : + UpdateEventPriority; + + Check(application); + application->Post(priority, entity, message); +} + +// +//############################################################################# +// PostDestructionEvent +//############################################################################# +// +void + InterestManager::PostDestructionEvent( + Entity *entity, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(message); + + EventPriorities priority = DestructionEventPriority; + + #if 0 + switch (entity->GetInterestPriority(renderer->GetLinkedEntity())) + { + case LowInterestPriority: + priority = LowEventPriority; + break; + + case HighInterestPriority: + priority = DefaultEventPriority; + break; + + default: + Fail("Application::PostInterestEvent - Should never reach here"); + break; + } + #endif + + Check(application); + application->Post(priority, entity, message); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestManager::RemoveUninterestingEntitiesFromInterestOrigin( + InterestOrigin *interest_origin + ) +{ + Check(this); + Check(interest_origin); + + interest_origin->RemoveUninterestingEntities(); +} + +//~~~~~~~~~~~~~~~~~ InterestManager__EntitySubscribeToUpdatesMessage ~~~~~~~~~~ + +InterestManager__EntitySubscribeToUpdatesMessage:: + InterestManager__EntitySubscribeToUpdatesMessage(): + NetworkClient::Message( + InterestManager::EntitySubscribeToUpdatesMessageID, + sizeof(InterestManager__EntitySubscribeToUpdatesMessage) + ) +{ +} + +//~~~~~~~~~~~~~~ InterestManager__EntityBroadcastToReplicantsMessage ~~~~~~~~~~ + +InterestManager__EntityBroadcastToReplicantsMessage:: + InterestManager__EntityBroadcastToReplicantsMessage(size_t message_length): + NetworkClient::Message( + InterestManager::EntityBroadcastToReplicantsMessageID, + message_length + ) +{ +} + +//~~~~~~~~~~~~~~~~~ InterestManager__EntityNewInterestZoneMessage ~~~~~~~~~~~~~ + +InterestManager__EntityNewInterestZoneMessage:: + InterestManager__EntityNewInterestZoneMessage( + const EntityID &entity_ID, + InterestZoneID interest_zone_ID + ): + NetworkClient::Message( + InterestManager::EntityNewInterestZoneMessageID, + sizeof(InterestManager__EntityNewInterestZoneMessage) + ) +{ + entityID = entity_ID; + interestZoneID = interest_zone_ID; +} + +//~~~~~~~~~~~~~~~~~ InterestManager__HostInterestArenaChangedMessage ~~~~~~~~~~ + +InterestManager__HostInterestArenaChangedMessage:: + InterestManager__HostInterestArenaChangedMessage(): + NetworkClient::Message( + InterestManager::HostInterestArenaChangedMessageID, + sizeof(InterestManager__HostInterestArenaChangedMessage) + ) +{ +} + +//~~~~~~~~~~~~~~~~~ InterestManager__InterestZoneDeltaMessage ~~~~~~~~~~~~~~~~~ + +InterestManager__InterestZoneDeltaMessage:: + InterestManager__InterestZoneDeltaMessage(): + NetworkClient::Message( + InterestManager::InterestZoneDeltaMessageID, + sizeof(InterestManager__InterestZoneDeltaMessage) + ) +{ +} \ No newline at end of file diff --git a/MUNGA/INTEREST.h b/MUNGA/INTEREST.h new file mode 100644 index 0000000..c85f695 --- /dev/null +++ b/MUNGA/INTEREST.h @@ -0,0 +1,571 @@ +#pragma once + +#include "network.h" +#include "host.h" +#include "intorgn.h" +#include "entityid.h" + +class Renderer; +class Entity; +class Entity__MakeMessage; +class Entity__UpdateMessage; +class Entity__DestroyEntityMessage; +class Entity__Message; + +//########################################################################## +//####################### InterestManager ############################ +//########################################################################## + +#define INTERESTMANAGER_MESSAGE_BUFFER_SIZE (1536) + +class Mission; + +class InterestManager__EntitySubscribeToUpdatesMessage; +class InterestManager__EntityBroadcastToReplicantsMessage; +class InterestManager__EntityNewInterestZoneMessage; +class InterestManager__HostInterestArenaChangedMessage; +class InterestManager__InterestZoneDeltaMessage; + +// +//-------------------------------------------------------------------------- +// InterestManager +// +// Entity types relevant to the interest managers operation: +// +// Static Entity (!replicated, !executing, !moving, trapped, map, id) +// - an entity that is not replicated, it does not execute or move. +// It is a component of the map and therefore trapped within its +// interest zone. It has a preallocated entity id. (rock, fence, wall) +// +// Dynamic Entity (replicated, executing, moving, !trapped, !map, !id) +// - an entity that may be replicated. It executes upon its host +// machine. It is also moves freely, crossing interest zones if it +// wishes. It is not a component of the map and can not be given a +// preallocated entity id. (VTV, Mech, missile) +// +// Dynamic Trapped Entity (replicated, executing, moving, trapped, !map, !id) +// - an entity that may be replicated. It executes upon its host +// machine. It may move but not out of its interest zone. It is not +// a component of the map and can not be given a preallocated entity id. +// (mines, burning husk of Mech) +// +// Dynamic Map Entity (replicated, executing, moving, !trapped, map, id) +// - an entity that may be replicated. It executes upon its host machine. +// It is also moves freely, crossing interest zones if it wishes. It +// is a component of the map and can be given a preallocated entity id. +// (The ork that activates upon entering the dungeon and then follows you, +// the one moon around the planet that orbits once every 24 hours) +// +// Dynamic Trapped Map Entity (replicated, executing, moving, trapped, map, id) +// - an entity that may be replicated. It executes upon its host machine. +// It is also moves freely, but may not change interest zones. It is a +// component of the map and can be given a preallocated entity id. +// (The swinging crane, the RP door) +//-------------------------------------------------------------------------- +// + +class InterestManager: + public NetworkClient +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + InterestManager(); + ~InterestManager(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execution control +// +public: + virtual void + LoadInterestArenas(Mission *mission); + virtual void + LoadMission(Mission *mission); + void + LoadMapStream( + MemoryStream *map_stream, + const Origin& root, + EntityID& static_id, + int &landmark_id + ); + + virtual void + Shutdown(); + + void + Execute(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest Origin methods +// +public: + // + //----------------------------------------------------------------------- + // AdoptInterestOrigin + // + // Asserts that the entity is a origin of interest of a specified + // type (example: visual, auditory, radar). Traversals of the interest + // lattice are performed with respect to this origin and may be + // performed with different algorithms depending upon type. The + // Lattice is traversed to a particular "depth" or "cost" for a + // specific interest type and may be calibrated with the + // DepthCalibration parameter. + //----------------------------------------------------------------------- + // + void + AdoptInterestOrigin(InterestOrigin *interestOrigin); + + // + //----------------------------------------------------------------------- + // OrphanInterestOrigin + //----------------------------------------------------------------------- + // + void + OrphanInterestOrigin(InterestOrigin *interest_origin); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Entity methods +// +public: + // + //----------------------------------------------------------------------- + // NotifyOfEntityCreation + //----------------------------------------------------------------------- + // + void + NotifyOfEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + + // + //----------------------------------------------------------------------- + // NotifyOfEntityDestruction + // + // This method is called to notify the interest manager that a + // entity has been destroyed. + //----------------------------------------------------------------------- + // + void + NotifyOfEntityDestruction(Entity *entity); + + // + //----------------------------------------------------------------------- + // EntityUpdateInterestZone + // + // This method is called if the entity may have changed the + // interest zone that it is in. This is used by the update + // manager. + //----------------------------------------------------------------------- + // + void + EntityUpdateInterestZone(Entity *entity); + + // + //----------------------------------------------------------------------- + // EntityForceToInteresting + // + // This forces the interest manager to treat the entity as + // interesting. + // + // HACK - Is effect local? Is the entity forced to be + // interesting on just this host? Or, does the effect pervade + // all hosts? + //----------------------------------------------------------------------- + // + void + EntityForceToInteresting(Entity *entity); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accesors for interest lattice manager +// +public: + InterestLatticeManager* + GetInterestLatticeManager(); + + InterestZone* + GetInterestZone(InterestZoneID interestZoneID); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + // + // Message IDs + // + enum + { + // + //-------------------------------------------------------------------- + // Sent by an interest manager to itself and others when it has been + // notified that a new dynamic entity has been created on the host + // machine. + //-------------------------------------------------------------------- + // + NewDynamicEntityMessageID = NetworkClient::NextMessageID, + + #if 0 + // + //-------------------------------------------------------------------- + // Sent by an interest manager to itself and others when it has been + // notified that a new dynamic map entity has been created on the + // host machine. + //-------------------------------------------------------------------- + // + NewMapEntityMessageID, + #endif + + // + //-------------------------------------------------------------------- + // Sent by an interest manager to itself and others when it has been + // notified that a entity is under going deletion. + //-------------------------------------------------------------------- + // + DestroyDynamicEntityMessageID, + + // + //-------------------------------------------------------------------- + // Message is sent to the host of the original (serving) entity that + // the host id wishes to be on the entities update list. + //-------------------------------------------------------------------- + // + EntitySubscribeToUpdatesMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to itself and others when a hosted + // entity needs to send updates to its replicants. + //-------------------------------------------------------------------- + // + EntityUpdateReplicantsMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to itself and others when a hosted + // entity needs to broadcast a message to its replicants. + //-------------------------------------------------------------------- + // + EntityBroadcastToReplicantsMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to itself and others when a hosted + // entity has changed interest zones. + //-------------------------------------------------------------------- + // + EntityNewInterestZoneMessageID, + + // + //-------------------------------------------------------------------- + // Sent by the interest manager to others when its interest arena has + // changed. + //-------------------------------------------------------------------- + // + HostInterestArenaChangedMessageID, + + // + //-------------------------------------------------------------------- + // Tells interest managers of a change to a interest zone. This is + // for the purpose of creating and destroying Dynamic Map Entities. + // The creation time stamp is used by the interest manager to resolve + // synchronization problems. + //-------------------------------------------------------------------- + // + InterestZoneDeltaMessageID, + + NextMessageID + }; + + // + // Message types + // + typedef Entity__MakeMessage + NewDynamicEntityMessage; + typedef Entity__DestroyEntityMessage + DestroyDynamicEntityMessage; + typedef Entity__UpdateMessage + EntityUpdateReplicantsMessage; + + typedef InterestManager__EntitySubscribeToUpdatesMessage + EntitySubscribeToUpdatesMessage; + typedef InterestManager__EntityBroadcastToReplicantsMessage + EntityBroadcastToReplicantsMessage; + typedef InterestManager__EntityNewInterestZoneMessage + EntityNewInterestZoneMessage; + typedef InterestManager__HostInterestArenaChangedMessage + HostInterestArenaChangedMessage; + typedef InterestManager__InterestZoneDeltaMessage + InterestZoneDeltaMessage; + + // + //----------------------------------------------------------------------- + // NewDynamicEntityHandler + //----------------------------------------------------------------------- + // + void + NewDynamicEntityHandler(NewDynamicEntityMessage *message); + + // + //----------------------------------------------------------------------- + // DestroyEntityHandler + //----------------------------------------------------------------------- + // + void + DestroyDynamicEntityHandler(DestroyDynamicEntityMessage *message); + + // + //----------------------------------------------------------------------- + // EntitySubscribeToUpdates & EntitySubscribeToUpdatesHandler + //----------------------------------------------------------------------- + // + void + EntitySubscribeToUpdates( + EntityID entity_ID, + HostID master_host, + HostID replicant_host + ); + void + EntitySubscribeToUpdatesHandler( + EntitySubscribeToUpdatesMessage *message + ); + + // + //----------------------------------------------------------------------- + // EntityUpdateReplicants & EntityUpdateReplicantsHandler + // + // If the entity has any subscribers then send then update to subscribers. + //----------------------------------------------------------------------- + // + void + EntityUpdateReplicants( + Entity *entity, + Entity__UpdateMessage *update_message + ); + void + EntityUpdateReplicantsHandler( + EntityUpdateReplicantsMessage *update_message + ); + + // + //----------------------------------------------------------------------- + // EntityBroadcastToReplicants & EntityBroadcastToReplicantsHandler + // + // If the entity has any subscribers then send then update to subscribers. + //----------------------------------------------------------------------- + // + void + EntityBroadcastToReplicants( + Entity *entity, + Entity__Message *broadcast_message + ); + void + EntityBroadcastToReplicantsHandler( + EntityBroadcastToReplicantsMessage *broadcast_message + ); + + // + //----------------------------------------------------------------------- + // EntityNewInterestZoneHandler + //----------------------------------------------------------------------- + // + void + EntityNewInterestZoneHandler( + EntityNewInterestZoneMessage *message + ); + + // + //----------------------------------------------------------------------- + // HostInterestArenaChanged + //----------------------------------------------------------------------- + // + void + HostInterestArenaChangedHandler( + HostInterestArenaChangedMessage *message + ); + + // + //----------------------------------------------------------------------- + // InterestZoneDelta + //----------------------------------------------------------------------- + // + void + InterestZoneDeltaHandler( + InterestZoneDeltaMessage *message + ); + + // + //----------------------------------------------------------------------- + // LoadResourceFinished + //----------------------------------------------------------------------- + // + void + LoadResourceFinishedHandler(Message *message); + + // + //----------------------------------------------------------------------- + // Shared Data and message tables + //----------------------------------------------------------------------- + // + static Derivation *GetClassDerivations(); + static SharedData + DefaultData; + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Creation and Interest Event Posting +// +public: + void + PostRendererEvent( + Entity *entity, + Renderer *renderer, + Receiver::Message *message + ); + +private: + void + PostCreationEvent(Receiver::Message *message); + void + PostUpdateEvent( + Entity *entity, + Receiver::Message *message + ); + void + PostDestructionEvent( + Entity *entity, + Receiver::Message *message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private entity creation and destruction management +// +private: + void + StaticEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + void + DynamicEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + void + ReplicantEntityCreation( + Entity *entity, + Entity__MakeMessage *creation_message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private interest origin management +// +private: + void + AddInterestingEntityToInterestOrigins(Entity *entity); + void + RemoveUninterestingEntityFromInterestOrigins(Entity *entity); + void + AddInterestingEntitiesToInterestOrigin( + InterestOrigin *interest_origin + ); + void + RemoveUninterestingEntitiesFromInterestOrigin( + InterestOrigin *interest_origin + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + InterestLatticeManager + interestLatticeManager; + SChainOf + interestOriginSocket; + InterestArena + *interestArena; + + static unsigned char + messageBuildBuffer[INTERESTMANAGER_MESSAGE_BUFFER_SIZE]; +}; + +//~~~~~~~~~~~~~ InterestManager__EntitySubscribeToUpdatesMessage ~~~~~~~~~~~ + +class InterestManager__EntitySubscribeToUpdatesMessage: + public NetworkClient::Message +{ +public: + InterestManager__EntitySubscribeToUpdatesMessage(); +}; + +//~~~~~~~~~~~ InterestManager__EntityBroadcastToReplicantsMessage ~~~~~~~~~~ + +class InterestManager__EntityBroadcastToReplicantsMessage: + public NetworkClient::Message +{ +public: + InterestManager__EntityBroadcastToReplicantsMessage( + size_t message_length + ); +}; + +//~~~~~~~~~~~~~ InterestManager__EntityNewInterestZoneMessage ~~~~~~~~~~~~~~ + +class InterestManager__EntityNewInterestZoneMessage: + public NetworkClient::Message +{ +public: + InterestManager__EntityNewInterestZoneMessage( + const EntityID &entity_ID, + InterestZoneID interest_zone_ID + ); + + EntityID + entityID; + InterestZoneID + interestZoneID; + // + // HACK - a way is needed to get from the entity the information + // required for another host to create the replicant + // +}; + +//~~~~~~~~~~~~~ InterestManager__HostInterestArenaChangedMessage ~~~~~~~~~~~ + +class InterestManager__HostInterestArenaChangedMessage: + public NetworkClient::Message +{ +public: + InterestManager__HostInterestArenaChangedMessage(); +}; + +//~~~~~~~~~~~~~~~~~ InterestManager__InterestZoneDeltaMessage ~~~~~~~~~~~~~~ + +class InterestManager__InterestZoneDeltaMessage: + public NetworkClient::Message +{ +public: + InterestManager__InterestZoneDeltaMessage(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ InterestManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline InterestLatticeManager* + InterestManager::GetInterestLatticeManager() +{ + return &interestLatticeManager; +} + +inline InterestZone* + InterestManager::GetInterestZone(InterestZoneID interestZoneID) +{ + Check(&interestLatticeManager); + return interestLatticeManager.GetInterestZone(interestZoneID); +} \ No newline at end of file diff --git a/MUNGA/INTORGN.cpp b/MUNGA/INTORGN.cpp new file mode 100644 index 0000000..c970f98 --- /dev/null +++ b/MUNGA/INTORGN.cpp @@ -0,0 +1,151 @@ +#include "munga.h" +#pragma hdrstop + +#include "intorgn.h" +#include "app.h" +#include "interest.h" + +//############################################################################# +//####################### InterestOrigin ################################ +//############################################################################# + +// +//############################################################################# +// InterestOrigin +//############################################################################# +// +InterestOrigin::InterestOrigin( + InterestZoneID interest_zone_ID, + InterestType interest_type, + InterestDepth depth_calibration +): + interestArenaSocket(NULL) +{ + interestZoneID = interest_zone_ID; + interestType = interest_type; + depthCalibration = depth_calibration; +} + +// +//############################################################################# +// ~InterestOrigin +//############################################################################# +// +InterestOrigin::~InterestOrigin() +{ + InterestArena *interest_arena; + + Check(&interestArenaSocket); + if ((interest_arena = interestArenaSocket.GetCurrent()) != NULL) + { + Unregister_Object(interest_arena); + delete interest_arena; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + InterestOrigin::TestInstance() const +{ + Node::TestInstance(); + + Verify(interestZoneID != NullInterestZoneID); + Verify( + interestType == VisualInterestType || + interestType == AudioInterestType || + interestType == GaugeInterestType || + interestType == CollisionInterestType + ); + Check(&interestArenaSocket); + + return True; +} + +// +//############################################################################# +// Update +//############################################################################# +// +void + InterestOrigin::Update( +#if DEBUG_LEVEL>0 + InterestZoneID interest_zone_ID +#else + InterestZoneID +#endif + ) +{ + Check(this); + Verify(interest_zone_ID != NullInterestZoneID); + + #if 0 + // + // If (the interest zone has changed) + // + // + // Calculate the new interest arena for this interest origin + // + + // + // Add this interest origin to a "changed" list + // + #else + // + // HACK - there is only one interest zone right now... + // + if (interestArenaSocket.GetCurrent() == NULL) + { + InterestManager *interest_manager; + + Check(application); + interest_manager = application->GetInterestManager(); + Check(interest_manager); + Check(interest_manager->GetInterestLatticeManager()); + + InterestArena *interest_arena = + interest_manager->GetInterestLatticeManager()->MakeInterestArena( + (InterestZoneID)0, + (InterestType)0, + (InterestDepth)0 + ); + Register_Object(interest_arena); + + interestArenaSocket.Add(interest_arena); + Verify(interest_arena == interestArenaSocket.GetCurrent()); + } + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + InterestOrigin::AddInterestingEntity(Entity*) +{ + Fail("InterestOrigin::AddInterestingEntity - Should never reach here\n"); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestOrigin::RemoveUninterestingEntity(Entity*) +{ + Fail("InterestOrigin::RemoveUninterestingEntity - Should never reach here\n"); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestOrigin::RemoveUninterestingEntities() +{ + Fail("InterestOrigin::RemoveUninterestingEntities - Should never reach here\n"); +} diff --git a/MUNGA/INTORGN.h b/MUNGA/INTORGN.h new file mode 100644 index 0000000..215ae45 --- /dev/null +++ b/MUNGA/INTORGN.h @@ -0,0 +1,176 @@ +#pragma once + +#include "network.h" +#include "lattice.h" + +class Entity; + +class InterestOrigin: + public Node +{ + friend class InterestManager; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor, and Testing +// +public: + ~InterestOrigin(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Update +// +public: + // + //----------------------------------------------------------------------- + // Update + // + // Updates the interest origins internal data structures for the + // interest zone ID. This method is most likely called by the + // renderer manager. + //----------------------------------------------------------------------- + // + virtual void + Update(InterestZoneID interest_zone_ID); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +private: +InterestZoneID + GetInterestZoneID(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor +// +protected: + InterestOrigin( + InterestZoneID interest_zone_ID, + InterestType interest_type, + InterestDepth depth_calibration + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest Manager support +// +private: + virtual void + AddInterestingEntity(Entity *interesting_entity); + virtual void + RemoveUninterestingEntity(Entity *uninteresting_entity); + virtual void + RemoveUninterestingEntities(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + InterestZoneID + interestZoneID; + InterestType + interestType; + InterestDepth + depthCalibration; + SlotOf + interestArenaSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~ InterestOrigin inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline InterestZoneID +InterestOrigin::GetInterestZoneID() +{ +Check(this); + return interestZoneID; +} + +#if 0 + //########################################################################## + //####################### InterestOrigin ############################# + //########################################################################## + + class InterestOrigin: + public Node + { + friend class InterestManager; + friend class InterestOrigin__InterestingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Public types + // + public: + typedef InterestOrigin__InterestingEntityIterator + InterestingEntityIterator; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, and Testing + // + public: + InterestOrigin( + const EntityID &entity_ID, + InterestType interest_type, + InterestDepth depth_calibration + ); + ~InterestOrigin(); + + Logical + TestInstance() const; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Renderer support + // + public: + // + //-------------------------------------------------------------------- + // UpdateInterestOrigin + // + // Updates the interest managers internal data structures for the + // interest origin entity. This method is most likely called by the + // renderer manager. It prepares the data that will be accessed by + // InterestingEntityIterator. + //-------------------------------------------------------------------- + // + virtual void + Update(); + + InterestArena* + GetInterestArena(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Interest Manager support + // + protected: + virtual void + AddInterestingEntity(Entity *interesting_entity); + virtual void + RemoveUninterestingEntity(Entity *uninteresting_entity); + virtual void + RemoveUninterestingEntities(); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Private data + // + private: + EntityID + entityID; + InterestType + interestType; + InterestDepth + depthCalibration; + SlotOf + interestArenaSocket; + SChainOf + interestingEntitySocket; + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~ InterestOrigin inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + + inline InterestArena* + InterestOrigin::GetInterestArena() + { + Check(this); + return interestArenaSocket.GetCurrent(); + } +#endif diff --git a/MUNGA/ITERATOR.cpp b/MUNGA/ITERATOR.cpp new file mode 100644 index 0000000..e6291ea --- /dev/null +++ b/MUNGA/ITERATOR.cpp @@ -0,0 +1,154 @@ +#include "munga.h" +#pragma hdrstop + +#include "iterator.h" + +// +//############################################################################# +//############################################################################# +// +Iterator::Iterator() +{ +} + +// +//############################################################################# +//############################################################################# +// +Iterator::~Iterator() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Iterator::TestInstance() const +{ + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + Iterator::First() +{ + Fail("Iterator::First - Should never reach here"); +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + Iterator::Last() +{ + Fail("Iterator::Last - Should never reach here"); +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + Iterator::Next() +{ + Fail("Iterator::Next - Should never reach here"); +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + Iterator::Previous() +{ + Fail("Iterator::Previous - Should never reach here"); +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + Iterator::GetSize() +{ + Fail("Iterator::GetSize - Should never reach here"); + return 0; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *Iterator::ReadAndNextImplementation() +{ + void *item; + + if ((item = GetCurrentImplementation()) != NULL) + { + Next(); + } + return item; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *Iterator::ReadAndPreviousImplementation() +{ + void *item; + + if ((item = GetCurrentImplementation()) != NULL) + { + Previous(); + } + return item; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + Iterator::GetCurrentImplementation() +{ + Fail("Iterator::GetCurrentImplementation - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *Iterator::GetNthImplementation(CollectionSize index) +{ + CollectionSize i = 0; + void *item; + + First(); + while ((item = GetCurrentImplementation()) != NULL) + { + if (i == index) + return item; + Next(); + i++; + } + return NULL; +} diff --git a/MUNGA/ITERATOR.h b/MUNGA/ITERATOR.h new file mode 100644 index 0000000..a59cebe --- /dev/null +++ b/MUNGA/ITERATOR.h @@ -0,0 +1,64 @@ +#pragma once + +#include "style.h" + +typedef int CollectionSize; +typedef int IteratorPosition; + +class Iterator SIGNATURED +{ +public: + virtual ~Iterator(); + Logical TestInstance() const; + + virtual void First(); + virtual void Last(); + + virtual void Next(); + virtual void Previous(); + + void *ReadAndNextItem() { return ReadAndNextImplementation(); } + void *ReadAndPreviousItem() { return ReadAndPreviousImplementation(); } + void *GetCurrentItem() { return GetCurrentImplementation(); } + + virtual CollectionSize GetSize(); + void *GetNthItem(CollectionSize index) { return GetNthImplementation(index); } + + virtual Iterator& BeginIterator() { return BeginImplementation(); } + virtual Iterator& EndIterator() { return EndImplementation(); } + + virtual Iterator& ForwardIterator() { return ForwardImplementation(); } + virtual Iterator& BackwardIterator(){ return BackwardImplementation(); } + +protected: + Iterator(); + + virtual void *ReadAndNextImplementation(); + virtual void *ReadAndPreviousImplementation(); + virtual void *GetCurrentImplementation(); + virtual void *GetNthImplementation(CollectionSize index); + + virtual Iterator& BeginImplementation() + { + First(); + return *this; + } + + virtual Iterator& EndImplementation() + { + Last(); + return *this; + } + + virtual Iterator& ForwardImplementation() + { + Next(); + return *this; + } + + virtual Iterator& BackwardImplementation() + { + Previous(); + return *this; + } +}; \ No newline at end of file diff --git a/MUNGA/JMOVER.cpp b/MUNGA/JMOVER.cpp new file mode 100644 index 0000000..ae2c912 --- /dev/null +++ b/MUNGA/JMOVER.cpp @@ -0,0 +1,2044 @@ +#include "munga.h" +#pragma hdrstop + +#include "jmover.h" +#include "fileutil.h" +#include "app.h" +#include "notation.h" +#include "namelist.h" + +//############################################################################# +//############################ JointedMover ############################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* JointedMover::GetClassDerivations() +{ static Derivation classDerivations(Mover::GetClassDerivations(), "JointedMover"); + return &classDerivations; +} + + +JointedMover::SharedData + JointedMover::DefaultData( + JointedMover::GetClassDerivations(), + JointedMover::GetMessageHandlers(), + JointedMover::GetAttributeIndex(), + JointedMover::StateCount, + (Entity::MakeHandler)JointedMover::Make + ); + +//############################################################################# +// Attribute Support +// + + const JointedMover::IndexEntry + JointedMover::AttributePointers[]= +{ + { + JointedMover::SegmentCountAttributeID, + "SegmentCount", + (Simulation::AttributePointer)&JointedMover::segmentCount + }, + { + JointedMover::SegmentTableAttributeID, + "SegmentTable", + (Simulation::AttributePointer)&JointedMover::segmentTable + }, + { + JointedMover::JointSubsystemAttributeID, + "JointSubsystem", + (Simulation::AttributePointer)&JointedMover::jointSubsystem + } +}; + +JointedMover::AttributeIndexSet& JointedMover::GetAttributeIndex() +{ + static JointedMover::AttributeIndexSet attributeIndex(ELEMENTS(JointedMover::AttributePointers), + JointedMover::AttributePointers, + Mover::GetAttributeIndex() + ); + return attributeIndex; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment* + JointedMover::GetSegment(CString segment_name) +{ + Check(this); + Check_Pointer(segment_name); + EntitySegment::SegmentTableIterator iterator(segmentTable); + + EntitySegment *current_segment; + + while( (current_segment = iterator.ReadAndNext() ) != NULL) + { + if(segment_name.Compare(current_segment->GetName()) == 0) + { + return current_segment; + } + } + return NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment* + JointedMover::GetSegmentFromDamageZone(CString damage_zone) +{ + EntitySegment::SegmentTableIterator iterator(segmentTable); + EntitySegment *current_segment; + while ((current_segment = iterator.ReadAndNext() ) != NULL) + { + EntitySegment::IntegerTableIterator *damage_iterator; + damage_iterator = current_segment->MakeDamageZoneIndexTable(); + Register_Object(damage_iterator); + EntitySegment::IntegerPlug *index_plug; + while ((index_plug = damage_iterator->ReadAndNext() ) != NULL) + { + CString current_name; + Verify(index_plug->GetItem() >= 0); + Verify(index_plug->GetItem() <= damageZoneCount); + + current_name = damageZones[index_plug->GetItem()]->damageZoneName; + Check_Pointer(¤t_name); + if(current_name.Compare(damage_zone) == 0) + { + Unregister_Object(damage_iterator); + delete damage_iterator; + return current_segment; + } + } + Unregister_Object(damage_iterator); + delete damage_iterator; + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + JointedMover::GetSegmentToWorld( + EntitySegment &my_segment, + LinearMatrix *transform + ) +{ + Check(this); + JointSubsystem *joints = GetJointSubsystem(); + Check(joints); + + // + //--------------------------------------------------------------- + // Check to see if the segment transforms need to be recalculated + //--------------------------------------------------------------- + // + if (joints->AreJointsModified()) + { + EntitySegment::SegmentTableIterator iterator(segmentTable); + EntitySegment *current_segment; + while( (current_segment = iterator.ReadAndNext() ) != NULL) + { + current_segment->ModifySegment(); + } + joints->ModifyJoints(False); + } + + // + //----------------------------- + // Compute the actual transform + //----------------------------- + // + transform->Multiply( + my_segment.GetSegmentToEntity(), + localToWorld + ); + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointedMover::JointedMover( + JointedMover::MakeMessage *creation_message, + JointedMover::SharedData &virtual_data +): + Mover(creation_message, virtual_data), + jointSubsystem(NULL), + segmentTable(this, True) +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the JointSubsystem + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + JointSubsystem *joint_subsystem = new JointSubsystem( + (Entity*) this, + Entity::EntitySubsystemID + ); + + Register_Object(joint_subsystem); + jointSubsystem.Add(joint_subsystem); + Check(joint_subsystem); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get Resource Description + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *skl_resource = + application->GetResourceFile()->SearchList( + creation_message->resourceID, + ResourceDescription::SkeletonStreamResourceType + ); + Check(skl_resource); + skl_resource->Lock(); + + DynamicMemoryStream segment_stream( + skl_resource->resourceAddress, + skl_resource->resourceSize); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // read in segmentCount and jointCount + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int joint_count; + segment_stream >> segmentCount >> joint_count; + + int current_joint_type; + int current_joint_index = 0; + + CString segment_name; + EntitySegment *parent_segment; + EntitySegment *current_segment; + int segment_joint_index; + Joint *segment_joint_pointer; + int parent_index; + CString video_object_name; + LinearMatrix segment_offset(LinearMatrix::Identity); + Logical site_segment; + + int ii; + for(ii=0;ii> segment_name >> parent_index; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // read parent index & find parentSegment ptr + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(parent_index == -1) + { + parent_segment = NULL; + } + else + { + EntitySegment::SegmentTableIterator iterator(segmentTable); + parent_segment = iterator.GetNth(parent_index); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Determine if this segment is a site + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + segment_stream >> site_segment >> current_joint_type; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the joint type & init the joint + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(current_joint_type != Joint::NULLJointType) + { + segment_joint_index = current_joint_index; + segment_joint_pointer = + new Joint( + joint_subsystem, + (Joint::JointType)current_joint_type + ); + Register_Object(segment_joint_pointer); + joint_subsystem->AddJoint(current_joint_index, segment_joint_pointer); + + ++current_joint_index; + } + else + { + segment_joint_pointer = NULL; + segment_joint_index = -1; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in the segment offset matrix + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + segment_stream >> segment_offset; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get The Primary Damage Zone + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int primary_dzone_index; + segment_stream >> primary_dzone_index; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create this segment and add + // add it to the segment table + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + current_segment = new EntitySegment( + segment_name, + ii, // my_index + parent_index, + segment_joint_index, + segment_joint_pointer, + segment_offset, + parent_segment, + site_segment, + primary_dzone_index + ); + Register_Object(current_segment); + segmentTable.AddValue(current_segment, ii); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int video_object_count; + EntitySegment::SkeletonType skl_type; + + segment_stream >> video_object_count; + Verify(video_object_count); + + int jj; + for(jj=0;jj> skl_type >> video_object_name; + if(video_object_name.Compare("None")) + { + current_segment->AddVideoObjectName( + video_object_name, + skl_type, + DamageZone::ExistsGraphicState + ); + } + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL DESTROYED VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int destroyed_video_object_count; + + segment_stream >> destroyed_video_object_count; + + for(jj=0;jj> skl_type >> video_object_name; + if(video_object_name.Compare("None")) + { + current_segment->AddVideoObjectName( + video_object_name, + skl_type, + DamageZone::DestroyedGraphicState + ); + } + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in DamageZone information + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int damage_zone_count; + int damage_zone_index; + + segment_stream >> damage_zone_count; + if(damage_zone_count) + { + + for(int dd=0;dd> damage_zone_index; + current_segment->AddDamageZone(damage_zone_index, dd); + } + } + // + // Read in the Children Information + // + int children_count; + int child_index; + + segment_stream >> children_count; + + if(children_count) + { + for(int jj=0;jj> child_index; + current_segment->AddChildIndex(child_index, jj); + } + } + } + skl_resource->Unlock(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize all the child Pointers for each segment + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(ii=0;iiMakeChildIndexTable(); + Register_Object(iterator); + EntitySegment::IntegerPlug *current_index; + int child_count=0; + while((current_index = iterator->ReadAndNext()) != NULL) + { + EntitySegment *child_segment; + child_segment = segment_iterator.GetNth(current_index->GetItem()); + Check(child_segment); + current_segment->AddChildPointer(child_segment, child_count); + ++child_count; + } + Unregister_Object(iterator); + delete iterator; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointedMover::~JointedMover() +{ + EntitySegment::SegmentTableIterator iterator(segmentTable); + iterator.DeletePlugs(); +// +//--------------------------------------------------------------------- +// This should be deleted by the entity subsystemArray[jointSubsystem] +//--------------------------------------------------------------------- +// +#if 0 + JointSubsystem *joint_subsystem = jointSubsystem.GetCurrent(); + Unregister_Object(joint_subsystem); + delete joint_subsystem; +#endif +} + +//######################################################################## +// DamageZone Support +// +ResourceDescription::ResourceID + JointedMover::CreateDamageZoneStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .skl file + //------------------- + // + const char* skl_entry; + if ( + !model_file->GetEntry( + "video", + "skeleton", + &skl_entry + ) + ) + { + DEBUG_STREAM << model_name << " is missing .skl file specification!\n" << std::flush; + return -1; + } + char *skl_filename = + MakePathedFilename(directories->videoDirectory, skl_entry); + Register_Pointer(skl_filename); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!\n" << std::flush; +Dump_And_Die_1: + Unregister_Pointer(skl_filename); + delete[] skl_filename; + Unregister_Object(skl_file); + delete skl_file; + return ResourceDescription::NullResourceID; + } + + // + //------------------- + // Find the .dmg file + //------------------- + // + const char* dmg_entry; + if ( + !model_file->GetEntry( + "gamedata", + "DamageZones", + &dmg_entry + ) + ) + { + DEBUG_STREAM << model_name << " is missing .dmg file specification!\n" << std::flush; + goto Dump_And_Die_1; + } + + char *dmg_filename = + MakePathedFilename(directories->modelDirectory, dmg_entry); + Register_Pointer(dmg_filename); + + NotationFile *dmg_file = new NotationFile(dmg_filename); + Register_Object(dmg_file); + + if (!dmg_file->PageCount()) + { + DEBUG_STREAM << dmg_filename << " is empty or missing!\n" << std::flush; +Dump_And_Die_2: + Unregister_Pointer(dmg_filename); + delete[] dmg_filename; + Unregister_Object(dmg_file); + delete dmg_file; + goto Dump_And_Die_1; + } + + // + // Get the number of Damage zones + // + int dzone_count; + if ( + !skl_file->GetEntry( + "ROOT", + "DZoneCount", + &dzone_count + ) + ) + { + DEBUG_STREAM << model_name << " is missing DZoneCount \n" << std::flush; + goto Dump_And_Die_2; + } + + DynamicMemoryStream damage_zone_stream; + + // + // write the Damage Zone Count Info from the + // .dmg file to the stream + // + damage_zone_stream << dzone_count; + + // + // Make an entry list of all the entries in the damage zone page + // + NameList *dzone_namelist = + skl_file->MakeEntryList("DamageZones","dz_"); + Register_Object(dzone_namelist); + + if (dzone_namelist->EntryCount() == 0) + { + DEBUG_STREAM << "No dZones listed in DamageZones Page"<GetFirstEntry(); + + while (dzone_entry) + { + ++num_dzones_found; + // + // Get dzone name in .skl file + // + Str_Copy( + current_dzone_name, + dzone_entry->GetName(), + sizeof(current_dzone_name) + ); + + // + // Create the stream for this damage zone + // + DamageZone::CreateStreamedDamageZone( + model_file, + model_name, + skl_file, + current_dzone_name, + &damage_zone_stream, + dmg_file, + directories + ); + + // + // Get next dzone entry in this segment page + // + dzone_entry = dzone_entry->GetNextEntry(); + } // End while more dzone_entries + + if(dzone_count != num_dzones_found) + { + DEBUG_STREAM <<"DZoneCount != damage zones found in Page DamageZones"<AddResourceMemoryStream( + model_name, + ResourceDescription::DamageZoneStreamResourceType, + 1, + ResourceDescription::Preload, + &damage_zone_stream + ); + Check(new_res); + // + // Free mem + // + Unregister_Pointer(skl_filename); + delete skl_filename; + Unregister_Object(skl_file); + delete skl_file; + Unregister_Pointer(dmg_filename); + delete dmg_filename; + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dzone_namelist); + delete dzone_namelist; + return new_res->resourceID; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + JointedMover::CreateSkeletonStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .skl file + //------------------- + // + const char *entry_data; + if ( + !model_file->GetEntry( + "video", + "skeleton", + &entry_data + ) + ) + { + DEBUG_STREAM << model_name << " is missing .skl file specification!\n" << std::flush; + return -1; + } + // + // Get the name of the SKL File + // + char *filename = MakePathedFilename(directories->videoDirectory, entry_data); + Register_Pointer(filename); + + // + // Create a Notation file from the skl ASCII File + // + NotationFile *skl_file = new NotationFile(filename); + Register_Object(skl_file); + + // + // Get number of Segments(or Pages) + // + int segment_count = skl_file->PageCount(); + + // + // Do not count Lab_Only and DamageZones they are not included + // + if (skl_file->PageExists("LAB_ONLY")) + --segment_count; + if(skl_file->PageExists("DamageZones")) + --segment_count; + + if (!segment_count) + { + DEBUG_STREAM << model_name << " has no Segments!\n" << std::flush; +Dump_And_Die: + Unregister_Pointer(filename); + delete filename; + Unregister_Object(skl_file); + delete skl_file; + return -1; + } + int joint_count; + if ( + !skl_file->GetEntry( + "ROOT", + "JointCount", + &joint_count + ) + ) + { + DEBUG_STREAM << model_name << " is missing JointCount \n" << std::flush; + goto Dump_And_Die; + } + DynamicMemoryStream segment_stream; + + // + // Write Segment Count to the stream + // + segment_stream << segment_count << joint_count; + + // + // Create a list of the pages and get the first entry + // + NameList *segment_namelist = skl_file->MakePageList(); + Register_Object(segment_namelist); + NameList::Entry *segment_entry = segment_namelist->GetFirstEntry(); + int + parent_index = -1, + children_count; + + CString + segment_page_name; + + EulerAngles + rotation; + + Point3D + translation; + + LinearMatrix + base_offset(LinearMatrix::Identity); + + while(segment_entry) + { + segment_page_name = segment_entry->GetName(); + + if( + (strcmp(segment_page_name, "LAB_ONLY") == 0) || + (strcmp(segment_page_name,"DamageZones") ==0) + ) + { + segment_entry = segment_entry->GetNextEntry(); + continue; + } + + segment_stream << segment_page_name; + // + // Get the information about the parent + // + const char *parent_name; + if( + skl_file->GetEntry( + segment_page_name, + "parent", + &parent_name + ) + ) + { + parent_index = GetSegmentIndex(parent_name, skl_file); + if(parent_index == -1) + { + DEBUG_STREAM<GetEntry( + segment_page_name, + "Type", + &joint_name) + ) + { + if( strcmp("ROOT", segment_page_name) != 0) + { + is_site = True; + } + } + else + { + if(strcmp(joint_name,"static")==0) + { + joint_type = Joint::StaticJointType; + } + else + if(strcmp(joint_name, "hingex")==0) + { + joint_type = Joint::HingeXJointType; + } + else + if(strcmp(joint_name,"hingey")==0) + { + joint_type = Joint::HingeYJointType; + } + else + if(strcmp(joint_name,"hingez")==0) + { + joint_type = Joint::HingeZJointType; + } + else + if(strcmp(joint_name,"ball")==0) + { + joint_type = Joint::BallJointType; + } + else + if(strcmp(joint_name,"balltranslate")==0) + { + joint_type = Joint::BallTranslationJointType; + } + } + segment_stream << is_site << joint_type; + // + // Get offsets + // + skl_file->GetEntry(segment_page_name, "tranx" ,&translation.x); + skl_file->GetEntry(segment_page_name, "trany" ,&translation.y); + skl_file->GetEntry(segment_page_name, "tranz" ,&translation.z); + skl_file->GetEntry(segment_page_name, "pitch" ,&rotation.pitch.angle); + skl_file->GetEntry(segment_page_name, "yaw" ,&rotation.yaw.angle); + skl_file->GetEntry(segment_page_name, "roll" ,&rotation.roll.angle); + + base_offset = translation; + base_offset = rotation; + + // + // Write out the base offset + // + segment_stream << base_offset; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Primary Damage Zone + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char* skl_entry; + if (!model_file->GetEntry( + "video", + "skeleton", + &skl_entry + ) + ) + { + goto Dump_And_Die; + } + else + { + CString skl_filename = + MakePathedFilename(directories->videoDirectory, skl_entry); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!"<GetEntry( + segment_page_name, + "dzone", + &dzone_name + ) + ) + { + primary_damage_zone = GetDamageZoneIndex(dzone_name, skl_file); + } + else + { + primary_damage_zone = -1; + } + segment_stream << primary_damage_zone; + Unregister_Object(skl_file); + delete skl_file; + } + + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (! + InitVideoObjectNames( + &segment_stream, + model_file, + segment_page_name, + directories + ) + ) + { + goto Dump_And_Die; + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in ALL DESTROYED VideoObjectNames + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (! + InitDestroyedVideoObjectNames( + &segment_stream, + model_file, + segment_page_name, + directories + ) + ) + { + goto Dump_And_Die; + } + + // + // Get the damageZones associated with this segment + // + NameList *damage_zone_list = + skl_file->MakeEntryList(segment_entry->GetName(), "dzone"); + Register_Object(damage_zone_list); + + NameList::Entry *damage_zone_entry = damage_zone_list->GetFirstEntry(); + + int damage_zone_count = damage_zone_list->EntryCount(); + + segment_stream << damage_zone_count; + + if (damage_zone_count) + { + for (int dd=0;ddGetChar(); + + int damage_zone_index; + damage_zone_index = + GetDamageZoneIndex(damage_zone_name, skl_file); + + if(damage_zone_index == -1) + { + + DEBUG_STREAM<GetNextEntry(); + } + } + Unregister_Object(damage_zone_list); + delete damage_zone_list; + + // + // Get the number of children, 0 if no children + // + NameList *children_list = + skl_file->MakeEntryList(segment_entry->GetName(),"joint"); + Register_Object(children_list); + NameList::Entry *child_entry = children_list->GetFirstEntry(); + children_count = 0; + while(child_entry) + { + ++children_count; + child_entry = child_entry->GetNextEntry(); + } + // + // Write how many children + // + segment_stream << children_count; + if(children_count) + { + child_entry = children_list->GetFirstEntry(); + // + // Write out the segment index for every child + // + for(int cc=0;ccGetChar(), skl_file); + if(child_index == -1) + { + DEBUG_STREAM<GetName()<<" Not Found!!"<GetNextEntry(); + } + } + Unregister_Object(children_list); + delete children_list; + segment_entry = segment_entry->GetNextEntry(); + } + + // + //-------------------------------------------------------------------- + // Write the stream out to disk. + //-------------------------------------------------------------------- + // + ResourceDescription *new_res = + resource_file->AddResourceMemoryStream( + model_name, + ResourceDescription::SkeletonStreamResourceType, + 1, + ResourceDescription::Preload, + &segment_stream + ); + Check(new_res); + + // + // Fre Mem + // + Unregister_Pointer(filename); + delete filename; + Unregister_Object(skl_file); + delete skl_file; + Unregister_Object(segment_namelist); + delete segment_namelist; + + return new_res->resourceID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + JointedMover::InitDestroyedVideoObjectNames( + MemoryStream *mem_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ) +{ + Check(model_file); + Check(mem_stream); + + NameList *skl_namelist = model_file->MakeEntryList("video","destroyed"); + Register_Object(skl_namelist); + int entry_count = skl_namelist->EntryCount(); + *mem_stream << entry_count; + + if (!entry_count) + { + Unregister_Object(skl_namelist); + delete skl_namelist; + return True; + } + Verify(entry_count); + + NameList::Entry *skl_entry = skl_namelist->GetFirstEntry(); + while(skl_entry) + { + CString entry_name = skl_entry->GetName(); + EntitySegment::SkeletonType skeleton_type; + if (! entry_name.Compare("destroyed") ) + { + skeleton_type = EntitySegment::SkeletonType_N; + } + else if (! entry_name.Compare("destroyeds") ) + { + skeleton_type = EntitySegment::SkeletonType_S; + } + else if (! entry_name.Compare("destroyedt") ) + { + skeleton_type = EntitySegment::SkeletonType_T; + } + else if (! entry_name.Compare("destroyedo") ) + { + skeleton_type = EntitySegment::SkeletonType_O; + } + else if (! entry_name.Compare("destroyeda") ) + { + skeleton_type = EntitySegment::SkeletonType_A; + } + else if (! entry_name.Compare("destroyedb") ) + { + skeleton_type = EntitySegment::SkeletonType_B; + } + else if (! entry_name.Compare("destroyedc") ) + { + skeleton_type = EntitySegment::SkeletonType_C; + } + else if (! entry_name.Compare("destroyedd") ) + { + skeleton_type = EntitySegment::SkeletonType_D; + } + *mem_stream << skeleton_type; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the video object filename + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString short_skl_filename = skl_entry->GetChar(); + CString skl_filename = + MakePathedFilename(directories->videoDirectory, short_skl_filename); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!"<GetEntry( + page_name, + "Object", + &c_name + ) + ) + { + video_object_name = c_name; + } + else + { + video_object_name = "None"; + } + *mem_stream << video_object_name; + + Unregister_Object(skl_file); + delete skl_file; + + skl_entry = skl_entry->GetNextEntry(); + } + Unregister_Object(skl_namelist); + delete skl_namelist; + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + JointedMover::InitVideoObjectNames( + MemoryStream *mem_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ) +{ + Check(model_file); + Check(mem_stream); + + NameList *skl_namelist = model_file->MakeEntryList("video","skeleton"); + Register_Object(skl_namelist); + int entry_count = skl_namelist->EntryCount(); + + Verify(entry_count); + *mem_stream << entry_count; + + NameList::Entry *skl_entry = skl_namelist->GetFirstEntry(); + while(skl_entry) + { + CString entry_name = skl_entry->GetName(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Write out the skeleton type + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + EntitySegment::SkeletonType skeleton_type; + if (! entry_name.Compare("skeleton") ) + { + skeleton_type = EntitySegment::SkeletonType_N; + } + else if (! entry_name.Compare("skeletons") ) + { + skeleton_type = EntitySegment::SkeletonType_S; + } + else if (! entry_name.Compare("skeletont") ) + { + skeleton_type = EntitySegment::SkeletonType_T; + } + else if (! entry_name.Compare("skeletono") ) + { + skeleton_type = EntitySegment::SkeletonType_O; + } + else if (! entry_name.Compare("skeletona") ) + { + skeleton_type = EntitySegment::SkeletonType_A; + } + else if (! entry_name.Compare("skeletonb") ) + { + skeleton_type = EntitySegment::SkeletonType_B; + } + else if (! entry_name.Compare("skeletonc") ) + { + skeleton_type = EntitySegment::SkeletonType_C; + } + else if (! entry_name.Compare("skeletond") ) + { + skeleton_type = EntitySegment::SkeletonType_D; + } + *mem_stream << skeleton_type; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the video object filename + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString short_skl_filename = skl_entry->GetChar(); + CString skl_filename = + MakePathedFilename(directories->videoDirectory, short_skl_filename); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!"<GetEntry( + page_name, + "Object", + &c_name + ) + ) + { + video_object_name = c_name; + } + else + { + video_object_name = "None"; + } + *mem_stream << video_object_name; + + Unregister_Object(skl_file); + delete skl_file; + + skl_entry = skl_entry->GetNextEntry(); + } + Unregister_Object(skl_namelist); + delete skl_namelist; + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + JointedMover::GetDamageZoneIndex( + CString damage_zone_name, + NotationFile *skl_file + ) +{ + int damage_zone_index = -1; + + NameList *name_list = skl_file->MakeEntryList("DamageZones", "dz_"); + Register_Object(name_list); + + if (name_list->EntryCount() == 0) + { + DEBUG_STREAM << "No dZones listed in DamageZones Page"<GetFirstEntry(); + while(damage_zone) + { + if(strcmp(damage_zone->GetName(), damage_zone_name) == 0) + { + Convert_From_Ascii(damage_zone->GetChar(), &damage_zone_index); + Unregister_Object(name_list); + delete name_list; + return damage_zone_index; + } + damage_zone = damage_zone->GetNextEntry(); + } + Unregister_Object(name_list); + delete name_list; + + return damage_zone_index; + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + JointedMover::GetSegmentIndex( + CString segment_name, + NotationFile *skl_file + ) +{ + int segment_index=-1; + + char page_name[128]; + NameList *page_list = skl_file->MakePageList(); + Register_Object(page_list); + NameList::Entry *current_entry = page_list->GetFirstEntry(); + while(current_entry) + { + Str_Copy( + page_name, + current_entry->GetName(), + sizeof(page_name) + ); + if( + (strcmp(page_name, "LAB_ONLY") == 0) || + (strcmp(page_name,"DamageZones") == 0) + ) + { + current_entry = current_entry->GetNextEntry(); + continue; + } + ++segment_index; + if((strcmp(page_name, segment_name) == 0)) + { + Unregister_Object(page_list); + delete page_list; + return segment_index; + } + current_entry = current_entry->GetNextEntry(); + } + Unregister_Object(page_list); + delete page_list; + return -1; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointedMover* + JointedMover::Make(JointedMover::MakeMessage *creation_message) +{ + return new JointedMover(creation_message, DefaultData); +} +//########################################################################## +//########################## Animation ############################### +//########################################################################## + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AnimationInstance::AnimationInstance(JointedMover *jointed_mover) +{ + Check_Pointer(this); + Check(jointed_mover); + + lerpToZero = False; + moverToAnimate = jointed_mover; + jointSubToAnimate = jointed_mover->GetJointSubsystem(); + animationResource = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + AnimationInstance::SetAnimation( + ResourceDescription::ResourceID animation_number, + JointedMover::AnimationCallback finished_callback + ) +{ + Check_Pointer(this); + finishedCallback = finished_callback; + currentTime = 0.0f; + currentFrame = 0; + + if (animationResource) + { + Check(animationResource); + animationResource->Unlock(); + } + animationResource = + application->GetResourceFile()->FindResourceDescription( + animation_number + ); + Check(animationResource); + animationResource->Lock(); + int *animation_data = (int*)animationResource->resourceAddress; + Check_Pointer(animation_data); + frameCount = animation_data[0]; + jointCount = animation_data[1]; + footStepThreshold = (float *)&animation_data[2]; + jointIndices = &animation_data[3]; + frameStart = (Scalar*)(jointIndices + jointCount); + + keyFrames = frameStart + frameCount; + currentFrameTo = keyFrames; + void* to; + to = keyFrames; + // + //----------------------------------- + // find the end of the keyframes data + //----------------------------------- + // + for(int ii=0;iiGetJoint(jointIndices[jj])->GetJointType()) + { + case Joint::BallTranslationJointType: + { + to = (void *)((char *)to+sizeof(EulerAngles)); + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeXJointType: + case Joint::HingeYJointType: + case Joint::HingeZJointType: + { + to = (void *)((char *)to+sizeof(Hinge)); + break; + } + case Joint::BallJointType: + to = (void *)((char *)to+sizeof(EulerAngles)); + break; + } + } + + // + // + // This should be contained in the keyframes + // + // keyJointPos = (Vector3D*)(keyFrames + jointCount*frameCount); + + rootTranslations = (Vector3D*)(to); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AnimationInstance::~AnimationInstance() +{ + if (animationResource) + { + Check(animationResource); + animationResource->Unlock(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + AnimationInstance::Animate(Scalar time_slice, Logical move_joints) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Find the frame to lerp towards. As each frame boundary is crossed, set + // the joints to the position of that boundary and adjust the remaining time + // to lerp + //-------------------------------------------------------------------------- + // + int i; + // + //----------------------------------------- + // This void * can point to any joint type + //----------------------------------------- + // + void + *to; + + + Scalar frame_time = currentTime + time_slice; + Scalar movement = 0.0f; + + // + //------------------------------------------------------------- + // to points to the place in the memory stream we left off at + // last time we were on this loop + //------------------------------------------------------------- + // + to = currentFrameTo; + Joint *current_joint; + + while (currentFrame < frameCount) + { + if (frame_time < frameStart[currentFrame]) + { + break; + } + for (i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Only modify the joint if the value has changed + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (current_joint->GetEulerAngles() != *(EulerAngles*)to) + { + if (move_joints) + { + current_joint->SetRotation(*(EulerAngles*)to); + } + } + to = (void *)((char *)to+sizeof(EulerAngles)); + + if (current_joint->GetTranslation() != *(Point3D*)to) + { + if (move_joints) + { + current_joint->SetTranslation(*(Point3D*)to); + } + } + + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeXJointType: + case Joint::HingeYJointType: + case Joint::HingeZJointType: + { + if (current_joint->GetHinge() != *(Hinge*) to) + { + if (move_joints) + { + current_joint->SetHinge(*(Hinge*) to); + } + } + to = (void *)((char *)to+sizeof(Hinge)); + break; + } + case Joint::BallJointType: + + if (current_joint->GetEulerAngles() != *(EulerAngles*)to) + { + if (move_joints) + { + current_joint->SetRotation(*(EulerAngles*)to); + } + } + to = (void *)((char *)to+sizeof(EulerAngles)); + break; + case Joint::StaticJointType: + break; + } + } + movement += + (frameStart[currentFrame] - currentTime) + * rootTranslations[currentFrame].z; + currentTime = frameStart[currentFrame]; + ++currentFrame; + } + + // + //---------------------------------------------------------------------- + // We we have run off the end of the animation, trigger the callback and + // return + //---------------------------------------------------------------------- + // + if (currentFrame == frameCount) + { + + movement += + (moverToAnimate->*finishedCallback)( + animationResource->resourceID, + frame_time - frameStart[frameCount - 1], + move_joints + ); + return movement; + } + + currentFrameTo = to; + // + //------------------------------------------------------- + // Set up to lerp the rotations between to two key frames + //------------------------------------------------------- + // + Verify(!Small_Enough(frameStart[currentFrame] - currentTime)); + Scalar delta = + (frame_time - currentTime)/(frameStart[currentFrame] - currentTime); + + for (i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + Point3D new_trans; + EulerAngles new_angles; + + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + if (move_joints) + { + current_joint->SetRotation(new_angles); + } + } + to = (void *)((char *)to+sizeof(EulerAngles)); + + new_trans.Lerp( + current_joint->GetTranslation(), + *(Vector3D*)to, + delta + ); + if (current_joint->GetTranslation() != new_trans) + { + if (move_joints) + { + current_joint->SetTranslation(new_trans); + } + } + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeZJointType: + case Joint::HingeYJointType: + case Joint::HingeXJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + *(Hinge*)to, + delta + ); + if (current_joint->GetRadians() != new_hinge.rotationAmount) + { + if (move_joints) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + } + to = (void *)((char *)to+sizeof(Hinge)); + + break; + } + case Joint::BallJointType: + { + EulerAngles new_angles; + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + if (move_joints) + { + current_joint->SetRotation(new_angles); + } + } + + to = (void *)((char *)to+sizeof(EulerAngles)); + + break; + } + case Joint::StaticJointType: + break; + } + } + movement += (frame_time - currentTime) * rootTranslations[currentFrame].z; + currentTime = frame_time; + return movement; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +Logical + AnimationInstance::LerpToPose(Scalar time_slice, Scalar time_to_lerp, Logical move_joints) +{ + Check(this); + + int i; + // + //----------------------------------------- + // This void * can point to any joint type + //----------------------------------------- + // + void + *to; + + + if (!lerpToZero) + { + lerpToZero = True; + deltaTime = time_to_lerp; + } + + Scalar delta = time_slice / deltaTime; + + + // + //------------------------------------------------------------- + // to points to the place in the memory stream we left off at + // last time we were on this loop + //------------------------------------------------------------- + // + + to = currentFrameTo; + Joint *current_joint; + + if (move_joints) + { + for (i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + Point3D new_trans; + EulerAngles new_angles; + + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + to = (void *)((char *)to+sizeof(EulerAngles)); + + new_trans.Lerp( + current_joint->GetTranslation(), + *(Vector3D*)to, + delta + ); + if (current_joint->GetTranslation() != new_trans) + { + current_joint->SetTranslation(new_trans); + } + to = (void *)((char *)to+sizeof(Vector3D)); + break; + } + case Joint::HingeZJointType: + case Joint::HingeYJointType: + case Joint::HingeXJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + *(Hinge*)to, + delta + ); + if (current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + to = (void *)((char *)to+sizeof(Hinge)); + + break; + } + case Joint::BallJointType: + { + EulerAngles new_angles; + new_angles.Lerp( + current_joint->GetEulerAngles(), + *(EulerAngles*)to, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + + to = (void *)((char *)to+sizeof(EulerAngles)); + + break; + } + case Joint::StaticJointType: + break; + } + } + + } + + deltaTime -= time_slice; + if (deltaTime <= 0.0f) + { + lerpToZero = False; + return False; + } + return True; + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +Logical + AnimationInstance::LerpToRest(Scalar time_slice, Scalar time_to_lerp, Logical move_joints) +{ + + + if (!lerpToZero) + { + lerpToZero = True; + deltaTime = time_to_lerp; + } + + Scalar delta = time_slice / deltaTime; + + if (move_joints) + { + EulerAngles zero_euler(0.0f, 0.0f, 0.0f); + Hinge zero_hingeX(0.0f, X_Axis); + Hinge zero_hingeY(0.0f, Y_Axis); + Hinge zero_hingeZ(0.0f, Z_Axis); + Vector3D zero_vector(0.0f, 0.0f, 0.0f); + + for (int i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + EulerAngles new_angles; + new_angles.Lerp( + current_joint->GetEulerAngles(), + zero_euler, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + + Point3D new_trans; + + new_trans.Lerp( + current_joint->GetTranslation(), + zero_vector, + delta + ); + if (current_joint->GetTranslation() != new_trans) + { + current_joint->SetTranslation(new_trans); + } + break; + } + case Joint::HingeXJointType: + { + Hinge new_hinge; + + new_hinge.Lerp( + current_joint->GetHinge(), + zero_hingeX, + delta + ); + if(current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + break; + + } + case Joint::HingeYJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + zero_hingeY, + delta + ); + if(current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + break; + } + case Joint::HingeZJointType: + { + Hinge new_hinge; + new_hinge.Lerp( + current_joint->GetHinge(), + zero_hingeZ, + delta + ); + if(current_joint->GetRadians() != new_hinge.rotationAmount) + { + current_joint->SetRotation(new_hinge.rotationAmount); + } + break; + } + case Joint::BallJointType: + { + EulerAngles new_angles; + + new_angles.Lerp( + current_joint->GetEulerAngles(), + zero_euler, + delta + ); + if (current_joint->GetEulerAngles() != new_angles) + { + current_joint->SetRotation(new_angles); + } + + break; + } + case Joint::StaticJointType: + break; + } + } + } + deltaTime -= time_slice; + if (deltaTime <= 0.0f) + { + lerpToZero = False; + return False; + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void + AnimationInstance::SnapToRest(Logical move_joints) +{ + + if (!move_joints) + { + return; + } + + EulerAngles zero_euler(0.0f, 0.0f, 0.0f); + Hinge zero_hingeX(0.0f, X_Axis); + Hinge zero_hingeY(0.0f, Y_Axis); + Hinge zero_hingeZ(0.0f, Z_Axis); + Point3D zero_point(0.0f, 0.0f, 0.0f); + + for (int i=0; iGetJoint(jointIndices[i]); + Check(current_joint); + switch(current_joint->GetJointType()) + { + case Joint::BallTranslationJointType: + { + current_joint->SetRotation(zero_euler); + current_joint->SetTranslation(zero_point); + break; + } + case Joint::HingeXJointType: + { + current_joint->SetHinge(zero_hingeX); + break; + } + case Joint::HingeYJointType: + { + current_joint->SetHinge(zero_hingeY); + break; + } + case Joint::HingeZJointType: + { + current_joint->SetHinge(zero_hingeZ); + break; + } + case Joint::BallJointType: + { + current_joint->SetRotation(zero_euler); + break; + } + case Joint::StaticJointType: + break; + } + } +} +//########################################################################## +//############## Sketon Notation file utilities #################### +//########################################################################## + + +int + Get_Active_Joint_Count(NotationFile *skl_file) +{ + NameList *namelist = skl_file->MakePageList("joint"); + Register_Object(namelist); + NameList::Entry *entry = namelist->GetFirstEntry(); + + int count = 0; + + while (entry) + { + ++count; + entry = entry->GetNextEntry(); + } + + Unregister_Object(namelist); + delete namelist; + + return count; +} + +Logical + JointedMover::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/JMOVER.h b/MUNGA/JMOVER.h new file mode 100644 index 0000000..4c73cd9 --- /dev/null +++ b/MUNGA/JMOVER.h @@ -0,0 +1,245 @@ +#pragma once + +#include "mover.h" +#include "joint.h" +#include "slot.h" +#include "segment.h" + +//############################################################################## +//######################## JointedMover ################################## +//############################################################################## + +class JointedMover: + public Mover +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +#if 0 +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum{ + SegmentCountAttributeID = Mover::NextAttributeID, + SegmentTableAttributeID, + JointSubsystemAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex; + static AttributeIndexSet& GetAttributeIndex(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Segment Support +// +public: + + EntitySegment::SegmentTable + segmentTable; + + int + segmentCount; + + EntitySegment* + GetSegmentFromDamageZone(CString damage_zone); + + EntitySegment* + GetSegment(CString segment_name); + + EntitySegment* + GetSegment(int segment_index) + { + Check(this); + EntitySegment::SegmentTableIterator iterator(segmentTable); + return iterator.GetNth(segment_index); + } + + SlotOf + jointSubsystem; + + JointSubsystem* + GetJointSubsystem() + { + Check(this); return jointSubsystem.GetCurrent(); + } + + void + GetSegmentToWorld( + EntitySegment &my_segment, + LinearMatrix *transform + ); + + protected: + void + InitializeChildPointers(EntitySegment *current_segment); + + void + CalcSegmentTransforms(EntitySegment *final_segment); + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Animation Support +// +public: + +typedef + Scalar (JointedMover::*AnimationCallback)( + ResourceDescription::ResourceID animation_number, + Scalar carryover, + Logical animate_joints + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (JointedMover::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + + static JointedMover* + Make(MakeMessage *creation_message); + + static int + CreateDamageZoneStream ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static ResourceDescription::ResourceID + CreateSkeletonStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static Logical + InitDestroyedVideoObjectNames( + MemoryStream *segment_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ); + + + static Logical + InitVideoObjectNames( + MemoryStream *segment_stream, + NotationFile *model_file, + CString page_name, + const ResourceDirectories *directories + ); + static int + GetSegmentIndex( + CString segment_name, + NotationFile *skl_file + ); + + static int + GetDamageZoneIndex( + CString damage_zone_name, + NotationFile *skl_file + ); + + JointedMover( + MakeMessage *creation_message, + SharedData &virtual_data + ); + ~JointedMover(); + + Logical + TestInstance() const; +}; + +//########################################################################## +//########################## Animation ############################### +//########################################################################## + +class AnimationInstance: + public Plug +{ +private: + Logical lerpToZero; + Scalar deltaTime; +public: + AnimationInstance(JointedMover *jointed_mover); + ~AnimationInstance(); + + Scalar Animate(Scalar time_slice, Logical move_joints = True); + + Logical + LerpToPose(Scalar time_slice, Scalar time_to_lerp, Logical move_joints = True); + + Logical LerpToRest(Scalar time_slice, Scalar time_to_lerp, Logical move_joints = True); + + void SnapToRest(Logical move_joints = True); + + void + SetAnimation( + ResourceDescription::ResourceID animation_number, + JointedMover::AnimationCallback finished_callback + ); + + int + frameCount, + jointCount, + *jointIndices; + float + *footStepThreshold; + Scalar + *frameStart; + + void + *keyFrames; + + void + *currentFrameTo; + + Vector3D + *keyJointPos, + *rootTranslations; + + JointSubsystem + *jointSubToAnimate; + +protected: + int currentFrame; + JointedMover *moverToAnimate; + ResourceDescription *animationResource; + JointedMover::AnimationCallback finishedCallback; + Scalar currentTime; +}; diff --git a/MUNGA/JOINT.cpp b/MUNGA/JOINT.cpp new file mode 100644 index 0000000..d6df89d --- /dev/null +++ b/MUNGA/JOINT.cpp @@ -0,0 +1,513 @@ +#include "munga.h" +#pragma hdrstop + +#include "joint.h" +#include "jmover.h" + +//########################################################################## +//######################## BallTranslation ############################ +//########################################################################## + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile BallTranslation *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BallTranslation::BallTranslation() +{ + ballJoint = EulerAngles::Identity; + jointTranslation = Point3D::Identity; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BallTranslation::BallTranslation(const BallTranslation &new_ball) +{ + Check(&new_ball); + ballJoint = new_ball.ballJoint; + jointTranslation = new_ball.jointTranslation; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + BallTranslation::TestInstance() const +{ + return True; +} + +//########################################################################## +//########################## Joint ############################### +//########################################################################## + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Joint *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::Joint(JointSubsystem *subsystem) +{ + Check(subsystem); + + jointType = StaticJointType; + jointModified = True; + ballJoint = NULL; + jointSubsystem = subsystem; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::Joint( + JointSubsystem *subsystem, + JointType joint_type +) +{ + Check(subsystem); + + jointType = joint_type; + jointModified = True; + jointSubsystem = subsystem; + ballJoint = NULL; + + switch(joint_type) + { + case Joint::BallJointType: + ballJoint = new EulerAngles(EulerAngles::Identity); + Register_Object(ballJoint); + break; + + case Joint::BallTranslationJointType: + ballTranslationJoint = new BallTranslation; + Register_Object(ballTranslationJoint); + break; + + case Joint::HingeXJointType: + hingeJoint = new Hinge(X_Axis, 0.0f); + Register_Object(hingeJoint); + break; + + case Joint::HingeYJointType: + hingeJoint = new Hinge(Y_Axis, 0.0f); + Register_Object(hingeJoint); + break; + + case Joint::HingeZJointType: + hingeJoint = new Hinge(Z_Axis, 0.0f); + Register_Object(hingeJoint); + break; + + case Joint::StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::Joint(const Joint &new_joint) +{ + jointModified = True; + jointSubsystem = new_joint.jointSubsystem; + jointType = new_joint.jointType; + ballJoint = NULL; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a new joint of correct size + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + switch(new_joint.jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + hingeJoint = new Hinge(*new_joint.hingeJoint); + Register_Object(hingeJoint); + break; + + case BallJointType: + ballJoint = new EulerAngles(*new_joint.ballJoint); + Register_Object(ballJoint); + break; + + case BallTranslationJointType: + ballTranslationJoint = + new BallTranslation(*new_joint.ballTranslationJoint); + Register_Object(ballTranslationJoint); + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint& + Joint::operator=(const Joint &new_joint) +{ + Check(this); + + jointModified = True; + + // + //--------------------------------------------------- + // If not same kind of joint free up old joint memory + //--------------------------------------------------- + // + if(new_joint.jointType != jointType) + { + switch(jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + Unregister_Object(hingeJoint); + delete hingeJoint; + break; + + case BallJointType: + Unregister_Object(ballJoint); + delete ballJoint; + break; + + case BallTranslationJointType: + Unregister_Object(ballTranslationJoint); + delete ballTranslationJoint; + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } + jointType = new_joint.jointType; + + // + //----------------------------------- + // Create a new joint of correct size + //----------------------------------- + // + switch(new_joint.jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + hingeJoint = new Hinge(*new_joint.hingeJoint); + Register_Object(hingeJoint); + break; + + case BallJointType: + ballJoint = new EulerAngles(*new_joint.ballJoint); + Register_Object(ballJoint); + break; + + case BallTranslationJointType: + ballTranslationJoint = + new BallTranslation(*new_joint.ballTranslationJoint); + Register_Object(ballTranslationJoint); + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } + } + + // + //----------------------------------- + // Otherwise simply copy all the data + //----------------------------------- + // + else + { + switch(new_joint.jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + hingeJoint = new_joint.hingeJoint; + break; + + case BallJointType: + ballJoint = new_joint.ballJoint; + break; + + case BallTranslationJointType: + ballTranslationJoint = new_joint.ballTranslationJoint; + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } + } + return (*this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Joint::~Joint() +{ + switch(jointType) + { + case HingeXJointType: + case HingeYJointType: + case HingeZJointType: + Unregister_Object(hingeJoint); + delete hingeJoint; + break; + + case BallJointType: + Unregister_Object(ballJoint); + delete ballJoint; + break; + + case BallTranslationJointType: + Unregister_Object(ballTranslationJoint); + delete ballTranslationJoint; + break; + + case StaticJointType: + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Unsupported jointType!\n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const EulerAngles& + Joint::GetEulerAngles() +{ + Check(this); + switch(jointType) + { + case BallJointType: + return *ballJoint; + case BallTranslationJointType: + return ballTranslationJoint->GetEulerAngles(); +#if DEBUG_LEVEL>0 + default: + Fail("Joint must be a BallJoint of BallTranslationJoint \n"); + break; +#endif + } + return *ballJoint; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetHinge(const Hinge &new_hinge) +{ + Check(this); + if(*hingeJoint != new_hinge) + { + jointModified = True; + (*hingeJoint) = new_hinge; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetRotation(const EulerAngles &new_angles) +{ + Check(this); + + switch(jointType) + { + case BallJointType: + if ((*ballJoint) != new_angles) + { + (*ballJoint) = new_angles; +Joint_Modified: + jointModified = True; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } + break; + + case BallTranslationJointType: + if (ballTranslationJoint->GetEulerAngles() != new_angles) + { + ballTranslationJoint->SetEulerAngles(new_angles); + goto Joint_Modified; + } + break; + +#if DEBUG_LEVEL>0 + default: + Fail("Joint must be a Ball or Ball Translation Joint! \n"); + break; +#endif + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetRotation(const Radian &new_radian) +{ + Check(this); + + Verify ( + (jointType == HingeXJointType ) || + (jointType == HingeYJointType ) || + (jointType == HingeZJointType ) + ); + if(hingeJoint->rotationAmount != new_radian) + { + hingeJoint->rotationAmount = new_radian; + jointModified = True; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Joint::SetTranslation(const Point3D &new_trans) +{ + Check(this); + jointModified = True; + + Verify(jointType == BallTranslationJointType); + if (ballTranslationJoint->GetTranslation() != new_trans) + { + ballTranslationJoint->SetTranslation(new_trans); + jointModified = True; + Verify(jointSubsystem); + jointSubsystem->ModifyJoints(); + } +} + +//############################################################################# +// Shared Data Support +// +JointSubsystem::SharedData + JointSubsystem::DefaultData( + JointSubsystem::GetClassDerivations(), + JointSubsystem::GetMessageHandlers(), + JointSubsystem::GetAttributeIndex(), + JointSubsystem::StateCount + ); + +Derivation* JointSubsystem::GetClassDerivations() +{ + static Derivation classDerivations(Subsystem::GetClassDerivations(), "JointSubsystem"); + return &classDerivations; +} + +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + JointSubsystem::JointSubsystemSimulation(Scalar ) +{ + Check(this); + + + Joint *current_joint; + JointTableIterator iterator(jointTable); + + while ((current_joint = iterator.ReadAndNext() )!= NULL) + { + if (current_joint->IsJointModified()) + { + JointedMover *jointed_mover = Cast_Object( + JointedMover*, + GetEntity() + ); + jointed_mover->ForceSegmentTransformUpdate(); + break; + } + } + +} +#endif + +//############################################################################# +// Constructer/Destructor Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointSubsystem::JointSubsystem( + Entity *owner, + int subsystem_ID, + SharedData &shared_data +): + Subsystem( + owner, + subsystem_ID, + "Joint Subsystem", + JointSubsystemClassID, + shared_data + ), + jointTable(NULL, False) +{ + damageZone = new DamageZone(this, 0); + Register_Object(damageZone); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +JointSubsystem::~JointSubsystem() +{ + JointTableIterator iterator(jointTable); + iterator.DeletePlugs(); + Unregister_Object(damageZone); + delete damageZone; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + JointSubsystem::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/JOINT.h b/MUNGA/JOINT.h new file mode 100644 index 0000000..4a5e4c6 --- /dev/null +++ b/MUNGA/JOINT.h @@ -0,0 +1,271 @@ +#pragma once + +#include "subsystm.h" +#include "rotation.h" +#include "memstrm.h" + +//##################### Forward Class Declarations ########################## +class Entity; +class Joint; +class JointSubsystem; + +//########################################################################## +//######################## BallTranslation ############################ +//########################################################################## + +class BallTranslation +{ + friend class Joint; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile BallTranslation *); + #endif + +protected: + Point3D + jointTranslation; + EulerAngles + ballJoint; + + const EulerAngles& + GetEulerAngles() + {Check(this); return ballJoint;} + const Point3D& + GetTranslation() + {Check(this); return jointTranslation;} + + void + SetTranslation(const Point3D &new_trans) + {Check(this); jointTranslation = new_trans; } + void + SetEulerAngles(const EulerAngles &new_angles) + {Check(this); ballJoint = new_angles;} + + BallTranslation(); + BallTranslation(const BallTranslation &new_ball); + + Logical + TestInstance() const; + + BallTranslation& + operator=(const BallTranslation &new_ball) + { + ballJoint = new_ball.ballJoint; + jointTranslation = new_ball.jointTranslation; + return (*this); + } +}; + +//########################################################################## +//############################ Joint ################################# +//########################################################################## + +class Joint : + public Plug +{ + friend class BallTranslation; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Joint *); + #endif + +public: + enum JointType { + NULLJointType = -1, + HingeXJointType, + HingeYJointType, + HingeZJointType, + StaticJointType, + BallJointType, + BallTranslationJointType + }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructors +// +public: + Joint(JointSubsystem *subsystem); + Joint(const Joint &new_joint); + Joint( + JointSubsystem *subsystem, + JointType joint_type + ); + ~Joint(); + + Joint& + operator=(const Joint &new_joint); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Joint Data +// +protected: + union { + EulerAngles *ballJoint; + Hinge *hingeJoint; + BallTranslation *ballTranslationJoint; + }; + + JointType + jointType; + Logical + jointModified; + JointSubsystem + *jointSubsystem; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Reading Joints +// +public: + const Hinge& + GetHinge() + {Check(this); return *hingeJoint;} + + const EulerAngles& + GetEulerAngles(); + + const Point3D& + GetTranslation() + { + Check(this); + Verify(jointType == BallTranslationJointType); + return ballTranslationJoint->GetTranslation(); + } + + Radian + GetRadians() const + { + Check(this); + Verify ( + (jointType == HingeXJointType ) || + (jointType == HingeYJointType ) || + (jointType == HingeZJointType ) + ); + return hingeJoint->rotationAmount; + } + + JointType + GetJointType() const + {Check(this); return jointType; } + + Logical + IsJointModified() const + {Check(this); return jointModified;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Writing Joints +// +public: + void + SetHinge(const Hinge &new_hinge); + + void + SetRotation(const EulerAngles &new_angles); + + void + SetRotation(const Radian &new_radian); + + void + SetTranslation(const Point3D &new_trans); + + void + JointModified(Logical new_value=True) + {Check(this); jointModified = new_value;} +}; + +//############################################################################## +//####################### Class JointSubsystem ################################# +//############################################################################## + +class JointSubsystem : +public Subsystem +{ +friend Joint; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// + typedef void + (JointSubsystem::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// local Support +// +public: + + typedef TableOf + JointTable; + + typedef TableIteratorOf + JointTableIterator; + + Joint* + GetJoint(int joint_index) + { + Check(this); + JointTableIterator iterator(jointTable); + return iterator.GetNth(joint_index); } + + void + AddJoint( + int joint_index, + Joint *new_joint + ) + {Check(this); jointTable.AddValue(new_joint,joint_index);} + + int + GetJointCount() + { + Check(this); + JointTableIterator iterator(jointTable); + return iterator.GetSize(); + } + + Logical + AreJointsModified() + {Check(this); return jointsModified;} + void + ModifyJoints(Logical modified=True) + {Check(this); jointsModified=modified;} + +protected: + + JointTable + jointTable; + Logical + jointsModified; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction / Destruction Support +// + +public: + + JointSubsystem( + Entity *owner, + int subsystem_ID, + SharedData &shared_data = DefaultData + ); + ~JointSubsystem(); + + void + InitializeJoint(int joint_index, Joint::JointType joint_type); + + Logical + TestInstance() const; +}; diff --git a/MUNGA/LAMP.cpp b/MUNGA/LAMP.cpp new file mode 100644 index 0000000..c1a5256 --- /dev/null +++ b/MUNGA/LAMP.cpp @@ -0,0 +1,363 @@ +#include "munga.h" +#pragma hdrstop + +#include "lamp.h" + +//######################################################################### +//############################# LampManager ############################### +//######################################################################### +LampManager::LampManager(): + lampList(NULL), + activeLampList(NULL), + inactiveLampList(NULL) +{ + previousModeMask = (ModeMask) 0; + Check_Fpu(); +} + +LampManager::~LampManager() +{ + Check(this); + RemoveAllLamps(); + Check_Fpu(); +} + +Logical + LampManager::TestInstance() const +{ + return True; +} + +void + LampManager::Update(ModeMask current_mode_mask) +{ + Check(this); + //--------------------------------------------------------------- + // If the modeMask has changed, update the active/inactive lists. + //--------------------------------------------------------------- + if (previousModeMask != current_mode_mask) + { + previousModeMask = current_mode_mask; + + ActivateLamps(current_mode_mask); + DeactivateLamps(current_mode_mask); + } + //----------------------------------------------------------------- + // Process all active lamps + //----------------------------------------------------------------- + ChainIteratorOf + i(activeLampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + lamp_pointer->Update(); + } + Check_Fpu(); +} + +void + LampManager::ActivateLamps(ModeMask current_mode_mask) +{ + Check(this); + //----------------------------------------------------------- + // Test the lamps in the 'inactive' list. If any of them + // have bits in their modeMask corresponding to the + // new mode mask, move them to the 'active' list. + //----------------------------------------------------------- + ChainIteratorOf + i(inactiveLampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.GetCurrent()) != NULL) + { + Check(lamp_pointer); + //----------------------------------- + // Became active? + //----------------------------------- + if (lamp_pointer->modeMask & current_mode_mask) + { + //----------------------------------- + // Yes, move to 'active' list + //----------------------------------- + i.Remove(); + activeLampList.Add(lamp_pointer); + //----------------------------------- + // Cause lamp to update itself + //----------------------------------- + lamp_pointer->Update(True); // force notification of state change + } + else + { + //----------------------------------- + // No, try the next one + //----------------------------------- + i.Next(); + } + } + Check_Fpu(); +} + +void + LampManager::DeactivateLamps(ModeMask current_mode_mask) +{ + Check(this); + //--------------------------------------------------------------- + // Test the lamps in the 'active' list. If any of them do NOT + // have bits in their modeMask corresponding to the new mode + // mask, move them to the 'inactive' list. + //--------------------------------------------------------------- + ChainIteratorOf + i(activeLampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.GetCurrent()) != NULL) + { + Check(lamp_pointer); + //----------------------------------- + // Became inactive? + //----------------------------------- + if (!(lamp_pointer->modeMask & current_mode_mask)) + { + //----------------------------------- + // Yes, move to 'inactive' list + //----------------------------------- + i.Remove(); + inactiveLampList.Add(lamp_pointer); + } + else + { + //----------------------------------- + // No, try the next one + //----------------------------------- + i.Next(); + } + } + Check_Fpu(); +} + +Lamp* + LampManager::FindLamp(LampID lamp_id, ModeMask mode_mask) +{ + Check(this); + + //--------------------------------------------------------------- + // Search for lamp with both proper ID and modeMask + //--------------------------------------------------------------- + ChainIteratorOf + i(lampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + + if (lamp_pointer->lampID == lamp_id) + { + if (lamp_pointer->modeMask == mode_mask) + { + Check_Fpu(); + return lamp_pointer; + } + } + } + Check_Fpu(); + return NULL; +} + +void + LampManager::AddLamp(Lamp *new_lamp) +{ + Check(this); + // + // Don't call Check(new_lamp) here! + // The Lamp creator calls AddLamp before the lamp is fully built! + // + Check_Pointer(new_lamp); + + lampList.Add(new_lamp); + + if (new_lamp->modeMask & previousModeMask) + { + activeLampList.Add(new_lamp); + } + else + { + inactiveLampList.Add(new_lamp); + } + + Check_Fpu(); +} + +void + LampManager::RemoveLamp(LampID lamp_id, ModeMask mode_mask) +{ + Check(this); + Lamp + *lamp_pointer = FindLamp(lamp_id, mode_mask); + if (lamp_id != NULL) + { + Unregister_Object(lamp_pointer); + delete lamp_pointer; + } + + Check_Fpu(); +} + +void + LampManager::RemoveAllLamps() +{ + Check(this); + //------------------------------------------- + // Delete all lamps + //------------------------------------------- + ChainIteratorOf + i(lampList); + Lamp + *lamp_pointer; + + while ((lamp_pointer=i.ReadAndNext()) != NULL) + { + Check(lamp_pointer); + Unregister_Object(lamp_pointer); + delete lamp_pointer; + } + Check_Fpu(); +} + +//######################################################################### +//################################# Lamp ################################## +//######################################################################### +Lamp::Lamp( + LampID lamp_id, + ModeMask mode_mask, + LampManager *lamp_manager +): + Node(Gauge::GaugeClassID) +{ + Check(lamp_manager); + Verify(mode_mask != (ModeMask) 0); // if zero, it would NEVER execute + + lampID = lamp_id; + modeMask = mode_mask; + previousState = LampStateUndefined; + manager = lamp_manager; + alertActive = 0; + + manager->AddLamp(this); + Check_Fpu(); +} + +Lamp::~Lamp() +{ + Check(this); + Check_Fpu(); +} + +Logical + Lamp::TestInstance() const +{ + return True; +} + +void + Lamp::SetState(LampState new_state) +{ + Check(this); + + if (new_state != previousState) + { + previousState = new_state; + //--------------------------------------------- + // Update if mode is currently allowed + //--------------------------------------------- + Check(manager); + if (modeMask & manager->previousModeMask) + { + NotifyOfStateChange(); + } + } + Check_Fpu(); +} + +void + Lamp::SetAlertState(Logical alert_state) +{ + Check(this); + + if (alert_state) + { + ++alertActive; + } + else + { + --alertActive; + if (alertActive < 0) + { + alertActive = 0; + } + } + + //--------------------------------------------- + // Update if mode is currently allowed + //--------------------------------------------- + Check(manager); + if (modeMask & manager->GetPreviousModeMask()) + { + NotifyOfStateChange(); + } + Check_Fpu(); +} + +void + Lamp::Update(Logical /*force_notification*/) +{ + Fail("Lamp::Update method not overridden!"); +} + +void + Lamp::NotifyOfStateChange() +{ + Check(this); + Check_Fpu(); +} + +//######################################################################### +//############################## GraphicLamp ############################## +//######################################################################### +GraphicLamp::GraphicLamp( + LampID lamp_id, + ModeMask mode_mask, + LampManager *lamp_manager, + GaugeRenderer *the_renderer, + int graphics_port_number +): + Lamp(lamp_id, mode_mask, lamp_manager), + renderer(the_renderer), + localView( + the_renderer == NULL ? + NULL : + the_renderer->GetGraphicsPort(graphics_port_number) + ) +{ + Check_Fpu(); +} + +GraphicLamp::~GraphicLamp() +{ + Check(this); + Check_Fpu(); +} + +Logical + GraphicLamp::TestInstance() const +{ + Check(&localView); + Check_Fpu(); + return Lamp::TestInstance(); +} diff --git a/MUNGA/LAMP.h b/MUNGA/LAMP.h new file mode 100644 index 0000000..03b4134 --- /dev/null +++ b/MUNGA/LAMP.h @@ -0,0 +1,172 @@ +#pragma once + +#include "gaugrend.h" +#include "style.h" +#include "graph2d.h" +#include "mode.h" +#include "slot.h" +#include "chain.h" + +class LampManager; +class GraphicLamp; +typedef int LampID; +typedef int LampState; + +//######################################################################### +//################################# Lamp ################################## +//######################################################################### +class Lamp : public Node +{ + friend class LampManager; + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- +public: + enum + { + LampStateUndefined = -1, + LampStateOff = 0, + LampStateOn, + NextLampState + }; + + virtual ~Lamp(); + + Logical + TestInstance() const; + + virtual void + SetState(LampState new_state); + + void + SetAlertState(Logical alert_on = True); + + LampState + GetState() + { + Check(this); + return previousState; + } + +protected: + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- + Lamp( + LampID lamp_id, + ModeMask mode_mask, + LampManager *lamp_manager + ); + + virtual void + Update(Logical force_notify_of_state_change = False); + + virtual void + NotifyOfStateChange(); + // + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- + // + LampID + lampID; + ModeMask + modeMask; + LampState + previousState; + LampManager + *manager; + int + alertActive; +}; + +//######################################################################### +//############################## GraphicLamp ############################## +//######################################################################### +class GraphicLamp : + public Lamp +{ + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- +public: + ~GraphicLamp(); + + Logical + TestInstance() const; + + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- +protected: + GraphicLamp( + LampID lamp_id, + ModeMask mode_mask, + LampManager *lamp_manager, + GaugeRenderer *renderer, + int graphics_port_number + ); + //---------------------------------------------------------------------- + // Public data + //---------------------------------------------------------------------- + GaugeRenderer + *renderer; + GraphicsView + localView; +}; + +#include "gaugrend.h" // LampManager is a part of GaugeRenderer... + +//############################## LampManager ############################## +// The Lamp Manager belongs to the Gauge Renderer: it is responsible for +// handling specialized 'lamp' objects similar to (but not identical to) +// gauge objects. +//######################################################################### +class LampManager SIGNATURED +{ + friend class Lamp; + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- +public: + virtual ~LampManager(); + + Logical + TestInstance() const; + + virtual void + Update(ModeMask current_mode_mask); + Lamp * + FindLamp(LampID lamp_id, ModeMask mode_mask); + void + RemoveAllLamps(); + ModeMask + GetPreviousModeMask() + { + Check(this); + Check_Fpu(); + return previousModeMask; + } + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- +protected: + LampManager(); + + void + ActivateLamps(ModeMask bits_became_active); + void + DeactivateLamps(ModeMask bits_became_inactive); + void + AddLamp(Lamp *new_lamp); + void + RemoveLamp(LampID lamp_id, ModeMask mode_mask); + + ModeMask + previousModeMask; + + ChainOf + lampList, + activeLampList, + inactiveLampList; +}; diff --git a/MUNGA/LATTICE.cpp b/MUNGA/LATTICE.cpp new file mode 100644 index 0000000..752641c --- /dev/null +++ b/MUNGA/LATTICE.cpp @@ -0,0 +1,692 @@ +#include "munga.h" +#pragma hdrstop + +#include "boxsolid.h" +#include "collorgn.h" +#include "app.h" +#include "notation.h" + +//############################################################################# +//########################### LatticeZone ############################### +//############################################################################# + +LatticeZone::LatticeZone(const ExtentBox &extents): + boundingBox(extents, this) +{ +} + +LatticeZone::~LatticeZone() +{ +} + +//############################################################################# +//######################### EnvironmentZone ############################# +//############################################################################# + +EnvironmentZone::EnvironmentZone( + const ExtentBox &extents, + const Environment &the_environment +): + LatticeZone(extents) +{ + environment = the_environment; +} + +EnvironmentZone::~EnvironmentZone() +{ +} + +Logical + EnvironmentZone::TestInstance() const +{ + LatticeZone::TestInstance(); + Check(&environment); + return True; +} + +//############################################################################# +//########################### InterestZone ############################## +//############################################################################# + +InterestZone::InterestZone( + const ExtentBox &extents, + InterestZoneID interest_zone_id, + BoxedSolidTree *collision_root, + EnvironmentZone *environment_zone, + BoundingBoxTree *existance_root +): + LatticeZone(extents) +{ + Verify(interest_zone_id != NullInterestZoneID); + Check(collision_root); + Check(environment_zone); + Check(existance_root); + + interestZoneID = interest_zone_id; + collisionRoot = collision_root; + environmentZone = environment_zone; + collisionOrigin = NULL; + existanceRoot = existance_root; +} + +InterestZone::~InterestZone() +{ + // + // HACK - delete collision tree + // + Unregister_Object(collisionRoot); + delete collisionRoot; + collisionRoot = NULL; + + // + // HACK - delete environment zone + // + Unregister_Object(environmentZone); + delete environmentZone; + environmentZone = NULL; + + // + // HACK - delete existance tree + // + Unregister_Object(existanceRoot); + delete existanceRoot; + existanceRoot = NULL; + + // + // HACK - delete collision origin + // + if (collisionOrigin != NULL) + { + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->OrphanInterestOrigin(collisionOrigin); + CollisionOrigin *col_origin = collisionOrigin; + collisionOrigin = NULL; + Unregister_Object(col_origin); + delete col_origin; + } +} + +Logical + InterestZone::TestInstance() const +{ + LatticeZone::TestInstance(); + + Verify(interestZoneID != NullInterestZoneID); + + if (collisionOrigin != NULL) + { + Check(collisionOrigin); + } + if (collisionRoot != NULL) + { + Check(collisionRoot); + } + if (environmentZone != NULL) + { + Check(environmentZone); + } + if (existanceRoot != NULL) + { + Check(existanceRoot); + } + + return True; +} + +//############################################################################# +//########################### InterestArena ############################# +//############################################################################# + +InterestArena::InterestArena(InterestZone *interest_zone): + interestZoneSocket(NULL) +{ + Check(interest_zone); + Check(&interestZoneSocket); + interestZoneSocket.Add(interest_zone); +} + +InterestArena::~InterestArena() +{ + // + // deconnect from interest zone + // + Check(&interestZoneSocket); + #if DEBUG_LEVEL>0 + InterestZone *interest_zone = interestZoneSocket.GetCurrent(); + Check(interest_zone); + #endif + interestZoneSocket.Remove(); + + #if 0 + // + // If the interest zone is not in any interest arenas then delete + // + PlugIterator iterator(interest_zone); + Check(&iterator); + if (iterator.GetSize() == 0) + { + Unregister_Object(interest_zone); + delete interest_zone; + } + #endif +} + +Logical + InterestArena::TestInstance() const +{ + Node::TestInstance(); + Check(&interestZoneSocket); + return True; +} + +//############################################################################# +//########################### LatticeManager ############################ +//############################################################################# + +LatticeManager::LatticeManager() +{ +} + +LatticeManager::~LatticeManager() +{ +} + +//############################################################################# +//####################### InterestLatticeManager ######################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +InterestLatticeManager::InterestLatticeManager(): + interestZoneSocket(NULL) +{ +} + +// +//############################################################################# +//############################################################################# +// +InterestLatticeManager::~InterestLatticeManager() +{ + InterestZone *interest_zone; + + Check(&interestZoneSocket); + if ((interest_zone = interestZoneSocket.GetCurrent()) != NULL) + { + Unregister_Object(interest_zone); + delete interest_zone; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + InterestLatticeManager::TestInstance() const +{ + Node::TestInstance(); + Check(&interestZoneSocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +InterestArena* + InterestLatticeManager::MakeInterestArena( + InterestZoneID, + InterestType, + InterestDepth + ) +{ + Check(this); + + // + //--------------------------------------------------------------------- + // HACK - See if the one interest zone has been created + //--------------------------------------------------------------------- + // + InterestZone *interest_zone; + + if ((interest_zone = interestZoneSocket.GetCurrent()) == NULL) + { + // + //--------------------------------------------------------------------- + // Create the one environment + //--------------------------------------------------------------------- + // + EnvironmentZone *environment_zone; + + // + // Make the memory stream + // + Check(application); + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + + ResourceDescription *resource_description = + res_file->FindResourceDescription( + "EnvironmentZone", + ResourceDescription::EnvironmentZoneResourceType + ); + if (resource_description) + { + Check(resource_description); + resource_description->Lock(); + + MemoryStream + memory_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + + // + // Get the construction arguments + // + ExtentBox extent_box; + Environment environment; + + memory_stream >> extent_box >> environment; + + resource_description->Unlock(); + + // + // Make the environment zone + // + environment_zone = new EnvironmentZone(extent_box, environment); + Register_Object(environment_zone); + } + + // + //--------------------------------------------------------------------- + // Create the one interest zone + //--------------------------------------------------------------------- + // + resource_description = + res_file->FindResourceDescription( + "InterestZone", + ResourceDescription::InterestZoneResourceType + ); + if (resource_description) + { + Check(resource_description); + resource_description->Lock(); + + MemoryStream + memory_stream( + resource_description->resourceAddress, + resource_description->resourceSize + ); + + // + // Get the construction arguments + // + ExtentBox extent_box; + InterestZoneID interest_zone_ID; + CString map_resource_name; + + memory_stream >> extent_box >> interest_zone_ID >> map_resource_name; + + resource_description->Unlock(); + + // + // Make the collision tree root + // + BoxedSolidTree *collision_root = new BoxedSolidTree; + Register_Object(collision_root); + + // + // Make the existance tree root + // + BoundingBoxTree *existance_root = new BoundingBoxTree; + Register_Object(existance_root); + + // + // Make the interest zone + // + interest_zone = + new InterestZone( + extent_box, + interest_zone_ID, + collision_root, + environment_zone, + existance_root + ); + Register_Object(interest_zone); + } + + interestZoneSocket.Add(interest_zone); + Verify(interest_zone == interestZoneSocket.GetCurrent()); + } + Check(interest_zone); + + // + //--------------------------------------------------------------------- + // Create an interest arena pointing at this zone + //--------------------------------------------------------------------- + // + return new InterestArena(interest_zone); +} +#if 0 +InterestArena* + InterestLatticeManager::MakeInterestArena( + InterestZoneID, + InterestType, + InterestDepth + ) +{ + Check(this); + + // + //--------------------------------------------------------------------- + // HACK - Create one interest zone + //--------------------------------------------------------------------- + // + InterestZone *interest_zone; + + if ((interest_zone = interestZoneSocket.GetCurrent()) == NULL) + { + const Scalar min_dimension = -100000.0f; + const Scalar max_dimension = 100000.0f; + + Vector3D min_vector(min_dimension, min_dimension, min_dimension); + Vector3D max_vector(max_dimension, max_dimension, max_dimension); + ExtentBox big_extent(min_vector, max_vector); + + // + // Pick one interest zone id + // + InterestZoneID interest_zone_ID = NullInterestZoneID + 1; + + // + // Set up one environment + // + Environment environment; + EnvironmentZone *environment_zone; + + environment.gravityConstant = 6.5f; + environment.airDensity = 1.0f; + environment.windVelocity = Vector3D::Identity; + environment.ambientTemperature = 294.26f; // Seventy degrees farenheit + + environment_zone = new EnvironmentZone(big_extent, environment); + Register_Object(environment_zone); + + // + // Load entire collision tree + // + BoxedSolidTree *collision_root = new BoxedSolidTree; + Register_Object(collision_root); + + // + // Make one interest zone for everything + // + interest_zone = + new InterestZone( + big_extent, + interest_zone_ID, + collision_root, + environment_zone + ); + Register_Object(interest_zone); + + interestZoneSocket.Add(interest_zone); + Verify(interest_zone == interestZoneSocket.GetCurrent()); + } + Check(interest_zone); + + // + //--------------------------------------------------------------------- + // Create an interest arena pointing at this zone + //--------------------------------------------------------------------- + // + return new InterestArena(interest_zone); +} +#endif + +#if 0 +// +//############################################################################# +//############################################################################# +// +void + InterestLatticeManager::DestroyInterestArena(InterestArena *interest_arena) +{ + Check(this); + Check(interest_arena); + + // + //--------------------------------------------------------------------- + // Delete the interest arena + //--------------------------------------------------------------------- + // + Unregister_Object(interest_arena); + delete interest_arena; +} +#endif + +// +//############################################################################# +//############################################################################# +// +InterestZoneID + InterestLatticeManager::SearchForEntityInterestZone( + InterestZoneID, + const EntityID& + ) +{ + Check(this); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetInterestZoneID(); +} + +// +//############################################################################# +//############################################################################# +// +InterestZone* + InterestLatticeManager::GetInterestZone(InterestZoneID) +{ + Check(this); + return interestZoneSocket.GetCurrent(); +} + +// +//############################################################################# +//############################################################################# +// +void + InterestLatticeManager::CreateZoneResources( + ResourceFile *resource_file, + NotationFile *zone_notation_file + ) +{ + Check(zone_notation_file); + + // + //--------------------------------------------------------------------- + // HACK - Create the one environment zone resource + //--------------------------------------------------------------------- + // + { + // + // Environment zone construction arguments + // + ExtentBox extent_box; + Environment environment; + + // + // Get environment zone construction arguments + // + const char *contents; + + #if DEBUG_LEVEL>0 + int ret = zone_notation_file->GetEntry( + "EnvironmentZone", + "extent_box", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "EnvironmentZone", + "extent_box", + &contents + ); + #endif + Convert_From_Ascii(contents, &extent_box); + + #if DEBUG_LEVEL>0 + ret = zone_notation_file->GetEntry( + "EnvironmentZone", + "environment", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "EnvironmentZone", + "environment", + &contents + ); + #endif + Convert_From_Ascii(contents, &environment); + + // + // Create environment zone memory stream + // + DynamicMemoryStream environment_zone_memory_stream; + + environment_zone_memory_stream << extent_box << environment; + + // + // Add environment zone resource + // + CString environment_zone_resource_name("EnvironmentZone"); + + #if DEBUG_LEVEL>0 + ResourceDescription *res_description = + resource_file->AddResourceMemoryStream( + environment_zone_resource_name, + ResourceDescription::EnvironmentZoneResourceType, + 1, + ResourceDescription::Preload, + &environment_zone_memory_stream + ); + Check(res_description); + #else + resource_file->AddResourceMemoryStream( + environment_zone_resource_name, + ResourceDescription::EnvironmentZoneResourceType, + 1, + ResourceDescription::Preload, + &environment_zone_memory_stream + ); + #endif + } + + // + //--------------------------------------------------------------------- + // HACK - Create the one interest zone resource + //--------------------------------------------------------------------- + // + { + // + // Interest zone construction arguments + // + ExtentBox extent_box; + InterestZoneID interest_zone_ID; + CString map_resource_name; + + // + // Get interest zone construction arguments + // + const char *contents; + + #if DEBUG_LEVEL>0 + int ret = zone_notation_file->GetEntry( + "InterestZone", + "extent_box", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "InterestZone", + "extent_box", + &contents + ); + #endif + Convert_From_Ascii(contents, &extent_box); + + #if DEBUG_LEVEL>0 + ret = zone_notation_file->GetEntry( + "InterestZone", + "interest_zone_ID", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "InterestZone", + "interest_zone_ID", + &contents + ); + #endif + Convert_From_Ascii(contents, &interest_zone_ID); + + #if DEBUG_LEVEL>0 + ret = zone_notation_file->GetEntry( + "InterestZone", + "map_resource_name", + &contents + ); + Verify(ret); + #else + zone_notation_file->GetEntry( + "InterestZone", + "map_resource_name", + &contents + ); + #endif + map_resource_name = contents; + + // + // Create interest zone memory stream + // + DynamicMemoryStream interest_zone_memory_stream; + + interest_zone_memory_stream << extent_box << interest_zone_ID; + interest_zone_memory_stream << map_resource_name; + + // + // Add interest zone resource + // + CString interest_zone_resource_name("InterestZone"); + + #if DEBUG_LEVEL>0 + ResourceDescription *res_description = + resource_file->AddResourceMemoryStream( + interest_zone_resource_name, + ResourceDescription::InterestZoneResourceType, + 1, + ResourceDescription::Preload, + &interest_zone_memory_stream + ); + Check(res_description); + #else + resource_file->AddResourceMemoryStream( + interest_zone_resource_name, + ResourceDescription::InterestZoneResourceType, + 1, + ResourceDescription::Preload, + &interest_zone_memory_stream + ); + #endif + } +} diff --git a/MUNGA/LATTICE.h b/MUNGA/LATTICE.h new file mode 100644 index 0000000..de4bc03 --- /dev/null +++ b/MUNGA/LATTICE.h @@ -0,0 +1,480 @@ +#pragma once + +#include "node.h" +#include "bndgbox.h" +#include "envirnmt.h" +#include "network.h" +#include "slot.h" + +class BoundingBoxTree; + +//########################################################################## +//######## Support types for InterestOrigin & InterestManager ######## +//########################################################################## + +enum InterestType +{ + VisualInterestType, + AudioInterestType, + GaugeInterestType, + CollisionInterestType +}; + +typedef int InterestDepth; + +const InterestDepth DefaultInterestDepth = 1; + +enum InterestPriority +{ + LowInterestPriority = 0, + HighInterestPriority +}; + +//########################################################################## +//########################### LatticeZone ############################ +//########################################################################## + +class ExtentBox; + +// +// HACK - Lattice zones support being connected to each in variously +// interesting ways. For now there is only one. +// + +class LatticeZone: +public Plug +{ +public: +LatticeZone(const ExtentBox &extents); + ~LatticeZone(); + +private: +TaggedBoundingBoxOf + boundingBox; +}; + +//########################################################################## +//######################### EnvironmentZone ########################## +//########################################################################## + +class EnvironmentZone: +public LatticeZone +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor, Destructor, and Testing +// +public: +EnvironmentZone( + const ExtentBox &extents, + const Environment &environment + ); + ~EnvironmentZone(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HACK - Accessors +// +public: + Environment* + GetEnvironment() + {return &environment;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + Environment + environment; +}; + +//########################################################################## +//########################### InterestZone ########################### +//########################################################################## + +class BoxedSolidTree; +class CollisionOrigin; + +// +// HACK - Right now the interest zone holds data that would normally +// be within its own zone, i.e., environment zones, collision zones, +// audio zones, etc..., The interest zone should hold sockets to +// zones which are included in its interesting "domain" +// + +class InterestZone: +public LatticeZone +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor, Destructor, and Testing +// +public: +InterestZone( + const ExtentBox &extents, + InterestZoneID interest_zone_id, + BoxedSolidTree *collision_root, + EnvironmentZone *environment_zone, + BoundingBoxTree *existance_root + ); + ~InterestZone(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HACK - Accessors +// +public: + InterestZoneID + GetInterestZoneID(); + BoxedSolidTree* + GetCollisionRoot(); + Environment* + GetEnvironment(); + BoundingBoxTree* + GetExistanceRoot(); + + void + AdoptCollisionOrigin(CollisionOrigin *collision_origin); + CollisionOrigin* + GetCollisionOrigin(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + InterestZoneID + interestZoneID; + BoxedSolidTree + *collisionRoot; + EnvironmentZone + *environmentZone; + CollisionOrigin + *collisionOrigin; + BoundingBoxTree + *existanceRoot; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ InterestZone inlines ~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline InterestZoneID + InterestZone::GetInterestZoneID() +{ + Check(this); + return interestZoneID; +} + +inline BoxedSolidTree* + InterestZone::GetCollisionRoot() +{ +Check(this); + return collisionRoot; +} + +inline Environment* + InterestZone::GetEnvironment() +{ + Check(this); + Check(environmentZone); + return environmentZone->GetEnvironment(); +} + +inline BoundingBoxTree* + InterestZone::GetExistanceRoot() +{ + Check(this); + return existanceRoot; +} + +inline void + InterestZone::AdoptCollisionOrigin(CollisionOrigin *collision_origin) +{ + Check(this); + Verify(collisionOrigin == NULL); + Check_Pointer(collision_origin); + collisionOrigin = collision_origin; +} + +inline CollisionOrigin* + InterestZone::GetCollisionOrigin() +{ +Check(this); + return collisionOrigin; +} + +//########################################################################## +//########################### InterestArena ########################## +//########################################################################## + +// +// HACK - The interest arena maintains sets of interest zones. Since +// we only have one interest zone at present the interest arena has +// only the capability to reference one interest zone +// + +class InterestArena: +public Node +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor, Destructor, and Testing +// +public: + InterestArena(InterestZone *interest_zone); + ~InterestArena(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HACK - Accessors +// +public: + InterestZoneID + GetInterestZoneID(); + BoxedSolidTree* + GetCollisionRoot(); + Environment* + GetEnvironment(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest Zone and Entity support +// +public: + // + //-------------------------------------------------------------- + // Boolean IncludesInterestZone(InterestArena, InterestZoneID) + // + // Description: + // Does the interest arena include the interest zone? + // + // Parameters: + // InterestArena - reference to the interest arena. + // InterestZoneID - id of the interest zone. + // + // Returns: + // True if it does, otherwise False + //-------------------------------------------------------------- + // + + // + //-------------------------------------------------------------- + // Boolean IncludesPosition(InterestArena, 3DPosition) + // + // Description: + // Does the interest arena include the spatial position? + // + // Parameters: + // InterestArena - reference to the interest arena. + // 3DPosition- the spatial position. + // + // Returns: + // True if it does, otherwise False + //-------------------------------------------------------------- + // + + // + //-------------------------------------------------------------- + // ArenaEntityList GetArenaList(InterestArena) + // + // Description: + // Returns a list of resident entities and associated attributes + // based on interest zone connectivity. The actual return will + // probably by a safe iterator, meaning that it is resilient to + // changes in the underlying data structures. + // + // Parameters: + // Reference to the interest arena. + // + // Return: + // ArenaEntityList - a list of resident entities and extracted + // data from interest zone connectivity. + //-------------------------------------------------------------- + // + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: +SlotOf + interestZoneSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ InterestArena inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + +inline InterestZoneID + InterestArena::GetInterestZoneID() +{ + Check(&interestZoneSocket); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetInterestZoneID(); +} + +inline BoxedSolidTree* + InterestArena::GetCollisionRoot() +{ + Check(&interestZoneSocket); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetCollisionRoot(); +} + +inline Environment* + InterestArena::GetEnvironment() +{ + Check(&interestZoneSocket); + Check(interestZoneSocket.GetCurrent()); + return interestZoneSocket.GetCurrent()->GetEnvironment(); +} + +//########################################################################## +//########################### LatticeManager ######################### +//########################################################################## + +// +// HACK - The lattice manager managers connected lattices of zones +// of a particular type +// + +class LatticeManager: +public Node +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor, Destructor, and Testing +// +public: +LatticeManager(); + ~LatticeManager(); +}; + +//########################################################################## +//####################### InterestLatticeManager ##################### +//########################################################################## + +class EntityID; +class ResourceFile; + +// +// HACK - the interest lattice manager manages the lattice of interest +// zones. Right now, is stubbed out for one interest zone. +// + +class InterestLatticeManager: + public LatticeManager +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor, Destructor, and Testing +// +public: + InterestLatticeManager(); + ~InterestLatticeManager(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest arena and entity support +// +public: + // + //-------------------------------------------------------------- + // InterestArena + // MakeInterestArena(OriginInterestZoneID, Type, DepthCalibration) + // + // Description: + // Establishes an interest arena the locus of which is an interest + // zone, The arena is established with a type and depth + // specification (see interest manager). + // + // Parameters: + // OriginInterestZoneID- id of the interest zone. + // Type - a type of interest. + // DepthCalibration - a specification of the "depth" or "cost" associated + // with extent of the arena. + // + // Return: + // InterestArena - a reference to the created interest arena. + //-------------------------------------------------------------- + // + InterestArena* + MakeInterestArena( + InterestZoneID, + InterestType, + InterestDepth + ); + + #if 0 + // + //-------------------------------------------------------------- + // DestroyInterestArena(InterestArena) + // + // Description: + // Destroys the interest arena. + // + // Parameters: + // InterestArena - Reference to the interest arena. + // UpdateInterestArena(InterestArena, DepthCalibration) + // + // Description: + // Updates the interest arenas internal data structures. This method + // is called by the interest manager. + // + // Parameters: + // InterestArena - Reference to the interest arena. + // DepthCalibration - new depth of arena extent. + //-------------------------------------------------------------- + // + void + DestroyInterestArena(InterestArena*); + #endif + + // + //-------------------------------------------------------------- + // InterestZoneID + // SearchForEntityInterestZone(OriginInterestZoneID, EntityID) + // + // Description: + // If an entity has changed interest zones (its current location + // is not within the bounding volume of it interest zone) then + // this method searches prior adjacent interest zones for the entity. + // + // Parameters: + // OriginInterestZoneID - id of the interest zone to begin the + // search from. + // EntityID - id of the entity. + // + // Return: + // A reference to the interest zone if found, otherwise NULL. + //-------------------------------------------------------------- + // + InterestZoneID + SearchForEntityInterestZone( + InterestZoneID old_interest_zone_ID, + const EntityID &entityID + ); + + // + //-------------------------------------------------------------- + // InterestZoneID + //-------------------------------------------------------------- + // + InterestZone* + GetInterestZone(InterestZoneID interest_zone_ID); + + // + //-------------------------------------------------------------- + // HACK ****************** + //-------------------------------------------------------------- + // + static void + CreateZoneResources( + ResourceFile *resource_file, + NotationFile *zone_notation_file + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: +SlotOf + interestZoneSocket; +}; diff --git a/MUNGA/LINE.cpp b/MUNGA/LINE.cpp new file mode 100644 index 0000000..59b5bb4 --- /dev/null +++ b/MUNGA/LINE.cpp @@ -0,0 +1,72 @@ +#include "munga.h" +#pragma hdrstop + +#include "line.h" +#include "plane.h" + +// +//########################################################################### +//########################################################################### +// +Line& + Line::operator=(const Vector3D &vector) +{ + Check_Pointer(this); + Check(&vector); +// +// Make sure length of vector is non-zero +// + length = vector.Length(); + Verify(length); +// +// Normalize the vector and put it into the line +// + direction.x = vector.x/length; + direction.y = vector.y/length; + direction.z = vector.z/length; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Line& + Line::operator=(const Point3D &point) +{ + Check_Pointer(this); + Check(&point); +// +// Copy the point over into the line. +// + origin.x = point.x; + origin.y = point.y; + origin.z = point.z; + return *this; +} + +Scalar + Line::DistanceTo( + const Plane &plane, + Scalar *product + ) const +{ + *product = direction * plane.normal; + if (Small_Enough(*product)) + { + Check_Fpu(); + return -1.0f; + } + Scalar result = -plane.DistanceTo(origin) / *product; + Check_Fpu(); + return result; +} + +Scalar + Line::DistanceTo( + const Sphere &,//sphere, + Scalar *//penetration + ) const +{ + return -1.0f; // HACK +} diff --git a/MUNGA/LINE.h b/MUNGA/LINE.h new file mode 100644 index 0000000..d5115e7 --- /dev/null +++ b/MUNGA/LINE.h @@ -0,0 +1,33 @@ +#pragma once + +#include "ray.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Line3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Line : public Ray +{ +public: + Scalar length; + + Line() {} + Line(const Ray &ray, Scalar length) : Ray(ray), length(length) {} + Line(const Point3D &start, const UnitVector &direction, Scalar length) : Ray(start,direction), length(length) {} + + void FindEnd(Point3D *result) + { + Check(this); + Check_Pointer(result); + Ray::Project(length, result); + } + + // + // Assignment operators + // + Line& operator=(const Vector3D &vector); + Line& operator=(const Point3D &point); + // + // Ray intersection functions + // + Scalar DistanceTo(const Plane &plane, Scalar *product) const; + Scalar DistanceTo(const Sphere &sphere, Scalar *penetration) const; +}; diff --git a/MUNGA/LINK.cpp b/MUNGA/LINK.cpp new file mode 100644 index 0000000..426753b --- /dev/null +++ b/MUNGA/LINK.cpp @@ -0,0 +1,89 @@ +#include "munga.h" +#pragma hdrstop + +#include "link.h" +#include "plug.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Link ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Link +//############################################################################# +// +Link::Link(Socket *socket, Plug *plug) +{ + this->socket = socket; + this->plug = plug; + + // Add this new link to the plugs current set of links + AddToPlug(plug); +} + +// +//############################################################################# +// ~Link +//############################################################################# +// +Link::~Link() +{ + // Remove this link from the plugs current set of links + ReleaseFromPlug(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical Link::TestInstance() const +{ + Check_Signature(socket); + Check_Signature(plug); + return True; +} + +// +//############################################################################# +// ReleaseFromPlug +//############################################################################# +// +void Link::ReleaseFromPlug() +{ + // + //----------------------------------------------------- + // Remove this link from the plugs current set of links + //----------------------------------------------------- + // + Check(plug); + if (plug->linkHead == this) + plug->linkHead = nextLink; + if (prevLink != NULL) + { + Check(prevLink); + prevLink->nextLink = nextLink; + } + if (nextLink != NULL) + { + Check(nextLink); + nextLink->prevLink = prevLink; + } + prevLink = nextLink = NULL; +} + +// +//############################################################################# +// AddToPlug +//############################################################################# +// +void Link::AddToPlug(Plug *plug) +{ + Check(plug); + if ((nextLink = plug->linkHead) != NULL) + { + Check(nextLink); + nextLink->prevLink = this; + } + this->prevLink = NULL; + plug->linkHead = this; +} diff --git a/MUNGA/LINK.h b/MUNGA/LINK.h new file mode 100644 index 0000000..d9fd15e --- /dev/null +++ b/MUNGA/LINK.h @@ -0,0 +1,34 @@ +#pragma once + +#include "style.h" + +class Socket; +class Plug; +class PlugIterator; +class Node; + +class Link SIGNATURED +{ + friend class PlugIterator; + +public: + virtual ~Link(); + Logical TestInstance() const; + + Socket *GetSocket() { return socket; } + Plug *GetPlug() { return plug; } + +protected: + Link(Socket *socket, Plug *plug); + + void ReleaseFromPlug(); + + Socket *socket; + Plug *plug; + +private: + void AddToPlug(Plug *plug); + + Link *nextLink; + Link *prevLink; +}; \ No newline at end of file diff --git a/MUNGA/LINMTRX.cpp b/MUNGA/LINMTRX.cpp new file mode 100644 index 0000000..ec9248f --- /dev/null +++ b/MUNGA/LINMTRX.cpp @@ -0,0 +1,138 @@ +#include "munga.h" +#pragma hdrstop + +#include "linmtrx.h" +#include "matrix.h" +#include "linmtrx.h" + +const LinearMatrix LinearMatrix::Identity(true); + +LinearMatrix& + LinearMatrix::operator=(const AffineMatrix &m) +{ + // + // Make sure to test linearness on m + // + AffineMatrix::operator=(m); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::operator=(const Matrix4x4 &m) +{ + // + // Make sure to test linearness on m + // + AffineMatrix::operator=(m); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::operator=(const TransposedMatrix &m) +{ + // + // Make sure to test linearness on m + // + AffineMatrix::operator=(m); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::Invert(const LinearMatrix& Source) +{ + + // + //----------------------------------------- + // First, transpose the 3x3 rotation matrix + //----------------------------------------- + // + (*this)(0,0) = Source(0,0); + (*this)(0,1) = Source(1,0); + (*this)(0,2) = Source(2,0); + (*this)(1,0) = Source(0,1); + (*this)(1,1) = Source(1,1); + (*this)(1,2) = Source(2,1); + (*this)(2,0) = Source(0,2); + (*this)(2,1) = Source(1,2); + (*this)(2,2) = Source(2,2); + + // + //---------------------------- + // Now run the offsets through + //---------------------------- + // + (*this)(3,0) = + -Source(3,0)*Source(0,0) + -Source(3,1)*Source(0,1) + -Source(3,2)*Source(0,2); + (*this)(3,1) = + -Source(3,0)*Source(1,0) + -Source(3,1)*Source(1,1) + -Source(3,2)*Source(1,2); + (*this)(3,2) = + -Source(3,0)*Source(2,0) + -Source(3,1)*Source(2,1) + -Source(3,2)*Source(2,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LinearMatrix& + LinearMatrix::Normalize() +{ + (*this)(0,2) = (*this)(1,0)*(*this)(2,1) - (*this)(1,1)*(*this)(2,0); + (*this)(1,2) = (*this)(2,0)*(*this)(0,1) - (*this)(2,1)*(*this)(0,0); + (*this)(2,2) = (*this)(0,0)*(*this)(1,1) - (*this)(0,1)*(*this)(1,0); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + LinearMatrix::TestInstance() const +{ + UnitVector v1; + GetFromAxis(X_Axis,&v1); + if (!v1.TestInstance()) + { + Dump(*this); + Dump(v1); + return False; + } + + UnitVector v2; + GetFromAxis(Y_Axis,&v2); + if (!v2.TestInstance()) + { + Dump(*this); + Dump(v1); + return False; + } + + UnitVector v3; + v3.Vector3D::Cross(v1,v2); + GetFromAxis(Z_Axis,&v1); + return Close_Enough(v1,v3); +} + +#if defined(TEST_CLASS) + #include "linmtrx.tcp" +#endif + diff --git a/MUNGA/LINMTRX.h b/MUNGA/LINMTRX.h new file mode 100644 index 0000000..709b0ae --- /dev/null +++ b/MUNGA/LINMTRX.h @@ -0,0 +1,119 @@ +#pragma once + +#include "affnmtrx.h" +#include "unitvec.h" +#include "rotation.h" + +class LinearMatrix : public AffineMatrix +{ +public: + static const LinearMatrix Identity; + + LinearMatrix() { BuildIdentity(); } + LinearMatrix(int) { BuildIdentity(); } + + LinearMatrix& operator=(const LinearMatrix &m) { AffineMatrix::operator=(m); return *this; } + LinearMatrix& operator=(const Origin &p) { AffineMatrix::operator=(p); return *this; } + LinearMatrix& operator=(const Hinge &hinge) { AffineMatrix::operator=(hinge); return *this; } + LinearMatrix& operator=(const EulerAngles &angles) { AffineMatrix::operator=(angles); return *this; } + LinearMatrix& operator=(const YawPitchRoll &angles) { AffineMatrix::operator=(angles); return *this; } + LinearMatrix& operator=(const Quaternion &q) { AffineMatrix::operator=(q); return *this; } + LinearMatrix& operator=(const Point3D &p) { AffineMatrix::operator=(p); return *this; } + LinearMatrix& operator=(const AffineMatrix &m); + LinearMatrix& operator=(const Matrix4x4 &m); + LinearMatrix& operator=(const TransposedMatrix &m); + + void GetFromAxis(size_t index, UnitVector *v) const { AffineMatrix::GetFromAxis(index, v); } + void GetToAxis(size_t index, UnitVector *v) const { AffineMatrix::GetToAxis(index, v); } + + LinearMatrix& SetFromAxis(size_t index, const UnitVector &v) + { + AffineMatrix::SetFromAxis(index, v); + return *this; + } + LinearMatrix& SetToAxis(size_t index, const UnitVector &v) + { + AffineMatrix::SetToAxis(index, v); + return *this; + } + + LinearMatrix& Multiply(const LinearMatrix& m1, const LinearMatrix& m2) + { + AffineMatrix::Multiply(m1, m2); + return *this; + } + LinearMatrix& operator*=(const LinearMatrix& M) + { + LinearMatrix src(*this); + return Multiply(src, M); + } + + LinearMatrix& Invert(const LinearMatrix& Source); + LinearMatrix& Invert() + { + LinearMatrix src(*this); + return Invert(src); + } + + LinearMatrix& Multiply(const LinearMatrix &m, const Quaternion &q) + { + Check_Pointer(this); + Check(&m); + Check(&q); + AffineMatrix::Multiply(m, q); + return *this; + } + LinearMatrix& operator*=(const Quaternion &q) + { + Check(this); + LinearMatrix m(*this); + return Multiply(m, q); + } + LinearMatrix& Multiply(const LinearMatrix &m, const Point3D &p) + { + Check_Pointer(this); + Check(&m); + Check(&p); + AffineMatrix::Multiply(m, p); + return *this; + } + LinearMatrix& operator*=(const Point3D& p) + { + Check(this); + LinearMatrix m(*this); + return Multiply(m, p); + } + + LinearMatrix& Normalize(); + + Logical TestInstance() const; + static Logical TestClass(); + +private: + LinearMatrix& Solve(); +}; + +inline UnitVector& UnitVector::Multiply(const UnitVector &v, const LinearMatrix &m) +{ + Check(&v); + Vector3D::Multiply(v, m); + return *this; +} + +inline UnitVector& UnitVector::operator *=(const LinearMatrix &m) +{ + UnitVector src(*this); + return Multiply(src, m); +} + +inline Quaternion& Quaternion::Multiply(const Quaternion &q, const LinearMatrix &m) +{ + Cast_Object(Vector3D*, this)->Multiply(SKIPPY_CAST(Vector3D, q), m); + return *this; +} + +inline Quaternion& Quaternion::operator *=(const LinearMatrix &m) +{ + Quaternion t(*this); + return Multiply(t, m); +} \ No newline at end of file diff --git a/MUNGA/MAPTOOL.cpp b/MUNGA/MAPTOOL.cpp new file mode 100644 index 0000000..f495c95 --- /dev/null +++ b/MUNGA/MAPTOOL.cpp @@ -0,0 +1,987 @@ +#include "munga.h" +#pragma hdrstop + +#include "tool.h" +#include "fileutil.h" +#include "eyecandy.h" +#include "dropzone.h" +#include "terrain.h" +#include "cultural.h" +#include "doorfram.h" +#include "camship.h" +#include "boxsolid.h" +#include "team.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ApplicationTool::CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(class_name,"TerrainClassID")) + { + Terrain::CreateMakeMessage( + (Terrain::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name,"UnscalableTerrainClassID")) + { + UnscalableTerrain::CreateMakeMessage( + (UnscalableTerrain::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name,"CulturalIconClassID")) + { + CulturalIcon::CreateMakeMessage( + (CulturalIcon::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name,"LandmarkClassID")) + { + Landmark::CreateMakeMessage( + (Landmark::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name,"DoorFrameClassID")) + { + DoorFrame::CreateMakeMessage( + (DoorFrame::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name,"EyeCandyClassID")) + { + EyeCandy::CreateMakeMessage( + (EyeCandy::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name, "TeamClassID")) + { + Team::CreateMakeMessage( + (Team::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + + // + //----------------------------------------------- + // Not a class MUNGA knows about, so return False + //----------------------------------------------- + // + return False; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ApplicationTool::WriteMaps( + char *map_name, + NotationFile *notation_file, + NotationFile *ops_file, + StreamableResourceFile *file, + const ResourceDirectories *resource_directories, + int resource_id + ) +{ + const char + *entry_data, *type, *ops_name; + char *p; + char + short_map_name[15], + ops_file_page[100], + ops_file_data[100], + temp[100]; + + + Str_Copy(short_map_name, map_name, 15); + p = short_map_name; + p += strlen(short_map_name) - 4; + *p = '\0'; + + + + + //---------------------- + // Write ops_file stuff + //---------------------- + + ops_file->GetEntry("resource", "res name", &ops_name); + + strcpy(ops_file_data, ops_name); + strcat(ops_file_data, "::Standard::Location::"); + strcat(ops_file_data, short_map_name ); + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::Standard::LocationList"); + + ops_file->AppendEntry(ops_file_page, "location", ops_file_data); + ops_file->SetEntry(ops_file_data, "tag", short_map_name ); + ops_file->AppendEntry(ops_file_data, NULL, (char *)NULL); + + + // + //----------------------------------------------- + // Get exsitance box stream from notation file + // named after map then save it to the resource + // Not required yet! + //----------------------------------------------- + // + + + + + strcpy(temp, short_map_name); + strcat(temp, ".xst"); + + char *filename = MakePathedFilename( + resource_directories->collisionDirectory, + temp); + Register_Pointer(filename); + + NotationFile *exist_notation_file = new NotationFile(filename); + Register_Object(exist_notation_file); + + Unregister_Pointer(filename); + delete filename; + + labOnly |= exist_notation_file->IsMarkedLabOnly(); + + if (exist_notation_file->PageCount()) + { + + + + int size; + ExtentBox *existance_box = MakeExistanceBoxStream(exist_notation_file, &size); + Register_Pointer(existance_box); + + file->AddResource( + short_map_name, + ResourceDescription::ExistanceBoxStreamResourceType, + 1, + ResourceDescription::Preload, + existance_box, + size * sizeof(ExtentBox) + ); + + Unregister_Pointer(existance_box); + delete[] existance_box; + } + + Unregister_Object(exist_notation_file); + delete exist_notation_file; + + + + //--------------------- + // Make camera stream + //--------------------- + + CameraInstanceManager::CreateCameraInstancesStream( + file, + map_name, + resource_directories + ); + + // + //-------------------------------------------------------- + // Get the name and types of all the pages in the map file + //-------------------------------------------------------- + // + + NameList *namelist = notation_file->MakePageList(); + Register_Object(namelist); + NameList::Entry *entry = namelist->GetFirstEntry(); + + + Logical model_failed = False; + + char model_name[100]; + while (entry) + { + entry_data = entry->GetName(); + + + if (!stricmp(entry_data, "LAB_ONLY")) + { + labOnly = True; + entry = entry->GetNextEntry(); + continue; + } + + else if(!notation_file->GetEntry(entry_data, "type", &type)) + { + std::cout << "No Type in " << entry_data << std::endl; + + Unregister_Object(namelist); + delete namelist; + + return False; + + + } + + // + //---------------------------- + // Read in a model description + //---------------------------- + // + char scenario_name[100]; + + if (!stricmp(type, "model")) + { + strcpy(model_name, entry_data); + + if( + !notation_file->GetEntry( + model_name, + "modelfile", + &entry_data + ) + ) + { + std::cout << "No modelfile in " << model_name << std::endl; + Unregister_Object(namelist); + delete namelist; + + return False; + } + + ResourceDescription *res = file->FindResourceDescription( + model_name, + ResourceDescription::ModelListResourceType + ); + if (!res) + { + char *filename = + MakePathedFilename( + resource_directories->modelDirectory, + entry_data + ); + Register_Pointer(filename); + + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + if (new_notation_file->PageCount()) + { + if ( + !WriteModels( + new_notation_file, + ops_file, + file, + model_name, + resource_directories + ) + ) + { + std::cout << "Model Failed : " << filename << std::endl; + model_failed = True; + } + } + else + { + std::cout << "Model File : " << filename << " does not exist!\n"; + model_failed = True; + } + + Unregister_Pointer(filename); + delete filename; + Unregister_Object(new_notation_file); + delete new_notation_file; + } + } + + else if (!stricmp(type, "dropzone")) + { +#if 0 + strcpy(model_name, entry_data); + ResourceDescription *res = + file->FindResourceDescription( + model_name, + ResourceDescription::ModelListResourceType + ); + if (!res) + { + // + // make drop zone name be blah.name + // + char dropzone_name[32]; + Str_Copy(dropzone_name, short_map_name, sizeof(dropzone_name)); + Str_Cat(dropzone_name, ".", sizeof(dropzone_name)); + Str_Cat(dropzone_name, model_name,sizeof(dropzone_name)); + + + + strcpy(ops_file_data, ops_name); + strcat(ops_file_data, "::"); + strcat(ops_file_data, short_map_name); + strcat(ops_file_data, "::DropZone::" ); + strcat(ops_file_data, dropzone_name); + + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::"); + strcat(ops_file_page, short_map_name ); + strcat(ops_file_page, "::DropZoneList"); + + ops_file->AppendEntry(ops_file_page, "DropZone", ops_file_data); + ops_file->SetEntry(ops_file_data, "tag", dropzone_name ); + ops_file->SetEntry(ops_file_data, "classID", "DpZn"); + ops_file->AppendEntry(ops_file_data, NULL, (char *)NULL); + + + ResourceDescription::ResourceID res_number = + DropZone::CreateModelResource( + file, + model_name, + notation_file, + dropzone_name, + resource_directories + ); + + if (res_number != ResourceDescription::NullResourceID) + { + file->AddResourceList( + dropzone_name, + ResourceDescription::ModelListResourceType, + 1, + ResourceDescription::Preload, + &res_number, + 1 + ); + } + else + { + model_failed = True; + } + } +#endif + } + + else if (!stricmp(type, "include")) + { + strcpy(scenario_name, entry_data); + + NameList *namelist2 = + notation_file->MakeEntryList(entry_data, "file"); + Register_Object(namelist2); + NameList::Entry *entry2 = namelist2->GetFirstEntry(); + + while(entry2 != NULL) + { + + const char *entry2_data = entry2->GetChar(); + + char *filename = + MakePathedFilename( + resource_directories->mapDirectory, + entry2_data + ); + Register_Pointer(filename); + + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + + // + // Write out drop zones.... + // Write out maps... + // + char short_name[100]; + strcpy( short_name, StripDirectory(entry2_data) ); + + if (new_notation_file->PageCount()) + { + if( + !WriteMaps( + short_name, + new_notation_file, + ops_file, + file, + resource_directories + ) + ) + { + std::cout << "Include Failed : " << filename << std::endl; + model_failed = True; + } + } + else + { + std::cout << "Include File : " << filename << " does not exist\n"; + model_failed = True; + } + + + Unregister_Pointer(filename); + delete filename; + Unregister_Object(new_notation_file); + delete new_notation_file; + entry2 = entry2->GetNextEntry(); + } + + Unregister_Object(namelist2); + delete namelist2; + + } + + else if (!stricmp(type, "map")) + { + if (model_failed == False) + { + // + // Check to see that map is not already in resource file + // + + ResourceDescription *test = file->FindResourceDescription( + short_map_name, ResourceDescription::MakeMessageStreamResourceType); + + BoxedSolidList *box_solid_list = new BoxedSolidList; + Register_Object(box_solid_list); + + if ( test == NULL) + { + NameList *namelist2 = + notation_file->MakeEntryList(entry_data, "instance"); + Register_Object(namelist2); + NameList::Entry *entry2 = namelist2->GetFirstEntry(); + + // + //---------------- + // Count instances + //---------------- + // + int instance_count; + for (instance_count=0; entry2; ++instance_count) + { + entry2 = entry2->GetNextEntry(); + } + entry2 = namelist2->GetFirstEntry(); + + // + //------------------------------------------------------- + // make a buffer to hold all these messages, and have the + // beginning store the number of messages + //------------------------------------------------------- + // + int streamSize = instance_count * 4 * sizeof(Entity::MakeMessage); + Entity::MakeMessage *stream = (Entity::MakeMessage*)new char[streamSize]; + memset(stream, 0, streamSize); + + MemoryStream m(stream, streamSize); + *(int*)m.GetPointer() = instance_count; + m.AdvancePointer(sizeof(int)); + + EulerAngles angular_position; + Degree value; + + while (entry2) + { + char find_me[100]; + strcpy(find_me, entry2->GetChar()); + char *p = find_me; + char *token = strtok(p,White_Space); + ResourceDescription *res = NULL; + + if (!stricmp( entry2->GetName(), "instancedropzone")) + { + + char dropzone_name[32]; + #if 0 + Str_Copy(dropzone_name, short_map_name, sizeof(dropzone_name)); + Str_Cat(dropzone_name, ".", sizeof(dropzone_name)); + Str_Cat(dropzone_name,token,sizeof(dropzone_name)); + #else + Str_Copy(dropzone_name,token,sizeof(dropzone_name)); + #endif + + + DropZone::CreateMakeMessage( + (DropZone::MakeMessage*)m.GetPointer(), + token, + dropzone_name, + notation_file + ); + } + else + { + notation_file->GetEntry(token,"type",&type); + + if(!stricmp(type, "include")) + { + res = + file->FindResourceDescription( + token, + ResourceDescription::MakeMessageStreamResourceType + ); + + } + else + { + res = + file->FindResourceDescription( + token, + ResourceDescription::ModelListResourceType + ); + } + + if (!res) + { + std::cout << "Instance Not Found : " << token << std::endl; + + Unregister_Object(namelist2); + Unregister_Pointer(stream); + Unregister_Object(namelist); + delete namelist2; + delete[] stream; + delete namelist; + + return False; + } + + } + + // + //-------------- + // Next instance + //-------------- + // + + // + // If it's not a drop zone + // + if (!stricmp( entry2->GetName(), "instancedropzone")) + { + // do nothing this is already done. + } + else + { + + notation_file->GetEntry(token,"type",&type); + + + if(!stricmp(type, "include")) + { + + char name[100]; + Str_Copy(name, token, 100); + + + ResourceDescription *map_res = file->FindResourceDescription( + name, ResourceDescription::MakeMessageStreamResourceType); + + if (!map_res) + { + std::cout << "CreateMakeMapMessage Failed To Find Map : " << name << std::endl; + Unregister_Object(namelist2); + Unregister_Pointer(stream); + Unregister_Object(namelist); + delete namelist2; + delete[] stream; + delete namelist; + + return False; + + } + + if ( + !Entity::CreateMakeMapMessage( + (Entity::MakeMapMessage*)m.GetPointer(), + map_res->resourceID, + notation_file, + resource_directories + ) + ) + { + std::cout << "CreateMakeMapMessage Failed : " << type << std::endl; + Unregister_Object(namelist2); + Unregister_Pointer(stream); + Unregister_Object(namelist); + delete namelist2; + delete[] stream; + delete namelist; + + return False; + + } + } + else + { + if (!notation_file->GetEntry(token,"modelfile",&type)) + { + std::cout << token << " has no modelfile specification\n"; + Unregister_Object(namelist2); + Unregister_Pointer(stream); + Unregister_Object(namelist); + delete namelist2; + delete[] stream; + delete namelist; + + return False; + } + + char *filename3 = + MakePathedFilename( + resource_directories->modelDirectory, + type + ); + Register_Pointer(filename3); + NotationFile *new_notation_file = + new NotationFile(filename3); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + Unregister_Pointer(filename3); + delete filename3; + + if (!new_notation_file->PageCount()) + { + std::cout << filename3 << " does not exist!"; + Unregister_Object(namelist2); + Unregister_Pointer(stream); + Unregister_Object(namelist); + delete namelist2; + delete[] stream; + delete namelist; + + return False; + + } + + if(!new_notation_file->GetEntry("gamedata","class",&type)) + { + std::cout << "gamedata not found\n"; + Unregister_Object(namelist2); + Unregister_Pointer(stream); + Unregister_Object(namelist); + delete namelist2; + delete[] stream; + delete namelist; + + return False; + + } + + if ( + !CreateMakeMessage( + type, + (Entity::MakeMessage*)m.GetPointer(), + new_notation_file, + resource_directories + ) + ) + { + std::cout << "Invalid gamedata type : " << type << std::endl; + Unregister_Object(namelist2); + Unregister_Pointer(stream); + Unregister_Object(namelist); + delete namelist2; + delete[] stream; + delete namelist; + + return False; + + } + + Unregister_Object(new_notation_file); + delete new_notation_file; + } + } + + + Entity::MakeMessage *message = + (Entity::MakeMessage*)m.GetPointer(); + if ( + !(message->messageFlags + & Entity::MakeMessage::MapStreamMarkerFlag) + ) + { + message->resourceID = + (res) ? + res->resourceID + : ResourceDescription::NullResourceID; + message->ownerID = MapHostID; + message->interestZoneID = 0; + } + m.AdvancePointer(message->messageLength); + entry2 = entry2->GetNextEntry(); + } + + + if (resource_id == -1) + { + file->AddResource( + short_map_name, + ResourceDescription::MakeMessageStreamResourceType, + 1, + ResourceDescription::Preload, + stream, + (char*)m.GetPointer() - (char*)stream + ); + } + else + { + + // + // Check for resource_id , if there Fail. + // + + ResourceDescription *res_des = + file->FindResourceDescription(resource_id); + + if (!res_des) + { + + file->AddResource( + short_map_name, + ResourceDescription::MakeMessageStreamResourceType, + 1, + ResourceDescription::Preload, + stream, + (char*)m.GetPointer() - (char*)stream, + resource_id + ); + } + else + { + DEBUG_STREAM << short_map_name << " : " << resource_id << std::endl << std::flush; + Fail("Duplicate Resource Number"); + } + + } + + + Unregister_Pointer(stream); + delete[] stream; + Unregister_Object(namelist2); + delete namelist2; + } + Unregister_Object(box_solid_list); + delete box_solid_list; + } + else + { + Unregister_Object(namelist); + delete namelist; + return False; + } + + } + else + { + std::cout << "Error: unknown type " << type << "!\n"; + + + Unregister_Object(namelist); + delete namelist; + return False; + } + + entry = entry->GetNextEntry(); + } + + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::"); + strcat(ops_file_page, short_map_name ); + strcat(ops_file_page, "::DropZoneList"); + ops_file->AppendEntry(ops_file_page, NULL, (char *)NULL); + + Unregister_Object(namelist); + delete namelist; + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This does NOT write the maps to the ops file, Write maps does that. +// This just finishes the ops file up +// +void + ApplicationTool::WriteOpsFile( + NotationFile *ops_file, + StreamableResourceFile *file, + const ResourceDirectories *resource_directories + ) +{ + // + //-------------------------------------- + // open vehicle table and write out info + //-------------------------------------- + // + const char *ops_name; + ops_file->GetEntry("resource", "res name", &ops_name); + + char *filename3 = + MakePathedFilename(resource_directories->modelDirectory, "vehicle.tbl"); + Register_Pointer(filename3); + + NotationFile *new_notation_file = new NotationFile(filename3); + Register_Object(new_notation_file); + + // + // Kill if file isn't there. + // + + if (!new_notation_file->PageCount()) + { + std::cout << "vehicle.tbl does not exist in the resource directory!\n" << std::flush; + Unregister_Pointer(filename3); + delete filename3; + PostQuitMessage(AbortExitCodeID); + } + Unregister_Pointer(filename3); + delete filename3; + + NameList *list = new_notation_file->MakeEntryList("color"); + Register_Object(list); + NameList::Entry *entry = list->GetFirstEntry(); + + char ops_file_data[100]; + char ops_file_page[100]; + while(entry) + { + if(entry->GetChar() != NULL) + { + strcpy(ops_file_data, ops_name); + strcat(ops_file_data, "::Standard::Color::"); + strcat(ops_file_data, entry->GetName() ); + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::Standard::ColorList"); + + ops_file->AppendEntry(ops_file_page, "color", ops_file_data); + ops_file->SetEntry(ops_file_data, "tag", entry->GetName() ); + ops_file->AppendEntry(ops_file_data, NULL, (char *)NULL); + } + + entry = entry->GetNextEntry(); + } + + ops_file->AppendEntry(ops_file_page, NULL, (char *)NULL); + Unregister_Pointer(list); + delete list; + + list = new_notation_file->MakeEntryList("badge"); + Register_Object(list); + entry = list->GetFirstEntry(); + + while(entry) + { + if(entry->GetChar() != NULL) + { + strcpy(ops_file_data, ops_name); + strcat(ops_file_data, "::Standard::Badge::"); + strcat(ops_file_data, entry->GetName() ); + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::Standard::BadgeList"); + + ops_file->AppendEntry(ops_file_page, "badge", ops_file_data); + ops_file->SetEntry(ops_file_data, "tag", entry->GetName() ); + ops_file->AppendEntry(ops_file_data, NULL, (char *)NULL); + } + + entry = entry->GetNextEntry(); + } + + ops_file->AppendEntry(ops_file_page, NULL, (char *)NULL); + Unregister_Pointer(list); + delete list; + + + // + // Put spaces at the end of vehicles and maps + // that were defined elsewere. + // + + char temp[30]; + + + + strcpy(temp, ops_name); + strcat(temp, "::Standard::LocationList"); + ops_file->AppendEntry(temp, NULL, (char *)NULL); + strcpy(temp, ops_name); + strcat(temp, "::Standard::VehicleList"); + ops_file->AppendEntry(temp, NULL, (char *)NULL); + + + // + // Add notation file to resource. + // + + long size; + size = new_notation_file->SizeOfText(); + Verify( size >= 0 ); + #define EDO_DEBUG False + #if EDO_DEBUG + Dump( size ); + #endif + char *notation_string = new char[size]; + Register_Pointer(notation_string); + #if DEBUG_LEVEL>0 + long actual_size; + actual_size = + #endif + new_notation_file->WriteText(notation_string, size); + + #if EDO_DEBUG + { + ofstream edo_debug; + edo_debug.open("DEBUGRES.EDO",std::ios::out); + if (!edo_debug) { Fail("can't open DEBUGRES.EDO"); } + const char + *whip = notation_string, + *stop = whip + size; + std::cout << "writing DEBUGRES.EDO" << std::endl; + while (whip < stop) + { + edo_debug << "|" << whip << "|" << std::endl; + whip = strchr(whip, '\0') + 1; + } + edo_debug << "" << std::endl; + edo_debug.close(); + } + #endif + + Verify( actual_size == size ); + file->AddResource( + "vehicletable", + ResourceDescription::VehicleTableResourceType, + 1, + ResourceDescription::Preload, + notation_string, + sizeof(char) * size + ); + + Unregister_Pointer(notation_string); + Unregister_Object(new_notation_file); + delete[] notation_string; + delete new_notation_file; +} diff --git a/MUNGA/MATRIX.cpp b/MUNGA/MATRIX.cpp new file mode 100644 index 0000000..bfa8768 --- /dev/null +++ b/MUNGA/MATRIX.cpp @@ -0,0 +1,711 @@ +#include "munga.h" +#pragma hdrstop + +#include "matrix.h" +#include "affnmtrx.h" +#include "origin.h" + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile AbstractMatrix4x4 *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +AbstractMatrix4x4& + AbstractMatrix4x4::operator=(const AbstractMatrix4x4 &m) +{ + //#if sizeof(entries) > sizeof(m.entries) + //# error memcpy size mismatch! + //#endif + + memcpy(entries, m.entries, sizeof(m.entries)); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +AbstractMatrix4x4& + AbstractMatrix4x4::Transpose(const AbstractMatrix4x4 &m) +{ + entries[0] = m.entries[0]; + entries[1] = m.entries[4]; + entries[2] = m.entries[8]; + entries[3] = m.entries[12]; + + entries[4] = m.entries[1]; + entries[5] = m.entries[5]; + entries[6] = m.entries[9]; + entries[7] = m.entries[13]; + + entries[8] = m.entries[2]; + entries[9] = m.entries[6]; + entries[10] = m.entries[10]; + entries[11] = m.entries[14]; + + entries[12] = m.entries[3]; + entries[13] = m.entries[7]; + entries[14] = m.entries[11]; + entries[15] = m.entries[15]; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + AbstractMatrix4x4::TestInstance() const +{ + return True; +} + +const Matrix4x4 + Matrix4x4::Identity(True); + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::BuildIdentity() +{ + (*this)(0,0) = 1.0f; + (*this)(1,0) = 0.0f; + (*this)(2,0) = 0.0f; + (*this)(3,0) = 0.0f; + + (*this)(0,1) = 0.0f; + (*this)(1,1) = 1.0f; + (*this)(2,1) = 0.0f; + (*this)(3,1) = 0.0f; + + (*this)(0,2) = 0.0f; + (*this)(1,2) = 0.0f; + (*this)(2,2) = 1.0f; + (*this)(3,2) = 0.0f; + + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const AffineMatrix &m) +{ + (*this)(0,0) = m(0,0); + (*this)(0,1) = m(0,1); + (*this)(0,2) = m(0,2); + (*this)(0,3) = 0.0f; + + (*this)(1,0) = m(1,0); + (*this)(1,1) = m(1,1); + (*this)(1,2) = m(1,2); + (*this)(1,3) = 0.0f; + + (*this)(2,0) = m(2,0); + (*this)(2,1) = m(2,1); + (*this)(2,2) = m(2,2); + (*this)(2,3) = 0.0f; + + (*this)(3,0) = m(3,0); + (*this)(3,1) = m(3,1); + (*this)(3,2) = m(3,2); + (*this)(3,3) = 1.0f; + return *this; +} + +Matrix4x4& Matrix4x4::operator=(const D3DXMATRIX &m) +{ + (*this)(0,0) = m._11; + (*this)(0,1) = m._12; + (*this)(0,2) = m._13; + (*this)(0,3) = m._14; + + (*this)(1,0) = m._21; + (*this)(1,1) = m._22; + (*this)(1,2) = m._23; + (*this)(1,3) = m._24; + + (*this)(2,0) = m._31; + (*this)(2,1) = m._32; + (*this)(2,2) = m._33; + (*this)(2,3) = m._34; + + (*this)(3,0) = m._41; + (*this)(3,1) = m._42; + (*this)(3,2) = m._43; + (*this)(3,3) = m._44; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const Origin& p) +{ + Check_Pointer(this); + Check(&p); + + BuildRotation(p.angularPosition); + BuildTranslation(p.linearPosition); + + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Matrix4x4& + Matrix4x4::operator=(const EulerAngles &angles) +{ + Check_Pointer(this); + Check(&angles); + + SinCosPair + x, + y, + z; + + x = angles.pitch; + y = angles.yaw; + z = angles.roll; + + (*this)(0,0) = y.cosine*z.cosine; + (*this)(0,1) = y.cosine*z.sine; + (*this)(0,2) = -y.sine; + (*this)(0,3) = 0.0f; + + (*this)(1,0) = x.sine*y.sine*z.cosine - x.cosine*z.sine; + (*this)(1,1) = x.sine*y.sine*z.sine + x.cosine*z.cosine; + (*this)(1,2) = x.sine*y.cosine; + (*this)(1,3) = 0.0f; + + (*this)(2,0) = x.cosine*y.sine*z.cosine + x.sine*z.sine; + (*this)(2,1) = x.cosine*y.sine*z.sine - x.sine*z.cosine; + (*this)(2,2) = x.cosine*y.cosine; + (*this)(2,3) = 0.0f; + + (*this)(3,0) = 0.0f; + (*this)(3,1) = 0.0f; + (*this)(3,2) = 0.0f; + (*this)(3,3) = 1.0f; + + Check(this); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::BuildRotation(const Quaternion &q) +{ + Check_Pointer(this); + Check(&q); + + Scalar + a = q.x*q.y, + b = q.y*q.z, + c = q.z*q.x, + d = q.w*q.x, + e = q.w*q.y, + f = q.w*q.z, + g = q.w*q.w, + h = q.x*q.x, + i = q.y*q.y, + j = q.z*q.z; + + (*this)(0,0) = g + h - i - j; + (*this)(1,0) = 2.0f*(a - f); + (*this)(2,0) = 2.0f*(c + e); + + (*this)(0,1) = 2.0f*(f + a); + (*this)(1,1) = g - h + i - j; + (*this)(2,1) = 2.0f*(b - d); + + (*this)(0,2) = 2.0f*(c - e); + (*this)(1,2) = 2.0f*(b + d); + (*this)(2,2) = g - h - i + j; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const Quaternion &q) +{ + Check_Pointer(this); + Check(&q); + + BuildRotation(q); + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,0) = 0.0f; + (*this)(3,1) = 0.0f; + (*this)(3,2) = 0.0f; + (*this)(3,3) = 1.0f; + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::BuildTranslation(const Point3D& p) +{ + Check_Pointer(this); + Check(&p); + + (*this)(3,0) = p.x; + (*this)(3,1) = p.y; + (*this)(3,2) = p.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::operator=(const Point3D& p) +{ + Check_Pointer(this); + Check(&p); + + BuildTranslation(p); + + (*this)(0,0) = 1.0f; + (*this)(0,1) = 0.0f; + (*this)(0,2) = 0.0f; + (*this)(0,3) = 0.0f; + (*this)(1,0) = 0.0f; + (*this)(1,1) = 1.0f; + (*this)(1,2) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,0) = 0.0f; + (*this)(2,1) = 0.0f; + (*this)(2,2) = 1.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const Matrix4x4 &Source1, + const Matrix4x4 &Source2 + ) +{ + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0) + + Source1(0,3)*Source2(3,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0) + + Source1(1,3)*Source2(3,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0) + + Source1(2,3)*Source2(3,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source1(3,3)*Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1) + + Source1(0,3)*Source2(3,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1) + + Source1(1,3)*Source2(3,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1) + + Source1(2,3)*Source2(3,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source1(3,3)*Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2) + + Source1(0,3)*Source2(3,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2) + + Source1(1,3)*Source2(3,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2) + + Source1(2,3)*Source2(3,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source1(3,3)*Source2(3,2); + + (*this)(0,3) = + Source1(0,0)*Source2(0,3) + + Source1(0,1)*Source2(1,3) + + Source1(0,2)*Source2(2,3) + + Source1(0,3)*Source2(3,3); + (*this)(1,3) = + Source1(1,0)*Source2(0,3) + + Source1(1,1)*Source2(1,3) + + Source1(1,2)*Source2(2,3) + + Source1(1,3)*Source2(3,3); + (*this)(2,3) = + Source1(2,0)*Source2(0,3) + + Source1(2,1)*Source2(1,3) + + Source1(2,2)*Source2(2,3) + + Source1(2,3)*Source2(3,3); + (*this)(3,3) = + Source1(3,0)*Source2(0,3) + + Source1(3,1)*Source2(1,3) + + Source1(3,2)*Source2(2,3) + + Source1(3,3)*Source2(3,3); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const Matrix4x4 &Source1, + const AffineMatrix &Source2 + ) +{ + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0) + + Source1(0,3)*Source2(3,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0) + + Source1(1,3)*Source2(3,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0) + + Source1(2,3)*Source2(3,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source1(3,3)*Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1) + + Source1(0,3)*Source2(3,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1) + + Source1(1,3)*Source2(3,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1) + + Source1(2,3)*Source2(3,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source1(3,3)*Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2) + + Source1(0,3)*Source2(3,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2) + + Source1(1,3)*Source2(3,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2) + + Source1(2,3)*Source2(3,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source1(3,3)*Source2(3,2); + + (*this)(0,3) = Source1(0,3); + (*this)(1,3) = Source1(1,3); + (*this)(2,3) = Source1(2,3); + (*this)(3,3) = Source1(3,3); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const AffineMatrix &Source1, + const Matrix4x4 &Source2 + ) +{ + (*this)(0,0) = + Source1(0,0)*Source2(0,0) + + Source1(0,1)*Source2(1,0) + + Source1(0,2)*Source2(2,0); + (*this)(1,0) = + Source1(1,0)*Source2(0,0) + + Source1(1,1)*Source2(1,0) + + Source1(1,2)*Source2(2,0); + (*this)(2,0) = + Source1(2,0)*Source2(0,0) + + Source1(2,1)*Source2(1,0) + + Source1(2,2)*Source2(2,0); + (*this)(3,0) = + Source1(3,0)*Source2(0,0) + + Source1(3,1)*Source2(1,0) + + Source1(3,2)*Source2(2,0) + + Source2(3,0); + + (*this)(0,1) = + Source1(0,0)*Source2(0,1) + + Source1(0,1)*Source2(1,1) + + Source1(0,2)*Source2(2,1); + (*this)(1,1) = + Source1(1,0)*Source2(0,1) + + Source1(1,1)*Source2(1,1) + + Source1(1,2)*Source2(2,1); + (*this)(2,1) = + Source1(2,0)*Source2(0,1) + + Source1(2,1)*Source2(1,1) + + Source1(2,2)*Source2(2,1); + (*this)(3,1) = + Source1(3,0)*Source2(0,1) + + Source1(3,1)*Source2(1,1) + + Source1(3,2)*Source2(2,1) + + Source2(3,1); + + (*this)(0,2) = + Source1(0,0)*Source2(0,2) + + Source1(0,1)*Source2(1,2) + + Source1(0,2)*Source2(2,2); + (*this)(1,2) = + Source1(1,0)*Source2(0,2) + + Source1(1,1)*Source2(1,2) + + Source1(1,2)*Source2(2,2); + (*this)(2,2) = + Source1(2,0)*Source2(0,2) + + Source1(2,1)*Source2(1,2) + + Source1(2,2)*Source2(2,2); + (*this)(3,2) = + Source1(3,0)*Source2(0,2) + + Source1(3,1)*Source2(1,2) + + Source1(3,2)*Source2(2,2) + + Source2(3,2); + + (*this)(0,3) = + Source1(0,0)*Source2(0,3) + + Source1(0,1)*Source2(1,3) + + Source1(0,2)*Source2(2,3); + (*this)(1,3) = + Source1(1,0)*Source2(0,3) + + Source1(1,1)*Source2(1,3) + + Source1(1,2)*Source2(2,3); + (*this)(2,3) = + Source1(2,0)*Source2(0,3) + + Source1(2,1)*Source2(1,3) + + Source1(2,2)*Source2(2,3); + (*this)(3,3) = + Source1(3,0)*Source2(0,3) + + Source1(3,1)*Source2(1,3) + + Source1(3,2)*Source2(2,3) + + Source2(3,3); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::Multiply( + const AffineMatrix &m1, + const AffineMatrix &m2 + ) +{ + Cast_Object(AffineMatrix*,this)->Multiply(m1,m2); + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Matrix4x4& + Matrix4x4::SetToProjection( + Scalar Z_Plane, + Scalar Inv_Q, + Scalar Dx, + Scalar Dy, + Scalar Inv_Dz + ) +{ + Scalar + temp; + + // + // This may need to be transposed!!!! + // + (*this)(0,0) = 1.0; + (*this)(0,1) = 0.0; + (*this)(0,2) = 0.0; + (*this)(0,3) = 0.0; + + (*this)(1,0) = 0.0; + (*this)(1,1) = 1.0; + (*this)(1,2) = 0.0; + (*this)(1,3) = 0.0; + + temp = Dx * Inv_Dz; + (*this)(3,0) = temp * Z_Plane; + (*this)(2,0) = -temp; + temp = Dy * Inv_Dz; + (*this)(3,1) = temp * Z_Plane; + (*this)(2,1) = -temp; + + Inv_Dz *= -Inv_Q; + (*this)(2,2) = Z_Plane * Inv_Dz; + (*this)(2,3) = Z_Plane * (1.0 - (*this)(2,2)); + (*this)(3,2) = Inv_Dz; + (*this)(3,3) = 1.0 - (*this)(2,2); + + return *this; +} + +// +//########################################################################### +//########################################################################### +// +D3DXMATRIX Matrix4x4::ToD3DMatrix() +{ + D3DXMATRIX d3dMatrix; + + memcpy(d3dMatrix.m, entries, sizeof(Scalar) * 16); + //// reverse x translation + //d3dMatrix(3, 0) *= -1; + + //// reverse yaw rotation + //d3dMatrix(0, 0) *= -1; + //d3dMatrix(0, 2) *= -1; + //d3dMatrix(2, 0) *= -1; + //d3dMatrix(2, 2) *= -1; + + return d3dMatrix; +} + +// +//########################################################################### +//########################################################################### +// +std::ostream& operator <<(std::ostream& Stream, const Matrix4x4 &A_Matrix) +{ + Stream << std::setprecision(4); + Stream << "\n\t| " << std::setw(9) << A_Matrix(0,0) << ", " << std::setw(9); + Stream << A_Matrix(0,1) << ", " << std::setw(9) << A_Matrix(0,2) << ", "; + Stream << std::setw(9) << A_Matrix(0,3) << " |\n\t| " << std::setw(9); + Stream << A_Matrix(1,0) << ", " << std::setw(9) << A_Matrix(1,1) << ", "; + Stream << std::setw(9) << A_Matrix(1,2) << ", " << std::setw(9) << A_Matrix(1,3); + Stream << " |\n\t| " << std::setw(9) << A_Matrix(2,0) << ", " << std::setw(9); + Stream << A_Matrix(2,1) << ", " << std::setw(9) << A_Matrix(2,2) << ", "; + Stream << std::setw(9) << A_Matrix(2,3) << " |\n\t| " << std::setw(9); + Stream << A_Matrix(3,0) << ", " << std::setw(9) << A_Matrix(3,1) << ", "; + Stream << std::setw(9) << A_Matrix(3,2) << ", " << std::setw(9) << A_Matrix(3,3); + return Stream << " |"; +} + +// +//########################################################################### +//########################################################################### +// +TransposedMatrix& + TransposedMatrix::operator=(const AffineMatrix &m) +{ + //#if sizeof(m.entries) > sizeof(entries) + //# error memcpy size mismatch! + //#endif + + memcpy(entries, m.entries, sizeof(m.entries)); + (*this)(0,3) = 0.0f; + (*this)(1,3) = 0.0f; + (*this)(2,3) = 0.0f; + (*this)(3,3) = 1.0f; + return *this; +} + +#if defined(TEST_CLASS) +# include "matrix.tcp" +#endif diff --git a/MUNGA/MATRIX.h b/MUNGA/MATRIX.h new file mode 100644 index 0000000..5222447 --- /dev/null +++ b/MUNGA/MATRIX.h @@ -0,0 +1,180 @@ +#pragma once + +#include "scalar.h" +#include + +class AffineMatrix; +class TransposedMatrix; +class Origin; +class Hinge; +class EulerAngles; +class YawPitchRoll; +class Point3D; +class Quaternion; + +class AbstractMatrix4x4 +{ +public: + Scalar entries[16]; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile AbstractMatrix4x4 *); + #endif + + AbstractMatrix4x4& operator=(const AbstractMatrix4x4& m); + + Logical TestInstance() const; + +protected: + AbstractMatrix4x4() {} + AbstractMatrix4x4& Transpose(const AbstractMatrix4x4 &m); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Matrix4x4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Matrix4x4 : public AbstractMatrix4x4 +{ +public: + static const Matrix4x4 Identity; + + Matrix4x4() {} + Matrix4x4& BuildIdentity(); + Matrix4x4(int) { BuildIdentity(); } + + Matrix4x4& operator=(const Matrix4x4 &m) + { + Check_Pointer(this); + Check(&m); + AbstractMatrix4x4::operator=(m); + return *this; + } + Matrix4x4& operator=(const TransposedMatrix &m); + Matrix4x4& operator=(const AffineMatrix &m); + Matrix4x4& operator=(const Origin &p); + Matrix4x4& operator=(const Hinge &hinge); + Matrix4x4& operator=(const EulerAngles &angles); + Matrix4x4& operator=(const YawPitchRoll &angles); + Matrix4x4& operator=(const D3DXMATRIX &m); + Matrix4x4& BuildRotation(const Quaternion &q); + Matrix4x4& operator=(const Quaternion &q); + Matrix4x4& BuildTranslation(const Point3D &p); + Matrix4x4& operator=(const Point3D &p); + + // + // Index operators + // Note that Matrix4x4 is stored in row major format, not column major, + // although they are indexed the same + // + Scalar& operator ()(size_t Row,size_t Column) + { + Check_Pointer(this); + Warn(Row>3); + Warn(Column>3); + return entries[(Row<<2)+Column]; + } + const Scalar& operator ()(size_t Row,size_t Column) const + { + Check_Pointer(this); + Warn(Row>3); + Warn(Column>3); + return entries[(Row<<2)+Column]; + } + + Matrix4x4& Multiply(const Matrix4x4& Source1, const Matrix4x4& Source2); + Matrix4x4& operator *=(const Matrix4x4& m) + { + Matrix4x4 temp(*this); + return Multiply(temp,m); + } + Matrix4x4& Multiply(const Matrix4x4& Source1, const AffineMatrix &Source2); + Matrix4x4& operator *=(const AffineMatrix& m) + { + Matrix4x4 temp(*this); + return Multiply(temp,m); + } + Matrix4x4& Multiply(const AffineMatrix &Source1, const Matrix4x4& Source2); + Matrix4x4& Multiply(const AffineMatrix &Source1, const AffineMatrix &Source2); + +#if 0 + Matrix4x4& Invert(const Matrix4x4& Source); + Matrix4x4& Invert() + { + Matrix4x4 src(*this); + return Invert(src); + } +#endif + + Matrix4x4& SetToProjection(Scalar Z_Plane, Scalar Inv_Q, Scalar Dx, Scalar Dy, Scalar Dz); + Matrix4x4& SetToPerspectiveProjection(Scalar Distance) + { + Verify(Distance != 0.0); + return SetToProjection(0.0, 1.0 / Distance, 0.0, 0.0, -1.0); + } + Matrix4x4& SetToOrthogonalProjection() { return SetToProjection(0.0, 0.0, 0.0, 0.0, -1.0); } + + D3DXMATRIX ToD3DMatrix(); + + friend std::ostream& operator <<(std::ostream& stream, const Matrix4x4& Matrix4x4); + static Logical TestClass(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Matrix4x4 ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class TransposedMatrix : public AbstractMatrix4x4 +{ +public: + // + // Constructors + // + TransposedMatrix() {} + + // + // Assignment operators + // + TransposedMatrix& operator=(const Matrix4x4 &m) + { + Check_Pointer(this); + Check(&m); + AbstractMatrix4x4::Transpose(m); + return *this; + } + TransposedMatrix& operator=(const TransposedMatrix &m) + { + Check_Pointer(this); + Check(&m); + AbstractMatrix4x4::operator=(m); + return *this; + } + TransposedMatrix& operator=(const AffineMatrix &m); + + // + // Index operators + // + Scalar& operator()(size_t Row,size_t Column) + { + Check_Pointer(this); + Warn(Row>3); + Warn(Column>3); + return entries[(Column<<2)+Row]; + } + const Scalar& operator()(size_t Row,size_t Column) const + { + Check_Pointer(this); + Warn(Row>3); + Warn(Column>3); + return entries[(Column<<2)+Row]; + } + + // + // Support Functions + // + friend std::ostream& operator <<(std::ostream& stream, const TransposedMatrix& Matrix4x4); +}; + +inline Matrix4x4& Matrix4x4::operator=(const TransposedMatrix &m) +{ + Check_Pointer(this); + Check(&m); + AbstractMatrix4x4::Transpose(m); + return *this; +} diff --git a/MUNGA/MEMBLOCK.cpp b/MUNGA/MEMBLOCK.cpp new file mode 100644 index 0000000..5d7ffcd --- /dev/null +++ b/MUNGA/MEMBLOCK.cpp @@ -0,0 +1,658 @@ +#include "munga.h" +#pragma hdrstop + +#include "memblock.h" +#include "scalar.h" + +//#define MEMORY_VERIFY + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlockHeader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile MemoryBlockHeader *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +Logical + MemoryBlockHeader::TestInstance() +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlockBase ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +MemoryBlockBase* + MemoryBlockBase::firstBlock = NULL; + +// +//############################################################################# +// +// This function constructs a MemoryBlockBase variable, allocating a block of +// blockMemory from heap, preparing it for suballocation of a constant record +// blockSize. +// +// NOTE: Record blockSize must be large enough to contain a void pointer in order +// to properly set up the re-use chain! +// +// Rec_Size - blockSize in bytes of the suballocation unit +// Start - number of records to allocate initially +// Delta - number of records to allocate when growing the blockMemory block +// +//############################################################################# +// +MemoryBlockBase::MemoryBlockBase( + size_t rec_size, + size_t start, + size_t delta, + const char* name +) +{ + // + //---------------------------------------------------------------------- + // Make sure that the requested record blockSize is large enough if debugging + // is enabled + //---------------------------------------------------------------------- + // + Verify(rec_size >= sizeof(MemoryBlockHeader)); + + // + //------------------------------------------------------------------------ + // Set up the blockSize variables for the blockMemory block, and figure out the byte + // sizes of the initial block and delta blocks + //------------------------------------------------------------------------ + // + recordSize = rec_size; + blockSize = start * recordSize; + deltaSize = delta * recordSize; + blockName = name; + + // + //------------------------------------------------------------------------- + // Allocate a block big enough for the requested blockMemory plus a link to + // the next blockMemory block, initializing this link to NULL + //------------------------------------------------------------------------- + // + #if !defined(MEMORY_VERIFY) + blockMemory = (MemoryBlockHeader*)new Byte[sizeof(MemoryBlockHeader) + blockSize]; + Verify(blockMemory); + blockMemory->nextBlock = NULL; + blockMemory->blockSize = blockSize; + + // + //---------------------------------------------------------------------- + // Establish the beginning of the firstHeaderRecord record block, and point + // the freeRecord record pointer to the beginning. There are no deletedRecord + // records yet, so make sure Deleted is NULL + //---------------------------------------------------------------------- + // + firstHeaderRecord = (Byte*)(blockMemory + 1); + freeRecord = firstHeaderRecord; + deletedRecord = NULL; + #endif + + // + //-------------------------------------------------------------------------- + // If this is the first memory block, set the first block pointer and + // initialize the ring. If not, insert the new block at the end of the ring + //-------------------------------------------------------------------------- + // + if (!firstBlock) + { + firstBlock = nextBlock = previousBlock = this; + } + else + { + MemoryBlockBase *block = firstBlock; + Check(block); + block = block->previousBlock; + Check(block); + nextBlock = firstBlock; + previousBlock = block; + block->nextBlock = this; + firstBlock->previousBlock = this; + } +} + +// +//############################################################################# +// +// This function destroys the MemoryBlockBase object, deleting any additional +// record blocks which were allocated +// +//############################################################################# +// +MemoryBlockBase::~MemoryBlockBase() +{ +#if !defined(MEMORY_VERIFY) + // + //------------------------------------------------------------------------ + // Find the address of the first record block, then delete blocks until we + // come to the end of the chain + //------------------------------------------------------------------------ + // + Check(this); + MemoryBlockHeader *block = blockMemory; + + while (block) + { + + // + //-------------------------------------------------------------------- + // Save the address of the next blockMemory block, then delete this one and + // get ready to delete the next one + //-------------------------------------------------------------------- + // + Check(block); + MemoryBlockHeader *next_block = block->nextBlock; + delete block; + block = next_block; + } +#endif + + // + //------------------------------------------------------------------------ + // Remove the block from the ring. If the block is the first one, set the + // first block pointer correctly. Note that we memoryblocks, as static + // objects, should deconstruct in the opposite order they constructed, so + // when we reach the first block, it should be the only one in the queue. + //------------------------------------------------------------------------ + // + if (firstBlock == this) + { + if (nextBlock == this) + { + firstBlock = NULL; + } + else + { + firstBlock = nextBlock; + goto Unlink; + } + } + else + { +Unlink: + MemoryBlockBase *next = nextBlock; + Check(next); + MemoryBlockBase *prev = previousBlock; + Check(prev); + next->previousBlock = prev; + prev->nextBlock = next; + } +} + +// +//############################################################################# +// +// This function allocates a fixed blockSize record from the record blocks +// +//############################################################################# +// +void* + MemoryBlockBase::Grow() +{ + #if defined(MEMORY_VERIFY) + Fail("MemoryBlockBase::Grow() not available!\n"); + #endif + // + //--------------------------------------------------------------------- + // If we have freeRecord space left in the firstHeaderRecord record block, allocate the + // new record from here, updating the next freeRecord record pointer + //--------------------------------------------------------------------- + // + Check(this); + if (freeRecord - firstHeaderRecord <= blockSize - recordSize) + { + void *result = freeRecord; + freeRecord += recordSize; + return result; + } + + // + //----------------------------------------------------------------------- + // Allocate a new block of records using the growth blockSize, and make the + // link field of the firstHeaderRecord block point to the new block. Then make the + // new block the firstHeaderRecord block, and make its next link NULL, as it is the + // end of the chain + //----------------------------------------------------------------------- + // + blockSize = deltaSize; + firstHeaderRecord -= sizeof(MemoryBlockHeader); + Byte *new_block = new Byte[blockSize + sizeof(MemoryBlockHeader)]; + Verify(new_block); + + MemoryBlockHeader *header = (MemoryBlockHeader*)firstHeaderRecord; + header->nextBlock = (MemoryBlockHeader*)new_block; + + firstHeaderRecord = new_block; + header = (MemoryBlockHeader*)firstHeaderRecord; + header->nextBlock = NULL; + header->blockSize = deltaSize; + + // + //--------------------------------------------------------------------- + // Make firstHeaderRecord point to the first available address in the new block + // (having skipped the first field allocated to the link pointer), and + // allocate this first block to the caller. Update the freeRecord pointer to + // reflect this allocation + //--------------------------------------------------------------------- + // + firstHeaderRecord += sizeof(MemoryBlockHeader); + freeRecord = firstHeaderRecord + recordSize; + return (void*)firstHeaderRecord; +} + +// +//############################################################################# +//############################################################################# +// +void + MemoryBlockBase::UsageReport() +{ +#if !defined(MEMORY_VERIFY) + DEBUG_STREAM << "#Bytes #Rcds #Dels #Free Use% Name\n" << std::flush; + DEBUG_STREAM << "------ ----- ----- ----- ---- -------------------------------\n" << std::flush; + MemoryBlockBase *block = firstBlock; + do + { + Check(block); + MemoryBlockHeader *header = block->blockMemory; + size_t byte_count = 0; + size_t record_count = 0; + size_t deletion_count = 0; + size_t unused_count = + block->blockSize - (block->freeRecord - block->firstHeaderRecord); + unused_count /= block->recordSize; + while (header) + { + Check(header); + record_count += header->blockSize / block->recordSize; + byte_count += header->blockSize + sizeof(MemoryBlockHeader); + header = header->nextBlock; + } + Byte *deletion = block->deletedRecord; + while (deletion) + { + ++deletion_count; + deletion = *(Byte**)deletion; + } + Scalar usage = 1.0f - (deletion_count+unused_count)/(float)record_count; + record_count -= deletion_count + unused_count; + DEBUG_STREAM << std::setw(6) << byte_count << std::setw(6) << record_count + << std::setw(6) << deletion_count << std::setw(6) << unused_count << std::setw(4) + << ((int)(usage*100.0f)) << '%'; + if (block->blockName) + { + DEBUG_STREAM << ' ' << block->blockName << std::flush; + } + DEBUG_STREAM << std::endl << std::flush; + block = block->nextBlock; + } + while (block != firstBlock); + DEBUG_STREAM << std::endl << std::flush; +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryBlock ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// +// This function allocates a fixed blockSize record from the record blocks +// +//############################################################################# +// +void* + MemoryBlock::New() +{ + void *result; + #if defined(MEMORY_VERIFY) + result = new char[recordSize]; + #else + // + //---------------------------------------------------------------------- + // If we have a deletedRecord record, go ahead and reuse it, updating the next + // deletedRecord record value from the firstHeaderRecord one. This chain is independant + // of the firstHeaderRecord record block. If not, grow the blockMemory block by one + // record + //---------------------------------------------------------------------- + // + Check(this); + if (deletedRecord) + { + result = (void*)deletedRecord; + deletedRecord = *(Byte**)deletedRecord; + } + else + { + result = Grow(); + } + #endif + + // + //---------------------------------------------------------------------- + // If we are checking for unassigned variables, initialize the allocated + // memory with NANs + //---------------------------------------------------------------------- + // + #if defined(DEBUG_NEW_ON) + #define SNAN_POSITIVE_LONG 0x7fb07fb0 + long *filler = (long *)result; + for (int i = recordSize >> 2; i; --i) + { + *filler++ = SNAN_POSITIVE_LONG; + } + #endif + + // + //------------------------------------- + // Return the address of the new record + //------------------------------------- + // + return result; +} + +// +//############################################################################# +// +// This function deallocates a record, making it available for re-use +// +//############################################################################# +// +void + MemoryBlock::Delete( + void* where + ) +{ + #if defined(MEMORY_VERIFY) + delete where; + #else + // + //-------------------------------------------------------------------- + // If we are in debug2 mode, check to see if the deletedRecord region really + // belongs to us + //-------------------------------------------------------------------- + // + Check(this); + + #if DEBUG_LEVEL>1 + + // + //-------------------------------------------------------------------- + // Make sure the address of this record is not already in the deletion + // chain + //-------------------------------------------------------------------- + // + void *record; + for ( + record = (void*)deletedRecord; + record; + record = *(Byte**)record + ) + { + if (record == where) + { + break; + } + } + Verify(!record); + + // + //------------------------------------------------------------------ + // Find the address of the first record block, then check each block + // until we come to the end of the chain + //------------------------------------------------------------------ + // + unsigned + offset; + MemoryBlockHeader* + block = blockMemory; + + while (block) + { + + // + //--------------------------------------------------------------- + // If the record is in this block and is positioned correctly, go + // ahead and break as we have found a legal place within a block + //--------------------------------------------------------------- + // + Check(block); + offset = (unsigned)((Byte*)where - (Byte*)(block + 1)); + if (offset < block->blockSize) + { + Verify(!(offset % recordSize)); + break; + } + + // + //--------------------- + // Go to the next block + //--------------------- + // + block = block->nextBlock; + } + Verify(block); + + // + //----------------------------------------------------------- + // Now make sure that the address is not in our future region + //----------------------------------------------------------- + // + Verify(block->nextBlock || offset < freeRecord-firstHeaderRecord); + + #endif + + // + //---------------------------------------------------------------------- + // Make the first few bytes of the record act as the link pointer to the + // beginning of the firstHeaderRecord deletedRecord chain, then make the first record + // available for reuse this one + //---------------------------------------------------------------------- + // + *(Byte**)where = deletedRecord; + deletedRecord = (Byte*)where; + #endif +} + +// +//############################################################################# +//############################################################################# +// +void* + MemoryBlock::operator[](size_t index) +{ + #if defined(MEMORY_VERIFY) + Fail("MemoryBlock::operator[] not available!\n"); + #endif + + // + //------------------------------------------------------------------ + // Find the address of the first record block, then check each block + // until we come to the end of the chain + //------------------------------------------------------------------ + // + Check(this); + MemoryBlockHeader + *block = blockMemory; + + while (block) + { + // + //--------------------------------------------------------------- + // If the index is in this block, go ahead and return its address + //--------------------------------------------------------------- + // + Check(block); + Verify(recordSize); + int + records = block->blockSize / recordSize; + if (index < records) + { + return (Byte*)(block + 1) + index * recordSize; + } + + // + //-------------------------------------------------------------------- + // Save the address of the next blockMemory block, then delete this one and + // get ready to delete the next one + //-------------------------------------------------------------------- + // + index -= records; + block = block->nextBlock; + } + + // + //----------------------------------------- + // The record doesn't exist, so return NULL + //----------------------------------------- + // + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +void* + MemoryStack::Push(const void* what) +{ + Check(this); + Check_Pointer(what); + + Byte *block = firstHeaderRecord; + topOfStack = freeRecord; + Mem_Copy(Grow(), what, recordSize, blockSize - (freeRecord - firstHeaderRecord)); + if (firstHeaderRecord != block) + { + topOfStack = firstHeaderRecord; + } + return topOfStack; +} + +// +//############################################################################# +//############################################################################# +// +void* + MemoryStack::Push() +{ + Check(this); + Byte *block = firstHeaderRecord; + topOfStack = freeRecord; + Grow(); + + if (firstHeaderRecord != block) + { + topOfStack = firstHeaderRecord; + } + return topOfStack; +} + +// +//########################################################################### +//########################################################################### +// +void + MemoryStack::Pop() +{ + MemoryBlockHeader + *block, + *new_block; + + // + //----------------------------------------- + // Make sure that something is in the stack + //----------------------------------------- + // + Check(this); + if (topOfStack) + { + // + //-------------------------------------------------------------------- + // If the topOfStack of the stack is not at the bottom of a blockMemory block, the + // freeRecord and topOfStack pointers can move normally + //-------------------------------------------------------------------- + // + if (topOfStack != firstHeaderRecord) + { + // + //------------------------------------------------------------------- + // If the freeRecord pointer is at the bottom of a block, we have to delete + // the block and update the variables to the previous block + //------------------------------------------------------------------- + // + if (freeRecord == firstHeaderRecord) + { + new_block = (MemoryBlockHeader*)firstHeaderRecord - 1; + Check(new_block); + for ( + block = blockMemory; + block->nextBlock != new_block; + block = block->nextBlock + ) + { + Check(block); + } + + delete new_block; + block->nextBlock = NULL; + firstHeaderRecord = (Byte*)(block + 1); + blockSize = block->blockSize; + } + + // + //----------------------------------------------- + // Move the topOfStack and freeRecord pointers back one record + //----------------------------------------------- + // + freeRecord = topOfStack; + topOfStack -= recordSize; + } + + // + //-------------------------------------------------------------------- + // Otherwise, we have to wrap the top of the stack pointer back to the + // previous block. If there is only one allocated block, then the + // stack is empty + //-------------------------------------------------------------------- + // + else if (!blockMemory->nextBlock) + { + topOfStack = NULL; + } + + // + //-------------------------------------------------------------------- + // Point the top of the stack to the last record of the previous block + //-------------------------------------------------------------------- + // + else + { + new_block = (MemoryBlockHeader*)firstHeaderRecord - 1; + Check(new_block); + for ( + block = blockMemory; + block->nextBlock != new_block; + block = block->nextBlock + ) + { + Check(block); + } + topOfStack = (Byte*)(block + 1) + block->blockSize - recordSize; + } + } +} + +#if defined(TEST_CLASS) +# include "memblock.tcp" +#endif diff --git a/MUNGA/MEMBLOCK.h b/MUNGA/MEMBLOCK.h new file mode 100644 index 0000000..ec75373 --- /dev/null +++ b/MUNGA/MEMBLOCK.h @@ -0,0 +1,108 @@ +#pragma once + +#include "style.h" + +class MemoryBlockHeader +{ +public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile MemoryBlockHeader *p); + #endif + + MemoryBlockHeader *nextBlock; + size_t blockSize; + + Logical TestInstance(); +}; + +class MemoryBlockBase SIGNATURED +{ +public: + Logical TestInstance() { return blockMemory != NULL; } + + static void UsageReport(); + static void Collapse(); + +protected: + const char *blockName; + + MemoryBlockHeader *blockMemory; + + size_t blockSize, recordSize, deltaSize; + + Byte *firstHeaderRecord, *freeRecord, *deletedRecord; + + MemoryBlockBase(size_t rec_size, size_t start, size_t delta, const char* name = NULL); + ~MemoryBlockBase(); + + void *Grow(); + +private: + static MemoryBlockBase *firstBlock; + MemoryBlockBase *nextBlock, *previousBlock; + + static void SortDeletions(); +}; + +class MemoryBlock : public MemoryBlockBase +{ +public: + static Logical TestClass(); + + MemoryBlock(size_t rec_size, size_t start, size_t delta, const char *name = NULL) + : MemoryBlockBase(rec_size, start, delta, name) + { + } + + void *New(); + void Delete(void *Where); + + void *operator[](size_t Index); +}; + +template class MemoryBlockOf : public MemoryBlock +{ +public: + MemoryBlockOf(size_t start, size_t delta, const char *name = NULL) + : MemoryBlock(sizeof(T), start, delta, name) + { + } + + T* New() { return (T*)MemoryBlock::New(); } + void Delete(void *where) { MemoryBlock::Delete(where); } + + T* operator[](size_t index) { return (T*)MemoryBlock::operator [](index); } +}; + +class MemoryStack : public MemoryBlockBase +{ +public: + static Logical TestClass(); + +protected: + Byte *topOfStack; + + MemoryStack(size_t rec_size, size_t start, size_t delta, const char* name = NULL) + : MemoryBlockBase(rec_size, start, delta, name) + { + topOfStack = NULL; + } + + void *Push(const void *What); + void *Push(); + void *Peek() { return (void*)topOfStack; } + void Pop(); +}; + +template class MemoryStackOf : public MemoryStack +{ +public: + MemoryStackOf(size_t start, size_t delta, const char *name) + : MemoryStack(sizeof(T), start, delta, nome) + { + } + + T *Push(const T *what) { return (T*)MemoryStack::Push(what); } + T *Peek() { return (T*)MemoryStack::Peek(); } + void Pop() { MemoryStack::Pop(); } +}; \ No newline at end of file diff --git a/MUNGA/MEMREG.cpp b/MUNGA/MEMREG.cpp new file mode 100644 index 0000000..8f42e7f --- /dev/null +++ b/MUNGA/MEMREG.cpp @@ -0,0 +1,654 @@ +#include "munga.h" +#pragma hdrstop + +#include "plug.h" +#include "node.h" +#include "hash.h" + +class MemoryRegister; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MRStats ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define MR_FILENAME_LEN (64) +#define MR_HASH_SIZE (500) + +class MRStats: + public Plug +{ + friend class MemoryRegister; + +public: + MRStats( + void *address, + MRStatsAddressType address_type, + char *fileName, + int lineNum + ); + ~MRStats(); + +private: + void + *address; + char + fileName[MR_FILENAME_LEN]; + int + lineNum; + + #ifdef MEMORY_VERIFY + MRStatsAddressType + addressType; + #endif +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryRegister ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class MemoryRegister: + public Node +{ +public: + friend void Start_Registering_Function(); + friend void Stop_Registering_Function(); + + friend void Register_Pointer_Function( + void *address, + MRStatsAddressType address_type, + char *file_name, + int line_num + ); + friend void Unregister_Pointer_Function( + void *address, + char *file_name, + int line_num + ); + + friend void Address_Registration_Function( + void *address, + char *file_name, + int line_num + ); + + friend void Check_All_Signatures_Function( + char *file_name, + int line_num + ); + + MemoryRegister(); + ~MemoryRegister(); + + Logical + TestInstance() const; + + void + Report(); + +private: + Logical + RegisterAddress( + void *address, + MRStatsAddressType, + char *fileName, + int lineNum + ); + + Logical + ReleaseAddress( + void *address, + char *fileName, + int lineNum + ); + + Logical + IsRegistered( + void *address + ); + + void + AddressRegistration( + void *address, + char *file_name, + int line_num + ); + + void + CheckAllSignatures( + char *file_name, + int line_num + ); + + static Logical + VerifyAddress( + void *address, + char *fileName, + int lineNum + ); + +private: + HashOf + memoryStats; + Logical + collectStats; + long + registrations; + + #ifdef MEMORY_VERIFY + Logical + checkAllSignatures; + ChainOf + verificationSocket; + Time + nextTell; + #endif +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MemoryRegisterShell ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class MemoryRegisterShell +{ +public: + MemoryRegisterShell(); + ~MemoryRegisterShell(); + + static MemoryRegister + *store; +}; + +#ifdef MEMORY_REGISTER +MemoryRegisterShell + memory_register_shell; +#endif +MemoryRegister + *MemoryRegisterShell::store=NULL; + +// +//########################################################################### +// MemoryRegisterShell +//########################################################################### +// +MemoryRegisterShell::MemoryRegisterShell() +{ + store = new MemoryRegister; + Check(store); +} + +// +//########################################################################### +// ~MemoryRegisterShell +//########################################################################### +// +MemoryRegisterShell::~MemoryRegisterShell() +{ + MemoryRegister *obj; + + Check(store); + store->Report(); + obj = store; + store = NULL; + delete obj; +} + +// +//########################################################################### +// MRStats +//########################################################################### +// +#ifdef MEMORY_VERIFY +MRStats::MRStats( + void *address, + MRStatsAddressType address_type, + char *fileName, + int lineNum +) +{ + this->address = address; + this->lineNum = lineNum; + + Str_Copy(this->fileName, fileName, MR_FILENAME_LEN); + + this->addressType = address_type; +} +#else +MRStats::MRStats( + void *address, + MRStatsAddressType, + char *fileName, + int lineNum +) +{ + this->address = address; + this->lineNum = lineNum; + + Str_Copy(this->fileName, fileName, MR_FILENAME_LEN); +} +#endif + +MRStats::~MRStats() +{ +} + +// +//########################################################################### +// MemoryRegister +//########################################################################### +// +#ifdef MEMORY_VERIFY +MemoryRegister::MemoryRegister(): + memoryStats(MR_HASH_SIZE, NULL, True), + verificationSocket(NULL) +{ + collectStats = True; + registrations = 0; + checkAllSignatures = True; + nextTell = Now(); +} +#else +MemoryRegister::MemoryRegister(): + memoryStats(MR_HASH_SIZE, NULL, True) +{ + collectStats = True; + registrations = 0; +} +#endif + +// +//########################################################################### +// ~MemoryRegister +//########################################################################### +// +MemoryRegister::~MemoryRegister() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + MemoryRegister::TestInstance() const +{ + Node::TestInstance(); + + Check(&memoryStats); + #ifdef MEMORY_VERIFY + Check(&verificationSocket); + #endif + + return True; +} + +// +//########################################################################### +// RegisterAddress +//########################################################################### +// +Logical + MemoryRegister::RegisterAddress( + void *address, + MRStatsAddressType address_type, + char *fileName, + int lineNum + ) +{ + MRStats *stats; + + if (!collectStats) + return True; + + if (!VerifyAddress(address, fileName, lineNum)) + return False; + + Check(&memoryStats); + if ((stats = memoryStats.Find((unsigned long)address)) != NULL) + { + Tell( + stats->address << " : " << + stats->fileName << '(' << + stats->lineNum << ")\n" + ); + Verify_Failed( + "MemoryRegister::RegisterAddress: Address already registered by above", + fileName, + lineNum + ); + return False; + } + + stats = new MRStats(address, address_type, fileName, lineNum); + Check(stats); + + Check(&memoryStats); + collectStats = False; + memoryStats.AddValue(stats, (unsigned long)address); + #ifdef MEMORY_VERIFY + // Currently, only verify signatured objects + if (address_type == ObjectMRStatsAddressType) + { + Check(&verificationSocket); + checkAllSignatures = False; + verificationSocket.Add(stats); + checkAllSignatures = True; + } + #endif + collectStats = True; + + registrations++; + + return True; +} + +// +//########################################################################### +// ReleaseAddress +//########################################################################### +// +Logical + MemoryRegister::ReleaseAddress( + void *address, + char *fileName, + int lineNum + ) +{ + MRStats *stats; + + if (!collectStats) + return True; + + if (!VerifyAddress(address, fileName, lineNum)) + return False; + + stats = memoryStats.Find((unsigned long)address); + if (stats != NULL) + { + Check(stats); + collectStats = False; + delete stats; + collectStats = True; + return True; + } + + Verify_Failed( + "MemoryRegister::ReleaseAddress: Address not found", + fileName, + lineNum + ); + return False; +} + +// +//########################################################################### +// IsRegistered +//########################################################################### +// +Logical + MemoryRegister::IsRegistered(void *address) +{ + return (memoryStats.Find((unsigned long)address) != NULL); +} + +// +//########################################################################### +// AddressRegistration +//########################################################################### +// +void + MemoryRegister::AddressRegistration( + void *address, + char *file_name, + int line_num + ) +{ + MRStats *stats; + + if ((stats = memoryStats.Find((unsigned long)address)) != NULL) + { + std::cout << + stats->address << " : allocated at : " << + stats->fileName << '(' << + stats->lineNum << ")\n" + ; + } + else + { + Verify_Failed( + "MemoryRegister::AddressRegistration: Address not found", + file_name, + line_num + ); + } +} + +// +//########################################################################### +// CheckAllSignatures +//########################################################################### +// +#ifdef MEMORY_VERIFY +void + MemoryRegister::CheckAllSignatures( + char *file_name, + int line_num + ) +{ + if (checkAllSignatures) + { + checkAllSignatures = False; + + if (nextTell < Now()) + { + nextTell += 1.0f; + Tell("."); + } + + ChainIteratorOf + iterator(&verificationSocket); + MRStats + *stats; + + Check(&iterator); + while ((stats = iterator.ReadAndNext()) != NULL) + { + Check(stats); + switch (stats->addressType) + { + case PointerMRStatsAddressType: + Check_Pointer(stats->address); + break; + + case ObjectMRStatsAddressType: + if (Is_Signature_Bad((Signature*)stats->address)) + { + Tell( + stats->address << " : allocated at : " << + stats->fileName << '(' << + stats->lineNum << ") corrupted at : " << + file_name << '(' << + line_num << ")\n" + ); + Check_Signature((Signature*)stats->address); + } + break; + + default: + Fail("MemoryRegister::CheckAllSignatures - Unknown addressType"); + break; + } + } + + checkAllSignatures = True; + } +} +#else +void + MemoryRegister::CheckAllSignatures( + char*, + int + ) +{ +} +#endif + +// +//########################################################################### +// Report +//########################################################################### +// +void + MemoryRegister::Report() +{ + HashIteratorOf + iterator(memoryStats); + MRStats + *stats; + + Tell("MemoryRegister::Report\n"); + Tell("Registrations " << registrations << std::endl); + Tell("Unreleased Addresses:\n"); + + while ((stats = iterator.ReadAndNext()) != NULL) + { + Check(stats); + std::cout << + stats->address << " : " << + stats->fileName << '(' << + stats->lineNum << ")\n" + ; + } +} + +// +//########################################################################### +// VerifyAddress +//########################################################################### +// +Logical + MemoryRegister::VerifyAddress( + void *address, + char *fileName, + int lineNum + ) +{ + // + // HACK - An improvement would make sure that the memory + // address is within our heap or stack + // + if (address == 0L) + { + Verify_Failed( + "MemoryRegister::VerifyAddress: Address is NULL", + fileName, + lineNum + ); + return False; + } + return True; +} + +// +//########################################################################### +// Start +//########################################################################### +// +void + Start_Registering_Function() +{ + #if 0 + MemoryRegister::store = new MemoryRegister; + Check(MemoryRegister::store); + #endif +} + +// +//########################################################################### +// Stop +//########################################################################### +// +void + Stop_Registering_Function() +{ + #if 0 + MemoryRegister *obj; + + Check(MemoryRegister::store); + MemoryRegister::store->Report(); + obj = MemoryRegister::store; + MemoryRegister::store = NULL; + delete obj; + #endif +} + +// +//########################################################################### +// Register_Pointer_Function +//########################################################################### +// +void + Register_Pointer_Function( + void *address, + MRStatsAddressType address_type, + char *file_name, + int line_num + ) +{ + if (MemoryRegisterShell::store) + { + MemoryRegisterShell::store->RegisterAddress( + address, + address_type, + file_name, + line_num + ); + } +} + +// +//########################################################################### +// Unregister_Pointer_Function +//########################################################################### +// +void + Unregister_Pointer_Function( + void *address, + char *file_name, + int line_num + ) +{ + if (MemoryRegisterShell::store) + { + MemoryRegisterShell::store->ReleaseAddress(address, file_name, line_num); + } +} + +// +//########################################################################### +// Address_Registration_Function +//########################################################################### +// +void + Address_Registration_Function( + void *address, + char *file_name, + int line_num + ) +{ + if (MemoryRegisterShell::store) + { + MemoryRegisterShell::store->AddressRegistration(address, file_name, line_num); + } +} + +// +//########################################################################### +// Check_All_Signatures_Function +//########################################################################### +// +void + Check_All_Signatures_Function( + char *file_name, + int line_num + ) +{ + if (MemoryRegisterShell::store) + { + MemoryRegisterShell::store->CheckAllSignatures(file_name, line_num); + } +} diff --git a/MUNGA/MEMREG.h b/MUNGA/MEMREG.h new file mode 100644 index 0000000..44a98dd --- /dev/null +++ b/MUNGA/MEMREG.h @@ -0,0 +1,76 @@ +#pragma once + +#include + +typedef enum +{ + PointerMRStatsAddressType, + ObjectMRStatsAddressType +} MRStatsAddressType; + +#undef Start_Registering +#undef Stop_Registering +#undef Register_Object +#undef Register_Pointer +#undef Unregister_Object +#undef Unregister_Pointer +#undef Object_Registration +#undef Check_All_Signatures + +#if !defined(MEMORY_REGISTER) + #define Start_Registering() + #define Start_Registering() + #define Stop_Registering() + #define Register_Object(address) Check(address) + #define Register_Pointer(address) Check_Pointer(address) + #define Unregister_Object(address) Check(address) + #define Unregister_Pointer(address) Check_Pointer(address) + #define Object_Registration(address) + #define Check_All_Signatures() +#else + extern void Start_Registering_Function(); + extern void Stop_Registering_Function(); + + extern void Register_Pointer_Function(void *address, MRStatsAddressType address_type, char *file_name, int line_num); + extern void Unregister_Pointer_Function(void *address, char *file_name, int line_num); + + extern void Object_Registration_Function(void *address, char *file_name, int line_num); + + extern void Check_All_Signatures_Function(char *file_name, int line_num); + + #define Start_Registering() Start_Registering_Function() + #define Stop_Registering() Stop_Registering_Function() + + #define Check_All_Signatures() Check_All_Signatures_Function(__FILE__, __LINE__) + + #if defined(MEMORY_VERIFY) + #undef Check + #define Check(p)\ + {\ + Check_Signature(p);\ + Verify((p)->TestInstance());\ + Check_All_Signatures();\ + } + #endif + + #define Register_Object(address)\ + {\ + Check(address);\ + Register_Pointer_Function(\ + address,\ + Is_Signature_Bad((Signature*)address) ?\ + PointerMRStatsAddressType : ObjectMRStatsAddressType,\ + __FILE__, __LINE__\ + );\ + } + + #define Register_Pointer(address) Register_Pointer_Function(address, PointerMRStatsAddressType, __FILE__, __LINE__) + #define Unregister_Object(address)\ + {\ + Check(address);\ + Unregister_Pointer_Function(address, __FILE__, __LINE__);\ + } + + #define Unregister_Pointer(address) Unregister_Pointer_Function(address, __FILE__, __LINE__) + #define Object_Registration(address) Object_Registration_Function(address, __FILE__, __LINE__) +#endif diff --git a/MUNGA/MEMSTRM.CPP b/MUNGA/MEMSTRM.CPP new file mode 100644 index 0000000..ee693d4 --- /dev/null +++ b/MUNGA/MEMSTRM.CPP @@ -0,0 +1,180 @@ +#include +#include "memstrm.h" + +//############################################################################# +//########################## MemoryStream ############################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream::MemoryStream(void *stream_start, size_t stream_size, size_t initial_offset) +{ + streamStart = (char*)stream_start; + streamSize = stream_size; + + Verify(initial_offset <= stream_size); + currentPosition = streamStart + initial_offset; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& MemoryStream::ReadBytes(void *ptr, size_t number_of_bytes) +{ + Verify(GetBytesRemaining() >= number_of_bytes); + + memcpy(ptr, GetPointer(), number_of_bytes); + AdvancePointer(number_of_bytes); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& MemoryStream::WriteBytes(const void *ptr, size_t number_of_bytes) +{ + Verify(number_of_bytes > 0); + Verify(number_of_bytes <= GetBytesRemaining()); + + memcpy(GetPointer(), ptr, number_of_bytes); + AdvancePointer(number_of_bytes); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& MemoryStream_Write(MemoryStream *stream, std::istream *input) +{ + Verify(!input->bad()); + input->clear(); + + // + //-------------------------------------------------------- + // If we are reading a binary stream, read it in one chunk + //-------------------------------------------------------- + // + if (input->flags() & std::ios::binary) + { + input->seekg(0, std::ios::end); + int len = input->tellg(); + input->clear(); + input->seekg(0); + + if (!stream->AllocateBytes(len)) + return *stream; + + input->read((char*)stream->GetPointer(), len); + stream->AdvancePointer(len); + } + + // + //---------------------------------------------------------------- + // Read a text file character by character if we are a DOS machine + //---------------------------------------------------------------- + // + else + { + input->clear(); + input->seekg(0); + unsigned char byte; + + while (input->get((char*)&byte, 1)) + *stream << byte; + } + + return *stream; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& MemoryStream_Write(MemoryStream *stream, const MemoryStream *input_stream) +{ + return stream->WriteBytes(input_stream->GetPointer(), input_stream->GetBytesRemaining()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +bool MemoryStream::TestInstance() const +{ + return size_t(currentPosition - streamStart) <= streamSize; +} + +//############################################################################# +//###################### DynamicMemoryStream ############################ +//############################################################################# + +// +// calculate the allocation size for stream +// +inline size_t Calculate_Buffer_Size(size_t needed) +{ + return (needed + 0x80) & ~0x7F; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DynamicMemoryStream::DynamicMemoryStream(size_t stream_size) + : MemoryStream(NULL, stream_size) +{ + streamSize = Calculate_Buffer_Size(stream_size); + streamStart = new char[streamSize]; + + currentPosition = streamStart; + streamLength = 0L; + ownsStream = true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DynamicMemoryStream::DynamicMemoryStream(void *stream_start, size_t stream_size, size_t initial_offset) + : MemoryStream(stream_start, stream_size, initial_offset) +{ + ownsStream = false; + streamLength = stream_size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DynamicMemoryStream::~DynamicMemoryStream() +{ + if (ownsStream) + delete[] streamStart; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +bool DynamicMemoryStream::AllocateBytes(size_t count) +{ + if (ownsStream && MemoryStream::GetBytesRemaining() < count) + { + size_t current_offset = currentPosition - streamStart; + size_t new_stream_size = streamSize + count - MemoryStream::GetBytesRemaining() + 1; + new_stream_size = Calculate_Buffer_Size(new_stream_size); + char *new_stream_start = new char[new_stream_size]; + + memcpy(new_stream_start, streamStart, streamSize); + delete[] streamStart; + streamStart = new_stream_start; + streamSize = new_stream_size; + currentPosition = streamStart + current_offset; + } + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& DynamicMemoryStream::WriteBytes(const void *ptr, size_t number_of_bytes) +{ + Verify(number_of_bytes > 0); + + // + //-------------------------------------------------------------------- + // If we own the stream, and we don't have enough memory to accept the + // write, copy the buffer and make a new stream that is bigger + //-------------------------------------------------------------------- + // + AllocateBytes(number_of_bytes); + memcpy(GetPointer(), ptr, number_of_bytes); + AdvancePointer(number_of_bytes); + + streamLength = __max(streamLength, GetBytesUsed()); + return *this; +} \ No newline at end of file diff --git a/MUNGA/MEMSTRM.H b/MUNGA/MEMSTRM.H new file mode 100644 index 0000000..2ae6f70 --- /dev/null +++ b/MUNGA/MEMSTRM.H @@ -0,0 +1,141 @@ +#pragma once + +#include +#include "style.h" + +//########################################################################## +//####################### MemoryStream ############################### +//########################################################################## + +class MemoryStream +{ + friend MemoryStream& MemoryStream_Write(MemoryStream *stream, const MemoryStream *input_stream); + +public: + MemoryStream(void *stream_start, size_t stream_size, size_t initial_offset=0); + + size_t GetIndex() const { return currentPosition - streamStart; } + size_t GetSize() const { return streamSize; } + size_t GetBytesUsed() const { return currentPosition - streamStart; } + void Rewind() { SetPointer(0U); } + bool TestInstance() const; + + virtual void* GetPointer() const { return currentPosition; } + virtual size_t GetBytesRemaining() const { return streamSize - GetBytesUsed(); } + virtual void SetPointer(void *new_pointer) { currentPosition = (char*)new_pointer; } + virtual void SetPointer(size_t index) { currentPosition = streamStart + index; } + virtual bool AllocateBytes(size_t count) { return GetBytesRemaining() <= count; } + virtual MemoryStream& RewindPointer(size_t count) { currentPosition -= count; return *this; } + virtual MemoryStream& AdvancePointer(size_t count) { currentPosition += count; return *this; } + virtual MemoryStream& ReadBytes(void *ptr, size_t number_of_bytes); + virtual MemoryStream& WriteBytes(const void *ptr, size_t number_of_bytes); + + void operator= (void *new_pointer) { SetPointer(new_pointer); } + void operator= (size_t index) { SetPointer(index); } + MemoryStream& operator+= (size_t count) { return AdvancePointer(count); } + MemoryStream& operator-= (size_t count) { return RewindPointer(count); } + +protected: + char *streamStart, *currentPosition; + size_t streamSize; +}; + +//-------------------------------------------------------------------------- +// Extraction operators +// +template inline MemoryStream& operator>>(MemoryStream &stream, T &output) +{ return MemoryStream_Read(&stream, &output); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, char *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned char *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, short *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned short *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, int *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned int *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, long *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, unsigned long *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +//-------------------------------------------------------------------------- +// Insertion operators +// +template inline MemoryStream& operator<<(MemoryStream &stream, const T &input) +{ return MemoryStream_Write(&stream, &input); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const char *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned char *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const short *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned short *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const int *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned int *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const long *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const unsigned long *input) +{ return stream->WriteBytes(input, sizeof(*input)); } + +MemoryStream& MemoryStream_Write(MemoryStream* stream, std::istream *input); +MemoryStream& MemoryStream_Write(MemoryStream* stream, const MemoryStream* input_stream); + +#define MEM_STRM_WRITE_ENTRY(stream, name_list, type, name)\ + {\ + type name;\ + const char* data = (const char*)(name_list)->FindData(#name);\ + if (!data)\ + {\ + DEBUG_STREAM << "DYN_MEM_STRM_WRITE_ENTRY - #name == " << std::flush;\ + DEBUG_STREAM << #name << "\n" << std::flush;\ + Fail("DYN_MEM_STRM_WRITE_ENTRY - (name_list)->FindData(#name) == NULL");\ + }\ + Check_Pointer(data);\ + Convert_From_Ascii(data, &name);\ + stream << name;\ + } + +//########################################################################## +//################### DynamicMemoryStream ############################ +//########################################################################## + +class DynamicMemoryStream : public MemoryStream +{ +public: + DynamicMemoryStream(size_t stream_size = 0); + DynamicMemoryStream(void *stream_start, size_t stream_size, size_t initial_offset = 0); + ~DynamicMemoryStream(); + + bool TestInstance() const { return ((size_t)(currentPosition - streamStart) <= streamSize && streamLength <= streamSize); } + size_t GetBytesRemaining() const { return streamSize - GetBytesUsed(); } + bool AllocateBytes(size_t count); + + MemoryStream& WriteBytes(const void *ptr, size_t number_of_bytes); + +private: + size_t streamLength; + bool ownsStream; +}; \ No newline at end of file diff --git a/MUNGA/MISSION.cpp b/MUNGA/MISSION.cpp new file mode 100644 index 0000000..b16acf3 --- /dev/null +++ b/MUNGA/MISSION.cpp @@ -0,0 +1,623 @@ +#include "munga.h" +#pragma hdrstop + +#include "mission.h" +#include "namelist.h" +#include "notation.h" +#include "graph2d.h" + +//############################################################################# +//####################### MissionHostData ############################### +//############################################################################# + +MissionHostData::MissionHostData( + const CString &address_string, + HostType host_type +): + addressString(address_string), + hostType(host_type) +{ +} + +MissionHostData::~MissionHostData() +{ +} + +//############################################################################# +//########################### Mission ################################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadOrdinalBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load ordinal bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the bitmap names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *ord_namelist = notation_file->MakeEntryList("ordinals", "bitmap"); + if (!ord_namelist) + { + Warn("No Ordinal Bitmaps in Egg \n"); + return; + } + Register_Object(ord_namelist); + NameList::Entry *ord_entry = ord_namelist->GetFirstEntry(); + BitMap *new_bitmap; + int index(0); + while(ord_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the bitmap pageName + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + ++index; + CString ord_bitmap_name = ord_entry->GetChar(); + new_bitmap = new BitMap(notation_file, ord_bitmap_name); + + Register_Object(new_bitmap); + ordinalBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~ + // Increment the index + //~~~~~~~~~~~~~~~~~~~~ + // + ord_entry = ord_entry->GetNextEntry(); + } + + Unregister_Object(ord_namelist); + delete ord_namelist; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadTeamBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load team bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the team names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *team_namelist = notation_file->MakeEntryList("teams", "team"); + if (!team_namelist) + { + return; + } + Register_Object(team_namelist); + NameList::Entry *team_entry = team_namelist->GetFirstEntry(); + BitMap *new_bitmap; + int index(0); + while(team_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the team pageName + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString team_name = team_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Team Bitmap Page Name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char *team_bitmap_name; + notation_file->GetEntry( + team_name, + "bitmap", + &team_bitmap_name + ); + // + //~~~~~~~~~~~~~~~~~~ + // Create the bitMap + //~~~~~~~~~~~~~~~~~~ + // + new_bitmap = new BitMap(notation_file, team_bitmap_name); + Register_Object(new_bitmap); + teamBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~ + // Increment the index + //~~~~~~~~~~~~~~~~~~~~ + // + ++index; + team_entry = team_entry->GetNextEntry(); + } + Unregister_Object(team_namelist); + delete team_namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadNameBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load name bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the large bitmap names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *large_namelist = notation_file->MakeEntryList("largebitmap", "bitmap"); + if (!large_namelist) + { + Warn("No Large NameBitmaps in Egg \n"); + return; + } + Register_Object(large_namelist); + NameList::Entry *large_entry = large_namelist->GetFirstEntry(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the small bitmap names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *small_namelist = notation_file->MakeEntryList("smallbitmap", "bitmap"); + if (!small_namelist) + { + Warn("No Small NameBitmaps in Egg \n"); + return; + } + Register_Object(small_namelist); + NameList::Entry *small_entry = small_namelist->GetFirstEntry(); + + BitMap *new_bitmap; + CString large_bitmap_name, small_bitmap_name; + int index(0); + while(large_entry && small_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the large Name bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ++index; + large_bitmap_name = large_entry->GetChar(); + new_bitmap = new BitMap(notation_file, large_bitmap_name); + Register_Object(new_bitmap); + largeNameBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the small Name bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + small_bitmap_name = small_entry->GetChar(); + new_bitmap = new BitMap(notation_file, small_bitmap_name); + Register_Object(new_bitmap); + smallNameBitmapChain.AddValue(new_bitmap, index); + + small_entry = small_entry->GetNextEntry(); + large_entry = large_entry->GetNextEntry(); + } + + Unregister_Object(large_namelist); + delete large_namelist; + + Unregister_Object(small_namelist); + delete small_namelist; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mission::LoadLandmarkBitmaps(NotationFile *notation_file) +{ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Load Landmark bitmaps from egg +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(notation_file); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make an entrylist of all the landmark names + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + NameList *landmark_namelist = notation_file->MakeEntryList("landmarks", "landmark"); + if (!landmark_namelist) + { + return; + } + Register_Object(landmark_namelist); + NameList::Entry *landmark_entry = landmark_namelist->GetFirstEntry(); + BitMap *new_bitmap; + int index(0); + while(landmark_entry) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the landmark pageName + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString landmark_name = landmark_entry->GetChar(); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the landmark Bitmap Page Name + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char *landmark_bitmap_name; + notation_file->GetEntry( + landmark_name, + "bitmap", + &landmark_bitmap_name + ); + // + //~~~~~~~~~~~~~~~~~~ + // Create the bitMap + //~~~~~~~~~~~~~~~~~~ + // + new_bitmap = new BitMap(notation_file, landmark_bitmap_name); + Register_Object(new_bitmap); + landmarkBitmapChain.AddValue(new_bitmap, index); + // + //~~~~~~~~~~~~~~~~~~~~ + // Increment the index + //~~~~~~~~~~~~~~~~~~~~ + // + ++index; + landmark_entry = landmark_entry->GetNextEntry(); + } + Unregister_Object(landmark_namelist); + delete landmark_namelist; +} + + +// +//############################################################################# +//############################################################################# +// +Mission::Mission( + NotationFile *notation_file, + ResourceFile *resources +): + missionHostSocket(NULL), + largeNameBitmapChain(NULL, True), + smallNameBitmapChain(NULL, True), + ordinalBitmapChain(NULL, True), + teamBitmapChain(NULL, True), + landmarkBitmapChain(NULL, True), + scenarioRoleChain(NULL, True) +{ + Check(notation_file); + Check(resources); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // NULL out All allocated variables + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + colorName = NULL; + badgeName = NULL; + dropZoneName = NULL; + gameModel = NULL; + missionTime = NULL; + missionWeather = NULL; + scenarioName = NULL; + positionName = NULL; + // + //----------------- + // Get the map name + //----------------- + // + Logical ret; + const char *map_name; + + ret = notation_file->GetEntry("mission", "map", &map_name); + if (!ret) + { + DEBUG_STREAM << "ERROR: no map in egg!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + // + //----------------------- + // Get the mission length + //----------------------- + // + gameLength = 0.0; + notation_file->GetEntry("mission", "length", &gameLength); + + // + //------------------------ + // Get the map resource id + //------------------------ + // + ResourceDescription *map = + resources->FindResourceDescription( + map_name, + ResourceDescription::MakeMessageStreamResourceType + ); + if (!map) + { + DEBUG_STREAM << "ERROR: Couldn't find map in resource file!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + Check(map); + mapID = map->resourceID; + + // + //---------------------------------- + // Get the existance map resource id + //---------------------------------- + // + map = + resources->FindResourceDescription( + map_name, + ResourceDescription::ExistanceBoxStreamResourceType + ); + if (!map) + { + DEBUG_STREAM << "ERROR: Couldn't find existance map in resource file!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + Check(map); + existanceMapID = map->resourceID; + + // + //--------------------------------------------- + // Get the mission time, weather, and scenario + //-------------------------------------------- + // + const char *mission_time; + const char *mission_weather; + const char *mission_scenario; + + ret = notation_file->GetEntry("mission", "time", &mission_time); + if (!ret) + { + DEBUG_STREAM << "ERROR: no time in egg!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + ret = notation_file->GetEntry("mission", "weather", &mission_weather); + if (!ret) + { + DEBUG_STREAM << "ERROR: no weather in egg!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + ret = notation_file->GetEntry("mission", "scenario", &mission_scenario); + if (!ret) + { + DEBUG_STREAM << "ERROR: no scenario in egg!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + int length; + + length = strlen(mission_time) + 1; + missionTime = new char[length]; + Register_Pointer(missionTime); // safer to register BEFORE using + Str_Copy(missionTime, mission_time, length); + + length = strlen(mission_weather) + 1; + missionWeather = new char[length]; + Register_Pointer(missionWeather); // safer to register BEFORE using + Str_Copy(missionWeather, mission_weather, length); + + length = strlen(mission_scenario) + 1; + scenarioName = new char[length]; + Register_Pointer(scenarioName); // safer to register BEFORE using + Str_Copy(scenarioName, mission_scenario, length); + + // + //-------------------------- + // Get the mission host data + //-------------------------- + // + NameList *entry_list; + NameList::Entry *entry; + + playerCount = 0; + entry_list = notation_file->MakeEntryList("pilots", "pilot"); + Register_Object(entry_list); + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + + // + // Get the host address character string + // + char *host_address_pointer = entry->GetChar(); + Check_Pointer(host_address_pointer); + + // + // Create the host address string + // + CString host_address_string(host_address_pointer); + Check(&host_address_string); + + // + // Get the host type + // + int host_type; + + ret = notation_file->GetEntry( + host_address_pointer, + "hostType", + &host_type + ); + if (!ret) + { + DEBUG_STREAM << "ERROR: no host type in egg!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + // + // Create the mission host data + // + MissionHostData *mission_host_data; + + mission_host_data = + new MissionHostData( + host_address_string, + (HostType)host_type + ); + Register_Object(mission_host_data); + + // + // Add to the host socket + // + missionHostSocket.Add(mission_host_data); + ++playerCount; + + entry = entry->GetNextEntry(); + } + #if DEBUG_LEVEL>0 + SChainIteratorOf iterator(&missionHostSocket); + Check(&iterator); + Verify(iterator.GetSize() > 0); + #endif + Unregister_Object(entry_list); + delete entry_list; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Load all the Bitmaps from the Notation File + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + LoadOrdinalBitmaps(notation_file); + LoadNameBitmaps(notation_file); + //LoadTeamBitmaps(notation_file); + //LoadLandmarkBitmaps(notation_file); + + positionName = NULL; +} + +// +//############################################################################# +//############################################################################# +// +Mission::~Mission() +{ + Check(this); + + // + // Delete mission host data + // + SChainIteratorOf iterator(&missionHostSocket); + Check(&iterator); + iterator.DeletePlugs(); + + // + // Delete the text fields + // + if (gameModel) + { + Unregister_Pointer(gameModel); + delete[] gameModel; + } + if (dropZoneName) + { + Unregister_Pointer(dropZoneName); + delete[] dropZoneName; + } + if (colorName) + { + Unregister_Pointer(colorName); + delete[] colorName; + } + if (badgeName) + { + Unregister_Pointer(badgeName); + delete[] badgeName; + } + if (positionName) + { + Unregister_Pointer(positionName); + delete[] positionName; + } + if (missionTime) + { + Unregister_Pointer(missionTime); + delete[] missionTime; + } + if (missionWeather) + { + Unregister_Pointer(missionWeather); + delete[] missionWeather; + } + if (scenarioName) + { + Unregister_Pointer(scenarioName); + delete[] scenarioName; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // delete all the bitmaps + //~~~~~~~~~~~~~~~~~~~~~~~ + // + VChainIteratorOf small_iterator(smallNameBitmapChain); + small_iterator.DeletePlugs(); + + VChainIteratorOf large_iterator(largeNameBitmapChain); + large_iterator.DeletePlugs(); + + VChainIteratorOf ordinal_iterator(ordinalBitmapChain); + ordinal_iterator.DeletePlugs(); + + VChainIteratorOf team_iterator(teamBitmapChain); + team_iterator.DeletePlugs(); + + VChainIteratorOf landmark_iterator(landmarkBitmapChain); + landmark_iterator.DeletePlugs(); + + + VChainIteratorOf role_iterator(scenarioRoleChain); + role_iterator.DeletePlugs(); +} + +// +//############################################################################# +//############################################################################# +// +void + Mission::SetPlayerData( + NotationFile * //notation_file + ) +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Mission::TestInstance() const +{ + Check(&missionHostSocket); + return True; +} + +//############################################################################# +//###################### Mission_HostIterator ########################### +//############################################################################# + +Mission_HostIterator::Mission_HostIterator(Mission *mission): + SChainIteratorOf(&mission->missionHostSocket) +{ +} + +Mission_HostIterator::~Mission_HostIterator() +{ +} diff --git a/MUNGA/MISSION.h b/MUNGA/MISSION.h new file mode 100644 index 0000000..32becbf --- /dev/null +++ b/MUNGA/MISSION.h @@ -0,0 +1,274 @@ +#pragma once + +#include "cstr.h" +#include "schain.h" +#include "vchain.h" +#include "resource.h" +#include "host.h" +#include "scnrole.h" + +class BitMap; + +//########################################################################## +//####################### MissionHostData ############################ +//########################################################################## + +class MissionHostData : public Plug +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction +// +public: + MissionHostData(const CString &address_string, HostType host_type); + virtual ~MissionHostData(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +public: + CString GetAddressString() { return addressString; } + HostType GetHostType() { return hostType; } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + CString addressString; + HostType hostType; +}; + +//########################################################################## +//########################### Mission ################################ +//########################################################################## + +class Mission SIGNATURED +{ + friend class Mission_HostIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public types +// +public: + typedef Mission_HostIterator HostIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + Mission( + NotationFile *notation_file, + ResourceFile *resources + ); + virtual ~Mission(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Set the player data +// +public: + virtual void + SetPlayerData(NotationFile *notation_file); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +public: + ResourceDescription::ResourceID + GetMapID(); + ResourceDescription::ResourceID + GetExistanceMapID(); + const char* + GetDropZoneName() + {Check(this); return dropZoneName;} + const char* + GetGameModel() + {Check(this); return gameModel;} + Logical + IsDropZoneHost() + {Check(this); return dropZoneHost;} + const char* + GetColorName() + {Check(this); return colorName;} + const char* + GetBadgeName() + {Check(this); return badgeName;} + const char* + GetMissionTime() + {Check(this); return missionTime;} + const char* + GetMissionWeather() + {Check(this); return missionWeather;} + const char* + GetScenarioName() + {Check(this); return scenarioName;} + + int + GetTeamID() + { Check(this); return teamID; } + int + GetPlayerCount() + {Check(this); return playerCount;} + + const char* + GetPositionName() + { Check(this); return positionName; } + + Scalar + GetGameLength() + { Check(this); return gameLength; } + + BitMap* + GetLargeNameBitmap(int index) + { + Check(this); + return largeNameBitmapChain.Find(index); + } + + BitMap* + GetSmallNameBitmap(int index) + { + Check(this); + return smallNameBitmapChain.Find(index); + } + + BitMap* + GetOrdinalBitmap(int index) + { + Check(this); + return ordinalBitmapChain.Find(index); + } + + BitMap* + GetTeamBitmap(int team_index) + { + Check(this); + return teamBitmapChain.Find(team_index); + } + + BitMap* + GetLandmarkBitmap(int landmark_index) + { + Check(this); + return landmarkBitmapChain.Find(landmark_index); + } + + int + GetPlayerBitmapIndex() const + {Check(this); return playerBitmapIndex;} + + ScenarioRole* + GetScenarioRole(const CString &role_name) + { + Check(this); + VChainIteratorOf iterator(scenarioRoleChain); + return iterator.Find(role_name); + } + + void + AddScenarioRole(ScenarioRole *scenario_role) + { + Check(this); + Check(scenario_role); + if (!GetScenarioRole(scenario_role->GetRoleName())) + { + scenarioRoleChain.AddValue(scenario_role, scenario_role->GetRoleName()); + } + #if DEBUG_LEVEL > 0 + else + { + Tell(scenario_role->GetRoleName()); + Warn(" already exists not adding to Mission \n"); + } + #endif + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected data +// +protected: + + ResourceDescription::ResourceID + mapID, + existanceMapID; + SChainOf + missionHostSocket; + char + *colorName, + *badgeName, + *dropZoneName, + *gameModel, + *missionTime, + *missionWeather, + *scenarioName; + + Logical + dropZoneHost; + char + *positionName; + + int + teamID, + playerCount; + + int + playerBitmapIndex; + + VChainOf + scenarioRoleChain; + + VChainOf + largeNameBitmapChain, + smallNameBitmapChain; + + VChainOf + ordinalBitmapChain; + + VChainOf + teamBitmapChain; + + VChainOf + landmarkBitmapChain; + + void + LoadOrdinalBitmaps(NotationFile *notation_file); + + void + LoadNameBitmaps(NotationFile *notation_file); + + void + LoadTeamBitmaps(NotationFile *notation_file); + + void + LoadLandmarkBitmaps(NotationFile *notation_file); + + Scalar + gameLength; +}; + +inline ResourceDescription::ResourceID + Mission::GetMapID() +{ + Check(this); + return mapID; +} + +inline ResourceDescription::ResourceID + Mission::GetExistanceMapID() +{ + Check(this); + return existanceMapID; +} + +//########################################################################## +//##################### Mission_HostIterator ######################### +//########################################################################## + +class Mission_HostIterator: + public SChainIteratorOf +{ +public: + Mission_HostIterator(Mission *mission); + ~Mission_HostIterator(); +}; diff --git a/MUNGA/MODE.cpp b/MUNGA/MODE.cpp new file mode 100644 index 0000000..689221c --- /dev/null +++ b/MUNGA/MODE.cpp @@ -0,0 +1,59 @@ +#include "munga.h" +#pragma hdrstop + +#include "mode.h" + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//############################################################################ +//############################ ModeManager ############################# +//############################################################################ +ModeManager::ModeManager(ModeMask initial_mask) +{ + Check_Pointer(this); + + modeMask = initial_mask; + + Check_Fpu(); +} + +ModeManager::~ModeManager() +{ + Check(this); + Check_Fpu(); +} + +Logical + ModeManager::TestInstance() const +{ + Check_Fpu(); + return True; +} + +Logical + ModeManager::ModeStringLookup( + const char *name, + ModeMask *returned_value + ) +{ + Check(this); + + // There's only one mode value available at this level. + + if (stricmp(name, "ModeAlwaysActive") == 0) + { + *returned_value = ModeManager::ModeAlwaysActive; + Check_Fpu(); + return True; + } + else + { + *returned_value = (ModeMask) 0; + } + Check_Fpu(); + return False; +} diff --git a/MUNGA/MODE.h b/MUNGA/MODE.h new file mode 100644 index 0000000..41b667a --- /dev/null +++ b/MUNGA/MODE.h @@ -0,0 +1,66 @@ +#pragma once + +#include "style.h" + +typedef unsigned long ModeMask; + +class ModeManager SIGNATURED +{ +public: + enum + { + nextModeBit = 0 + }; + enum + { + ModeAlwaysActive = -1L // WARNING! Assumed to be 32 bits!!! + }; + +public: + ModeManager(ModeMask initial_mask); + ~ModeManager(); + + Logical TestInstance() const; + +public: + void AddModeMask(ModeMask mode_mask) + { + Check(this); + previousModeMask = modeMask; + modeMask |= mode_mask; + Check_Fpu(); + } + void RemoveModeMask(ModeMask mode_mask) + { + Check(this); + previousModeMask = modeMask; + modeMask &= ~mode_mask; + Check_Fpu(); + } + void ReplaceModeMask(ModeMask mode_mask) + { + Check(this); + previousModeMask = modeMask; + modeMask = mode_mask; + Check_Fpu(); + } + ModeMask GetModeMask() + { + Check(this); + Check_Fpu(); + return modeMask; + } + + ModeMask GetPreviousModeMask() + { + Check(this); + Check_Fpu(); + return previousModeMask; + } + +public: + virtual Logical ModeStringLookup(const char *name, ModeMask *returned_value); + +protected: + ModeMask modeMask, previousModeMask; +}; diff --git a/MUNGA/MODTOOL.cpp b/MUNGA/MODTOOL.cpp new file mode 100644 index 0000000..a51513e --- /dev/null +++ b/MUNGA/MODTOOL.cpp @@ -0,0 +1,637 @@ +#include "munga.h" +#pragma hdrstop + +#include "tool.h" +#include "fileutil.h" +#include "dropzone.h" +#include "camship.h" +#include "doorfram.h" +#include "eyecandy.h" +#include "explode.h" +#include "gaugalrm.h" +#include "cultural.h" +#include "scnrole.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ApplicationTool::CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(model_class,"CameraShipClassID")) + { + model_resources.subsystemResourceID = + CameraShip::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class,"DoorFrameClassID")) + { + model_resources.subsystemResourceID = + DoorFrame::CreateSubsystemStream( + resource_file, + model_name, + model_file, + directories + ); + } + else if(!stricmp(model_class,"EyeCandyClassID")) + { + model_resources.subsystemResourceID = + EyeCandy::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if(!stricmp(model_class,"ExplosionClassID")) + { + model_resources.gameResourceID = + Explosion::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "CulturalIconClassID")) + { + model_resources.gameResourceID = + CulturalIcon::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + model_resources.damageZoneResourceID = + CulturalIcon::CreateDamageZoneStream( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "LandmarkClassID")) + { + model_resources.gameResourceID = + Landmark::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + model_resources.damageZoneResourceID = + Landmark::CreateDamageZoneStream( + resource_file, + model_name, + model_file, + directories + ); + } + else if(!stricmp(model_class,"ScenarioRoleClassID")) + { + model_resources.gameResourceID = + ScenarioRole::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ApplicationTool::WriteModels( + NotationFile *notation_file, + NotationFile *ops_file, + StreamableResourceFile *file, + const char *model_name, + const ResourceDirectories *resource_directories, + int resource_id + ) +{ + // + //------------------------------------------------ + // If model is already in resource then we're done + //------------------------------------------------ + // + ResourceDescription *res_description = file->FindResourceDescription( + model_name, + ResourceDescription::ModelListResourceType + ); + if (res_description) + { + return True; + } + + // + //---------------------------------------- + // Initialize model data and ops file info + //---------------------------------------- + // + ModelData model; + model.videoResourceID = -1; + model.audioResourceID = -1; + model.collisionID = -1; + model.gameResourceID = -1; + model.subsystemResourceID = -1; + model.controlsMappingsResourceID = -1; + model.skeletonResourceID = -1; + model.damageZoneResourceID = -1; + model.gaugeImageResourceID =-1; + model.gaugeAlarmResourceID =-1; + model.gaugeMissionReviewResourceID =-1; + model.explosionTableResourceID = -1; + + const char *ops_name; + ops_file->GetEntry("resource", "res name", &ops_name); + + // + //------------------------------------------------ + // Find the geometry file and make an entry for it + //------------------------------------------------ + // + model.videoResourceID = + platformTool->CreateModelVideoStreamResource( + file, + model_name, + notation_file, + resource_directories + ); + + // + //-------------------------------------------------- + // Find the audio file and make and entry for it + //-------------------------------------------------- + // + model.audioResourceID = + platformTool->CreateModelAudioStreamResource( + file, + model_name, + notation_file, + resource_directories + ); + + const char *model_class; + if (notation_file->GetEntry("gamedata","class",&model_class)) + { + CreateModelResource( + model, + model_class, + file, + model_name, + notation_file, + resource_directories + ); + } + + // + //---------------------------------------------- + // Find the animations and make entries for them + //---------------------------------------------- + // + + char animation_name[200]; + + if(notation_file->PageExists("animations")) + { + NameList *animationnames = + notation_file->MakeEntryList("animations", "animation"); + Register_Object(animationnames); + NameList::Entry *animationentry = animationnames->GetFirstEntry(); + + while (animationentry) + { + strcpy(animation_name, animationentry->GetChar()); + + char *filename2 = + MakePathedFilename( + resource_directories->animationDirectory, + animation_name + ); + Register_Pointer(filename2); + + if(verboseMode) + { + Tell("Opening Animation : " << filename2 << std::endl); + } + + NotationFile *new_notation_file = new NotationFile(filename2); + Register_Object(new_notation_file); + + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + const char *anim_p = StripExtension(StripDirectory(animation_name)); + const char *temp_pointer = animationentry->GetName(); + + if (new_notation_file->PageCount()) + { + if(strstr(temp_pointer, "transition")) + { + + if (verboseMode) + { + std::cout << "Type Transition" << std::endl; + } + + if (!WriteAnimationTransition(new_notation_file, file, anim_p)) + { + + std::cout << "Error - Animation did not work : " << filename2 << std::endl; + + } + } + else + { + if(verboseMode) + { + std::cout << "Type Cycle" << std::endl; + } + if (!WriteAnimationCycle(new_notation_file, file, anim_p)) + { + + std::cout << "Error - Animation did not work : " << filename2 << std::endl; + + } + } + } + else + { + std::cout << filename2 << " does not exist " << std::endl; + } + + Unregister_Pointer(filename2); + delete filename2; + + Unregister_Object(new_notation_file); + delete new_notation_file; + + animationentry = animationentry->GetNextEntry(); + } + + Unregister_Object(animationnames); + delete animationnames; + + } + + // + //-------------------------------------------------- + // Find the collision file and make and entry for it + //-------------------------------------------------- + // + const char *entry_data; + if (notation_file->GetEntry("collision","name",&entry_data)) + { + Check_Pointer(entry_data); + + Logical convert_boxes = False; + const char *dummy; + + if (notation_file->GetEntry("collision","convertboxes",&dummy)) + { + convert_boxes = True; + } + else if (!stricmp(model_class, "LandmarkClassID")) + { + convert_boxes = True; + } + else if(!stricmp(model_class,"CulturalIconClassID")) + { + convert_boxes = True; + } + + + model.collisionID = + BoxedSolidResource::CreateBoxedSolidStream( + entry_data, + file, + resource_directories, + convert_boxes + ); + } + + // + //------------------------------------------------------------------- + // Find the controls mapping page and build a list of all the control + // mappings there + //------------------------------------------------------------------- + // + if (notation_file->PageExists("ControlMappings")) + { + NameList *mapping_list = notation_file->MakeEntryList("ControlMappings"); + Register_Object(mapping_list); + NameList::Entry *entry = mapping_list->GetFirstEntry(); + + // + //----------------------------------------------------------------------- + // Count the number of mapping files, and build a list big enough to hold + // all of the mappings + //----------------------------------------------------------------------- + // + int count=0; + while (entry) + { + ++count; + entry = entry->GetNextEntry(); + } + if (!count) + { + Unregister_Object(mapping_list); + delete mapping_list; + goto Make_Directory; + } + ResourceDescription::ResourceID *mappings = + new ResourceDescription::ResourceID[count]; + Register_Pointer(mappings); + + // + //------------------------------------------------------------------- + // Step through the list, reading each of the specified control files + //------------------------------------------------------------------- + // + entry = mapping_list->GetFirstEntry(); + count = 0; + while (entry) + { + mappings[count] = -1; + char *ctl_filename = + MakePathedFilename( + resource_directories->modelDirectory, + entry->GetChar() + ); + Register_Pointer(ctl_filename); + + NotationFile *ctl_file = new NotationFile(ctl_filename); + Register_Object(ctl_file); + if (!ctl_file->PageCount()) + { + std::cout << model_name << " unable to open " << ctl_filename << "!\n"; +Unwind_1: + Unregister_Object(ctl_file); + delete ctl_file; + Unregister_Pointer(ctl_filename); + delete[] ctl_filename; + Unregister_Pointer(mappings); + delete[] mappings; + Unregister_Object(mapping_list); + delete mapping_list; + goto Make_Directory; + } + + // + //----------------------------- + // Find out which model to call + //----------------------------- + // + mappings[count] = + CreateControlMappingStream( + model_class, + entry->GetName(), + ctl_file, + file, + model_name, + notation_file, + resource_directories, + platformTool + ); + if (mappings[count] == -1) + { + std::cout << model_name << " unable to process " << entry->GetName() + << " control mapping!\n"; + goto Unwind_1; + } + Unregister_Object(ctl_file); + delete ctl_file; + Unregister_Pointer(ctl_filename); + delete[] ctl_filename; + ++count; + entry = entry->GetNextEntry(); + } + + res_description = file->AddResourceList( + model_name, + ResourceDescription::ControlMappingsListResourceType, + 1, + ResourceDescription::LoadOnDemandFlag, + mappings, + count + ); + + + Verify(res_description); + model.controlsMappingsResourceID = res_description->resourceID; + Unregister_Object(mapping_list); + Unregister_Pointer(mappings); + delete mapping_list; + delete[] mappings; + } + // + //------------------------------------------------------------------- + // Find the gaugeMissionReview page and save the pertinent data + //------------------------------------------------------------------- + // + model.gaugeMissionReviewResourceID = + platformTool->CreateModelGaugeMissionReviewStreamResource( + file, + model_name, + notation_file, + resource_directories + ); + // + //----------------------------------------------- + // Find GaugeImage File and make an entry for it + //----------------------------------------------- + // + model.gaugeImageResourceID = + platformTool->CreateModelGaugeImageStreamResource( + file, + model_name, + notation_file, + resource_directories + ); + // + //------------------------------------------------ + // Find Gauge alarm file and make an entry for it + //------------------------------------------------ + // + { + GaugeAlarmManager + *gaugeAlarmManager = platformTool->gaugeAlarmManager; + + if (gaugeAlarmManager == NULL) + { + model.gaugeAlarmResourceID = -1; + } + else + { + Check(gaugeAlarmManager); + + model.gaugeAlarmResourceID = + gaugeAlarmManager->CreateModelGaugeAlarmStreamResource( + file, + model_name, + notation_file, + resource_directories + ); + } + } + // + //------------------------------------------- + // Make a directory for the model information + //------------------------------------------- + // +Make_Directory: + int *model_data = new int[20]; + Register_Pointer(model_data); + int i = 0; + if (model.videoResourceID >= 0) + { + model_data[i++] = model.videoResourceID; + } + if (model.audioResourceID >= 0) + { + model_data[i++] = model.audioResourceID; + } + if (model.collisionID >= 0) + { + model_data[i++] = model.collisionID; + } + if (model.gameResourceID >= 0) + { + model_data[i++] = model.gameResourceID; + } + if (model.subsystemResourceID >= 0) + { + model_data[i++] = model.subsystemResourceID; + } + if (model.skeletonResourceID >= 0) + { + model_data[i++] = model.skeletonResourceID; + } + if (model.controlsMappingsResourceID >= 0) + { + model_data[i++] = model.controlsMappingsResourceID; + } + if (model.damageZoneResourceID >= 0) + { + model_data[i++] = model.damageZoneResourceID; + } + if (model.gaugeImageResourceID >= 0) + { + model_data[i++] = model.gaugeImageResourceID; + } + if (model.gaugeAlarmResourceID >= 0) + { + model_data[i++] = model.gaugeAlarmResourceID; + } + if (model.gaugeMissionReviewResourceID >= 0) + { + model_data[i++] = model.gaugeMissionReviewResourceID; + } + if (model.explosionTableResourceID >= 0) + { + model_data[i++] = model.explosionTableResourceID; + } + + res_description = + file->FindResourceDescription( + model_name, + ResourceDescription::ModelListResourceType + ); + + if (!res_description) + { + if (i > 0) + { + if (resource_id == -1) + { + file->AddResourceList( + model_name, + ResourceDescription::ModelListResourceType, + 1, + ResourceDescription::Preload, + model_data, + i + ); + } + else + { + + ResourceDescription + *res_des = file->FindResourceDescription(resource_id); + + if (!res_des) + { + file->AddResourceList( + model_name, + ResourceDescription::ModelListResourceType, + 1, + ResourceDescription::Preload, + model_data, + i, + resource_id + ); + } + else + { + DEBUG_STREAM << model_name << " : " << resource_id << std::endl << std::flush; + Fail("Duplicate Resource Number"); + } + } + } + else + { + if (resource_id == -1) + { + file->AddResource( + model_name, + ResourceDescription::ModelListResourceType, + 1, + ResourceDescription::Preload, + &i, + sizeof(i) + ); + } + else + { + ResourceDescription + *res_des = file->FindResourceDescription(resource_id); + + if (!res_des) + { + file->AddResource( + model_name, + ResourceDescription::ModelListResourceType, + 1, + ResourceDescription::Preload, + &i, + sizeof(i), + resource_id + ); + } + else + { + DEBUG_STREAM << model_name << " : " << resource_id << std::endl << std::flush; + Fail("Duplicate Resource Number"); + } + } + } + } + Unregister_Pointer(model_data); + delete model_data; + return True; +} diff --git a/MUNGA/MOTION.cpp b/MUNGA/MOTION.cpp new file mode 100644 index 0000000..2555ee4 --- /dev/null +++ b/MUNGA/MOTION.cpp @@ -0,0 +1,78 @@ +#include "munga.h" +#pragma hdrstop + +#include "motion.h" + +const Motion Motion::Identity(Vector3D::Identity, Vector3D::Identity); + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const volatile Motion *) + { + return False; + } +#endif + +Motion::Motion(const Motion& motion) +{ + Check_Pointer(this); + Check(&motion); + + angularMotion = motion.angularMotion; + linearMotion = motion.linearMotion; +} + +// +//########################################################################### +//########################################################################### +// +Motion& Motion::operator=(const Motion &motion) +{ + Check_Pointer(this); + Check(&motion); + + angularMotion = motion.angularMotion; + linearMotion = motion.linearMotion; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical Motion::operator==(const Motion &motion) const +{ + Check(this); + return (memcmp(this, &motion, sizeof(Motion)) == 0); +} + +// +//########################################################################### +//########################################################################### +// +Motion& Motion::AddScaled(const Motion& source, const Motion& delta, Scalar t) +{ + Check_Pointer(this); + Check(&source); + Check(&delta); + Verify(t >= 0.0f); + + linearMotion.AddScaled(source.linearMotion, delta.linearMotion, t); + angularMotion.AddScaled(source.angularMotion, delta.angularMotion, t); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +std::ostream& operator<<(std::ostream& stream, const Motion& p) +{ + return stream << '{' << p.linearMotion << ',' << p.angularMotion << '}'; +} + +// +//########################################################################### +//########################################################################### +// +Logical Motion::TestInstance() const +{ + return angularMotion.TestInstance(); +} diff --git a/MUNGA/MOTION.h b/MUNGA/MOTION.h new file mode 100644 index 0000000..379bb48 --- /dev/null +++ b/MUNGA/MOTION.h @@ -0,0 +1,53 @@ +#pragma once + +#include "vector3d.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Motion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Motion +{ + public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Motion *); + #endif + + Vector3D linearMotion; + Vector3D angularMotion; + + static const Motion Identity; + + // + // Constructors + // + Motion() {} + Motion(const Motion& motion); + Motion(const Vector3D& t, const Vector3D& q) + { + Check(&t); + Check(&q); + linearMotion = t; + angularMotion = q; + } + + // + // Assignment operators + // + Motion& operator=(const Motion& p); + + // + // Equality operator + // + Logical operator==(const Motion&) const; + + // + // Origin motion + // + Motion& AddScaled(const Motion& source, const Motion& delta, Scalar t); + + // + // Support functions + // + friend std::ostream& operator<<(std::ostream& stream, const Motion& p); + Logical TestInstance() const; + static Logical TestClass(); +}; diff --git a/MUNGA/MOVER.cpp b/MUNGA/MOVER.cpp new file mode 100644 index 0000000..cb1a062 --- /dev/null +++ b/MUNGA/MOVER.cpp @@ -0,0 +1,2084 @@ +#include "munga.h" +#pragma hdrstop + +#include "mover.h" +#include "player.h" +#include "boxsolid.h" +#include "interest.h" +#include "collasst.h" +#include "doorfram.h" +#include "door.h" +#include "line.h" +#include "app.h" +#include "notation.h" + +//############################################################################# +//############################### Mover ################################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Mover::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(), "Mover"); + return &classDerivations; +} + +Mover::SharedData + Mover::DefaultData( + Mover::GetClassDerivations(), + Mover::GetMessageHandlers(), + Mover::GetAttributeIndex(), + Mover::StateCount, + (Entity::MakeHandler)Mover::Make + ); + +//############################################################################# +// Message Support +// +#if 0 +const Receiver::HandlerEntry + Mover::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Mover, Update) +}; + +Entity::MessageHandlerSet + Mover::MessageHandlers( + ELEMENTS(Mover::MessageHandlerEntries), + Mover::MessageHandlerEntries, + Entity::GetMessageHandlers() + ); +#endif + +//############################################################################# +// Attribute Support +// +const Mover::IndexEntry + Mover::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Mover, LocalVelocity, localVelocity), + ATTRIBUTE_ENTRY(Mover, LocalAcceleration, localAcceleration), + ATTRIBUTE_ENTRY(Mover, WorldLinearVelocity, worldLinearVelocity), + ATTRIBUTE_ENTRY(Mover, WorldLinearAcceleration, worldLinearAcceleration), + ATTRIBUTE_ENTRY(Mover, MoverMass, moverMass), + ATTRIBUTE_ENTRY(Mover, MomentOfInertia, momentOfInertia), + ATTRIBUTE_ENTRY( + Mover, + PositiveLinearDragCoefficients, + positiveLinearDragCoefficients + ), + ATTRIBUTE_ENTRY( + Mover, + NegativeLinearDragCoefficients, + negativeLinearDragCoefficients + ), + ATTRIBUTE_ENTRY(Mover, AngularDragCoefficients, angularDragCoefficients), + ATTRIBUTE_ENTRY(Mover, FrictionCoefficient, frictionCoefficient), + ATTRIBUTE_ENTRY(Mover, ElasticityCoefficient, elasticityCoefficient), + ATTRIBUTE_ENTRY(Mover, MinimumBounceSpeed, minimumBounceSpeed) +}; + +Mover::AttributeIndexSet& Mover::GetAttributeIndex() +{ + static Mover::AttributeIndexSet attributeIndex(ELEMENTS(Mover::AttributePointers), + Mover::AttributePointers, + Entity::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::UpdateWorldMotion() +{ + Check(this); + + // + //--------------------------------------------------- + // Move the accelerations back into world coordinates + //--------------------------------------------------- + // + worldLinearAcceleration.Multiply( + localAcceleration.linearMotion, + localToWorld + ); + worldLinearVelocity.Multiply( + localVelocity.linearMotion, + localToWorld + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::UpdateLocalMotion() +{ + Check(this); + localVelocity.linearMotion.MultiplyByInverse( + worldLinearVelocity, + localToWorld + ); + localAcceleration.linearMotion.MultiplyByInverse( + worldLinearAcceleration, + localToWorld + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyWorldAccelerations(Scalar time_slice) +{ + Check(this); + Verify(time_slice > 0.0f); + + // + //-------------------------------------------------- + // Calculate the new position as p += v*t + a*.5*t*t + //-------------------------------------------------- + // + Scalar + half_t_squared = 0.5f * time_slice * time_slice; + Vector3D + position_delta; + position_delta.Multiply(worldLinearAcceleration, half_t_squared); + Check_Fpu(); + + position_delta.AddScaled( + position_delta, + worldLinearVelocity, + time_slice + ); + Check_Fpu(); + + localOrigin.linearPosition.Add(localOrigin.linearPosition, position_delta); + Check_Fpu(); + + position_delta.Multiply(localAcceleration.angularMotion, half_t_squared); + Check_Fpu(); + + position_delta.AddScaled( + position_delta, + localVelocity.angularMotion, + time_slice + ); + Check_Fpu(); + + Quaternion + old_position = localOrigin.angularPosition; + localOrigin.angularPosition.Add(old_position, position_delta); + Check_Fpu(); + // + //----------------------------------- + // Calculate our velocity as v += a*t + //----------------------------------- + // + worldLinearVelocity.AddScaled( + worldLinearVelocity, + worldLinearAcceleration, + time_slice + ); + Check_Fpu(); + localVelocity.angularMotion.AddScaled( + localVelocity.angularMotion, + localAcceleration.angularMotion, + time_slice + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::CalculateDrag( + Vector3D *drag, + const Vector3D &velocity, + const Vector3D &positive_CODs, + const Vector3D &negative_CODs, + Scalar power + ) +{ + Environment *air = GetEnvironment(); + Check(air); + Vector3D temp,temp2; + temp.MultiplyByInverse(air->GetWindVelocity(), localToWorld); + temp += velocity; + + if (temp.x < 0.0f) + { + drag->x = negative_CODs.x; + temp2.x = Power(-temp.x, power); + Check_Fpu(); + } + else + { + drag->x = -positive_CODs.x; + temp2.x = Power(temp.x, power); + Check_Fpu(); + } + + if (temp.y < 0.0f) + { + drag->y = negative_CODs.y; + temp2.y = Power(-temp.y, power); + Check_Fpu(); + } + else + { + drag->y = -positive_CODs.y; + temp2.y = Power(temp.y, power); + Check_Fpu(); + } + + if (temp.z < 0.0f) + { + drag->z = negative_CODs.z; + temp2.z = Power(-temp.z, power); + Check_Fpu(); + } + else + { + drag->z = -positive_CODs.z; + temp2.z = Power(temp.z, power); + Check_Fpu(); + } + + *drag *= air->airDensity; + drag->Multiply(*drag, temp2); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyAirResistanceAndGravity(Scalar power) +{ + Check(this); + + // + //------------------------------------------------------------------------- + // Apply drag to the system, allowing for different drag numbers based upon + // the direction of motion along the axis + //------------------------------------------------------------------------- + // + Vector3D acceleration; + CalculateDrag( + &acceleration, + localVelocity.linearMotion, + positiveLinearDragCoefficients, + negativeLinearDragCoefficients, + power + ); + localAcceleration.linearMotion += acceleration; + + acceleration.Multiply(angularDragCoefficients, localVelocity.angularMotion); + localAcceleration.angularMotion -= acceleration; + + // + //--------------------------- + // Apply gravity to the craft + //--------------------------- + // + UpdateWorldMotion(); + worldLinearAcceleration.y -= GetEnvironment()->gravityConstant; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyLocalForce( + const Vector3D &force, + const Vector3D &moment + ) +{ + Check(this); + Check(&force); + Check(&moment); + + Vector3D acceleration; + Verify(!Small_Enough(moverMass)); + acceleration.Divide(force, moverMass); + ApplyLocalAcceleration(acceleration, moment); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ApplyLocalAcceleration( + const Vector3D &acceleration, + const Vector3D &moment + ) +{ + Check(this); + Check(&acceleration); + Check(&moment); + + localAcceleration.linearMotion += acceleration; + Vector3D torque; + torque.Cross(moment, acceleration); + torque *= momentOfInertia; + localAcceleration.angularMotion += torque; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::NoDeadReckoner() +{ + Check(this); + + // + //------------------------------------------------------------------------- + // If we are the replicant instance and we are not yet past the anticipated + // time for the next event, project out to the next event + //------------------------------------------------------------------------- + // + projectedOrigin = updateOrigin; + Check_Fpu(); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::LinearDeadReckoner() +{ + Check(this); + Logical lerp_mode; + Scalar time_slice; + + // + //------------------------------------------------------------------------- + // If we are the replicant instance and we are not yet past the anticipated + // time for the next event, project out to the next event + //------------------------------------------------------------------------- + // + if (GetInstance() == ReplicantInstance && lastPerformance < nextUpdate) + { + time_slice = nextUpdate - lastUpdate; + lerp_mode = True; + } + else + { + time_slice = lastPerformance - lastUpdate; + lerp_mode = False; + } + + // + //--------------------------------------- + // Calculate the new position as p += v*t + //--------------------------------------- + // + Vector3D position_delta; + position_delta.Multiply(updateVelocity.linearMotion, time_slice); + projectedOrigin.linearPosition.Add( + updateOrigin.linearPosition, + position_delta + ); + + // + //------------------------------- + // Handle projecting the rotation + //------------------------------- + // + position_delta.Multiply(updateVelocity.angularMotion, time_slice); + projectedOrigin.angularPosition.Add( + updateOrigin.angularPosition, + position_delta + ); + projectedVelocity = updateVelocity; + + Check_Fpu(); + return lerp_mode; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::AcceleratedDeadReckoner() +{ + Check(this); + Logical lerp_mode; + Scalar time_slice; + + // + //------------------------------------------------------------------------- + // If we are the replicant instance and we are not yet past the anticipated + // time for the next event, project out to the next event + //------------------------------------------------------------------------- + // + if (GetInstance() == ReplicantInstance && lastPerformance < nextUpdate) + { + time_slice = nextUpdate - lastUpdate; + lerp_mode = True; + } + else + { + time_slice = lastPerformance - lastUpdate; + lerp_mode = False; + } + + // + //-------------------------------------------------- + // Calculate the new position as p += v*t + a*.5*t*t + //-------------------------------------------------- + // + Scalar half_t_squared = 0.5f * time_slice * time_slice; + Vector3D position_delta; + position_delta.Multiply(updateAcceleration.linearMotion, half_t_squared); + position_delta.AddScaled( + position_delta, + updateVelocity.linearMotion, + time_slice + ); + projectedOrigin.linearPosition.Add( + updateOrigin.linearPosition, + position_delta + ); + + // + //------------------------------- + // Handle projecting the rotation + //------------------------------- + // + position_delta.Multiply(updateAcceleration.angularMotion, half_t_squared); + position_delta.AddScaled( + position_delta, + updateVelocity.angularMotion, + time_slice + ); + projectedOrigin.angularPosition.Add( + updateOrigin.angularPosition, + position_delta + ); + + // + //----------------------------------- + // Calculate our velocity as v += a*t + //----------------------------------- + // + if (GetInstance() == ReplicantInstance) + { + projectedVelocity.linearMotion.AddScaled( + updateVelocity.linearMotion, + worldLinearAcceleration, + time_slice + ); + projectedVelocity.angularMotion.AddScaled( + updateVelocity.angularMotion, + localAcceleration.angularMotion, + time_slice + ); + } + Check_Fpu(); + return lerp_mode; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::DeadReckon(Scalar time_slice) +{ + Check(this); + + // + //------------------------------ + // Run the chosen dead reckoning + //------------------------------ + // + Verify(GetInstance() == ReplicantInstance); + if (deadReckoner) + { + // + //--------------------------------------------------------------------- + // Merge the projected origin with the current origin if we are in lerp + // mode. If not, just copy the projected origin into the local origin + //--------------------------------------------------------------------- + // + if ((this->*deadReckoner)()) + { + Scalar percent = + time_slice / ((nextUpdate - lastPerformance) + time_slice); + + // + //------------------------------------------ + // Do a spherical lerp on the angular motion + //------------------------------------------ + // + localOrigin.angularPosition.Lerp( + localOrigin.angularPosition, + projectedOrigin.angularPosition, + percent + ); + localVelocity.angularMotion.Lerp( + localVelocity.angularMotion, + projectedVelocity.angularMotion, + percent + ); + + // + //------------------------- + // Spline the linear motion + //------------------------- + // + #if 0 + CubicCurve + spline( + localOrigin.linearPosition, + worldLinearVelocity, + projectedOrigin.linearPosition, + projectedVelocity.linearMotion + ); + spline.Evaluate( + percent, + &localOrigin.linearPosition, + &worldLinearVelocity + ); + #else + localOrigin.linearPosition.Lerp( + localOrigin.linearPosition, + projectedOrigin.linearPosition, + percent + ); + worldLinearVelocity.Lerp( + worldLinearVelocity, + projectedVelocity.linearMotion, + percent + ); + #endif + } + else + { + localOrigin = projectedOrigin; + worldLinearVelocity = projectedVelocity.linearMotion; + localVelocity.angularMotion = projectedVelocity.angularMotion; + } + + // + //---------------------------------------------------- + // Update the collision volume and the local variables + //---------------------------------------------------- + // + if (IsCollisionVolume()) + { + MoveCollisionVolume(); + } + else + { + localToWorld = localOrigin; + } + UpdateLocalMotion(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::PerformAndWatch( + const Time &till, + MemoryStream *update_stream + ) +{ + Check(this); + Check(&till); + + int i; + + // + //-------------------------------------------------------------------------- + // Make sure that the time into the simulations is stable. If a half-second + // delay occurs, or we are in stasis, just bring everything up to date + //-------------------------------------------------------------------------- + // + Scalar time_slice = till - lastPerformance; + if (time_slice < SMALL) + { + Tell("No time!\n"); +Bye_Bye: + WriteSimulationUpdate(update_stream); + return; + } + + if (GetSimulationState() == StasisState || time_slice > 0.5f) + { + lastPerformance = till; + if (GetSimulationState() == StasisState) + { + lastUpdate = till; + } + if (subsystemArray) + { + Check_Pointer(subsystemArray); + for (i=0; iSetLastPerformance(till); + } + } + } + //SetSimulationState(DefaultState); + goto Bye_Bye; + } + + // + //------------------------------------ + // Set up for local motion calculation + //------------------------------------ + // + localVelocity.linearMotion.MultiplyByInverse( + worldLinearVelocity, + localToWorld + ); + localAcceleration = Motion::Identity; + previousOrigin = localOrigin; + + // + //----------------------- + // Process the subsystems + //----------------------- + // + Entity::PerformAndWatch(till, update_stream); + + // + //----------------------------------------------- + // Make sure the position quaternion stays stable + //----------------------------------------------- + // + if (++normalizeCount == 20) + { + localOrigin.angularPosition.Normalize(); + normalizeCount = 0; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ReadUpdateRecord(Simulation::UpdateRecord *record) +{ + Check(this); + Check_Pointer(record); + switch (record->recordID) + { + case DefaultUpdateModelBit: + { + + // + //------------------------------------------- + // HACK - precalculation for next update time + //------------------------------------------- + // + nextUpdate = Now(); + Scalar diff = nextUpdate - lastUpdate; + if (diff < 10.0f) + { + nextUpdate.ticks += nextUpdate.ticks - lastUpdate.ticks; + } + + // + //--------------------------------------- + // Handle updating the entity information + //--------------------------------------- + // + Entity::ReadUpdateRecord(record); + + // + //----------------------- + // Update the motion data + //----------------------- + // + UpdateRecord *update = (UpdateRecord*)record; + + localAcceleration = update->localAcceleration; + worldLinearAcceleration = update->worldLinearAcceleration; + + updateVelocity.linearMotion = update->worldLinearVelocity; + updateVelocity.angularMotion = update->localVelocity.angularMotion; + + updateAcceleration.linearMotion = update->worldLinearAcceleration; + updateAcceleration.angularMotion = update->localAcceleration.angularMotion; + + // + //----------------------------------------- + // Update the collision volume if necessary + //----------------------------------------- + // + if (IsCollisionVolume()) + { + MoveCollisionVolume(); + } + } + break; + + default: + Entity::ReadUpdateRecord(record); + break; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::WriteUpdateRecord( + Simulation::UpdateRecord *record, + int update_model + ) +{ + Check(this); + Check_Pointer(record); + switch (update_model) + { + case DefaultUpdateModelBit: + { + Entity::WriteUpdateRecord(record, update_model); + + UpdateRecord *update = (UpdateRecord*)record; + + update->recordLength = sizeof(*update); + update->localVelocity = localVelocity; + update->localAcceleration = localAcceleration; + + update->worldLinearVelocity = worldLinearVelocity; + update->worldLinearAcceleration = worldLinearAcceleration; + + updateVelocity.linearMotion = worldLinearVelocity; + updateVelocity.angularMotion = localVelocity.angularMotion; + + updateAcceleration.linearMotion = worldLinearAcceleration; + updateAcceleration.angularMotion = localAcceleration.angularMotion; + } + break; + default: + Entity::WriteUpdateRecord(record, update_model); + break; + } + Check_Fpu(); +} + +//############################################################################# +// Collision support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::MoveCollisionVolume() +{ + // + //--------------------------------------------------- + // Make sure that there is a collision volume to move + //--------------------------------------------------- + // + Check(this); + if (!collisionVolumeCount) + { + Check_Fpu(); + return; + } + + // + //------------------------------------------------------------------------ + // Set up the extents of the collision volume from the template and the + // current position. We must find the center point of the template volume + // and rotate it about the y axis + //------------------------------------------------------------------------ + // + Check(collisionTemplate); + Check(collisionVolume); + Verify(collisionVolumeCount == 1); + Verify(collisionTemplate->solidType == BoxedSolid::YAxisCylinderType); + + localToWorld = localOrigin; + Point3D centerPoint; + centerPoint.x = (collisionTemplate->minX + collisionTemplate->maxX) * 0.5f; + centerPoint.y = (collisionTemplate->minY + collisionTemplate->maxY) * 0.5f; + centerPoint.z = (collisionTemplate->minZ + collisionTemplate->maxZ) * 0.5f; + Vector3D radius; + radius.x = collisionTemplate->maxX - centerPoint.x; + radius.y = collisionTemplate->maxY - centerPoint.y; + radius.z = collisionTemplate->maxZ - centerPoint.z; + Point3D rotated; + rotated.Multiply(centerPoint, localToWorld); + + collisionVolume->minX = rotated.x - radius.x; + collisionVolume->maxX = rotated.x + radius.x; + collisionVolume->minY = rotated.y - radius.y; + collisionVolume->maxY = rotated.y + radius.y; + collisionVolume->minZ = rotated.z - radius.z; + collisionVolume->maxZ = rotated.z + radius.z; + + // + //------------------------------------------------------------ + // Now, Find the smallest node containing our collision column + //------------------------------------------------------------ + // + if (GetInstance() != ReplicantInstance) + { + InterestManager *interest_mgr = + application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = + interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + containedByNode = + tree->FindSmallestNodeContainingColumn(*collisionVolume); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolidCollisionList* + Mover::AllocateCollisionList() +{ + Check(this); + + // + //----------------------------------------------------------- + // Find the correct collision list to use, and reset to empty + //----------------------------------------------------------- + // + BoxedSolidCollisionList *collision_list; + if (lastCollisionList == collisionLists) + { + collision_list = &collisionLists[1]; + } + else + { + collision_list = collisionLists; + } + Check(collision_list); + collision_list->Reset(); + return collision_list; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolidCollisionList* + Mover::GetCurrentCollisions(BoxedSolidCollisionList *collision_list) +{ + Check(this); + + if (!collision_list) + { + collision_list = AllocateCollisionList(); + } + Check(collision_list); + + // + //--------------------------------- + // Test against the tangible movers + //--------------------------------- + // + Check(collisionAssistant); + CollisionAssistant::MovingEntityIterator iterator(collisionAssistant); + Entity *entity; + Check(collisionVolume); + while ((entity = iterator.ReadAndNext()) != NULL) + { + // + //------------------------------------------------------------------ + // If we are checking against ourselves, or something more than 50m + // away, skip it + //------------------------------------------------------------------ + // + Check(entity); + if (entity == this) + { + continue; + } + Vector3D delta; + delta.Subtract( + entity->localOrigin.linearPosition, + localOrigin.linearPosition + ); + if (delta.LengthSquared() > 2500.0f) + { + continue; + } + + // + //-------------------------------------------------- + // If we have a mover class object, check against it + //-------------------------------------------------- + // + if (entity->IsDerivedFrom(*Mover::GetClassDerivations())) + { + Mover *mover = (Mover*)entity; + Check(mover); + Check(mover->collisionVolume); + CheckAgainstBoxedSolidChain(collision_list, mover->collisionVolume); + } + + // + //----------------------------------------------------------------------- + // If we have a door, check against its subsystems if we are close enough + // for it to matter + //----------------------------------------------------------------------- + // + else if (entity->IsDerivedFrom(*DoorFrame::GetClassDerivations())) + { + DoorFrame *door_frame = (DoorFrame*)entity; + Check(door_frame); + for (int i=0; iGetSubsystemCount(); ++i) + { + Door *door = (Door*)door_frame->GetSubsystem(i); + CheckAgainstBoxedSolidChain( + collision_list, + door->GetFirstBoxedSolid() + ); + } + } + } + + // + //------------------------------ + // Test against the static world + //------------------------------ + // + containedByNode->FindBoundingBoxesContaining( + collisionVolume, + *collisionVolume, + *collision_list + ); + + Check_Fpu(); + return collision_list; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid* + Mover::FindBoxedSolidHitBy( + Line *line, + Entity *except + ) +{ + Check(this); + Check(line); + + // + //------------------------------------------------------------------------- + // Calculate the midpoint of the line, and sweep a sphere out around the + // line from that point, including an extra 50 meters. This extra distance + // takes into account the doors... + //------------------------------------------------------------------------- + // + Point3D center; + Scalar radius = line->length * 0.5f; + line->Project(radius, ¢er); + + // + //--------------------------------- + // Test against the tangible movers + //--------------------------------- + // + Check(collisionAssistant); + CollisionAssistant::MovingEntityIterator iterator(collisionAssistant); + Entity *entity; + BoxedSolid + *solid = NULL, + *result; + + while ((entity = iterator.ReadAndNext()) != NULL) + { + // + //--------------------------------------------------------------- + // If we are checking against ourselves or the exception, skip it + //--------------------------------------------------------------- + // + Check(entity); + if (entity == this || except && except == entity) + { + continue; + } + + // + //------------------------------------------------------------------- + // If we have a mover class object, check against it. If we have no + // collision volume, we are just using a line, so just run it against + // the collision volume chain + //------------------------------------------------------------------- + // + if (entity->IsDerivedFrom(*Mover::GetClassDerivations())) + { + Mover *mover = (Mover*)entity; + Check(mover); + Check(mover->collisionVolume); + + // + //----------------------------------------------------------------- + // If the mover is close enough to the radius of the line, check it + //----------------------------------------------------------------- + // + Vector3D delta; + delta.Subtract(entity->localOrigin.linearPosition, center); + Scalar r2 = + mover->collisionVolume->maxX - mover->collisionVolume->minX; + r2 += mover->collisionVolume->maxY - mover->collisionVolume->minY; + r2 *= 0.5f; + r2 += radius; + if (delta.LengthSquared() > r2*r2) + { + continue; + } + + result = + CheckLineAgainstBoxedSolidChain(line, mover->collisionVolume); + if (result) + { + Check(result); + solid = result; + } + } + + // + //----------------------------------------------------------------------- + // If we have a door, check against its subsystems if we are close enough + // for it to matter + //----------------------------------------------------------------------- + // + else if (entity->IsDerivedFrom(*DoorFrame::GetClassDerivations())) + { + // + //----------------------------------------------------------------- + // If the mover is close enough to the radius of the line, check it + //----------------------------------------------------------------- + // + Vector3D delta; + delta.Subtract(entity->localOrigin.linearPosition, center); + Scalar r2 = radius + 50.0f; + if (delta.LengthSquared() > r2*r2) + { + continue; + } + + DoorFrame *door_frame = (DoorFrame*)entity; + Check(door_frame); + for (int i=0; iGetSubsystemCount(); ++i) + { + Door *door = (Door*)door_frame->GetSubsystem(i); + result = + CheckLineAgainstBoxedSolidChain( + line, + door->GetFirstBoxedSolid() + ); + if (result) + { + Check(result); + solid = result; + } + } + } + } + + // + //------------------------------ + // Test against the static world + //------------------------------ + // + InterestManager *interest_mgr = application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + result = (BoxedSolid*)tree->FindBoundingBoxHitBy(line); + if (result) + { + Check(result); + solid = result; + } + Check_Fpu(); + return solid; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolidCollisionList* + Mover::CollideCenterOfMotion( + Line *line, + BoxedSolidCollisionList *list + ) +{ + Check(this); + Check(line); + + // + //----------------------------------------------------------- + // Find the correct collision list to use, and reset to empty + //----------------------------------------------------------- + // + if (!list) + { + list = AllocateCollisionList(); + } + Check(list); + + // + //------------------------------------------------------------------------ + // If the length of the line has changed, we must reposition the collision + // volume appropriately + //------------------------------------------------------------------------ + // + BoxedSolid *solid = FindBoxedSolidHitBy(line, NULL); + if (solid && IsCollisionVolume()) + { + line->FindEnd(&localOrigin.linearPosition); + MoveCollisionVolume(); + ExtentBox slice; + slice.Intersect(*collisionVolume, *solid); + Verify(list->GetCollisionsLeft()); + list->AddCollisionToList(solid, slice); + } + + Check_Fpu(); + return list; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ProcessCollisionList( + BoxedSolidCollisionList *collisions, + Scalar time_slice, + const Point3D &old_position, + Damage *damage + ) +{ + Check(this); + Check(collisions); + Verify(time_slice > 0.0f); + Check(&old_position); + Check_Pointer(damage); + + damage->damageAmount = 0.0f; + damage->damageType = Damage::CollisionDamageType; + damage->impactPoint = Point3D::Identity; + + if (collisions->GetCollisionCount()) + { + // + //------------------------------------------------------------------ + // Reduce the number of collisions we have to play with based on our + // velocity + //------------------------------------------------------------------ + // + collisions->ReduceCollisionList(worldLinearVelocity); + + // + //----------------------------------------------------------------- + // Setup up the totaling variables to handle averaging out multiple + // collisions + //----------------------------------------------------------------- + // + int total_collisions = 0; + Vector3D resultant_velocity = Vector3D::Identity; + Point3D resultant_position = Point3D::Identity; + Vector3D resultant_normal = Vector3D::Identity; + Vector3D initial_velocity = worldLinearVelocity; + Vector3D initial_position = localOrigin.linearPosition; + Scalar total_damage = 0.0f; + + // + //--------------------------------------------------------------------- + // For each hit in the list, process it, and if the collision is + // determined to be valid, bounce it and add the result into the others + //--------------------------------------------------------------------- + // + for (int i=0; iGetRealCollisions(); ++i) + { + // + //---------------------------------------------------------- + // Make sure to bounce the vehicle from the correct location + //---------------------------------------------------------- + // + worldLinearVelocity = initial_velocity; + localOrigin.linearPosition = initial_position; + damage->damageAmount = 0.0f; + ProcessCollision( + time_slice, + (*collisions)[i], + old_position, + damage + ); + if (damage->damageAmount > 0.0f) + { + ++total_collisions; + resultant_velocity += worldLinearVelocity; + resultant_position += localOrigin.linearPosition; + resultant_normal += damage->surfaceNormal; + total_damage += damage->damageAmount; + ExtentBox *box = &(*collisions)[i].collisionSlice; + damage->impactPoint.x += 0.5 * + ( + box->minX + box->maxX + - (collisionVolume->minX - collisionVolume->maxX) + ); + damage->impactPoint.y += 0.5 * + ( + box->minY + box->maxY + - (collisionVolume->minY - collisionVolume->maxY) + ); + damage->impactPoint.z += 0.5 * + ( + box->minZ + box->maxZ + - (collisionVolume->minZ - collisionVolume->maxZ) + ); + } + } + + // + //----------------------------------------------------------------- + // If we collided with more than one thing, average out the results + //----------------------------------------------------------------- + // + if (total_collisions > 1) + { + worldLinearVelocity.Divide(resultant_velocity, total_collisions); + localOrigin.linearPosition.Divide( + resultant_position, + total_collisions + ); + damage->surfaceNormal.Vector3D::Divide( + resultant_normal, + total_collisions + ); + goto Figure_Normal; + } + + // + //------------------------------------------------------ + // Otherwise, just set up the positions from the results + //------------------------------------------------------ + // + else if (total_collisions == 1) + { + worldLinearVelocity = resultant_velocity; + localOrigin.linearPosition = resultant_position; + damage->surfaceNormal.operator=(resultant_normal); + + // + //--------------------------------------------------------- + // Figure out the normal, and calculate the collision force + //--------------------------------------------------------- + // +Figure_Normal: + if (Small_Enough(damage->surfaceNormal.LengthSquared())) + { + damage->surfaceNormal.x = 0.0f; + damage->surfaceNormal.y = 1.0f; + damage->surfaceNormal.z = 0.0f; + } + else + { + damage->surfaceNormal.Normalize(damage->surfaceNormal); + } + MoveCollisionVolume(); + damage->damageAmount = total_damage; + damage->damageForce.Subtract(worldLinearVelocity, initial_velocity); + } + lastCollisionList = collisions; + } + else + { + lastCollisionList = NULL; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ) +{ + Check(this); + Verify(time_slice > 0.0f); + Check(&collision); + Check(&old_position); + Check_Pointer(damage); + + Scalar penetration; + + // + //------------------------------------------------------------------------ + // If we really have a collision, do a static bounce off of the normal + // generated. This is default behavior, and any derived class should make + // sure to handle any handshaking that needs to be done + //------------------------------------------------------------------------ + // + if ( + collisionVolume->ProcessCollision( + collision, + worldLinearVelocity, + lastCollisionList, + &damage->surfaceNormal, + &penetration + ) + ) + { + Max_Clamp(penetration, time_slice); + Scalar r = penetration / time_slice; + Scalar elasticity = elasticityCoefficient; + Scalar friction = frictionCoefficient; + + damage->damageAmount = + StaticBounce( + old_position, + time_slice, + r, + damage->surfaceNormal, + &elasticity, + minimumBounceSpeed, + &friction + ); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::StartCollisionAssistant() +{ + Check(this); + Verify(collisionAssistant == NULL); + + collisionAssistant = CollisionAssistant::Make(this); + Register_Object(collisionAssistant); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + Mover::StaticBounce( + const Point3D &, //old_position, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity, + Scalar bounce_min, + Scalar *friction + ) +{ + Check(this); + Check(&normal); + Check_Pointer(elasticity); + Check_Pointer(friction); + + Verify(penetration >= 0.0f && penetration <= 1.0f); + Verify(*elasticity >= 0.0f && *elasticity <= 1.0f); + Verify(*friction >= 0.0f); + Verify(delta_t > SMALL); + +// penetration = 1.0f; // HACK - should keep stuff from going through the floor + + // + //----------------------------------------------------------------------- + // Calculate the impact speed and vectors. If we didn't hit fast enough, + // don't do any bounce + //----------------------------------------------------------------------- + // + Scalar impact = worldLinearVelocity * normal; + Vector3D vn,vp; + vn.Multiply(normal, impact); + vp.Subtract(worldLinearVelocity, vn); + if (impact > 0.0f) + { + Check_Fpu(); + return 0.0f; + } + if (-impact <= bounce_min * delta_t) + { + *elasticity = 0.0f; + } + + // + //-------------------------------------- + // Calculate the energy lost to friction + //-------------------------------------- + // + Scalar resistance = vp.Length(); + if (Small_Enough(resistance)) + { + *friction = resistance = 0.0f; + } + else + { + resistance = + 1.0f + *friction * (1.0f + *elasticity) * impact / resistance; + if (resistance < 0.0f) + { + *friction = resistance = 0.0f; + } + } + + // + //---------------------------------------------------- + // Compute the velocity delta created by the collision + //---------------------------------------------------- + // + Scalar temp = resistance - 1.0f; + Vector3D delta_v; + delta_v.Multiply(worldLinearVelocity, temp); + temp = resistance + *elasticity; + delta_v.AddScaled(delta_v, vn, -temp); + + // + //------------------------------------ + // Figure out the kinetic energy stuff + //------------------------------------ + // + temp = -1.0f - *elasticity; + vn *= temp; + vp.AddScaled(vn, worldLinearVelocity, 2.0f); + + // + // Reflect the velocity vector + // + worldLinearVelocity += delta_v; + temp = penetration * delta_t; + delta_v *= temp; + localOrigin.linearPosition += delta_v; + + // + // Compute the kinetic energy loss + // + Check_Fpu(); + return -0.0005 * (vn * vp) * moverMass; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + Mover::DynamicBounce( + Mover *other, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity + ) +{ + Check(this); + Check(other); + Check(&normal); + Check_Pointer(elasticity); + + Verify(penetration >= 0.0f && penetration <= 1.0f); + Verify(*elasticity >= 0.0f && *elasticity <= 1.0f); + Verify(delta_t > SMALL); + + // + //------------------------------------------------------------------------ + // Get the relative velocity of the other guy, and figure out the velocity + // delta along the normal + //------------------------------------------------------------------------ + // + Scalar k1 = worldLinearVelocity.LengthSquared(); + Scalar k2 = other->worldLinearVelocity.LengthSquared(); + + Scalar mass_ratio = other->moverMass / (moverMass + other->moverMass); + Check_Fpu(); + Vector3D v; + v.Subtract(other->worldLinearVelocity, worldLinearVelocity); + Scalar temp = (1.0f + *elasticity) * (v*normal); + Vector3D delta_v; + delta_v.Multiply(normal, temp); + + // + //------------------------------------------------------------------------- + // Figure out the kinetic energy loss in kilojoules, and bounce the primary + // mover + // + // There was an additional multiplication by mass ratio in system 3 code... + // we should make sure it is really needed... + //------------------------------------------------------------------------- + // + v.AddScaled(delta_v, v, -2.0f); + worldLinearVelocity.AddScaled( + worldLinearVelocity, + delta_v, + mass_ratio + ); + localOrigin.linearPosition.AddScaled( + localOrigin.linearPosition, + delta_v, + delta_t * penetration + ); + + // + //---------------------------------------------------------- + // Bounce the second object, and reset it's update values... + //---------------------------------------------------------- + // + other->worldLinearVelocity.AddScaled( + other->worldLinearVelocity, + delta_v, + mass_ratio - 1.0f + ); + other->localOrigin.linearPosition.AddScaled( + other->localOrigin.linearPosition, + delta_v, + delta_t + ); + other->updateVelocity.linearMotion = other->worldLinearVelocity; + other->updateOrigin.linearPosition = other->localOrigin.linearPosition; + other->lastUpdate = Now(); + + // + //-------------------------------- + // Return the result in kilojoules + //-------------------------------- + // + k1 -= worldLinearVelocity.LengthSquared(); + k2 -= other->worldLinearVelocity.LengthSquared(); + Check_Fpu(); + return 0.0005f * mass_ratio * (moverMass * k1 + other->moverMass * k2); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::CheckAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ) +{ + Check(this); + Check(collisions); + + // + //---------------------------------------------------------------------- + // If the two movers collided against with each other, add the result to + // the collision list + //---------------------------------------------------------------------- + // + while (chain) + { + Check(chain); + ExtentBox slice; + if (chain->Intersects(*collisionVolume, &slice)) + { + Verify(collisions->GetCollisionsLeft()); + collisions->AddCollisionToList(chain, slice); + if (!collisions->GetCollisionsLeft()) + { + return; + } + } + chain = chain->GetNextSolid(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Mover::CheckVolumeAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ) +{ + Check(this); + Check(collisions); + + // + //---------------------------------------------------------------------- + // If the two movers collided against with each other, add the result to + // the collision list + //---------------------------------------------------------------------- + // + while (chain) + { + Check(chain); + ExtentBox slice; + if (chain->Intersects(*collisionVolume, &slice)) + { + Verify(collisions->GetCollisionsLeft()); + collisions->AddCollisionToList(collisionVolume, slice); + if (!collisions->GetCollisionsLeft()) + { + return; + } + } + chain = chain->GetNextSolid(); + } + Check_Fpu(); +} + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +BoxedSolid* + Mover::CheckLineAgainstBoxedSolidChain( + Line *line, + BoxedSolid *chain + ) +{ + Check(this); + Check(line); + + // + //---------------------------------------------------------------------- + // If the two movers collided against with each other, add the result to + // the collision list + //---------------------------------------------------------------------- + // + BoxedSolid *result = NULL; + while (chain) + { + Check(chain); + if (chain->HitBy(line)) + { + result = chain; + } + chain = chain->GetNextSolid(); + } + Check_Fpu(); + return result; +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Mover::Mover( + Mover::MakeMessage *creation_message, + Mover::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + Check_Pointer(this); + Check(creation_message); + + Check(application); + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + + // + //------------------------------ + // Initialize the motion vectors + //------------------------------ + // + localVelocity = creation_message->localVelocity; + localAcceleration = creation_message->localAcceleration; + worldLinearAcceleration.Multiply( + localAcceleration.linearMotion, + localToWorld + ); + worldLinearVelocity.Multiply( + localVelocity.linearMotion, + localToWorld + ); + + updateVelocity.linearMotion = worldLinearVelocity; + updateVelocity.angularMotion = localVelocity.linearMotion; + + updateAcceleration.linearMotion = worldLinearAcceleration; + updateAcceleration.angularMotion = localAcceleration.linearMotion; + nextUpdate = lastUpdate; + + normalizeCount = 0; + if (IsInitialStasis()) + { + SetSimulationState(StasisState); + } + + collisionVolume = NULL; + collisionTemplate = NULL; + containedByNode = NULL; + collisionLists = NULL; + lastCollisionList = NULL; + collisionAssistant = NULL; + deadReckoner = NULL; + collisionVolumeCount = 0; + + ResourceDescription *res = + res_file->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + ModelResource* model = (ModelResource*)res->resourceAddress; + Check_Pointer(model); + + moverMass = model->moverMass; + Verify(!Small_Enough(model->momentOfInertia.x)); + momentOfInertia.x = 1.0f/model->momentOfInertia.x; + Verify(!Small_Enough(model->momentOfInertia.y)); + momentOfInertia.y = 1.0f/model->momentOfInertia.y; + Verify(!Small_Enough(model->momentOfInertia.z)); + momentOfInertia.z = 1.0f/model->momentOfInertia.z; + positiveLinearDragCoefficients = model->positiveLinearDragCoefficients; + negativeLinearDragCoefficients = model->negativeLinearDragCoefficients; + angularDragCoefficients = model->angularDragCoefficients; + frictionCoefficient = model->frictionCoefficient; + elasticityCoefficient = model->elasticityCoefficient; + minimumBounceSpeed = model->minimumBounceSpeed; + + // + //-------------------------------------------------------------------- + // Read the collision information from the resource file, but for now, + // assume a VTV + //-------------------------------------------------------------------- + // + collisionLists = new BoxedSolidCollisionList[2]; + Register_Pointer(collisionLists); + res->Unlock(); + if (IsCollisionVolume()) + { + res = + res_file->SearchList( + resourceID, + ResourceDescription::BoxedSolidStreamResourceType + ); + Check(res); + res->Lock(); + + BoxedSolidResource* box = (BoxedSolidResource*)res->resourceAddress; + Check_Pointer(box); + collisionVolumeCount = res->resourceSize / sizeof(BoxedSolidResource); + + for (int i=0; iUnlock(); + MoveCollisionVolume(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Mover::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->messageLength = sizeof(Mover::MakeMessage); + creation_message->classToCreate = RegisteredClass::TrivialMoverClassID; +// creation_message->instanceFlags = DefaultFlags; + creation_message->localVelocity = Motion::Identity; + creation_message->localAcceleration = Motion::Identity; + Check_Fpu(); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + Mover::CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *model_file, + const ResourceDirectories *,//directories, + ModelResource *model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + // + //----------------------------------------------------------------------- + // If we were not provided a buffer to write the model data into, we must + // create it ourselves + //----------------------------------------------------------------------- + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + // + //----------------- + // Read in the mass + //----------------- + // + if (!model_file->GetEntry("gamedata", "MoverMass", &local_model->moverMass)) + { + std::cerr << model_name << " missing MoverMass!\n"; +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + Check_Fpu(); + return -1; + } + + // + //------------------------------ + // Read in the moment of inertia + //------------------------------ + // + const char* entry; + if ( + !model_file->GetEntry( + "gamedata", + "MomentOfInertia", + &entry + ) + ) + { + std::cerr << model_name << " missing MomentOfInertia!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->momentOfInertia.x, + &local_model->momentOfInertia.y, + &local_model->momentOfInertia.z + ); + + // + //------------------------------ + // Read in the drag coefficients + //------------------------------ + // + if ( + !model_file->GetEntry( + "gamedata", + "PositiveLinearDragCoefficients", + &entry + ) + ) + { + std::cerr << model_name << " missing PositiveLinearDragCoefficients!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->positiveLinearDragCoefficients.x, + &local_model->positiveLinearDragCoefficients.y, + &local_model->positiveLinearDragCoefficients.z + ); + + if ( + !model_file->GetEntry( + "gamedata", + "NegativeLinearDragCoefficients", + &entry + ) + ) + { + std::cerr << model_name << " missing NegativeLinearDragCoefficients!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->negativeLinearDragCoefficients.x, + &local_model->negativeLinearDragCoefficients.y, + &local_model->negativeLinearDragCoefficients.z + ); + + // + //------------------------- + // Read in the angular drag + //------------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "AngularDragCoefficients", + &entry + ) + ) + { + std::cerr << model_name << " missing AngularDragCoefficients!\n"; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->angularDragCoefficients.x, + &local_model->angularDragCoefficients.y, + &local_model->angularDragCoefficients.z + ); + + // + //--------------------- + // Read in the friction + //--------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "FrictionCoefficient", + &local_model->frictionCoefficient + ) + ) + { + std::cerr << model_name << " missing FrictionCoefficient!\n"; + goto Dump_And_Die; + } + + // + //----------------------- + // Read in the elasticity + //----------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "ElasticityCoefficient", + &local_model->elasticityCoefficient + ) + ) + { + std::cerr << model_name << " missing ElasticityCoefficient!\n"; + goto Dump_And_Die; + } + + // + //--------------------------------- + // Read in the minimum bounce speed + //--------------------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "MinimumBounceSpeed", + &local_model->minimumBounceSpeed + ) + ) + { + std::cerr << model_name << " missing MinimumBounceSpeed!\n"; + goto Dump_And_Die; + } + + // + //------------------------------------------------------------------------- + // If we created the model buffer, then we have the responsibility to write + // it out to the resource file + //------------------------------------------------------------------------- + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Mover* + Mover::Make(Mover::MakeMessage *creation_message) +{ + return new Mover(creation_message, DefaultData); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Mover::~Mover() +{ + Unregister_Pointer(collisionLists); + delete[] collisionLists; + + if (IsCollisionVolume()) + { + BoxedSolid *box = collisionTemplate; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } + box = collisionVolume; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } + } + + if (collisionAssistant) + { + Unregister_Object(collisionAssistant); + delete collisionAssistant; + } + Check_Fpu(); +} + +Logical + Mover::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/MOVER.h b/MUNGA/MOVER.h new file mode 100644 index 0000000..5dffe01 --- /dev/null +++ b/MUNGA/MOVER.h @@ -0,0 +1,463 @@ +#pragma once + +#include "entity.h" +#include "motion.h" + +class Mover__SharedData; +class Mover; +class CollisionAssistant; +class BoundingBoxTreeNode; +class BoxedSolid; +class BoxedSolidCollision; +class BoxedSolidCollisionList; +class Normal; +class Line; +class Environment; + +//########################################################################## +//#################### Mover::UpdateMessage ########################## +//########################################################################## + +struct Mover__UpdateRecord: + public Entity::UpdateRecord +{ +public: + Motion + localVelocity, + localAcceleration; + Vector3D + worldLinearVelocity, + worldLinearAcceleration; +}; + +//########################################################################## +//##################### Mover::MakeMessage ########################## +//########################################################################## + +class Mover__MakeMessage: + public Entity::MakeMessage +{ +public: + Motion + localVelocity, + localAcceleration; + + Mover__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration + ): + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + localVelocity(velocity), + localAcceleration(acceleration) + {} + Mover__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration + ): + Entity::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + localVelocity(velocity), + localAcceleration(acceleration) + {} +}; + +//########################################################################## +//##################### Mover::ModelResource ######################### +//########################################################################## + +struct Mover__ModelResource +{ + Scalar moverMass; + Vector3D + momentOfInertia, + positiveLinearDragCoefficients, + negativeLinearDragCoefficients, + angularDragCoefficients; + Scalar + frictionCoefficient, + elasticityCoefficient, + minimumBounceSpeed; +}; + +//########################################################################## +//############################ Mover ################################# +//########################################################################## + +class Mover: + public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + LocalVelocityAttributeID = Entity::NextAttributeID, + LocalAccelerationAttributeID, + WorldLinearVelocityAttributeID, + WorldLinearAccelerationAttributeID, + MoverMassAttributeID, + MomentOfInertiaAttributeID, + PositiveLinearDragCoefficientsAttributeID, + NegativeLinearDragCoefficientsAttributeID, + AngularDragCoefficientsAttributeID, + FrictionCoefficientAttributeID, + ElasticityCoefficientAttributeID, + MinimumBounceSpeedAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + Motion + localVelocity, + localAcceleration; + Vector3D + worldLinearVelocity, + worldLinearAcceleration; + Scalar moverMass; + Vector3D + momentOfInertia, + positiveLinearDragCoefficients, + negativeLinearDragCoefficients, + angularDragCoefficients; + Scalar + frictionCoefficient, + elasticityCoefficient, + minimumBounceSpeed; + +// +// virtual access +// +public: + virtual Vector3D + GetWorldLinearVelocity() + {return worldLinearVelocity;} + virtual Vector3D + GetWorldLinearAcceleration() + {return worldLinearAcceleration;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + enum { + StasisState = Entity::StateCount, + StateCount + }; + + typedef Mover__UpdateRecord UpdateRecord; + typedef Mover__MakeMessage MakeMessage; + typedef void + (Mover::*Performance)(Scalar time_slice); + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + UpdateWorldMotion(); + void + UpdateLocalMotion(); + void + ApplyWorldAccelerations(Scalar time_slice); + void + ApplyAirResistanceAndGravity(Scalar power=1.0f); + void + CalculateDrag( + Vector3D *drag, + const Vector3D &velocity, + const Vector3D &positive_CODs, + const Vector3D &negative_CODs, + Scalar power + ); + + void + ApplyLocalForce( + const Vector3D &force, + const Vector3D &moment + ); + void + ApplyLocalAcceleration( + const Vector3D &acceleration, + const Vector3D &moment + ); + + Environment* + GetEnvironment() + {Check(this); return localEnvironment;} + + typedef Logical (Mover::*DeadReckoner)(); + void + SetDeadReckoner(DeadReckoner reckoner) + {Check(this); deadReckoner = reckoner;} + + Logical + NoDeadReckoner(); + Logical + LinearDeadReckoner(); + Logical + AcceleratedDeadReckoner(); + void + DeadReckon(Scalar time_slice); + +protected: + void + WriteUpdateRecord( + Simulation::UpdateRecord *message, + int update_model + ); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + void + PerformAndWatch( + const Time& till, + MemoryStream *update_stream + ); + + int + normalizeCount; + Environment + *localEnvironment; + DeadReckoner + deadReckoner; + Origin + projectedOrigin, + previousOrigin; + Motion + projectedVelocity, + updateAcceleration, + updateVelocity; + Time + nextUpdate; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Collision support +// +public: + virtual void + MoveCollisionVolume(); + BoundingBoxTreeNode* + GetMoverCollisionRoot() + {Check(this); return containedByNode;} + + BoxedSolidCollisionList* + AllocateCollisionList(); + BoxedSolidCollisionList* + GetCurrentCollisions(BoxedSolidCollisionList *list=NULL); + BoxedSolid* + FindBoxedSolidHitBy( + Line *line, + Entity *except_by + ); + BoxedSolidCollisionList* + CollideCenterOfMotion( + Line *line, + BoxedSolidCollisionList *list + ); + void + ProcessCollisionList( + BoxedSolidCollisionList *collisions, + Scalar time_slice, + const Point3D &old_position, + Damage *damage + ); + + Scalar + StaticBounce( + const Point3D &old_position, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity, + Scalar bounce_min, + Scalar *friction + ); + Scalar + DynamicBounce( + Mover *other, + Scalar delta_t, + Scalar penetration, + const Normal &normal, + Scalar *elasticity + ); + + BoxedSolid* + GetCollisionVolume() + {Check(this); return collisionVolume;} + BoxedSolid* + GetCollisionTemplate() + {Check(this); return collisionTemplate;} + int + GetCollisionVolumeCount() + {Check(this); return collisionVolumeCount;} + + virtual void + StartCollisionAssistant(); + +protected: +int collisionVolumeCount; + BoxedSolid + *collisionVolume, + *collisionTemplate; + BoundingBoxTreeNode *containedByNode; + BoxedSolidCollisionList + *collisionLists, + *lastCollisionList; + CollisionAssistant *collisionAssistant; + + virtual void + ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ); + + void + CheckAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ); + +public: + void + CheckVolumeAgainstBoxedSolidChain( + BoxedSolidCollisionList *collisions, + BoxedSolid *chain + ); + +protected: + BoxedSolid* + CheckLineAgainstBoxedSolidChain( + Line *line, + BoxedSolid *chain + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Flag Support +// +public: + enum { + NoCollisionVolumeBit = Entity::NextBit, + NoCollisionTestBit, + InitialStasisBit, + NextBit + }; + + enum { + NoCollisionVolumeFlag = 1<Multiply(*old_top,matrix); + return *this; +} + +LinearMatrixStack& LinearMatrixStack::Concatenate(const LinearMatrix& matrix) +{ + LinearMatrix *old_top = Cast_Object(LinearMatrix*,Peek()); + LinearMatrix *new_top = (LinearMatrix*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4Stack& Matrix4x4Stack::Concatenate(const Matrix4x4& matrix) +{ + Matrix4x4 *old_top = Cast_Object(Matrix4x4*,Peek()); + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4Stack& Matrix4x4Stack::Concatenate(const AffineMatrix& matrix) +{ + Matrix4x4 *old_top = Cast_Object(Matrix4x4*,Peek()); + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + new_top->Multiply(*old_top,matrix); + return *this; +} + +Matrix4x4& Matrix4x4Stack::Push(const AffineMatrix& matrix) +{ + Matrix4x4 *new_top = (Matrix4x4*)MemoryStack::Push(); + return *new_top = matrix; +} diff --git a/MUNGA/MTRXSTK.h b/MUNGA/MTRXSTK.h new file mode 100644 index 0000000..5822a50 --- /dev/null +++ b/MUNGA/MTRXSTK.h @@ -0,0 +1,123 @@ +#pragma once + +#include "memblock.h" +#include "matrix.h" +#include "linmtrx.h" + +//~~~~~~~~~~~~~~~~~~~~~~~ AffineMatrixStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AffineMatrixStack: + public MemoryStack +{ + public: + AffineMatrixStack( + size_t start, + size_t delta + ): + MemoryStack(sizeof(AffineMatrix),start,delta) + {} + + AffineMatrix* + Peek() + { + Check(this); + return Cast_Object(AffineMatrix*,MemoryStack::Peek()); + } + + AffineMatrixStack& + Concatenate(const AffineMatrix& matrix); + AffineMatrixStack& + operator*=(const AffineMatrix& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + + AffineMatrix& + Push(const AffineMatrix& matrix) + { + Check(this); Check(&matrix); + return *Cast_Object(AffineMatrix*,MemoryStack::Push(&matrix)); + } + + operator AffineMatrix&() + {Check(this); return *Peek();} +}; + +//~~~~~~~~~~~~~~~~~~~~~~~ LinearMatrixStack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LinearMatrixStack: + public MemoryStack +{ + public: + LinearMatrixStack( + size_t start, + size_t delta + ): + MemoryStack(sizeof(LinearMatrix),start,delta) + {} + + LinearMatrix* + Peek() + { + Check(this); + return Cast_Object(LinearMatrix*,MemoryStack::Peek()); + } + + LinearMatrixStack& + Concatenate(const LinearMatrix& matrix); + LinearMatrixStack& + operator*=(const LinearMatrix& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + + LinearMatrix& + Push(const LinearMatrix& matrix) + { + Check(this); Check(&matrix); + return *Cast_Object(LinearMatrix*,MemoryStack::Push(&matrix)); + } + + operator LinearMatrix&() + {Check(this); return *Peek();} +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Matrix4x4Stack ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Matrix4x4Stack: + public MemoryStack +{ + public: + Matrix4x4Stack( + size_t start, + size_t delta + ): + MemoryStack(sizeof(Matrix4x4),start,delta) + {} + + Matrix4x4* + Peek() + { + Check(this); + return Cast_Object(Matrix4x4*,MemoryStack::Peek()); + } + + Matrix4x4Stack& + Concatenate(const Matrix4x4& matrix); + Matrix4x4Stack& + Concatenate(const AffineMatrix& matrix); + Matrix4x4Stack& + operator*=(const Matrix4x4& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + Matrix4x4Stack& + operator*=(const AffineMatrix& matrix) + {Check(this); Check(&matrix); return Concatenate(matrix);} + + Matrix4x4& + Push(const Matrix4x4& matrix) + { + Check(this); Check(&matrix); + return *Cast_Object(Matrix4x4*,MemoryStack::Push(&matrix)); + } + Matrix4x4& + Push(const AffineMatrix& matrix); + + operator Matrix4x4&() + {Check(this); return *Peek();} +}; diff --git a/MUNGA/MUNGA.h b/MUNGA/MUNGA.h new file mode 100644 index 0000000..02bcb4b --- /dev/null +++ b/MUNGA/MUNGA.h @@ -0,0 +1,50 @@ +#pragma once + +#define WIN32_WINNT 0x0500 +#define WINVER 0x0500 + + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#if defined(__BCPLUSPLUS__) + #include +#endif + +#if defined(LBE4) + #include +#else + #include +#endif + +enum +{ + NullExitCodeID = 0, + AbortExitCodeID +}; + +#include "trace.h" + +#if !defined(NO_PRECOMPILED_HEADERS) + #include "cstr.h" + #include "namelist.h" + #include "notation.h" + #include "slot.h" + #include "chain.h" + #include "schain.h" + #include "vchain.h" + #include "table.h" + #include "tree.h" + #include "hash.h" + #include "origin.h" +#endif \ No newline at end of file diff --git a/MUNGA/NAMELIST.cpp b/MUNGA/NAMELIST.cpp new file mode 100644 index 0000000..bacfd3d --- /dev/null +++ b/MUNGA/NAMELIST.cpp @@ -0,0 +1,448 @@ +#include "munga.h" +#pragma hdrstop + +#include "namelist.h" + +//############################################################################# +//############## ObjectNameList ######################################### +//############################################################################# + +ObjectNameList::ObjectNameList() +{ + Check_Pointer(this); + firstEntry = lastEntry = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ObjectNameList::~ObjectNameList() +{ + Check(this); + + Entry + *next; + + while (firstEntry) + { + Check_Pointer(firstEntry); + next = firstEntry->nextEntry; + Unregister_Pointer(firstEntry); + delete firstEntry; + firstEntry = next; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + ObjectNameList::AddEntry( + const char *name, + void *data + ) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry; + + entry = (Entry *)new char[ sizeof(Entry) + strlen(name) + 1 ]; + Register_Pointer(entry); + + entry->dataReference = data; + entry->nextEntry = NULL; + + if (firstEntry) + { + Check_Pointer(lastEntry); + lastEntry->nextEntry = entry; + } + else + { + firstEntry = entry; + } + lastEntry = entry; + + entry->SetName(name); + + return entry->GetName(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void* + ObjectNameList::FindObject(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (!strcmp(entry->GetName(), name)) + { + break; + } + } + return (entry)?entry->dataReference:NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ObjectNameList::DeleteEntry(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *cur, + *prev, + *entry; + + //---------------------------------------------------- + // ***** DANGEROUS!!! see notice in namelist.hh ***** + //---------------------------------------------------- + entry = (Entry *)(name - sizeof(Entry)); + Check_Pointer(entry); + prev = NULL; + for (cur=firstEntry; cur && cur != entry; cur = cur->nextEntry) + { + Check_Pointer(cur); + prev = cur; + } + Verify(cur == entry); + if (!prev) + { + firstEntry = entry->nextEntry; + } + else + { + prev->nextEntry = entry->nextEntry; + } + if (entry == lastEntry) + { + lastEntry = prev; + } + Unregister_Pointer(entry); + delete entry; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + ObjectNameList::EntryCount() const +{ + Check(this); + + Entry + *entry = firstEntry; + int + count = 0; + + while (entry) + { + Check_Pointer(entry); + count++; + entry = entry->nextEntry; + } + return count; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + ObjectNameList::BuildSubList( + const ObjectNameList &source_list, + const char *prefix + ) +{ + Check(this); + Check(&source_list); + Check_Pointer(prefix); + + const int + length = strlen(prefix); + Entry + *entry = source_list.firstEntry; + const char + *name; + int + count = 0; + + //------------------------------------------------------ + // add entries to SubList whose name begins with prefix + //------------------------------------------------------ + while (entry) + { + Check_Pointer(entry); + name = entry->GetName(); + Check_Pointer(name); + if (!strncmp(name, prefix, length)) + { + count++; + AddEntry(name, entry->dataReference); + } + entry = entry->nextEntry; + } + //------------------------------------------- + // return number of entries added to SubList + //------------------------------------------- + return count; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ObjectNameList::TestInstance() const +{ + // nothing to check + return True; +} + +//############################################################################# +//############## ObjectNameList::Entry ################################## +//############################################################################# + +void + ObjectNameList::Entry::SetName(const char *name) +{ + Check_Pointer(this); + Check_Pointer(name); + strcpy((char *)this + sizeof(ObjectNameList::Entry), name); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile ObjectNameList__Entry *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ObjectNameList::Entry::IsName(const char *name) const +{ + Check(this); + //do not check name here + + if (name) + { + Check_Pointer(name); + return strcmp(GetName(), name) == 0; + } + else + { + return GetName() == name; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ObjectNameList::Entry::TestInstance() const +{ + // nothing to check + //do not check dataReference even if it is not NULL! + return True; +} + +//############################################################################# +//############## NameList ############################################### +//############################################################################# + +NameList::NameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList::~NameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + NameList::FindName(void *data) +{ + Check(this); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (entry->dataReference == data) + { + break; + } + } + return (entry)?entry->GetName():NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList::Entry* + NameList::FindEntry(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (!strcmp(entry->GetName(), name)) + { + break; + } + } + return entry; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList::Entry + *NameList::FindEntry(void *data) +{ + Check(this); + + Entry + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (entry->dataReference == data) + { + break; + } + } + return entry; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NameList::DeleteEntry(const char *name) +{ + Check(this); + Check_Pointer(name); + + Entry + *prev = NULL, + *entry; + + for (entry = firstEntry; entry; entry = entry->nextEntry) + { + Check_Pointer(entry); + if (!strcmp(entry->GetName(), name)) + { + break; + } + prev = entry; + } + if (entry) + { + if (!prev) + { + firstEntry = entry->nextEntry; + } + else + { + prev->nextEntry = entry->nextEntry; + } + if (entry == lastEntry) + { + lastEntry = prev; + } + Unregister_Pointer(entry); + delete entry; + } + return; +} + +//############################################################################# +//############## AlphaNameList ########################################## +//############################################################################# + +AlphaNameList::AlphaNameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList::~AlphaNameList() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const char* + AlphaNameList::AddEntry( + const char *name, + void *data + ) +{ + Check(this); + Check_Pointer(name); + + Entry + *entry, + *next = firstEntry, + *prev = NULL; + + entry = (Entry *)new char[ sizeof(Entry) + strlen(name) + 1 ]; + Verify(entry); + Register_Pointer(entry); + + //----------------------------------- + // find location to insert new entry + //----------------------------------- + while (next) + { + Check_Pointer(next); + if (strcmp(name, next->GetName()) < 0) + { + break; + } + prev = next; + next = next->nextEntry; + } + //--------------------------------------------- + // insert new entry after prev and before next + //--------------------------------------------- + if (!next) + { + lastEntry = entry; + } + if (!prev) + { + firstEntry = entry; + } + else + { + prev->nextEntry = entry; + } + entry->dataReference = data; + entry->nextEntry = next; + entry->SetName(name); + + return entry->GetName(); +} + +#if defined(TEST_CLASS) + #include "namelist.tcp" +#endif \ No newline at end of file diff --git a/MUNGA/NAMELIST.h b/MUNGA/NAMELIST.h new file mode 100644 index 0000000..c6e5f10 --- /dev/null +++ b/MUNGA/NAMELIST.h @@ -0,0 +1,165 @@ +#pragma once + +class ObjectNameList; +class ObjectNameList__Entry; +class NameList; +class AlphaNameList; + +class ObjectNameList SIGNATURED +{ +public: + typedef ObjectNameList__Entry Entry; + +protected: + Entry *firstEntry, *lastEntry; + +public: + ObjectNameList(); + virtual ~ObjectNameList(); + + virtual const char* AddEntry(const char *name, void *data); + void* FindObject(const char *name); + void DeleteEntry(const char *name); + int EntryCount() const; + Logical IsEmpty() const + { + Check(this); + return firstEntry == NULL && lastEntry == NULL; + } + Entry* GetFirstEntry() + { + Check(this); + return firstEntry; + } + const Entry* GetFirstEntry() const + { + Check(this); + return firstEntry; + } + Entry* GetLastEntry() + { + Check(this); + return lastEntry; + } + const Entry* GetLastEntry() const + { + Check(this); + return lastEntry; + } + int BuildSubList(const ObjectNameList &source_list, const char *prefix); + + Logical TestInstance() const; + static Logical TestClass(); +}; + +class ObjectNameList__Entry +{ + friend class ObjectNameList; + friend class NameList; + friend class AlphaNameList; + +private: + ObjectNameList::Entry *nextEntry; + +public: + void *dataReference; + +protected: + void SetName(const char *name); + +public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile ObjectNameList__Entry *); + #endif + + const char* GetName() const + { + Check(this); + return &((const char *)this)[sizeof(ObjectNameList::Entry)]; + } + Logical IsName(const char *name) const; + + /* + * HACK SB 01/21/07 -- Windows uses this function name and macros it, + and GetData seems to do the same thing, so don't + use this. + void* GetObject() + { + Check(this); + return dataReference; + } + */ + void* GetData() + { + Check(this); + return dataReference; + } + const void* GetData() const + { + Check(this); + return dataReference; + } + char* GetChar() + { + Check(this); + return (char *)dataReference; + } + const char* GetChar() const + { + Check(this); + return (const char *)dataReference; + } + int GetAtoi() const + { + Check(this); + Check_Pointer(dataReference); + return atoi((const char *)dataReference); + } + long GetAtol() const + { + Check(this); + Check_Pointer(dataReference); + return atol((const char *)dataReference); + } + double GetAtof() const + { + Check(this); + Check_Pointer(dataReference); + return atof((const char *)dataReference); + } + ObjectNameList::Entry* GetNextEntry() + { + Check(this); + return nextEntry; + } + const ObjectNameList::Entry* GetNextEntry() const + { + Check(this); + return nextEntry; + } + Logical TestInstance() const; +}; + +class NameList : public ObjectNameList +{ +public: + NameList(); + ~NameList(); + + void* FindData(const char *name) { return FindObject(name); } + const char* FindName(void *data); + Entry* FindEntry(const char *name); + Entry* FindEntry(void *data); + void DeleteEntry(const char *name); // this one is searches for name + static Logical TestClass(); +}; + +class AlphaNameList : public NameList +{ +public: + AlphaNameList(); + ~AlphaNameList(); + + const char* AddEntry(const char *name, void *data); + static Logical TestClass(); +}; \ No newline at end of file diff --git a/MUNGA/NETWORK.cpp b/MUNGA/NETWORK.cpp new file mode 100644 index 0000000..fcaea72 --- /dev/null +++ b/MUNGA/NETWORK.cpp @@ -0,0 +1,440 @@ +#include "munga.h" +#pragma hdrstop + +#include "hostmgr.h" +#include "interest.h" +#include "icom.h" +#include "app.h" +#include "notation.h" +#include "nttmgr.h" + +#if defined(TRACE_ROUTE_PACKET) + static BitTrace Route_Packet("Route Packet"); +# define SET_ROUTE_PACKET() Route_Packet.Set() +# define CLEAR_ROUTE_PACKET() Route_Packet.Clear() +#else +# define SET_ROUTE_PACKET() +# define CLEAR_ROUTE_PACKET() +#endif + +const NetworkAddress NullNetworkAddress = 0x00000000;// 0.0.0.0 (in TCP land); + +//############################################################################# +// Shared Data Support +// +NetworkClient::SharedData + NetworkClient::DefaultData( + NetworkClient::GetClassDerivations(), + NetworkClient::GetMessageHandlers() + ); + +// +//############################################################################# +// Code for the network client class +//############################################################################# +// +Derivation* NetworkClient::GetClassDerivations() +{ + static Derivation classDerivations(Receiver::GetClassDerivations(), "NetworkClient"); + return &classDerivations; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the NetworkClient +// +NetworkClient::NetworkClient( + ClassID class_ID, + SharedData &virtual_data, + ClientID client_ID +): + Receiver(class_ID, virtual_data) +{ + clientID = client_ID; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the NetworkClient +// +NetworkClient::~NetworkClient() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the NetworkClient +// +Logical + NetworkClient::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Receive packet for the NetworkClient +// +void + NetworkClient::ReceiveNetworkPacket( + NetworkPacket*, + Receiver::Message *packet_message + ) +{ + Dispatch(packet_message); +} + +// +//############################################################################# +// Code for the network manager class +//############################################################################# + +const Receiver::HandlerEntry + NetworkManager::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(NetworkManager,ReceiveEggFile) +}; + +Receiver::MessageHandlerSet& NetworkManager::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(NetworkManager::MessageHandlerEntries), NetworkManager::MessageHandlerEntries, NetworkClient::GetMessageHandlers()); + return messageHandlers; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +NetworkManager::SharedData + NetworkManager::DefaultData( + NetworkManager::GetClassDerivations(), + NetworkManager::GetMessageHandlers() + ); + +Derivation* NetworkManager::GetClassDerivations() +{ + static Derivation classDerivations(NetworkClient::GetClassDerivations(), "NetworkManager"); + return &classDerivations; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the NetworkManager +// +NetworkManager::NetworkManager(SharedData &shared_data): + NetworkClient(NetworkManagerClassID, shared_data, NetworkManagerClientID) +{ +// basic init goes here + gameID = 0; + addresses = NULL; + num_addresses = 0; + eggTempBuffer = NULL; + networkEggNotationFile = NULL; + eggTempNext = 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Creates a host for us. Any derived class must deal with reading the +// notation file to get the network nodes to connect to. This start is +// designed for STAND-ALONE MODE ONLY and should not be inherited for use by +// +void + NetworkManager::StartConnecting(Mission *) +{ + Check(this); + + // + //--------------------------------------------------------- + // Make the local host, and get the application to adopt it + //--------------------------------------------------------- + // + SOCKADDR_IN address; + address.sin_family = AF_INET; + address.sin_addr.S_un.S_addr = 1; + Host *local_host = new Host(1, GameMachineHostType, &address); + Register_Object(local_host); + + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptLocalHost(local_host); + + // + //-------------------------------------------------------------------- + // Now, since this host creator is for stand-alone mode, send the load + // mission message to the application + //-------------------------------------------------------------------- + // + Check(application); + Application::Message + load_message( + Application::LoadMissionMessageID, + sizeof(Application::Message) + ); + application->Post(DefaultEventPriority, application, &load_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::EndMission This routine is called when a mission ends to +// allow the network management system to do stuff (like disconnecting network +// connections between pods and so on) +// +Logical + NetworkManager::Shutdown() +{ + // + // If there is a notation file floating about, kill it! + // + if (networkEggNotationFile) + { + Unregister_Object(networkEggNotationFile); + delete networkEggNotationFile; + } + + // + // Deregister local host + // + Host *local_host; + + local_host = application->GetHostManager()->OrphanLocalHost(); + Unregister_Object(local_host); + delete local_host; + + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the NetworkManager +// +NetworkManager::~NetworkManager() +{ +// shutdown net goes here +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::ReceiveEggFileMessageHandler +// +void + NetworkManager::ReceiveEggFileMessageHandler( + ReceiveEggFileMessage* EggMessage + ) +{ + // + // An egg sequence number of -1 means that the egg is posted locally, and + // should just call create mission + // + if (EggMessage->sequenceNumber == -1) + { + application->CreateMission(networkEggNotationFile); + return; + } + + if (EggMessage->sequenceNumber == 0) + { + // + // Make a buffer + // + eggTempBuffer = new char[EggMessage->notationFileLength]; + Register_Pointer(eggTempBuffer); + eggTempNext = 0; + } + + // + // Write the egg data into the buffer + // + memcpy( + (eggTempBuffer+eggTempNext), + EggMessage->notationData, + EggMessage->thisMessageLength + ); + eggTempNext += EggMessage->thisMessageLength; + + // + // If we don't have all the data, return and wait for more + // + if(eggTempNext < EggMessage->notationFileLength) + { + return; + } + + // + // We've got all the data, make the notation file + // + networkEggNotationFile = new NotationFile(); + Register_Object(networkEggNotationFile); + networkEggNotationFile->ReadText(eggTempBuffer, eggTempNext); + networkEggNotationFile->WriteFile("last.egg"); + + // + // Now turn the notation file into a mission + // + application->CreateMission(networkEggNotationFile); + + // + // Get rid of the ram buffer now that we're done with it + // + Unregister_Pointer(eggTempBuffer); + delete eggTempBuffer; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::Send Handles sending a message to a specific network address +// which can NOT be us. Default behavior is to do nothing, as no network is +// hooked up if we get here +// +void + NetworkManager::Send( + Message *, + ClientID, + HostID + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::Broadcast Handles broadcasting a message to everyone, +// including ourselves. !!!! Reliable broadcasting is currently used, +// implimented by sending a point-to-point message to every destination. +// +void + NetworkManager::Broadcast( + Message *message, + ClientID client_id + ) +{ + // + // Send this message back to ourselves + // + NetworkClient *client = GetNetworkClientPointer(client_id); + Check(client); + client->ReceiveNetworkPacket(NULL, message); + + // + // Broadcast the message to everyone else on the network + // + ExclusiveBroadcast(message,client_id); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::ExclusiveBroadcast Broadcasts a message to everyone on the +// network execpt us. Default behavior sends it to nobody, as there is really +// no network +// +void + NetworkManager::ExclusiveBroadcast( + Message *, + ClientID + ) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::GetNetworkClientPointer Determine who the client of a +// message is and return a pointer to them. +// +NetworkClient* + NetworkManager::GetNetworkClientPointer(ClientID client_id) +{ + switch (client_id) + { + case NetworkClient::NetworkManagerClientID: + return this; + + case NetworkClient::EntityManagerClientID: + Check(application); + return application->GetEntityManager(); + + case NetworkClient::HostManagerClientID: + Check(application); + return application->GetHostManager(); + + case NetworkClient::InterestManagerClientID: + Check(application); + return application->GetInterestManager(); + + case NetworkClient::IcomManagerClientID: + Check(application); + return application->GetIntercomManager(); + + case NetworkClient::ApplicationClientID: + Check(application); + return application; + + default: + DEBUG_STREAM << "------UNKNOWN NETWORK CLIENT ID " << client_id << std::endl << std::flush; + Fail("Unknown Client ID"); + break; + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::RoutePacket +// +Logical + NetworkManager::RoutePacket() +{ + Check(this); + + Byte + message_buffer[NETWORKMANAGER_BUFFER_SIZE]; + NetworkPacket + *p; + + // + // Return if check buffers doesn't have a packet for us + // + if (!CheckBuffers((NetworkPacket*)message_buffer)) + { + return False; + } + + // + // Process and route the packet properly + // + p = (NetworkPacket*)message_buffer; + + if (p->gameID == gameID) + { +// cout<<"++++++++client "<clientID<<" gameID "<gameID<<" fromHost "<fromHost<<"\n"; + NetworkClient *client = GetNetworkClientPointer(p->clientID); + + Check(client); + SET_ROUTE_PACKET(); + client->ReceiveNetworkPacket(p, &p->messageData); + CLEAR_ROUTE_PACKET(); + } + else + { + DEBUG_STREAM << "+++++++++ client " << p->clientID << " gameID " << p->gameID << " fromHost " << p->fromHost << std::endl << std::flush; + Fail("######### NOT A PACKET FOR THIS GAME!"); + } + + RemovePacket(p); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::ExecuteBackground Allows the network to perform tasks in +// the applications background. The method should return True if the manager +// is busy, false otherwise. For example, if the input and output buffers of +// the network driver are not empty then return True, otherwise return False. +// +Logical + NetworkManager::ExecuteBackground() +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::CheckBuffers Checks to see if there is a message for us +// buffered up in the network interface card and returns a pointer to it. +// +Logical + NetworkManager::CheckBuffers(NetworkPacket*) +{ + Fail("NetworkManager::CheckBuffers - should never reach here!"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::RemovePacket If the network implimentation requires us to +// free up a packet buffer, this routine would do it. +// +void + NetworkManager::RemovePacket(NetworkPacket*) +{ + Fail("NetworkManager::RemovePacket - should never reach here!"); +} diff --git a/MUNGA/NETWORK.h b/MUNGA/NETWORK.h new file mode 100644 index 0000000..a277b14 --- /dev/null +++ b/MUNGA/NETWORK.h @@ -0,0 +1,281 @@ +#pragma once + +#include "receiver.h" +#include "time.h" +#include "hostid.h" + +//WinSock support :ADB 01/06/07 +#include +#include + +class Mission; +class NetworkManager; +class NotationFile; + +// +//--------------------------------------------------- +// Support types for interest manager +//--------------------------------------------------- +// +typedef Enumeration InterestZoneID; +const InterestZoneID NullInterestZoneID = 0; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkAddress ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef LWord NetworkAddress; + +extern const NetworkAddress NullNetworkAddress; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkClient ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class NetworkPacket; + +class NetworkClient: + public Receiver +{ + friend class NetworkManager; + +//########################################################################## +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//########################################################################## +// Construction and destruction support +// +public: + enum ClientID { + NetworkManagerClientID = 0, + EntityManagerClientID = 1, + HostManagerClientID = 2, + InterestManagerClientID = 3, + ApplicationClientID = 4, + ConsoleClientID = 5, + IcomManagerClientID = 6 + }; + +private: + ClientID + clientID; + +protected: + NetworkClient( + ClassID class_ID, + SharedData &virtual_data, + ClientID clientID + ); + +public: + ~NetworkClient(); + + Logical + TestInstance() const; + +//########################################################################## +// Message packet receiving +// +public: + virtual void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Network ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define NETWORKMANAGER_BUFFER_SIZE 1600 + +class NetworkManager__ReceiveEggFileMessage; + +class NetworkManager: + public NetworkClient +{ +//########################################################################## +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +public: + typedef Enumeration GameID; + + //WinSock support :ADB 01/06/07 + //const NetworkAddress& + // GetAddress() + NetworkAddress* GetAddress() + {return addresses;} + + NetworkManager(SharedData &shared_data); + ~NetworkManager(); + + void + SetGameID(GameID new_id) + {gameID = new_id;} + + virtual void + Send( + Message *what, + ClientID to, + HostID host_id + ); + void + Broadcast( + Message *what, + ClientID to + ); + virtual void + ExclusiveBroadcast( + Message *what, + ClientID to + ); + Logical + RoutePacket(); + virtual Logical + ExecuteBackground(); + + NetworkClient* + GetNetworkClientPointer(ClientID client_id); + + virtual void + StartConnecting(Mission *mission); + + virtual Logical + Shutdown(); + + virtual void + Marker(char *) {}; + + enum NetworkMode + { + ReliableMode, + UnreliableMode + }; + + virtual void + Mode(NetworkMode) {}; + +// protected: //GY for test only + virtual Logical + CheckBuffers(NetworkPacket*); + virtual void + RemovePacket(NetworkPacket *packet); + + GameID + gameID; + //WinSock support :ADB 01/06/07 + //NetworkAddress address; + NetworkAddress* addresses; + int num_addresses; + //struct addrinfo* address; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + // + // Message IDs + // + enum + { + ReceiveEggFileMessageID = NetworkClient::NextMessageID, + NextMessageID + }; + + // + // Message types + // + typedef NetworkManager__ReceiveEggFileMessage + ReceiveEggFileMessage; + + // + // Message table + // + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + ReceiveEggFileMessageHandler(ReceiveEggFileMessage* EggMessage); + +protected: + char + *eggTempBuffer; + NotationFile + *networkEggNotationFile; + long + eggTempNext; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkManager messages ~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager__ReceiveEggFileMessage +// NOTE: this message should be setup as variable length rather than fixing the +// size at 1000, I wasn't sure how to do this and there wasn't anyone around +// to ask at the time so I did it this way temporarily. +// +class NetworkManager__ReceiveEggFileMessage: + public Receiver__Message +{ +public: + NetworkManager__ReceiveEggFileMessage( + int sequence_number, + int total_file_length, + char* notation_data, + int length + ): + Receiver__Message( + NetworkManager::ReceiveEggFileMessageID, + sizeof(NetworkManager__ReceiveEggFileMessage) + ), + sequenceNumber(sequence_number), + notationFileLength(total_file_length), + thisMessageLength(length) + {Mem_Copy(notationData,notation_data,length,sizeof(notationData));} + int + sequenceNumber; + int + notationFileLength; + int + thisMessageLength; + char + notationData[1000]; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ NetworkPacketHeader ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class NetworkPacketHeader +{ +public: + NetworkClient::ClientID + clientID; + NetworkManager::GameID + gameID; + HostID + fromHost; + Time + timeStamp; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ NetworkPacket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class NetworkPacket: + public NetworkPacketHeader +{ +public: + Receiver::Message + messageData; + +}; + + + +bool operator==(SOCKADDR_IN &address1, SOCKADDR_IN &address2) +{ + return (address1.sin_family == address2.sin_family && + address1.sin_addr.S_un.S_addr == address2.sin_addr.S_un.S_addr && + address1.sin_port == address2.sin_port); +} diff --git a/MUNGA/NODE.cpp b/MUNGA/NODE.cpp new file mode 100644 index 0000000..be2a07d --- /dev/null +++ b/MUNGA/NODE.cpp @@ -0,0 +1,22 @@ +#include "munga.h" +#pragma hdrstop + +#include "node.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Node ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Node::Node(ClassID class_id) : Plug(class_id) +{ +} + +Node::Node(PlugStream *stream) : Plug(stream) +{ +} + +Node::~Node() +{ +} + +void Node::ReleaseLinkHandler(Socket*, Plug*) +{ +} diff --git a/MUNGA/NODE.h b/MUNGA/NODE.h new file mode 100644 index 0000000..1fee5e8 --- /dev/null +++ b/MUNGA/NODE.h @@ -0,0 +1,17 @@ +#pragma once + +#include "socket.h" + +class Node : public Plug +{ +public: + ~Node(); + + virtual int ReceiveNodeCommand(NodeCommandID, void *) { return 0; } + + virtual void ReleaseLinkHandler(Socket *, Plug *); + +protected: + Node(ClassID class_id = TrivialNodeClassID); + Node(PlugStream *stream); +}; \ No newline at end of file diff --git a/MUNGA/NORMAL.cpp b/MUNGA/NORMAL.cpp new file mode 100644 index 0000000..c923f0f --- /dev/null +++ b/MUNGA/NORMAL.cpp @@ -0,0 +1,41 @@ +#include "munga.h" +#pragma hdrstop + +#include "normal.h" +#include "affnmtrx.h" + +// +//############################################################################# +//############################################################################# +// +Normal& Normal::Multiply_Inverse(const Normal &Source, const AffineMatrix &M) +{ + Check(this); + Check(&Source); + Check(&M); + + x = Source.x*M(0,0) + Source.y*M(0,1) + Source.z*M(0,2); + y = Source.x*M(1,0) + Source.y*M(1,1) + Source.z*M(1,2); + z = Source.x*M(2,0) + Source.y*M(2,1) + Source.z*M(2,2); + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Normal& Normal::Multiply(const Normal &Source, const AffineMatrix &M) +{ + Check(this); + Check(&Source); + Check(&M); + + AffineMatrix m; + m.Invert(M); + return Multiply_Inverse(Source,m); +} + +#if defined(TEST_CLASS) +# include "normal.tcp" +#endif diff --git a/MUNGA/NORMAL.h b/MUNGA/NORMAL.h new file mode 100644 index 0000000..32d7037 --- /dev/null +++ b/MUNGA/NORMAL.h @@ -0,0 +1,72 @@ +#pragma once + +#include "unitvec.h" + +class Normal : public UnitVector +{ +public: + Normal() {} + Normal(Scalar x, Scalar y, Scalar z) : UnitVector(x,y,z) {} + Normal(const UnitVector& v) : UnitVector(v) {} + + Normal& operator=(const UnitVector& v) + { + UnitVector::operator=(v); + return *this; + } + Normal& operator=(const Vector3D& v) + { + Normalize(v); + return *this; + } + + Normal& Negate(const Normal &v) + { + Vector3D::Negate(v); + return *this; + } + + Scalar operator*(const Vector3D& v) const + { + return Vector3D::operator*(v); + } + + Normal& Multiply(const Normal &n, const LinearMatrix &m) + { + UnitVector::Multiply(n,m); + return *this; + } + Normal& operator*=(const LinearMatrix &M) + { + Normal src(*this); + return Multiply(src,M); + } + + // + // These functions will cause the vector to lose its unit length, thus + // cause any downstream verifies to fail. We have to be able to only + // normalize the normal once after all transformations if these are to + // be of any benefit, so don't use them for now + Normal& Multiply_Inverse(const Normal &Source, const AffineMatrix &M); + Normal& Multiply(const Normal &Source, const AffineMatrix &M); + + static Logical TestClass(); + +private: + static const Normal identity; + Normal& Negate(const Vector3D &V); + Normal& Add(const Vector3D& V1,const Vector3D& V2); + Normal& operator+=(const Vector3D& V); + Normal& Subtract(const Vector3D& V1,const Vector3D& V2); + Normal& operator-=(const Vector3D& V); + Normal& Cross(const Vector3D& V1,const Vector3D& V2); + Normal& Multiply(const Vector3D& V,Scalar Scale); + Normal& operator*=(Scalar Value); + Normal& Multiply(const Vector3D& V1,const Vector3D& V2); + Normal& operator*=(const Vector3D &V); + Normal& Multiply(const Vector3D &Source, const AffineMatrix &M); + Normal& operator*=(const AffineMatrix &M); + Normal& Divide(const Vector3D& V,Scalar Scale); + Normal& operator/=(Scalar Value); + Normal& Combine(const Vector3D& V1,Scalar t1,const Vector3D& V2,Scalar t2); +}; \ No newline at end of file diff --git a/MUNGA/NOTATION.cpp b/MUNGA/NOTATION.cpp new file mode 100644 index 0000000..9e59e90 --- /dev/null +++ b/MUNGA/NOTATION.cpp @@ -0,0 +1,2110 @@ +#include "munga.h" +#include "notation.h" +#include "namelist.h" + +//############################################################################# +//############## NotationFile ########################################### +//############################################################################# + +NotationFile::NotationFile( + const char *filename, + Enumeration operation_modes +) +{ + Check_Pointer(this); + //do not check filename here + + fileName = NULL; + firstNotePage = lastNotePage = NULL; + pageCount = cleanPageCount = 0; + dirtyFlag = False; + saveNotePage = NULL; + operationModes = operation_modes; + + if (filename && *filename) + { + Check_Pointer(filename); + ReadFile(filename); + } + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile::~NotationFile() +{ + Check(this); + + NotePage + *next = firstNotePage; + + if (dirtyFlag) + { + if (fileName && *fileName && !WriteFile()) + { + std::cerr << "NotationFile: Error writing file '" << fileName << + "' - changes lost!" << std::endl; + } + } + + while (next) + { + Check(next); + firstNotePage = next->nextNotePage; + Unregister_Object(next); + delete next; + next = firstNotePage; + } + if (fileName) + { + Unregister_Pointer(fileName); + delete fileName; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::PageExists(const char *pagename) +{ + // let FindNotePage() check this and pagename + + NotePage + *notepage; + + return FindNotePage(pagename, ¬epage); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::EntryCount(const char *pagename) +{ + // let FindNotePage() check this and pagename + + NotePage + *notepage; + + if (FindNotePage(pagename, ¬epage)) + { + Check(notepage); + return ((operationModes&CleanEntryListMode)?notepage->cleanNotationCount:notepage->notationCount); + } + return 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile::NotePage* + NotationFile::SetPage( + const char *pagename, + const char *comment + ) +{ + // let FindNotePage() check this and pagename + // let AppentPage() or SetComment() check comment + + NotePage + *notepage; + + SetDirty(); + if (!FindNotePage(pagename, ¬epage)) + { + notepage = AppendPage(pagename, comment); + } + else + { + notepage->SetComment(comment); + } + return notepage; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile::NotePage* + NotationFile::AppendPage( + const char *pagename, + const char *comment + ) +{ + Check(this); + Check_Pointer(pagename); + // let SetComment() check comment + + NotePage + *notepage; + + SetDirty(); + notepage = new NotePage(this); + Register_Object(notepage); + notepage->SetName(pagename, &cleanPageCount); + notepage->SetComment(comment); + AppendNotePage(notepage); + + return notepage; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + const char **contents + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(contents); + + NotePage + *notepage; + Notation + *notation; + + //--------------- + // return string + //--------------- + if (FindNotePage(pagename, ¬epage)) + { + Check(notepage); + if (notepage->FindNote(entryname, ¬ation)) + { + Check(notation); + *contents = notation->GetEntry(); + return True; + } + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + int *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //---------------- + // return integer + //---------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + *value = atoi(contents); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + Scalar *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //--------------- + // return scalar + //--------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + *value = atof(contents); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetEntry( + const char *pagename, + const char *entryname, + double *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //--------------- + // return double + //--------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + *value = atof(contents); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + NotationFile::GetLogicalEntry( + const char *pagename, + const char *entryname, + Logical *value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + Check_Pointer(value); + + const char + *contents; + + //---------------- + // return Logical + //---------------- + if (GetEntry(pagename, entryname, &contents)) + { + Check_Pointer(contents); + //-------------------------------------------------------- + // these stricmp()'s must not affected by IgnoreCaseModes + //-------------------------------------------------------- + *value = (!stricmp(contents, "true") || !stricmp(contents, "yes") || atoi(contents) != 0); + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + const char *contents + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + if (contents) { Check_Pointer(contents); } + + NotePage + *notepage; + Notation + *notation; + + SetDirty(); + //--------------- + // assign string + //--------------- + if (!FindNotePage(pagename, ¬epage)) + { + notepage = AppendPage(pagename); + } + notation = new Notation; + Register_Object(notation); + notation->SetName(entryname, &(notepage->cleanNotationCount)); + notation->SetEntry(contents); + notepage->UpdateNote(notation); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + int value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[12]; + std::ostrstream stream(contents, sizeof(contents)); + + stream << value << std::ends; + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + Scalar value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[32]; + std::ostrstream stream(contents, sizeof(contents)); + + stream << value << std::ends; + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetEntry( + const char *pagename, + const char *entryname, + double value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[64]; + std::ostrstream stream(contents, sizeof(contents)); + + stream << value << std::ends; + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::SetLogicalEntry( + const char *pagename, + const char *entryname, + Logical value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[6]; + std::ostrstream stream(contents, sizeof(contents)); + + if (value) + { + stream << "True" << std::ends; + } + else + { + stream << "False" << std::ends; + } + + SetEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + const char *contents + ) +{ + Check(this); + Check_Pointer(pagename); + if (entryname) { Check_Pointer(entryname); } + if (contents) { Check_Pointer(contents); } + + NotePage + *notepage; + Notation + *notation; + + SetDirty(); + //--------------- + // assign string + //--------------- + if (!FindNotePage(pagename, ¬epage)) + { + notepage = AppendPage(pagename); + } + notation = new Notation; + Register_Object(notation); + notation->SetName(entryname, &(notepage->cleanNotationCount)); + notation->SetEntry(contents); + notepage->AppendNote(notation); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + int value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[12]; + std::ostrstream stream(contents, sizeof(contents)); + + stream << value << std::ends; + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + Scalar value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[32]; + std::ostrstream stream(contents, sizeof(contents)); + + stream << value << std::ends; + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendEntry( + const char *pagename, + const char *entryname, + double value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[64]; + std::ostrstream stream(contents, sizeof(contents)); + + stream << value << std::ends; + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendLogicalEntry( + const char *pagename, + const char *entryname, + Logical value + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + static char + contents[6]; + std::ostrstream stream(contents, sizeof(contents)); + + if (value) + { + stream << "True" << std::ends; + } + else + { + stream << "False" << std::ends; + } + + AppendEntry(pagename, entryname, contents); + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList* + NotationFile::MakeEntryList( + const char *pagename, + const char *entryname_prefix + ) +{ + Check(this); + Check_Pointer(pagename); + //do not check entryname_prefix here + + NotePage + *notepage; + + //-------------------------------------------------- + // return namelist of matching entries and contents + //-------------------------------------------------- + if (FindNotePage(pagename, ¬epage)) + { + return MakeEntryList(notepage, entryname_prefix); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList* + NotationFile::MakeEntryList( + NotePage *notepage, + const char *entryname_prefix + ) +{ + Check(this); + Check(notepage); + //do not check entryname_prefix here + + const char + *name_prefix = entryname_prefix?entryname_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + NameList + *namelist; + Notation + *notation; + const char + *name; + Logical + prefix_matches, + add_entry; + + //-------------------------------------------------- + // return namelist of matching entries and contents + //-------------------------------------------------- + namelist = new NameList; + //do not register namelist + notation = notepage->firstNotation; + while (notation) + { + Check(notation); + name = notation->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnoreEntryCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (entryname_prefix == NULL); + } + if (operationModes&CleanEntryListMode) + { + add_entry = (notation->cleanNotation && prefix_matches); + } + else if (name) + { + add_entry = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_entry = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_entry = False; + //add_entry = (prefix_matches); + } + if (add_entry) + { + if (notation->GetEntry()) + { Check_Pointer(notation->GetEntry()); } + namelist->AddEntry(name, (void *)notation->GetEntry()); + } + notation = notation->nextNotation; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NameList* + NotationFile::MakePageList(const char *pagename_prefix) +{ + Check(this); + //do not check pagename_prefix here + + const char + *name_prefix = pagename_prefix?pagename_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + NameList + *namelist; + NotePage + *notepage; + const char + *name; + Logical + prefix_matches, + add_page; + + //----------------------------------------------------- + // return namelist of matching pagenames and notepages + //----------------------------------------------------- + namelist = new NameList; + //do not register namelist + notepage = firstNotePage; + while (notepage) + { + Check(notepage); + name = notepage->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnorePageCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (pagename_prefix == NULL); + } + if (operationModes&CleanPageListMode) + { + add_page = (notepage->cleanPage && prefix_matches); + } + else if (name) + { + add_page = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_page = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_page = False; + //add_page = (pagename_prefix==NULL); + } + if (add_page) + { + namelist->AddEntry(name, (void *)notepage); + } + notepage = notepage->nextNotePage; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList* + NotationFile::MakeAlphaEntryList( + const char *pagename, + const char *entryname_prefix + ) +{ + Check(this); + Check_Pointer(pagename); + //do not check entryname_prefix here + + NotePage + *notepage; + + //------------------------------------------------------- + // return alphanamelist of matching entries and contents + //------------------------------------------------------- + if (FindNotePage(pagename, ¬epage)) + { + return MakeAlphaEntryList(notepage, entryname_prefix); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList* + NotationFile::MakeAlphaEntryList( + NotePage *notepage, + const char *entryname_prefix + ) +{ + Check(this); + Check(notepage); + //do not check entryname_prefix here + + const char + *name_prefix = entryname_prefix?entryname_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + AlphaNameList + *namelist; + Notation + *notation; + const char + *name; + Logical + prefix_matches, + add_entry; + + //------------------------------------------------------- + // return alphanamelist of matching entries and contents + //------------------------------------------------------- + namelist = new AlphaNameList; + //do not register namelist + notation = notepage->firstNotation; + while (notation) + { + Check(notation); + name = notation->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnoreEntryCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (entryname_prefix == NULL); + } + if (operationModes&CleanEntryListMode) + { + add_entry = (notation->cleanNotation && prefix_matches); + } + else if (name) + { + add_entry = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_entry = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_entry = False; + //add_entry = (entryname_prefix==NULL); + } + if (add_entry) + { + if (notation->GetEntry()) + { Check_Pointer(notation->GetEntry()); } + namelist->AddEntry(name, (void *)notation->GetEntry()); + } + notation = notation->nextNotation; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AlphaNameList* + NotationFile::MakeAlphaPageList(const char *pagename_prefix) +{ + Check(this); + //do not check pagename_prefix here + + const char + *name_prefix = pagename_prefix?pagename_prefix:"\0"; + Check_Pointer(name_prefix); + const int + length = strlen(name_prefix); + AlphaNameList + *namelist; + NotePage + *notepage; + const char + *name; + Logical + prefix_matches, + add_page; + + //---------------------------------------------------------- + // return alphanamelist of matching pagenames and notepages + //---------------------------------------------------------- + namelist = new AlphaNameList; + //do not register namelist + notepage = firstNotePage; + while (notepage) + { + Check(notepage); + name = notepage->GetName(); + if (name) + { + Check_Pointer(name); + if (operationModes&IgnorePageCaseMode) + { + prefix_matches = (!strnicmp(name, name_prefix, length)); + } + else + { + prefix_matches = (!strncmp(name, name_prefix, length)); + } + } + else + { + prefix_matches = (pagename_prefix == NULL); + } + if (operationModes&CleanPageListMode) + { + add_page = (notepage->cleanPage && prefix_matches); + } + else if (name) + { + add_page = (prefix_matches); + } + else if (operationModes&SkipBlanksListMode) + { + add_page = False; + } + else + { + //------------------------------------------------------ + // HACK: NameList::AddEntry() should accept name==NULL + //------------------------------------------------------ + add_page = False; + //add_page = (pagename_prefix==NULL); + } + if (add_page) + { + namelist->AddEntry(name, (void *)notepage); + } + notepage = notepage->nextNotePage; + } + return namelist; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeleteEntry( + const char *pagename, + const char *entryname + ) +{ + Check(this); + Check_Pointer(pagename); + Check_Pointer(entryname); + + NotePage + *notepage; + + //--------------------------- + // if found, delete Notation + //--------------------------- + if (FindNotePage(pagename, ¬epage)) + { + Check(notepage); + SetDirty(); + notepage->DeleteNote(entryname); + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeletePage(const char *pagename) +{ + Check(this); + Check_Pointer(pagename); + + NotePage + *notepage, + *prev; + + //---------------------------- + // if found, delete Note_Page + //---------------------------- + if (FindNotePage(pagename, ¬epage, &prev)) + { + DeletePage(notepage, prev); + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::ReadFile(const char *filename) +{ + Check(this); + Check_Pointer(filename); + + std::ifstream notefile(filename); + char buffer[512]; + Logical was_empty = IsEmpty(); + + //------------------------------- + // store first notation filename + //------------------------------- + if (!fileName) + { + fileName = new char[strlen(filename) + 1]; + Register_Pointer(fileName); + strcpy(fileName, filename); + } + + //-------------------- + // read notation file + //-------------------- + if (notefile) + { + //Dump( "--- read notation file ---" ); + + while (notefile.getline(buffer, sizeof(buffer))) + { + //------------------------------ + // process line of NotationFile + //------------------------------ + Read(buffer); + } + notefile.close(); + Read(NULL); // (reset static variable) + + //Dump( "--- end ---" ); + } + if (was_empty) + { + dirtyFlag = False; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::ReadText( + char *start, + long length + ) +{ + Check(this); + Check_Pointer(start); + + char + *stop, + *buffer; + Logical + was_empty = IsEmpty(); + + //-------------------------------- + // read notation file from memory + //-------------------------------- + stop = start + length; + while (start < stop) + { + //--------------------------------------------------------- + // this must preceed Read() which does not preserve buffer + //--------------------------------------------------------- + buffer = start; + start = strchr(buffer, '\0') + 1; + + //------------------------------ + // process line of NotationFile + //------------------------------ + Read(buffer); + } + Read(NULL); // (reset static variable) + if (was_empty) + { + dirtyFlag = False; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::WriteFile(const char *filename) +{ + Check(this); + //do not check filename + + std::ofstream output; + + if (filename && *filename) + { + Check_Pointer(filename); + output.open(filename); + } + else if (fileName && *fileName) + { + Check_Pointer(fileName); + output.open(fileName); + } + else + { + return False; // you tried to WriteFile with no default fileName! + } + + if (output.is_open()) + { + Write(output); + output.close(); + if (filename && *filename) + { + if (fileName) + { + Unregister_Pointer(fileName); + delete fileName; + } + fileName = new char[strlen(filename) + 1]; + Register_Pointer(fileName); + strcpy(fileName, filename); + } + dirtyFlag = False; + return True; + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::SizeOfText() +{ + Check(this); + + std::ofstream + dummy; + + return Write(dummy, Size_Only); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::WriteText( + char *buffer, + long size + ) +{ + Check(this); + Check_Pointer(buffer); + Verify( size >= 0 ); + + std::ostrstream + output(buffer, size); + long + actual_size; + + if ((actual_size = Write(output, Text_Memory)) <= size) + { + dirtyFlag = False; + return actual_size; + } + + return -1L; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Abort() +{ + Check(this); + dirtyFlag = False; + this->~NotationFile(); + //this->NotationFile(); //does not compile! + *this = NotationFile(); + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeleteStandardPages() +{ + Check(this); + + NotePage + *prev = NULL, + *notepage = firstNotePage, + *next; + const char + *name; + + while (notepage) + { + Check(notepage); + next = notepage->nextNotePage; + name = notepage->pageName; + if (*name != '_' && strcmp(name, "LAB_ONLY") != 0) + { + DeletePage(notepage, prev); + } + else + { + prev = notepage; + } + notepage = next; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::MarkLabOnly() +{ + Check(this); + + if (!IsMarkedLabOnly()) + { + SetPage("LAB_ONLY","\t// this file has not been approved for release"); + AppendEntry("LAB_ONLY", NULL, (char *)NULL); // (blank line) + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::AppendNotePage(NotePage *notepage) +{ + Check(this); + Check(notepage); + + //--------------------------------- + // append NotePage to NotationFile + //--------------------------------- + if (!lastNotePage) + { + firstNotePage = notepage; + } + else + { + Check(lastNotePage); + lastNotePage->nextNotePage = notepage; + } + lastNotePage = notepage; + lastNotePage->nextNotePage = NULL; + if (notepage->cleanPage) + { + ++cleanPageCount; + } + ++pageCount; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::FindNotePage( + const char *pagename, + NotePage **notepage + ) +{ + //----------------------------------------------------------------- + // HACK: This routine should be changed to support NULL pagename. + //----------------------------------------------------------------- + Check(this); + Check_Pointer(pagename); + Check_Pointer(notepage); + + //------------------------------------------- + // check to see if same as previous NotePage + //------------------------------------------- + if (saveNotePage && + saveNotePage->pageName && + ((operationModes&IgnorePageCaseMode && + !stricmp(saveNotePage->pageName, pagename)) || + (!(operationModes&IgnorePageCaseMode) && + !strcmp(saveNotePage->pageName, pagename)))) + { + Check(saveNotePage); + *notepage = saveNotePage; + return True; + } + else + { + //------------------------------ + // search for matching NotePage + //------------------------------ + NotePage + *notepg = firstNotePage; + + while (notepg) + { + Check(notepg); + if (notepg->pageName && + ((operationModes&IgnorePageCaseMode && + !stricmp(notepg->pageName, pagename)) || + (!(operationModes&IgnorePageCaseMode) && + !strcmp(notepg->pageName, pagename)))) + { + *notepage = saveNotePage = notepg; + return True; + } + notepg = notepg->nextNotePage; + } + } + //----------- + // not found + //----------- + *notepage = NULL; + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::FindNotePage( + const char *pagename, + NotePage **notepage, + NotePage **prevpage + ) +{ + //----------------------------------------------------------------- + // HACK: This routine should be changed to support NULL pagename. + //----------------------------------------------------------------- + Check(this); + Check_Pointer(pagename); + Check_Pointer(notepage); + Check_Pointer(prevpage); + + NotePage + *notepg = firstNotePage, + *prev = NULL; + + //------------------------------ + // search for matching NotePage + //------------------------------ + while (notepg) + { + Check(notepg); + if (notepg->pageName && + ((operationModes&IgnorePageCaseMode && + !stricmp(notepg->pageName, pagename)) || + (!(operationModes&IgnorePageCaseMode) && + !strcmp(notepg->pageName, pagename)))) + { + *notepage = notepg; + *prevpage = prev; + return True; + } + prev = notepg; + notepg = notepg->nextNotePage; + } + //----------- + // not found + //----------- + *notepage = *prevpage = NULL; + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::DeletePage( + NotePage *notepage, + NotePage *prev + ) +{ + Check(this); + Check(notepage); + //do not check prev here + + //--------------------------- + // remove & delete Note_Page + //--------------------------- + SetDirty(); + + if (prev) + { + Check(prev); + prev->nextNotePage = notepage->nextNotePage; + } + else + { + firstNotePage = notepage->nextNotePage; + } + if (lastNotePage == notepage) + { + lastNotePage = prev; + } + if (notepage == saveNotePage) + { + saveNotePage = NULL; + } + if (notepage->cleanPage) + { + --cleanPageCount; + } + --pageCount; + Unregister_Object(notepage); + delete notepage; + + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Read(char *buffer) +{ + Check(this); + //do not check buffer here + + static NotePage + *notepage = NULL; + Notation + *notation; + char + *token, + *entry, + *p; + Logical +// blank_line, + comment_line; + + if (!buffer) + { + //------------------------------ + // reset notepage for next read + //------------------------------ + notepage = NULL; + return; + } + Check_Pointer(buffer); + + //-------------------------------- + // find first non-blank character + //-------------------------------- + p = buffer; + while (*p == ' ' || *p == '\t') + { + ++p; + } + + //-------------------- + // begin new NotePage + //-------------------- + if (*p == '[') + { + token = p+1; + if ((p = strchr(token, ']')) != NULL) + { + *p = '\0'; + ++p; + } + notepage = AppendPage(token, p); +// std::cerr << "[" << notepage->GetName() << "]" << std::endl; // TESTING! +// notepage->Write( std::cerr ); // TESTING! + return; + } + + //--------------------------------- + // detect blank lines and comments + //--------------------------------- +// blank_line = (*p == '\0'); + comment_line = Comment_Line(p); + + //--------------- + // read Notation + //--------------- + token = p; + if ((p = strchr(token, '=')) != NULL) + { + *p = '\0'; + entry = ++p; +// if (*entry == '\0') +// { +// entry = NULL; +// } + } + else + { + entry = NULL; + } + if (*token == '\0') + { + token = NULL; + } + + //------------------------ + // remove trailing blanks + //------------------------ + if (token && !comment_line) + { + p = strchr(token, '\0') - 1; + while (*p == ' ' || *p == '\t') + { + *p = '\0'; + if (--p < token) + { + break; + } + } + } + + if (!notepage) + { + notepage = new NotePage(this); + Register_Object(notepage); + AppendNotePage(notepage); + } + notation = new Notation; + Register_Object(notation); + notation->SetName(token, &(notepage->cleanNotationCount)); + notation->SetEntry(entry); + notepage->AppendNote(notation); +// std::cerr << token << "=" << entry << std::endl; // TESTING! +// notation->Write( std::cerr ); // TESTING! +// notepage->Write( std::cerr ); // TESTING! + + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::Write( + std::ostream &stream, + WriteMode mode + ) +{ + Check(this); + + NotePage + *notepg = firstNotePage; + long + size = 0; + + while (notepg) + { + Check(notepg); + size += notepg->WriteNote(stream, mode); + notepg = notepg->nextNotePage; + } + return size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::TestInstance() const +{ + //do not Check(this); + if (fileName) { Check_Pointer(fileName); } + if (firstNotePage) { Check_Signature(firstNotePage); } + if (lastNotePage) { Check_Signature(lastNotePage); } + if (saveNotePage) { Check_Signature(saveNotePage); } + return True; +} + +//############################################################################# +//############## NotationFile::Notation ################################# +//############################################################################# + +NotationFile__Notation::~NotationFile__Notation() +{ + Check(this); + + if (notationName) + { + Check_Pointer(notationName); + Unregister_Pointer(notationName); + delete notationName; + } + if (notationEntry) + { + Check_Pointer(notationEntry); + Unregister_Pointer(notationEntry); + delete notationEntry; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Notation::SetName( + const char *entryname, + long *clean_notation_count + ) +{ + Check(this); + //do not check entryname here + Check_Pointer(clean_notation_count); + + if (notationName) + { + if (cleanNotation) + { + cleanNotation = False; + --(*clean_notation_count); + } + Check_Pointer(notationName); + Unregister_Pointer(notationName); + delete notationName; + } + if (entryname) // (do not add "&& *entryname") + { + Check_Pointer(entryname); + notationName = new char[strlen(entryname) + 1]; + Register_Pointer(notationName); + strcpy(notationName, entryname); + cleanNotation = (*notationName && !Comment_Line(notationName)); + } + else + { + notationName = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::Notation::SetEntry(const char *contents) +{ + Check(this); + //do not check contents here + + if (notationEntry) + { + Check_Pointer(notationEntry); + Unregister_Pointer(notationEntry); + delete notationEntry; + } + if (contents) // (do not add "&& *contents") + { + Check_Pointer(contents); + notationEntry = new char[strlen(contents) + 1]; + Register_Pointer(notationEntry); + strcpy(notationEntry, contents); + } + else + { + notationEntry = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::Notation::WriteNotation( + std::ostream &stream, + NotationFile::WriteMode mode + ) const +{ + Check(this); + +// Logical +// comment_line = True; + long + size = 0; + + if (notationName) + { + Check_Pointer(notationName); + if (mode) + { + stream << notationName; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(notationName); + } +// comment_line = Comment_Line(notationName); +// if (!comment_line) +// { +// stream << "="; +// } + } + if (notationEntry) + { + Check_Pointer(notationEntry); +// if (comment_line) +// { +// stream << "="; +// } + if (mode) + { + stream << "=" << notationEntry; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(notationEntry) + 1; + } + } + if (mode == NotationFile::Disk_File) + { + stream << std::endl; + } + else if (mode) + { + stream << std::ends; + } + if (mode != NotationFile::Disk_File) + { + size += 1; + } + + return size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::Notation::TestInstance() const +{ + //do not Check(this); + if (nextNotation) { Check_Signature(nextNotation); } + if (notationName) { Check_Pointer(notationName); } + if (notationEntry) { Check_Pointer(notationEntry); } + return True; +} + +//############################################################################# +//############## NotationFile::NotePage ################################# +//############################################################################# + +NotationFile__NotePage::NotationFile__NotePage(NotationFile *notation_file) +{ + Check_Pointer(this); + Check(notation_file); + + notationFile = notation_file; + nextNotePage = NULL; + firstNotation = lastNotation = NULL; + notationCount = cleanNotationCount = 0; + pageName = pageComment = NULL; + cleanPage = False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NotationFile__NotePage::~NotationFile__NotePage() +{ + Check(this); + + NotationFile::Notation + *notation = firstNotation; + + while (notation) + { + Check(notation); + firstNotation = notation->nextNotation; + Unregister_Object(notation); + delete notation; + notation = firstNotation; + } + if (pageName) + { + Check_Pointer(pageName); + Unregister_Pointer(pageName); + delete pageName; + } + if (pageComment) + { + Check_Pointer(pageComment); + Unregister_Pointer(pageComment); + delete pageComment; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::SetName( + const char *pagename, + long *clean_page_count + ) +{ + Check(this); + //do not check pagename here + Check_Pointer(clean_page_count); + + if (pageName) + { + if (cleanPage) + { + cleanPage = False; + --(*clean_page_count); + } + Check_Pointer(pageName); + Unregister_Pointer(pageName); + delete pageName; + } + if (pagename) // (do not add "&& *pagename") + { + Check_Pointer(pagename); + pageName = new char[strlen(pagename) + 1]; + Register_Pointer(pageName); + strcpy(pageName, pagename); + cleanPage = (*pageName && (*pageName != '!') && strcmp(pageName, "LAB_ONLY")); + } + else + { + pageName = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::SetComment(const char *comment) +{ + Check(this); + //do not check comment here + + if (pageComment) + { + Check_Pointer(pageComment); + Unregister_Pointer(pageComment); + delete pageComment; + } + if (comment && *comment) + { + Check_Pointer(comment); + pageComment = new char[strlen(comment) + 1]; + Register_Pointer(pageComment); + strcpy(pageComment, comment); + } + else + { + pageComment = NULL; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::AppendNote(NotationFile::Notation *note) +{ + Check(this); + Check(note); + + //----------------------------- + // append Notation to NotePage + //----------------------------- + if (!lastNotation) + { + firstNotation = note; + } + else + { + Check(lastNotation); + lastNotation->nextNotation = note; + } + lastNotation = note; + lastNotation->nextNotation = NULL; + if (note->cleanNotation) + { + ++cleanNotationCount; + } + ++notationCount; + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::NotePage::FindNote( + const char *entryname, + NotationFile::Notation **note + ) +{ + NotationFile::Notation + *prev; + + return FindNote(entryname, note, &prev); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::NotePage::FindNote( + const char *entryname, + NotationFile::Notation **note, + NotationFile::Notation **prev + ) +{ + //------------------------------------------------------------------ + // HACK: This routine should be changed to support NULL entryname. + //------------------------------------------------------------------ + Check(this); + Check_Pointer(entryname); + Check_Pointer(note); + Check_Pointer(prev); + + NotationFile::Notation + *notation = firstNotation, + *previous = NULL; + + //------------------------------ + // search for matching Notation + //------------------------------ + while (notation) + { + Check(notation); + if (notation->notationName && + ((notationFile->operationModes&NotationFile::IgnoreEntryCaseMode && + !stricmp(notation->notationName, entryname)) || + (!(notationFile->operationModes&NotationFile::IgnoreEntryCaseMode) && + !strcmp(notation->notationName, entryname)))) + { + *note = notation; + *prev = previous; + return True; + } + previous = notation; + notation = notation->nextNotation; + } + //----------- + // not found + //----------- + *note = *prev = NULL; + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::UpdateNote(NotationFile::Notation *note) +{ + Check(this); + Check(note); + + NotationFile::Notation + *notation, + *prev; + + //------------------------------ + // search for matching Notation + //------------------------------ + if (FindNote(note->notationName, ¬ation, &prev)) + { + Check(notation); + + //------------------ + // replace Notation + //------------------ + if (prev) + { + Check(prev); + prev->nextNotation = note; + } + else + { + firstNotation = note; + } + if ((note->nextNotation = notation->nextNotation) == NULL) + { + lastNotation = note; + } + Unregister_Object(notation); + delete notation; + } + else + { + //----------------- + // append Notation + //----------------- + AppendNote(note); + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + NotationFile::NotePage::DeleteNote(const char *entryname) +{ + Check(this); + Check_Pointer(entryname); + + NotationFile::Notation + *notation, + *prev; + + //------------------------------ + // search for matching Notation + //------------------------------ + if (FindNote(entryname, ¬ation, &prev)) + { + Check(notation); + + //-------------------------- + // remove & delete Notation + //-------------------------- + if (prev) + { + Check(prev); + prev->nextNotation = notation->nextNotation; + } + else + { + firstNotation = notation->nextNotation; + } + if (lastNotation == notation) + { + lastNotation = prev; + } + if (notation->cleanNotation) + { + --cleanNotationCount; + } + --notationCount; + Unregister_Object(notation); + delete notation; + } + return; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + NotationFile::NotePage::WriteNote( + std::ostream &stream, + NotationFile::WriteMode mode + ) const +{ + Check(this); + + NotationFile::Notation + *notation = firstNotation; + long + size = 0; + + if (pageName) + { + Check_Pointer(pageName); + if (mode) + { + stream << "[" << pageName << "]"; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(pageName) + 2; + } + } + if (pageComment) + { + Check_Pointer(pageComment); + if (mode) + { + stream << pageComment; + } + if (mode != NotationFile::Disk_File) + { + size += strlen(pageComment); + } + } + if (pageName || pageComment) + { + if (mode == NotationFile::Disk_File) + { + stream << std::endl; + } + else if (mode) + { + stream << std::ends; + } + if (mode != NotationFile::Disk_File) + { + size += 1; + } + } + while (notation) + { + Check(notation); + size += notation->WriteNotation(stream, mode); + notation = notation->nextNotation; + } + return size; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + NotationFile::NotePage::TestInstance() const +{ + //do not Check(this); + if (nextNotePage) { Check_Signature(nextNotePage); } + if (firstNotation) { Check_Signature(firstNotation); } + if (lastNotation) { Check_Signature(lastNotation); } + if (pageName) { Check_Pointer(pageName); } + return True; +} + +//############################################################################# +//############## TestClass() ############################################ +//############################################################################# + +#if defined(TEST_CLASS) + #include "notation.tcp" +#endif + +//===========================================================================// diff --git a/MUNGA/NOTATION.h b/MUNGA/NOTATION.h new file mode 100644 index 0000000..a22249b --- /dev/null +++ b/MUNGA/NOTATION.h @@ -0,0 +1,194 @@ +#pragma once + +#include "namelist.h" +#include "scalar.h" + +class NotationFile; +class NotationFile__Notation; +class NotationFile__NotePage; +class NameList; +class AlphaNameList; + +inline Logical Comment_Line(const char *p) { return ((*p == ';') || (*p == '#') || (*p == '/' && *(p+1) == '/')); } + +class NotationFile SIGNATURED +{ + friend class NotationFile__NotePage; + friend class NotationFile__Notation; + +public: + typedef NotationFile__Notation Notation; + typedef NotationFile__NotePage NotePage; + +private: + char *fileName; + NotePage *firstNotePage, *lastNotePage; + long pageCount, cleanPageCount; + Logical dirtyFlag; + NotePage *saveNotePage; + Enumeration operationModes; + + enum WriteMode + { + //-------------------------------------------- + // NOTE: These numbers are not arbitrary! + // See code before changing or adding values. + //-------------------------------------------- + Size_Only = 0, + Disk_File = 1, + Text_Memory = 2, + Binary_Memory = 3 // not implemented yet + }; + +public: + +#if 0 + enum Mode + { + // Access Modes: + EXCLUSIVE = 0, + SHARED = 1, + // Error Modes: + QUIET = 0, + FATAL = 2, + // Default Modes: + DEFAULT = (EXCLUSIVE | QUIET) + }; +#endif + + enum OperationModes + { + RawOperationModes = 0x0000, + SkipBlanksListMode = 0x0001, + CleanPageListMode = 0x0002, + CleanEntryListMode = 0x0004, + IgnorePageCaseMode = 0x0008, + IgnoreEntryCaseMode = 0x0010, + DefaultOperationModes = (SkipBlanksListMode), + CleanListMode = (CleanPageListMode | CleanEntryListMode), + IgnoreCaseMode = (IgnorePageCaseMode | IgnoreEntryCaseMode), + RelaxedOperationModes = (CleanListMode | IgnoreCaseMode) + }; + + NotationFile(const char *filename = NULL, Enumeration operation_modes = DefaultOperationModes); + ~NotationFile(); + + Enumeration GetModes() { Check(this); return operationModes; } + Enumeration PutModes(Enumeration operation_modes) { Check(this); return (operationModes = operation_modes); } + Enumeration SetMode(Enumeration operation_modes) { Check(this); return (operationModes |= operation_modes); } + Enumeration ClearMode(Enumeration operation_modes) { Check(this); return (operationModes &= ~operation_modes); } + Logical IsDirty() const { Check(this); return dirtyFlag; } + Logical IsEmpty() const { Check(this); return (pageCount == 0L); } + const char *GetFileName() const { Check(this); return fileName; } + long PageCount() const { Check(this); return ((operationModes & CleanPageListMode) ? cleanPageCount:pageCount); } + Logical PageExists(const char *pagename); + long EntryCount(const char *pagename); + + NotePage* SetPage(const char *pagename, const char *comment = NULL); + NotePage* AppendPage(const char *pagename, const char *comment = NULL); + + int GetEntry(const char *pagename, const char *entryname, const char **contents); + int GetEntry(const char *pagename, const char *entryname, int *value); + int GetEntry(const char *pagename, const char *entryname, Scalar *value); + int GetEntry(const char *pagename, const char *entryname, double *value); + int GetLogicalEntry(const char *pagename, const char *entryname, Logical *value); + + void SetEntry(const char *pagename, const char *entryname, int value); + void SetEntry(const char *pagename, const char *entryname, Scalar value); + void SetEntry(const char *pagename, const char *entryname, double value); + void SetEntry(const char *pagename, const char *entryname, const char *contents); + void SetLogicalEntry(const char *pagename, const char *entryname, Logical value); + + void AppendEntry(const char *pagename, const char *entryname, const char *contents); + void AppendEntry(const char *pagename, const char *entryname, int value); + void AppendEntry(const char *pagename, const char *entryname, Scalar value); + void AppendEntry(const char *pagename, const char *entryname, double value); + void AppendLogicalEntry(const char *pagename, const char *entryname, Logical value); + + NameList* MakeEntryList(const char *pagename, const char *entryname_prefix = NULL); + NameList* MakeEntryList(NotationFile::NotePage *notepage, const char *entryname_prefix = NULL); + NameList* MakePageList(const char *pagename_prefix = NULL); + + AlphaNameList* MakeAlphaEntryList(const char *pagename, const char *entryname_prefix = NULL); + AlphaNameList* MakeAlphaEntryList(NotationFile::NotePage *notepage, const char *entryname_prefix = NULL); + AlphaNameList* MakeAlphaPageList(const char *pagename_prefix = NULL); + + void DeleteEntry(const char *pagename, const char *entryname); + void DeletePage(const char *pagename); + void ReadFile(const char *filename); + void ReadText(char *start, long length); + Logical WriteFile(const char *filename = NULL); + long SizeOfText(); + long WriteText(char *buffer, long size); + void Abort(); + + void DeleteStandardPages(); + void MarkLabOnly(); + Logical IsMarkedLabOnly() { Check(this); return PageExists("LAB_ONLY"); } + +private: + void AppendNotePage(NotePage *notepage); + Logical FindNotePage(const char *pagename, NotePage **notepage); + Logical FindNotePage(const char *pagename, NotePage **notepage, NotePage **prevpage); + void SetDirty() { Check(this); dirtyFlag = true; } + void DeletePage(NotePage *notepage, NotePage *prev); + void Read(char *buffer); + long Write(std::ostream &stream, WriteMode mode = Disk_File); + +public: + Logical TestInstance() const; + static Logical TestClass(); +}; + +class NotationFile__Notation SIGNATURED +{ + friend class NotationFile; + friend class NotationFile__NotePage; + +private: + NotationFile::Notation *nextNotation; + char *notationName, *notationEntry; + Logical cleanNotation; + + NotationFile__Notation() + { + nextNotation = NULL; + notationName = notationEntry = NULL; + cleanNotation = false; + } + ~NotationFile__Notation(); + + void SetName(const char *entryname, long *clean_notation_count); + void SetEntry(const char *contents); + const char* GetName() const { Check(this); return notationName; } + const char* GetEntry() const { Check(this); return notationEntry; } + long WriteNotation(std::ostream &stream, NotationFile::WriteMode mode) const; + Logical TestInstance() const; +}; + +class NotationFile__NotePage SIGNATURED +{ + friend class NotationFile; + +private: + NotationFile *notationFile; + NotationFile::NotePage *nextNotePage; + NotationFile::Notation *firstNotation, *lastNotation; + long notationCount, cleanNotationCount; + char *pageName, *pageComment; + Logical cleanPage; + + NotationFile__NotePage(NotationFile *notation_file); + ~NotationFile__NotePage(); + + void SetName(const char *pagename, long *clean_page_count); + void SetComment(const char *comment); + const char *GetName() const { Check(this); return pageName; } + void AppendNote(NotationFile::Notation *note); + Logical FindNote(const char *entryname, NotationFile::Notation **note); + Logical FindNote(const char *entryname, NotationFile::Notation **note, NotationFile::Notation **prev); + void UpdateNote(NotationFile::Notation *note); + void DeleteNote(const char *entryname); + long WriteNote(std::ostream &stream, NotationFile::WriteMode mode) const; + Logical TestInstance() const; +}; \ No newline at end of file diff --git a/MUNGA/NTTMGR.cpp b/MUNGA/NTTMGR.cpp new file mode 100644 index 0000000..8847f06 --- /dev/null +++ b/MUNGA/NTTMGR.cpp @@ -0,0 +1,216 @@ +#include "munga.h" +#pragma hdrstop + +#include "nttmgr.h" +#include "namelist.h" +#include "app.h" +#include "entity.h" +#include "hostmgr.h" +#include "dropzone.h" +#include "registry.h" + +//############################################################################# +//############################ EntityGroup ############################## +//############################################################################# + + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityGroup::EntityGroup(): + groupMembers(NULL) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityGroup::~EntityGroup() +{ +} + +//############################################################################# +//########################### EntityManager ############################# +//############################################################################# + +Derivation* EntityManager::GetClassDerivations() +{ + static Derivation classDerivations(NetworkClient::GetClassDerivations(), "EntityManager"); + return &classDerivations; +} + +EntityManager::SharedData + EntityManager::DefaultData( + EntityManager::GetClassDerivations(), + EntityManager::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityManager::EntityManager(): + NetworkClient( + EntityManager::EntityManagerClassID, + DefaultData, + NetworkClient::EntityManagerClientID + ) +{ + deathRow = UseGroup("DeathRow"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityManager::~EntityManager() +{ + // + //---------------------------------------------- + // Erase all the groups listed in the group list + //---------------------------------------------- + // + ObjectNameList::Entry *entry; + while ((entry = groupList.GetFirstEntry()) != NULL) + { + Check(entry); + EntityGroup *group = (EntityGroup*)entry->GetData(); + groupList.DeleteEntry(entry->GetName()); + Unregister_Object(group); + delete group; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntityManager::FryDeathRow() +{ + Check(this); + Check(deathRow); + + // + // ECH 8/23/95 - Just delete one ... this allows the application to + // delete as many entities as it can within the current frame + // + ChainIteratorOf iterator(deathRow->groupMembers); + Node *node; + + if ((node = iterator.GetCurrent()) != NULL) + { + Unregister_Object(node); + delete node; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntityManager::ReceiveNetworkPacket( + NetworkPacket*, + Receiver::Message *packet_message + ) +{ + Check(this); + Check_Pointer(packet_message); + + // + //------------------------------------------------------------------------- + // Check to see if the interest zone contained in the message is one we are + // interested in, and if not, ignore the message + //------------------------------------------------------------------------- + // + Entity::MakeMessage + *message = Cast_Object(Entity::MakeMessage*, packet_message); + + // + //----------------------------------------------------------------------- + // Find the address of the entity. If it exists, post the message on the + // application event queue. + //----------------------------------------------------------------------- + // + Entity + *entity = + application->GetHostManager()->GetEntityPointer(message->entityID); + if (entity) + { + // + // HACK -- This hack puts dropzone messages on max priority. It should + // really be done with a message priority encoded in the message + // + if ( + entity->GetClassID() == DropZoneClassID + && message->messageID == DropZone::AssignDropZoneMessageID + ) + { + application->Post(MaxEventPriority, entity, message); + } + else + { + application->Post(EntityManagerEventPriority, entity, message); + } + } + + // + //-------------------------------------------------------------------------- + // If the entity does not exist, check to see if this is a manager message, + // or see if we have to ask for a remake + //-------------------------------------------------------------------------- + // + else + { + switch (message->messageID) + { + case Entity::MakeMessageID: + { + #if DEBUG_LEVEL>0 + Entity *entity = application->GetRegistry()->MakeEntity(message); + Register_Object(entity); + #else + application->GetRegistry()->MakeEntity(message); + #endif + } + break; + + // + //--------------------------------------------------------------------- + // Send a remake message to the sending host to have our entity rebuilt + //--------------------------------------------------------------------- + // + default: + break; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntityGroup* + EntityManager::UseGroup(const char *name) +{ + EntityGroup *group = FindGroup(name); + if (!group) + { + group = new EntityGroup; + group->groupName = groupList.AddEntry(name, group); + Register_Object(group); + } + return group; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntityManager::RemoveGroup(EntityGroup *group) +{ + Check(group); + groupList.DeleteEntry(group->groupName); + Unregister_Object(group); + delete group; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + EntityManager::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/NTTMGR.h b/MUNGA/NTTMGR.h new file mode 100644 index 0000000..4ca9889 --- /dev/null +++ b/MUNGA/NTTMGR.h @@ -0,0 +1,107 @@ +#pragma once + +#include "namelist.h" +#include "node.h" +#include "chain.h" +#include "network.h" + +class Entity; + +//########################################################################## +//######################### EntityGroup ############################## +//########################################################################## + +class EntityGroup : public Node +{ + friend class EntityManager; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +protected: + EntityGroup(); + ~EntityGroup(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Naming functions +// +public: + const char* GetGroupName() + { + Check(this); + return groupName; + } + +protected: + const char *groupName; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Grouping functions +// +public: + void Add(Entity *entity) + { + Check(this); + groupMembers.Add(Cast_Object(Node*,entity)); + } + + void Add(EntityGroup *group) + { + Check(this); + Check(group); + groupMembers.Add(group); + } + + ChainOf groupMembers; +}; + +//########################################################################## +//######################## EntityManager ############################# +//########################################################################## + +class EntityManager : public NetworkClient +{ + friend class Entity; + +//########################################################################## +// Shared Data support +// +protected: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//########################################################################## +// Construction and destruction support +// +public: + EntityManager(); + ~EntityManager(); + + void FryDeathRow(); + +protected: + EntityGroup *deathRow; + +//########################################################################## +// Message packet receiving +// +public: + void ReceiveNetworkPacket(NetworkPacket *packet, Receiver::Message *packet_message); + +//########################################################################## +// Entity grouping +// +public: + EntityGroup* UseGroup(const char *name); + EntityGroup* FindGroup(const char *name) + { + Check_Pointer(name); + return (EntityGroup*)groupList.FindObject(name); + } + void RemoveGroup(EntityGroup* group); + + Logical TestInstance() const; + +protected: + ObjectNameList groupList; +}; \ No newline at end of file diff --git a/MUNGA/OBJSTRM.cpp b/MUNGA/OBJSTRM.cpp new file mode 100644 index 0000000..70ac344 --- /dev/null +++ b/MUNGA/OBJSTRM.cpp @@ -0,0 +1,1203 @@ +#include "munga.h" +#pragma hdrstop + +#include "objstrm.h" +#include "fileutil.h" +#include "resource.h" +#include "cstr.h" +#include "namelist.h" +#include "notation.h" + +//############################################################################# +//########################## ObjectStream ############################### +//############################################################################# + +ObjectID ObjectStream::lastObjectID = NullObjectID; + +// +//############################################################################# +// ObjectStream +//############################################################################# +// +ObjectStream::ObjectStream() +{ + resourceFile = NULL; + macroSocket = NULL; +} + +// +//############################################################################# +// ObjectStream +//############################################################################# +// +ObjectStream::ObjectStream( + void *stream_start, + size_t stream_size +): + DynamicMemoryStream(stream_start, stream_size) +{ + resourceFile = NULL; + macroSocket = NULL; +} + +// +//############################################################################# +// ObjectStream +//############################################################################# +// +ObjectStream::ObjectStream(ResourceDescription *resource_description): + DynamicMemoryStream( + resource_description->resourceAddress, + resource_description->resourceSize + ) +{ + resourceFile = NULL; + macroSocket = NULL; +} + +// +//############################################################################# +// ~ObjectStream +//############################################################################# +// +ObjectStream::~ObjectStream() +{ + Verify(resourceFile == NULL); + Verify(macroSocket == NULL); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + ObjectStream::TestInstance() const +{ + DynamicMemoryStream::TestInstance(); + if (resourceFile != NULL) + { + Check(resourceFile); + } + if (macroSocket != NULL) + { + Check(macroSocket); + } + return True; +} + +// +//############################################################################# +// MakeUniqueObjectID +//############################################################################# +// +ObjectID + ObjectStream::MakeUniqueObjectID() +{ + lastObjectID++; + Verify(lastObjectID < ULONG_MAX); + return lastObjectID; +} + +// +//############################################################################# +// CreateObjects +//############################################################################# +// +void + ObjectStream::CreateObjects() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // While the stream is not empty, read objects... + //-------------------------------------------------------------------------- + // + while (GetBytesRemaining() > 0L) + { + // + //----------------------------------------------------------------------- + // Read the class ID and object ID + //----------------------------------------------------------------------- + // + Enumeration class_ID; + ObjectID object_ID; + + MemoryStream_Read(this, &class_ID); + MemoryStream_Read(this, &object_ID); + RewindPointer(sizeof(object_ID)); + RewindPointer(sizeof(class_ID)); + + Verify(class_ID != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + + // + //----------------------------------------------------------------------- + // Read the object + //----------------------------------------------------------------------- + // + RegisteredClass *object = MakeObjectImplementation(class_ID); + Register_Object(object); + + // + //----------------------------------------------------------------------- + // Perform post creation processing + //----------------------------------------------------------------------- + // + CreatedObjectImplementation(object, object_ID); + } +} + +// +//############################################################################# +// MakeObject +//############################################################################# +// +RegisteredClass* + ObjectStream::MakeObjectImplementation(Enumeration class_ID) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + + // + //----------------------------------------------------------------------- + // HACK - Constructors should be referenced through registration, for + // now just use a switch statement + //----------------------------------------------------------------------- + // + RegisteredClass *object = NULL; + + switch (class_ID) + { + default: + Dump(class_ID); + Fail("ObjectStream::MakeObject - Unknown class ID"); + break; + } + return object; +} + +// +//############################################################################# +// CreatedObject +//############################################################################# +// +void + ObjectStream::CreatedObjectImplementation( + RegisteredClass*, + ObjectID + ) +{ + Check(this); + + // + // Default behavior is to do nothing + // +} + +// +//############################################################################# +// BuildFromNotationFile +//############################################################################# +// +void + ObjectStream::BuildFromNotationFile( + NotationFile *notation_file, + ResourceFile *resource_file + ) +{ + Check(this); + Check(notation_file); + Check(resource_file); + + // + // Remember resource file + // + Verify(resourceFile == NULL); + resourceFile = resource_file; + + // + // Make the macro socket + // + macroSocket = new MacroSocket(NULL, True); + Register_Object(macroSocket); + + // + // Parse... + // + ParseNotationFile(notation_file); + + // + // Delete macros + // + { + MacroIterator iterator(macroSocket); + iterator.DeletePlugs(); + } + + // + // Clean up + // + Unregister_Object(macroSocket); + delete macroSocket; + macroSocket = NULL; + resourceFile = NULL; +} + +// +//############################################################################# +// ParseNotationFile +//############################################################################# +// +void + ObjectStream::ParseNotationFile(NotationFile *notation_file) +{ + Check(this); + Check(notation_file); + Verify(DoesNotationFileExist(notation_file)); + + // + //-------------------------------------------------------------------------- + // Parse pages + //-------------------------------------------------------------------------- + // + NameList *page_name_list; + NameList::Entry *page_entry; + + page_name_list = notation_file->MakePageList(); + Register_Object(page_name_list); + page_entry = page_name_list->GetFirstEntry(); + while (page_entry != NULL) + { + Check(page_entry); + + // + //----------------------------------------------------------------------- + // Read the page name + //----------------------------------------------------------------------- + // + CString inculde_name_string("include"); + CString macro_name_string("macro"); + CString page_name_string; + + Check_Pointer(page_entry->GetName()); + page_name_string = page_entry->GetName(); + + // + //----------------------------------------------------------------------- + // Skip "no-ops" + //----------------------------------------------------------------------- + // + if (page_name_string.operator [](0) == '!') + { + page_entry = page_entry->GetNextEntry(); + continue; + } + + // + //----------------------------------------------------------------------- + // Make the entry list + //----------------------------------------------------------------------- + // + NameList *entry_list = + notation_file->MakeEntryList( + (NotationFile::NotePage*)page_entry->GetData() + ); + Register_Object(entry_list); + + // + //----------------------------------------------------------------------- + // Read "included" files + //----------------------------------------------------------------------- + // + if (page_name_string == inculde_name_string) + { + ReadIncludedFiles(entry_list); + } + + // + //----------------------------------------------------------------------- + // Read "macros" + //----------------------------------------------------------------------- + // + else if (page_name_string == macro_name_string) + { + ReadMacros(entry_list); + } + + // + //----------------------------------------------------------------------- + // Read the class ID and object name + //----------------------------------------------------------------------- + // + else + { + Tell(" Class " << page_name_string << "\n"); + + // + // Get class ID and object ID + // + Enumeration class_ID; + ObjectID object_ID; + + class_ID = RegisteredClass::GetClassID(page_name_string); + if (class_ID == RegisteredClass::NullClassID) + { + Dump(page_name_string); + Dump(class_ID); + } + Verify(class_ID != RegisteredClass::NullClassID); + object_ID = MakeUniqueObjectID(); + Verify(object_ID != NullObjectID); + + // + // Get object name + // + const char *object_name; + CString object_name_string; + + PerformMacroReplacement(entry_list); + if ( + (object_name = (const char *)entry_list->FindData("name")) != NULL + ) + { + object_name_string = object_name; + } + Check(&object_name_string); + + // + //-------------------------------------------------------------------- + // Build the object stream from the page + //-------------------------------------------------------------------- + // + BuildFromPageImplementation(entry_list, class_ID, object_ID); + CleanupMacroReplacement(entry_list); + + // + //-------------------------------------------------------------------- + // Perform post build processing + //-------------------------------------------------------------------- + // + BuiltFromPageImplementation(class_ID, object_ID, object_name_string); + } + + Unregister_Object(entry_list); + delete entry_list; + page_entry = page_entry->GetNextEntry(); + } + + Unregister_Object(page_name_list); + delete page_name_list; +} + +// +//############################################################################# +// ReadIncludedFiles +//############################################################################# +// +void + ObjectStream::ReadIncludedFiles(NameList *entry_list) +{ + Check(this); + NameList::Entry *entry; + + Check(entry_list); + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("file")) + { + Check_Pointer(entry->GetChar()); + + CString included_file_name_string; + included_file_name_string = entry->GetChar(); + Tell(" File " << included_file_name_string << "\n"); + + NotationFile included_notation_file(included_file_name_string); + Check(&included_notation_file); + ParseNotationFile(&included_notation_file); + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +// ReadMacros +//############################################################################# +// +void + ObjectStream::ReadMacros(NameList *entry_list) +{ + Check(this); + NameList::Entry *entry; + + Check(entry_list); + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->GetData() != NULL) + { + Check_Pointer(entry->GetName()); + Check_Pointer(entry->GetChar()); + + CString macro_name; + MacroValue *macro_value; + MacroValue *current_macro_value; + + macro_name = entry->GetName(); + macro_value = new MacroValue(entry->GetChar()); + Register_Object(macro_value); + + Check(macroSocket); + if ((current_macro_value = macroSocket->Find(macro_name)) != NULL) + { + Unregister_Object(current_macro_value); + delete current_macro_value; + } + macroSocket->AddValue(macro_value, macro_name); + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +// PerformMacroReplacement +//############################################################################# +// +void + ObjectStream::PerformMacroReplacement(NameList *entry_list) +{ + Check(this); + NameList::Entry *entry; + + Check(entry_list); + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->GetData() != NULL) + { + CString value_string(entry->GetChar()); + + // + // Create a replacement string by matching each token in the + // value against the tokens in the macro table + // + CString replacement_string; + CString token_string; + CString delimiter_string(","); + CString empty_string; + int i = 0; + + Check(&value_string); + Check(&empty_string); + while ((token_string = value_string.GetNthToken(i)) != empty_string) + { + Check(&token_string); + + // + // Append delimter + // + if (replacement_string != empty_string) + { + replacement_string += delimiter_string; + } + + // + // Does a macro exist for this token? If so, use it, otherwise + // use the original token + // + #if 0 + MacroValue *macro_value; + + Check(macroSocket); + if ((macro_value = macroSocket->Find(token_string)) != NULL) + { + Check(macro_value); + Check(&replacement_string); + replacement_string += macro_value->GetItem(); + } + else + { + replacement_string += token_string; + } + #else + replacement_string += DeriveMacroValue(token_string); + #endif + i++; + } + + // + // Allocate memory for the string and assign it to the entry + // + size_t size; + char *pointer; + + size = replacement_string.Length() + 1; +#if 0 + pointer = (char*)malloc(size); +#else + pointer = new char[size]; +#endif + Register_Pointer(pointer); + Str_Copy(pointer, ((const char*)replacement_string), size); + entry->dataReference = pointer; + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +//############################################################################# +// +CString + ObjectStream::DeriveMacroValue(const CString &token_string) +{ + Check(this); + Check(&token_string); + + MacroValue *macro_value; + CString replacement_string = token_string; + + Check(macroSocket); + while ((macro_value = macroSocket->Find(replacement_string)) != NULL) + { + Check(macro_value); + replacement_string = macro_value->GetItem(); + } + return replacement_string; +} + +// +//############################################################################# +// CleanupMacroReplacement +//############################################################################# +// +void + ObjectStream::CleanupMacroReplacement(NameList *entry_list) +{ + Check(this); + NameList::Entry *entry; + + Check(entry_list); + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + Check(entry); + if (entry->GetData() != NULL) + { + char *replacement_string = entry->GetChar(); + + Unregister_Pointer(replacement_string); +#if 0 + free(replacement_string); +#else + delete[] replacement_string; +#endif + } + entry = entry->GetNextEntry(); + } +} + +// +//############################################################################# +// BuildFromPage +//############################################################################# +// +void + ObjectStream::BuildFromPageImplementation( + NameList*, + Enumeration class_ID, + ObjectID + ) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + + // + //----------------------------------------------------------------------- + // HACK - Page interpreters should be referenced through registration, + // for now just use a switch statement + //----------------------------------------------------------------------- + // + switch (class_ID) + { + default: + Dump(class_ID); + Fail("ObjectStream::BuildFromPage - Unknown class ID"); + break; + } +} + +// +//############################################################################# +// BuiltFromPage +//############################################################################# +// +void + ObjectStream::BuiltFromPageImplementation( + Enumeration, + ObjectID, + const CString& + ) +{ + Check(this); + + // + // Default behavior is to do nothing + // +} + +//############################################################################# +//####################### PlugStreamManager ############################# +//############################################################################# + +PlugStreamManager PlugStreamManager::plugStreamManager; + +#define PLUGSTREAMMANAGER_HASHSIZE (500) + +// +//############################################################################# +// PlugStreamManager +//############################################################################# +// +PlugStreamManager::PlugStreamManager(): + plugIndex(PLUGSTREAMMANAGER_HASHSIZE, NULL, True), + objectIDIndex(NULL, True) +{ +} + +// +//############################################################################# +// ~PlugStreamManager +//############################################################################# +// +PlugStreamManager::~PlugStreamManager() +{ + Cleanup(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + PlugStreamManager::TestInstance() const +{ + Node::TestInstance(); + Check(&plugIndex); + Check(&objectIDIndex); + return True; +} + +// +//############################################################################# +// Cleanup +//############################################################################# +// +void + PlugStreamManager::Cleanup() +{ + Check(this); + + // + // Delete static objects + // + { + TreeIteratorOf iterator(&objectIDIndex); + + Check(&iterator); + iterator.DeletePlugs(); + } + { + HashIteratorOf iterator(&plugIndex); + + Check(&iterator); + iterator.DeletePlugs(); + } +} + +// +//############################################################################# +// AddPlug +//############################################################################# +// +void + PlugStreamManager::AddPlug( + Plug *plug, + ObjectID object_ID + ) +{ + Check(plug); + Check(&plugStreamManager); + plugStreamManager.plugIndex.AddValue(plug, object_ID); +} + +// +//############################################################################# +// FindPlug +//############################################################################# +// +Plug* + PlugStreamManager::FindPlug(ObjectID object_ID) +{ + Check(&plugStreamManager); + return plugStreamManager.plugIndex.Find(object_ID); +} + +// +//############################################################################# +// AddPlugName +//############################################################################# +// +void + PlugStreamManager::AddPlugName( + ObjectID object_ID, + const CString &object_name_string + ) +{ + Check(&object_name_string); + + ObjectIDPlug *object_ID_plug = + new ObjectIDPlug(object_ID); + Register_Object(object_ID_plug); + + Check(&plugStreamManager.objectIDIndex); + #if DEBUG_LEVEL>0 + if (plugStreamManager.objectIDIndex.Find(object_name_string) != NULL) + { + Dump(object_name_string); + } + #endif + plugStreamManager.objectIDIndex.AddValue( + object_ID_plug, + object_name_string + ); +} + +// +//############################################################################# +// FindPlugName +//############################################################################# +// +ObjectID + PlugStreamManager::FindPlugName(const CString &object_name_string) +{ + Check(&object_name_string); + Check(&plugStreamManager.objectIDIndex); + ObjectIDPlug *plug = plugStreamManager.objectIDIndex.Find(object_name_string); + if (plug != NULL) + { + Check(plug); + return plug->GetItem(); + } + return NullObjectID; +} + +//############################################################################# +//########################### PlugStream ################################ +//############################################################################# + +// +//############################################################################# +// PlugStream +//############################################################################# +// +PlugStream::PlugStream() +{ + localPlugIndex = NULL; + localObjectIDIndex = NULL; +} + +// +//############################################################################# +// PlugStream +//############################################################################# +// +PlugStream::PlugStream( + void *stream_start, + size_t stream_size +): + ObjectStream(stream_start, stream_size) +{ + localPlugIndex = NULL; + localObjectIDIndex = NULL; +} + +// +//############################################################################# +// PlugStream +//############################################################################# +// +PlugStream::PlugStream(ResourceDescription *resource_description): + ObjectStream(resource_description) +{ + localPlugIndex = NULL; + localObjectIDIndex = NULL; +} + +// +//############################################################################# +// ~PlugStream +//############################################################################# +// +PlugStream::~PlugStream() +{ + Verify(localPlugIndex == NULL); + Verify(localObjectIDIndex == NULL); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + PlugStream::TestInstance() const +{ + ObjectStream::TestInstance(); + if (localPlugIndex != NULL) + { + Check(localPlugIndex); + } + if (localObjectIDIndex != NULL) + { + Check(localObjectIDIndex); + } + return True; +} + +// +//############################################################################# +// CreateObjects +//############################################################################# +// +void + PlugStream::CreateObjects() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Keep local object address index + //-------------------------------------------------------------------------- + // + LocalPlugIndex + local_index(NULL, True); + + Check(&local_index); + localPlugIndex = &local_index; + + // + //-------------------------------------------------------------------------- + // Parse object stream + //-------------------------------------------------------------------------- + // + ObjectStream::CreateObjects(); + + // + //-------------------------------------------------------------------------- + // Forget local object address index + //-------------------------------------------------------------------------- + // + localPlugIndex = NULL; +} + +// +//############################################################################# +// CreatedObject +//############################################################################# +// +void + PlugStream::CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ) +{ + Check(this); + AddLocalPlug(Cast_Object(Plug*, object), object_ID); +} + +// +//############################################################################# +// AddLocalPlugAddress +//############################################################################# +// +void + PlugStream::AddLocalPlug( + Plug *plug, + ObjectID object_ID + ) +{ + Check(this); + Check(localPlugIndex); + localPlugIndex->AddValue(plug, object_ID); +} + +// +//############################################################################# +// AddGlobalPlugAddress +//############################################################################# +// +void + PlugStream::AddGlobalPlug( + Plug *plug, + ObjectID object_ID + ) +{ + Check(this); + #if 0 + Check(&plugStreamManager); + plugStreamManager.globalPlugIndex.AddValue(plug, object_ID); + #else + PlugStreamManager::AddPlug(plug, object_ID); + #endif +} + +// +//############################################################################# +// FindPlug +//############################################################################# +// +Plug* + PlugStream::FindPlug(ObjectID object_ID) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Search the local address index + //-------------------------------------------------------------------------- + // + Plug *plug; + + Check(localPlugIndex); + if ((plug = localPlugIndex->Find(object_ID)) != NULL) + { + Check(plug); + return plug; + } + + // + //-------------------------------------------------------------------------- + // Search the global address index + //-------------------------------------------------------------------------- + // + #if 0 + Check(&plugStreamManager); + if ((plug = plugStreamManager.globalPlugIndex.Find(object_ID)) != NULL) + { + Check(plug); + return plug; + } + return NULL; + #else + if ((plug = PlugStreamManager::FindPlug(object_ID)) != NULL) + { + Check(plug); + return plug; + } + return NULL; + #endif +} + +// +//############################################################################# +// BuildFromNotationFile +//############################################################################# +// +void + PlugStream::BuildFromNotationFile( + NotationFile *notation_file, + ResourceFile *resource_file + ) +{ + Check(this); + Check(notation_file); + Check(resource_file); + + // + //-------------------------------------------------------------------------- + // Keep local object ID index + //-------------------------------------------------------------------------- + // + LocalObjectIDIndex + local_index(NULL, True); + + Check(&local_index); + localObjectIDIndex = &local_index; + + // + //-------------------------------------------------------------------------- + // Parse notation file + //-------------------------------------------------------------------------- + // + ObjectStream::BuildFromNotationFile(notation_file, resource_file); + + // + //-------------------------------------------------------------------------- + // Forget local object ID index + //-------------------------------------------------------------------------- + // + { + VChainIteratorOf iterator(&local_index); + Check(&iterator); + iterator.DeletePlugs(); + } + localObjectIDIndex = NULL; +} + +// +//############################################################################# +// BuiltFromPage +//############################################################################# +// +void + PlugStream::BuiltFromPageImplementation( + Enumeration, + ObjectID object_ID, + const CString &object_name_string + ) +{ + Check(this); + Check(&object_name_string); + AddLocalObjectID(object_ID, object_name_string); +} + +// +//############################################################################# +// AddLocalObjectID +//############################################################################# +// +void + PlugStream::AddLocalObjectID( + ObjectID object_ID, + const CString &object_name_string + ) +{ + Check(this); + Check(&object_name_string); + + ObjectIDPlug *object_ID_plug = + new ObjectIDPlug(object_ID); + Register_Object(object_ID_plug); + + Check(localObjectIDIndex); + #if DEBUG_LEVEL>0 + if (localObjectIDIndex->Find(object_name_string) != NULL) + { + Dump(object_name_string); + } + #endif + localObjectIDIndex->AddValue(object_ID_plug, object_name_string); +} + +// +//############################################################################# +// AddGlobalObjectID +//############################################################################# +// +void + PlugStream::AddGlobalObjectID( + ObjectID object_ID, + const CString &object_name_string + ) +{ + Check(this); + Check(&object_name_string); + + PlugStreamManager::AddPlugName(object_ID, object_name_string); +} + +// +//############################################################################# +// FindObjectID +//############################################################################# +// +ObjectID + PlugStream::FindObjectID(const CString &object_name_string) +{ + Check(this); + Check(&object_name_string); + + // + //-------------------------------------------------------------------------- + // Search the local object ID index + //-------------------------------------------------------------------------- + // + ObjectIDPlug *plug; + + Check(localObjectIDIndex); + if ((plug = localObjectIDIndex->Find(object_name_string)) != NULL) + { + Check(plug); + return plug->GetItem(); + } + + // + //-------------------------------------------------------------------------- + // Search the global address index + //-------------------------------------------------------------------------- + // + #if 0 + Check(&plugStreamManager); + plug = plugStreamManager.globalObjectIDIndex.Find(object_name_string); + if (plug != NULL) + { + Check(plug); + return plug->GetItem(); + } + return NULL; + #else + return PlugStreamManager::FindPlugName(object_name_string); + #endif +} + +// +//############################################################################# +// PlugStream_FindEntryAndWriteObjectID +//############################################################################# +// +void + PlugStream_FindEntryAndWriteObjectID( + PlugStream *stream, + NameList *name_list, + const CString &entry_name + ) +{ + Check(stream); + Check(name_list); + Check(&entry_name); + + void *entry_data; + CString object_name; + ObjectID object_ID; + + entry_data = name_list->FindData(entry_name); + if (entry_data == NULL) + { + std::cout << "PlugStream_FindEntryAndWriteObjectID - entry_name == "; + std::cout << entry_name << "\n"; + Fail("PlugStream_FindEntryAndWriteObjectID - entry_data == NULL"); + } + Check_Pointer(entry_data); + object_name = (const char *)entry_data; + + Check(stream); + object_ID = stream->FindObjectID(object_name); + if (object_ID == NullObjectID) + { + std::cout << "PlugStream_FindEntryAndWriteObjectID - object_name == "; + std::cout << object_name << "\n"; + Fail("PlugStream_FindEntryAndWriteObjectID - object_ID == NullObjectID"); + } + Verify(object_ID != NullObjectID); + MemoryStream_Write(stream, &object_ID); +} diff --git a/MUNGA/OBJSTRM.h b/MUNGA/OBJSTRM.h new file mode 100644 index 0000000..ec6086f --- /dev/null +++ b/MUNGA/OBJSTRM.h @@ -0,0 +1,333 @@ +#pragma once + +#include "memstrm.h" +#include "node.h" +#include "hash.h" +#include "tree.h" +#include "cstr.h" + +class NotationFile; +class NameList; +class CString; +class ResourceFile; +class ResourceDescription; + +//########################################################################## +//######################### ObjectStream ############################# +//########################################################################## + +class ObjectStream: + public DynamicMemoryStream +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction and testing +// +public: + ObjectStream(); + ObjectStream( + void *stream_start, + size_t stream_size + ); + ObjectStream(ResourceDescription *resource_description); + ~ObjectStream(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Object creation +// +public: + virtual void + CreateObjects(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Notation file parsing +// +public: + virtual void + BuildFromNotationFile( + NotationFile *notation_file, + ResourceFile *resource_file + ); + + ResourceFile* + GetResourceFile() + {return resourceFile;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Object ID generation +// +protected: + static ObjectID + MakeUniqueObjectID(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +protected: + virtual RegisteredClass* + MakeObjectImplementation(Enumeration class_ID); + + virtual void + CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ); + + virtual void + BuildFromPageImplementation( + NameList *name_list, + Enumeration class_ID, + ObjectID object_ID + ); + + virtual void + BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name_string + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + void + ParseNotationFile(NotationFile *notation_file); + void + ReadIncludedFiles(NameList *entry_list); + void + ReadMacros(NameList *entry_list); + + void + PerformMacroReplacement(NameList *entry_list); + CString + DeriveMacroValue(const CString &token_string); + void + CleanupMacroReplacement(NameList *entry_list); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + typedef PlugOf + MacroValue; + typedef TreeOf + MacroSocket; + typedef TreeIteratorOf + MacroIterator; + + static ObjectID + lastObjectID; + ResourceFile + *resourceFile; + MacroSocket + *macroSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ ObjectIDPlug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef PlugOf + ObjectIDPlug; + +//########################################################################## +//###################### PlugStreamManager ########################### +//########################################################################## + +class PlugStreamManager: +public Node +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Plug stream types +// +public: + typedef HashOf + PlugIndex; + + typedef TreeOf + ObjectIDIndex; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction and testing +// +public: +PlugStreamManager(); + ~PlugStreamManager(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Program termination +// +public: +void + Cleanup(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Manager Accessors +// +public: + static void + AddPlug( + Plug *plug, + ObjectID object_ID + ); + + static Plug* + FindPlug(ObjectID object_ID); + + static void + AddPlugName( + ObjectID object_ID, + const CString &object_name_string + ); + + static ObjectID + FindPlugName(const CString &object_name_string); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + PlugIndex + plugIndex; + ObjectIDIndex + objectIDIndex; + + static PlugStreamManager + plugStreamManager; +}; + +//########################################################################## +//########################## PlugStream ############################## +//########################################################################## + +class PlugStream: +public ObjectStream +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Plug stream types +// +public: + typedef VChainOf + LocalPlugIndex; + + typedef VChainOf + LocalObjectIDIndex; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction and testing +// +public: + PlugStream(); + PlugStream( + void *stream_start, + size_t stream_size + ); + PlugStream(ResourceDescription *resource_description); + ~PlugStream(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Object creation and utilities +// +public: + void + CreateObjects(); + + void + AddLocalPlug( + Plug *plug, + ObjectID object_ID + ); + + void + AddGlobalPlug( + Plug *plug, + ObjectID object_ID + ); + + Plug* + FindPlug(ObjectID object_ID); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Notation file parsing +// +public: + void + BuildFromNotationFile( + NotationFile *notation_file, + ResourceFile *resource_file + ); + + void + AddLocalObjectID( + ObjectID object_ID, + const CString &object_name_string + ); + + void + AddGlobalObjectID( + ObjectID object_ID, + const CString &object_name_string + ); + + ObjectID + FindObjectID(const CString &object_name_string); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +protected: + void + CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ); + + void + BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name_string + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + LocalPlugIndex + *localPlugIndex; + LocalObjectIDIndex + *localObjectIDIndex; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugStream functions ~~~~~~~~~~~~~~~~~~~~~~~~ + +template void +PlugStream_ReadObjectIDAndFindPlug( + PlugStream *stream, + T** type_pointer + ) +{ +Check(stream); + Check_Pointer(type_pointer); + + ObjectID object_ID; + Plug *plug; + + MemoryStream_Read(stream, &object_ID); + plug = stream->FindPlug(object_ID); + *type_pointer = Cast_Object(T*, plug); +} + +void +PlugStream_FindEntryAndWriteObjectID( + PlugStream *stream, + NameList *name_list, + const CString &entry_name + ); diff --git a/MUNGA/ORIGIN.cpp b/MUNGA/ORIGIN.cpp new file mode 100644 index 0000000..f6397b5 --- /dev/null +++ b/MUNGA/ORIGIN.cpp @@ -0,0 +1,116 @@ +#include "munga.h" +#pragma hdrstop + +#include "origin.h" +#include "motion.h" +#include "linmtrx.h" + +const Origin Origin::Identity(Point3D::Identity, Quaternion::Identity); + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const volatile Origin *) + { + return false; + } +#endif + +// +//########################################################################### +//########################################################################### +// +Origin::Origin(const LinearMatrix &matrix) +{ + Check(&matrix); + linearPosition = matrix; + angularPosition = matrix; +} + +// +//########################################################################### +//########################################################################### +// +Origin& Origin::operator=(const Origin &origin) +{ + Check_Pointer(this); + Check(&origin); + + angularPosition = origin.angularPosition; + linearPosition = origin.linearPosition; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Origin& Origin::operator=(const LinearMatrix &matrix) +{ + Check_Pointer(this); + Check(&matrix); + + angularPosition = matrix; + linearPosition = matrix; + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical Origin::operator==(const Origin &origin) const +{ + Check(this); + return (memcmp(this, &origin, sizeof(Origin)) == 0); +} + +// +//########################################################################### +//########################################################################### +// +Origin& Origin::AddScaled(const Origin& source, const Motion& delta, Scalar t) +{ + Check_Pointer(this); + Check(&source); + Check(&delta); + Verify(t >= 0.0f); + + linearPosition.AddScaled(source.linearPosition, delta.linearMotion, t); + angularPosition.AddScaled(source.angularPosition, delta.angularMotion, t); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Origin& Origin::Lerp(const Origin &start, const Origin &end, Scalar t) +{ + Check_Pointer(this); + Check(&start); + Check(&end); + + linearPosition.Lerp(start.linearPosition, end.linearPosition, t); + angularPosition.Lerp(start.angularPosition, end.angularPosition, t); + Check(this); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +std::ostream& operator<<(std::ostream& stream, const Origin& p) +{ + return stream << '{' << p.linearPosition << ',' << p.angularPosition << '}'; +} + +// +//########################################################################### +//########################################################################### +// +Logical Origin::TestInstance() const +{ + return angularPosition.TestInstance(); +} + +#if defined(TEST_CLASS) + #include "origin.tcp" +#endif diff --git a/MUNGA/ORIGIN.h b/MUNGA/ORIGIN.h new file mode 100644 index 0000000..7e979f0 --- /dev/null +++ b/MUNGA/ORIGIN.h @@ -0,0 +1,80 @@ +#pragma once + +#include "point3d.h" +#include "rotation.h" + +class Motion; + +class Origin +{ +#if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Origin *); +#endif + +public: + Point3D linearPosition; + Quaternion angularPosition; + + static const Origin Identity; + + Origin() {} + Origin(const Point3D &t, const EulerAngles& q) + { + Check(&t); + Check(&q); + linearPosition = t; + angularPosition = q; + } + Origin(const Point3D &t, const Quaternion& q) + { + Check(&t); + Check(&q); + linearPosition = t; + angularPosition = q; + } + Origin(const LinearMatrix &matrix); + + Origin& operator=(const Origin& p); + Origin& operator=(const Point3D& p) + { + Check_Pointer(this); + Check(&p); + linearPosition = p; + return *this; + } + Origin& operator=(const EulerAngles& q) + { + Check_Pointer(this); + Check(&q); + angularPosition = q; + return *this; + } + Origin& operator=(const YawPitchRoll& q) + { + Check_Pointer(this); + Check(&q); + angularPosition = q; + return *this; + } + Origin& operator=(const Quaternion& q) + { + Check_Pointer(this); + Check(&q); + angularPosition = q; + return *this; + } + Origin& operator=(const LinearMatrix &m); + + Logical operator==(const Origin&) const; + + Origin& AddScaled(const Origin& source, const Motion& delta, Scalar t); + Origin& Lerp(const Origin& start, const Origin& end, Scalar t); + + friend std::ostream& operator<<(std::ostream& stream, const Origin& p); + Logical TestInstance() const; + static Logical TestClass(); +}; + +inline Point3D& Point3D::operator=(const Origin& p) { return operator=(p.linearPosition); } +inline EulerAngles& EulerAngles::operator=(const Origin& p) { return operator=(p.angularPosition); } +inline Quaternion& Quaternion::operator=(const Origin& p) { return operator=(p.angularPosition); } diff --git a/MUNGA/PLANE.cpp b/MUNGA/PLANE.cpp new file mode 100644 index 0000000..74603c6 --- /dev/null +++ b/MUNGA/PLANE.cpp @@ -0,0 +1,192 @@ +#include "munga.h" +#pragma hdrstop + +#include "plane.h" +#include "sphere.h" +#include "linmtrx.h" +#include "extntbox.h" + +// +//############################################################################# +//############################################################################# +// +Plane::Plane( + const Point3D& p0, + const Point3D& p1, + const Point3D& p2 +) +{ + Vector3D v1,v2; + v1.Subtract(p1, p0); + v2.Subtract(p2, p1); + + Vector3D axis; + axis.Cross(v1, v2); + Verify(!Small_Enough(axis.Length())); + normal = axis; + offset = -(normal * p0); + Verify(Small_Enough(DistanceTo(p1))); + Verify(Small_Enough(DistanceTo(p2))); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +Plane& + Plane::Multiply( + const Plane &p, + const LinearMatrix &m + ) +{ + Check_Pointer(this); + Check(&p); + Check(&m); + + normal.x = p.normal.x*m(0,0) + p.normal.y*m(1,0) + p.normal.z*m(2,0); + normal.y = p.normal.x*m(0,1) + p.normal.y*m(1,1) + p.normal.z*m(2,1); + normal.z = p.normal.x*m(0,2) + p.normal.y*m(1,2) + p.normal.z*m(2,2); + offset = + p.normal.x*m(3,0) + p.normal.y*m(3,1) + p.normal.z*m(3,2) + p.offset; + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::Contains(const Point3D &point) const +{ + return normal * point <= offset; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsSomeOf(const Sphere &sphere) const +{ + return normal*sphere.center - offset <= sphere.radius; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsAllOf(const Sphere &sphere) const +{ + return offset - normal*sphere.center >= sphere.radius; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsSomeOf(const ExtentBox &box) const +{ + Check(this); + Check(&box); + + Point3D test; + test.x = (normal.x > 0.0f) ? box.minX : box.maxX; + test.y = (normal.y > 0.0f) ? box.minY : box.maxY; + test.z = (normal.z > 0.0f) ? box.minZ : box.maxZ; + return Contains(test); +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::ContainsAllOf(const ExtentBox &box) const +{ + Check(this); + Check(&box); + + Point3D test; + test.x = (normal.x < 0.0f) ? box.minX : box.maxX; + test.y = (normal.y < 0.0f) ? box.minY : box.maxY; + test.z = (normal.z < 0.0f) ? box.minZ : box.maxZ; + return Contains(test); +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::Intersect(const Sphere &sphere) const +{ + Scalar dist = normal*sphere.center - offset; + return Abs(dist) <= sphere.radius; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Plane::Intersect(const ExtentBox &box) const +{ + if (!ContainsSomeOf(box)) + { + return False; + } + Plane inverse(-normal.x, -normal.y, -normal.z, -offset); + return inverse.ContainsSomeOf(box); +} + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator<<(std::ostream& Stream, const Plane &A_Plane) +{ + Stream << "\n\tPlane Normal: " << A_Plane.normal; + return Stream << "\n\tOffset: " << -A_Plane.offset; +} + +// +//########################################################################### +//########################################################################### +// +Logical Plane::TestInstance() const +{ + return True; +} + +Scalar + Plane::CalculateX(Scalar y, Scalar z) +{ + Check(this); + Verify(!Small_Enough(normal.x)); + Scalar result = (offset - y*normal.y - z*normal.z)/normal.x; + Check_Fpu(); + return result; +} + +Scalar + Plane::CalculateY(Scalar x, Scalar z) +{ + Check(this); + Verify(!Small_Enough(normal.y)); + Scalar result = (offset - x*normal.x - z*normal.z)/normal.y; + Check_Fpu(); + return result; +} +Scalar + Plane::CalculateZ(Scalar x, Scalar y) +{ + Check(this); + Verify(!Small_Enough(normal.z)); + Scalar result = (offset - x*normal.x - y*normal.y)/normal.z; + Check_Fpu(); + return result; +} diff --git a/MUNGA/PLANE.h b/MUNGA/PLANE.h new file mode 100644 index 0000000..b01b96c --- /dev/null +++ b/MUNGA/PLANE.h @@ -0,0 +1,76 @@ +#pragma once + +#include "normal.h" +#include "point3d.h" + +class Sphere; +class ExtentBox; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Plane ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Plane SIGNATURED +{ +public: + // + // The plane equation is P*N = 0, where P is a homogeneous point, and N + // is a quadruple representing the plane. Due to some slight + // improvements gained when the offset is negated, a negative offset is + // stored. This must be taken into account whenever we are doing the + // point-to-plane dot product, where we must do a subtraction instead of + // an addition + // + Normal normal; + Scalar offset; + + // + // Constructors + // + Plane() {} + Plane(Scalar x, Scalar y, Scalar z, Scalar offset) : normal(x,y,z), offset(offset) {} + Plane(const Normal& n, Scalar offset) : normal(n), offset(offset) {} + Plane(const Point3D& p0, const Point3D& p1, const Point3D& p2); + + // + // Transform functions + // + Plane& Multiply(const Plane &p, const LinearMatrix &m); + Plane& operator*=(const LinearMatrix &m) + { + Check(this); + Plane t(*this); + return Multiply(t,m); + } + + // + // half-space division functions + // + Logical SeenBy(const Vector3D &A_Vector) const { return normal * A_Vector < 0.0; } + Logical SeenBy(const Point3D &A_Point) const { return normal * A_Point > offset; } + Scalar DistanceTo(const Point3D& A_Point) const { return normal * A_Point - offset; } + + // + // half-space containment functions + // + Logical Contains(const Point3D &point) const; + Logical ContainsSomeOf(const Sphere &sphere) const; + Logical ContainsAllOf(const Sphere &sphere) const; + Logical ContainsSomeOf(const ExtentBox &box) const; + Logical ContainsAllOf(const ExtentBox &box) const; + + // + // plane surface intersection functions + // + Logical Intersect(const Sphere &sphere) const; + Logical Intersect(const ExtentBox &box) const; + + friend std::ostream& operator<<(std::ostream& Stream, const Plane &A_Plane); + Logical TestInstance() const; + static Logical TestClass(); + + // + // Equation solutions + // + Scalar CalculateX(Scalar y, Scalar z); + Scalar CalculateY(Scalar x, Scalar z); + Scalar CalculateZ(Scalar x, Scalar y); +}; diff --git a/MUNGA/PLAYER.cpp b/MUNGA/PLAYER.cpp new file mode 100644 index 0000000..73bf11a --- /dev/null +++ b/MUNGA/PLAYER.cpp @@ -0,0 +1,876 @@ +#include "munga.h" +#pragma hdrstop + +#include "player.h" +#include "icom.h" +#include "camship.h" +#include "dropzone.h" +#include "mission.h" +#include "audio.h" +#include "director.h" +#include "app.h" +#include "hostmgr.h" +#include "nttmgr.h" +#include "console.h" +#include "appmsg.h" + +//############################################################################# +//####################### Player::StatusMessage ######################### +//############################################################################# + +Player__StatusMessage::Player__StatusMessage(Player *player_involved, int message_type, Scalar display_time) +{ + playerInvolved = player_involved; + messageType = message_type; + displayTime = display_time; +} + +//############################################################################# +//############################### Player ################################ +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Player::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(), "Player"); + return &classDerivations; +} + +Player::SharedData + Player::DefaultData( + Player::GetClassDerivations(), + Player::GetMessageHandlers(), + Player::GetAttributeIndex(), + Player::StateCount, + (Entity::MakeHandler)Player::Make + ); + +//############################################################################# +// Attribute Support +// + +const Player::IndexEntry + Player::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Player, CurrentScore, currentScore), + ATTRIBUTE_ENTRY(Player, PlayerRanking, playerRanking), + ATTRIBUTE_ENTRY(Player, DropZoneLocation, dropZoneLocation), + ATTRIBUTE_ENTRY(Player, StatusMessagePointer,statusMessagePointer), + ATTRIBUTE_ENTRY(Player, PlayerBitmapIndex, playerBitmapIndex), + ATTRIBUTE_ENTRY(Player, PlayerHighlighted, playerHighlighted) +}; + +Player::AttributeIndexSet& Player::GetAttributeIndex() +{ + static Player::AttributeIndexSet attributeIndex(ELEMENTS(Player::AttributePointers), + Player::AttributePointers, + Entity::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Player::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Player, DropZoneReply), + MESSAGE_ENTRY(Player, Score), + MESSAGE_ENTRY(Player, VehicleDead), + MESSAGE_ENTRY(Player, MissionStarting), + MESSAGE_ENTRY(Player, MissionEnding) +}; + +Receiver::MessageHandlerSet& Player::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(Player::MessageHandlerEntries), Player::MessageHandlerEntries, Entity::GetMessageHandlers()); + return messageHandlers; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::MissionStartingMessageHandler(Message *) +{ + Check(this); + Tell("Player::MissionStartingMessageHandler - starting fade in\n"); + fadeTimeRemaining = 3.0f; + SetSimulationState(MissionStartingState); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::MissionEndingMessageHandler(Message *) +{ + Check(this); + fadeTimeRemaining = 3.0f; + ForceUpdate(); + SetSimulationState(MissionEndingState); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Enumeration + Player::GetAudioRepresentation( +#if DEBUG_LEVEL>0 + Entity *linked_entity +#else + Entity * +#endif + ) +{ + Check(this); + Check(linked_entity); + Check_Fpu(); + + return + (GetInstance() == MasterInstance) ? + InternalAudioRepresentation : ExternalAudioRepresentation; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::ScoreMessageHandler(ScoreMessage *message) +{ + Check(this); + Check(message); + + currentScore += message->scoreAward; + + // + // HACK - ECH 7/6/95 - Allow the player vehicle to respond to score + // messages, allows attribute system to be used for scoring + // + Check(playerVehicle); + playerVehicle->RespondToScoreMessage(message); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::DropZoneReplyMessageHandler( + DropZone::ReplyMessage * //message + ) +{ + Check(this); + Fail("Drop zone reply should not be handled by base player class!\n"); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::CreatePlayerVehicle(Origin camera_origin) +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create any MUNGA level vehicles + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (IsCameraShipPlayer()) + { + Check(application); + ResourceFile *resources = application->GetResourceFile(); + Check(resources); + Check_Pointer(playerMission->GetGameModel()); + + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + ResourceDescription *camera_res = + resources->FindResourceDescription( + playerMission->GetGameModel(), + ResourceDescription::ModelListResourceType + ); + Check(camera_res); + CameraShip::MakeMessage + create_camera( + CameraShip::MakeMessageID, + sizeof(CameraShip::MakeMessage), + EntityID(host_manager->GetLocalHostID()), + CameraShipClassID, + EntityID::Null, + camera_res->resourceID, + CameraShip::DefaultFlags, + camera_origin, + Motion::Identity, + Motion::Identity + ); + CameraShip *camera = + (CameraShip*)application->MakeAndLinkViewpointEntity(&create_camera); + Register_Object(camera); + playerVehicle = camera; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::VehicleDeadMessageHandler(VehicleDeadMessage *message) +{ + Check(this); + Check(message); + Check(application); + + + //DEBUG_STREAM << "VEHICLEDEAD : " << endl << std::flush; + + // + //------------------------------------------------------------------------- + // If we have let the player fry, send a message to the dropzone to give us + // a new location to return to + //------------------------------------------------------------------------- + // + if ( + message->deathCount == deathCount + && GetSimulationState() != DropZoneAcquiredState) + { + DropZone *dropzone; + + + + // + //--------------------------------------------------------------------- + // If no dropzone has been assigned to this death, find the closest one + //--------------------------------------------------------------------- + // + if (message->dropZoneID == EntityID::Null) + { + + //DEBUG_STREAM << " Find Closest" << endl << std::flush; + + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *dropzones = entity_manager->FindGroup("DropZones"); + Check(dropzones); + ChainIteratorOf iterator(dropzones->groupMembers); + + DropZone *closest_dropzone; + Vector3D range; + Scalar closest_range; + + while ((dropzone = (DropZone*)iterator.ReadAndNext()) != NULL) + { + Check(dropzone); + + if (!strnicmp(dropzone->GetDropZoneName(), "win", 3)) + { + continue; + } + + closest_dropzone = dropzone; + range.Subtract( + localOrigin.linearPosition, + dropzone->localOrigin.linearPosition + ); + closest_range = range.LengthSquared(); + break; + } + + while ((dropzone = (DropZone*)iterator.ReadAndNext()) != NULL) + { + Check(dropzone); + if (!strnicmp(dropzone->GetDropZoneName(), "win", 3)) + { + continue; + } + range.Subtract( + localOrigin.linearPosition, + dropzone->localOrigin.linearPosition + ); + Scalar len = range.LengthSquared(); + if (len < closest_range) + { + closest_dropzone = dropzone; + closest_range = len; + } + } + message->dropZoneID = closest_dropzone->GetEntityID(); + dropzone = closest_dropzone; + } + + // + //---------------------------------------------- + // Otherwise, get this one from the host manager + //---------------------------------------------- + // + else + { + //DEBUG_STREAM << " Use Assigned" << endl << std::flush; + + HostManager *host = application->GetHostManager(); + Check(host); + dropzone = + Cast_Object( + DropZone*, + host->GetEntityPointer(message->dropZoneID) + ); + } + + Check(dropzone); + DropZone::AssignDropZoneMessage + request( + DropZone::AssignDropZoneMessageID, + sizeof(DropZone::AssignDropZoneMessage), + GetEntityID(), + DropZoneReplyMessageID, + deathCount + ); + dropzone->Dispatch(&request); + Time when = Now(); + when += 2.0f; + application->Post(HighEventPriority, this, message, when); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::HuntForDropZone(Scalar) +{ + Check(this); + Check(playerMission); + + // + //---------------------------------------------------------------------- + // See if our designated drop zone is around yet. If the dropzone group + // does not exist, then no dropzones at all are available + //---------------------------------------------------------------------- + // + Check(application); + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *dropzones = entity_manager->FindGroup("DropZones"); + if (!dropzones) + { + Check_Fpu(); + return; + } + + Check(dropzones); + ChainIteratorOf iterator(dropzones->groupMembers); + DropZone *dropzone; + const char* zone_name = playerMission->GetDropZoneName(); + while ((dropzone = (DropZone*)iterator.ReadAndNext()) != NULL) + { + if (!strcmp(dropzone->GetDropZoneName(), zone_name)) + { + break; + } + } + + // + //------------------------------------------------------------------------ + // If it is, reset our performance, and send a message to the drop zone to + // give us a location + //------------------------------------------------------------------------ + // + if (dropzone) + { + + //DEBUG_STREAM << "FOUND DROPZONE" << endl << std::flush; + + Check(dropzone); + SetPerformance(&Player::DoNothingOnce); + VehicleDeadMessage + dead( + VehicleDeadMessageID, + sizeof(VehicleDeadMessage), + dropzone->GetEntityID() + ); + dead.deathCount = -2; + + DropZone::AssignDropZoneMessage + request( + DropZone::AssignDropZoneMessageID, + sizeof(DropZone::AssignDropZoneMessage), + GetEntityID(), + DropZoneReplyMessageID, + deathCount + ); + dropzone->Dispatch(&request); + Time when = Now(); + when += 2.0f; + application->Post(HighEventPriority, this, &dead, when); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::ManageApplicationStatus(Scalar time_slice) +{ + // + //-------------------------------------------------------------------------- + // If we are in the game start/stop phase, count the timer down and send the + // appropriate message to the application when done + //-------------------------------------------------------------------------- + // + Check(this); + Check(application); + switch (GetSimulationState()) + { + case MissionStartingState: + Verify(fadeTimeRemaining <= 3.0f); + fadeTimeRemaining -= time_slice; + if (fadeTimeRemaining <= 0.0f) + { + SetSimulationState(VehicleTranslocatedState); + Check(application); + switch (application->GetApplicationState()) + { + case Application::LaunchingMission: + { + Application::RunMissionMessage message; + application->Dispatch(&message); + } + break; + case Application::ResumingMission: + { + Application::ResumeMissionMessage message; + application->Dispatch(&message); + } + break; + } + } + break; + case MissionEndingState: + fadeTimeRemaining -= time_slice; + if (fadeTimeRemaining <= 0.0f) + { + Check(application); + switch (application->GetApplicationState()) + { + case Application::EndingMission: + { + // Fill in appropriate exit code here. GAH + Application::StopMissionMessage message(NullExitCodeID); + application->Dispatch(&message); + } + break; + case Application::AbortingMission: + { + // Fill in appropriate exit code here. GAH + Application::AbortMissionMessage message(NullExitCodeID); + application->Dispatch(&message); + } + break; + case Application::SuspendingMission: + { + Application::SuspendMissionMessage message; + application->Dispatch(&message); + } + break; + } + } + break; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::CameraShipSimulation(Scalar time_slice) +{ + Check(this); + CalcRanking(); + + ManageApplicationStatus(time_slice); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::PlayerSimulation(Scalar time_slice) +{ + Check(this); + + //------------------------------- + // Calculate the player's ranking + //------------------------------- + CalcRanking(); + + //---------------------------------- + // ...manage the application status? + //---------------------------------- + ManageApplicationStatus(time_slice); + + //------------------------------- + // Copy vehicle position + //------------------------------- + if (playerVehicle) + { + Check(playerVehicle); + localOrigin = playerVehicle->localOrigin; + localToWorld = playerVehicle->localToWorld; + } + + //--------------------------------- + // Service the status message queue + //--------------------------------- + StatusMessageUpdate(time_slice); + + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::GoToVehicle(Scalar) +{ + Check(this); + if (playerVehicle) + { + Check(playerVehicle); + localOrigin = playerVehicle->localOrigin; + localToWorld = playerVehicle->localToWorld; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + Player::CalcRanking() +{ + + // + //--------------------------------------- + // Get all players from the entity group + //--------------------------------------- + // + EntityGroup *player_group = + application->GetEntityManager()->FindGroup("Players"); + if(player_group) + { + int num_players = 0; + Player *active_player; + // + //----------------------------------------------------- + // Iterate through the players add to the sorted chain + //----------------------------------------------------- + // + ChainIteratorOf iterator(player_group->groupMembers); + VChainOf player_rank(NULL, False); + while ((active_player = (Player*) iterator.ReadAndNext()) != NULL) + { + if(active_player->IsScoringPlayer()) + { + player_rank.AddValue(active_player, active_player->currentScore); + ++num_players; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // Reset Player Highlighted + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // + active_player->playerHighlighted = False; + } + else + { + active_player->playerRanking = -1; + } + + } + --num_players; + // + //------------------------------------------------ + // Iterate through the chain assigning the rank + //------------------------------------------------ + // + VChainIteratorOf rank_iterator(player_rank); + + + while ((active_player = rank_iterator.ReadAndNext()) != NULL) + { + active_player->playerRanking = num_players; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If player in first place turn on player highlighted + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (!active_player->playerRanking) + { + active_player->playerHighlighted = True; + } + --num_players; + } + Check_Fpu(); + } + return 1; +} +//############################################################################# +// Update Support +// +void + Player::ReadUpdateRecord(Simulation::UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + Entity::ReadUpdateRecord(message); + UpdateRecord* record = (UpdateRecord*) message; + + currentScore = record->currentScore; + dropZoneLocation = record->dropZoneLocation; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::WriteUpdateRecord( + Simulation::UpdateRecord *record, + int update_model + ) +{ + Check(this); + Check_Pointer(record); + + Entity::WriteUpdateRecord(record, update_model); + + UpdateRecord* update = (UpdateRecord*) record; + + update->recordLength = sizeof(*update); + update->currentScore = currentScore; + update->dropZoneLocation = dropZoneLocation; + Check_Fpu(); +} + + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Player::Player( + Player::MakeMessage *creation_message, + Player::SharedData &virtual_data +): + Entity(creation_message, virtual_data), + statusMessageQueue(NULL) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + + scenarioRole = NULL; + //--------------------------------- + // Initialize data + //--------------------------------- + statusMessagePointer = NULL; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the playerMission + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + playerMission = application->GetCurrentMission(); + Check(playerMission); + // + //--------------------------------- + // Set the resource ID for a player + //--------------------------------- + // + Check(application); + Check(application->GetResourceFile()); + ResourceDescription *resource_description = + application->GetResourceFile()->FindResourceDescription( + "player", + ResourceDescription::ModelListResourceType + ); + if (resource_description != NULL) + { + Verify(resourceID == ResourceDescription::NullResourceID); + resourceID = resource_description->resourceID; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the host type associated with the entity ID + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + HostType host_type; + + HostID host_ID = entityID.GetHostID(); + Check(application); + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + Host *local_host = host_mgr->GetLocalHost(); + Check(local_host); + if (host_ID == local_host->GetHostID()) + { + host_type = local_host->GetHostType(); + } + else + { + HostManager::RemoteHostIterator iterator(host_mgr); + local_host = iterator.Find(host_ID); + Check(local_host); + host_type = local_host->GetHostType(); + } + + if (IsCameraShipPlayer()) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make A CameraPlayers Entity Group + // since cameras are not involved in + // standard game play they need a + // separate Entity Group! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + playerBitmapIndex = -1; + } + else + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make A Regular Players Entity Group + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application); + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *players = entity_manager->UseGroup("Players"); + Check(players); + players->Add(this); + playerBitmapIndex = creation_message->playerBitmapIndex; + } + + SetValidFlag(); + playerVehicle = NULL; + if (GetInstance() != ReplicantInstance) + { + Check(application->GetCurrentMission()); + playerMission = application->GetCurrentMission(); + SetPerformance(&Player::HuntForDropZone); + } + else + { + SetPerformance(&Player::GoToVehicle); + playerMission = NULL; + } + + playerRanking = 0; + deathCount = -2; + + //------------------------------------- + // Clear score + //------------------------------------- + currentScore = 0.0f; + //------------------------------------- + // Create intercom object + //------------------------------------- + Check(application); + IcomManager + *intercom_manager = application->GetIntercomManager(); + Check(intercom_manager); + + intercomPointer = intercom_manager->MakeIcom(GetOwnerID()); + Check(intercomPointer); + // registered in MakeIcom() + + playerHighlighted = False; + fadeTimeRemaining = 0.0f; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Player* Player::Make(Player::MakeMessage *creation_message) +{ + Check_Fpu(); + return new Player(creation_message, DefaultData); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Player::~Player() +{ + Check(this); + + //-------------------------------------------- + // Delete intercom object + //-------------------------------------------- + Check(intercomPointer); + Unregister_Object(intercomPointer); + delete intercomPointer; + intercomPointer = NULL; + + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::AddStatusMessage(StatusMessage *status_message) +{ + Check(this); + Check_Pointer(status_message); + statusMessageQueue.Add(status_message); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Player::StatusMessageUpdate(Scalar time_slice) +{ + Check(this); + //------------------------------------- + // We handle this queue as a STACK. + // The most recent message is presented + // first, causing older messages to + // wait "below" them on the stack. + // This allows a default message to + // sit at the "bottom" of the stack + // and allow others to override it + // temporarily. + //------------------------------------- + // + ChainIteratorOf + iterator(statusMessageQueue); + //---------------------------------------- + // ...we really want iterator.GetLast(), + // but since it doesn't exist we'll + // do it directly. + //---------------------------------------- + statusMessagePointer = NULL; + { + StatusMessage + *the_message; + + while ((the_message = iterator.ReadAndNext()) != NULL) + { + statusMessagePointer = the_message; + } + } + //---------------------------------------- + // If a message exists, decrement the + // timer: discard it if timed out. + //---------------------------------------- + if (statusMessagePointer != NULL) + { + Check_Pointer(statusMessagePointer); + + statusMessagePointer->displayTime -= time_slice; + if (statusMessagePointer->displayTime <= (Scalar) 0.0f) + { + Unregister_Object(statusMessagePointer); + delete statusMessagePointer; + statusMessagePointer = NULL; + } + } + Check_Fpu(); +} + +Logical + Player::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/PLAYER.h b/MUNGA/PLAYER.h new file mode 100644 index 0000000..1794ce7 --- /dev/null +++ b/MUNGA/PLAYER.h @@ -0,0 +1,461 @@ +#pragma once + +#include "entity.h" +#include "icom.h" +#include "scnrole.h" + +class Mission; +class DropZone__ReplyMessage; + +//########################################################################## +//##################### Player::MakeMessage ########################## +//########################################################################## +class Player__MakeMessage: + public Entity::MakeMessage +{ +public: + + int + playerBitmapIndex; + + Player__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int player_bitmap_index + ): + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + playerBitmapIndex(player_bitmap_index) + { } + + Player__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int player_bitmap_index + ): + Entity::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + playerBitmapIndex(player_bitmap_index) + { } + +}; + +//########################################################################## +//################### Player::UpdateRecord #################### +//########################################################################## + +struct Player__UpdateRecord : + public Entity::UpdateRecord +{ + Scalar + currentScore; + Point3D + dropZoneLocation; +}; + +//########################################################################## +//################# ScoreZone::ReplyMessage ########################## +//########################################################################## + +class Player__ScoreMessage : + public Entity::Message +{ +public: + Scalar + scoreAward; + + Player__ScoreMessage( + Receiver::MessageID message_ID, + size_t length, + Scalar score + ): + Entity::Message(message_ID, length), + scoreAward(score) + {} +}; + +//########################################################################## +//################# ScoreZone::ReplyMessage ########################## +//########################################################################## + +class Player__VehicleDeadMessage: + public Entity::Message +{ +public: + int deathCount; + EntityID dropZoneID; + + Player__VehicleDeadMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &dropzone_id=EntityID::Null + ): + Entity::Message(message_ID, length), + deathCount(-1), + dropZoneID(dropzone_id) + {} +}; + +//########################################################################## +//###################### Player::StatusMessage ######################### +//########################################################################## +class Player; + +class Player__StatusMessage: + public Node +{ +public: + Player__StatusMessage( + Player *player_involved, + int message_type, + Scalar display_time + ); + + enum { + NoMessage = -1, + NextMessageType = 0 + }; + + int + messageType; + Player + *playerInvolved; + Scalar + displayTime; +}; + +//########################################################################## +//########################### Player ################################ +//########################################################################## + +class Player: + public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData + DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// + enum + { + CurrentScoreAttributeID = Entity::NextAttributeID, + DropZoneLocationAttributeID, + PlayerRankingAttributeID, + StatusMessagePointerAttributeID, + PlayerBitmapIndexAttributeID, + PlayerHighlightedAttributeID, + NextAttributeID + }; + +private: + + static const IndexEntry + AttributePointers[]; + +protected: + + //static AttributeIndexSet AttributeIndex; + static AttributeIndexSet& GetAttributeIndex(); + + virtual int + CalcRanking(); + +public: + + Logical + playerHighlighted; + + Scalar + currentScore; + int + playerRanking; + + Point3D + dropZoneLocation; + + Player__StatusMessage + *statusMessagePointer; + + int + playerBitmapIndex; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Gauge Support +// +public: + typedef Player__StatusMessage + StatusMessage; + void + AddStatusMessage(StatusMessage *status_message); + void + StatusMessageUpdate(Scalar time_slice); + +protected: + ChainOf + statusMessageQueue; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum + { + DropZoneReplyMessageID = Entity::NextMessageID, + ScoreMessageID, + VehicleDeadMessageID, + MissionStartingMessageID, + MissionEndingMessageID, + NextMessageID + }; + + typedef Player__VehicleDeadMessage VehicleDeadMessage; + +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Game start/stop support +// +public: + typedef Message MissionStartingMessage; + typedef Message MissionEndingMessage; + +protected: + void + MissionStartingMessageHandler(Message *message); + void + MissionEndingMessageHandler(Message *message); + + Scalar + fadeTimeRemaining; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + + enum { + DropZoneAcquiredState = Entity::StateCount, + VehicleTranslocatedState, + MissionStartingState, + MissionEndingState, + StateCount + }; + + typedef void + (Player::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + virtual void + PlayerSimulation(Scalar time_slice); + + virtual void + CameraShipSimulation(Scalar time_slice); + + void + GoToVehicle(Scalar time_slice); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Vehicle creation +// +protected: + void + DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + void + VehicleDeadMessageHandler(VehicleDeadMessage *message); + + void + HuntForDropZone(Scalar time_slice); + + Mission* + playerMission; + + Entity* + playerVehicle; + + int + deathCount; + +public: + Entity* + GetPlayerVehicle() + {Check(this); return playerVehicle;} + + void + SetPlayerVehicle(Entity *player_vehicle) + { + Check(player_vehicle); + Check(this); + playerVehicle = player_vehicle; + } + + Mission* + GetMission() + { + Check(this); + return playerMission; + } + + int + GetDeathCount() + {Check(this); return deathCount;} +protected: + + virtual void + CreatePlayerVehicle(Origin); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Renderer Support +// +public: + Enumeration + GetAudioRepresentation(Entity *linked_entity); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Intercom Support +// +public: + Icom* + GetIntercom() + { + Check(this); + return intercomPointer; + } + +protected: + Icom + *intercomPointer; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Scoring Support +// +public: + typedef Player__ScoreMessage ScoreMessage; + + const ScenarioRole* + GetScenarioRole() const + {Check(this); return scenarioRole; } + +protected: + void + ScoreMessageHandler(ScoreMessage *message); + + ScenarioRole + *scenarioRole; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Flag Support +// +public: + enum { + NonScoringPlayerBit = Entity::NextBit, + CameraShipPlayerBit, + NextBit + }; + + enum { + NonScoringPlayerFlag = 1 << NonScoringPlayerBit, + CameraShipPlayerFlag = 1 << CameraShipPlayerBit, + DefaultFlags = + Entity::DefaultFlags + | NonScoringPlayerFlag + | PreRunFlag + }; + + void + SetNonScoringPlayerFlag() + {Check(this); simulationFlags |= NonScoringPlayerFlag;} + void + SetScoringPlayerFlag() + {Check(this); simulationFlags &= ~NonScoringPlayerFlag;} + + Logical + IsScoringPlayer() + {Check(this); return (simulationFlags&NonScoringPlayerFlag) == 0;} + + Logical IsCameraShipPlayer() + { + Check(this); + return (simulationFlags & CameraShipPlayerFlag) != 0; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Update Support +// + + typedef Player__UpdateRecord UpdateRecord; + +protected: + void + WriteUpdateRecord( + Simulation::UpdateRecord *message, + int update_model + ); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + + typedef Player__MakeMessage MakeMessage; + + static Player* + Make(MakeMessage *creation_message); + + Player( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~Player(); + + Logical + TestInstance() const; + +protected: + + void + ManageApplicationStatus(Scalar time_slice); +}; diff --git a/MUNGA/PLUG.cpp b/MUNGA/PLUG.cpp new file mode 100644 index 0000000..bc79bae --- /dev/null +++ b/MUNGA/PLUG.cpp @@ -0,0 +1,490 @@ +#include "munga.h" +#pragma hdrstop + +#include "plug.h" +#include "objstrm.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Plug ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Plug +//############################################################################# +// +Plug::Plug(ClassID class_id): + RegisteredClass(class_id) +{ + linkHead = NULL; +} + +// +//############################################################################# +// Plug +//############################################################################# +// +Plug::Plug(PlugStream *stream): + RegisteredClass(stream) +{ + linkHead = NULL; +} + +// +//########################################################################### +// ~Plug +//########################################################################### +// +Plug::~Plug() +{ + while (linkHead != NULL) + { + Unregister_Object(linkHead); + delete(linkHead); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Plug::TestInstance() const +{ + if (linkHead != NULL) + { + Check(linkHead); + } + return True; +} + +// +//############################################################################# +// ReceivePlugCommand +//############################################################################# +// + +// Considering removal +#if 0 +int + Plug::ReceivePlugCommand( + Plug::CommandID, + void* + ) +{ + return 0; +} +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PlugIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// PlugIterator +//############################################################################# +// +PlugIterator::PlugIterator( + const Plug *plug, + RegisteredClass::ClassID class_to_iterate +) +{ + Check(plug); + this->plug = plug; + classToIterate = class_to_iterate; + currentLink = plug->linkHead; +} + +PlugIterator::PlugIterator(const PlugIterator &iterator) +{ + Check(&iterator); + plug = iterator.plug; + classToIterate = iterator.classToIterate; + currentLink = iterator.currentLink; +} + +// +//############################################################################# +// PlugIterator +//############################################################################# +// +PlugIterator::~PlugIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + PlugIterator::TestInstance() const +{ + if (currentLink != NULL) + { + Check(currentLink); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + PlugIterator::First() +{ + Check(plug); + currentLink = plug->linkHead; + NextNode(); +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + PlugIterator::Last() +{ + if (currentLink == NULL) + { + Check(plug); + if ((currentLink = plug->linkHead) == NULL) + return; + } + + Check(currentLink); + while(currentLink->nextLink != NULL) + { + currentLink = currentLink->nextLink; + Check(currentLink); + } + PreviousNode(); +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + PlugIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->nextLink; + NextNode(); +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + PlugIterator::Previous() +{ + Check(currentLink); + currentLink = currentLink->prevLink; + PreviousNode(); +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void* + PlugIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + + node = currentLink->socket->GetReleaseNode(); + currentLink = currentLink->nextLink; + NextNode(); + return node; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void* + PlugIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + + node = currentLink->socket->GetReleaseNode(); + currentLink = currentLink->prevLink; + PreviousNode(); + return node; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + PlugIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + Check(currentLink->socket); + + return currentLink->socket->GetReleaseNode(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +#if 0 +CollectionSize + PlugIterator::GetSize() +{ + Link *link; + CollectionSize count; + + Check(plug); + + count = 0; + for + ( + link = plug->linkHead; + link != NULL; + link = link->nextLink + ) + { + Check(link); + Check(link->socket); + if (link->socket->GetReleaseNode() != NULL) + count++; + } + return count; +} +#else +CollectionSize + PlugIterator::GetSize() +{ + CollectionSize i = 0; + + First(); + while (GetCurrentImplementation() != NULL) + { + i++; + Next(); + } + return i; +} +#endif + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +#if 0 +void* + PlugIterator::GetNthImplementation( + CollectionSize index + ) +{ + Link *link; + CollectionSize count; + + Check(plug); + + count = 0; + for + ( + link = plug->linkHead; + link != NULL; + link = link->nextLink + ) + { + Check(link); + if (count == index) { + currentLink = link; + + Check(currentLink); + Check(currentLink->socket); + + return currentLink->socket->GetReleaseNode(); + } + count++; + } + return NULL; +} +#else +void* + PlugIterator::GetNthImplementation( + CollectionSize index + ) +{ + CollectionSize i = 0; + void *item; + + First(); + while ((item = GetCurrentImplementation()) != NULL) + { + if (i == index) + return item; + Next(); + i++; + } + return NULL; +} +#endif + +// +//########################################################################### +// NextNode +//########################################################################### +// +void + PlugIterator::NextNode() +{ + while (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + if ((node = currentLink->socket->GetReleaseNode()) != NULL) + { + Check(node); + if ( + node->GetClassID() == classToIterate || + classToIterate == RegisteredClass::NullClassID + ) + { + return; + } + } + currentLink = currentLink->nextLink; + } + return; +} + +// +//########################################################################### +// PreviousNode +//########################################################################### +// +void + PlugIterator::PreviousNode() +{ + while (currentLink != NULL) + { + Node *node; + + Check(currentLink); + Check(currentLink->socket); + if ((node = currentLink->socket->GetReleaseNode()) != NULL) + { + Check(node); + if ( + node->GetClassID() == classToIterate || + classToIterate == RegisteredClass::NullClassID + ) + { + return; + } + } + currentLink = currentLink->prevLink; + } + return; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + PlugIterator::Remove() +{ + Link *old_link; + + Check(currentLink); + + old_link = currentLink; + currentLink = currentLink->nextLink; + + Unregister_Object(old_link); + delete old_link; +} + +// +//############################################################################# +// SendNodeCommand +//############################################################################# +// +int + PlugIterator::SendNodeCommand( + NodeCommandID node_command, + void *info + ) +{ + int ret; + Node *node; + + First(); + while ((node = (Node *)GetCurrentImplementation()) != NULL) + { + Check(node); + if ((ret = node->ReceiveNodeCommand(node_command, info)) != 0) + return ret; + Next(); + } + return 0; +} + +// +//########################################################################### +// RemoveSocket +//########################################################################### +// +void + PlugIterator::RemoveSocket(Socket *socket) +{ + Link *link; + + Check(socket); + Check(plug); + for + ( + link = plug->linkHead; + link != NULL; + link = link->nextLink + ) + { + Check(link); + if (link->GetSocket() == socket) + { + currentLink = link->nextLink; + Unregister_Object(link); + delete link; + return; + } + } +} diff --git a/MUNGA/PLUG.h b/MUNGA/PLUG.h new file mode 100644 index 0000000..d68653b --- /dev/null +++ b/MUNGA/PLUG.h @@ -0,0 +1,144 @@ +#pragma once + +#include "vdata.h" +#include "iterator.h" +#include "link.h" + +class PlugStream; + +typedef Enumeration NodeCommandID; + +enum +{ + NodeNullCommandID = 0, + NodeNextCommandID +}; + +class PlugIterator; + +class Plug : public RegisteredClass +{ + friend class Link; + friend class PlugIterator; + +public: + ~Plug(); + Logical TestInstance() const; + +protected: + Plug(ClassID class_id = TrivialPlugClassID); + Plug(PlugStream *stream); + +private: + Link *linkHead; +}; + +template class PlugOf : public Plug +{ +public: + PlugOf(const T &item); + ~PlugOf(); + + operator T() const { return item; } + + T GetItem() const { return item; } + T *GetPointer() { return &item; } + +private: + T item; +}; + +template PlugOf::PlugOf(const T &the_item) +{ + item = the_item; +} + +template PlugOf::~PlugOf() +{ +} + +class PlugIterator : public Iterator +{ +public: + PlugIterator(const Plug *plug, RegisteredClass::ClassID class_to_iterate = RegisteredClass::NullClassID); + PlugIterator(const PlugIterator &iterator); + ~PlugIterator(); + + Logical TestInstance() const; + + void First(); + void Last(); + void Next(); + void Previous(); + CollectionSize GetSize(); + void Remove(); + + int SendNodeCommand(NodeCommandID node_command, void *info = NULL); + + void RemoveSocket(Socket *socket); + +protected: + void *ReadAndNextImplementation(); + void *ReadAndPreviousImplementation(); + void *GetCurrentImplementation(); + void *GetNthImplementation(CollectionSize index); + +protected: + const Plug *plug; + Link *currentLink; + +private: + RegisteredClass::ClassID classToIterate; + + void NextNode(); + void PreviousNode(); +}; + +template class PlugIteratorOf : public PlugIterator +{ +public: + PlugIteratorOf(const Plug *plug, RegisteredClass::ClassID class_to_iterate=RegisteredClass::NullClassID); + PlugIteratorOf(const Plug &plug, RegisteredClass::ClassID class_to_iterate=RegisteredClass::NullClassID); + PlugIteratorOf(const PlugIteratorOf &iterator); + + ~PlugIteratorOf(); + + T ReadAndNext() { return (T)ReadAndNextImplementation(); } + T ReadAndPrevious() { return (T)ReadAndPreviousImplementation(); } + T GetCurrent() { return (T)GetCurrentImplementation(); } + T GetNth(CollectionSize index) { return (T)GetNthImplementation(index); } + +#if 0 + Logical operator !() { return currentLink == NULL; } + operator T() { return GetCurrent(); } + T operator->() { return GetCurrent(); } + PlugIteratorOf& operator++() + { + Next(); + return *this; + } + PlugIteratorOf& operator--() + { + Previous(); + return *this; + } + T operator++(int) { return ReadAndNext(); } + T operator--(int) { return ReadAndPrevious(); } +#endif +}; + +template PlugIteratorOf::PlugIteratorOf(const Plug *plug, RegisteredClass::ClassID class_to_iterate) : PlugIterator(plug, class_to_iterate) +{ +} + +template PlugIteratorOf::PlugIteratorOf(const Plug &plug, RegisteredClass::ClassID class_to_iterate) : PlugIterator(&plug, class_to_iterate) +{ +} + +template PlugIteratorOf::PlugIteratorOf(const PlugIteratorOf &iterator) : PlugIterator(iterator) +{ +} + +template PlugIteratorOf::~PlugIteratorOf() +{ +} \ No newline at end of file diff --git a/MUNGA/POINT3D.cpp b/MUNGA/POINT3D.cpp new file mode 100644 index 0000000..0e439ce --- /dev/null +++ b/MUNGA/POINT3D.cpp @@ -0,0 +1,56 @@ +#include "munga.h" +#pragma hdrstop + +#include "point3d.h" +#include "linmtrx.h" +#include "vector4d.h" + +const Point3D Point3D::Identity(0.0f,0.0f,0.0f); + +// +//########################################################################### +//########################################################################### +// +Point3D& Point3D::operator=(const Vector4D& v) +{ + Check_Pointer(this); + Check(&v); + Verify(v.w); + + x = v.x / v.w; + y = v.y / v.w; + z = v.z / v.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Point3D& Point3D::Multiply(const Point3D& p,const AffineMatrix& m) +{ + Check_Pointer(this); + Check(&p); + Check(&m); + + x = p.x * m(0,0) + p.y * m(1,0) + p.z * m(2,0) + m(3,0); + y = p.x * m(0,1) + p.y * m(1,1) + p.z * m(2,1) + m(3,1); + z = p.x * m(0,2) + p.y * m(1,2) + p.z * m(2,2) + m(3,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Point3D& Point3D::MultiplyByInverse(const Point3D &p, const LinearMatrix &m) +{ + x = p.x * m(0,0) + p.y * m(0,1) + p.z * m(0,2) - m(3,0) * m(0,0) - m(3,1) * m(0,1) - m(3,2) * m(0,2); + y = p.x * m(1,0) + p.y * m(1,1) + p.z * m(1,2) - m(3,0) * m(1,0) - m(3,1) * m(1,1) - m(3,2) * m(1,2); + z = p.x * m(2,0) + p.y * m(2,1) + p.z * m(2,2) - m(3,0) * m(2,0) - m(3,1) * m(2,1) - m(3,2) * m(2,2); + return *this; +} + +#if defined(TEST_CLASS) + #include "point3d.tcp" +#endif diff --git a/MUNGA/POINT3D.h b/MUNGA/POINT3D.h new file mode 100644 index 0000000..c0c338d --- /dev/null +++ b/MUNGA/POINT3D.h @@ -0,0 +1,126 @@ +#pragma once + +#include "vector3d.h" + +class Origin; +class Vector4D; +class AffineMatrix; + +class Point3D : public Vector3D +{ +public: + static const Point3D Identity; + + Point3D() {} + Point3D(Scalar x, Scalar y, Scalar z) : Vector3D(x, y, z) {} + + Point3D& operator=(const Vector3D& v) + { + Vector3D::operator =(v); + return *this; + } + Point3D& operator=(const Vector4D& v); + Point3D& operator=(const Origin &p); + Point3D& operator=(const AffineMatrix &matrix); + + Point3D& Negate(const Vector3D &v) + { + Vector3D::Negate(v); + return *this; + } + + Point3D& Add(const Vector3D& v1, const Vector3D& v2) + { + Vector3D::Add(v1, v2); + return *this; + } + Point3D& operator+=(const Vector3D& v) + { + return Add(*this, v); + } + + Point3D& Subtract(const Point3D& p, const Vector3D& v) + { + Vector3D::Subtract(p, v); + return *this; + } + Point3D& operator-=(const Vector3D& v) + { + return Subtract(*this, v); + } + + Scalar operator*(const Vector3D& v) const + { + return Vector3D::operator*(v); + } + + Point3D& Multiply(const Point3D& p, Scalar scale) + { + Vector3D::Multiply(p, scale); + return *this; + } + Point3D& operator *=(Scalar value) + { + return Multiply(*this, value); + } + + Point3D& Multiply(const Point3D& p, const Vector3D& v) + { + Vector3D::Multiply(p, v); + return *this; + } + Point3D& operator*=(const Vector3D &v) + { + return Multiply(*this, v); + } + + Point3D& Divide(const Vector3D& v, Scalar scale) + { + Vector3D::Divide(v, scale); + return *this; + } + + Point3D& Divide(const Vector3D& v1, const Vector3D& v2) + { + Vector3D::Divide(v1, v2); + return *this; + } + Point3D& operator/=(const Vector3D &v) + { + return Divide(*this, v); + } + + Point3D& Multiply(const Vector3D &v, const AffineMatrix &m) + { + Vector3D::Multiply(v, m); + return *this; + } + Point3D& Multiply(const Point3D &p, const AffineMatrix &m); + Point3D& operator*=(const AffineMatrix &m) + { + Point3D src(*this); + return Multiply(src, m); + } + Point3D& MultiplyByInverse(const Vector3D &v, const LinearMatrix &m) + { + Vector3D::MultiplyByInverse(v, m); + return *this; + } + Point3D& MultiplyByInverse(const Point3D &p, const LinearMatrix &m); + + Point3D& Combine(const Vector3D& v1, Scalar t1, const Vector3D& v2, Scalar t2) + { + Vector3D::Combine(v1, t1, v2, t2); + return *this; + } + + Point3D& Lerp(const Vector3D& v1, const Vector3D& v2, Scalar t) + { + Vector3D::Lerp(v1, v2, t); + return *this; + } + + static Logical TestClass(); +}; + +#include "affnmtrx.h" \ No newline at end of file diff --git a/MUNGA/RANDOM.cpp b/MUNGA/RANDOM.cpp new file mode 100644 index 0000000..0df4010 --- /dev/null +++ b/MUNGA/RANDOM.cpp @@ -0,0 +1,176 @@ +#include "munga.h" +#pragma hdrstop + +#include "random.h" + +int RandomGenerator::Numbers[250]; +int RandomGenerator::Index = -1; + +RandomGenerator Random; + +// +//########################################################################### +//########################################################################### +// +void RandomGenerator::Init() +{ + int i, msb, mask; + + // + //-------------------------------------------------------------------- + // After making sure the table is built only once, initialize the + // Borland C++ random numbers with the low word of the current time in + // milliseconds, and initialize the index pointer + //-------------------------------------------------------------------- + // + char *seed_spec = getenv("RANDOM"); + unsigned seed; + if (seed_spec) + { + seed = (unsigned)atol(seed_spec); + } + else + { + seed = (unsigned)time(NULL); + } + #if defined(TEST_CLASS) + cout << "Random Seed = " << seed << endl; + #endif + srand(seed); + Index = 0; + + // + //------------------------------------------------------------------ + // Load the random number buffer, then go thru and set the sign bit + // randomly, increasing the range of random numbers from 0..32767 to + // 0..65535 + //------------------------------------------------------------------ + // + for (i=0; i<250; i++) + { + Numbers[i] = rand(); + } + + // + //-------------------------------------------------------------------- + // In order to preserve a good random number mix for the XOR function, + // mask and set the bits of 16 words in a descending manner as in + // 1xx..., 01xx..., 001xx..., 0001xx..., ... + //-------------------------------------------------------------------- + // + mask = RAND_MAX >> 1; + msb = mask + 1; + int rand_size; + for (rand_size=0; !(msb&(1<>= 1; + msb >>= 1; + i += 11; + } +} + +// +//########################################################################### +//########################################################################### +// +int RandomGenerator::GetRandomInt() +{ + int indent, result; + + // + //------------------------------------------------------------------ + // The random number generated will be the result of an XOR with the + // element 103 positions further (wrapping around) in the table + //------------------------------------------------------------------ + // + indent = (Index>=147)?Index-147:Index+103; + result = Numbers[Index]^Numbers[indent]; + + // + //------------------------------------------------------------------------ + // Replace the current random number with the new one generated, increment + // the buffer index pointer, and return the number + //------------------------------------------------------------------------ + // + Numbers[Index] = result; + if (++Index == ELEMENTS(Numbers)) + Index=0; + return result; +} + +// +//########################################################################### +//########################################################################### +// +RandomGenerator::operator Scalar() +{ + Scalar result; + + result = GetRandomInt(); + result /= (float)(RAND_MAX + 1); + return result; +} + +// +//########################################################################### +//########################################################################### +// +int RandomGenerator::operator ()(int range) +{ + int result, max; + + max = RAND_MAX - ((RAND_MAX + 1)%range); + do + { + result = GetRandomInt(); + } while (result>max); + return result%range; +} + +// +//########################################################################### +//########################################################################### +// +Die::Die(int n) +{ + dieSides = (n>1)?n:2; + highestRandom = RAND_MAX - ((RAND_MAX+1)%dieSides); +} + +// +//########################################################################### +//########################################################################### +// +Die::operator int() +{ + int result; + + // + //------------------------------------------------------------------------ + // In order to not skew the probabilities to the low numbers, make sure + // that the random # used is not greater than the limit determined for the + // number of sides. + //------------------------------------------------------------------------ + // + do + { + result = Random.GetInt(); + } while (result>highestRandom); + + // + //------------------------------------------------------------------- + // Once the base random number is determined, do modulus division and + // increment by 1 to map into the die range. + //------------------------------------------------------------------- + // + return result % dieSides + 1; +} + +#if defined(TEST_CLASS) + #include "random.tcp" +#endif diff --git a/MUNGA/RANDOM.h b/MUNGA/RANDOM.h new file mode 100644 index 0000000..d2b9cd7 --- /dev/null +++ b/MUNGA/RANDOM.h @@ -0,0 +1,53 @@ +#pragma once + +#include "scalar.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Random ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class RandomGenerator SIGNATURED +{ + private: + static int Numbers[250]; // the random number table + static int Index; // the current entry within the table + + static void Init(); + + static int GetRandomInt(); + + public: + RandomGenerator() + { + if (Index == -1) + Init(); + } + + // + //------------------------ + // Random number functions + //------------------------ + // + int GetInt() // returns 0 .. RAND_MAX + { + return GetRandomInt(); + } + + operator Scalar(); // returns 0.0f <= x < 1.0f + int operator ()(int Range); // returns 0 .. Range-1 + + static Logical TestClass(); +}; + +extern RandomGenerator Random; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Die ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Die SIGNATURED +{ +private: + int highestRandom; // the highest random number giving a uniform dist. + int dieSides; // the number of sides on the die (starting from 1) + +public: + Die(int sides); + operator int(); // returns 1 .. dieSides +}; diff --git a/MUNGA/RAY.cpp b/MUNGA/RAY.cpp new file mode 100644 index 0000000..a02fc7f --- /dev/null +++ b/MUNGA/RAY.cpp @@ -0,0 +1,168 @@ +#include "munga.h" +#pragma hdrstop + +#include "ray.h" +#include "plane.h" +#include "sphere.h" + +// +//############################################################################# +//############################################################################# +// +void Ray::Project(Scalar length, Point3D *result) +{ + Check(this); + Check(result); + + Vector3D temp; + + temp.Multiply(direction,length); + result->Add(origin,temp); +} + +// +//############################################################################# +//############################################################################# +// +Scalar Ray::LengthToClosestPointTo(const Point3D &point) +{ + Check(this); + Check(&point); + + Vector3D temp; + + temp.Subtract(point,origin); + return temp*direction; +} + +// +//############################################################################# +//############################################################################# +// +Scalar Ray::DistanceTo(const Plane &plane, Scalar *product) const +{ + Scalar t; + + // + //------------------------------------------------------------------ + // Compute the dot product of the ray and plane normal, and find the + // distance from the origin of the ray to the plane + //------------------------------------------------------------------ + // + *product = plane.normal * direction; + t = plane.DistanceTo(origin); + + // + //---------------------------------------------------------------------- + // If the ray is not parallel to the plane, determine how far to proceed + // along the ray until we hit the plane + //---------------------------------------------------------------------- + // + if (!Small_Enough(*product)) + t /= -*product; + return t; +} + +// +//############################################################################# +//############################################################################# +// +Scalar Ray::DistanceTo(const Sphere &sphere, Scalar *penetration) const +{ + Scalar b, c; + Vector3D temp; + + // + //------------------------------------------------------------------------- + // Set up to solve a quadratic equation for the intersection of the ray and + // sphere. The solution is based on finding the closest point on the line + // to the sphere, and then calculating the interval between the entry and + // exit points of the ray + //------------------------------------------------------------------------- + // + temp.Subtract(origin,sphere.center); + b = 2.0f * (direction * temp); + c = temp.LengthSquared() - sphere.radius*sphere.radius; + + // + //-------------------------------------------------------------------------- + // Compute the squared interval to use for the solution. If it is negative, + // then the ray misses the sphere + //-------------------------------------------------------------------------- + // + *penetration = b*b - 4.0f*c; + if (*penetrationAddScaled(origin1, velocity1, *time); + result2->AddScaled(origin2, velocity2, *time); + d = closest.Length(); + Check_Fpu(); + return d; +} + +#if defined(TEST_CLASS) +# include "ray.tcp" +#endif diff --git a/MUNGA/RAY.h b/MUNGA/RAY.h new file mode 100644 index 0000000..c047f62 --- /dev/null +++ b/MUNGA/RAY.h @@ -0,0 +1,48 @@ +#pragma once + +#include "point3d.h" +#include "unitvec.h" + +class Plane; +class Sphere; +class Cylinder; +class Cone; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ray ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Ray SIGNATURED +{ + public: + Point3D origin; + UnitVector direction; + + Ray() {} + Ray(const Point3D &origin, const UnitVector &direction) : origin(origin), direction(direction) {} + + // + // Ray projection functions + // + void Project(Scalar length, Point3D *result); + Scalar LengthToClosestPointTo(const Point3D &point); + void ClosestPointTo(const Point3D &point, Point3D *result) + { + Check(this); + Check(result); + Check(&point); + Project(LengthToClosestPointTo(point), result); + } + + // + // Ray intersection functions + // + Scalar DistanceTo(const Plane &plane, Scalar *product) const; + Scalar DistanceTo(const Sphere &sphere, Scalar *penetration) const; + + // + // Test support + // + Logical TestInstance() const; + static Logical TestClass(); +}; + +extern Scalar Find_Closest_Approach(const Point3D& origin1, const Vector3D& velocity1, Point3D *result1, const Point3D& origin2, const Vector3D& velocity2, Point3D *result2, Scalar *time, Logical *constant); \ No newline at end of file diff --git a/MUNGA/RECEIVER.cpp b/MUNGA/RECEIVER.cpp new file mode 100644 index 0000000..6966179 --- /dev/null +++ b/MUNGA/RECEIVER.cpp @@ -0,0 +1,645 @@ +#include "munga.h" +#pragma hdrstop + +#include "receiver.h" +#include "event.h" + +//############################################################################# +//############################# Receiver ################################ +//############################################################################# + +const Receiver::Handler + Receiver::NullHandler=NULL; + +Receiver::SharedData + Receiver::DefaultData( + Receiver::GetClassDerivations(), + Receiver::GetMessageHandlers() + ); + +Derivation* Receiver::GetClassDerivations() +{ + static Derivation classDerivations("Receiver"); + return &classDerivations; +} + +const Receiver::HandlerEntry + Receiver::MessageHandlerEntries[]= +{ + { + Receiver::WatcherChangedMessageID, + "WatcherChanged", + (Receiver::Handler)&Receiver::DefaultMessageHandler + }, + { + Receiver::LoadResourceFinishedMessageID, + "LoadResourceFinished", + (Receiver::Handler)&Receiver::DefaultMessageHandler + } +}; + +Receiver::MessageHandlerSet& Receiver::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(Receiver::MessageHandlerEntries), Receiver::MessageHandlerEntries); + return messageHandlers; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Receiver__Message *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void +#if DEBUG_LEVEL>0 + Receiver::DefaultMessageHandler(Message* message) +#else + Receiver::DefaultMessageHandler(Message*) +#endif +{ + Tell( + "Default Handler activated on message ID " << message->messageID << endl + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Receiver::Receive(Message *what) +{ + // + //------------------------------------------------------------------------- + // Service the message taps by creating an iterator to step through all the + // MessageTaps registered with the Derivation object for the receiver's + // class. Each tap will do whatever it thinks best about this receiver + // having received this message + //------------------------------------------------------------------------- + // + Check(this); + Check_Pointer(what); + ChainIteratorOf i(GetDerivation()->activeTaps); + MessageTap *tap; + while ((tap = i.ReadAndNext()) != NULL) + { + tap->Scan(this,what); + } + + // + //-------------------------------------------------------------------------- + // Now, see if the receiver can handle this type of message, and if so, send + // the message to the returned method handler + //-------------------------------------------------------------------------- + // + Receiver::SharedData *sharedData = GetSharedData(); + Handler handler = sharedData->activeMessageHandlers->Find(what->messageID); + if (handler != Receiver::NullHandler) + { + (this->*handler)(what); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Receiver::Receive(Event *event) +{ + Receive(event->messageToSend); + Unregister_Object(event); + delete event; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Receiver::FlushEvents(int) // max_priority doesn't work yet!!!! +{ + Check(this); + PlugIteratorOf i(this); + Event *event; + while ((event = i.ReadAndNext()) != NULL) + { + if (event->GetClassID() == EventClassID) + { + Unregister_Object(event); + delete event; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Receiver::FlushMatchingEvents( + Receiver::MessageID target_message, + int // max_priority doesn't work yet!!!! + ) +{ + Check(this); + PlugIteratorOf + i(this); + Event* event; + while ((event = i.ReadAndNext()) != NULL) + { + if ( + event->GetClassID() == EventClassID && ( + target_message == Receiver::AnyMessageID + || event->messageToSend->messageID == target_message + ) + ) + { + Unregister_Object(event); + delete event; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Receiver::ProcessDeferredQueue() +{ + // + //------------------------------------------------ + // Find a delay queue, and return if there is none + //------------------------------------------------ + // + Check(this); + PlugIteratorOf i(this); + DeferredEventQueue *deferred_queue; + while ((deferred_queue = i.ReadAndNext()) != NULL) + { + if (deferred_queue->GetClassID() == DeferredEventQueueClassID) + { + break; + } + } + if (!deferred_queue) + { + return; + } + + // + //-------------------------------------------------------------- + // Now, tell the queue to process all its events, then delete it + //-------------------------------------------------------------- + // + deferred_queue->ProcessAllEvents(); + Unregister_Object(deferred_queue); + delete deferred_queue; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Receiver::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +//######################### Receiver::Message ########################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Receiver::Message::TestInstance() const +{ + return True; +} + +//############################################################################# +//######################### Receiver::DynamicMessage ########################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Receiver__DynamicMessage::Receiver__DynamicMessage( + Receiver::MessageID message_ID, + size_t message_size +) +{ + Receiver::Message new_message(message_ID, message_size); + WriteBytes(&new_message, message_size); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MemoryStream& + Receiver::DynamicMessage::WriteBytes( + const void *ptr, + size_t number_of_bytes + ) +{ + DynamicMemoryStream::WriteBytes(ptr, number_of_bytes); + + Receiver::Message *message = GetMessagePointer(); + size_t new_size = GetBytesUsed(); + message->messageLength = new_size; + return *this; +} + +//############################################################################# +//############################ MessageTap ############################### +//############################################################################# + +MemoryBlock *MessageTap::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(MessageTap), 30, 30, "Message Taps"); + return &allocatedMemory; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MessageTap::MessageTap( + Derivation *derivation, + Receiver *client, + Receiver::ScanCallback call_back +): + Plug(MessageTapClassID) +{ + // + //--------------------------- + // Initialize the message tap + //--------------------------- + // + Check(client); + clientReceiver = client; + scanCallback = call_back; + matchingReceiver = NULL; + matchingMessageID = Receiver::AnyMessageID; + + // + //-------------------------------------------- + // Hook the tap up to the specified derivation + //-------------------------------------------- + // + Check(derivation); + derivation->AppendMessageTap(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MessageTap::MessageTap( + Derivation *derivation, + Receiver *client, + Receiver::ScanCallback call_back, + Receiver::MessageID messageID, + Receiver *receiver +): + Plug(MessageTapClassID) +{ + // + //--------------------------- + // Initialize the message tap + //--------------------------- + // + Check(client); + clientReceiver = client; + scanCallback = call_back; + + matchingReceiver = receiver; + matchingMessageID = messageID; + + // + //-------------------------------------------- + // Hook the tap up to the specified derivation + //-------------------------------------------- + // + Check(derivation); + derivation->AppendMessageTap(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + MessageTap::Scan( + Receiver *receiver, + Receiver::Message *message + ) +{ + Check(this); + Check(message); + + if ( + (!matchingReceiver || matchingReceiver == receiver) + && ( + matchingMessageID == Receiver::AnyMessageID + || matchingMessageID == message->messageID + ) + ) + { + (clientReceiver->*scanCallback)(message,receiver); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + MessageTap::TestInstance() const +{ + return True; +} + +//############################################################################# +//##################### Receiver::InheritanceSet ######################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Receiver::InheritanceSet::TestInstance() const +{ + return True; +} + +//############################################################################# +//#################### Receiver::MessageHandlerSet ###################### +//############################################################################# + +const Receiver::MessageHandlerSet + Receiver::MessageHandlerSet::NullSet; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Receiver__MessageHandlerSet::~Receiver__MessageHandlerSet() +{ + if (messageHandlers) + { + Unregister_Pointer(messageHandlers); + delete[] messageHandlers; + messageHandlers = NULL; + } +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Receiver::MessageHandlerSet::Build( + Receiver::MessageID count, + const Receiver::HandlerEntry handler_table[], + const Receiver::MessageHandlerSet *inheritance + ) +{ + // + //------------------------------------------------------- + // Find out the highest message type we have to deal with + //------------------------------------------------------- + // + Check(this); + Check_Pointer(handler_table); + entryCount = 0; + Receiver::MessageID i; + for (i=0; i entryCount) + { + entryCount = handler_table[i].entryID; + } + } + if (inheritance) + { + Check(inheritance); + if (entryCount < inheritance->entryCount) + { + entryCount = inheritance->entryCount; + } + #if DEBUG_LEVEL>0 + else if (entryCount > inheritance->entryCount) + { + i = inheritance->entryCount+1; + goto Check_Table; + } + #endif + } + else + { + Verify(entryCount == count); + #if DEBUG_LEVEL>0 + i = 1; +Check_Table: + while (i <= entryCount) + { + int j; + for (j=0; j count); + #endif + } + + // + //----------------------------------------------------------------------- + // Allocate the memory for the new handler set, and copy the inherited + // handlers to the new table. We are guaranteed to have enough space for + // the inherited table + //----------------------------------------------------------------------- + // + messageHandlers = new Receiver::HandlerEntry[entryCount]; + Check_Pointer(messageHandlers); + Register_Pointer(messageHandlers); + i = 0; + if (inheritance) + { + for (; ientryCount; ++i) + { + messageHandlers[i] = inheritance->messageHandlers[i]; + } + } + + // + //---------------------------------------------------------------------- + // Step through the new table supplied, placing each handler in the slot + // determined by the message type + //---------------------------------------------------------------------- + // + for (i=0; i= 0 && index < entryCount); + messageHandlers[index] = handler_table[i]; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const Receiver::HandlerEntry* + Receiver::MessageHandlerSet::Find(const char* name) const +{ + Check(this); + Check_Pointer(name); + + for (int i=0; iAppendDerivation(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Derivation::AppendMessageTap(MessageTap* tap) +{ + Check(this); + Check(tap); + + // + //---------------------------------------------------------------------- + // Add the tap to the taps chain, then step through all our derivations, + // sending each of them this same method + //---------------------------------------------------------------------- + // + activeTaps.Add(tap); + ChainIteratorOf + i(classDerivations); + Derivation *derivation; + while ((derivation = i.ReadAndNext()) != NULL) + { + derivation->AppendMessageTap(tap); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Derivation::IsDescendedFrom(Derivation& parent) +{ + Check(this); + Check(&parent); + + // + //------------------------------ + // We are descended from ourself + //------------------------------ + // + if (&parent == this) + { + return True; + } + + // + //---------------------------------------------------------------------- + // Find our parent derivation, and ask him + // sending each of them this same method + //---------------------------------------------------------------------- + // + PlugIteratorOf i(this); + Derivation *derivation; + while ((derivation = i.ReadAndNext()) != NULL) + { + if (derivation->GetClassID() == DerivationClassID) + { + return derivation->IsDescendedFrom(parent); + } + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Derivation::IsDescendedFrom(const char* parent) +{ + Check(this); + Check_Pointer(parent); + + // + //------------------------------ + // We are descended from ourself + //------------------------------ + // + Check_Pointer(className); + if (!strcmp(className, parent)) + { + return True; + } + + // + //---------------------------------------------------------------------- + // Find our parent derivation, and ask him + // sending each of them this same method + //---------------------------------------------------------------------- + // + PlugIteratorOf i(this); + Derivation *derivation; + while ((derivation = i.ReadAndNext()) != NULL) + { + Check(derivation); + if (derivation->GetClassID() == DerivationClassID) + { + return derivation->IsDescendedFrom(parent); + } + } + return False; +} + +//############################################################################# +//###################### Receiver::SharedData ########################## +//############################################################################# + +Logical + Receiver::SharedData::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) +# include "receiver.tcp" +#endif diff --git a/MUNGA/RECEIVER.h b/MUNGA/RECEIVER.h new file mode 100644 index 0000000..1538a89 --- /dev/null +++ b/MUNGA/RECEIVER.h @@ -0,0 +1,546 @@ +#pragma once + +#include "node.h" +#include "chain.h" +#include "memblock.h" +#include "memstrm.h" + +class Receiver__SharedData; +class Receiver__InheritanceSet; +struct Receiver__HandlerEntry; +class Receiver__MessageHandlerSet; +class Receiver__Message; +class Receiver__DynamicMessage; +class Derivation; +class Event; +class DynamicMemoryStream; +class MessageTap; + +//########################################################################## +//########################## Receiver ################################ +//########################################################################## +// +// It is suggested that calls to methods meant to be serviced by a receiver +// be built through inline functions in the derived class, rather than +// having to build the parameter block in the scope of the caller. Letting +// the inline code build the parameter block is much cleaner, and allows the +// message code numbers to be held inside the derived class, further +// protecting against calling methods for objects not in a proper derivation +// chain. +// +class Receiver: + public Node +{ +//########################################################################## +// Shared Data Support +// +public: + typedef Receiver__SharedData SharedData; + SharedData* + GetSharedData() const; + + static Derivation* GetClassDerivations(); + Derivation* + GetDerivation() const; + + static SharedData DefaultData; + + Logical + IsDerivedFrom(Derivation& parent) const; + Logical + IsDerivedFrom(const char* parent) const; + +protected: + const SharedData* sharedData; + +//########################################################################## +// Construction and Destruction Support +// +protected: + Receiver( + ClassID class_ID, + SharedData &shared_data + ): + Node(class_ID), + sharedData(&shared_data) + {} + + Receiver( + PlugStream *stream, + SharedData &shared_data + ): + Node(stream), + sharedData(&shared_data) + {} + +//########################################################################## +// Messaging Support +// +public: + typedef Receiver__Message Message; + typedef Receiver__DynamicMessage DynamicMessage; + typedef Receiver__InheritanceSet InheritanceSet; + typedef Receiver__HandlerEntry HandlerEntry; + typedef Receiver__MessageHandlerSet MessageHandlerSet; + typedef void (Receiver::*Handler)(const Message*); + typedef Enumeration MessageID; + + enum { + AnyMessageID=0, + WatcherChangedMessageID, + LoadResourceFinishedMessageID, + NextMessageID + }; + + static const Handler NullHandler; + + void + Receive(Message *What); + + virtual void + Dispatch(Message *What) + {Receive(What);} + + void + DefaultMessageHandler(Message*); + + typedef void (Receiver::*ScanCallback)( + Receiver::Message *message, + Receiver *receiver + ); + + MessageTap* + MakeMessageTap( + Derivation *derivation, + ScanCallback callback + ); + MessageTap* + MakeMessageTap( + Derivation *derivation, + ScanCallback callback, + Receiver::MessageID matching_message, + Receiver *match_receiver + ); + +protected: + static const HandlerEntry MessageHandlerEntries[]; + // swapping the commented line for the following one due to inconsitincies + // in the order of initialization for static member variables + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//########################################################################## +// Event Support +// +public: + virtual void + Receive(Event *event); + + void + FlushEvents(int max_priority=-1); + void + FlushMatchingEvents( + MessageID target_message, + int max_priority=-1 + ); + + void + ProcessDeferredQueue(); + +//########################################################################## +// Test Support +// +public: + static Logical + TestClass(); + Logical + TestInstance() const; +}; + +//########################################################################## +//###################### Receiver::Message ########################### +//########################################################################## + +class Receiver__Message +{ +public: + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Receiver__Message *); + #endif + + size_t + messageLength; + Receiver::MessageID + messageID; + + enum { + ReliableBit, + NextBit + }; + + enum { + ReliableFlag = 1 << ReliableBit + }; + + LWord + messageFlags; + + Receiver__Message( + Receiver::MessageID id, + size_t message_length + ): + messageID(id), + messageLength(message_length), + messageFlags(ReliableFlag) // HACK + {} + + Logical + TestInstance() const; +}; + +//########################################################################## +//################### Receiver::DynamicMessage ####################### +//########################################################################## + +class Receiver__DynamicMessage: + public DynamicMemoryStream +{ +public: + Receiver__DynamicMessage() + {} + Receiver__DynamicMessage( + void *stream_start, + size_t stream_size, + size_t initial_offset=0 + ): + DynamicMemoryStream(stream_start, stream_size, initial_offset) + {} + Receiver__DynamicMessage( + Receiver::MessageID message_ID, + size_t size = sizeof(Receiver::Message) + ); + + Receiver::Message* + GetMessagePointer() + {Check(this); return Cast_Object(Receiver::Message*, streamStart);} + +protected: + MemoryStream& + WriteBytes( + const void *ptr, + size_t number_of_bytes + ); +}; + +//########################################################################## +//#################### ReceiverDataMessageOf ######################### +//########################################################################## + +template class ReceiverDataMessageOf: + public Receiver::Message +{ +public: + T + dataContents; + + ReceiverDataMessageOf( + Receiver::MessageID id, + size_t message_length, + const T& data + ): + Receiver::Message(id, message_length), + dataContents(data) + {} +}; + +//########################################################################## +//######################### MessageTap ############################### +//########################################################################## + +class MessageTap: + public Plug +{ +//########################################################################## +// MessageTap Functionality +// +public: + MessageTap( + Derivation *derivation, + Receiver *client, + Receiver::ScanCallback callback + ); + MessageTap( + Derivation *derivation, + Receiver *client, + Receiver::ScanCallback callback, + Receiver::MessageID matching_message, + Receiver *match_receiver + ); + +private: + Receiver::ScanCallback scanCallback; + Receiver* clientReceiver; + Receiver* matchingReceiver; + Receiver::MessageID matchingMessageID; + +public: + void + Scan( + Receiver *receiver, + Receiver::Message *message + ); + +//########################################################################## +// Memory Allocation +// +private: + static MemoryBlock* GetAllocatedMemory(); + +public: + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } + +//########################################################################## +// Test support +// +public: + Logical + TestInstance() const; + static Logical + TestClass(); +}; + +//########################################################################## +//################## Receiver::InheritanceSet ######################## +//########################################################################## +// +// NOTE: An InheritanceSet generated for a class should only be inherited by +// other classes derived from that base class. If this is not done, +// SEVERE run-time weirdness will happen +// +class Receiver__InheritanceSet SIGNATURED +{ +public: + Logical + TestInstance() const; + Enumeration + GetEntryCount() + {Check(this); return entryCount;} + +protected: + Enumeration + entryCount; + + Receiver__InheritanceSet() + {} + ~Receiver__InheritanceSet() + {} +}; + +//########################################################################## +//################### Receiver::HandlerEntry ######################### +//########################################################################## + +struct Receiver__HandlerEntry +{ + Enumeration + entryID; + const char* + entryName; + Receiver::Handler + entryHandler; +}; + +#define MESSAGE_ENTRY(class,message)\ + {\ + class::message##MessageID,\ + #message,\ + (Receiver::Handler)&class::message##MessageHandler\ + } + +//########################################################################## +//################# Receiver::MessageHandlerSet ###################### +//########################################################################## + +class Receiver__MessageHandlerSet: + public Receiver__InheritanceSet +{ +//########################################################################## +// Constructors and Destructors +// +public: + Receiver__MessageHandlerSet(Receiver::MessageID count, const Receiver::HandlerEntry handler_table[], const Receiver::MessageHandlerSet &inheritance) { Build(count, handler_table, &inheritance); } + Receiver__MessageHandlerSet(Receiver::MessageID count, const Receiver::HandlerEntry handler_table[]) { Build(count, handler_table, NULL); } + Receiver__MessageHandlerSet(const Receiver::MessageHandlerSet& source) { Build(0, NULL, &source); } + Receiver__MessageHandlerSet() + { + messageHandlers = NULL; + entryCount = 0; + } + ~Receiver__MessageHandlerSet(); + +protected: + void + Build( + Receiver::MessageID count, + const Receiver::HandlerEntry handler_table[], + const Receiver::MessageHandlerSet *inheritance + ); + +//########################################################################## +// HandlerSet Functionality +// +public: + static const Receiver::MessageHandlerSet + NullSet; + + Receiver::Handler Find(Receiver::MessageID message) const + { + Check(this); + Verify(message > 0); + return (message<=entryCount) ? messageHandlers[message-1].entryHandler : Receiver::NullHandler; + } + + const Receiver::HandlerEntry* + Find(const char* name) const; + + const char * + GetName(Receiver::MessageID message) const + { + Check(this); + return (message<=entryCount) + ? messageHandlers[message-1].entryName + : NULL; + } + +protected: + Receiver::HandlerEntry* messageHandlers; + +//########################################################################## +// Test Support +// +public: + static Logical + TestClass(); +}; + +//########################################################################## +//########################## Derivation ############################## +//########################################################################## + +class Derivation: + public Node +{ + friend class Receiver; + +//########################################################################## +// Construction and Destruction +// +public: + Derivation(char *who); + Derivation(Derivation *parent,char *who); + + char *className; + +//########################################################################## +// Messagetap support +// +private: + Derivation(Derivation& copy); + ChainOf + activeTaps; + +public: + void + AppendMessageTap(MessageTap* tap); + Logical + IsDescendedFrom(Derivation& parent); + Logical + IsDescendedFrom(const char* parent); + +//########################################################################## +// Inheritance Registration Support +// +private: + ChainOf + classDerivations; + + void + AppendDerivation(Derivation* child) + {Check(this); classDerivations.Add(child);} + +//########################################################################## +// Test Support +// +public: + static Logical + TestClass(); +}; + +//########################################################################## +//################### Receiver::SharedData ########################## +//########################################################################## + +class Receiver__SharedData SIGNATURED +{ +public: + Receiver__SharedData( + Derivation* derivation, + Receiver::MessageHandlerSet &handler + ): + derivedClasses(derivation), + activeMessageHandlers(&handler) + { + //activeMessageHandlers = &activeMessageHandlersInstance; + } + + Derivation *derivedClasses; + Receiver::MessageHandlerSet *activeMessageHandlers; + + Logical + TestInstance() const; +//private: +// Receiver::MessageHandlerSet activeMessageHandlersInstance; +}; + +inline Receiver::SharedData* + Receiver::GetSharedData() const + {Check(this); return Cast_Object(SharedData*,sharedData);} + +inline Derivation* + Receiver::GetDerivation() const + {Check(this); return GetSharedData()->derivedClasses;} + +inline Logical + Receiver::IsDerivedFrom(Derivation& parent) const + {return sharedData->derivedClasses->IsDescendedFrom(parent);} + +inline Logical + Receiver::IsDerivedFrom(const char* parent) const + {Check(this); return GetDerivation()->IsDescendedFrom(parent);} + +inline MessageTap* + Receiver::MakeMessageTap( + Derivation *derivation, + ScanCallback callback + ) + {Check(this); return new MessageTap(derivation, this, callback);} + +inline MessageTap* + Receiver::MakeMessageTap( + Derivation *derivation, + ScanCallback callback, + Receiver::MessageID matching_message, + Receiver *match_receiver + ) + { + Check(this); + return new MessageTap( + derivation, + this, + callback, + matching_message, + match_receiver + ); + } diff --git a/MUNGA/RECT2D.cpp b/MUNGA/RECT2D.cpp new file mode 100644 index 0000000..43dfa10 --- /dev/null +++ b/MUNGA/RECT2D.cpp @@ -0,0 +1,138 @@ +#include "munga.h" +#pragma hdrstop + +#include "rect2d.h" + +// +//------------------------------------------------------------------------ +// Creators +//------------------------------------------------------------------------ +// +Rectangle2D::Rectangle2D() +{ + MakeEmpty(); // uninitialized rectangles should be "empty" +} + +Rectangle2D::Rectangle2D( + Vector2DOf bl, + Vector2DOf tr + ) +{ + bottomLeft = bl; + topRight = tr; +} + +Rectangle2D::Rectangle2D( + int x1, int y1, int x2, int y2 + ) +{ + bottomLeft.x = x1; + bottomLeft.y = y1; + topRight.x = x2; + topRight.y = y2; +} + +// +//------------------------------------------------------------------------ +// Union (returns bounding rectangle) +//------------------------------------------------------------------------ +// +void + Rectangle2D::Union( + const Rectangle2D& r1, + const Rectangle2D& r2 + ) +{ + Check(this); + Check(&r1); + Check(&r2); + + if (r1.IsEmpty()) + { + if (r2.IsEmpty()) + { + MakeEmpty(); + } + else + { + bottomLeft = r2.bottomLeft; + topRight = r2.topRight; + } + } + else + { + if (r2.IsEmpty()) + { + bottomLeft = r1.bottomLeft; + topRight = r1.topRight; + } + else + { + bottomLeft.x = Min(r1.bottomLeft.x, r2.bottomLeft.x); + bottomLeft.y = Min(r1.bottomLeft.y, r2.bottomLeft.y); + topRight.x = Max(r1.topRight.x, r2.topRight.x); + topRight.y = Max(r1.topRight.y, r2.topRight.y); + } + } +} + +// +//------------------------------------------------------------------------ +// Intersection (returns overlapping section) +//------------------------------------------------------------------------ +// +void + Rectangle2D::Intersection( + const Rectangle2D& r1, + const Rectangle2D& r2 + ) +{ + Check(this); + Check(&r1); + Check(&r2); + + if (r1.IsEmpty()) + { + MakeEmpty(); + } + else + { + if (r2.IsEmpty()) + { + MakeEmpty(); + } + else + { + bottomLeft.x = Max(r1.bottomLeft.x, r2.bottomLeft.x); + bottomLeft.y = Max(r1.bottomLeft.y, r2.bottomLeft.y); + topRight.x = Min(r1.topRight.x, r2.topRight.x); + topRight.y = Min(r1.topRight.y, r2.topRight.y); + } + } +} + +// +//------------------------------------------------------------------------ +// Output stream operator +//------------------------------------------------------------------------ +// +std::ostream& operator<<(std::ostream& Stream, const Rectangle2D& r) +{ + Check(&r); + return Stream << '(' << r.bottomLeft << ',' << r.topRight << ')'; +} + +// +//------------------------------------------------------------------------ +// TestInstance +//------------------------------------------------------------------------ +// +Logical + Rectangle2D::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) +# include "rect2d.tcp" +#endif diff --git a/MUNGA/RECT2D.h b/MUNGA/RECT2D.h new file mode 100644 index 0000000..4262a31 --- /dev/null +++ b/MUNGA/RECT2D.h @@ -0,0 +1,49 @@ +#pragma once + +#include "vector2d.h" + +// Note that the coordinate system used here is such that +// (0,0) is in the lower left corner. + +class Rectangle2D SIGNATURED +{ +public: + Vector2DOf bottomLeft, topRight; + + Rectangle2D(); + Rectangle2D(Vector2DOf bl, Vector2DOf tr); + Rectangle2D(int x1, int y1, int x2, int y2); + ~Rectangle2D() {} + + Logical operator==(const Rectangle2D& r) const + { + return ((bottomLeft == r.bottomLeft) && (topRight == r.topRight)); + } + Logical operator!=(const Rectangle2D& r) const + { + return ((bottomLeft != r.bottomLeft) || (topRight != r.topRight)); + } + + void Union(const Rectangle2D& r1, const Rectangle2D& r2); + + void Intersection(const Rectangle2D& r1, const Rectangle2D& r2); + + void MakeEmpty() + { + Check(this); + bottomLeft.x = 1; + topRight.x = 0; + } + + Logical IsEmpty() const + { + return ((bottomLeft.x > topRight.x) || (bottomLeft.y > topRight.y)); + } + + + friend std::ostream& operator<<(std::ostream& stream, const Rectangle2D& r); + + Logical TestInstance() const; + + static Logical TestClass(); +}; \ No newline at end of file diff --git a/MUNGA/REGISTRY.cpp b/MUNGA/REGISTRY.cpp new file mode 100644 index 0000000..2c47bd4 --- /dev/null +++ b/MUNGA/REGISTRY.cpp @@ -0,0 +1,679 @@ +#include "munga.h" +#pragma hdrstop + +#include "registry.h" +#include "player.h" +#include "mission.h" +#include "terrain.h" +#include "cultural.h" +#include "dropzone.h" +#include "explode.h" +#include "doorfram.h" +#include "eyecandy.h" +#include "director.h" +#include "camship.h" +#include "app.h" +#include "hostmgr.h" + +//############################################################################# +//############################# Registry ################################ +//############################################################################# + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Registry::MessageHandlerEntries[]= +{ + { + Registry::MakeEntityMessageID, + "MakeEntity", + (Registry::Handler)&Registry::MakeEntityMessageHandler + } +}; + +Registry::MessageHandlerSet& Registry::GetMessageHandlers() +{ + static Registry::MessageHandlerSet messageHandlers(ELEMENTS(Registry::MessageHandlerEntries), Registry::MessageHandlerEntries, Receiver::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Shared Data support +// +Derivation* Registry::GetClassDerivations() +{ + static Derivation classDerivations(Receiver::GetClassDerivations(), "Registry"); + return &classDerivations; +} + +Registry::SharedData + Registry::DefaultData( + Registry::GetClassDerivations(), + Registry::GetMessageHandlers() + ); + +// +//############################################################################# +// Registry +//############################################################################# +// +Registry::Registry( + ClassID class_ID, + SharedData &shared_data +): + Receiver(class_ID, shared_data) +{ +} + +// +//############################################################################# +// Registry +//############################################################################# +// +Registry::Registry(): + Receiver(TrivialReceiverClassID, DefaultData) +{ +} + +// +//############################################################################# +// ~Registry +//############################################################################# +// +Registry::~Registry() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Registry::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +// +//############################################################################# +// MakeEntity +//############################################################################# +// +Entity* + Registry::MakeEntity(Entity::MakeMessage *message) +{ + Check(this); + Check(message); + + Entity::SharedData *static_data = GetStaticData(message->classToCreate); + + if (static_data != NULL) + { + Check(static_data); + Check_Pointer(static_data->makeHandler); + return (*static_data->makeHandler)(message); + } + return NULL; +} + +// +//############################################################################# +// MakeTransferedEntity +//############################################################################# +// +Entity* + Registry::MakeTransferedEntity( + HostID, + EntityID, + void* + ) +{ + Fail("Registry::MakeTransferedEntity - under construction"); + return NULL; +} + +// +//############################################################################# +// MakeEntityReplacement +//############################################################################# +// +Entity* + Registry::MakeEntityReplacement( + HostID, + EntityID + ) +{ + Fail("Registry::MakeEntityReplacement - under construction"); + return NULL; +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Entity::SharedData* + Registry::GetStaticData(ClassID class_ID) +{ + switch (class_ID) + { + case TrivialEntityClassID: + return &Entity::DefaultData; + case DropZoneClassID: + return &DropZone::DefaultData; + case TerrainClassID: + return &Terrain::DefaultData; + case CulturalIconClassID: + return &CulturalIcon::DefaultData; + case LandmarkClassID: + return &Landmark::DefaultData; + case TeamClassID: + return &Team::DefaultData; + case UnscalableTerrainClassID: + return &UnscalableTerrain::DefaultData; + case ExplosionClassID: + return &Explosion::DefaultData; + case PlayerClassID: + return &Player::DefaultData; + case DoorFrameClassID: + return &DoorFrame::DefaultData; + case EyeCandyClassID: + return &EyeCandy::DefaultData; + case CameraShipClassID: + return &CameraShip::DefaultData; + case CameraDirectorClassID: + return &CameraDirector::DefaultData; + default: + return NULL; + } +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Player* + Registry::MakePlayer(Mission *mission) +{ + Check(mission); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See if we are a CameraShip + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Enumeration player_flags = Player::DefaultFlags; + if (!strcmp(mission->GetGameModel(), "camera")) + { + player_flags |= Player::CameraShipPlayerFlag; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See if we are a MissionReview, CameraShipHost + // GameMachine CameraShip or regular Player! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application); + HostManager *host_mgr = application->GetHostManager(); + Host *host_ptr = host_mgr->GetLocalHost(); + Check(host_ptr); + HostType host_type = host_ptr->GetHostType(); + + switch(host_type) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make A Player Which is a GameMachine Host + // i.e. VTV, Mech, CameraShip w/controls + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + case GameMachineHostType: + { + Player::MakeMessage make_player( + Player::MakeMessageID, + sizeof(Player::MakeMessage), + PlayerClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + player_flags, + Origin::Identity, + mission->GetPlayerBitmapIndex() + ); + return new Player(&make_player); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make A CameraShip Or Mission Review + // Not a CameraShip to Run on a POD! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + case CameraShipHostType: + case MissionReviewHostType: + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Add any extra flags for a director + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + player_flags |= CameraDirector::DefaultFlags; + CameraDirector::MakeMessage create_director( + CameraDirector::MakeMessageID, + sizeof(CameraDirector::MakeMessage), + CameraDirectorClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + player_flags, + Origin::Identity, + mission->GetPlayerBitmapIndex() + ); + return new CameraDirector(&create_director); + } + } + return NULL; +} + +// +//############################################################################# +// MakeEntityMessageHandler +//############################################################################# +// +void + Registry::MakeEntityMessageHandler(MakeEntityMessage *message) +{ + Check(this); + Check(message); + Verify(message->messageID == MakeEntityMessageID); + + // + // Extract the make message + // + MemoryStream + memory_stream( + message, + message->messageLength + ); + Entity::MakeMessage + *make_message; + + memory_stream.AdvancePointer(sizeof(MakeEntityMessage)); + make_message = Cast_Object(Entity::MakeMessage*, memory_stream.GetPointer()); + Check(make_message); + + // + // Make the entity + // +#if DEBUG_LEVEL>0 + Entity *entity = MakeEntity(make_message); + if (entity) + { + Register_Object(entity); + } +#else + MakeEntity(make_message); +#endif +} + +// +//############################################################################# +// CreateStaticObjectStreamResource +//############################################################################# +// +ResourceDescription::ResourceID + Registry::CreateStaticObjectStreamResource( + NotationFile *notation_file, + ResourceFile *resource_file + ) +{ + Check(notation_file); + Check(resource_file); + + // + //-------------------------------------------------------------------------- + // Build the static object stream + //-------------------------------------------------------------------------- + // + RegistryObjectStream static_object_stream; + + Check(&static_object_stream); + static_object_stream.BuildFromNotationFile( + notation_file, + resource_file + ); + + // + //-------------------------------------------------------------------------- + // Add the resource + //-------------------------------------------------------------------------- + // + ResourceDescription *res_description; + + res_description = + resource_file->AddResourceMemoryStream( + "RegistryStaticObjectStream", + ResourceDescription::RegistryStaticObjectStreamResourceType, + 1, + ResourceDescription::Preload, + &static_object_stream + ); + Check(res_description); + return res_description->resourceID; +} + +// +//############################################################################# +// LoadStaticObjectStreamResource +//############################################################################# +// +void + Registry::LoadStaticObjectStreamResource() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Create static objects + //-------------------------------------------------------------------------- + // + +#if 0 + // + // Get static object stream resource + // + ResourceDescription *resource_description; + + Check(application); + Check(application->GetResourceFile()); + resource_description = + application->GetResourceFile()->FindResourceDescription( + "RegistryStaticObjectStream", + ResourceDescription::RegistryStaticObjectStreamResourceType + ); + + if (resource_description != NULL) + { + Check(resource_description); + + // + // Parse the static object stream + // + RegistryObjectStream static_object_stream(resource_description); + + Check(&static_object_stream); + static_object_stream.CreateObjects(); + } +#else + // + // Load all static object streams + // + ResourceFile *resource_file; + ResourceDescription::ResourceID index, max_resource_ID; + + Check(application); + resource_file = application->GetResourceFile(); + Check(resource_file); + max_resource_ID = resource_file->GetMaxResourceID(); + + for (index = 0; index <= max_resource_ID; index++) + { + ResourceDescription *resource_description = + resource_file->FindResourceDescription(index); + if (resource_description) + { + Check(resource_description); + + // + // Load the static object streams + // + if ( + resource_description->resourceType == + ResourceDescription::RegistryStaticObjectStreamResourceType + ) + { + resource_description->Lock(); + // + // Parse the static object stream + // + RegistryObjectStream static_object_stream(resource_description); + + Check(&static_object_stream); + static_object_stream.CreateObjects(); + resource_description->Unlock(); + } + } + } + resource_file->ReleaseUnlockedResources(); +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~ Registry__MakeEntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Registry__MakeEntityMessage +//############################################################################# +// +Registry__MakeEntityMessage::Registry__MakeEntityMessage(size_t total_length): + Receiver::Message( + Registry::MakeEntityMessageID, + total_length + ) +{ +} + +// +//############################################################################# +// Make +//############################################################################# +// +Registry__MakeEntityMessage* + Registry__MakeEntityMessage::Make(Entity::MakeMessage *make_message) +{ + Check(make_message); + + // + // Allocate memory for the make message + // + size_t + total_length; + void + *buffer; + + total_length = + sizeof (Registry__MakeEntityMessage) + make_message->messageLength; + buffer = new unsigned char[total_length]; + Check_Pointer(buffer); + + // + // Build the make message + // + MemoryStream + memory_stream(buffer, total_length); + Registry__MakeEntityMessage + *make_entity_message; + + make_entity_message = + new (memory_stream.GetPointer()) Registry__MakeEntityMessage(total_length); + Check(make_entity_message); + + memory_stream.AdvancePointer(sizeof(Registry__MakeEntityMessage)); + Mem_Copy( + memory_stream.GetPointer(), + make_message, + make_message->messageLength, + memory_stream.GetBytesRemaining() + ); + + return make_entity_message; +} + +//############################################################################# +//####################### RegistryObjectStream ########################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +RegistryObjectStream::RegistryObjectStream( + ResourceDescription *resource_description +): + PlugStream(resource_description) +{ +} + +// +//############################################################################# +//############################################################################# +// +RegistryObjectStream::RegistryObjectStream() +{ +} + +// +//############################################################################# +//############################################################################# +// +RegistryObjectStream::~RegistryObjectStream() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + RegistryObjectStream::TestInstance() const +{ + PlugStream::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +RegisteredClass* + RegistryObjectStream::MakeObjectImplementation(Enumeration class_ID) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + + RegisteredClass *object; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::ExplosionResourceTableClassID: + object = new ExplosionResourceTable(this); + break; + + // + // Inherited behavior + // + default: + object = PlugStream::MakeObjectImplementation(class_ID); + break; + } + return object; +} + +// +//############################################################################# +//############################################################################# +// +void + RegistryObjectStream::CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ) +{ + Check(this); + Check(object); + Verify(object_ID != NullObjectID); + + // + // Decide which index to add object to + // + switch (object->GetClassID()) + { + // + // Static resources ... + // + case RegisteredClass::ExplosionResourceTableClassID: + AddGlobalPlug(Cast_Object(Plug*, object), object_ID); + break; + + default: + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + RegistryObjectStream::BuildFromPageImplementation( + NameList *name_list, + Enumeration class_ID_enumeration, + ObjectID object_ID + ) +{ + Check(this); + Verify(class_ID_enumeration != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + + RegisteredClass::ClassID + class_ID = (RegisteredClass::ClassID)class_ID_enumeration; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::ExplosionResourceTableClassID: + ExplosionResourceTable::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Inherited behavior + // + default: + PlugStream::BuildFromPageImplementation(name_list, class_ID, object_ID); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + RegistryObjectStream::BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name + ) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + Check(&object_name); + + // + // Decide which index to add object to + // + switch (class_ID) + { + case RegisteredClass::ExplosionResourceTableClassID: + AddGlobalObjectID(object_ID, object_name); + break; + + default: + break; + } +} diff --git a/MUNGA/REGISTRY.h b/MUNGA/REGISTRY.h new file mode 100644 index 0000000..39ea7d1 --- /dev/null +++ b/MUNGA/REGISTRY.h @@ -0,0 +1,163 @@ +#pragma once + +#include "host.h" +#include "objstrm.h" +#include "entity.h" +#include "entityid.h" +#include "resource.h" + +//########################################################################## +//############################ Registry ############################## +//########################################################################## + +class Player; +class Registry__MakeEntityMessage; +class Entity; +class Entity__MakeMessage; +class Entity__SharedData; + +class Registry : public Receiver +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + Registry(ClassID class_ID, SharedData &shared_data); + Registry(); + ~Registry(); + + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Entity creation +// +public: + // + //----------------------------------------------------------------------- + // MakeEntity + //----------------------------------------------------------------------- + // + Entity* MakeEntity(Entity__MakeMessage *message); + + // + //----------------------------------------------------------------------- + // MakeTransferedEntity + // + // The registry creates an entity on this machine which + // represents the transfer of ownership from the old host to this + // host. + //----------------------------------------------------------------------- + // + Entity* MakeTransferedEntity(HostID old_entity_host, EntityID old_entity_ID, void *old_entity_state_data); + + // + //----------------------------------------------------------------------- + // MakeEntityReplacement + // + // If a host abnormally terminates there may be replicants + // hanging unattended by updates. The host manager attempts + // to create a replacement for the lost entity using the + // replicant as a recipe for the replacement. + //----------------------------------------------------------------------- + // + Entity* MakeEntityReplacement(HostID old_entity_host, EntityID replicant_entity_ID); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Entity data access +// +public: + // + //----------------------------------------------------------------------- + // GetStaticData + // + // Provides an interface by which the static data for a class + // may be accessed. + //----------------------------------------------------------------------- + // + virtual Entity__SharedData* GetStaticData(ClassID entity_class); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Player creation +// +public: + // + //----------------------------------------------------------------------- + // Create the player object + //----------------------------------------------------------------------- + // + virtual Player* MakePlayer(Mission *mission); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum + { + MakeEntityMessageID = Receiver::NextMessageID, + NextMessageID + }; + + typedef Registry__MakeEntityMessage + MakeEntityMessage; + + static const HandlerEntry MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + MakeEntityMessageHandler(MakeEntityMessage *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Static object methods +// +public: + static ResourceDescription::ResourceID CreateStaticObjectStreamResource(NotationFile *notation_file, ResourceFile *resource_file); + + void LoadStaticObjectStreamResource(); +}; + +//~~~~~~~~~~~~~~~~~~~~~ Registry__MakeEntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~ + +class Registry__MakeEntityMessage : public Receiver::Message +{ +public: + Registry__MakeEntityMessage(size_t total_length); + + static Registry__MakeEntityMessage* Make(Entity__MakeMessage *message); +}; + +//########################################################################## +//##################### RegistryObjectStream ######################### +//########################################################################## + +class RegistryObjectStream : public PlugStream +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction and testing +// +public: + RegistryObjectStream(); + RegistryObjectStream(ResourceDescription *resource_description); + ~RegistryObjectStream(); + + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +private: + RegisteredClass* MakeObjectImplementation(Enumeration class_ID); + + void CreatedObjectImplementation(RegisteredClass *object, ObjectID object_ID); + + void BuildFromPageImplementation(NameList *entry_list, Enumeration class_ID, ObjectID object_ID); + + void BuiltFromPageImplementation(Enumeration class_ID, ObjectID object_ID, const CString &object_name_string); +}; diff --git a/MUNGA/RENDERER.cpp b/MUNGA/RENDERER.cpp new file mode 100644 index 0000000..25b7493 --- /dev/null +++ b/MUNGA/RENDERER.cpp @@ -0,0 +1,1031 @@ +#include "munga.h" +#pragma hdrstop + +#include "renderer.h" +#include "rndorgn.h" +#include "explode.h" +#include "app.h" +#include "objstrm.h" +#include "hostmgr.h" +#include "subsystm.h" + +//############################################################################# +//############################ Renderer ################################# +//############################################################################# + +const RendererRate DefaultRendererRate = 30.0f; +const RendererComplexity MaxRendererComplexity = 3.0f; +const RendererComplexity MinRendererComplexity = 0.0f; +const RendererFrameBudget DefaultRendererFrameBudget = 0.14f; //0.12f; // 0.16f; + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + Renderer::MessageHandlerEntries[]= +{ + { + Renderer::NotifyOfNewInterestingEntityMessageID, + "NotifyOfNewInterestingEntity", + (Renderer::Handler)&Renderer::NotifyOfNewInterestingEntityMessageHandler + }, + { + Renderer::NotifyOfBecomingUninterestingEntityMessageID, + "NotifyOfBecomingUninterestingEntity", + (Renderer::Handler)&Renderer::NotifyOfBecomingUninterestingEntityMessageHandler + }, + { + Renderer::StartEntityEffectMessageID, + "StartEntityEffect", + (Renderer::Handler)&Renderer::StartEntityEffectMessageHandler + }, + { + Renderer::StopAllEntityEffectsMessageID, + "StopAllEntityEffects", + (Renderer::Handler)&Renderer::StopAllEntityEffectsMessageHandler + }, + { + Renderer::StartEntityAlarmMessageID, + "StartEntityAlarm", + (Renderer::Handler)&Renderer::StartEntityAlarmMessageHandler + }, + { + Renderer::StopEntityAlarmMessageID, + "StopEntityAlarm", + (Renderer::Handler)&Renderer::StopEntityAlarmMessageHandler + } +}; + +Renderer::MessageHandlerSet& Renderer::GetMessageHandlers() +{ + static Renderer::MessageHandlerSet messageHandlers(ELEMENTS(Renderer::MessageHandlerEntries), Renderer::MessageHandlerEntries, Receiver::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Shared Data Support +// +Derivation* Renderer::GetClassDerivations() +{ + static Derivation classDerivations(Receiver::GetClassDerivations(), "Renderer"); + return &classDerivations; +} + +Renderer::SharedData + Renderer::DefaultData( + Renderer::GetClassDerivations(), + Renderer::GetMessageHandlers() + ); + +// +//############################################################################# +// Renderer +//############################################################################# +// +Renderer::Renderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration, + ClassID class_ID, + SharedData &virtual_data +): + Receiver(class_ID, virtual_data), + rendererOriginSocket(NULL), + entitySocket(NULL) +{ + rendererStatus = InactiveRendererStatus; + + calibrationRate = calibration_rate; + calibrationFrameDuration = 1.0f / calibration_rate; + nextRenderTime = 0.0f; + + Verify(MinRendererComplexity < calibration_complexity); + Verify(calibration_complexity <= MaxRendererComplexity); + calibrationComplexity = calibration_complexity; + + calibrationPriority = calibration_priority; + interestType = interest_type; + depthCalibration = depth_calibration; + framePercentBudget = DefaultRendererFrameBudget; + Check_Fpu(); +} + +// +//############################################################################# +// ~Renderer +//############################################################################# +// +Renderer::~Renderer() +{ + UnlinkFromEntity(); + Check_Fpu(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Renderer::TestInstance() const +{ + if (!IsDerivedFrom(*GetClassDerivations())) + { + return False; + } + Check(&rendererOriginSocket); + Check(&entitySocket); + return True; +} + +// +//############################################################################# +// LinkToEntity +//############################################################################# +// +void + Renderer::LinkToEntity(Entity *entity) +{ + Check(this); + Check(entity); + + // + //-------------------------------------------------------------------------- + // Unlink from current entity and add new entity + //-------------------------------------------------------------------------- + // + UnlinkFromEntity(); + entitySocket.Add(entity); + + // + //-------------------------------------------------------------------------- + // Make an interest origin for the given entity + //-------------------------------------------------------------------------- + // + RendererOrigin *rendererOrigin; + + rendererOrigin = + new RendererOrigin( + this, + entity, + interestType, + depthCalibration + ); + Register_Object(rendererOrigin); + + Check(application); + application->GetInterestManager()->AdoptInterestOrigin(rendererOrigin); + rendererOriginSocket.Add(rendererOrigin); + Check_Fpu(); +} + +// +//############################################################################# +// UnlinkFromEntity +//############################################################################# +// +void + Renderer::UnlinkFromEntity() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Delete current interest origin + //-------------------------------------------------------------------------- + // + RendererOrigin *rendererOrigin; + + if ((rendererOrigin = rendererOriginSocket.GetCurrent()) != NULL) + { + Check(rendererOrigin); + + // + // Remove entity from socket + // + entitySocket.Remove(); + + // + // Delete the interest origin + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->OrphanInterestOrigin(rendererOrigin); + Unregister_Object(rendererOrigin); + delete rendererOrigin; + } + Check_Fpu(); +} + +// +//############################################################################# +// LoadMission +//############################################################################# +// +void + Renderer::LoadMission(Mission *mission) +{ + Check(this); + + Verify(rendererStatus == InactiveRendererStatus); + rendererStatus = LoadingRendererStatus; + nextRenderTime = Now(); + + Check(application); + application->GetRendererManager()->StartRenderer(this); + LoadMissionImplementation(mission); + Check_Fpu(); +} + +// +//############################################################################# +// Shutdown +//############################################################################# +// +void + Renderer::Shutdown() +{ + Check(this); + + // + //------------------------------------------------- + // Shutdown and unhook the renderer if it is active + //------------------------------------------------- + // + if (rendererStatus == InactiveRendererStatus) + { + return; + } + + rendererStatus = InactiveRendererStatus; + Check(application); + application->GetRendererManager()->StopRenderer(this); + + ShutdownImplementation(); + Check_Fpu(); +} + +// +//############################################################################# +// SetRendererStatusToRunning +//############################################################################# +// +void + Renderer::SetRendererStatusToRunning() +{ + Verify(rendererStatus == LoadingRendererStatus); + rendererStatus = RunningRendererStatus; + Check_Fpu(); +} + +// +//############################################################################# +// UpdateRendererOrigin +//############################################################################# +// +void + Renderer::UpdateInterestOrigin(Time target_render_time) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // If the renderer is inactive, skip it + //-------------------------------------------------------------------------- + // + if (rendererStatus == InactiveRendererStatus) + return; + + // + //-------------------------------------------------------------------------- + // Does the renderer need to run this frame to meet its frame rate? + //-------------------------------------------------------------------------- + // + if (nextRenderTime > target_render_time) + return; + + // + //-------------------------------------------------------------------------- + // Update the interest origin + //-------------------------------------------------------------------------- + // + Entity *entity; + RendererOrigin *rendererOrigin; + + entity = entitySocket.GetCurrent(); + Check(entity); + rendererOrigin = rendererOriginSocket.GetCurrent(); + Check(rendererOrigin); + rendererOrigin->Update(entity->GetInterestZoneID()); + Check_Fpu(); +} + +// +//############################################################################# +// Execute +//############################################################################# +// +void + Renderer::Execute( + Time target_render_time, + RendererComplexity complexity_update + ) +{ + Check(this); + + mTargetRenderTime = target_render_time; + + // + //-------------------------------------------------------------------------- + // If the renderer is suspended, skip it + //-------------------------------------------------------------------------- + // + if (rendererStatus == InactiveRendererStatus) + return; + + // + //-------------------------------------------------------------------------- + // Does the renderer need to run this frame to meet its frame rate? + //-------------------------------------------------------------------------- + // +// if (nextRenderTime > target_render_time) +// return; + // nextRenderTime += calibrationFrameDuration; + nextRenderTime = Now(); + nextRenderTime += calibrationFrameDuration; + + // + //-------------------------------------------------------------------------- + // Keep track of renderers frame budget + //-------------------------------------------------------------------------- + // + RendererFrameBudget start_percent; + RendererFrameBudget end_percent; + + start_percent = Get_Frame_Percent_Used(); + end_percent = start_percent + framePercentBudget; + Clamp(end_percent, 0.0f, 1.0f); + + // + //-------------------------------------------------------------------------- + // Get interest orign + //-------------------------------------------------------------------------- + // + RendererOrigin *rendererOrigin; + + rendererOrigin = rendererOriginSocket.GetCurrent(); + Check(rendererOrigin); + + // + //-------------------------------------------------------------------------- + // Get iterators for the renderers interest origin and execute + // renderer + //-------------------------------------------------------------------------- + // + RendererOrigin::InterestingEntityIterator + interesting_entity_iterator(rendererOrigin); + + Check(&interesting_entity_iterator); + +Time startImplementation = Now(); + ExecuteImplementation( + complexity_update, + &interesting_entity_iterator + ); +Time endImplementation = Now(); + + // + //-------------------------------------------------------------------------- + // If the renderer is under budget then run background if available + //-------------------------------------------------------------------------- + // + RendererFrameBudget current_frame_use; + /*for ( + current_frame_use = Get_Frame_Percent_Used(); + (start_percent < current_frame_use) && (current_frame_use < end_percent); + current_frame_use = Get_Frame_Percent_Used() + ) + { + if (!ExecuteBackground()) + break; + }*/ + + Check_Fpu(); +} + +// +//############################################################################# +// NotifyOfNewInterestingEntityMessageHandler +//############################################################################# +// +void + Renderer::NotifyOfNewInterestingEntityMessageHandler( + NotifyOfNewInterestingEntityMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == NotifyOfNewInterestingEntityMessageID); + + Entity *entity; + + if ((entity = message->GetInterestingEntity()) != NULL) + { + Check(entity); + NotifyOfNewInterestingEntity(entity); + } + Check_Fpu(); +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntityMessageHandler +//############################################################################# +// +void + Renderer::NotifyOfBecomingUninterestingEntityMessageHandler( + NotifyOfBecomingUninterestingEntityMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == NotifyOfBecomingUninterestingEntityMessageID); + + NotifyOfBecomingUninterestingEntity(message->GetUninterestingEntity()); + Check_Fpu(); +} + +// +//############################################################################# +// StartEntityEffectMessageHandler +//############################################################################# +// +void + Renderer::StartEntityEffectMessageHandler( + StartEntityEffectMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StartEntityEffectMessageID); + + // + //-------------------------------------------------------------------------- + // If the entity does not exists then return + //-------------------------------------------------------------------------- + // + Entity *entity; + if ((entity = message->GetEntity()) == NULL) + return; + Check(entity); + + // + //-------------------------------------------------------------------------- + // Get the effect model resource + //-------------------------------------------------------------------------- + // + ResourceDescription::ResourceID effect_resource_ID; + ResourceDescription *resource_description; + Explosion::ModelResource *model_resource; + + effect_resource_ID = message->GetResourceID(); + Check(application); + Check(application->GetResourceFile()); + resource_description = + application->GetResourceFile()->SearchList( + effect_resource_ID, + ResourceDescription::GameModelResourceType + ); + Check(resource_description); + resource_description->Lock(); + model_resource = + (Explosion::ModelResource*)resource_description->resourceAddress; + Check_Pointer(model_resource); + + // + //-------------------------------------------------------------------------- + // If an explosion resource table is being used then use it to set + // the resource + //-------------------------------------------------------------------------- + // + if (model_resource->resourceTableObjectID != NullObjectID) + { + // + // Get resource table pointer, + // Then set the appropriate resource ID + // + Plug *plug; + ExplosionResourceTable *resource_table; + ResourceDescription::ResourceID new_resource_ID; + + plug = PlugStreamManager::FindPlug(model_resource->resourceTableObjectID); + resource_table = Cast_Object(ExplosionResourceTable*, plug); + Check(resource_table); + new_resource_ID = resource_table->FindResourceID(entity); + if (new_resource_ID != ResourceDescription::NullResourceID) + { + effect_resource_ID = new_resource_ID; + } + } + + // + //-------------------------------------------------------------------------- + // Call the start effect implementation + //-------------------------------------------------------------------------- + // + StartEntityEffectImplementation( + entity, + message->GetDamageZone(), + effect_resource_ID + ); + resource_description->Unlock(); +} + +// +//############################################################################# +// StopAllEntityEffectsMessageHandler +//############################################################################# +// +void + Renderer::StopAllEntityEffectsMessageHandler( + StopAllEntityEffectsMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StopAllEntityEffectsMessageID); + + Entity *entity; + if ((entity = message->GetEntity()) != NULL) + { + Check(entity); + StopAllEntityEffectsImplementation(entity); + } +} + +// +//############################################################################# +// StartEntityAlarmMessageHandler +//############################################################################# +// +void + Renderer::StartEntityAlarmMessageHandler( + StartEntityAlarmMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StartEntityAlarmMessageID); + + Entity *entity; + if ((entity = message->GetEntity()) != NULL) + { + Check(entity); + StartEntityAlarmImplementation( + entity, + message->GetSubsystem(), + message->GetCondition(), + message->GetResourceID() + ); + } +} + +// +//############################################################################# +// StopEntityAlarmMessageHandler +//############################################################################# +// +void + Renderer::StopEntityAlarmMessageHandler( + StopEntityAlarmMessage *message + ) +{ + Check(this); + Check(message); + Verify(message->messageID == StopEntityAlarmMessageID); + + Entity *entity; + if ((entity = message->GetEntity()) != NULL) + { + Check(entity); + StopEntityAlarmImplementation( + entity, + message->GetSubsystem(), + message->GetCondition() + ); + } +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +void + Renderer::ExecuteImplementation( + RendererComplexity, + RendererOrigin::InterestingEntityIterator* + ) +{ + Fail("Renderer::ExecuteImplementation - Should never reach here"); +} + +// +//############################################################################# +// LoadMissionImplementation +//############################################################################# +// +void + Renderer::LoadMissionImplementation(Mission*) +{ + Fail("Renderer::LoadMissionImplementation - Should never reach here"); +} + +// +//############################################################################# +// ShutdownImplementation +//############################################################################# +// +void + Renderer::ShutdownImplementation() +{ + Fail("Renderer::ShutdownImplementation - Should never reach here"); +} + +//############################################################################# +//######################### RendererManager ############################# +//############################################################################# + +// +//############################################################################# +// RendererManager +//############################################################################# +// +RendererManager::RendererManager(): + Receiver(RendererManagerClassID, DefaultData), + renderers(NULL) +{ +} + +// +//############################################################################# +// ~RendererManager +//############################################################################# +// +RendererManager::~RendererManager() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + RendererManager::TestInstance() const +{ + Receiver::TestInstance(); + Check(&renderers); + Check_Fpu(); + return True; +} + +// +//############################################################################# +// StartRenderer +//############################################################################# +// +void + RendererManager::StartRenderer(Renderer *renderer) +{ + Check(this); + Check(renderer); + + #if DEBUG_LEVEL>0 + SChainIterator iterator(&renderers); + Verify(iterator.IsPlugMember(renderer) == False); + #endif + + renderers.Add(renderer); + Check_Fpu(); +} + +// +//############################################################################# +// StopRenderer +//############################################################################# +// +void + RendererManager::StopRenderer(Renderer *renderer) +{ + Check(this); + Check(renderer); + + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&renderers); + Verify(iterator.IsPlugMember(renderer) == True); + } + #endif + + SChainIteratorOf iterator(&renderers); + iterator.RemovePlug(renderer); + Check_Fpu(); +} + +// +//############################################################################# +// AreRenderersRunning +//############################################################################# +// +Logical + RendererManager::AreRenderersRunning() +{ + Check(this); + + Renderer + *renderer; + SChainIteratorOf + renderers_iterator(&renderers); + + if (renderers_iterator.GetCurrent() == NULL) + return False; + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + if (renderer->GetRendererStatus() != RunningRendererStatus) + return False; + } + Check_Fpu(); + return True; +} + +// +//############################################################################# +// UpdateInterestOrigins +//############################################################################# +// +void + RendererManager::UpdateInterestOrigins(Time target_render_time) +{ + Check(this); + + // + // HACK - under construction, does not include complexity or priorities + // + Renderer + *renderer; + SChainIteratorOf + renderers_iterator(&renderers); + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + renderer->UpdateInterestOrigin(target_render_time); + } + Check_Fpu(); +} + +// +//############################################################################# +// Execute +//############################################################################# +// +void + RendererManager::Execute( + Time target_render_time, + Time, + Time + ) +{ + Check(this); + + // + // HACK - under construction, does not include complexity or priorities + // + Renderer *renderer; + RendererComplexity complexity_update; + SChainIteratorOf renderers_iterator(&renderers); +Time startRender = Now(); + int renderItem = 0; + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + + // Calculate current complexity + // HACK - use calibration complexity for now +Time startComplexity = Now(); + complexity_update = renderer->GetCalibrationComplexity(); +Time endComplexity = Now(); + + renderer->Execute(target_render_time, complexity_update); + renderItem++; + } +Time endRender = Now(); +endRender = endRender; + Check_Fpu(); +} + +// +//############################################################################# +// ExecuteIdle +//############################################################################# +// +void RendererManager::ExecuteIdle() +{ + Renderer *renderer; + SChainIteratorOf renderers_iterator(&renderers); + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + + renderer->ExecuteIdle(); + } + Check_Fpu(); +} + +// +//############################################################################# +// PostRendererEvent +//############################################################################# +// +void + RendererManager::PostRendererEvent( + Entity *entity, + Receiver::Message *message + ) +{ + Check(this); + Check(entity); + Check(message); + + Renderer + *renderer; + SChainIteratorOf + renderers_iterator(&renderers); + + while ((renderer = renderers_iterator.ReadAndNext()) != NULL) + { + Check(renderer); + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->PostRendererEvent( + entity, + renderer, + message + ); + } +} + +//~~~~~~~~~~~~~~~~~ Renderer__NotifyOfNewInterestingEntityMessage ~~~~~~~~~~~~~ + +Renderer__NotifyOfNewInterestingEntityMessage:: + Renderer__NotifyOfNewInterestingEntityMessage( + Entity *interesting_entity + ): + Receiver::Message( + Renderer::NotifyOfNewInterestingEntityMessageID, + sizeof(Renderer__NotifyOfNewInterestingEntityMessage) + ) +{ + Check(interesting_entity); + entityID = interesting_entity->GetEntityID(); + Check_Fpu(); +} + +Entity* + Renderer__NotifyOfNewInterestingEntityMessage::GetInterestingEntity() +{ + Check(this); + Check(application); + Check(application->GetHostManager()); + + Check_Fpu(); + return application->GetHostManager()->GetEntityPointer(entityID); +} + +//~~~~~~~~~~~~~~ Renderer__NotifyOfBecomingUninterestingEntityMessage ~~~~~~~~~ + +Renderer__NotifyOfBecomingUninterestingEntityMessage:: + Renderer__NotifyOfBecomingUninterestingEntityMessage( + Entity *uninteresting_entity + ): + Receiver::Message( + Renderer::NotifyOfBecomingUninterestingEntityMessageID, + sizeof(Renderer__NotifyOfBecomingUninterestingEntityMessage) + ) +{ + uninterestingEntity = uninteresting_entity; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~ Renderer__EntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__EntityMessage::Renderer__EntityMessage( + Receiver::MessageID message_ID, + size_t message_size, + Entity *entity +): + Receiver::Message( + message_ID, + message_size + ) +{ + Check(entity); + entityID = entity->GetEntityID(); +} + +Entity* + Renderer__EntityMessage::GetEntity() +{ + Check(this); + Check(application); + Check(application->GetHostManager()); + return application->GetHostManager()->GetEntityPointer(entityID); +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityEffectMessage ~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__StartEntityEffectMessage::Renderer__StartEntityEffectMessage( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID +): + Renderer__EntityMessage( + Renderer::StartEntityEffectMessageID, + sizeof(Renderer__StartEntityEffectMessage), + entity + ) +{ + Check(damage_zone); + Verify(resource_ID != ResourceDescription::NullResourceID); + damageZone = damage_zone; + resourceID = resource_ID; +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StopAllEntityEffectsMessage ~~~~~~~~~~~~~~~~~~~~ + +Renderer__StopAllEntityEffectsMessage::Renderer__StopAllEntityEffectsMessage( + Entity *entity +): + Renderer__EntityMessage( + Renderer::StopAllEntityEffectsMessageID, + sizeof(Renderer__StopAllEntityEffectsMessage), + entity + ) +{ +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__StartEntityAlarmMessage::Renderer__StartEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition, + ResourceDescription::ResourceID resource_ID +): + Renderer__EntityMessage( + Renderer::StartEntityAlarmMessageID, + sizeof(Renderer__StartEntityAlarmMessage), + entity + ) +{ + Check(alarm_subsystem); + #if DEBUG_LEVEL>0 + if (resource_ID == ResourceDescription::NullResourceID) + { + Dump(alarm_subsystem->GetClassID()); + Dump(alarm_condition); + } + #endif + Warn(resource_ID == ResourceDescription::NullResourceID); // HACK - ECH Why is this sometimes NULL? + subsystem = alarm_subsystem; + condition = alarm_condition; + resourceID = resource_ID; +} + +//~~~~~~~~~~~~~~~~~~ Renderer__StopEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~~~~ + +Renderer__StopEntityAlarmMessage::Renderer__StopEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition +): + Renderer__EntityMessage( + Renderer::StopEntityAlarmMessageID, + sizeof(Renderer__StopEntityAlarmMessage), + entity + ) +{ + Check(alarm_subsystem); + subsystem = alarm_subsystem; + condition = alarm_condition; +} + +#ifdef TEST_CLASS +# include "renderer.tcp" +#endif diff --git a/MUNGA/RENDERER.h b/MUNGA/RENDERER.h new file mode 100644 index 0000000..7a10689 --- /dev/null +++ b/MUNGA/RENDERER.h @@ -0,0 +1,740 @@ +#pragma once + +#include "interest.h" +#include "rndorgn.h" +#include "resource.h" + +class DamageZone; +class Subsystem; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ Renderer support types ~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef Scalar RendererRate; +extern const RendererRate DefaultRendererRate; + +typedef Scalar RendererComplexity; +extern const RendererComplexity MaxRendererComplexity; +extern const RendererComplexity MinRendererComplexity; + +typedef Scalar RendererFrameBudget; +extern const RendererFrameBudget DefaultRendererFrameBudget; + +enum RendererPriority +{ + LowRendererPriority = 0, + DefaultRendererPriority, + HighRendererPriority +}; + +enum RendererStatus +{ + InactiveRendererStatus, + LoadingRendererStatus, + RunningRendererStatus +}; + +//########################################################################## +//########################### Renderer ############################### +//########################################################################## + +class Renderer__NotifyOfNewInterestingEntityMessage; +class Renderer__NotifyOfBecomingUninterestingEntityMessage; + +class Renderer__StartEntityEffectMessage; +class Renderer__StopAllEntityEffectsMessage; +class Renderer__StartEntityAlarmMessage; +class Renderer__StopEntityAlarmMessage; + +class Renderer: + public Receiver +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destruction, and Testing +// +public: + ~Renderer(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Control and processing +// +public: + // + //----------------------------------------------------------------------- + // LoadMission, Shutdown + //----------------------------------------------------------------------- + // + void + LoadMission(Mission *mission); + void + Shutdown(); + + // + //----------------------------------------------------------------------- + // LinkToEntity + // + // This method links the renderer to an entity. Overrides must call + // the inherited method. + //----------------------------------------------------------------------- + // + virtual void + LinkToEntity(Entity *entity); + + // + //----------------------------------------------------------------------- + // UnlinkFromEntity + //----------------------------------------------------------------------- + // + virtual void + UnlinkFromEntity(); + + // + //----------------------------------------------------------------------- + // SetRendererStatusToRunning + //----------------------------------------------------------------------- + // + void + SetRendererStatusToRunning(); + + // + //----------------------------------------------------------------------- + // UpdateInterestOrigin + //----------------------------------------------------------------------- + // + void + UpdateInterestOrigin(Time target_render_time); + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + void Execute(Time target_render_time, RendererComplexity complexity_update); + virtual void ExecuteIdle(); + virtual Logical ExecuteBackground(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +public: + // + //----------------------------------------------------------------------- + // GetLinkedEntity + //----------------------------------------------------------------------- + // + Entity* + GetLinkedEntity(); + + // + //----------------------------------------------------------------------- + // GetRendererStatus + //----------------------------------------------------------------------- + // + RendererStatus + GetRendererStatus(); + + // + //----------------------------------------------------------------------- + // Misc + //----------------------------------------------------------------------- + // + RendererComplexity + GetCalibrationComplexity(); + Time + GetCalibrationFrameDuration(); + RendererRate + GetCalibrationRate(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest Manager support +// +public: + // + //----------------------------------------------------------------------- + // NotifyOfNewInterestingEntity + //----------------------------------------------------------------------- + // + virtual void + NotifyOfNewInterestingEntity(Entity *) {} + + // + //----------------------------------------------------------------------- + // NotifyOfBecomingUninterestingEntity + //----------------------------------------------------------------------- + // + virtual void + NotifyOfBecomingUninterestingEntity(Entity *) {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum { + NotifyOfNewInterestingEntityMessageID = Receiver::NextMessageID, + NotifyOfBecomingUninterestingEntityMessageID, + StartEntityEffectMessageID, + StopAllEntityEffectsMessageID, + StartEntityAlarmMessageID, + StopEntityAlarmMessageID, + NextMessageID + }; + + typedef Renderer__NotifyOfNewInterestingEntityMessage + NotifyOfNewInterestingEntityMessage; + typedef Renderer__NotifyOfBecomingUninterestingEntityMessage + NotifyOfBecomingUninterestingEntityMessage; + typedef Renderer__StartEntityEffectMessage + StartEntityEffectMessage; + typedef Renderer__StopAllEntityEffectsMessage + StopAllEntityEffectsMessage; + typedef Renderer__StartEntityAlarmMessage + StartEntityAlarmMessage; + typedef Renderer__StopEntityAlarmMessage + StopEntityAlarmMessage; + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + NotifyOfNewInterestingEntityMessageHandler( + NotifyOfNewInterestingEntityMessage *message + ); + void + NotifyOfBecomingUninterestingEntityMessageHandler( + NotifyOfBecomingUninterestingEntityMessage *message + ); + void + StartEntityEffectMessageHandler( + StartEntityEffectMessage *message + ); + void + StopAllEntityEffectsMessageHandler( + StopAllEntityEffectsMessage *message + ); + void + StartEntityAlarmMessageHandler( + StartEntityAlarmMessage *message + ); + void + StopEntityAlarmMessageHandler( + StopEntityAlarmMessage *message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction +// +protected: + // + //----------------------------------------------------------------------- + // Construction + // + // Where calibration_rate indicates the update rate, and + // calibration_complexity indicates an arbitrary "maximum" complexity + // level passed to the renderer. The renderer manager will dynamically + // vary the value of complexity based on the actual frame rate that the + // renderer is able to maintain (if the total system load exceeds + // 100% of the maximum, each renderer's actual frame rate will drop + // below the requested rate: the renderer manager will detect this and + // lower the complexity value). The renderer manager will then + // periodically invoke the renderer's execute function, passing it the + // value indicated in complexity. + //----------------------------------------------------------------------- + // + Renderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration, + ClassID class_ID=TrivialReceiverClassID, + SharedData &virtual_data=DefaultData + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected accessors +// +protected: + // + //----------------------------------------------------------------------- + // GetInterestOrigin + //----------------------------------------------------------------------- + // + RendererOrigin* + GetInterestOrigin(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected implementations +// +protected: + Time mTargetRenderTime; + // + //----------------------------------------------------------------------- + // Execute + // + // This method is called by the rendering manager to execute renderer + // updates. Overrides must call the inherited method. + //----------------------------------------------------------------------- + // + virtual void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private implementations +// +private: + virtual void + LoadMissionImplementation(Mission *mission); + virtual void + ShutdownImplementation(); + virtual void + StartEntityEffectImplementation( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ) + {} + virtual void + StopAllEntityEffectsImplementation(Entity *entity) + {} + virtual void + StartEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID resource_ID + ) + {} + virtual void + StopEntityAlarmImplementation( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ) + {} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + // + // Current running state of the renderer + // + RendererStatus + rendererStatus; + + // + // Renderer frame rate related valriables + // + RendererRate + calibrationRate; + Time + calibrationFrameDuration, + nextRenderTime; + + // + // Renderer complexity, depth, and priority + // control related variables + // + RendererComplexity + calibrationComplexity; + RendererPriority + calibrationPriority; + InterestType + interestType; + InterestDepth + depthCalibration; + RendererFrameBudget + framePercentBudget; + + // + // Sockets + // + SlotOf + rendererOriginSocket; + SlotOf + entitySocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Renderer inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline Entity* + Renderer::GetLinkedEntity() +{ + Check(&entitySocket); + return entitySocket.GetCurrent(); +} + +inline RendererOrigin* + Renderer::GetInterestOrigin() +{ + Check(&rendererOriginSocket); + return rendererOriginSocket.GetCurrent(); +} + +inline RendererStatus + Renderer::GetRendererStatus() +{ + Check(this); + return rendererStatus; +} + +inline RendererComplexity +Renderer::GetCalibrationComplexity() +{ +Check(this); +return calibrationComplexity; +} + +inline Time +Renderer::GetCalibrationFrameDuration() +{ +Check(this); + return calibrationFrameDuration; +} + +inline RendererRate +Renderer::GetCalibrationRate() +{ +Check(this); + return calibrationRate; +} + +inline void Renderer::ExecuteIdle() +{ + Check(this); + return; +} + +inline Logical Renderer::ExecuteBackground() +{ +Check(this); + return False; +} + +//########################################################################## +//######################## RendererManager ########################### +//########################################################################## + +class RendererManager: + public Receiver +{ + friend class Renderer; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction. Testing +// +public: + RendererManager(); + ~RendererManager(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Control, and processing +// +public: + // + //----------------------------------------------------------------------- + // UpdateInterestOrigins + // + // Called by the application to update the renderers interest origins + // before the interest manager performs its execute method. + //----------------------------------------------------------------------- + // + void + UpdateInterestOrigins(Time target_render_time); + + // + //----------------------------------------------------------------------- + // Execute + // + // Perform renderer management functions + //----------------------------------------------------------------------- + // + void + Execute( + Time target_render_time, + Time target_frame_duration, + Time actual_frame_duration + ); + + // + //----------------------------------------------------------------------- + // ExecuteIdle + // + // Allow renderers to perform functions during idle (WaitingForEgg) + //----------------------------------------------------------------------- + // + void ExecuteIdle(); + + // + //----------------------------------------------------------------------- + // AreRenderersRunning + //----------------------------------------------------------------------- + // + Logical + AreRenderersRunning(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Effects and Alarms +// +public: + void + StartEntityEffect( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ); + + void + StopAllEntityEffects(Entity *entity); + + void + StartEntityAlarm( + Entity *entity, + Subsystem *subsystem, + Enumeration condition, + ResourceDescription::ResourceID resource_ID + ); + + void + StopEntityAlarm( + Entity *entity, + Subsystem *subsystem, + Enumeration condition + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + void + StartRenderer(Renderer *renderer); + void + StopRenderer(Renderer *renderer); + + void + RendererManager::PostRendererEvent( + Entity *entity, + Receiver::Message *message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + SChainOf + renderers; +}; + +//~~~~~~~~~~~~~~ Renderer__NotifyOfNewInterestingEntityMessage ~~~~~~~~~~~~~ + +class Renderer__NotifyOfNewInterestingEntityMessage: + public Receiver::Message +{ +public: + Renderer__NotifyOfNewInterestingEntityMessage( + Entity *interesting_entity + ); + + Entity* + GetInterestingEntity(); + +private: + EntityID + entityID; +}; + +//~~~~~~~~~~ Renderer__NotifyOfBecomingUninterestingEntityMessage ~~~~~~~~~~ + +class Renderer__NotifyOfBecomingUninterestingEntityMessage: + public Receiver::Message +{ +public: + Renderer__NotifyOfBecomingUninterestingEntityMessage( + Entity *uninteresting_entity + ); + + Entity* + GetUninterestingEntity() + {return uninterestingEntity;} + +private: + Entity + *uninterestingEntity; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~ Renderer__EntityMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Renderer__EntityMessage: + public Receiver::Message +{ +public: + Renderer__EntityMessage( + Receiver::MessageID message_ID, + size_t message_size, + Entity *entity + ); + + Entity* + GetEntity(); + +private: + EntityID + entityID; +}; + +//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityEffectMessage ~~~~~~~~~~~~~~~~~~~~ + +class Renderer__StartEntityEffectMessage: + public Renderer__EntityMessage +{ +public: + Renderer__StartEntityEffectMessage( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ); + + DamageZone* + GetDamageZone() + {return damageZone;} + ResourceDescription::ResourceID + GetResourceID() + {return resourceID;} + +private: + DamageZone + *damageZone; + ResourceDescription::ResourceID + resourceID; +}; + +//~~~~~~~~~~~~~~~~~~ Renderer__StopAllEntityEffectsMessage ~~~~~~~~~~~~~~~~~ + +class Renderer__StopAllEntityEffectsMessage: + public Renderer__EntityMessage +{ +public: + Renderer__StopAllEntityEffectsMessage(Entity *entity); +}; + +//~~~~~~~~~~~~~~~~~~ Renderer__StartEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~ + +class Renderer__StartEntityAlarmMessage: + public Renderer__EntityMessage +{ +public: + Renderer__StartEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition, + ResourceDescription::ResourceID resource_ID + ); + + Subsystem* + GetSubsystem() + {return subsystem;} + Enumeration + GetCondition() + {return condition;} + ResourceDescription::ResourceID + GetResourceID() + {return resourceID;} + +private: + Subsystem + *subsystem; + Enumeration + condition; + ResourceDescription::ResourceID + resourceID; +}; + +//~~~~~~~~~~~~~~~~~~ Renderer__StopEntityAlarmMessage ~~~~~~~~~~~~~~~~~~~~~~ + +class Renderer__StopEntityAlarmMessage: + public Renderer__EntityMessage +{ +public: + Renderer__StopEntityAlarmMessage( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition + ); + + Subsystem* + GetSubsystem() + {return subsystem;} + Enumeration + GetCondition() + {return condition;} + +private: + Subsystem + *subsystem; + Enumeration + condition; +}; + +//~~~~~~~~~~~~~~~~~~~~~~ RendererManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline void + RendererManager::StartEntityEffect( + Entity *entity, + DamageZone *damage_zone, + ResourceDescription::ResourceID resource_ID + ) +{ + Renderer::StartEntityEffectMessage + message(entity, damage_zone, resource_ID); + PostRendererEvent(entity, &message); +} + +inline void + RendererManager::StopAllEntityEffects(Entity *entity) +{ + Renderer::StopAllEntityEffectsMessage + message(entity); + PostRendererEvent(entity, &message); +} + +inline void + RendererManager::StartEntityAlarm( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition, + ResourceDescription::ResourceID resource_ID + ) +{ + Renderer::StartEntityAlarmMessage + message(entity, alarm_subsystem, alarm_condition, resource_ID); + PostRendererEvent(entity, &message); +} + +inline void + RendererManager::StopEntityAlarm( + Entity *entity, + Subsystem *alarm_subsystem, + Enumeration alarm_condition + ) +{ + Renderer::StopEntityAlarmMessage + message(entity, alarm_subsystem, alarm_condition); + PostRendererEvent(entity, &message); +} diff --git a/MUNGA/RESOURCE.cpp b/MUNGA/RESOURCE.cpp new file mode 100644 index 0000000..c9c42ee --- /dev/null +++ b/MUNGA/RESOURCE.cpp @@ -0,0 +1,911 @@ +#include "munga.h" +#include "windows.h" +#pragma hdrstop + +#include "resource.h" +#include "resver.h" + +ResourceDescription::ResourceDescription( + ResourceFile *file, + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord flags, + const void* address, + size_t size, + ResourceDescription::ResourceID index +) +{ + Check(this); + Check_Pointer(name); + + resourceFile = file; + resourceID = index; + resourceType = type; + Str_Copy(resourceName, name, sizeof(resourceName)); + for (int i = strlen(resourceName) + 1; iLoadResource(this); + Verify(resourceAddress); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ResourceDescription::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################## ResourceFile ############################### +//############################################################################# + +//############################################################################# +// ResourceFile CONSTRUCTORS & DESTRUCTORS +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceFile::ResourceFile(): + labOnly(0), + resourceArray(NULL), + resourceArraySize(0), + maxResourceID(ResourceDescription::NullResourceID), + lastPreallocatedResourceID(ResourceDescription::NullResourceID) +{ + versionArray[0] = RESOURCE_FORMAT_VERSION; + versionArray[1] = 0; + versionArray[2] = 0; + versionArray[3] = 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceFile::~ResourceFile() +{ + if (resourceArray) + { + for (int i=maxResourceID; i>=0; i--) + { + if (resourceArray[i]) + { + Unregister_Object(resourceArray[i]); + delete resourceArray[i]; + } + } + Unregister_Pointer(resourceArray); + delete[] resourceArray; + } + + versionArray[0] = RESOURCE_FORMAT_VERSION; + versionArray[1] = 0; + versionArray[2] = 0; + versionArray[3] = 0; + labOnly = 0; + resourceArraySize = 0; + maxResourceID = ResourceDescription::NullResourceID; + resourceArray = NULL; +} + +//############################################################################## +// ResourceFile METHODS +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription* + ResourceFile::AddResource( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + const void* address, + size_t size, + ResourceDescription::ResourceID index + ) +{ + Check(this); + Check_Pointer(name); + + int i; + // + //------------------------------------------------------------------------- + // If we asked for the next available ID number, find out what it should be + //------------------------------------------------------------------------- + // + if (index == ResourceDescription::NullResourceID) + { + index = lastPreallocatedResourceID + 1; + if (resourceArray) + { + Check_Pointer(resourceArray); + for (; index<=resourceArraySize; ++index) + { + if (!resourceArray[index]) + { + break; + } + } + } + } + + // + //------------------------------------------------------------- + // Check to see if the resource index table needs to be created + //------------------------------------------------------------- + // + if (!resourceArray) + { + resourceArraySize = index + IndexBlockSize; + resourceArray = new ResourceDescription* [resourceArraySize]; + Register_Pointer(resourceArray); + for (i=0; i= resourceArraySize) + { + // + //---------------------------------------- + // Allocate a new table for the main index + //---------------------------------------- + // + ResourceDescription **new_index = + new ResourceDescription* [index + IndexBlockSize]; + Register_Pointer(new_index); + + // + //------------------------------------ + // Copy the old table into the new one + //------------------------------------ + // + Check_Pointer(resourceArray); + for (i=0; i maxResourceID) + { + maxResourceID = index; + } + resourceArray[index] = + new ResourceDescription( + this, + name, + type, + priority, + load_flag, + address, + size, + index + ); + + // + //---------------------------------------------------------------------- + // The caller of this function is responsible for registering the memory + //---------------------------------------------------------------------- + // + Register_Object(resourceArray[index]); + return resourceArray[index]; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription* + ResourceFile::AddResourceList( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + const ResourceDescription::ResourceID* address, + int count, + ResourceDescription::ResourceID index + ) +{ + Check(this); + Check_Pointer(name); + Check_Pointer(address); + + // + //-------------------------------------------------------- + // prefix the directory table with the count of references + //-------------------------------------------------------- + // + ResourceDescription::ResourceID *table = + new ResourceDescription::ResourceID[count+1]; + Register_Pointer(table); + for (int i=0; iGetBytesUsed(); + memory_stream->Rewind(); + + return + AddResource( + name, + type, + priority, + load_flag, + memory_stream->GetPointer(), + size, + index + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ResourceFile::DeleteResource(ResourceDescription *resource) +{ + Check(this); + Check(resource); + Check_Pointer(resourceArray); + Verify(!resource->IsLocked()); + + // + //------------------------------------------------------------------------ + // Delete pointer from resoureArray if it was there + //------------------------------------------------------------------------ + // + if (resource->resourceID != ResourceDescription::NullResourceID ) + { + resourceArray[resource->resourceID] = NULL; + + // + //------------------------------------------------------------------------ + // Find new maxResourceID + //------------------------------------------------------------------------ + // + if (resource->resourceID == maxResourceID ) + { + ResourceDescription::ResourceID i; + for (i = maxResourceID; i>=0; i--) + { + if(resourceArray[i] != NULL) + { + Check(resourceArray[i]); + break; + } + } + maxResourceID = i; + } + } + // + //------------------------------------------------------------------------ + // The caller of this function is responsible for unregistering the memory + //------------------------------------------------------------------------ + // + + delete resource; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription* + ResourceFile::FindResourceDescription(ResourceDescription::ResourceID index) +{ + Check(this); + + if (index<0 || index>maxResourceID || !resourceArray) + { + return NULL; + } + + Check_Pointer(resourceArray); + ResourceDescription *res = resourceArray[index]; + return res; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription* + ResourceFile::FindResourceDescription( + const char* name, + ResourceDescription::ResourceType type, + ResourceDescription::ResourceID after + ) +{ + Check(this); + + ResourceDescription *desc; + ResourceDescription::ResourceID i; + for (i=after+1; i<=maxResourceID; ++i) + { + desc = FindResourceDescription(i); + if (desc) + { + Check(desc); + if ( + type == desc->resourceType && + (!name || !strcmp(name, desc->resourceName)) + ) + { + break; + } + } + } + if (i > maxResourceID) + { + desc = NULL; + } + return desc; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription* + ResourceFile::SearchList( + ResourceDescription::ResourceID list_id, + ResourceDescription::ResourceType type + ) +{ + ResourceDescription *list_res = FindResourceDescription(list_id); + if (list_res) + { + Check(list_res); + list_res->Lock(); + Verify( + list_res->resourceType <= ResourceDescription::MaxListResourceType + ); + ResourceDescription::ResourceID *list = + (ResourceDescription::ResourceID*)list_res->resourceAddress; + Check_Pointer(list); + for (int i=1; i<=*list; ++i) + { + ResourceDescription *res = FindResourceDescription(list[i]); + Check(res); + if (res->resourceType == type) + { + list_res->Unlock(); + return res; + } + } + list_res->Unlock(); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription* + ResourceFile::SearchList( + ResourceDescription::ResourceID list_id, + const char* name + ) +{ + Check_Pointer(name); + ResourceDescription *list_res = FindResourceDescription(list_id); + if (list_res) + { + Check(list_res); + list_res->Lock(); + Verify( + list_res->resourceType <= ResourceDescription::MaxListResourceType + ); + ResourceDescription::ResourceID *list = + (ResourceDescription::ResourceID*)list_res->resourceAddress; + Check_Pointer(list); + for (int i=1; i<=*list; ++i) + { + ResourceDescription *res = FindResourceDescription(list[i]); + Check(res); + if (!strcmp(name, res->resourceName)) + { + list_res->Unlock(); + return res; + } + } + list_res->Unlock(); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ResourceFile::ReleaseUnlockedResources() +{ + for (ResourceDescription::ResourceID i = maxResourceID; i>=0; i--) + { + if(resourceArray[i] != NULL) + { + ResourceDescription *res = resourceArray[i]; + Check(res); + res->ReleaseUnlockedResource(); + } + } +} + +//############################################################################# +// ResourceFile Test Support +// + +Logical + ResourceFile::TestInstance() const +{ + return True; +} + +//############################################################################## +//########################## StreamableResourceFile ###################### +//############################################################################## +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +StreamableResourceFile::StreamableResourceFile() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +StreamableResourceFile::StreamableResourceFile(const char* file_name) +{ + Open(file_name); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +StreamableResourceFile::StreamableResourceFile(const char* file_name, Byte version_array[3], int match_level) +{ + Open(file_name); + int i; + for (i=0; i> labOnly >> maxResourceID; + + // + //------------------------------------------------------------------ + // Read in main index table first, and make room for expansion later + //------------------------------------------------------------------ + // + size_t *offset_table = new size_t[maxResourceID]; + Register_Pointer(offset_table); + + diskFile.ReadBytes(offset_table, maxResourceID*sizeof(size_t)); + resourceArraySize = maxResourceID + IndexBlockSize; + + resourceArray = new ResourceDescription*[resourceArraySize]; + Register_Pointer(resourceArray); + int i; + for (i=0; i> buffer; + + // + //------------------------------------------------- + // If the preload flag is set, read in the resource + //------------------------------------------------- + // + + char *data = NULL; + if (buffer.resourceFlags == ResourceDescription::Preload && buffer.resourceLength > 0) + { + data = new char[buffer.resourceLength]; + Register_Pointer(data); + diskFile.SetPointer(buffer.resourceOffset); + diskFile.ReadBytes(data, buffer.resourceLength); + } + if (buffer.resourceType > ResourceDescription::MaxListResourceType || !data) + { + resourceArray[i] = AddResource( + buffer.resourceName, + buffer.resourceType, + buffer.downloadPriority, + buffer.resourceFlags, + data, + buffer.resourceLength, + buffer.resourceID + ); + } + else + { + resourceArray[i] = AddResourceList( + buffer.resourceName, + buffer.resourceType, + buffer.downloadPriority, + buffer.resourceFlags, + (int*)data + 1, + *(int*)data, + buffer.resourceID + ); + } + resourceArray[i]->offsetInFile = buffer.resourceOffset; + if (data) + { + resourceArray[i]->Lock(); + Unregister_Pointer(data); + delete[] data; + } + } + + Unregister_Pointer(offset_table); + delete[] offset_table; + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + StreamableResourceFile::Save() +{ + Check(this); + if (!resourceArray) + { + return False; + } + + // + //----------------------------------------------------------------------- + // Make sure to load any unloaded resources before closing the input file + //----------------------------------------------------------------------- + // + ResourceDescription *desc; + ResourceDescription::ResourceID i; + for (i=0; i<=maxResourceID; ++i) + { + desc = resourceArray[i]; + if (desc) + { + Check(desc); + desc->LoadResource(); + } + } + + // + //------------------------------------------- + // Close the current file, and open a new one + //------------------------------------------- + // + if (diskFile.IsFileOpened()) + { + diskFile.Close(); + } + diskFile.Open(resourceFilename, True); + Verify(diskFile.IsFileOpened()); + + // + //------------------------------------- + // Write out resource count and version + //------------------------------------- + // + ++maxResourceID; + + diskFile.WriteBytes(&versionArray, sizeof(versionArray)); + diskFile << labOnly << maxResourceID; + + // + //-------------------------------------------------------------------------- + // Write out main index table first. This is just filling up space, and the + // offsets will have to be written back into this section later + //-------------------------------------------------------------------------- + // + size_t *offset_table = new size_t[maxResourceID]; + Register_Pointer(offset_table); + diskFile.WriteBytes(offset_table, maxResourceID*sizeof(size_t)); + + // + //------------------------------------------------------------------------- + // Step through the index table, writing out each description as we find it + //------------------------------------------------------------------------- + // + for (i=0; iresourceAddress, desc->resourceSize); + + // + //-------------------------- + // Write out the description + //-------------------------- + // + offset_table[i] = diskFile.GetIndex(); + buffer.resourceID = desc->resourceID; + buffer.resourceType = desc->resourceType; + + //#if sizeof(buffer.resourceName) < sizeof(desc->resourceName) + //# error ResourceDescription::resourceName is too big! + //#endif + + memcpy( + buffer.resourceName, + desc->resourceName, + sizeof(desc->resourceName) + ); + + buffer.resourceLength = desc->resourceSize; + buffer.downloadPriority = desc->downloadPriority; + buffer.resourceFlags = + desc->resourceFlags & ~ResourceDescription::LoadedFlag; + diskFile << buffer; + } + diskFile.SetPointer( + sizeof(maxResourceID) + sizeof(versionArray) + sizeof(labOnly) + ); + diskFile.WriteBytes(offset_table, maxResourceID*sizeof(long)); + Unregister_Pointer(offset_table); + delete(offset_table); + --maxResourceID; + diskFile.Close(); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + StreamableResourceFile::SaveAs(const char* file_name) +{ + Str_Copy(resourceFilename, file_name, sizeof(resourceFilename)); + return Save(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + StreamableResourceFile::LoadResource(ResourceDescription *res) +{ + ResourceFile::LoadResource(res); + Verify(!res->resourceAddress); + res->resourceAddress = new char[res->resourceSize]; + Register_Pointer(res->resourceAddress); + diskFile.SetPointer(res->offsetInFile); + diskFile.ReadBytes(res->resourceAddress, res->resourceSize); +} + +//############################################################################# +// StreamableResourceFile Test Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + StreamableResourceFile::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) + #include "resource.tcp" +#endif diff --git a/MUNGA/RESOURCE.h b/MUNGA/RESOURCE.h new file mode 100644 index 0000000..d17bfb7 --- /dev/null +++ b/MUNGA/RESOURCE.h @@ -0,0 +1,409 @@ +#pragma once + +#include "filestrm.h" + +//########################################################################## +//#################### ResourceDirectories ########################### +//########################################################################## + +struct ResourcePhysicalFormat; +class ResourceFile; + +struct ResourceDirectories +{ + const char *modelDirectory; + const char *mapDirectory; + const char *collisionDirectory; + const char *audioDirectory; + const char *videoDirectory; + const char *gaugeDirectory; + const char *animationDirectory; +}; + +//########################################################################## +//################### ResourceDescription ############################ +//########################################################################## + +class ResourceDescription SIGNATURED +{ + friend class ResourceFile; + friend class StreamableResourceFile; + +//########################################################################## +// Resource ID stuff +// +public: + typedef int ResourceID; + + enum + { + NullResourceID = -1 + }; + + ResourceID resourceID; + +//########################################################################## +// Resource Lock stuff +// +public: + void Lock() { if (!lockCount++) LoadResource(); } + void Unlock() { --lockCount; } + + Logical IsLocked() { return lockCount > 0; } + + void ReleaseUnlockedResource(); + +protected: + int lockCount; + +//########################################################################## +// Resource Type stuff +// +public: + typedef int ResourceType; + + enum + { + NullResourceType, + + // + // ONLY LIST RESOURCE TYPES HERE -- These Are Really OBSOLETE + // + ModelListResourceType, + MapListResourceType, + AudioStreamListResourceType, + VideoListResourceType, + SubsystemListResourceType, + ControlMappingsListResourceType, + DamageZoneListResourceType, + SkeletonListResourceType, + + FirstNonListResourceType, + MaxListResourceType = FirstNonListResourceType - 1, + // + // ALL OTHER RESOURCE TYPES + // + BoxedSolidStreamResourceType = FirstNonListResourceType, + VideoModelResourceType, + StaticAudioStreamResourceType, + InternalAudioStreamResourceType, + ExternalAudioStreamResourceType, + MakeMessageStreamResourceType, + GameModelResourceType, + AnimationResourceType, + SubsystemModelStreamResourceType, + GaugeImageStreamResourceType, + ControlMappingStreamResourceType, + DamageZoneStreamResourceType, + SkeletonStreamResourceType, + DropZoneResourceType, + EnvironmentZoneResourceType, + InterestZoneResourceType, + VehicleTableResourceType, + ExistanceBoxStreamResourceType, + CameraStreamResourceType, + RegistryStaticObjectStreamResourceType, + DamageLookupTableStreamResourceType, + ExplosionTableStreamResourceType, + GaugeAlarmStreamResourceType, + GaugeMissionReviewStreamResourceType, + ScenarioRoleResourceType + }; + + ResourceType resourceType; + +//########################################################################## +// Resource Name stuff +// +public: + enum + { + NameSize = 32 + }; + + char resourceName[NameSize]; + +//########################################################################## +// Loading stuff +// +public: + enum + { + LoadedBit=0, + LoadOnDemandBit + }; + enum + { + Preload = 0, // HACK - for backwards compatability + LoadedFlag = 1 << LoadedBit, + LoadOnDemandFlag = 1 << LoadOnDemandBit, + }; + + int downloadPriority; + + LWord resourceFlags; + + size_t offsetInFile; + + void SetLoaded() { resourceFlags |= LoadedFlag; } + void SetNotLoaded() { resourceFlags &= ~LoadedFlag; } + Logical IsLoaded() { return (resourceFlags & LoadedFlag) != 0; } + + void LoadOnDemand() { resourceFlags |= LoadOnDemandFlag; } + void MarkForPreload() { resourceFlags &= ~LoadOnDemandFlag; } + Logical IsPreloadable() { return (resourceFlags & LoadOnDemandFlag) == 0; } + +//########################################################################## +// Construction and Destruction +// +protected: + ResourceDescription( + ResourceFile *file, + const char* name, + ResourceType type, + int priority, + LWord resource_flags, + const void* address, + size_t size, + ResourceID index=NullResourceID + ); + + ~ResourceDescription(); + + void LoadResource(); + +protected: + ResourceFile *resourceFile; + +//########################################################################## +// Resource Data stuff +// +public: + void *resourceAddress; + + size_t resourceSize; + +//########################################################################## +// Test stuff +// +public: + Logical TestInstance() const; +}; + +//########################################################################## +// Format in physical memory: FILE,ROM,CD... +// +struct ResourcePhysicalFormat +{ + ResourceDescription::ResourceID + resourceID; + ResourceDescription::ResourceType + resourceType; + char + resourceName[32]; + int + downloadPriority; + LWord + resourceFlags; + size_t + resourceOffset, + resourceLength; +}; + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + ResourcePhysicalFormat *ptr + ) + {return stream->ReadBytes(ptr, sizeof(*ptr));} +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const ResourcePhysicalFormat *ptr + ) + {return stream->WriteBytes(ptr, sizeof(*ptr));} + +//########################################################################## +//####################### ResourceFile ############################### +//########################################################################## + +class ResourceFile SIGNATURED +{ + friend class ResourceDescription; + +public: + // + //----------------------------------------------------------------------- + // Constructors & destructors + //----------------------------------------------------------------------- + // + ResourceFile(); + ~ResourceFile(); + +public: + // + //----------------------------------------------------------------------- + // Public data + //----------------------------------------------------------------------- + // + enum { + IndexBlockSize = 50 + }; + + Byte + versionArray[4]; + int + labOnly; + +protected: + ResourceDescription** + resourceArray; + int + resourceArraySize; + ResourceDescription::ResourceID + lastPreallocatedResourceID, + maxResourceID; + + virtual void + LoadResource(ResourceDescription* res) + {Check(res); res->SetLoaded();} + +public: + // + //----------------------------------------------------------------------- + // Public interface + //----------------------------------------------------------------------- + // + ResourceDescription::ResourceID + GetMaxResourceID() + {Check(this); return maxResourceID;} + void + PreAllocateIDs(ResourceDescription::ResourceID last_id) + { + Verify(lastPreallocatedResourceID == ResourceDescription::NullResourceID); + lastPreallocatedResourceID = last_id; + } + + ResourceDescription* + AddResource( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + const void* address, + size_t size, + ResourceDescription::ResourceID index=-1 + ); + ResourceDescription* + AddResourceList( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + const ResourceDescription::ResourceID* address, + int count, + ResourceDescription::ResourceID index=-1 + ); + ResourceDescription* + AddResourceMemoryStream( + const char* name, + ResourceDescription::ResourceType type, + int priority, + LWord load_flag, + MemoryStream* memory_stream, + ResourceDescription::ResourceID index=-1 + ); + void + DeleteResource(ResourceDescription *resource); + + ResourceDescription* + FindResourceDescription( + const char* name, + ResourceDescription::ResourceType type, + ResourceDescription::ResourceID after=-1 + ); + ResourceDescription* + FindResourceDescription( + ResourceDescription::ResourceID index + ); + + ResourceDescription* + SearchList( + ResourceDescription::ResourceID list_id, + ResourceDescription::ResourceType type + ); + ResourceDescription* + SearchList( + ResourceDescription::ResourceID list_id, + const char* name + ); + + void + ReleaseUnlockedResources(); + void + ReportLockedResources(); + + // + //--------------------------------------------------------------------------- + // Lab tests + //--------------------------------------------------------------------------- + // +public: + Logical + TestInstance() const; + static Logical + TestClass(); +}; + +//########################################################################## +//################### StreamableResourceFile ############################# +//########################################################################## + +class StreamableResourceFile: + public ResourceFile +{ +public: + // + //------------------------------------------------------------------------ + // Constructors & destructors + //------------------------------------------------------------------------ + // + enum { + FileNameLength = 1024 + }; + + + StreamableResourceFile(); + StreamableResourceFile(const char * name); + StreamableResourceFile(const char * name, Byte version_array[3], int match_level = 3); + ~StreamableResourceFile(); + +protected: + void + LoadResource(ResourceDescription* res); + + FileStream + diskFile; + + // + //------------------------------------------------------------------------ + // Public data + //------------------------------------------------------------------------ + // +public: + char + resourceFilename[FileNameLength]; + + int + Open(const char *file_name); + int + Save(); + int + SaveAs(const char* file_name); + + Logical + TestInstance() const; + + static Logical + TestClass(); +}; diff --git a/MUNGA/RESVER.h b/MUNGA/RESVER.h new file mode 100644 index 0000000..177f701 --- /dev/null +++ b/MUNGA/RESVER.h @@ -0,0 +1,3 @@ +#pragma once + +#define RESOURCE_FORMAT_VERSION 1 \ No newline at end of file diff --git a/MUNGA/RETICLE.cpp b/MUNGA/RETICLE.cpp new file mode 100644 index 0000000..43e6dda --- /dev/null +++ b/MUNGA/RETICLE.cpp @@ -0,0 +1,104 @@ +#include "munga.h" +#pragma hdrstop + +#include "reticle.h" + +//########################################################################## +//########################### Class Reticle ######################### +//########################################################################## + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Reticle::Reticle() +{ + // + // NOTE...most of these things should be initialization parameters to the constructor + // + reticleState = ReticleOn; + reticlePosition.x = 0.0f; + reticlePosition.y = 0.0f; + pickPointingOn = False; + rayIntersection.x = 0.0f; + rayIntersection.y = 0.0f; + rayIntersection.z = 0.0f; + targetEntity = 0; + targetDamageZone = -1; + reticleElementMask = AllEnabledGroup; // all reticle elements are on +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Reticle::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + Reticle::CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *model_file, + const ResourceDirectories *, + ModelResource *model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + if( + !model_file->GetEntry( + "gamedata", + "ReticleX", + &local_model->reticlePosition.x + ) + ) + { + local_model->reticlePosition.x = 0.0f; + } + if( + !model_file->GetEntry( + "gamedata", + "ReticleY", + &local_model->reticlePosition.y + ) + ) + { + local_model->reticlePosition.y = 0.0f; + } + // + //--------------------------- + // Write out the new resource + //--------------------------- + // + if(!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + return new_res->resourceID; + } + else + { + return 0; + } +} diff --git a/MUNGA/RETICLE.h b/MUNGA/RETICLE.h new file mode 100644 index 0000000..7cc49a4 --- /dev/null +++ b/MUNGA/RETICLE.h @@ -0,0 +1,64 @@ +#pragma once + +#include "point3d.h" +#include "vector2d.h" +#include "resource.h" +#include "notation.h" + +class Entity; +//########################################################################## +//##################### Reticle::ModelResource ####################### +//########################################################################## + +struct Reticle__ModelResource +{ + Vector2DOf reticlePosition; +}; +//########################################################################## +//########################### Class Reticle ######################### +//########################################################################## + +class Reticle SIGNATURED +{ +public: + enum ReticleState + { + ReticleOff, // Reticle is invisible + ReticleOn, // Reticle is visible (may be more than one "on" state added later) + }; + + enum ReticleElements // these are bits that turn parts of the reticle on and off + { + FrontFiringWeaponsOn = 0x00000001, // Display Front firing weapons + RearFiringWeaponsOn = 0x00000002, // Display rear firing weapons + LeftFiringWeaponsOn = 0x00000004, // Display left firing weapons + RightFiringWeaponsOn = 0x00000008, // Display right firing weapons + WeaponsControlGroup = 0x0000000F, // Mask defining the weapons group + TargetDesignatorOn = 0x00000010, // Display target designator box and direction arrows + PrimaryHudOn = 0x00000020, // if set, you get the full hud, if not just a simple x + AllEnabledGroup = 0xFFFFFFFF, // All bits on + }; + + Vector2DOf reticlePosition; // screen position -1.0 -> +1.0 + ReticleState reticleState; // current state of reticle, graphic to display + Logical pickPointingOn; // Pick point intersection testing on/off + Point3D rayIntersection; // Current pickpoint intersection in 3d world + Entity *targetEntity; // entity being targeted + int targetDamageZone; // damage zone on the entity + ReticleElements reticleElementMask; // controls what parts of the reticle are displayed + + Reticle(); + + Logical + TestInstance() const; + typedef Reticle__ModelResource ModelResource; + + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *map_file, + const ResourceDirectories *directories, + ModelResource *model = NULL + ); +}; \ No newline at end of file diff --git a/MUNGA/RNDORGN.cpp b/MUNGA/RNDORGN.cpp new file mode 100644 index 0000000..2bfe45e --- /dev/null +++ b/MUNGA/RNDORGN.cpp @@ -0,0 +1,187 @@ +#include "munga.h" +#pragma hdrstop + +#include "rndorgn.h" +#include "renderer.h" +#include "app.h" +#include "entity.h" + +// +//############################################################################# +// RendererOrigin +//############################################################################# +// +RendererOrigin::RendererOrigin( + Renderer *the_renderer, + Entity *entity, + InterestType interest_type, + InterestDepth depth_calibration +): + InterestOrigin( + entity->GetInterestZoneID(), + interest_type, + depth_calibration + ), + interestingEntitySocket(NULL) +{ + Check(the_renderer); + renderer = the_renderer; +} + +// +//############################################################################# +// ~RendererOrigin +//############################################################################# +// +RendererOrigin::~RendererOrigin() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + RendererOrigin::TestInstance() const +{ + InterestOrigin::TestInstance(); + Check_Signature(renderer); + Check(&interestingEntitySocket); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + RendererOrigin::AddInterestingEntity(Entity *interesting_entity) +{ + Check(this); + Check(interesting_entity); + + // + // Add to the socket + // + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&interestingEntitySocket); + Check(&iterator); + Verify(iterator.IsPlugMember(interesting_entity) == False); + } + #endif + interestingEntitySocket.Add(interesting_entity); + + // + // Notify the renderer + // + #if 0 + Renderer::NotifyOfNewInterestingEntityMessage + message(interesting_entity); + + Check(&message); + Check(application); + Check(renderer); + application->PostInterestEvent(renderer, &message); + #else + Renderer::NotifyOfNewInterestingEntityMessage + message(interesting_entity); + + Check(&message); + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->PostRendererEvent( + interesting_entity, + renderer, + &message + ); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + RendererOrigin::RemoveUninterestingEntity(Entity *uninteresting_entity) +{ + Check(this); + Check(uninteresting_entity); + + // + // Notify the renderer + // + #if 1 + Check(renderer); + renderer->NotifyOfBecomingUninterestingEntity(uninteresting_entity); + #else + Renderer::NotifyOfBecomingUninterestingEntityMessage + message(uninteresting_entity); + + Check(&message); + Check(application); + Check(renderer); + application->PostInterestEvent(renderer, &message); + #endif + + // + // Remove from socket + // + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&interestingEntitySocket); + Verify(iterator.IsPlugMember(uninteresting_entity) == True); + } + #endif + PlugIterator remover(uninteresting_entity); + remover.RemoveSocket(&interestingEntitySocket); +} + +// +//############################################################################# +//############################################################################# +// +void + RendererOrigin::RemoveUninterestingEntities() +{ + Check(this); + + // + // Notify the renderer of uninteresting entities + // + SChainIteratorOf iterator(&interestingEntitySocket); + Entity *uninteresting_entity; + + Check(&iterator); + #if 0 + while ((uninteresting_entity = iterator.GetCurrent()) != NULL) + { + Check(uninteresting_entity); + Check(renderer); + renderer->NotifyOfBecomingUninterestingEntity(uninteresting_entity); + iterator.Remove(); + } + #else + while ((uninteresting_entity = iterator.GetCurrent()) != NULL) + { + Check(uninteresting_entity); + RemoveUninterestingEntity(uninteresting_entity); + } + #endif +} + +//~~~~~~~~~~~~~~~~~ RendererOrigin__InterestingEntityIterator ~~~~~~~~~~~~~~~~~ + +RendererOrigin__InterestingEntityIterator:: + RendererOrigin__InterestingEntityIterator( + RendererOrigin *renderer_origin + ): + SChainIteratorOf(&renderer_origin->interestingEntitySocket) +{ +} + +RendererOrigin__InterestingEntityIterator:: + ~RendererOrigin__InterestingEntityIterator() +{ +} diff --git a/MUNGA/RNDORGN.h b/MUNGA/RNDORGN.h new file mode 100644 index 0000000..59d117d --- /dev/null +++ b/MUNGA/RNDORGN.h @@ -0,0 +1,96 @@ +#pragma once + +#include "intorgn.h" +#include "schain.h" + +//########################################################################## +//####################### RendererOrigin ############################# +//########################################################################## + +class Renderer; +class Entity; + +class RendererOrigin : public InterestOrigin +{ + friend class RendererOrigin__InterestingEntityIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public types +// +public: + typedef RendererOrigin__InterestingEntityIterator InterestingEntityIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor, Destructor, and Testing +// +public: + RendererOrigin(Renderer *renderer, Entity *entity, InterestType interest_type, InterestDepth depth_calibration); + ~RendererOrigin(); + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Interest Manager support +// +private: + void AddInterestingEntity(Entity *interesting_entity); + void RemoveUninterestingEntity(Entity *uninteresting_entity); + void RemoveUninterestingEntities(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + Renderer* renderer; + SChainOf interestingEntitySocket; +}; + +//~~~~~~~~~~~~~~~~~ RendererOrigin__InterestingEntityIterator ~~~~~~~~~~~~~~ + +class RendererOrigin__InterestingEntityIterator : public SChainIteratorOf +{ +public: + RendererOrigin__InterestingEntityIterator(RendererOrigin *renderer_origin); + ~RendererOrigin__InterestingEntityIterator(); +}; + +#if 0 + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ RendererOrigin ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + // + //-------------------------------------------------------------------- + // RendererOrigin + // + // Represent a renderers origin of interest. + //-------------------------------------------------------------------- + // + + class RendererOrigin : public InterestOrigin + { + public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, and Testing + //-------------------------------------------------------------------- + // + RendererOrigin(const EntityID &entity_ID, InterestType interest_type, InterestDepth depth_calibration, Renderer *renderer); + ~RendererOrigin(); + Logical TestInstance() const; + + // + //-------------------------------------------------------------------- + // Interest Manager support + //-------------------------------------------------------------------- + // + void AddInterestingEntity(Entity *interesting_entity); + void RemoveUninterestingEntity(Entity *uninteresting_entity); + void RemoveUninterestingEntities(); + + protected: + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // + SlotOf rendererSocket; + }; +#endif diff --git a/MUNGA/ROTATION.cpp b/MUNGA/ROTATION.cpp new file mode 100644 index 0000000..c766590 --- /dev/null +++ b/MUNGA/ROTATION.cpp @@ -0,0 +1,1338 @@ +#include "munga.h" +#pragma hdrstop + +#include "rotation.h" +#include "linmtrx.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Close_Enough( + const Hinge &a1, + const Hinge &a2, + Scalar e + ) +{ + return a1.axisNumber == a2.axisNumber + && Close_Enough(a1.rotationAmount, a2.rotationAmount, e); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Hinge& + Hinge::Lerp( + const Hinge& v1, + const Hinge& v2, + Scalar t + ) +{ + Check_Pointer(this); + Check(&v1); + Check(&v2); + Verify(v1.axisNumber == v2.axisNumber); + + axisNumber = v1.axisNumber; + rotationAmount.Lerp(v1.rotationAmount, v2.rotationAmount, t); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +std::ostream& operator<<(std::ostream& stream, const Hinge& angles) +{ + Check(&angles); + stream << angles.rotationAmount << " about "; + switch (angles.axisNumber) + { + case X_Axis: + stream << "X Axis"; + break; + case Y_Axis: + stream << "Y Axis"; + break; + case Z_Axis: + stream << "Z Axis"; + break; + } + return stream; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Hinge::TestInstance() const +{ + return (unsigned)axisNumber <= Z_Axis; +} + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Hinge *) + { + return False; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ EulerAngles ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const EulerAngles + EulerAngles::Identity(0.0f,0.0f,0.0f); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile EulerAngles *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::operator=(const EulerAngles &angles) +{ + Check_Pointer(this); + Check(&angles); + + pitch = angles.pitch; + yaw = angles.yaw; + roll = angles.roll; + return *this; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::operator=(const YawPitchRoll &angles) +{ + Check_Pointer(this); + Check(&angles); + + LinearMatrix m; + m = angles; + *this = m; + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::operator=(const Hinge &hinge) +{ + Check_Pointer(this); + Check(&hinge); + + pitch = 0.0f; + yaw = 0.0f; + roll = 0.0f; + + switch (hinge.axisNumber) + { + case X_Axis: + pitch = hinge.rotationAmount; + break; + case Y_Axis: + yaw = hinge.rotationAmount; + break; + case Z_Axis: + roll = hinge.rotationAmount; + break; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::operator=(const Quaternion &quaternion) +{ + Check_Pointer(this); + Check(&quaternion); + + LinearMatrix m; + m = quaternion; + return *this = m; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::operator=(const LinearMatrix &matrix) +{ + Check_Pointer(this); + Check(&matrix); + + SinCosPair + p,y,r; + + y.sine = -matrix(0,2); + if (Close_Enough(y.sine,1.0f,0.0001f)) { + y.cosine = 0.0f; + r.sine = 0.0f; + r.cosine = 1.0f; + p.sine = matrix(1,0); + p.cosine = matrix(2,0); + } + else if (Close_Enough(y.sine,-1.0f,0.0001f)) { + y.cosine = 0.0f; + r.sine = 0.0f; + r.cosine = 1.0f; + p.sine = -matrix(1,0); + p.cosine = -matrix(2,0); + } + else { + y.cosine = Sqrt(1.0f - y.sine*y.sine); + p.sine = matrix(1,2) / y.cosine; + p.cosine = matrix(2,2) / y.cosine; + r.sine = matrix(0,1) / y.cosine; + r.cosine = matrix(0,0) / y.cosine; + + if ( + !Close_Enough(p.sine*y.sine*r.cosine - p.cosine*r.sine,matrix(1,0)) + ) { + y.sine = -y.sine; + p.sine = -p.sine; + p.cosine = -p.cosine; + r.sine = -r.sine; + r.cosine = -r.cosine; + } + } + + pitch = p; + yaw = y; + roll = r; + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Small_Enough( + const EulerAngles& angles, + Scalar e + ) +{ + Check(&angles); + + return + Small_Enough(angles.pitch,e) + && Small_Enough(angles.yaw,e) + && Small_Enough(angles.roll,e); +} + +// +//############################################################################# +//############################################################################# +// +Logical + Close_Enough( + const EulerAngles& a1, + const EulerAngles& a2, + Scalar e + ) +{ + Check(&a1); + Check(&a2); + + return + Close_Enough(a1.pitch,a2.pitch,e) + && Close_Enough(a1.yaw,a2.yaw,e) + && Close_Enough(a1.roll,a2.roll,e); +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::Multiply( + const EulerAngles &q1, + const EulerAngles &q2 + ) +{ + Check_Pointer(this); + Check(&q1); + Check(&q2); + + pitch = q1.pitch + q2.pitch; + yaw = q1.yaw + q2.yaw; + roll = q1.roll + q2.roll; + + #if DEBUG_LEVEL>0 + if (!TestInstance()) + { + Dump(q1); + Dump(q2); + Dump(*this); + Fail("EulerAngle multiplication is unstable!\n"); + } + #endif + return *this; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::Multiply( + const EulerAngles &q, + Scalar t + ) +{ + Check_Pointer(this); + Check(&q); + + pitch = q.pitch * t; + yaw = q.yaw * t; + roll = q.roll * t; + return *this; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::MultiplyScaled( + const EulerAngles &q1, + const EulerAngles &q2, + Scalar t + ) +{ + Check_Pointer(this); + Check(&q1); + Check(&q2); + Verify(t>=0.0f); + + pitch = q1.pitch + q2.pitch * t; + yaw = q1.yaw + q2.yaw * t; + roll = q1.roll + q2.roll * t; + return *this; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::Lerp( + const EulerAngles &a1, + const EulerAngles &a2, + Scalar t + ) +{ + Check_Pointer(this); + Check(&a1); + Check(&a2); + + pitch = ::Lerp(a1.pitch,a2.pitch,t); + yaw = ::Lerp(a1.yaw,a2.yaw,t); + roll = ::Lerp(a1.roll,a2.roll,t); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +EulerAngles& + EulerAngles::Normalize() +{ + Check_Pointer(this); + + pitch.Normalize(); + yaw.Normalize(); + roll.Normalize(); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator<<(std::ostream& stream, const EulerAngles& angles) +{ + return stream << '<' << angles.pitch << ',' << angles.yaw << ',' << angles.roll << '>'; +} + +// +//############################################################################# +//############################################################################# +// +Logical + EulerAngles::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ YawPitchRoll ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const YawPitchRoll + YawPitchRoll::Identity(0.0f,0.0f,0.0f); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile YawPitchRoll *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +YawPitchRoll& + YawPitchRoll::operator=(const YawPitchRoll &angles) +{ + Check_Pointer(this); + Check(&angles); + + pitch = angles.pitch; + yaw = angles.yaw; + roll = angles.roll; + return *this; +} + +// +//############################################################################# +//############################################################################# +// +YawPitchRoll& + YawPitchRoll::operator=(const EulerAngles &angles) +{ + Check_Pointer(this); + Check(&angles); + + LinearMatrix m; + m = angles; + *this = m; + + return *this; +} + +// +//############################################################################# +//############################################################################# +// +YawPitchRoll& + YawPitchRoll::operator=(const Hinge &hinge) +{ + Check_Pointer(this); + Check(&hinge); + + pitch = 0.0f; + yaw = 0.0f; + roll = 0.0f; + + switch (hinge.axisNumber) + { + case X_Axis: + pitch = hinge.rotationAmount; + break; + case Y_Axis: + yaw = hinge.rotationAmount; + break; + case Z_Axis: + roll = hinge.rotationAmount; + break; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +YawPitchRoll& + YawPitchRoll::operator=(const Quaternion &quaternion) +{ + Check_Pointer(this); + Check(&quaternion); + + LinearMatrix m; + m = quaternion; + return *this = m; +} + +// +//############################################################################# +//############################################################################# +// +YawPitchRoll& + YawPitchRoll::operator=(const LinearMatrix &matrix) +{ + Check_Pointer(this); + Check(&matrix); + + SinCosPair + x,y,z; + + x.sine = -matrix(2,1); + if (Close_Enough(x.sine,1.0f,0.0001f)) { + x.cosine = 0.0f; + z.sine = 0.0f; + z.cosine = 1.0f; + y.sine = matrix(1,0); + y.cosine = matrix(0,0); + } + else if (Close_Enough(x.sine,-1.0f,0.0001f)) { + x.cosine = 0.0f; + z.sine = 0.0f; + z.cosine = 1.0f; + y.sine = matrix(0,2); + y.cosine = matrix(0,0); + } + else { + x.cosine = Sqrt(1.0f - x.sine*x.sine); + y.sine = matrix(2,0) / x.cosine; + y.cosine = matrix(2,2) / x.cosine; + z.sine = matrix(0,1) / x.cosine; + z.cosine = matrix(1,1) / x.cosine; + + if ( + !Close_Enough(y.cosine*z.cosine + x.sine*y.sine*z.sine,matrix(0,0)) + ) + { + x.sine = -x.sine; + y.sine = -y.sine; + y.cosine = -y.cosine; + z.sine = -z.sine; + z.cosine = -z.cosine; + } + } + + pitch = x; + yaw = y; + roll = z; + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Logical + Small_Enough( + const YawPitchRoll& angles, + Scalar e + ) +{ + Check(&angles); + + return + Small_Enough(angles.pitch,e) + && Small_Enough(angles.yaw,e) + && Small_Enough(angles.roll,e); +} + +// +//############################################################################# +//############################################################################# +// +Logical + Close_Enough( + const YawPitchRoll& a1, + const YawPitchRoll& a2, + Scalar e + ) +{ + Check(&a1); + Check(&a2); + + return + Close_Enough(a1.pitch,a2.pitch,e) + && Close_Enough(a1.yaw,a2.yaw,e) + && Close_Enough(a1.roll,a2.roll,e); +} + +// +//############################################################################# +//############################################################################# +// +YawPitchRoll& + YawPitchRoll::Normalize() +{ + Check_Pointer(this); + + pitch.Normalize(); + yaw.Normalize(); + roll.Normalize(); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator<<(std::ostream& stream, const YawPitchRoll& angles) +{ + return stream << '<' << angles.yaw << ',' << angles.pitch << ',' << angles.roll << '>'; +} + +// +//############################################################################# +//############################################################################# +// +Logical + YawPitchRoll::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Quaternion ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const Quaternion + Quaternion::Identity(0.0f, 0.0f, 0.0f, 1.0f); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Quaternion *) + { + return False; + } +#endif + +// +//############################################################################# +//############################################################################# +// +Quaternion::Quaternion( + Scalar x, + Scalar y, + Scalar z, + Scalar w +) +{ + this->x = x; + this->y = y; + this->z = z; + this->w = w; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::operator=(const Quaternion &q) +{ + Check_Pointer(this); + Check(&q); + + x = q.x; + y = q.y; + z = q.z; + w = q.w; + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::operator=(const Hinge &hinge) +{ + Check_Pointer(this); + Check(&hinge); + + Radian temp; + temp = hinge.rotationAmount * 0.5f; + SinCosPair half_angle; + half_angle = temp; + + w = half_angle.cosine; + x = 0.0f; + y = 0.0f; + z = 0.0f; + + switch (hinge.axisNumber) + { + case X_Axis: + x = half_angle.sine; + break; + case Y_Axis: + y = half_angle.sine; + break; + case Z_Axis: + z = half_angle.sine; + break; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::operator=(const EulerAngles &angles) +{ + Check_Pointer(this); + Check(&angles); + + LinearMatrix m; + m = angles; + Check(&m); + *this = m; + #if DEBUG_LEVEL>0 + if (!TestInstance()) + { + Dump(angles); + Dump(*this); + Fail("Quaternion construction from angles is unstable!\n"); + } + #endif + return *this; +} +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::operator=(const YawPitchRoll &angles) +{ + LinearMatrix lin_matrix; + lin_matrix = angles; + *this = lin_matrix; + return *this; +} +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::operator=(const LinearMatrix &matrix) +{ + Check_Pointer(this); + Check(&matrix); + + // + //------------------------------------------------------------------------ + // Compute the w component. If it is close enough to zero, then we have a + // 180 degree pivot, so figure out the correct axis to rotate around + //------------------------------------------------------------------------ + // + w = (1.0f + matrix(0,0) + matrix(1,1) + matrix(2,2)) * 0.25f; + if (Small_Enough(w,1e-2)) + { + Verify(w >= -SMALL); + if (w<0.0f) + { + w = 0.0f; + } + + // + //---------------------------------------------------------------- + // Figure out the length of each component of the axis of rotation + //---------------------------------------------------------------- + // + Scalar temp = (1.0f + matrix(0,0)) * 0.5f - w; + Min_Clamp(temp, 0.0f); + x = Sqrt(temp); + temp = (1.0f + matrix(1,1)) * 0.5f - w; + Min_Clamp(temp, 0.0f); + y = Sqrt(temp); + temp = (1.0f + matrix(2,2)) * 0.5f - w; + Min_Clamp(temp, 0.0f); + z = Sqrt(temp); + w = Sqrt(w); + + // + //------------------------------------------- + // Now figure out the signs of the components + //------------------------------------------- + // + if (matrix(0,1) < matrix(1,0)) + { + z = -z; + } + if (matrix(2,0) < matrix(0,2)) + { + y = -y; + } + if (matrix(1,2) < matrix(2,1)) + { + x = -x; + } + } + + // + //---------------------------------------------------------- + // Otherwise, determine x, y, and z directly from the matrix + //---------------------------------------------------------- + // + else + { + Verify(w>0.0f); + w = Sqrt(w); + x = (matrix(1,2) - matrix(2,1)) * 0.25f / w; + y = (matrix(2,0) - matrix(0,2)) * 0.25f / w; + z = (matrix(0,1) - matrix(1,0)) * 0.25f / w; + } + + #if DEBUG_LEVEL>0 + if (!TestInstance()) + { + Dump(matrix); + Dump(*this); + Fail("Quaternion construction from matrix is unstable!\n"); + } + #endif + return *this; +} + + +// +//############################################################################# +//############################################################################# +// +Scalar + Quaternion::GetAngle() +{ + Check(this); + + Scalar sine_of_half = Sqrt(x*x + y*y + z*z); + if (Small_Enough(sine_of_half)) + { + return 0.0f; + } + + SinCosPair half_angle(sine_of_half, w); + Radian angle; + angle = half_angle; + + return angle * 2.0f; +} + +// +//############################################################################# +//############################################################################# +// +void + Quaternion::GetAxis(UnitVector *axis) +{ + Check(this); + Check_Pointer(axis); + + Scalar len = Sqrt(x*x + y*y + z*z); + if (Small_Enough(len)) + { + axis->x = 1.0f; + axis->y = 0.0f; + axis->z = 0.0f; + } + else + { + axis->x = x / len; + axis->y = y / len; + axis->z = z / len; + } + + Check(axis); + return; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Multiply(const Quaternion &q1, const Quaternion &q2) +{ + Check_Pointer(this); + Check(&q1); + Check(&q2); + Verify(this != &q1 && this != &q2); + + x = q1.w*q2.x + q2.w*q1.x + q1.y*q2.z - q1.z*q2.y; + y = q1.w*q2.y + q2.w*q1.y + q1.z*q2.x - q1.x*q2.z; + z = q1.w*q2.z + q2.w*q1.z + q1.x*q2.y - q1.y*q2.x; + w = q1.w*q2.w - q1.x*q2.x - q1.y*q2.y - q1.z*q2.z; + #if DEBUG_LEVEL>0 + if (!TestInstance()) + { + Dump(q1); + Dump(q2); + Dump(*this); + Fail("Quaternion multiplication is unstable!\n"); + } + #endif + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Multiply( + const Quaternion &q, + Scalar t + ) +{ + Check_Pointer(this); + Check(&q); + + // + //--------------------------------------------------------- + // Figure out the half the angle of rotation and scale that + //--------------------------------------------------------- + // + Scalar sine_of_half = Sqrt(q.x*q.x + q.y*q.y + q.z*q.z); + if (Small_Enough(sine_of_half)) + { + *this = Identity; + return *this; + } + + SinCosPair half_angle(sine_of_half, q.w); + Radian angle; + angle = half_angle; + angle *= t; + half_angle = angle; + + // + //----------------------------------------------------------------- + // Build the scaled quaternion out of the components of the old one + //----------------------------------------------------------------- + // + w = half_angle.cosine; + sine_of_half = half_angle.sine / sine_of_half; + x = q.x * sine_of_half; + y = q.y * sine_of_half; + z = q.z * sine_of_half; + + #if DEBUG_LEVEL>0 + if (!TestInstance()) + { + Dump(q); + Dump(t); + Dump(*this); + Fail("Quaternion multiplication is unstable!\n"); + } + #endif + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::MultiplyScaled( + const Quaternion &q1, + const Quaternion &q2, + Scalar t + ) +{ + Check_Pointer(this); + Verify(this != &q1); + Check(&q1); + Check(&q2); + Verify(t>=0.0f); + + Quaternion scaled_quat; + scaled_quat.Multiply(q2, t); + Multiply(q1, scaled_quat); + + #if DEBUG_LEVEL>0 + if (!TestInstance()) + { + Dump(q1); + Dump(q2); + Dump(t); + Dump(*this); + Fail("Quaternion multiplication is unstable!\n"); + } + #endif + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Add( + const Quaternion &source, + const Vector3D &delta + ) +{ + Check_Pointer(this); + Check(&source); + Check(&delta); + Verify(&source != this); + + // + //--------------------------------------------------------------- + // See if there is any rotation to apply to the source quaternion + //--------------------------------------------------------------- + // + Scalar rotation = delta.Length(); + if (Small_Enough(rotation)) + { + return *this = source; + } + + // + //--------------------------------------------------------------------- + // Build a quaternion from the delta vector, treating the length as the + // amount of rotation and the direction of the vector as the axis of + // rotation + //--------------------------------------------------------------------- + // + SinCosPair half_angle; + half_angle = 0.5f * Radian::Normalize(rotation); + rotation = half_angle.sine / rotation; + Quaternion q( + delta.x * rotation, + delta.y * rotation, + delta.z * rotation, + half_angle.cosine + ); + Check(&q); + return Multiply(source, q); +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::AddScaled( + const Quaternion &source, + const Vector3D &delta, + Scalar t + ) +{ + Check_Pointer(this); + Check(&source); + Check(&delta); + Verify(&source != this); + + // + //--------------------------------------------------------------- + // See if there is any rotation to apply to the source quaternion + //--------------------------------------------------------------- + // + Scalar rotation = delta.Length(); + if (Small_Enough(rotation)) + { + return *this = source; + } + + // + //--------------------------------------------------------------------- + // Build a quaternion from the delta vector, treating the length as the + // amount of rotation and the direction of the vector as the axis of + // rotation + //--------------------------------------------------------------------- + // + SinCosPair half_angle; + rotation *= t; + half_angle = 0.5f*rotation; + rotation = half_angle.sine / rotation; + Quaternion q( + delta.x * rotation, + delta.y * rotation, + delta.z * rotation, + half_angle.cosine + ); + Check(&q); + return Multiply(source, q); +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Normalize() +{ + Scalar t = x*x + y*y + z*z; + if (t <= 1.0f) + { + t = Sqrt(1.0f - t); + if (w<0.0f) + { + x = -x; + y = -y; + z = -z; + } + w = t; + } + else + { + t = Sqrt(t); + x /= t; + y /= t; + z /= t; + w = 0.0f; + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Subtract( + const Quaternion &end, + const Quaternion &start + ) +{ + Check_Pointer(this); + Check(&start); + Check(&end); + + Quaternion inverse(start); + inverse.w = -inverse.w; + return Multiply(inverse, end); +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Subtract( + const UnitVector &end, + const UnitVector &start + ) +{ + Check_Pointer(this); + Check(&start); + Check(&end); + + Vector3D + axis; + SinCosPair + delta; + delta.cosine = start*end; + + // + //---------------------------------------------------------------------- + // See if the vectors point in the same direction. If so, return a null + // rotation + //---------------------------------------------------------------------- + // + if (Close_Enough(delta.cosine, 1.0f)) + { + x = 0.0f; + y = 0.0f; + z = 0.0f; + w = 1.0f; + } + + // + //------------------------------------------------------------------------- + // See if the vectors directly oppose each other. If so, pick the smallest + // axis coordinate and generate a vector along it. Project this onto the + // base vector and subtract it out, leaving a perpendicular projection. + // Extend that out to unit length, then set the angle to PI + //------------------------------------------------------------------------- + // + else if (Close_Enough(delta.cosine, -1.0f)) + { + // + //--------------------------- + // Pick out the smallest axis + //--------------------------- + // + int + smallest=0; + Scalar + value=2.0f; + for (int i=X_Axis; i<=Z_Axis; ++i) + { + if (Abs(start[i]) < value) + { + smallest = i; + value = Abs(start[i]); + } + } + + // + //---------------------------------------- + // Set up a vector along the selected axis + //---------------------------------------- + // + axis.x = 0.0f; + axis.y = 0.0f; + axis.z = 0.0f; + axis[smallest] = 1.0f; + + // + //------------------------------------------------------------------- + // If the value on that axis wasn't zero, subtract out the projection + //------------------------------------------------------------------- + // + if (!Small_Enough(value)) + { + Vector3D t; + t.Multiply(start, start*axis); + axis.Subtract(axis, t); + axis.Normalize(axis); + } + + // + //---------------------- + // Convert to quaternion + //---------------------- + // + x = axis.x; + y = axis.y; + z = axis.z; + w = 0.0f; + } + + // + //-------------------------------------------------- + // Otherwise, generate the cross product and unitize + //-------------------------------------------------- + // + else + { + axis.Cross(start, end); + delta.sine = axis.Length(); + axis /= delta.sine; + + // + //--------------------------------------------------------------- + // Now compute sine and cosine of half the angle and generate the + // quaternion + //--------------------------------------------------------------- + // + delta.sine = Sqrt((1.0f - delta.cosine)*0.5f); + x = axis.x * delta.sine; + y = axis.y * delta.sine; + z = axis.z * delta.sine; + w = Sqrt((1.0f + delta.cosine)*0.5f); + } + return *this; +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Subtract( + const Vector3D &end, + const Vector3D &start + ) +{ + Check_Pointer(this); + Check(&start); + Check(&end); + + UnitVector + s,e; + + s = start; + e = end; + return Subtract(e, s); +} + +// +//############################################################################# +//############################################################################# +// +Quaternion& + Quaternion::Lerp( + const Quaternion &q1, + const Quaternion &q2, + Scalar t + ) +{ + Check_Pointer(this); + Check(&q1); + Check(&q2); + + if (q1.x*q2.x + q1.y*q2.y + q1.z*q2.z + q1.w*q2.w >= 0.0f) + { + x = ::Lerp(q1.x, q2.x, t); + y = ::Lerp(q1.y, q2.y, t); + z = ::Lerp(q1.z, q2.z, t); + w = ::Lerp(q1.w, q2.w, t); + } + else + { + x = ::Lerp(q1.x, -q2.x, t); + y = ::Lerp(q1.y, -q2.y, t); + z = ::Lerp(q1.z, -q2.z, t); + w = ::Lerp(q1.w, -q2.w, t); + } + + Scalar len = x*x + y*y + z*z + w*w; + if (Small_Enough(len)) + { + x = 0.0f; + y = 0.0f; + z = 0.0f; + w = 1.0f; + } + else + { + len = 1.0f / Sqrt(len); + x *= len; + y *= len; + z *= len; + w *= len; + } + Check(this); + return *this; +} + +// +//############################################################################# +//############################################################################# +// +std::ostream& operator<<(std::ostream& stream, const Quaternion& q) +{ + return stream << '<' << q.x << ',' << q.y << ',' << q.z << ',' << q.w + << '>'; +} + +// +//############################################################################# +//############################################################################# +// +Logical Quaternion::TestInstance() const +{ +#if 0 + if (!Close_Enough(x*x + y*y + z*z + w*w,1.0f,2e-6)) + { + Scalar t = 1.0f - x*x - y*y - z*z - w*w; + + if (Small_Enough(t, 2e-6)) + { + Dump(*this); + Dump(1.0f - x*x - y*y - z*z - w*w); + return False; + } + } +#endif + return True; +} + +#if defined(TEST_CLASS) +# include "rotation.tcp" +#endif diff --git a/MUNGA/ROTATION.h b/MUNGA/ROTATION.h new file mode 100644 index 0000000..cb898d8 --- /dev/null +++ b/MUNGA/ROTATION.h @@ -0,0 +1,307 @@ +#pragma once + +#include "angle.h" + +class Quaternion; +class Origin; +class YawPitchRoll; +class UnitVector; +class LinearMatrix; +class Vector3D; + +//########################################################################## +//############################ Hinge ################################# +//########################################################################## + +class Hinge +{ +public: + int axisNumber; + Radian rotationAmount; + + // + // Constructors + // + Hinge() {} + Hinge(int axis, const Radian &angle) : axisNumber(axis), rotationAmount(angle) {} + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Hinge *); + #endif + // + // Assignment operators + // + Hinge& operator=(const Hinge &hinge) + { + Check_Pointer(this); + Check(&hinge); + axisNumber = hinge.axisNumber; + rotationAmount = hinge.rotationAmount; + return *this; + } + + // + // "Close-enough" comparators + // + friend Logical Small_Enough(const Hinge &a, Scalar e = SMALL) + { + Check(&a); + return Small_Enough(a, e); + } + Logical operator!() const { return Small_Enough(*this,SMALL); } + + friend Logical Close_Enough(const Hinge &a1, const Hinge &a2, Scalar e = SMALL); + Logical operator==(const Hinge& a) const { return Close_Enough(*this, a, SMALL); } + Logical operator!=(const Hinge& a) const { return !Close_Enough(*this, a, SMALL); } + + // + // Template support + // + Hinge& Lerp(const Hinge& v1, const Hinge& v2, Scalar t); + + // + // Support functions + // + friend std::ostream& operator<<(std::ostream& stream, const Hinge& angles); + Logical TestInstance() const; +}; + +//########################################################################## +//######################### EulerAngles ############################# +//########################################################################## + +class EulerAngles +{ +public: + Radian pitch, yaw, roll; + + static const EulerAngles Identity; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile EulerAngles *); + #endif + + // + // Constructors + // + EulerAngles() {} + EulerAngles(const Radian &pitch, const Radian &yaw, const Radian &roll) + { + this->pitch = pitch; + this->yaw = yaw; + this->roll = roll; + } + + // + // Assignment operators + // + EulerAngles& operator=(const EulerAngles &angles); + EulerAngles& operator=(const YawPitchRoll &angles); + EulerAngles& operator=(const Hinge &hinge); + EulerAngles& operator=(const Quaternion &quaternion); + EulerAngles& operator=(const LinearMatrix &matrix); + EulerAngles& operator=(const Origin &p); + + // + // "Close-enough" comparators + // + friend Logical Small_Enough(const EulerAngles &a, Scalar e = SMALL); + Logical operator!() const { return Small_Enough(*this); } + + friend Logical Close_Enough(const EulerAngles &a1, const EulerAngles &a2, Scalar e = SMALL); + Logical operator==(const EulerAngles& a) const { return Close_Enough(*this, a, SMALL); } + Logical operator!=(const EulerAngles& a) const { return !Close_Enough(*this, a, SMALL); } + + // + // Axis index operators + // + const Radian& operator[](size_t index) const + { + Check_Pointer(this); + Warn(index>Z_Axis); + return (&pitch)[index]; + } + Radian& operator[](size_t index) + { + Check_Pointer(this); + Warn(index>Z_Axis); + return (&pitch)[index]; + } + + // + // Multiplication operators + // + EulerAngles& Multiply(const EulerAngles &q1, const EulerAngles &q2); + EulerAngles& Multiply(const EulerAngles &q, Scalar scale); + EulerAngles& MultiplyScaled(const EulerAngles &q1, const EulerAngles &q2, Scalar t); + + // + // Template support + // + EulerAngles& Lerp(const EulerAngles& v1, const EulerAngles& v2, Scalar t); + + // + // Support functions + // + EulerAngles& Normalize(); + friend std::ostream& operator<<(std::ostream& stream, const EulerAngles& angles); + + // + // Test functions + // + Logical TestInstance() const; + static Logical TestClass(); +}; + +//########################################################################## +//######################### YawPitchRoll ############################ +//########################################################################## + +class YawPitchRoll +{ +public: + Radian yaw, pitch, roll; + + static const YawPitchRoll Identity; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile YawPitchRoll *); + #endif + + // + // Constructors + // + YawPitchRoll() {} + YawPitchRoll(const Radian &yaw, const Radian &pitch, const Radian &roll) + { + this->pitch = pitch; + this->yaw = yaw; + this->roll = roll; + } + + // + // Assignment operators + // + YawPitchRoll& operator=(const Hinge &hinge); + YawPitchRoll& operator=(const YawPitchRoll &angles); + YawPitchRoll& operator=(const EulerAngles &angles); + YawPitchRoll& operator=(const Quaternion &quaternion); + YawPitchRoll& operator=(const LinearMatrix &matrix); + YawPitchRoll& operator=(const Origin &p); + + // + // "Close-enough" comparators + // + friend Logical Small_Enough(const YawPitchRoll &a, Scalar e = SMALL); + Logical operator!() const { return Small_Enough(*this); } + + friend Logical Close_Enough(const YawPitchRoll &a1, const YawPitchRoll &a2, Scalar e = SMALL); + Logical operator==(const YawPitchRoll& a) const { return Close_Enough(*this, a); } + Logical operator!=(const YawPitchRoll& a) const { return !Close_Enough(*this, a); } + + // + // Support functions + // + YawPitchRoll& Normalize(); + friend std::ostream& operator<<(std::ostream& stream, const YawPitchRoll& angles); + + // + // Test functions + // + Logical TestInstance() const; +}; + +//########################################################################## +//######################### Quaternion ############################### +//########################################################################## + +class Quaternion +{ +public: + static const Quaternion Identity; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Quaternion *); + #endif + + Scalar x, y, z, w; + + // + // Constructors + // + Quaternion() {} + Quaternion(Scalar x, Scalar y, Scalar z, Scalar w); + + // + // Assignment operators + // + Quaternion& operator=(const Quaternion &q); + Quaternion& operator=(const Hinge &hinge); + Quaternion& operator=(const EulerAngles &angles); + Quaternion& operator=(const YawPitchRoll &angles); + Quaternion& operator=(const LinearMatrix &matrix); + Quaternion& operator=(const Origin &p); + + // + // "Close-enough" comparators + // + friend Logical Small_Enough(const Quaternion &q, Scalar e = SMALL) + { + Check(&q); + return Close_Enough(q.w, 1.0f, e); + } + Logical operator!() const { return Small_Enough(*this, SMALL); } + + // + // Axis index operators + // + const Scalar& operator[](size_t index) const + { + Check_Pointer(this); + Warn(index>W_Axis); + return (&x)[index]; + } + Scalar& operator[](size_t index) + { + Check_Pointer(this); + Warn(index>W_Axis); + return (&x)[index]; + } + + Scalar GetAngle(); + void GetAxis(UnitVector *axis); + + // + // Multiplication operators + // + Quaternion& Multiply(const Quaternion &q1, const Quaternion &q2); + Quaternion& Multiply(const Quaternion &q, Scalar scale); + Quaternion& MultiplyScaled(const Quaternion &q1, const Quaternion &q2, Scalar t); + Quaternion& Add(const Quaternion &source, const Vector3D &delta); + Quaternion& AddScaled(const Quaternion &source, const Vector3D &delta, Scalar t); + + // + // Transform functions + // + Quaternion& Multiply(const Quaternion &q, const LinearMatrix &m); + Quaternion& operator*=(const LinearMatrix &m); + + // + // Template support + // + Quaternion& Lerp(const Quaternion& v1, const Quaternion& v2, Scalar t); + + // + // Miscellaneous functions + // + Quaternion& Normalize(); + Quaternion& Subtract(const Quaternion &end, const Quaternion &start); + Quaternion& Subtract(const UnitVector &end, const UnitVector &start); + Quaternion& Subtract(const Vector3D &end, const Vector3D &start); + + // + // Support functions + // + friend std::ostream& operator<<(std::ostream& stream, const Quaternion& quaternion); + Logical TestInstance() const; + static Logical TestClass(); +}; diff --git a/MUNGA/SCALAR.cpp b/MUNGA/SCALAR.cpp new file mode 100644 index 0000000..debfc12 --- /dev/null +++ b/MUNGA/SCALAR.cpp @@ -0,0 +1,167 @@ +#include "munga.h" +#pragma hdrstop + +#include "scalar.h" + +int Round(Scalar value) +{ + int whole_part = floor(value); + Scalar fractional_part = value - whole_part; + if (fractional_part >= 0.5) + return whole_part + 1; + else + return whole_part; +} + + + +void Find_Roots(Scalar a, Scalar b, Scalar c, Scalar *center, Scalar *range) +{// a*x*x + b*x + c = 0 + + // See if the quadratic is solvable + *range = b*b - 4.0f*a*c; + if (*range < 0.0f || Small_Enough(a)) + { + *range = -1.0f; + } + else + { + // Solve the single root case + a *= 2.0f; + *center = -b / a; + if (*range < SMALL) + *range = 0.0f; + + // Find the two-root extents + else + { + *range = Sqrt(*range); + *range /= a; + } + } +} + +static void Verify_Arguments(const char *str, void *value) +{ + if (str == NULL) + Fail("Convert_From_Ascii - str == NULL"); + if (value == NULL) + Fail("Convert_From_Ascii - value == NULL"); + if (isalpha(*str)) + { + std::cout << "Convert_From_Ascii - str == " << str << "\n"; + Fail("Convert_From_Ascii - isalpha(*str)"); + } +} + +void Convert_From_Ascii(const char *str, char *value) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = (char)atoi(str); +} + +void Convert_From_Ascii(const char *str, unsigned char *value) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = (unsigned char)atoi(str); +} + +void Convert_From_Ascii(const char *str, int *value) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atoi(str); +} + +void Convert_From_Ascii(const char *str, unsigned int *value) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atoi(str); +} + +void Convert_From_Ascii(const char *str, long *value) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atol(str); +} + +void Convert_From_Ascii(const char *str, unsigned long *value) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atol(str); +} + +void Convert_From_Ascii(const char *str, Scalar *value) +{ + #if 0 + Check_Pointer(str); + Check_Pointer(value); + if (isalpha(*str)) + { + Dump(str); + } + Verify(!isalpha(*str)); + #else + Verify_Arguments(str, value); + #endif + *value = atof(str); +} \ No newline at end of file diff --git a/MUNGA/SCALAR.h b/MUNGA/SCALAR.h new file mode 100644 index 0000000..fe055e2 --- /dev/null +++ b/MUNGA/SCALAR.h @@ -0,0 +1,31 @@ +#pragma once + +#include +#include "style.h" +#include "memstrm.h" + +#define M_PI 3.14159265358979323846 + +typedef float Scalar; + +#define PI ((Scalar)(M_PI)) +#define PI_OVER_2 ((Scalar)(M_PI / 2.0)) +#define PI_OVER_3 ((Scalar)(M_PI / 3.0)) +#define PI_OVER_4 ((Scalar)(M_PI / 4.0)) +#define PI_OVER_6 ((Scalar)(M_PI / 6.0)) +#define TWO_PI ((Scalar)(2.0 * M_PI)) +#define DEG_PER_RAD ((Scalar)(180.0 / M_PI)) +#define RAD_PER_DEG ((Scalar)(M_PI / 180.0)) + +inline Scalar Lerp(Scalar a, Scalar b, Scalar t) { return a * (1.0f - t) + b * t; } +inline Logical Small_Enough(Scalar x, Scalar e=SMALL) { return fabs(x) <= e; } +inline Logical Close_Enough(Scalar x, Scalar y, Scalar e=SMALL) { return fabs(x - y) <= e; } + +int Round(Scalar value); + +void Find_Roots(Scalar a, Scalar b, Scalar c, Scalar *center, Scalar *range); + +inline MemoryStream& MemoryStream_Read(MemoryStream *stream, Scalar *output) { return stream->ReadBytes(output, sizeof(*output)); } +inline MemoryStream& MemoryStream_Write(MemoryStream *stream, const Scalar *input) { return stream->WriteBytes(input, sizeof(*input)); } + +void Convert_From_Ascii(const char *str, Scalar *value); \ No newline at end of file diff --git a/MUNGA/SCHAIN.cpp b/MUNGA/SCHAIN.cpp new file mode 100644 index 0000000..2eeebc1 --- /dev/null +++ b/MUNGA/SCHAIN.cpp @@ -0,0 +1,483 @@ +#include "munga.h" +#pragma hdrstop + +#include "schain.h" +#include "node.h" + +// +//########################################################################### +// SCHAINLINK +//########################################################################### +// + +MemoryBlock *SChainLink::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(SChainLink), SCHAINLINK_MEMORYBLOCK_ALLOCATION, SCHAINLINK_MEMORYBLOCK_ALLOCATION, "SChainLink"); + return &allocatedMemory; +} + +// +//########################################################################### +// SChainLink +//########################################################################### +// +SChainLink::SChainLink( + SChain *chain, + Plug *plug, + SChainLink *nextSChainLink, + SChainLink *prevSChainLink +): + Link(chain, plug) +{ + // + //------------------------- + // Link into existing chain + //------------------------- + // + if ((this->nextSChainLink = nextSChainLink) != NULL) + { + Check(nextSChainLink); + nextSChainLink->prevSChainLink = this; + } + if ((this->prevSChainLink = prevSChainLink) != NULL) + { + Check(prevSChainLink); + prevSChainLink->nextSChainLink = this; + } +} + +// +//########################################################################### +// ~SChainLink +//########################################################################### +// +SChainLink::~SChainLink() +{ + SChain *chain = Cast_Object(SChain*, socket); + + // + //--------------------------------------------- + // Notify iterators that the link is going away + //--------------------------------------------- + // + chain->SendIteratorMemo(PlugRemoved, this); + + // + //--------------------------- + // Remove from existing links + //--------------------------- + // + if (prevSChainLink != NULL) + { + Check(prevSChainLink); + prevSChainLink->nextSChainLink = nextSChainLink; + } + else + { + Check(chain); + chain->head = nextSChainLink; + } + if (nextSChainLink != NULL) + { + Check(nextSChainLink); + nextSChainLink->prevSChainLink = prevSChainLink; + } + else + { + Check(chain); + chain->tail = prevSChainLink; + } + prevSChainLink = nextSChainLink = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (chain->GetReleaseNode() != NULL) + { + Check(chain->GetReleaseNode()); + chain->GetReleaseNode()->ReleaseLinkHandler(chain, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SChainLink::TestInstance() const +{ + Link::TestInstance(); + + if (prevSChainLink != NULL) + { + Check_Signature(prevSChainLink); + } + if (nextSChainLink != NULL) + { + Check_Signature(nextSChainLink); + } + return True; +} + +// +//########################################################################### +// SCHAIN +//########################################################################### +// + +// +//########################################################################### +// SChain +//########################################################################### +// +SChain::SChain( + Node *node +) : +SafeSocket( + node +) +{ + head = NULL; + tail = NULL; +} + +// +//########################################################################### +// ~SChain +//########################################################################### +// +SChain::~SChain() +{ + SetReleaseNode(NULL); + while (head != NULL) + { + Unregister_Object(head); + delete head; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SChain::TestInstance() const +{ + SafeSocket::TestInstance(); + + if (head != NULL) + { + Check(head); + } + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + SChain::AddImplementation( + Plug *plug + ) +{ + tail = new SChainLink(this, plug, NULL, tail); + Register_Object(tail); + if (head == NULL) + { + head = tail; + } +} + +// +//########################################################################### +// InsertPlug +//########################################################################### +// +SChainLink* + SChain::InsertSChainLink( + Plug *plug, + SChainLink *link + ) +{ + Check(this); + Check(link); + Check(plug); + + SChainLink *new_link = + new SChainLink( + this, + plug, + link, + link->prevSChainLink + ); + Register_Object(new_link); + + Check(head); + if (head == link) + { + head = new_link; + } + return new_link; +} + +// +//########################################################################### +// SChainIterator +//########################################################################### +// +SChainIterator::SChainIterator(SChain *chain): + SafeIterator(chain) +{ + Check(chain); + currentLink = chain->head; +} + +SChainIterator::SChainIterator(const SChainIterator &iterator): + SafeIterator(Cast_Object(SChain*, iterator.socket)) +{ + Check(&iterator); + currentLink = iterator.currentLink; +} + +SChainIterator::~SChainIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SChainIterator::TestInstance() const +{ + SafeIterator::TestInstance(); + + if (currentLink != NULL) + { + Check(currentLink); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + SChainIterator::First() +{ + currentLink = Cast_Object(SChain*, socket)->head; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + SChainIterator::Last() +{ + currentLink = Cast_Object(SChain*, socket)->tail; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + SChainIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->nextSChainLink; +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + SChainIterator::Previous() +{ + Check(currentLink); + currentLink = currentLink->prevSChainLink; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void* + SChainIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->GetPlug(); + currentLink = currentLink->nextSChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void* + SChainIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->prevSChainLink; + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void* + SChainIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + return currentLink->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + SChainIterator::GetSize() +{ + SChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(SChain*, socket)->head; + link != NULL; + link = link->nextSChainLink + ) + { + Check(link); + count++; + } + return count; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void* + SChainIterator::GetNthImplementation( + CollectionSize index + ) +{ + SChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(SChain*, socket)->head; + link != NULL; + link = link->nextSChainLink + ) + { + Check(link); + if (count == index) + { + currentLink = link; + return currentLink->GetPlug(); + } + count++; + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + SChainIterator::Remove() +{ + Check(currentLink); + Unregister_Object(currentLink); + delete currentLink; +} + +// +//############################################################################# +// InsertImplementation +//############################################################################# +// +void + SChainIterator::InsertImplementation(Plug *plug) +{ + currentLink = + Cast_Object(SChain*, socket)->InsertSChainLink(plug, currentLink); + Check(currentLink); +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + SChainIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + if (memo == PlugRemoved) + { + if (content == currentLink) + { + Next(); + } + } +} + +#ifdef TEST_CLASS +# include "schain.tcp" +#endif diff --git a/MUNGA/SCHAIN.h b/MUNGA/SCHAIN.h new file mode 100644 index 0000000..ce31c41 --- /dev/null +++ b/MUNGA/SCHAIN.h @@ -0,0 +1,129 @@ +#pragma once + +#include "sfeskt.h" +#include "memblock.h" + +#define SCHAINLINK_MEMORYBLOCK_ALLOCATION (100) + +class SChainLink : public Link +{ + friend class SChain; + friend class SChainIterator; + +public: + ~SChainLink(); + Logical TestInstance() const; + +private: + SChainLink(SChain *chain, Plug *plug, SChainLink *nextSChainLink, SChainLink *prevSChainLink); + + SChainLink *nextSChainLink; + SChainLink *prevSChainLink; + +private: + static MemoryBlock* GetAllocatedMemory(); + + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { return GetAllocatedMemory()->Delete(where); } +}; + +class SChain : public SafeSocket +{ + friend class SChainLink; + friend class SChainIterator; + +public: + SChain(Node *node); + ~SChain(); + + Logical TestInstance() const; + static void TestClass(); + static void ProfileClass(); + +protected: + void AddImplementation(Plug *plug); + +private: + SChainLink* InsertSChainLink(Plug *plug, SChainLink *link); + + SChainLink *head; + SChainLink *tail; +}; + +template class SChainOf : public SChain +{ +public: + SChainOf(Node *node); + ~SChainOf(); + + void Add(T plug) { AddImplementation(Cast_Object(Plug*, plug)); } +}; + +template SChainOf::SChainOf(Node *node) : SChain(node) +{ +} + +template SChainOf::~SChainOf() +{ +} + +class SChainIterator : public SafeIterator +{ +public: + SChainIterator(SChain *chain); + SChainIterator(const SChainIterator &iterator); + ~SChainIterator(); + + Logical TestInstance() const; + + void First(); + void Last(); + void Next(); + void Previous(); + CollectionSize GetSize(); + void Remove(); + +protected: + void* ReadAndNextImplementation(); + void* ReadAndPreviousImplementation(); + void* GetCurrentImplementation(); + void* GetNthImplementation(CollectionSize index); + void InsertImplementation(Plug *plug); + +private: + void ReceiveMemo(IteratorMemo memo, void *content); + + SChainLink *currentLink; +}; + +template class SChainIteratorOf : public SChainIterator +{ +public: + SChainIteratorOf(SChainOf *chain); + SChainIteratorOf(SChainOf &chain); + SChainIteratorOf(const SChainIteratorOf &iterator); + + ~SChainIteratorOf(); + + T ReadAndNext() { return (T)ReadAndNextImplementation(); } + T ReadAndPrevious() { return (T)ReadAndPreviousImplementation(); } + T GetCurrent() { return (T)GetCurrentImplementation(); } + T GetNth(CollectionSize index) { return (T)GetNthImplementation(index); } + void Insert(T plug) { InsertImplementation(Cast_Object(Plug*, plug)); } +}; + +template SChainIteratorOf::SChainIteratorOf(SChainOf *chain) : SChainIterator(chain) +{ +} + +template SChainIteratorOf::SChainIteratorOf(SChainOf &chain) : SChainIterator(&chain) +{ +} + +template SChainIteratorOf::SChainIteratorOf(const SChainIteratorOf &iterator) : SChainIterator(iterator) +{ +} + +template SChainIteratorOf::~SChainIteratorOf() +{ +} \ No newline at end of file diff --git a/MUNGA/SCNROLE.cpp b/MUNGA/SCNROLE.cpp new file mode 100644 index 0000000..a135767 --- /dev/null +++ b/MUNGA/SCNROLE.cpp @@ -0,0 +1,235 @@ +#include "munga.h" +#pragma hdrstop + +#include "scnrole.h" +#include "app.h" +#include "notation.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ScenarioRole::ScenarioRole(const CString &role_name) +{ + damageReceivedModifier = 0.0f; + damageInflictedModifier = 0.0f; + damageBias = 0.0f; + friendlyFirePenalty = 0.0f; + killBonus = 0.0f; + roleName = role_name; + returnFromDeath = 0; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ScenarioRole::ScenarioRole(const CString &role_name, const CString &model_file) +{ + Check_Pointer(&role_name); + Check_Pointer(&model_file); + + roleName = role_name; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Truncate the Role:: from roleName + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceFile + *res = application->GetResourceFile(); + ResourceDescription + *player_res_des; + + player_res_des = res->FindResourceDescription( + model_file, + ResourceDescription::GameModelResourceType + ); + + if (player_res_des) + { + player_res_des->Lock(); + ModelResource + *player_data = (ModelResource *)player_res_des-> + resourceAddress; + + killBonus = player_data->killBonus; + returnFromDeath = player_data->returnFromDeath; + damageReceivedModifier = player_data->damageReceivedModifier; + damageInflictedModifier = player_data->damageInflictedModifier; + damageBias = player_data->damageBias; + friendlyFirePenalty = player_data->friendlyFirePenalty; + player_res_des->Unlock(); + } + else + { + Tell(role_name); + Warn(" does not exists in resource! "); + damageReceivedModifier = 0.0f; + damageInflictedModifier = 0.0f; + damageBias = 0.0f; + friendlyFirePenalty = 0.0f; + killBonus = 0.0f; + returnFromDeath = 0; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + ScenarioRole::CalcDamageReceivedScore(const Scalar &damage_received) +{ + Check(this); +// ] +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Calculate modified score for the player receiving damage +// damageReceived * damageReceivedModifier +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + Check(this); + + Check_Fpu(); + return -(damage_received * GetDamageReceivedModifier()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ScenarioRole::~ScenarioRole() +{ + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + ScenarioRole::CreateModelResource( +#if DEBUG_LEVEL>0 + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model +#else + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *, + ModelResource *model +#endif + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check_Pointer(directories); + + // + // If we were not provided a buffer to write the model data into, we must + // create it ourselves. Then make sure that the model stuff is read in + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + //---------------------------------------- + // Read in the data from notation file + //---------------------------------------- + // + // Get PointValue assigned to this ScoreZone + // + + if( + !model_file->GetEntry( + "gamedata", + "KillBonus", + &local_model->killBonus + ) + ) + { + std::cerr << model_name << "Missing KillBonus" << std::endl; +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + return -1; + } + + if( + !model_file->GetEntry( + "gamedata", + "DamageReceivedModifier", + &local_model->damageReceivedModifier + ) + ) + { + std::cerr << model_name << "Missing DamageReceivedModifier" << std::endl; + goto Dump_And_Die; + } + + if( + !model_file->GetEntry( + "gamedata", + "DamageInflictedModifier", + &local_model->damageInflictedModifier + ) + ) + { + std::cerr << model_name << "Missing DamageInflictedModifier" << std::endl; + goto Dump_And_Die; + } + if( + !model_file->GetEntry( + "gamedata", + "ReturnFromDeath", + &local_model->returnFromDeath + ) + ) + { + std::cerr << model_name << "Missing ReturnFromDeath" << std::endl; + goto Dump_And_Die; + } + if( + !model_file->GetEntry( + "gamedata", + "DamageBias", + &local_model->damageBias + ) + ) + { + std::cerr << model_name << "Missing DamageBias" << std::endl; + goto Dump_And_Die; + } + + if( + !model_file->GetEntry( + "gamedata", + "FriendlyFirePenalty", + &local_model->friendlyFirePenalty + ) + ) + { + std::cerr << model_name << "Missing FriendlyFirePenalty" << std::endl; + goto Dump_And_Die; + } + + + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check_Fpu(); + Check(new_res); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} diff --git a/MUNGA/SCNROLE.h b/MUNGA/SCNROLE.h new file mode 100644 index 0000000..95ef9d4 --- /dev/null +++ b/MUNGA/SCNROLE.h @@ -0,0 +1,116 @@ +#pragma once + +#include "node.h" +#include "cstr.h" +#include "resource.h" +#include "scalar.h" + +class NotationFile; + +struct ScenarioRole__ModelResource +{ + Scalar killBonus, damageReceivedModifier, damageInflictedModifier, damageBias, friendlyFirePenalty; + int returnFromDeath; +}; + +class ScenarioRole : public Node +{ +public: + Scalar CalcDamageReceivedScore(const Scalar &damage_received); + +protected: + Scalar damageInflictedModifier, damageReceivedModifier, friendlyFirePenalty, damageBias, killBonus; + CString roleName; + + int returnFromDeath; + +public: + const int GetReturnFromDeath() + { + Check(this); + return returnFromDeath; + } + + Scalar GetDamageInflictedModifier() const + { + Check(this); + return damageInflictedModifier; + } + + Scalar GetDamageReceivedModifier() const + { + Check(this); + return damageReceivedModifier; + } + + Scalar GetFriendlyFirePenalty() const + { + Check(this); + return friendlyFirePenalty; + } + + Scalar GetDamageBias() const + { + Check(this); + return damageBias; + } + + Scalar GetKillBonus() const + { + Check(this); + return killBonus; + } + + CString GetRoleName() const + { + Check(this); + return roleName; + } + + void SetDamageInflictedModifier(const Scalar &value) + { + Check(this); + damageInflictedModifier = value; + } + + void SetDamageReceivedModifier(const Scalar value) + { + Check(this); + damageReceivedModifier = value; + } + + void SetFriendlyFirePenalty(const Scalar &value) + { + Check(this); + friendlyFirePenalty = value; + } + + void SetDamageBias(const Scalar &value) + { + Check(this); + damageBias = value; + } + + void SetKillBonus(const Scalar &value) + { + Check(this); + killBonus = value; + } + + void SetReturnFromDeath(const int &value) + { + Check(this); + returnFromDeath = value; + } + +public: + typedef ScenarioRole__ModelResource ModelResource; + + ScenarioRole(const CString &role_name, const CString &model_file); + + ScenarioRole(const CString &role_name); + + ~ScenarioRole(); + + static ResourceDescription::ResourceID CreateModelResource(ResourceFile *resource_file, const char* model_name, NotationFile * model_file, const ResourceDirectories *directories, ModelResource *model = NULL); +}; diff --git a/MUNGA/SEGMENT.cpp b/MUNGA/SEGMENT.cpp new file mode 100644 index 0000000..7ecac09 --- /dev/null +++ b/MUNGA/SEGMENT.cpp @@ -0,0 +1,273 @@ +#include "munga.h" +#pragma hdrstop + +#include "segment.h" +#include "joint.h" + +//############################################################################# +// Segment::VideoObjectNames Support +// + +CString* + EntitySegment::VideoObjectNames::GetVideoObjectName( + Enumeration damage_graphic_state + ) +{ + Check(this); + CStringPlug *my_plug = videoObjectNames.Find(damage_graphic_state); + if (my_plug) + { + Check(my_plug); + return my_plug->GetPointer(); + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment__VideoObjectNames::EntitySegment__VideoObjectNames() : videoObjectNames(NULL, false) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment::VideoObjectNames::~VideoObjectNames() +{ + VChainIteratorOf iterator(videoObjectNames); + iterator.DeletePlugs(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::VideoObjectNames::AddVideoObjectName( + const CString &new_name, + Enumeration damage_graphic_state + ) +{ + Check(this); + CStringPlug *new_string = new CStringPlug(new_name); + Register_Object(new_string); + + videoObjectNames.AddValue(new_string, damage_graphic_state); +} + + +//############################################################################# +// Segment Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment::EntitySegment( + CString segment_name, + int this_index, + int parent_index, + int joint_index, + Joint *joint_ptr, + LinearMatrix &lin_matrix, + EntitySegment *parent_segment, + Logical is_site, + int primary_damage_zone +) : + baseOffset(LinearMatrix::Identity), + childIndexTable(NULL, True), + damageZoneTable(NULL,True), + videoObjectTable(NULL,True), + childPointerTable(NULL,True) +{ + segmentModified = True; + thisIndex = this_index; + parentIndex = parent_index; + jointIndex = joint_index; + jointPointer = joint_ptr; + baseOffset = lin_matrix; + parentSegment =parent_segment; + segmentName = segment_name; + siteSegment = is_site; + primaryDamageZone = primary_damage_zone; // Add To constructor Call + + segmentToParent = baseOffset; + segmentToEntity = baseOffset; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CString* + EntitySegment::GetVideoObjectName( + SkeletonType skl_type, + Enumeration damage_graphic_state + ) +{ + Check(this); + VideoObjectNames *video_names = videoObjectTable.Find(skl_type); + if(video_names) + { + return video_names->GetVideoObjectName(damage_graphic_state); + } + else + { + return NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +EntitySegment::~EntitySegment() +{ + IntegerTableIterator iterator_child( childIndexTable); + iterator_child.DeletePlugs(); + + IntegerTableIterator iterator_damage(damageZoneTable); + iterator_damage.DeletePlugs(); + + VideoTableIterator iterator_video(videoObjectTable); + iterator_video.DeletePlugs(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddChildIndex(int child_index, int index) +{ + Check(this); + IntegerPlug *child_plug = new IntegerPlug(child_index); + Register_Object(child_plug); + childIndexTable.AddValue(child_plug, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddChildPointer(EntitySegment* child_ptr, int index) +{ + Check(this); + childPointerTable.AddValue(child_ptr, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddDamageZone(int damage_index, int index) +{ + Check(this); + Check_Pointer(&damageZoneTable); + IntegerPlug *damage_plug = new IntegerPlug(damage_index); + Register_Object(damage_plug); + damageZoneTable.AddValue(damage_plug, index); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + EntitySegment::AddVideoObjectName( + CString video_object_name, + Enumeration skl_type, + Enumeration damage_graphic_state + ) +{ + Check(this); + Check_Pointer(&videoObjectTable); + VideoTableIterator iterator(videoObjectTable); + + VideoObjectNames *names_plug = iterator.Find(skl_type); + if(!names_plug) + { + names_plug = new VideoObjectNames(); + Register_Object(names_plug); + videoObjectTable.AddValue(names_plug, skl_type); + } + names_plug->AddVideoObjectName(video_object_name, damage_graphic_state); + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const LinearMatrix& + EntitySegment::GetSegmentToParent() +{ + Check(this); + + // + //----------------------------------------------------------------------- + // Recalculate the segment to parent matrix if we have a joint and it has + // changed + //----------------------------------------------------------------------- + // + if (jointPointer) + { + Check(jointPointer); + if (jointPointer->IsJointModified()) + { + jointPointer->JointModified(False); + LinearMatrix + t1 = baseOffset, + t2; + + switch(jointPointer->GetJointType()) + { + case Joint::BallJointType: + { + LinearMatrix euler_angles = LinearMatrix::Identity; + euler_angles = jointPointer->GetEulerAngles(); + t2.Invert(euler_angles); + segmentToParent.Multiply(t1,t2); + } + break; + + case Joint::HingeXJointType: + case Joint::HingeYJointType: + case Joint::HingeZJointType: + { + LinearMatrix hinge_joint = LinearMatrix::Identity; + hinge_joint = jointPointer->GetHinge(); + t2.Invert(hinge_joint); + segmentToParent.Multiply(t1,t2); + } + break; + + case Joint::BallTranslationJointType: + { + // + //------------------------------------- + // We only want to invert the rotations + //------------------------------------- + // + LinearMatrix euler_angles = LinearMatrix::Identity; + euler_angles = jointPointer->GetEulerAngles(); + segmentToParent.Invert(euler_angles); + t2.Multiply(t1,segmentToParent); + t1 = LinearMatrix::Identity; + t1 = jointPointer->GetTranslation(); + segmentToParent.Multiply(t2,t1); + } + break; + } + } + } + return segmentToParent; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +const LinearMatrix& + EntitySegment::GetSegmentToEntity() +{ + Check(this); + + // + //--------------------------------------------------------------------- + // Recalculate the segment to entity transform if something has changed + //--------------------------------------------------------------------- + // + if (segmentModified && parentSegment) + { + Check(parentSegment); + segmentToEntity.Multiply( + GetSegmentToParent(), + parentSegment->GetSegmentToEntity() + ); + ModifySegment(False); + } + return segmentToEntity; +} diff --git a/MUNGA/SEGMENT.h b/MUNGA/SEGMENT.h new file mode 100644 index 0000000..5c3624d --- /dev/null +++ b/MUNGA/SEGMENT.h @@ -0,0 +1,239 @@ +#pragma once + +#include "table.h" +#include "linmtrx.h" +#include "cstr.h" +#include "vchain.h" + +class DamageZone; +class Joint; +class JointedMover; + +//########################################################################## +//##################### Segment::VideoObjectNames ########################## +//########################################################################## + +class EntitySegment__VideoObjectNames : + public Plug +{ +public: + CString* + GetVideoObjectName(Enumeration damage_graphic_state); + + void + AddVideoObjectName( + const CString &new_name, + Enumeration damage_graphic_state + ); + + + EntitySegment__VideoObjectNames(); + ~EntitySegment__VideoObjectNames(); + +protected: + + typedef PlugOf CStringPlug; + + typedef VChainOf + VideoObjectNamesSocket; + + VideoObjectNamesSocket videoObjectNames; +}; + +//########################################################################## +//########################## Segment ############################### +//########################################################################## + +class EntitySegment : + public Plug +{ + friend class JointedMover; + +public: + typedef EntitySegment__VideoObjectNames VideoObjectNames; + typedef TableOf SegmentTable; + typedef TableIteratorOf SegmentTableIterator; + typedef PlugOf IntegerPlug; + typedef TableOf IntegerTable; + typedef TableIteratorOf IntegerTableIterator; + + enum SkeletonType { + SkeletonType_N, // Exterior + SkeletonType_S, // Interior + SkeletonType_T, + SkeletonType_O, + SkeletonType_A, + SkeletonType_B, + SkeletonType_C, + SkeletonType_D, + SkeletonTypeCount + }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Segment Data +// +protected: + Logical + segmentModified, + siteSegment; + + LinearMatrix + segmentToParent, + segmentToEntity, + baseOffset; + + typedef PlugOf CStringPlug; + typedef TableOf VideoObjectTable; + typedef TableIteratorOf VideoTableIterator; + + VideoObjectTable + videoObjectTable; + + Joint + *jointPointer; + int + jointIndex; + EntitySegment + *parentSegment; + int + parentIndex; + int + thisIndex; + + IntegerTable + damageZoneTable, + childIndexTable; + int + primaryDamageZone; + + SegmentTable + childPointerTable; + + CString + segmentName; + + const LinearMatrix& + GetSegmentToParent(); + + void + SetSegmentToEntity(LinearMatrix& new_matrix) + {Check(this); segmentToEntity = new_matrix;} + void + SetSegmentToParent(LinearMatrix& new_matrix) + {Check(this); segmentToParent = new_matrix;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Accessors +// +public: + void + ModifySegment(Logical modified = True) + {Check(this); segmentModified = modified;} + + const LinearMatrix& + GetBaseOffset() const + {Check(this); return baseOffset;} + + const LinearMatrix& + GetSegmentToEntity(); + + int + GetPrimaryDamageZone() const + {Check(this); return primaryDamageZone;} + int + GetParentIndex() const + {Check(this); return parentIndex;} + + const EntitySegment* + GetParent() const + {Check(this); return parentSegment;} + + int + GetIndex() const + {Check(this); return thisIndex;} + + int + IsSiteSegment() + {Check(this); return siteSegment;} + + CString + GetName() const + {Check(this); return segmentName;} + + int + GetJointIndex() const + {Check(this); return jointIndex;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Children of Segments Support +// +public: + CString* + GetVideoObjectName( + SkeletonType skl_type = SkeletonType_N, + Enumeration damage_graphic_state = 0 + ); + + void + AddChildIndex(int child_index, int index); + + void + AddChildPointer(EntitySegment *child_pointer, int index); + + void + AddDamageZone(int damage_index, int index); + + void + AddVideoObjectName( + CString video_object_name, + Enumeration skl_type, + Enumeration damage_graphic_state = 0 + ); + + IntegerTableIterator* + MakeChildIndexTable() + { + Check(this); + Check_Pointer(&childIndexTable); + IntegerTableIterator *iterator = new + IntegerTableIterator(&childIndexTable); + return iterator; + } + + IntegerTableIterator* + MakeDamageZoneIndexTable() + { + Check(this); + Check_Pointer(&damageZoneTable); + IntegerTableIterator *iterator = new + IntegerTableIterator(&damageZoneTable); + return iterator; + } + + EntitySegment( + CString segment_name, + int this_index, + int parent_index, + int joint_index, + Joint *joint_ptr, + LinearMatrix &lin_matrix, + EntitySegment *parent_segment, + Logical is_site, + int primary_damage_zone + + ); + ~EntitySegment(); +}; + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + EntitySegment::SkeletonType *output + ) + {return stream->ReadBytes(output, sizeof(*output));} +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const EntitySegment::SkeletonType *input + ) + {return stream->WriteBytes(input, sizeof(*input));} diff --git a/MUNGA/SET.cpp b/MUNGA/SET.cpp new file mode 100644 index 0000000..3b45825 --- /dev/null +++ b/MUNGA/SET.cpp @@ -0,0 +1,144 @@ +#include "munga.h" +#include "set.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Set +//############################################################################# +// +Set::Set(Node *node): + Socket(node), + contents(NULL) +{ + +} + + + + +// +//############################################################################# +// ~Set +//############################################################################# +// +Set::~Set() +{ + SetReleaseNode(NULL); + if (contents) + { + delete contents; + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Set::TestInstance() const +{ + Socket::TestInstance(); + Check(contents); + return True; +} + + +// +//############################################################################# +// Union +// +// Merge contents of this with rhs. Items that occur in either set are placed +// in the resulting set, with no duplication. It is assumed that both operands +// are proper sets, ie. they contain no duplicates. +//############################################################################# +// + +Set + Set::Union(const Set &) const +{ + Check(this); + + + Set result(NULL); + + return result; +} + + +// +//############################################################################# +// Intersection +// +// Merge contents of this with rhs. Items that occur in both sets are placed +// only once in the resulting set. It is assumed that both operands are proper +// sets, ie. they contain no duplicates. +// +// This implementation of set intersection is dumb and slow. +//############################################################################# +// + +Set + Set::Intersection(const Set &rhs) const +{ + Check(this); + Check(rhs); + + // Contents iterator is a SetIterator and not a ChainIterator in order to + // have access to the ChainIterator::ReadAndNextImplentation. + // We circumvent encapsulation protections by declaring Set a friend of SetIterator + // (which derives from ChainIterator). Set is not a friend of ChainIterator. + + SetIterator contents_iterator(contents); + + // Casting away const is safe since our local iterator is not going to insert or + // remove items from rhs. + SetIterator rhs_iterator((Set *) &rhs); + Plug *lhs_plug; + Plug *rhs_plug; + Set result(NULL); + + + while ((lhs_plug = Cast_Object(Plug *, contents_iterator.ReadAndNextImplementation())) != NULL) + { + while ((rhs_plug = Cast_Object(Plug *,rhs_iterator.ReadAndNextImplementation())) != NULL) + { + if (lhs_plug == rhs_plug) + { + result.AddImplementation(lhs_plug); + } + } + } + return result; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// SetIterator +//############################################################################# +// +SetIterator::SetIterator(Set *set): + ChainIterator(set->contents) +{ + Check(set); +} + +SetIterator::SetIterator(const SetIterator &iterator): + ChainIterator(Cast_Object(Chain*, (Cast_Object(Set *,iterator.socket)->contents))) +{ + Check(&iterator); +} + +SetIterator::SetIterator(Chain *chain): + ChainIterator(chain) +{ + Check(chain); +} + +SetIterator::~SetIterator() +{ +} diff --git a/MUNGA/SET.h b/MUNGA/SET.h new file mode 100644 index 0000000..864b01d --- /dev/null +++ b/MUNGA/SET.h @@ -0,0 +1,261 @@ +#pragma once + +#include "chain.h" + +// Classes Defined in this file + +class Set; +class SetIterator; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Set ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Set : public Socket +{ + + friend class SetIterator; + +public: + Logical + TestInstance() const; + + + // Constructor + Set(Node *node); + + ~Set(); + +protected: + Set& operator=(const Set &rhs); + + //STUBBED: UNKNOWN RB 1/15/07 + //void + // AddImplementation(Plug *plug); + + // Useful Set Operations + Logical operator==(const Set &rhs); + Set operator-(const Set &rhs) const; + Set Union(const Set &rhs) const; + Set Intersection(const Set &rhs) const; + + // Set membership + Logical + Exists(const Plug &element) const; + +private: + Chain *contents; +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +template class SetOf: + public Set +{ +public: + SetOf(Node *node); + ~SetOf(); + +protected: + SetOf(Set set): + Set(set) + { + } + +public: + + // Public interface + + void + Add(T *plug) + {AddImplementation(plug);} + + // Useful Set Operations + SetOf& + operator=(const SetOf &rhs) + { + if (this==&rhs) return *this; + Set::operator=(rhs); + return *this; + } + + Logical + operator==(const SetOf &rhs) + {return Set::operator==(rhs);} + + + SetOf + operator-(const SetOf rhs) const + {return (SetOf) Set::operator-(rhs);} + + SetOf + Union(const SetOf &rhs) const + {return (SetOf) Set::Union(rhs);} + + SetOf + Intersection(const SetOf &rhs) const + {return (SetOf) Set::Intersection(rhs);} + + +}; + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + SetOf::SetOf(Node *node): + Set(node) + { + } + + template + SetOf::~SetOf() + { + } + + + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ SetIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + class SetIterator: + public ChainIterator + { + public: + friend class Set; + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors, Destructor and testing + //-------------------------------------------------------------------- + // + SetIterator(Set *set); + SetIterator(const SetIterator &iterator); + ~SetIterator(); + + protected: + SetIterator(Chain *chain); // Used fot Set implementation to iterate on own contents + }; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ SetIteratorOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template class SetIteratorOf: + public SetIterator + { + public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Constructors and Destructor + //-------------------------------------------------------------------- + // + SetIteratorOf(SetOf *chain); + SetIteratorOf(SetOf &chain); + SetIteratorOf(const SetIteratorOf &iterator); + ~SetIteratorOf(); + + // + //-------------------------------------------------------------------- + // Iterator methods (see Iterator for full listing) + //-------------------------------------------------------------------- + // + T* + ReadAndNext() + {return (T*)ReadAndNextImplementation();} + T* + ReadAndPrevious() + {return (T*)ReadAndPreviousImplementation();} + T* + GetCurrent() + {return (T*)GetCurrentImplementation();} + T* + GetNth(CollectionSize index) + {return (T*)GetNthImplementation(index);} + void + Insert(T *plug) + {InsertImplementation(plug);} + + SetIteratorOf& + Begin() + {return (SetIteratorOf&)BeginImplementation();} + SetIteratorOf& + End() + {return (SetIteratorOf&)EndImplementation();} + SetIteratorOf& + Forward() + {return (SetIteratorOf&)ForwardImplementation();} + SetIteratorOf& + Backward() + {return (SetIteratorOf&)BackwardImplementation();} + + // + //--------------------------------------------------- + // Operators useful when it is know that the iterator + // is a SetOf<> Iterator + //--------------------------------------------------- + // +#if 0 + Logical + operator!() + {return currentLink == NULL;} + operator T*() + {return GetCurrent();} + T* + operator->() + {return GetCurrent();} + T& + operator*() + {return *GetCurrent();} + + SetIteratorOf& + operator++() + {Next(); return *this;} + SetIteratorOf& + operator--() + {Previous(); return *this;} + T* + operator++(int) + {return ReadAndNext();} + T* + operator--(int) + {return ReadAndPrevious();} +#endif + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~ SetIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + + template + SetIteratorOf::SetIteratorOf(SetOf *set): + SetIterator(chain) + { + } + + template + SetIteratorOf::SetIteratorOf(SetOf &set): + SetIterator(&chain) + { + } + + template + SetIteratorOf::SetIteratorOf(const SetIteratorOf &iterator): + SetIterator(iterator) + { + } + + template + SetIteratorOf::~SetIteratorOf() + { + } diff --git a/MUNGA/SFESKT.cpp b/MUNGA/SFESKT.cpp new file mode 100644 index 0000000..8588018 --- /dev/null +++ b/MUNGA/SFESKT.cpp @@ -0,0 +1,150 @@ +#include "munga.h" +#pragma hdrstop + +#include "sfeskt.h" + +// +//########################################################################### +// SafeSocket +//########################################################################### +// +SafeSocket::SafeSocket(Node *node): + Socket(node) +{ + iteratorHead = NULL; +} + +// +//########################################################################### +// ~SafeSocket +//########################################################################### +// +SafeSocket::~SafeSocket() +{ + Verify(iteratorHead == NULL); +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SafeSocket::TestInstance() const +{ + Socket::TestInstance(); + + if (iteratorHead != NULL) + { + Check_Signature(iteratorHead); + } + return True; +} + +// +//########################################################################### +// SendIteratorMemo +//########################################################################### +// +void + SafeSocket::SendIteratorMemo( + IteratorMemo memo, + void *content + ) +{ + SafeIterator *iterator; + + for ( + iterator = iteratorHead; + iterator != NULL; + iterator = iterator->nextIterator + ) { + Check(iterator); + iterator->ReceiveMemo(memo, content); + } +} + +// +//########################################################################### +// SafeIterator +//########################################################################### +// +SafeIterator::SafeIterator(SafeSocket *safeSocket): + SocketIterator(safeSocket) +{ + // + // Link iterator into sockets set of iterators + // + Check(safeSocket); + if ((nextIterator = safeSocket->iteratorHead) != NULL) + { + Check(nextIterator); + nextIterator->prevIterator = this; + } + prevIterator = NULL; + safeSocket->iteratorHead = this; +} + +// +//########################################################################### +// ~SafeIterator +//########################################################################### +// +SafeIterator::~SafeIterator() +{ + SafeSocket *safeSocket = Cast_Object(SafeSocket*, socket); + + // + // Remove iterator from sockets set of iterators + // + Check(safeSocket); + if (safeSocket->iteratorHead == this) + { + safeSocket->iteratorHead = nextIterator; + } + if (prevIterator != NULL) + { + Check(prevIterator); + prevIterator->nextIterator = nextIterator; + } + if (nextIterator != NULL) + { + Check(nextIterator); + nextIterator->prevIterator = prevIterator; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SafeIterator::TestInstance() const +{ + SocketIterator::TestInstance(); + + if (prevIterator != NULL) + { + Check_Signature(prevIterator); + } + if (nextIterator != NULL) + { + Check_Signature(nextIterator); + } + return True; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + SafeIterator::ReceiveMemo( + IteratorMemo, + void* + ) +{ + Fail("SafeIterator::ReceiveMemo - Should never reach here"); +} diff --git a/MUNGA/SFESKT.h b/MUNGA/SFESKT.h new file mode 100644 index 0000000..abe81aa --- /dev/null +++ b/MUNGA/SFESKT.h @@ -0,0 +1,49 @@ +#pragma once + +#include "socket.h" + +class SafeIterator; + +typedef int IteratorMemo; + +enum +{ + PlugAdded = 0, + PlugRemoved, + NextSafeSocketMemo +}; + +class SafeSocket : public Socket +{ + friend class SafeIterator; + +public: + ~SafeSocket(); + Logical TestInstance() const; + +protected: + SafeSocket(Node *node); + + void SendIteratorMemo(IteratorMemo memo, void *content); + +private: + SafeIterator *iteratorHead; +}; + +class SafeIterator : public SocketIterator +{ + friend class SafeSocket; + +public: + ~SafeIterator(); + Logical TestInstance() const; + +protected: + SafeIterator(SafeSocket *safeSocket); + +private: + virtual void ReceiveMemo(IteratorMemo memo, void *content); + + SafeIterator *nextIterator; + SafeIterator *prevIterator; +}; \ No newline at end of file diff --git a/MUNGA/SIMULATE.cpp b/MUNGA/SIMULATE.cpp new file mode 100644 index 0000000..33fe5c7 --- /dev/null +++ b/MUNGA/SIMULATE.cpp @@ -0,0 +1,715 @@ +#include "munga.h" +#pragma hdrstop + +#include "simulate.h" +#include "update.h" +#include "app.h" + +#if defined(TRACE_EXECUTE_WATCHERS) + static BitTrace Execute_Watchers("Execute Watchers"); + #define SET_EXECUTE_WATCHERS() Execute_Watchers.Set() + #define CLEAR_EXECUTE_WATCHERS() Execute_Watchers.Clear() +#else + #define SET_EXECUTE_WATCHERS() + #define CLEAR_EXECUTE_WATCHERS() +#endif + +//############################################################################# +//######################## StateIndicator ############################### +//############################################################################# + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::StateIndicator(): + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL) +{ + Check_Pointer(this); + stateCount = 0; + oldState = 0; + currentState = 0; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::StateIndicator(unsigned max_states): + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL) +{ + Check_Pointer(this); + stateCount = max_states; + oldState = max_states; + currentState = max_states; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::StateIndicator(const StateIndicator &state_indicator): + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL) +{ + Check_Pointer(this); + + // Do not perform deep copy of watchers + stateCount = state_indicator.stateCount; + oldState = state_indicator.oldState; + currentState = state_indicator.currentState; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator::~StateIndicator() +{ + Check(this); + + // + // Manual deletion of existing watchers + // + { + SChainIteratorOf iterator(&audioWatcherSocket); + #if DEBUG_LEVEL>2 + Component *component; + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + Dump(component->GetClassID()); + } + Warn(iterator.GetSize() != 0); + #endif + iterator.DeletePlugs(); + } + { + SChainIteratorOf iterator(&videoWatcherSocket); + #if DEBUG_LEVEL>2 + Component *component; + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + Dump(component->GetClassID()); + } + Warn(iterator.GetSize() != 0); + #endif + iterator.DeletePlugs(); + } + { + SChainIteratorOf iterator(&gaugeWatcherSocket); + #if DEBUG_LEVEL>2 + Component *component; + while ((component = iterator.ReadAndNext()) != NULL) + { + Check(component); + Dump(component->GetClassID()); + } + Warn(iterator.GetSize() != 0); + #endif + iterator.DeletePlugs(); + } + Check_Fpu(); +} + +//############################################################################# +// State stuff +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +StateIndicator& + StateIndicator::operator=(const StateIndicator &state_indicator) +{ + // Do not perform assignment of watchers + stateCount = state_indicator.stateCount; + oldState = state_indicator.oldState; + currentState = state_indicator.currentState; + + Check_Fpu(); + return *this; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + StateIndicator::operator==(const StateIndicator &state_indicator) const +{ + Check_Fpu(); + return + ( + stateCount == state_indicator.stateCount && + oldState == state_indicator.oldState && + currentState == state_indicator.currentState + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + StateIndicator::SetState(unsigned new_state) +{ + Check(this); + Verify(new_state < stateCount); + + // + //-------------------------------------------------------------------------- + // See if the state really changes + // + // NOTE - the old state does change to the current state, simulating a loop + // in the state engine. If it turns out that someone is watching the + // level of the state indicator and doing their own edge detection, + // this might possibly maybe screw something up + //-------------------------------------------------------------------------- + // + oldState = currentState; + if (new_state == currentState) + { + return; + } + + // + //------------------------------------------------------------------- + // If the state has changed, update the state values and then run any + // watchers + //------------------------------------------------------------------- + // + currentState = new_state; + Component *watcher; + + SET_EXECUTE_WATCHERS(); + + // Audio + { + SChainIteratorOf iterator(audioWatcherSocket); + Check(&iterator); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Video + { + SChainIteratorOf iterator(videoWatcherSocket); + Check(&iterator); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Gauge + { + SChainIteratorOf iterator(gaugeWatcherSocket); + Check(&iterator); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + CLEAR_EXECUTE_WATCHERS(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +std::ostream& operator << (std::ostream &strm, const StateIndicator &state_indicator) +{ + Check(&state_indicator); + + strm << "[" << state_indicator.stateCount << ","; + strm << state_indicator.oldState << ","; + strm << state_indicator.currentState << "]"; + + return strm; +} + +//############################################################################# +// Test Support +// +Logical + StateIndicator::TestInstance() const +{ + return True; +} + +//############################################################################# +//########################## Simulation ################################# +//############################################################################# + +//############################################################################# +// Virtual Data support +// +Derivation* Simulation::GetClassDerivations() +{ + static Derivation classDerivations(Receiver::GetClassDerivations(), "Simulation"); + return &classDerivations; +} + +Simulation::SharedData + Simulation::DefaultData( + Simulation::GetClassDerivations(), + Simulation::GetMessageHandlers(), + Simulation::GetAttributeIndex(), + Simulation::StateCount + ); + +//############################################################################# +// Model support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::ReadUpdateRecord(UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + + lastUpdate = Now(); // HACK - should be based upon message->timeStamp + SetSimulationState(message->simulationState); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::WriteUpdateRecord( + UpdateRecord *message, + int update_model + ) +{ + Check(this); + Check_Pointer(message); + + message->timeStamp = lastPerformance; + message->simulationState = GetSimulationState(); + message->recordLength = sizeof(*message); + message->recordID = (Word)update_model; + lastUpdate = lastPerformance; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::WriteSimulationUpdate(MemoryStream *update_stream) +{ + Check(this); + Check(update_stream); + + // + //----------------- + // Write the update + //----------------- + // + int bit=0; + int update_model = updateModel; + updateModel = 0; + while (update_model) + { + + if (update_model & 1) + { + UpdateRecord* update = (UpdateRecord*)update_stream->GetPointer(); + WriteUpdateRecord(update, bit); + update_stream->AdvancePointer(update->recordLength); + } + update_model >>= 1; + ++bit; + } + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation::Simulation( + Simulation::ClassID class_ID, + Simulation::SharedData &virtual_data +): + Receiver(class_ID, virtual_data), + simulationState(GetSharedData()->stateCount), + audioWatcherSocket(NULL), + videoWatcherSocket(NULL), + gaugeWatcherSocket(NULL), + effectWatcherSocket(NULL) +{ + Check_Pointer(this); + + SetSimulationState(DefaultState); + lastPerformance = Now(); + lastUpdate = lastPerformance; + activePerformance = &Simulation::DoNothingOnce; + updateModel = 0; + simulationFlags = 0; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation::~Simulation() +{ + Check(this); + + // + // Watchers should be deleted by renderers by now + // + #if DEBUG_LEVEL>0 + { + SChainIteratorOf iterator(&audioWatcherSocket); + Verify(iterator.GetSize() == 0); + } + { + SChainIteratorOf iterator(&videoWatcherSocket); + Verify(iterator.GetSize() == 0); + } + { + SChainIteratorOf iterator(&gaugeWatcherSocket); + Verify(iterator.GetSize() == 0); + } + #endif + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const Simulation::AttributePointer + Simulation::NullAttribute = NULL; + +const Simulation::IndexEntry + Simulation::AttributePointers[]= +{ + { + Simulation::SimulationStateAttributeID, + "SimulationState", + (Simulation::AttributePointer)&Simulation::simulationState + } +}; + +Simulation::AttributeIndexSet& Simulation::GetAttributeIndex() +{ + static Simulation::AttributeIndexSet attributeIndex(ELEMENTS(Simulation::AttributePointers), + Simulation::AttributePointers + ); + return attributeIndex; +} + +void* + Simulation::GetAttributePointer(Simulation::AttributeID attribute) +{ + Check(this); + + AttributePointer attr = + GetSharedData()->activeAttributeIndex->Find(attribute); + Check_Fpu(); + if (attr == NullAttribute) + { + return NULL; + } + else + { + return &(this->*attr); + } +} + +void* + Simulation::GetAttributePointer(const char* attribute_name) +{ + Check(this); + + AttributePointer attr = + GetSharedData()->activeAttributeIndex->Find(attribute_name); + Check_Fpu(); + if (attr == NullAttribute) + { + return NULL; + } + else + { + return &(this->*attr); + } +} + +//############################################################################# +// Simulation Support +// +void + Simulation::PerformAndWatch( + const Time& till, + MemoryStream *update_stream + ) +{ + Check(this); + Check(&till); + + Scalar slice = till - lastPerformance; + lastPerformance = till; + + Perform(slice); + if (!AreWatchersDelayed()) + { + ExecuteWatchers(); + } + WriteSimulationUpdate(update_stream); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::DoNothingOnce(Scalar) +{ + NeverExecute(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::DoNothing(Scalar) +{ + Check_Fpu(); +} + +//############################################################################# +// Watcher Support +// +void + Simulation::ExecuteWatchers() +{ + SET_EXECUTE_WATCHERS(); + + Component *watcher; + + // Audio + { + SChainIteratorOf iterator(audioWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Video + { + SChainIteratorOf iterator(videoWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Gauge + { + SChainIteratorOf iterator(gaugeWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + + // Effect + { + SChainIteratorOf iterator(effectWatcherSocket); + while ((watcher = iterator.ReadAndNext()) != NULL) + { + watcher->Execute(); + } + } + CLEAR_EXECUTE_WATCHERS(); +} + +//############################################################################# +// Test Support +// + +Logical + Simulation::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +//################### Simulation::AttributeIndexSet ##################### +//############################################################################# + +const Simulation::AttributeIndexSet + Simulation::AttributeIndexSet::NullSet; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation__AttributeIndexSet::~Simulation__AttributeIndexSet() +{ + if (attributeIndex) + { + Unregister_Pointer(attributeIndex); + delete[] attributeIndex; + } +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Simulation::AttributeIndexSet::Build( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[], + const Simulation::AttributeIndexSet *inheritance + ) +{ + // + //------------------------------------------------------- + // Find out the highest message type we have to deal with + //------------------------------------------------------- + // + Check(this); + Check_Pointer(index_table); + entryCount = 0; + Simulation::AttributeID i; + for (i=0; i entryCount) + { + entryCount = index_table[i].entryID; + } + } + if (inheritance) + { + Check(inheritance); + if (entryCountentryCount) + { + entryCount = inheritance->entryCount; + } + #if DEBUG_LEVEL>0 + else if (entryCount > inheritance->entryCount) + { + i = inheritance->entryCount+1; + goto Check_Table; + } + #endif + } + else + { + Verify(entryCount == count); + #if DEBUG_LEVEL>0 + i = 1; +Check_Table: + while (i <= entryCount) + { + int j; + for (j=0; j count); + #endif + } + + // + //----------------------------------------------------------------------- + // Allocate the memory for the new handler set, and copy the inherited + // handlers to the new table. We are guaranteed to have enough space for + // the inherited table + //----------------------------------------------------------------------- + // + attributeIndex = new Simulation::IndexEntry[entryCount]; + Check_Pointer(attributeIndex); + Register_Pointer(attributeIndex); + i = 0; + if (inheritance) + { + for (; ientryCount; ++i) + { + attributeIndex[i] = inheritance->attributeIndex[i]; + } + } + + // + //---------------------------------------------------------------------- + // Step through the new table supplied, placing each handler in the slot + // determined by the message type + //---------------------------------------------------------------------- + // + for (i=0; i inheritance->entryCount); + attributeIndex[index_table[i].entryID-1] = index_table[i]; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation::AttributePointer + Simulation::AttributeIndexSet::Find(const char* attribute_name) const +{ + Check(this); + Check_Pointer(attribute_name); + + for (int attribute=0; attributeGetUpdateManager(); + Check(updater); + updater->RequestEncore(this, encore); +} + +#if defined(TEST_CLASS) && 0 + #include "model.tcp" +#endif diff --git a/MUNGA/SIMULATE.h b/MUNGA/SIMULATE.h new file mode 100644 index 0000000..ab8acf5 --- /dev/null +++ b/MUNGA/SIMULATE.h @@ -0,0 +1,387 @@ +#pragma once + +#include "state.h" +#include "receiver.h" +#include "time.h" +#include "resource.h" + +class Simulation__SharedData; +class Simulation__IndexData; +struct Simulation__IndexEntry; +class Simulation__AttributeIndexSet; +class MemoryStream; + +//########################################################################## +//################# Simulation::UpdateRecord ######################### +//########################################################################## + +struct Simulation__UpdateRecord +{ +public: + size_t recordLength; + Word subsystemID; + Word recordID; + Time timeStamp; + Enumeration simulationState; +}; + +//########################################################################## +//####################### Simulation ################################# +//########################################################################## + +class Simulation: + public Receiver +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + typedef Simulation__SharedData SharedData; + SharedData* + GetSharedData(); + + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +protected: + Simulation( + ClassID class_ID, + SharedData &shared_data + ); + +public: + ~Simulation(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + typedef Enumeration AttributeID; + typedef Simulation__IndexData IndexData; + typedef Simulation__IndexEntry IndexEntry; + typedef Simulation__AttributeIndexSet AttributeIndexSet; + typedef int Simulation::*AttributePointer; + + enum { + AnyAttributeID = 0, + SimulationStateAttributeID, + NextAttributeID + }; + + static const AttributePointer NullAttribute; + + void* + GetAttributePointer(AttributeID attribute); + void* + GetAttributePointer(const char* attribute_name); + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Simulation Support +// +public: + typedef void + (Simulation::*Performance)(Scalar time_slice); + typedef void + (Simulation::*Encore)(); + typedef Simulation__UpdateRecord UpdateRecord; + + void + SetPerformance(Performance performance) + {Check(this); activePerformance = performance;} + void + Perform(Scalar time_slice) + { + Check(this); + (this->*activePerformance)(time_slice); + } + + virtual void + PerformAndWatch( + const Time& till, + MemoryStream *update_stream + ); + + void + DoNothingOnce(Scalar time_slice); + void + DoNothing(Scalar time_slice); + + void + SetLastPerformance(const Time& when) + {Check(this); Check(&when); lastPerformance = when;} + void + RequestEncore(Encore encore); + + virtual void + ReadUpdateRecord(UpdateRecord *message); + virtual void + WriteUpdateRecord( + UpdateRecord *message, + int update_model + ); + void + WriteSimulationUpdate(MemoryStream *update_stream); + + enum { + DefaultUpdateModelBit=0, + NextUpdateModelBit + }; + + enum { + DefaultUpdateModelFlag = 1<= lastPerformance; + } + Logical + IsNonReplicantExecutable() + {Check(this); return (simulationFlags&DontExecuteFlag) == 0;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// State support +// +public: + enum { + DefaultState = 0, + StateCount + }; + + unsigned + GetSimulationState() + {Check(this); return simulationState.GetState();} + unsigned + GetOldSimulationState() + {Check(this); return simulationState.GetOldState();} + void + SetSimulationState(unsigned new_state) + {Check(this); simulationState.SetState(new_state);} + + StateIndicator + simulationState; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Watcher Support +// +public: + void + AddAudioWatcher(Component *watcher) + {Check(&audioWatcherSocket);audioWatcherSocket.Add(watcher);} + void + AddVideoWatcher(Component *watcher) + {Check(&videoWatcherSocket);videoWatcherSocket.Add(watcher);} + void + AddGaugeWatcher(Component *watcher) + {Check(&gaugeWatcherSocket);gaugeWatcherSocket.Add(watcher);} + + void + AddEffectWatcher(Component *watcher) + {Check(&effectWatcherSocket); effectWatcherSocket.Add(watcher);} + + void + ExecuteWatchers(); + +private: + SChainOf + audioWatcherSocket; + SChainOf + videoWatcherSocket; + SChainOf + gaugeWatcherSocket; + SChainOf + effectWatcherSocket; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Support +// +public: + Logical + TestInstance() const; + static Logical + TestClass(); +}; + +//########################################################################## +//################### Simulation::IndexEntry ######################### +//########################################################################## + +struct Simulation__IndexEntry +{ + Enumeration + entryID; + const char * + entryName; + Simulation::AttributePointer + entryAddress; +}; + +#define ATTRIBUTE_ENTRY(class,name,attribute)\ + {\ + class::name##AttributeID,\ + #name,\ + (Simulation::AttributePointer) &class::attribute\ + } + +//########################################################################## +//################# Simulation::AttributeIndexSet #################### +//########################################################################## + +class Simulation__AttributeIndexSet: + public Receiver::InheritanceSet +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + Simulation__AttributeIndexSet( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[], + const Simulation::AttributeIndexSet &inheritance + ) + {Build(count, index_table, &inheritance);} + + Simulation__AttributeIndexSet( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[] + ) + {Build(count, index_table, NULL);} + + Simulation__AttributeIndexSet() + {attributeIndex = NULL; entryCount = 0;} + + ~Simulation__AttributeIndexSet(); + +protected: + void + Build( + Simulation::AttributeID count, + const Simulation::IndexEntry index_table[], + const Simulation::AttributeIndexSet *inheritance + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AttributeIndexSet Functionality +// +protected: + Simulation::IndexEntry + *attributeIndex; + +public: + Simulation::AttributePointer + Find(Simulation::AttributeID attribute) const + { + Check(this); + Verify(attribute > 0); + if (attribute<=entryCount) + return attributeIndex[attribute-1].entryAddress; + else + return Simulation::NullAttribute; + } + Simulation::AttributePointer + Find(const char* attribute_name) const; + const Simulation::IndexEntry* + FindEntry(const char* attribute_name) const; + + static const Simulation::AttributeIndexSet + NullSet; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Support +// +public: + static Logical + TestClass(); +}; + +//########################################################################## +//################### Simulation::SharedData ######################### +//########################################################################## + +class Simulation__SharedData: + public Receiver::SharedData +{ +public: + Simulation__SharedData( + Derivation* derivation, + Receiver::MessageHandlerSet &message_handlers, + Simulation::AttributeIndexSet &attribute_index, + int state_count + ): + Receiver::SharedData(derivation, message_handlers), + activeAttributeIndex(&attribute_index), + stateCount(state_count) + {} + + Simulation::AttributeIndexSet* activeAttributeIndex; + int stateCount; +}; + +inline Simulation::SharedData* + Simulation::GetSharedData() + {return Cast_Object(SharedData*,sharedData);} diff --git a/MUNGA/SLOT.cpp b/MUNGA/SLOT.cpp new file mode 100644 index 0000000..9fd59cf --- /dev/null +++ b/MUNGA/SLOT.cpp @@ -0,0 +1,167 @@ +#include "munga.h" +#pragma hdrstop + +#include "slot.h" +#include "node.h" + +MemoryBlock *SlotLink::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(SlotLink), SLOTLINK_MEMORYBLOCK_ALLOCATION, SLOTLINK_MEMORYBLOCK_ALLOCATION, "SlotLink"); + return &allocatedMemory; +} + +// +//########################################################################### +// SlotLink +//########################################################################### +// +SlotLink::SlotLink( + Slot *slot, + Plug *plug +): + Link(slot, plug) +{ +} + +// +//########################################################################### +// ~SlotLink +//########################################################################### +// +SlotLink::~SlotLink() +{ + Slot *slot = Cast_Object(Slot*, socket); + + // + //------------------------------------------------- + // Make sure the link is not referenced by the slot + //------------------------------------------------- + // + Check(slot); + Verify(slot->slotLink == this); + slot->slotLink = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the slot at this point in + // time. + //------------------------------------------------------------- + // + if (slot->GetReleaseNode() != NULL) + { + Check(slot->GetReleaseNode()); + slot->GetReleaseNode()->ReleaseLinkHandler(slot, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + SlotLink::TestInstance() const +{ + Link::TestInstance(); + return True; +} + +// +//########################################################################### +// Slot +//########################################################################### +// +Slot::Slot( + Node *node +): + Socket(node) +{ + slotLink = NULL; +} + +// +//########################################################################### +// ~Slot +//########################################################################### +// +Slot::~Slot() +{ + SetReleaseNode(NULL); + if (slotLink != NULL) + { + Unregister_Object(slotLink); + delete slotLink; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Slot::TestInstance() const +{ + Socket::TestInstance(); + + if (slotLink != NULL) + { + Check(slotLink); + } + return True; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + Slot::Remove() +{ + if (slotLink != NULL) + { + Unregister_Object(slotLink); + delete slotLink; + slotLink = NULL; + } +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Slot::AddImplementation( + Plug *plug + ) +{ + Verify(slotLink == NULL); + slotLink = new SlotLink(this, plug); + Register_Object(slotLink); +} + +// +//########################################################################### +// GetCurrentPlug +//########################################################################### +// +Plug* + Slot::GetCurrentPlug() const +{ + if (slotLink != NULL) + { + Check(slotLink); + return slotLink->GetPlug(); + } + return NULL; +} diff --git a/MUNGA/SLOT.h b/MUNGA/SLOT.h new file mode 100644 index 0000000..c383bb4 --- /dev/null +++ b/MUNGA/SLOT.h @@ -0,0 +1,65 @@ +#pragma once + +#include "socket.h" +#include "memblock.h" + +class Slot; + +#define SLOTLINK_MEMORYBLOCK_ALLOCATION (100) + +class SlotLink : public Link +{ + friend class Slot; + +public: + ~SlotLink(); + Logical TestInstance() const; + +private: + SlotLink(Slot *slot, Plug *plug); + +private: + static MemoryBlock* GetAllocatedMemory(); + + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { return GetAllocatedMemory()->Delete(where); } +}; + +class Slot : public Socket +{ + friend class SlotLink; + +public: + Slot(Node *node); + ~Slot(); + + Logical TestInstance() const; + + void Remove(); + +protected: + void AddImplementation(Plug *plug); + Plug* GetCurrentPlug() const; + +private: + SlotLink *slotLink; +}; + +template class SlotOf : public Slot +{ +public: + SlotOf(Node *node); + ~SlotOf(); + + void Add(T plug) { AddImplementation(Cast_Object(Plug*, plug)); } + + T GetCurrent() const { return (T)GetCurrentPlug(); } +}; + +template SlotOf::SlotOf(Node *node) : Slot(node) +{ +} + +template SlotOf::~SlotOf() +{ +} \ No newline at end of file diff --git a/MUNGA/SOCKET.cpp b/MUNGA/SOCKET.cpp new file mode 100644 index 0000000..2f8a7ac --- /dev/null +++ b/MUNGA/SOCKET.cpp @@ -0,0 +1,256 @@ +#include "munga.h" +#pragma hdrstop + +#include "socket.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Socket ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Socket +//############################################################################# +// +Socket::Socket(Node *node) +{ + socketsNode = node; + // Warn(socketsNode == NULL); +} + +// +//############################################################################# +// ~Socket +//############################################################################# +// +Socket::~Socket() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + Socket::TestInstance() const +{ + return True; +} + +// +//############################################################################# +// AddImplementation +//############################################################################# +// +void + Socket::AddImplementation(Plug*) +{ + Fail("Socket::AddImplementation - Should never reach here"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ SocketIterator ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +SocketIterator::SocketIterator(Socket *socket) +{ + this->socket = socket; +} + +// +//############################################################################# +//############################################################################# +// +SocketIterator::~SocketIterator() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + SocketIterator::TestInstance() const +{ + return True; +} + +// +//############################################################################# +// Remove +//############################################################################# +// +void + SocketIterator::Remove() +{ + Fail("SocketIterator::Remove - Should never reach here"); +} + +// +//############################################################################# +// IsPlugMember +//############################################################################# +// +Logical + SocketIterator::IsPlugMember( + Plug *find_plug + ) +{ + Plug *plug; + + First(); + while ((plug = ReadAndNextPlug()) != NULL) + { + Check(plug); + if (plug == find_plug) + return True; + } + return False; +} + +// +//############################################################################# +// RemovePlug +//############################################################################# +// +void + SocketIterator::RemovePlug( + Plug *find_plug + ) +{ + Plug *plug; + + Check(find_plug); + First(); + while ((plug = GetCurrentPlug()) != NULL) + { + Check(plug); + if (plug == find_plug) + { + Remove(); + return; + } + Next(); + } +} + +// +//############################################################################# +// DeletePlugs +//############################################################################# +// +void + SocketIterator::DeletePlugs(Logical defeat_release_node) +{ + Plug *plug; + Node *save_release_node; + + if (defeat_release_node) + { + Check(socket); + save_release_node = socket->GetReleaseNode(); + socket->SetReleaseNode(NULL); + } + + First(); + while ((plug = ReadAndNextPlug()) != NULL) + { + Unregister_Object(plug); + delete plug; + } + #if 0 + while ((plug = GetCurrentPlug()) != NULL) + { + Unregister_Object(plug); + delete plug; + } + #endif + + if (defeat_release_node) + { + Check(socket); + socket->SetReleaseNode(save_release_node); + } +} + +// +//############################################################################# +// SendPlugCommand +//############################################################################# +// + +// Considering removal +#if 0 +int + SocketIterator::SendPlugCommand( + Plug::CommandID plugCommand, + void *info + ) +{ + int ret; + Plug *plug; + + First(); + while ((plug = GetCurrentPlug()) != NULL) + { + Check(plug); + if ( + (ret = plug->ReceivePlugCommand(plugCommand, info)) != + IteratorFunctionNullReturn + ) + return ret; + Next(); + } + return IteratorFunctionNullReturn; +} +#endif + +// +//############################################################################# +// RunIteratorFunction +//############################################################################# +// + +// Considering removal +#if 0 +int + SocketIterator::RunIteratorFunction( + IteratorFunction iteratorFunction, + void *info + ) +{ + int ret; + Plug *plug; + + Check_Pointer(iteratorFunction); + + First(); + while ((plug = GetCurrentPlug()) != NULL) + { + Check(plug); + if ( + (ret = (*iteratorFunction)(plug, info)) != + IteratorFunctionNullReturn + ) + return ret; + Next(); + } + return IteratorFunctionNullReturn; +} +#endif + +// +//############################################################################# +// InsertImplementation +//############################################################################# +// +void + SocketIterator::InsertImplementation(Plug*) +{ + // + // Should never reach here + // + Fail("SocketIterator::InsertImplementation - Should never reach here"); +} diff --git a/MUNGA/SOCKET.h b/MUNGA/SOCKET.h new file mode 100644 index 0000000..e5bb696 --- /dev/null +++ b/MUNGA/SOCKET.h @@ -0,0 +1,67 @@ +#pragma once + +#include "plug.h" + +class Node; + +class Socket SIGNATURED +{ +public: + virtual ~Socket(); + Logical TestInstance() const; + + void AddPlug(Plug *plug) { AddImplementation(plug); } + + Node *GetReleaseNode() { return socketsNode; } + void SetReleaseNode(Node *release_node) { socketsNode = release_node; } + +protected: + Socket(Node *node); + + virtual void AddImplementation(Plug *plug); + + Node *socketsNode; +}; + +#if 0 + typedef int (*IteratorFunction)(Plug *plug, void *info); + + const int IteratorFunctionNullReturn = 0; +#endif + +class SocketIterator : public Iterator +{ +public: + ~SocketIterator(); + Logical TestInstance() const; + + Plug *ReadAndNextPlug() { return (Plug*)ReadAndNextImplementation(); } + Plug *ReadAndPreviousPlug() { return (Plug*)ReadAndPreviousImplementation(); } + Plug *GetCurrentPlug() { return (Plug*)GetCurrentImplementation(); } + Plug *GetNthPlug(CollectionSize index) { return (Plug*)GetNthImplementation(index); } + + void InsertPlug(Plug *plug) { InsertImplementation(plug); } + + virtual void Remove(); + + Logical IsPlugMember(Plug *plug); + + void RemovePlug(Plug *plug); + + void DeletePlugs(Logical defeat_release_node = true); + +#if 0 + int SendPlugCommand(Plug::CommandID plugCommand, void *info); +#endif + +protected: + SocketIterator(Socket *socket); + +#if 0 + int RunIteratorFunction(IteratorFunction iteratorFunction, void *info); +#endif + + virtual void InsertImplementation(Plug*); + + Socket *socket; +}; \ No newline at end of file diff --git a/MUNGA/SPHERE.cpp b/MUNGA/SPHERE.cpp new file mode 100644 index 0000000..64fdf1a --- /dev/null +++ b/MUNGA/SPHERE.cpp @@ -0,0 +1,40 @@ +#include "munga.h" +#pragma hdrstop + +#include "sphere.h" + +// +//########################################################################### +//########################################################################### +// +Logical Sphere::Contains(const Point3D &A_Point) const +{ + Vector3D diff; + + diff.Subtract(center,A_Point); + return radius*radius >= diff.LengthSquared(); +} + +// +//########################################################################### +//########################################################################### +// +Logical Sphere::Intersects(const Sphere &sphere) const +{ + Vector3D temp; + Scalar r; + + r = radius + sphere.radius; + temp.Subtract(center, sphere.center); + return temp.LengthSquared() <= r*r; +} + +// +//########################################################################### +//########################################################################### +// +std::ostream& operator<<(std::ostream& Stream, const Sphere &A_Sphere) +{ + Stream << "\n\tSphere Centerpoint: " << A_Sphere.center; + return Stream << "\n\tRadius: " << A_Sphere.radius; +} diff --git a/MUNGA/SPHERE.h b/MUNGA/SPHERE.h new file mode 100644 index 0000000..635f97a --- /dev/null +++ b/MUNGA/SPHERE.h @@ -0,0 +1,25 @@ +#pragma once + +#include "point3d.h" + +class Plane; + +class Sphere SIGNATURED +{ + public: + Point3D center; + Scalar radius; + + Sphere() {} + Sphere(const Point3D &A_Point, Scalar Radius) : center(A_Point), radius(Radius) {} + Sphere(Scalar X, Scalar Y, Scalar Z, Scalar Radius) : center(X,Y,Z), radius(Radius) {} + + // + // Intersection functions + // + Logical Contains(const Point3D &point) const; + Logical Intersects(const Sphere &sphere) const; + Logical Intersects(const Plane &plane) const; + + friend std::ostream& operator<<(std::ostream& Stream, const Sphere &A_Sphere); +}; diff --git a/MUNGA/SPLINE.cpp b/MUNGA/SPLINE.cpp new file mode 100644 index 0000000..e32ddaa --- /dev/null +++ b/MUNGA/SPLINE.cpp @@ -0,0 +1,114 @@ +#include "munga.h" +#pragma once + +#include "spline.h" + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const volatile CubicCurve *) + { + return False; + } +#endif + +Logical CubicCurve::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CubicCurve::CubicCurve( + const Point3D& p1, + const Vector3D& r1, + const Point3D& p4, + const Vector3D& r4 +) +{ + Check_Pointer(this); + Check(&p1); + Check(&r1); + Check(&p4); + Check(&r4); + + // + //---------------------------------- + // Generate the hermite basis matrix + //---------------------------------- + // + basisMatrix(0,0) = 2.0f*(p1.x - p4.x) + r1.x + r4.x; + basisMatrix(0,1) = 2.0f*(p1.y - p4.y) + r1.y + r4.y; + basisMatrix(0,2) = 2.0f*(p1.z - p4.z) + r1.z + r4.z; + + basisMatrix(1,0) = 3.0f*(p4.x - p1.x) - 2.0f*r1.x - r4.x; + basisMatrix(1,1) = 3.0f*(p4.y - p1.y) - 2.0f*r1.y - r4.y; + basisMatrix(1,2) = 3.0f*(p4.z - p1.z) - 2.0f*r1.z - r4.z; + + basisMatrix(2,0) = r1.x; + basisMatrix(2,1) = r1.y; + basisMatrix(2,2) = r1.z; + + basisMatrix(3,0) = p1.x; + basisMatrix(3,1) = p1.y; + basisMatrix(3,2) = p1.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CubicCurve::CubicCurve( + const Point3D& p1, + const Point3D& p2, + const Point3D& p3, + const Point3D& p4 +) +{ + Check_Pointer(this); + Check(&p1); + Check(&p2); + Check(&p3); + Check(&p4); + + // + //--------------------------------- + // Generate the bezier basis matrix + //--------------------------------- + // + basisMatrix(0,0) = p4.x - p1.x + 3.0f*(p2.x - p3.x); + basisMatrix(0,1) = p4.y - p1.y + 3.0f*(p2.y - p3.y); + basisMatrix(0,2) = p4.z - p1.z + 3.0f*(p2.z - p3.z); + + basisMatrix(1,0) = 3.0f*(p1.x + p3.x) - 6.0f*p2.x; + basisMatrix(1,1) = 3.0f*(p1.y + p3.y) - 6.0f*p2.y; + basisMatrix(1,2) = 3.0f*(p1.z + p3.z) - 6.0f*p2.z; + + basisMatrix(2,0) = 3.0f*(p2.x - p1.x); + basisMatrix(2,1) = 3.0f*(p2.y - p1.y); + basisMatrix(2,2) = 3.0f*(p2.z - p1.z); + + basisMatrix(3,0) = p1.x; + basisMatrix(3,1) = p1.y; + basisMatrix(3,2) = p1.z; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CubicCurve::Evaluate( + Scalar t, + Point3D *p, + Vector3D *v + ) +{ + Check(this); + Check_Pointer(p); + Check_Pointer(v); + Verify(t >= 0.0f && t <= 1.0f); + + Point3D t_pos; + t_pos.z = t; + t_pos.y = t_pos.z * t; + t_pos.x = t_pos.y * t; + p->Multiply(t_pos, basisMatrix); + + Vector3D t_vec(3.0f*t*t, 2.0f*t, 1.0f); + v->Multiply(t_vec, basisMatrix); +} diff --git a/MUNGA/SPLINE.h b/MUNGA/SPLINE.h new file mode 100644 index 0000000..0b60f62 --- /dev/null +++ b/MUNGA/SPLINE.h @@ -0,0 +1,31 @@ +#pragma once + +#include "affnmtrx.h" + +class CubicCurve +{ +public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile CubicCurve *); + #endif + + CubicCurve( // Hermite form + const Point3D& p1, + const Vector3D& r1, + const Point3D& p4, + const Vector3D& r4 + ); + CubicCurve( // Bezier form + const Point3D& p1, + const Point3D& p2, + const Point3D& p3, + const Point3D& p4 + ); + + void Evaluate(Scalar t, Point3D *p, Vector3D *v); + + Logical TestInstance() const; + +protected: + AffineMatrix basisMatrix; +}; \ No newline at end of file diff --git a/MUNGA/SPOOLER.cpp b/MUNGA/SPOOLER.cpp new file mode 100644 index 0000000..8b65ac0 --- /dev/null +++ b/MUNGA/SPOOLER.cpp @@ -0,0 +1,311 @@ +#include "munga.h" +#pragma hdrstop + +#include "spooler.h" +#include "filestrm.h" + +//############################################################################# +//############################## SpoolFile ################################ +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile::SpoolFile( + void *stream_start, + size_t stream_size, + size_t initial_offset +): + MemoryStream(stream_start, stream_size, initial_offset) +{ + spoolState = Empty; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile::SpoolFile(SpoolFile& spool): + MemoryStream( + spool.streamStart, + spool.streamSize, + spool.GetBytesUsed() + ) +{ + spoolState = spool.spoolState; + Verify(spoolState == Playing); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile::~SpoolFile() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolFile::SaveAs(const char *file_name) +{ + FileStream output(file_name, True); + size_t length = GetBytesUsed(); + output << length; + Rewind(); + output.WriteBytes(GetPointer(), length); + output.Close(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolFile::Read(const char *file_name) +{ + FileStream input(file_name); + if (!input.IsFileOpened()) + { + spoolState = Empty; + return; + } + + // + //------------------------------- + // Figure out how big the file is + //------------------------------- + // + size_t spool_size = 0; + input >> spool_size; + if (spool_size > GetBytesRemaining() || !spool_size) + { + spoolState = Empty; + } + + // + //----------- + // Read it in + //----------- + // + else + { + input.ReadBytes(streamStart, spool_size); + streamSize = spool_size; + Rewind(); + spoolState = Stored; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolFile::SpoolPacket(NetworkPacket *packet) +{ + Check(this); + Check_Pointer(packet); + + // + //------------------------------------------------------------------------- + // Check to see if we are out of spool space. For now, if it happens, just + // die + //------------------------------------------------------------------------- + // + int length = + packet->messageData.messageLength + sizeof(NetworkPacketHeader); + int remaining = GetBytesRemaining(); + if (remaining < length) + { + DEBUG_STREAM << "Error: Spool file ran out of memory!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + // + //----------------------------------------------------- + // Copy into the memory stream, and advance the pointer + //----------------------------------------------------- + // + Mem_Copy(GetPointer(), packet, length, remaining); + AdvancePointer(length); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkPacket* + SpoolFile::NextPacket() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Check to see if anything is left in the spool. If only a partial message + // remains, die from an error + //------------------------------------------------------------------------- + // + if (!GetBytesRemaining()) + { + return NULL; + } + NetworkPacket *packet = (NetworkPacket*)GetPointer(); + int length = + packet->messageData.messageLength + sizeof(NetworkPacketHeader); + if (GetBytesRemaining() < length) + { + DEBUG_STREAM << "Error: Partial packet in spool file!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + return NULL; + } + + // + //----------------------------------------------------- + // Copy into the memory stream, and advance the pointer + //----------------------------------------------------- + // + AdvancePointer(length); + return (NetworkPacket*)GetPointer(); +} + +//############################################################################# +//################# MissionReviewApplicationManager ##################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MissionReviewApplicationManager::MissionReviewApplicationManager( + HINSTANCE hInstance, + HWND hWnd, + Scalar frame_rate, + int spool_count, + size_t spool_size +): + ApplicationManager(hInstance, hWnd, frame_rate) +{ + // + //-------------------------------------------------------- + // Allocate the space for the spool files and buffer table + //-------------------------------------------------------- + // + spoolCount = spool_count; + spoolSize = spool_size; + spoolBuffers = new char* [spoolCount]; + Register_Pointer(spoolBuffers); + spoolFiles = new SpoolFile* [spoolCount]; + Register_Pointer(spoolFiles); + + // + //-------------------------------------------------------- + // Allocate each spool buffer, and initial the spool files to none + //-------------------------------------------------------- + // + for (int i=0; ispoolState == SpoolFile::Empty) + { + spoolFiles[i]->spoolState = SpoolFile::Spooling; + return spoolFiles[i]; + } + } + + Fail("No spool files available!"); + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolFile* + MissionReviewApplicationManager::GetStoredSpoolFile(CString spoolFileName) +{ + for (int i=0; ispoolState == SpoolFile::Empty) + { + spoolFiles[i]->Read(spoolFileName); + if (spoolFiles[i]->spoolState == SpoolFile::Stored) + { + spoolFiles[i]->spoolState = SpoolFile::Playing; + return spoolFiles[i]; + } + return NULL; + } + } + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + MissionReviewApplicationManager::StoreSpoolFile(SpoolFile *spool_file) +{ + for (int i=0; ispoolState == SpoolFile::Spooling); + spoolFiles[i]->spoolState = SpoolFile::Stored; + + struct tm newtime; + __int64 ltime; + + // get local time + _time64(<ime); + + // get UTC time + _gmtime64_s(&newtime, <ime); + + char filename[2056]; + sprintf(filename, "SPOOLS\\%.4i_%.2i_%.2i_%.2i%.2i%.2i.spl", newtime.tm_year + 1900, newtime.tm_mon + 1, newtime.tm_mday, newtime.tm_hour, newtime.tm_min, newtime.tm_sec); + + spoolFiles[i]->SaveAs(filename); + + // now copy the new file over to last.spl + CopyFileA(filename, "last.spl", FALSE); + + spoolFiles[i]->Rewind(); + return; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + MissionReviewApplicationManager::ReleaseSpoolFile(SpoolFile *spool_file) +{ + for (int i=0; ispoolState != SpoolFile::Spooling); + spoolFiles[i]->spoolState = SpoolFile::Empty; + spoolFiles[i]->Rewind(); + return; + } + } +} diff --git a/MUNGA/SPOOLER.h b/MUNGA/SPOOLER.h new file mode 100644 index 0000000..28a3db6 --- /dev/null +++ b/MUNGA/SPOOLER.h @@ -0,0 +1,66 @@ +#pragma once + +#include "appmgr.h" + +//########################################################################## +//########################### SpoolFile ################################ +//########################################################################## + +class SpoolFile: + public MemoryStream +{ +public: + SpoolFile( + void *stream_start, + size_t stream_size, + size_t initial_offset=0 + ); + SpoolFile(SpoolFile& spool); + ~SpoolFile(); + + enum SpoolState { + Empty, + Spooling, + Stored, + Playing + }; + SpoolState + spoolState; + + void + SaveAs(const char *name); + void + Read(const char *name); + + void + SpoolPacket(NetworkPacket *packet); + NetworkPacket* + NextPacket(); +}; + +//########################################################################## +//############## MissionReviewApplicationManager ##################### +//########################################################################## + +class MissionReviewApplicationManager: + public ApplicationManager +{ +public: + MissionReviewApplicationManager(HINSTANCE hInstance, HWND hWnd, Scalar frame_rate, int spool_count, size_t spool_size); + ~MissionReviewApplicationManager(); + + SpoolFile* + GetEmptySpoolFile(); + SpoolFile* + GetStoredSpoolFile(CString spoolFileName); + void + StoreSpoolFile(SpoolFile *spool_file); + void + ReleaseSpoolFile(SpoolFile *spool_file); + +protected: + int spoolCount; + SpoolFile **spoolFiles; + char **spoolBuffers; + size_t spoolSize; +}; diff --git a/MUNGA/SRTSKT.cpp b/MUNGA/SRTSKT.cpp new file mode 100644 index 0000000..0e3d65f --- /dev/null +++ b/MUNGA/SRTSKT.cpp @@ -0,0 +1,44 @@ +#include "munga.h" +#pragma hdrstop + +#include "srtskt.h" + +SortedSocket::SortedSocket(Node *node, Logical has_unique_entries) : SafeSocket(node) +{ + hasUniqueEntries = has_unique_entries; +} + +SortedSocket::~SortedSocket() +{ +} + +void SortedSocket::AddValueImplementation(Plug*, const void*) +{ + Fail("SortedSocket::AddValueImplementation - Should never reach here"); +} + +Plug* SortedSocket::FindImplementation(const void*) +{ + Fail("SortedSocket::FindImplementation - Should never reach here"); + return NULL; +} + +SortedIterator::SortedIterator(SortedSocket *sortedSocket) : SafeIterator(sortedSocket) +{ +} + +SortedIterator::~SortedIterator() +{ +} + +Plug* SortedIterator::FindImplementation(const void*) +{ + Fail("SortedIterator::FindImplementation - Should never reach here"); + return NULL; +} + +void* SortedIterator::GetValueImplementation() +{ + Fail("SortedIterator::GetValueImplementation - Should never reach here"); + return NULL; +} diff --git a/MUNGA/SRTSKT.h b/MUNGA/SRTSKT.h new file mode 100644 index 0000000..733a032 --- /dev/null +++ b/MUNGA/SRTSKT.h @@ -0,0 +1,39 @@ +#pragma once + +#include "sfeskt.h" + +class SortedSocket : public SafeSocket +{ +public: + ~SortedSocket(); + + void AddValuePlug(Plug *plug, const void *value) { AddValueImplementation(plug, value); } + + Plug *FindPlug(const void *value) { return FindImplementation(value); } + +protected: + SortedSocket(Logical has_unique_entries = true); + SortedSocket(Node *node, Logical has_unique_entries = true); + + Logical HasUniqueEntries() { return hasUniqueEntries; } + + virtual void AddValueImplementation(Plug *plug, const void *value); + + virtual Plug *FindImplementation(const void *value); + +private: + Logical hasUniqueEntries; +}; + +class SortedIterator : public SafeIterator +{ +public: + ~SortedIterator(); + + virtual Plug *FindImplementation(const void *value); + + virtual void *GetValueImplementation(); + +protected: + SortedIterator(SortedSocket *sortedSocket); +}; \ No newline at end of file diff --git a/MUNGA/STATE.h b/MUNGA/STATE.h new file mode 100644 index 0000000..fb720d0 --- /dev/null +++ b/MUNGA/STATE.h @@ -0,0 +1,62 @@ +#pragma once + +#include "cmpnnt.h" +#include "schain.h" + +class StateIndicator : public Node +{ +public: + StateIndicator(); + StateIndicator(unsigned max_states); + StateIndicator(const StateIndicator &state_indicator); + ~StateIndicator(); + + StateIndicator& operator=(const StateIndicator&); + + Logical operator==(const StateIndicator&) const; + +public: + unsigned GetState() + { + Check(this); + return currentState; + } + unsigned GetOldState() + { + Check(this); + return oldState; + } + void SetState(unsigned new_state); + +protected: + unsigned stateCount, oldState, currentState; + +public: + void AddAudioWatcher(Component *watcher) + { + Check(&audioWatcherSocket); + audioWatcherSocket.Add(watcher); + } + void AddVideoWatcher(Component *watcher) + { + Check(&videoWatcherSocket); + videoWatcherSocket.Add(watcher); + } + void AddGaugeWatcher(Component *watcher) + { + Check(&gaugeWatcherSocket); + gaugeWatcherSocket.Add(watcher); + } + +private: + SChainOf audioWatcherSocket; + SChainOf videoWatcherSocket; + SChainOf gaugeWatcherSocket; + +public: + friend std::ostream& operator << (std::ostream &strm, const StateIndicator &state_indicator); + +public: + Logical TestInstance() const; + static Logical TestClass(); +}; \ No newline at end of file diff --git a/MUNGA/STYLE.H b/MUNGA/STYLE.H new file mode 100644 index 0000000..026c3ce --- /dev/null +++ b/MUNGA/STYLE.H @@ -0,0 +1,139 @@ +#pragma once + +#include + +#if !defined(DEBUG_STREAM) + #define DEBUG_STREAM std::cout +#endif + +#if !defined(Verify) + #if !defined(DEBUG_LEVEL) + #define DEBUG_LEVEL 0 + #endif + #if DEBUG_LEVEL<1 + #include "debugoff.h" + #elif DEBUG_LEVEL<2 + #include "debug1on.h" + #elif DEBUG_LEVEL<3 + #include "debug2on.h" + #else + #include "debug3on.h" + #endif +#endif + +#if defined(__BCPLUSPLUS__) + extern int _matherr(struct exception *a); +#endif + +extern int Fpu_Ok(); +extern void Verify_Failed(char *message, char *file, int line); +//extern void Fail_To_Debugger(char *message, char *file, int line); +//extern void PostQuitMessage(int exit_code); + +class Signature +{ +private: +#if DEBUG_LEVEL>0 + enum Mark + { + ok, + destroyed, + corrupted, + noMagic=(int)0xAB135795L, + magic=(int)0xFFED1231L + } mark; +#endif + +protected: + Signature(); + ~Signature(); + +public: + friend int Is_Signature_Bad(const volatile Signature *p); +}; + +#if defined(USE_SIGNATURE) + #define SIGNATURED : public Signature +#else + #define SIGNATURED + #define Is_Signature_Bad(p) (false) +#endif + +//############# +//# MACROS # +//############# + +#define ELEMENTS(Array) (sizeof(Array)/sizeof(*Array)) + +#if defined(TEST_CLASS) + #define Test(c)\ + if (!(c))\ + {\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#c" failed!\07\n";\ + return false;\ + } + + #define Test_And_Dump(c, v)\ + if (!(c))\ + {\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#c" failed!\07\n";\ + DEBUG_STREAM << __FILE__"(" << __LINE__ << "): "#v" = " << (v) << '\n';\ + return false;\ + } + + #define Test_Message(m) (DEBUG_STREAM << m) + + #define Test_Branch_On() Fail("First visit of branch") + #define Test_Branch_Off() +#else + #define Test(c) + #define Test_And_Dump(c,v) + #define Test_Message(m) +#endif + +//################ +//# ENUMERATIONS # +//################ + +enum +{ + False = 0, + True = 1 +}; + +//########### +//# CASTING # +//########### + +#define SKIPPY_CAST(Type,var) (*((Type*)&(var))) + +//############# +//# TEMPLATES # +//############# + +//#include + +#define SMALL (1e-4f) + +#define Abs(value) ((value>0) ? value : -value) +#define Clamp(v,f,c) (v = ((vc) ? c : v))) +#define Max_Clamp(v,c) (v = ((v>c) ? c : v)) +#define Is_Many_Bits(value) (Lowbit(value)^value) +#define Low_Bit(value) (value & (-value)) +#define Min_Clamp(v,f) (v = ((vb) ? a : b) +#define Min(a,b) ((aSMALL) + +//############ +//# TYPEDEFS # +//############ + +typedef int Logical; +typedef unsigned __int8 Byte; +typedef unsigned __int16 Word; +typedef unsigned __int32 LWord; + +typedef int Enumeration; + +#include "memreg.h" \ No newline at end of file diff --git a/MUNGA/SUBSYSTM.cpp b/MUNGA/SUBSYSTM.cpp new file mode 100644 index 0000000..04c73ae --- /dev/null +++ b/MUNGA/SUBSYSTM.cpp @@ -0,0 +1,291 @@ +#include "munga.h" +#pragma hdrstop + +#include "subsystm.h" +#include "fileutil.h" +#include "notation.h" +#include "namelist.h" + +Subsystem::SharedData + Subsystem::DefaultData( + Subsystem::GetClassDerivations(), + Subsystem::GetMessageHandlers(), + Subsystem::GetAttributeIndex(), + Subsystem::StateCount + ); + +Derivation* Subsystem::GetClassDerivations() +{ + static Derivation classDerivations(Simulation::GetClassDerivations(), "Subsystem"); + return &classDerivations; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Subsystem::WriteUpdateRecord( + UpdateRecord *message, + int update_model + ) +{ + Check(this); + Check_Pointer(message); + + Simulation::WriteUpdateRecord(message, update_model); + message->subsystemID = (Word)(subsystemID+1); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Subsystem::Subsystem( + Entity *entity, + int subsystem_ID, + SubsystemResource *model, + SharedData &shared_data +): + Simulation(model->classID, shared_data) +{ + owningEntity = entity; + subsystemID = subsystem_ID; + size_t name_size = strlen(model->subsystemName)+1; + subsystemName = new char[name_size]; + Register_Pointer(subsystemName); + Str_Copy(subsystemName, model->subsystemName, name_size); + segmentIndex = model->segmentIndex; + simulationFlags = model->subsystemFlags; + damageZone = NULL; +} + +Subsystem::Subsystem( + Entity *entity, + int subsystem_id, + const char* subsystem_name, + RegisteredClass::ClassID class_id, + SharedData &shared_data +): + Simulation(class_id, shared_data) +{ + owningEntity = entity; + subsystemID = subsystem_id; + size_t name_size = strlen(subsystem_name)+1; + subsystemName = new char[name_size]; + Register_Pointer(subsystemName); + Str_Copy(subsystemName, subsystem_name, name_size); + segmentIndex = -1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Subsystem::~Subsystem() +{ + Unregister_Pointer(subsystemName); + delete[] subsystemName; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + Subsystem::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ) +{ + Check(model_file); + Check_Pointer(model_name); + Check_Pointer(subsystem_name); + Check_Pointer(subsystem_resource); + Check(subsystem_file); + Check_Pointer(directories); + + for(int ii=0; ii<(sizeof(subsystem_resource->subsystemName));ii++) + { + subsystem_resource->subsystemName[ii] = '\0'; + } + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + + if (strlen(subsystem_name) > sizeof(subsystem_resource->subsystemName)-1) + { + DEBUG_STREAM << subsystem_name << " is too long. Maximum name size is " + << (sizeof(subsystem_resource->subsystemName)-1) << " character!\n"; + return False; + } + Str_Copy( + subsystem_resource->subsystemName, + subsystem_name, + sizeof(subsystem_resource->subsystemName)-1 + ); + + // + //------------------------------------------ + // If any flags were specified, read them in + //------------------------------------------ + // + const char* flags; + subsystem_resource->subsystemFlags = 0; + if( + subsystem_file->GetEntry( + subsystem_name, + "SubsystemFlags", + &flags + ) + ) + { + if (!strcmp(flags,"DontReplicateFlag")) + { + subsystem_resource->subsystemFlags |= Subsystem::DontReplicateFlag; + } + else + { + DEBUG_STREAM << subsystem_name << " has an unknown subsystem flag!\n" << std::flush; + return False; + } + } + + // + //-------------------------------------------------- + // Get the Segment Name to locate in the .skl file + //-------------------------------------------------- + // + const char* desired_page; + subsystem_resource->segmentIndex = -1; + if( + subsystem_file->GetEntry( + subsystem_name, + "SegmentPageName", + &desired_page + ) + ) + { + subsystem_resource->segmentIndex = + Get_Segment_Index(model_file, model_name, directories, desired_page); + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Subsystem::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Subsystem::GenerateFault(int /*fault_index*/) +{ + Check(this); + Check_Fpu(); + return False; // fault not generated +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + Get_Segment_Index( + NotationFile *model_file, + const char* model_name, + const ResourceDirectories *directories, + const char *desired_page + ) +{ + //------------------------------------------ + // Get the Segment Index from the .skl file + //------------------------------------------ + // + const char* skl_entry; + if ( + !model_file->GetEntry( + "video", + "skeleton", + &skl_entry + ) + ) + { + std::cerr << model_name << " is missing .skl file specification!\n"; + return -1; + } + + char *skl_filename = + MakePathedFilename(directories->videoDirectory, skl_entry); + Register_Pointer(skl_filename); + + NotationFile *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + if (!skl_file->PageCount()) + { + std::cerr << skl_filename << " is empty or missing!\n"; +Dump_And_Die: + Unregister_Pointer(skl_filename); + delete[] skl_filename; + Unregister_Object(skl_file); + delete skl_file; + return ResourceDescription::NullResourceID; + } + + // + // Make a pagelist of all the segments + // + NameList *segment_pages = skl_file->MakePageList(); + Register_Object(segment_pages); + + NameList::Entry *segment_entry = segment_pages->GetFirstEntry(); + char + segment_page_name[32]; + int + segment_index = -1; + int + current_index = 0; + while(segment_entry) + { + Str_Copy( + segment_page_name, + segment_entry->GetName(), + sizeof(segment_page_name) + ); + // + //--------------------------------------- + // skip labonly and damagezones + //--------------------------------------- + // + if( + (strcmp(segment_page_name, "LAB_ONLY") == 0) || + (strcmp(segment_page_name,"DamageZones") ==0) + ) + { + segment_entry = segment_entry->GetNextEntry(); + continue; + } + // + //------------------------------------- + // if names match save the index + //------------------------------------- + // + else if(strcmp(segment_page_name,desired_page) ==0) + { + segment_index = current_index; + break; + } + ++current_index; + segment_entry = segment_entry->GetNextEntry(); + } + if(segment_index == -1) + { + std::cout<TakeDamage(damage); + } + +DamageZone *damageZone; + +virtual void + DeathReset(int /*reset_command*/) + {} + +virtual void + DeathShutdown(int /*shutdown_command*/) + {} +}; + +//########################################################################## +// Tool support +// +int +Get_Segment_Index( + NotationFile *model_file, + const char* model_name, + const ResourceDirectories *directories, + const char *desired_page +); diff --git a/MUNGA/TABLE.cpp b/MUNGA/TABLE.cpp new file mode 100644 index 0000000..e86eea1 --- /dev/null +++ b/MUNGA/TABLE.cpp @@ -0,0 +1,791 @@ +#include "munga.h" +#pragma hdrstop + +#include "table.h" +#include "node.h" + +#define VERIFY_INDEX(x) Verify(0 <= (x) && (x) < numItems) + +// +//########################################################################### +// TABLEENTRY +//########################################################################### +// + +TableEntry::TableEntry( + Table *table, + Plug *plug +): + Link(table, plug) +{ +} + +TableEntry::~TableEntry() +{ + Table *table = Cast_Object(Table*, socket); + IteratorPosition index; + + // + //-------------------------------------- + // Find the link in the table and remove + //-------------------------------------- + // + index = table->SearchForTableEntry(this); + table->RemoveNthTableEntry(index); + + // + //-------------------------------------------- + // Notify iterators that link is being deleted + //-------------------------------------------- + // + table->SendIteratorMemo(PlugRemoved, &index); + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (table->GetReleaseNode() != NULL) + { + Check(table->GetReleaseNode()); + table->GetReleaseNode()->ReleaseLinkHandler(table, plug); + } +} + +// +//########################################################################### +// TABLE +//########################################################################### +// + +// +//########################################################################### +// Table +//########################################################################### +// +Table::Table( + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + array = NULL; + numItems = 0; +} + +// +//########################################################################### +// ~Table +//########################################################################### +// +Table::~Table() +{ + SetReleaseNode(NULL); + while (numItems > 0) + { + Check_Pointer(array); + Check(array[0]); + + Unregister_Object(array[0]); + delete array[0]; + } + Verify(numItems == 0); + Verify(array == NULL); +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Table::TestInstance() const +{ + SortedSocket::TestInstance(); + + if (numItems > 0 || array != NULL) + { + Verify(numItems > 0); + Check_Pointer(array); + } + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Table::AddImplementation(Plug *plug) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + Table::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + TableEntry *link; + + /* + * Verify that value has not been added + */ + Verify(HasUniqueEntries() ? (SearchForValue(value) == TableNullIndex) : (Logical)True); + + /* + * Make new table entry + */ + link = MakeTableEntry(plug, value); + Register_Object(link); + + /* + * Add, sort and send memo to iterators to update references + */ + AddTableEntry(link); + SortTableEntries(); + SendIteratorMemo(PlugAdded, link); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + Table::FindImplementation( + const void *value + ) +{ + IteratorPosition index; + + if ((index = SearchForValue(value)) != TableNullIndex) + { + Check_Pointer(array); + VERIFY_INDEX(index); + Check(array[index]); + + return array[index]->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// MakeTableEntry +//########################################################################### +// +TableEntry* + Table::MakeTableEntry( + Plug*, + const void* + ) +{ + Fail("Table::MakeTableEntry - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// CompareTableEntries +//########################################################################### +// +int + Table::CompareTableEntries( + TableEntry*, + TableEntry* + ) +{ + Fail("Table::CompareTableEntries - Should never reach here"); + return 0; +} + +// +//########################################################################### +// CompareValueToTableEntry +//########################################################################### +// +int + Table::CompareValueToTableEntry( + const void*, + TableEntry* + ) +{ + Fail("Table::CompareValueToTableEntry - Should never reach here"); + return 0; +} + +// +//########################################################################### +// AddTableEntry +//########################################################################### +// +void + Table::AddTableEntry( + TableEntry *link + ) +{ + Check(link); + +#if 0 + numItems++; + if (array == NULL) + { + array = (TableEntry**)malloc(sizeof(TableEntry*)); + Register_Pointer(array); + } + else + { + Unregister_Pointer(array); + array = (TableEntry**)realloc(array, numItems * sizeof(TableEntry*)); + Register_Pointer(array); + } +#else + CollectionSize new_num_items = numItems+1; + if (array == NULL) + { + Verify(new_num_items == 1); + array = new TableEntry*[new_num_items]; + Register_Pointer(array); + } + else + { + TableEntry **new_array = new TableEntry*[new_num_items]; + Register_Pointer(new_array); + + Mem_Copy( + new_array, + array, + numItems * sizeof(TableEntry*), + new_num_items * sizeof(TableEntry*) + ); + Unregister_Pointer(array); + delete[] array; + array = new_array; + } + numItems = new_num_items; +#endif + Check_Pointer(array); + + array[numItems - 1] = link; +} + +// +//########################################################################### +// SortTableEntries +//########################################################################### +// +void + Table::SortTableEntries() +{ + size_t i, j; + TableEntry *temp; + + for (i = 1; i < numItems; i++) + { + Check_Pointer(array); + Verify(i < numItems); + + temp = array[i]; + j = i; + + Verify(j-1 < numItems); + + while (CompareTableEntries(array[j-1], temp) > 0) + { + Verify(j < numItems); + Verify(j-1 < numItems); + + array[j] = array[j-1]; + j--; + if (j < 1) + break; + } + + Verify(j < numItems); + array[j] = temp; + } +} + +// +//########################################################################### +// SearchForValue +//########################################################################### +// +IteratorPosition + Table::SearchForValue( + const void *value + ) +{ + size_t n = numItems; + size_t i = 0, j; + IteratorPosition k; + + while (i < n) + { + j = (i + n - 1) >> 1; + + Check_Pointer(array); + Verify(j < numItems); + + if ((k = CompareValueToTableEntry(value, array[j])) == 0) + return j; + + if (k < 0) + n = j; + else + i = j + 1; + } + return TableNullIndex; +} + +// +//########################################################################### +// SearchForTableEntry +//########################################################################### +// +IteratorPosition + Table::SearchForTableEntry( + TableEntry *link + ) +{ + CollectionSize i; + + for (i = 0; i < numItems; i++) + { + Check_Pointer(array); + VERIFY_INDEX(i); + + if (array[i] == link) + return i; + } + return TableNullIndex; +} + +// +//########################################################################### +// RemoveNthTableEntry +//########################################################################### +// +void + Table::RemoveNthTableEntry( + CollectionSize index + ) +{ + char *itemPtr, *lastItem; + size_t width; + + Check_Pointer(array); + VERIFY_INDEX(index); + + /* + * Find the location of the item + */ + itemPtr = (char*)&array[index]; + Check_Pointer(itemPtr); + + /* + * Remove the item from the array + */ + width = sizeof(void*); + lastItem = (char*)array + (numItems - 1) * width; + + if (itemPtr < lastItem) + { + memmove(itemPtr, itemPtr + width, (size_t)(lastItem - itemPtr)); + } + + /* + * Resize the array + */ +#if 0 + numItems--; + if (numItems == 0) + { + Unregister_Pointer(array); + free(array); + array = NULL; + } + else + { + Unregister_Pointer(array); + array = (TableEntry**)realloc(array, numItems * sizeof(TableEntry*)); + Register_Pointer(array); + } +#else + CollectionSize new_num_items = numItems-1; + if (new_num_items == 0) + { + Unregister_Pointer(array); + delete[] array; + array = NULL; + } + else + { + TableEntry **new_array = new TableEntry*[new_num_items]; + Register_Pointer(new_array); + + Mem_Copy( + new_array, + array, + new_num_items * sizeof(TableEntry*), + new_num_items * sizeof(TableEntry*) + ); + Unregister_Pointer(array); + delete[] array; + array = new_array; + } + numItems = new_num_items; +#endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableIterator inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if DEBUG_LEVEL>0 + TableEntry* + TableIterator::NthEntry( + CollectionSize index + ) + { + Check_Pointer(array); + Verify(0 <= index && index < numItems); + Check(array[index]); + + return array[index]; + } +#endif + +// +//########################################################################### +// TableIterator +//########################################################################### +// +TableIterator::TableIterator(Table *table): + SortedIterator(table) +{ + array = table->array; + numItems = table->numItems; + + if (array != NULL) + currentPosition = 0; + else + currentPosition = TableNullIndex; +} + +// +//########################################################################### +//########################################################################### +// +TableIterator::~TableIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + TableIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + if (array != NULL) + { + Check_Pointer(array); + Verify(0 < numItems); + Verify(currentPosition < numItems); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + TableIterator::First() +{ + if (array != NULL) + currentPosition = 0; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + TableIterator::Last() +{ + if (array != NULL) + currentPosition = numItems - 1; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + TableIterator::Next() +{ + IncrementPosition(); +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + TableIterator::Previous() +{ + DecrementPosition(); +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *TableIterator::ReadAndNextImplementation() +{ + if (currentPosition != TableNullIndex) + { + Plug *plug; + + plug = NthEntry(currentPosition)->GetPlug(); + IncrementPosition(); + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *TableIterator::ReadAndPreviousImplementation() +{ + if (currentPosition != TableNullIndex) + { + Plug *plug; + + plug = NthEntry(currentPosition)->GetPlug(); + DecrementPosition(); + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *TableIterator::GetCurrentImplementation() +{ + if (currentPosition != TableNullIndex) + { + return NthEntry(currentPosition)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + TableIterator::GetSize() +{ + return numItems; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *TableIterator::GetNthImplementation( + CollectionSize index + ) +{ + if (index < numItems) + { + return NthEntry(currentPosition = index)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + TableIterator::Remove() +{ + if (currentPosition != TableNullIndex) + { + Unregister_Object(NthEntry(currentPosition)); + delete NthEntry(currentPosition); + } +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug + *TableIterator::FindImplementation( + const void *value + ) +{ + IteratorPosition index; + Table *table = Cast_Object(Table*, socket); + + if ((index = table->SearchForValue(value)) != TableNullIndex) + { + if (!table->HasUniqueEntries()) + { + while ( + index-1 >= 0 && + table->CompareTableEntries(NthEntry(index-1), NthEntry(index)) == 0 + ) + { + index--; + } + } + return (NthEntry(currentPosition = index)->GetPlug()); + } + currentPosition = TableNullIndex; + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + TableIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + switch (memo) + { + case PlugAdded: + { + Table *table = Cast_Object(Table*, socket); + + Check(table); + array = table->array; + numItems = table->numItems; + + // + // If a plug is added before or at the current position then + // the current position should be incremented one forward, + // otherwise, no action is necessary + // + TableEntry *link; + IteratorPosition index; + + link = Cast_Object(TableEntry*, content); + index = table->SearchForTableEntry(link); + VERIFY_INDEX(index); + if (index <= currentPosition) + { + currentPosition++; + } + Verify(TableNullIndex <= currentPosition && currentPosition < numItems); + } + break; + + case PlugRemoved: + { + Table *table = Cast_Object(Table*, socket); + + Check(table); + array = table->array; + numItems = table->numItems; + + // + // If a plug is removed before the current position then decrement + // the current position, else if the current position is at the end + // of the table then decrement the counter + // + IteratorPosition index; + + Check_Pointer(content); + index = *(IteratorPosition*)content; + if (index < currentPosition) + { + currentPosition--; + } + else if (numItems <= currentPosition) + { + currentPosition--; + } + Verify(TableNullIndex <= currentPosition && currentPosition < numItems); + } + break; + #if 0 + { + IteratorPosition index; + + Check_Pointer(content); + index = *(IteratorPosition*)content; + + array = Cast_Object(Table*, socket)->array; + numItems = Cast_Object(Table*, socket)->numItems; + + /* + * Decrement counter, if at 0 this will automatically become + * TableNullIndex + */ + if (index < currentPosition) + { + currentPosition--; + } + else if (numItems <= currentPosition) + { + currentPosition--; + } + + Verify(TableNullIndex <= currentPosition && currentPosition < numItems); + break; + } + #endif + } +} + +#if defined(TEST_CLASS) +# include "table.tcp" +#endif diff --git a/MUNGA/TABLE.h b/MUNGA/TABLE.h new file mode 100644 index 0000000..e45f1d8 --- /dev/null +++ b/MUNGA/TABLE.h @@ -0,0 +1,273 @@ +#pragma once + +#include "srtskt.h" +#include "memblock.h" + +class Table; + +class TableEntry : public Link +{ +public: + TableEntry(Table *table, Plug *plug); + ~TableEntry(); +}; + +#define TABLEENTRY_MEMORYBLOCK_ALLOCATION (100) + +template class TableEntryOf : public TableEntry +{ +public: + TableEntryOf(Table *table, Plug *plug, const V &value); + ~TableEntryOf(); + + void* operator new(size_t); + void operator delete(void *where); + + V GetValue() { return value; } + V* GetValuePointer() { return &value; } + +private: + static MemoryBlock *allocatedMemory; + static CollectionSize allocationCount; + + V value; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableEntryOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +template MemoryBlock* TableEntryOf::allocatedMemory = NULL; +template CollectionSize TableEntryOf::allocationCount = 0; + +template TableEntryOf::TableEntryOf(Table *table, Plug *plug, const V &value) + : TableEntry(table, plug) +{ + this->value = value; +} + +template TableEntryOf::~TableEntryOf() +{ +} + +template void* TableEntryOf::operator new(size_t) +{ + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = new MemoryBlock(sizeof(TableEntryOf), TABLEENTRY_MEMORYBLOCK_ALLOCATION, TABLEENTRY_MEMORYBLOCK_ALLOCATION, "TableEntryOf"); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); +} + +template void TableEntryOf::operator delete(void *where) +{ + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); +} + +const IteratorPosition TableNullIndex = -1; + +class Table : public SortedSocket +{ + friend class TableEntry; + friend class TableIterator; + +public: + Table(Node *node, Logical has_unique_entries); + ~Table(); + + Logical TestInstance() const; + static Logical TestClass(); + static Logical ProfileClass(); + +protected: + void AddImplementation(Plug *plug); + void AddValueImplementation(Plug *plug, const void *value); + Plug *FindImplementation(const void *value); + +private: + virtual TableEntry *MakeTableEntry(Plug *plug, const void *value); + + virtual int CompareTableEntries(TableEntry *entry1, TableEntry *entry2); + + virtual int CompareValueToTableEntry(const void *value, TableEntry *entry); + + void AddTableEntry(TableEntry *entry); + void SortTableEntries(); + IteratorPosition SearchForValue(const void *value); + IteratorPosition SearchForTableEntry(TableEntry *entry); + void RemoveNthTableEntry(CollectionSize index); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + TableEntry **array; + CollectionSize numItems; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableOf ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +template class TableOf : public Table +{ +public: + TableOf(Node *node, Logical has_unique_entries); + ~TableOf(); + + void AddValue(T plug, const V &value) { AddValueImplementation(plug, &value); } + + T Find(const V &value) { return (T)FindImplementation(&value); } + +private: + TableEntry* MakeTableEntry(Plug *plug, const void *value) { return new TableEntryOf(this, plug, *(V*)value); } + int CompareTableEntries(TableEntry *entry1, TableEntry *entry2); + int CompareValueToTableEntry(const void *value, TableEntry *entry); +}; + +template TableOf::TableOf(Node *node, Logical has_unique_entries) + : Table(node, has_unique_entries) +{ +} + +template TableOf::~TableOf() +{ +} + +#if 0 + template int TableOf::CompareTableEntries(TableEntry *entry1, TableEntry *entry2) + { + V result = (V)(Cast_Object(TableEntryOf*, entry1)->GetValue() - Cast_Object(TableEntryOf*, entry2)->GetValue()); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } +#else + template int TableOf::CompareTableEntries(TableEntry *entry1, TableEntry *entry2) + { + V *ptr1 = Cast_Object(TableEntryOf*, entry1)->GetValuePointer(); + V *ptr2 = Cast_Object(TableEntryOf*, entry2)->GetValuePointer(); + + Check_Pointer(ptr1); + Check_Pointer(ptr2); + + if (*ptr1 == *ptr2) + return 0; + else + return ((*ptr1 > *ptr2) ? 1 : -1); + } +#endif + +#if 0 + template int TableOf::CompareValueToTableEntry(const void *value, TableEntry *link) + { + Check_Pointer(value); + + V result = (V)(*(V*)value - Cast_Object(TableEntryOf*, link)->GetValue()); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } +#else + template int TableOf::CompareValueToTableEntry(const void *value, TableEntry *link) + { + Check_Pointer(value); + + V *ptr = Cast_Object(TableEntryOf*, link)->GetValuePointer(); + Check_Pointer(ptr); + + if (*(V*)value == *ptr) + return 0; + else + return (*(V*)value > *ptr) ? 1 : -1; + } +#endif + +class TableIterator : public SortedIterator +{ +public: + TableIterator(Table *table); + ~TableIterator(); + Logical TestInstance() const; + + void First(); + void Last(); + void Next(); + void Previous(); + CollectionSize GetSize(); + void Remove(); + +protected: + void* ReadAndNextImplementation(); + void* ReadAndPreviousImplementation(); + void* GetCurrentImplementation(); + void* GetNthImplementation(CollectionSize index); + Plug* FindImplementation(const void *value); + + TableEntry* GetCurrentEntry() { return NthEntry(currentPosition); } + +private: + void ReceiveMemo(IteratorMemo memo, void *content); + + TableEntry* NthEntry(CollectionSize index) + #if DEBUG_LEVEL>0 + ; + #else + { return array[index]; } + #endif + + void IncrementPosition() + { + if (++currentPosition >= numItems) + currentPosition = TableNullIndex; + } + void DecrementPosition() + { + if (--currentPosition < 0) + currentPosition = TableNullIndex; + } + + TableEntry **array; + CollectionSize numItems; + IteratorPosition currentPosition; +}; + +template class TableIteratorOf : public TableIterator +{ +public: + TableIteratorOf(TableOf *table); + TableIteratorOf(TableOf &table); + ~TableIteratorOf(); + + T ReadAndNext() { return (T)ReadAndNextImplementation(); } + T ReadAndPrevious() { return (T)ReadAndPreviousImplementation(); } + T GetCurrent() { return (T)GetCurrentImplementation(); } + T GetNth(CollectionSize index) { return (T)GetNthImplementation(index); } + T Find(const V &value) { return (T)FindImplementation(&value); } + V GetValue() { return Cast_Object(TableEntryOf*, GetCurrentEntry())->GetValue(); } +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TableIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +template TableIteratorOf::TableIteratorOf(TableOf *table) : TableIterator(table) +{ +} + +template TableIteratorOf::TableIteratorOf(TableOf &table) : TableIterator(&table) +{ +} + +template TableIteratorOf::~TableIteratorOf() +{ +} \ No newline at end of file diff --git a/MUNGA/TEAM.cpp b/MUNGA/TEAM.cpp new file mode 100644 index 0000000..02256bf --- /dev/null +++ b/MUNGA/TEAM.cpp @@ -0,0 +1,203 @@ +#include "munga.h" +#pragma hdrstop + +#include "team.h" +#include "app.h" +#include "nttmgr.h" + +//############################################################################# +//############################### Team ################################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Team::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(), "Team"); + return &classDerivations; +} + +Team::SharedData + Team::DefaultData( + Team::GetClassDerivations(), + Team::MessageHandlers, + Team::GetAttributeIndex(), + Team::StateCount, + (Team::MakeHandler)Team::Make + ); +//############################################################################# +// Attribute Support +// + +const Team::IndexEntry + Team::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Team, TeamName, teamName), + ATTRIBUTE_ENTRY(Team, TeamScore, teamScore) +}; + +Team::AttributeIndexSet& Team::GetAttributeIndex() +{ + static Team::AttributeIndexSet attributeIndex(ELEMENTS(Team::AttributePointers), + Team::AttributePointers, + Entity::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Message Support +// + +const Receiver::HandlerEntry + Team::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Team, Score) +}; + +Receiver::MessageHandlerSet + Team::MessageHandlers( + ELEMENTS(Team::MessageHandlerEntries), + Team::MessageHandlerEntries, + Entity::GetMessageHandlers() + ); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Team::ScoreMessageHandler(ScoreMessage *score_message) +{ + Check(this); + Check(score_message); + + teamScore += score_message->scoreAward; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Team::TeamSimulation( + Scalar // time_slice + ) +{ + Check(this); + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Team::Team( + MakeMessage *creation_message, + SharedData &shared_data +) : + Entity (creation_message, shared_data) +{ + Str_Copy(teamName, creation_message->teamName, sizeof(teamName)); + + teamScore = creation_message->initialScore; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Add this to the Entity Group of Teams + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(application); + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *team_group = entity_manager->UseGroup("Teams"); + Check(team_group); + team_group->Add(this); + + SetValidFlag(); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Team::~Team() +{ + +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Team* + Team::Make(MakeMessage *creation_message) +{ + Check_Fpu(); + return new Team(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Team::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories +) +{ + Check(creation_message); + Check(model_file); + Check_Pointer(directories); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + return False; + } + + creation_message->messageLength = sizeof(Team::MakeMessage); + creation_message->classToCreate = TeamClassID; + creation_message->instanceFlags = MasterInstance | TrappedFlag | MapFlag; + Str_Copy(creation_message->teamName, "DEFUALT", sizeof(creation_message->teamName)); + + char *p; +#if 0 + // + //~~~~~~~~~~~~~~~ + // Get the TeamID + //~~~~~~~~~~~~~~~ + // + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "teamID missing!\n"; + return False; + } + creation_message->teamID = atoi(p); +#endif + + // + //~~~~~~~~~~~~~~~~~~~~~~ + // Get the Initial Score + //~~~~~~~~~~~~~~~~~~~~~~ + // + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "InitialScore missing!\n"; + return False; + } + creation_message->initialScore = atoi(p); + + + // + //~~~~~~~~~~~~~~~ + // Get the TeamName + //~~~~~~~~~~~~~~~ + // + if ((p = strtok(NULL, ",")) == NULL) + { + std::cerr << "teamName missing!\n"; + return False; + } + Str_Copy(creation_message->teamName,p, sizeof(creation_message->teamName)); + + + + return True; +} + +Logical + Team::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/TEAM.h b/MUNGA/TEAM.h new file mode 100644 index 0000000..bc76d39 --- /dev/null +++ b/MUNGA/TEAM.h @@ -0,0 +1,178 @@ +#pragma once + +#include "entity.h" + +//########################################################################## +//################# Team__MakeMessage ########################## +//########################################################################## + +class Team__MakeMessage : + public Entity::MakeMessage +{ + public: + + char + teamName[64]; + + int + initialScore; + + + + Team__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + char *team_name + ) : + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ) + { + Str_Copy(teamName, team_name, sizeof(teamName)); + } + +}; +//########################################################################## +//################# Team__ScoreMessage ########################## +//########################################################################## + +class Team__ScoreMessage : + public Entity::Message +{ + public: + + Scalar + scoreAward; + + Team__ScoreMessage( + Receiver::MessageID message_ID, + size_t length, + Scalar score + ): + Entity::Message(message_ID, length), + scoreAward(score) + {} +}; +//########################################################################## +//######################## CLASS Team ################################ +//########################################################################## +class Team : + public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + + static Derivation *GetClassDerivations(); + + static SharedData + DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// + + public: + + enum { + ScoreMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef Team__ScoreMessage ScoreMessage; + + void + ScoreMessageHandler(ScoreMessage *message); + + private: + + static const HandlerEntry MessageHandlerEntries[]; + + protected: + + static MessageHandlerSet MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// + private: + + static const IndexEntry + AttributePointers[]; + + protected: + + //static AttributeIndexSet AttributeIndex; + static AttributeIndexSet& GetAttributeIndex(); + + public: + + enum { + TeamNameAttributeID = Entity::NextAttributeID, + TeamScoreAttributeID, + NextAttributeID + }; + + char + teamName[64]; + + Scalar + teamScore; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// + public: + + typedef void + (Team::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + virtual void + TeamSimulation(Scalar time_slice); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction / Destruction Support +// +public: + + typedef Team__MakeMessage MakeMessage; + + Team( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + + ~Team(); + + Logical + TestInstance() const; + + static Team* + Make(MakeMessage *creation_message); + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); +}; diff --git a/MUNGA/TERRAIN.cpp b/MUNGA/TERRAIN.cpp new file mode 100644 index 0000000..720e1ef --- /dev/null +++ b/MUNGA/TERRAIN.cpp @@ -0,0 +1,303 @@ +#include "munga.h" +#pragma hdrstop + +#include "terrain.h" +#include "boxsolid.h" +#include "app.h" +#include "interest.h" + +//############################################################################# +//############################### Terrain ################################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Terrain::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(), "Terrain"); + return &classDerivations; +} + +Terrain::SharedData + Terrain::DefaultData( + Terrain::GetClassDerivations(), + Terrain::GetMessageHandlers(), + Terrain::GetAttributeIndex(), + Terrain::StateCount, + (Entity::MakeHandler)Terrain::Make + ); + +//############################################################################# +// Attribute Support +// +const Terrain::IndexEntry + Terrain::AttributePointers[]= +{ + { + Terrain::LocalScaleAttributeID, + "LocalScale", + (Entity::AttributePointer)&Terrain::localScale + } +}; + +Terrain::AttributeIndexSet& Terrain::GetAttributeIndex() +{ + static Terrain::AttributeIndexSet attributeIndex(ELEMENTS(Terrain::AttributePointers), + Terrain::AttributePointers, + Entity::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Terrain::Terrain( + Terrain::MakeMessage *creation_message, + Terrain::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + localScale = creation_message->localScale; + SetValidFlag(); + + // + //--------------------------------------------------------------------- + // For now, load in the collision resources into the tree pointed to by + // this resource + //--------------------------------------------------------------------- + // + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + ResourceDescription *res = + res_file->SearchList( + resourceID, + ResourceDescription::BoxedSolidStreamResourceType + ); + + collisionVolumes = NULL; + if (res) + { + Check(res); + res->Lock(); + InterestManager *interest_mgr = + application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = + interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + BoxedSolidResource* solids = + (BoxedSolidResource*)res->resourceAddress; + int size = res->resourceSize / sizeof(BoxedSolidResource); + Dump(localOrigin); + while (size--) + { + // + // Don't forget about scaling... + // + BoxedSolidResource rot_box; + rot_box.Instance(*solids,localOrigin); + collisionVolumes = + BoxedSolid::MakeBoxedSolid(&rot_box, this, collisionVolumes); + Register_Object(collisionVolumes); + tree->Add(collisionVolumes, rot_box.sliceExtents); + ++solids; + } + res->Unlock(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Terrain::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + return false; + } + + creation_message->messageLength = sizeof(MakeMessage); + creation_message->classToCreate = TerrainClassID; + creation_message->instanceFlags = HermitInstance|TrappedFlag; + + char *p; + if ((p = strtok(NULL, " ")) == NULL) + { + std::cerr << "Scale missing!\n"; + return false; + } + creation_message->localScale = atof(p); + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Terrain* + Terrain::Make(Terrain::MakeMessage *creation_message) +{ + return new Terrain(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Terrain::~Terrain() +{ + BoxedSolid *box = collisionVolumes; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } +} + +Logical + Terrain::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +//######################### UnscalableTerrain ########################### +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* UnscalableTerrain::GetClassDerivations() +{ static Derivation classDerivations(Terrain::GetClassDerivations(), "UnscalableTerrain"); + return &classDerivations; +} + + +UnscalableTerrain::SharedData + UnscalableTerrain::DefaultData( + UnscalableTerrain::GetClassDerivations(), + UnscalableTerrain::GetMessageHandlers(), + UnscalableTerrain::GetAttributeIndex(), + UnscalableTerrain::StateCount, + (Entity::MakeHandler)UnscalableTerrain::Make + ); + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +UnscalableTerrain::UnscalableTerrain( + UnscalableTerrain::MakeMessage *creation_message, + UnscalableTerrain::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + + // + //--------------------------------------------------------------------- + // For now, load in the collision resources into the tree pointed to by + // this resource + //--------------------------------------------------------------------- + // + SetValidFlag(); + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + ResourceDescription *res = + res_file->SearchList( + resourceID, + ResourceDescription::BoxedSolidStreamResourceType + ); + collisionVolumes = NULL; + + if (res) + { + Check(res); + res->Lock(); + InterestManager *interest_mgr = + application->GetInterestManager(); + Check(interest_mgr); + InterestZone *zone = + interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoxedSolidTree* tree = zone->GetCollisionRoot(); + Check(tree); + BoxedSolidResource* solids = + (BoxedSolidResource*)res->resourceAddress; + int size = res->resourceSize / sizeof(BoxedSolidResource); + while (size--) + { + BoxedSolidResource rot_box; + rot_box.Instance(*solids,localOrigin); + collisionVolumes = + BoxedSolid::MakeBoxedSolid(&rot_box, this, collisionVolumes); + Register_Object(collisionVolumes); + tree->Add(collisionVolumes, rot_box.sliceExtents); + ++solids; + } + res->Unlock(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + UnscalableTerrain::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + return false; + } + + creation_message->classToCreate = UnscalableTerrainClassID; + creation_message->instanceFlags = HermitInstance|TrappedFlag; + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +UnscalableTerrain* + UnscalableTerrain::Make(UnscalableTerrain::MakeMessage *creation_message) +{ + return new UnscalableTerrain(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +UnscalableTerrain::~UnscalableTerrain() +{ + BoxedSolid *box = collisionVolumes; + while (box) + { + BoxedSolid *next_box = box->GetNextSolid(); + Unregister_Object(box); + delete box; + box = next_box; + } +} + +Logical + UnscalableTerrain::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/TERRAIN.h b/MUNGA/TERRAIN.h new file mode 100644 index 0000000..7c0d6e8 --- /dev/null +++ b/MUNGA/TERRAIN.h @@ -0,0 +1,164 @@ +#pragma once + +#include "entity.h" + +class BoxedSolid; + +//########################################################################## +//##################### Terrain::MakeMessage ########################## +//########################################################################## + +class Terrain__MakeMessage: + public Entity::MakeMessage +{ +public: + Scalar + localScale; + + Terrain__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + Scalar scale + ): + Entity::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + EntityID::Null, + resource_ID, + instance_flags, + origin + ), + localScale(scale) + {} +}; + +//########################################################################## +//########################### Terrain ################################ +//########################################################################## + +class Terrain: + public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +typedef Terrain__MakeMessage MakeMessage; + +#if 0 +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + LocalScaleAttributeID = Entity::NextAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + Scalar localScale; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + static Terrain* + Make(MakeMessage *creation_message); + // + // Warning... This function requires a properly set up strtok!!!! + // + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + Terrain( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~Terrain(); + + Logical + TestInstance() const; + +protected: + BoxedSolid *collisionVolumes; +}; + +//########################################################################## +//###################### UnscalableTerrain ########################### +//########################################################################## + +class UnscalableTerrain: + public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + static UnscalableTerrain* + Make(MakeMessage *creation_message); + + // + // Warning... This function requires a properly set up strtok!!!! + // + static Logical + CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + UnscalableTerrain( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~UnscalableTerrain(); + + Logical + TestInstance() const; + +protected: + BoxedSolid *collisionVolumes; +}; diff --git a/MUNGA/TESTALL.cpp b/MUNGA/TESTALL.cpp new file mode 100644 index 0000000..8134ea6 --- /dev/null +++ b/MUNGA/TESTALL.cpp @@ -0,0 +1,166 @@ +#include "munga.h" +#pragma hdrstop + +#include "namelist.h" +#include "notation.h" +// +//------------------------------------------------- +// Math +//------------------------------------------------- +// +#include "rect2d.h" +#include "angle.h" +#include "random.h" +#include "vector4d.h" +#include "rotation.h" +#include "origin.h" +#include "linmtrx.h" +#include "matrix.h" +#include "unitvec.h" +#include "ray.h" +#include "normal.h" +// +//---------------- +// Spatial library +//---------------- +// +#include "boxsolid.h" +// +//------------------ +// Connection Engine +//------------------ +// +#include "vchain.h" +#include "tree.h" +#include "table.h" +#include "hash.h" +#include "time.h" +#include "receiver.h" + +// #define RUN_APPLICATION + +char GlobalEggFileName[80]; + +int main() +{ + #if defined(TEST_CLASS) + // + //----------------------- + // Test NameList classes + //----------------------- + // + #if 1 + #if 1 + ObjectNameList::TestClass(); + NameList::TestClass(); + AlphaNameList::TestClass(); + NotationFile::TestClass(); + #endif + + #if 1 + ResourceFile::TestClass(); + StreamableResourceFile::TestClass(); + #endif + + // + //------------------ + // Test string class + //------------------ + // + #if 1 + CString::TestClass(); + #endif + + // + //---------------- + // Test Math brick + //---------------- + // + #if 1 + RandomGenerator::TestClass(); + Radian::TestClass(); + Degree::TestClass(); + SinCosPair::TestClass(); + Vector3D::TestClass(); + LBE3Vector3D::TestClass(); + TIVector3D::TestClass(); + Vector4D::TestClass(); + Point3D::TestClass(); + UnitVector::TestClass(); + Ray::TestClass(); + EulerAngles::TestClass(); + Quaternion::TestClass(); + Origin::TestClass(); + AffineMatrix::TestClass(); + LinearMatrix::TestClass(); + Matrix4x4::TestClass(); + Normal::TestClass(); + Rectangle2D::TestClass(); + #endif + + // + //----------------- + // Test spatializer + //----------------- + // + #if 1 + BoundingBox::TestClass(); + BoxedSolid::TestClass(); + #endif + + // + //------------------ + // Test time manager + //------------------ + // + #if 1 + Time::TestClass(); + #endif + + // + //------------------------ + // Test connection library + //------------------------ + // + #if 1 + Chain::TestClass(); + SChain::TestClass(); + VChain::TestClass(); + Tree::TestClass(); + Table::TestClass(); + Hash::TestClass(); + #endif + + // + //------------------ + // Test Memory brick + //------------------ + // + #if 1 + MemoryBlock::TestClass(); + MemoryStack::TestClass(); + #endif + + // + //---------------------------- + // Test dynamic dispatch brick + //---------------------------- + // + #if 1 + MessageTap::TestClass(); + Receiver::MessageHandlerSet::TestClass(); + Derivation::TestClass(); + Receiver::TestClass(); + #endif + #endif + + // + //-------------------------------------------- + // Stop registering, and tell us about its use + //-------------------------------------------- + // + Tell("Exiting\n"); + #endif + + return 0; +} diff --git a/MUNGA/TIME.cpp b/MUNGA/TIME.cpp new file mode 100644 index 0000000..dc6f012 --- /dev/null +++ b/MUNGA/TIME.cpp @@ -0,0 +1,117 @@ +#include "munga.h" +#pragma hdrstop + +#include "time.h" + +//############################################################################# +//########################### System Clock ############################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void SystemClock::TogglePause() +{ + // + //-------------------------------------------------------------------- + // If the clock is currently paused, figure out how long it was paused + // and add that to the pause delay + //-------------------------------------------------------------------- + // + if (timer.pauseStart) + { + timer.pauseTime += GetRTC() - timer.pauseStart; + timer.pauseStart = 0; + } + else + { + //-------------------------------------------------------- + // Otherwise, start pausing by marking what time it is now + //-------------------------------------------------------- + timer.pauseStart = GetRTC(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +volatile Time& Now() +{ + static Time result; + + // + //------------------------------------------------- + // If we are in pause mode, return the paused clock + //------------------------------------------------- + // + if (SystemClock::timer.pauseStart) + { + result = SystemClock::timer.pauseStart; + } + else + { + //---------------------------------------------------------------- + // Otherwise, return the timer minus the amount of pause time lost + //---------------------------------------------------------------- + result = SystemClock::GetRTC() - SystemClock::timer.pauseTime; + } + + return result; +} + + +double HiResNow() +{ + return SystemClock::GetHiRes(); +} + +__int64 HiResNowTicks() +{ + return SystemClock::GetHiResTicks(); +} + +__int64 HiResCounterFreq() +{ + return SystemClock::perfCounterFreq; +} +//############################################################################# +//############################### Time ################################## +//############################################################################# + +Time Time::Null(SystemClock::timer); + +#if defined(USE_SIGNATURE) + int Is_Signature_Bad(const volatile Time *) + { + return false; + } +#endif + +// +//############################################################################# +//############################################################################# +// +Logical Time::TestInstance() const volatile +{ + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +void Convert_From_Ascii(const char *str, Time *time) +{ + Check_Pointer(str); + Check_Signature(time); + + Scalar seconds; + + seconds = atof(str); + *time = seconds; + Check(time); +} + +#if defined(TEST_CLASS) + #include "time.tcp" +#endif diff --git a/MUNGA/TIME.h b/MUNGA/TIME.h new file mode 100644 index 0000000..0e99309 --- /dev/null +++ b/MUNGA/TIME.h @@ -0,0 +1,170 @@ +#pragma once + +#include "scalar.h" + +class Time; + +//########################################################################## +//######################## System Clock ############################## +//########################################################################## + +class SystemClock SIGNATURED +{ + friend class Time; + +public: + friend float Get_Frame_Percent_Used(); + friend volatile Time& Now(); + friend double HiResNow(); + friend __int64 HiResNowTicks(); + friend __int64 HiResCounterFreq(); + static void TogglePause(); + + SystemClock(); + ~SystemClock() { Shutdown(); } + static SystemClock timer; + void Shutdown(); + static long GetTicksPerSecond() { return ticksPerSecond; } + +protected: + long pauseStart; + long pauseTime; + static long ticksPerSecond; + static __int64 perfCounterFreq; + + static long GetRTC(); + static double GetHiRes(); + static __int64 GetHiResTicks(); +}; + +//########################################################################## +//############################ Time ################################## +//########################################################################## + +class Time +{ +public: + long ticks; + static Time Null; + + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Time *p); + #endif + + Time() {} + Time(const volatile Time &t) : ticks(t.ticks) {} + Time(SystemClock&) : ticks(0) {} + + Time& operator=(const volatile Time &t) + { + Check_Pointer(this); + Check(&t); + ticks = t.ticks; + return *this; + } + Time& operator=(long t) + { + Check_Pointer(this); + ticks = t; + return *this; + } + Time& operator=(Scalar t) + { + Check_Pointer(this); + ticks = Float_To_Time(t); + return *this; + } + + operator Scalar() const volatile + { + Check(this); + return Time_To_Float(ticks); + } + operator long() const volatile + { + Check(this); + return ticks; + } + + Scalar operator-(const volatile Time &t) const volatile + { + Check(this); + Check(&t); + return Time_To_Float(ticks - t.ticks); + } + + Time& operator+=(const volatile Time &t) + { + Check(this); + Check(&t); + ticks += t.ticks; + return *this; + } + Time& operator+=(Scalar t) + { + Check(this); + ticks += Float_To_Time(t); + return *this; + } + Time& operator+=(long t) + { + Check(this); + ticks += t; + return *this; + } + Time& operator-=(const volatile Time &t) + { + Check(this); + Check(&t); + ticks -= t.ticks; + return *this; + } + Time& operator-=(Scalar t) + { + Check(this); + ticks -= Float_To_Time(t); + return *this; + } + + Logical operator<(const volatile Time &t) const volatile + { + Check(this); + Check(&t); + return ticks < t.ticks; + } + Logical operator<=(const volatile Time &t) const volatile + { + Check(this); + Check(&t); + return ticks <= t.ticks; + } + Logical operator>(const volatile Time &t) const volatile + { + Check(this); + Check(&t); + return ticks > t.ticks; + } + Logical operator>=(const volatile Time &t) const volatile + { + Check(this); + Check(&t); + return ticks >= t.ticks; + } + + friend std::ostream& operator <<(std::ostream& stream, const volatile Time& t) + { + Check(&t); + return stream << t.ticks; + } + + Logical TestInstance() const volatile; + static Logical TestClass(); + +private: + static long Float_To_Time(Scalar t) { return (long)(t * SystemClock::ticksPerSecond + 0.5f); } + static Scalar Time_To_Float(long t) { return (Scalar)(t / (float)SystemClock::ticksPerSecond); } +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Time functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void Convert_From_Ascii(const char *str, Time *time); diff --git a/MUNGA/TIMESTUB.cpp b/MUNGA/TIMESTUB.cpp new file mode 100644 index 0000000..8294b40 --- /dev/null +++ b/MUNGA/TIMESTUB.cpp @@ -0,0 +1,44 @@ +#include "munga.h" +#pragma hdrstop + +#include "time.h" + +//############################################################################# +//########################### System Clock ############################## +//############################################################################# +// +SystemClock SystemClock::timer; +long SystemClock::ticksPerSecond = 1000; + +long SystemClock::GetRTC() +{ + static long time=0L; + return time++; +} + +double SystemClock::GetHiRes() +{ + static __int64 time = 0; + return (double)time++; +} + +__int64 SystemClock::GetHiResTicks() +{ + static __int64 time = 0; + return time++; +} + +SystemClock::SystemClock() +{ + pauseStart = 0L; + pauseTime = 0L; +} + +void SystemClock::Shutdown() +{ +} + +float Get_Frame_Percent_Used() +{ + return 0.5f; +} \ No newline at end of file diff --git a/MUNGA/TOOL.cpp b/MUNGA/TOOL.cpp new file mode 100644 index 0000000..636629c --- /dev/null +++ b/MUNGA/TOOL.cpp @@ -0,0 +1,862 @@ +#include "munga.h" +#pragma hdrstop + +#include "tool.h" +#include "fileutil.h" +#include "audtools.h" +#include "registry.h" +#include "boxsolid.h" +#include "namelist.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + GetId(char *string) +{ + int id; + + char *number = strstr( string, "/id:"); + if (number != NULL) + { + number += 4; + id = atoi(number); + return id; + } + else + { + return -1; + } +} + +Logical + PlatformTool::ConvertStringToModeMask( + const char */*string*/, + ModeMask */*returned_value_ptr*/ + ) +{ + Fail("PlatformTool::ConvertStringToModeMask method not overridden!"); + return False; +} + +Logical + PlatformTool::ConvertStringToTechStatus( + const char */*string*/, + int */*returned_value_ptr*/ + ) +{ + Fail("PlatformTool::ConvertStringToTechStatus method not overridden!"); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + ApplicationTool::BuildResources( + int argc, + char **argv, + AudioCreateSymbols &create_symbols, + Byte minor_version + ) +{ + char temp_name[200]; + const char *Res_Name; + char *resfilename; + char ops_filename[150]; + char dirgauge[150]; + char dircollision[150]; + char dirmodel[150]; + char dirmap[150]; + char diraudio[150]; + char dirvideo[150]; + char diranim[150]; + + char short_name[100]; + char long_name[200]; + char id_name[100]; + + const char *tempdir; + + ResourceDirectories + resource_directories; + + NotationFile *ops_file = new NotationFile(); + Register_Object(ops_file); + + StreamableResourceFile file; + + if (argc < 2) + { + DEBUG_STREAM << "Usage: buildXX resource.bld [res2.bld ...]\n" << std::flush; + return 1; + } + + verboseMode = False; + labOnly = False; + + // + // Write audio symbols, add static audio resources + // + create_symbols.Execute(); + platformTool->CreateStaticAudioStreamResource(&file); + + // + //------------------------------------ + // Arguments are only build files, + // so step thru them + //------------------------------------ + // + for(int arg_number = 1; arg_number < argc; ++arg_number) + { + + strcpy(temp_name,argv[arg_number]); + NotationFile *notation_file; + + WorkingDirectory = MakeWorkingDirectory(temp_name); + Register_Pointer(WorkingDirectory); + + char *filename = MakePathedFilename(WorkingDirectory, temp_name); + Register_Pointer(filename); + + notation_file = new NotationFile(filename); + Register_Object(notation_file); + + labOnly |= notation_file->IsMarkedLabOnly(); + + if (!notation_file->PageCount()) + { + DEBUG_STREAM << filename << " does not exist! " << std::endl << std::flush; + Unregister_Object(notation_file); + delete notation_file; + Stop_Registering(); + return 0; + } + else if (!notation_file->PageExists("resource")) + { + DEBUG_STREAM << filename << " Not a valid resource list" << std::endl << std::flush; + Unregister_Object(notation_file); + delete notation_file; + Stop_Registering(); + return 0; + } + + Unregister_Pointer(filename); + delete filename; + + // + //----------------------------------------------- + // If this is the first file check + // for required info, if not skip this + // section so required info isn't overwritten + //----------------------------------------------- + // + + if(arg_number == 1) + { + + + // + // Check verboseMode + // + + const char *verb_string; + + if(notation_file->GetEntry("resource","verbose",&verb_string)) + { + if(!stricmp(verb_string, "true")) + { + verboseMode = True; + } + } + + //--------------------------------- + // Set up directories + //-------------------------------- + + if(!notation_file->GetEntry("resource","dirmap",&tempdir)) + { + DEBUG_STREAM << "No map directory specified!!!" << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + strcpy(dirmap, tempdir); + + if(!notation_file->GetEntry("resource","dirmodel", &tempdir)) + { + DEBUG_STREAM << "No model directory specified!!!" << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + strcpy(dirmodel, tempdir); + + if(!notation_file->GetEntry("resource","dircollision", &tempdir)) + { + DEBUG_STREAM << "No collision directory specified!!!" << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + strcpy(dircollision, tempdir); + + + const char + *vp, + *version_string; + Byte version[2] = {0,0}; + + notation_file->GetEntry("resource","diraudio", &tempdir); + if (tempdir) + { + strcpy(diraudio, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'diraudio'!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + notation_file->GetEntry("resource","dirvideo", &tempdir); + if (tempdir) + { + strcpy(dirvideo, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'dirvideo'!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + notation_file->GetEntry("resource","diranimation", &tempdir); + if (tempdir) + { + strcpy(diranim, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'diranimation'!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + notation_file->GetEntry("resource","dirgauge", &tempdir); + if (tempdir) + { + strcpy(dirgauge, tempdir); + } + else + { + DEBUG_STREAM << "No directory specified for 'gauge'!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + resource_directories.collisionDirectory = dircollision; + resource_directories.modelDirectory = dirmodel; + resource_directories.mapDirectory = dirmap; + resource_directories.audioDirectory = diraudio; + resource_directories.videoDirectory = dirvideo; + resource_directories.animationDirectory = diranim; + resource_directories.gaugeDirectory = dirgauge; + + //------------------------- + // Get version info + //------------------------- + + + if (!notation_file->GetEntry("release","version", &version_string)) + { + DEBUG_STREAM << "No version number in build!!!!" << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + version[0] = (Byte)atoi(version_string); + + vp = strchr(version_string, '.'); + + if (vp) + { + vp++; + version[1] = (Byte)atoi(vp); + } + + //------------------------- + // Get Resource Name + //------------------------- + + if(!notation_file->GetEntry("resource","name",&Res_Name)) + { + DEBUG_STREAM << "No resource file specified!!!" << std::endl << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + resfilename = MakePathedFilename(WorkingDirectory, Res_Name); + Register_Pointer(resfilename); + + strcpy(ops_filename, Res_Name); + char *p = ops_filename; + + p += strlen(ops_filename); + p -= 4; + *p = '\0'; + + + + //================================ + // Set ops_file "res name" + // write maps and write models + // can use this for ops file + // format. + //================================ + + ops_file->SetEntry("resource", "res name", ops_filename); + ops_file->AppendEntry("resource", NULL, (char *)NULL); + + strcat(ops_filename, ".ops"); + + file.versionArray[1] = version[0]; + file.versionArray[2] = version[1]; + file.versionArray[3] = minor_version; + } + + // + //--------------------------- + // Now step thru each entry + // in every build file + //--------------------------- + // + + NameList *entry_list = + notation_file->MakeEntryList("resource"); + Register_Object(entry_list); + NameList::Entry *entry = entry_list->GetFirstEntry(); + + const char *entry_data; + + int pre_allocated = 0; + + while (entry != NULL) + { + + entry_data = entry->GetName(); + if (entry_data == NULL) + { + entry = entry->GetNextEntry(); + continue; + } + + entry_data = entry->GetChar(); + if (entry_data == NULL) + { + entry = entry->GetNextEntry(); + continue; + } + + strcpy(id_name, entry_data); + int id = GetId(id_name); + if ( id != -1) + { + if(arg_number > 1) + { + + Fail("Manual ResourceID's not allowed in second build files!"); + + } + + if (id > pre_allocated) + { + pre_allocated = id; + } + } + + entry = entry->GetNextEntry(); + } + + // + // pre_allocated number.... + // + file.PreAllocateIDs(pre_allocated); + + + + entry = entry_list->GetFirstEntry(); + while (entry != NULL) + { + + entry_data = entry->GetName(); + + if (entry_data == NULL) + { + entry = entry->GetNextEntry(); + continue; + } + + if (!stricmp(entry_data, "LAB_ONLY")) + { + labOnly = True; + entry = entry->GetNextEntry(); + continue; + } + else if (!stricmp(entry_data, "map")) + { + + const char *q = entry->GetChar(); + strcpy(long_name, q); + + + int id = GetId(long_name); + if (id != -1) + { + + // + // Strip id number off + // + + char *p = strchr(long_name, '\t'); + if (p) + { + *p = '\0'; + } + else + { + char *p = strchr(long_name, ' '); + *p = '\0'; + } + } + + + // + // open mapname + // + + char *filename = MakePathedFilename(resource_directories.mapDirectory, long_name); + Register_Pointer(filename); + + DEBUG_STREAM << "Opening Map " << filename << std::endl << std::flush; + + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + StripDirectory(long_name); + strcpy(short_name, long_name); + + + if (new_notation_file->PageCount()) + { + if ( + !WriteMaps( + short_name, + new_notation_file, + ops_file, + &file, + &resource_directories, + id + ) + ) + { + DEBUG_STREAM << filename << " Did not work!!!! " << std::endl << std::flush; + + } + } + else + { + DEBUG_STREAM << filename << " Does not exist! " << std::endl << std::flush; + } + + + Unregister_Pointer(filename); + delete filename; + Unregister_Object(new_notation_file); + delete new_notation_file; + } + else if (!stricmp(entry_data, "model")) + { + + strcpy(long_name, entry->GetChar()); + + int id = GetId(long_name); + if (id != -1) + { + + // + // Strip id number off + // + + char *p = strchr(long_name, '\t'); + if (p) + { + *p = '\0'; + } + else + { + char *p = strchr(long_name, ' '); + *p = '\0'; + } + + } + + + // + // open modelname + // + + char *filename = MakePathedFilename(resource_directories.modelDirectory, long_name); + Register_Pointer(filename); + DEBUG_STREAM << "Opening Model " << filename << std::endl << std::flush; + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + const char *p = StripExtension(StripDirectory(long_name)); + + strcpy(short_name, p); + + + if (new_notation_file->PageCount()) + { + if ( + !WriteModels( + new_notation_file, + ops_file, + &file, + short_name, + &resource_directories, + id + ) + ) + { + + DEBUG_STREAM << "Error - Model did not work : " << filename << std::endl << std::flush; + + } + } + else + { + DEBUG_STREAM << filename << " does not exist " << std::endl << std::flush; + + } + + + Unregister_Pointer(filename); + delete filename; + + Unregister_Object(new_notation_file); + delete new_notation_file; + + } + else if (!stricmp(entry_data, "zone")) + { + char *q = entry->GetChar(); + strcpy(long_name, q); + + // + // open zone + // + + char *filename = MakePathedFilename(resource_directories.mapDirectory, long_name); + Register_Pointer(filename); + + DEBUG_STREAM << "Opening Zones " << filename << std::endl << std::flush; + + NotationFile *new_notation_file = new NotationFile(filename); + Register_Object(new_notation_file); + + labOnly |= new_notation_file->IsMarkedLabOnly(); + + if (new_notation_file->PageCount()) + { + + InterestLatticeManager::CreateZoneResources + ( + &file, + new_notation_file + ); + } + else + { + DEBUG_STREAM << filename << " Does not exist! " << std::endl << std::flush; + } + + + Unregister_Pointer(filename); + delete filename; + Unregister_Object(new_notation_file); + delete new_notation_file; + + } + else if (!stricmp(entry_data, "static")) + { + // + // Add registry static objects + // + Check(entry); + const char *static_object_file_name = entry->GetChar(); + Check_Pointer(static_object_file_name); + + char *full_path_file_name = + MakePathedFilename( + resource_directories.modelDirectory, + static_object_file_name + ); + Register_Pointer(full_path_file_name); + + NotationFile + static_object_notation_file(full_path_file_name); + + Registry::CreateStaticObjectStreamResource( + &static_object_notation_file, + &file + ); + + Unregister_Pointer(full_path_file_name); + delete full_path_file_name; + } + + entry = entry->GetNextEntry(); + } + + Unregister_Object(entry_list); + delete entry_list; + + // + //------------------------------------------------------- + // Make this resource Lab only if labOnly was specified + //------------------------------------------------------- + // + + if (labOnly == True) + { + file.labOnly = 1; + } + + + Unregister_Pointer(WorkingDirectory); + Unregister_Object(notation_file); + + delete WorkingDirectory; + delete notation_file; + + } + + WriteOpsFile(ops_file, &file, &resource_directories); + + file.SaveAs(resfilename); + ops_file->WriteFile(ops_filename); + + + Unregister_Pointer(resfilename); + delete resfilename; + + //------------------------ + // open the vehicle.tbl + // and write to ops and + //------------------------ + + + Unregister_Object(ops_file); + delete ops_file; + + return 0; +} + +//############################################################################# + +void + ApplicationTool::ListResource( + ResourceDescription *resource + ) +{ + Check(resource); + switch (resource->resourceType) + { + case ResourceDescription::ModelListResourceType: + DEBUG_STREAM << resource->resourceName << ": Model List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::MapListResourceType: + DEBUG_STREAM << resource->resourceName << ": Map List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::AudioStreamListResourceType: + DEBUG_STREAM << resource->resourceName << ": Audio stream List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::VideoListResourceType: + DEBUG_STREAM << resource->resourceName << ": Video List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::SubsystemListResourceType: + DEBUG_STREAM << resource->resourceName << ": Subsystem List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::ControlMappingsListResourceType: + DEBUG_STREAM << resource->resourceName << ": ControlsMappings List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::DamageZoneListResourceType: + DEBUG_STREAM << resource->resourceName << ": DamageZone List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::SkeletonListResourceType: + DEBUG_STREAM << resource->resourceName << ": Skeleton List of " + << *(int*)resource->resourceAddress << " elements"; + break; + + case ResourceDescription::BoxedSolidStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Boxed Solid Stream of " + << resource->resourceSize/sizeof(BoxedSolidResource) + << " solids"; + break; + + case ResourceDescription::VideoModelResourceType: + DEBUG_STREAM << resource->resourceName << ": VideoModel" << std::flush; + break; + + case ResourceDescription::StaticAudioStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": StaticAudioStream" << std::flush; + break; + + case ResourceDescription::InternalAudioStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": InternalAudioStream" << std::flush; + break; + + case ResourceDescription::ExternalAudioStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": ExternalAudioStream" << std::flush; + break; + + case ResourceDescription::MakeMessageStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Map stream of " + << *(int*)resource->resourceAddress << " instances"; + break; + + case ResourceDescription::GameModelResourceType: + DEBUG_STREAM << resource->resourceName << ": GameModel" << std::flush; + break; + + case ResourceDescription::AnimationResourceType: + DEBUG_STREAM << resource->resourceName << ": Animation" << std::flush; + break; + + case ResourceDescription::SubsystemModelStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " Subsystems"; + break; + + case ResourceDescription::GaugeImageStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": GaugeImage" << std::flush; + break; + + case ResourceDescription::ControlMappingStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " ControlsMappings"; + break; + + case ResourceDescription::DamageZoneStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " DamageZones"; + break; + + case ResourceDescription::SkeletonStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " Segments"; + break; + + case ResourceDescription::EnvironmentZoneResourceType: + DEBUG_STREAM << resource->resourceName << ": EnvironmentZone" << std::flush; + break; + + case ResourceDescription::InterestZoneResourceType: + DEBUG_STREAM << resource->resourceName << ": InterestZone" << std::flush; + break; + + case ResourceDescription::VehicleTableResourceType: + DEBUG_STREAM << resource->resourceName << ": VehicleTable" << std::flush; + break; + + case ResourceDescription::ExistanceBoxStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << resource->resourceSize/sizeof(ExtentBox) + << " Existance boxes"; + break; + + case ResourceDescription::CameraStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": Stream of " + << *(int*)resource->resourceAddress << " Cameras"; + break; + + case ResourceDescription::DamageLookupTableStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": DamageZoneLookupTable" << std::flush; + break; + + case ResourceDescription::ExplosionTableStreamResourceType: + DEBUG_STREAM << resource->resourceName << ": ExplosionTable" << std::flush; + break; + + default: + DEBUG_STREAM << "Unknown type " << resource->resourceType << std::flush; + break; + } +} + +//############################################################################# + +int + ApplicationTool::ListResources( + int argc, + char **argv + ) +{ + if (argc < 2) + { + DEBUG_STREAM << "Usage: listXX resource.res [res2.res ...]\n" << std::flush; + return 1; + } + + for (int i=1; i < argc; ++i) + { + char res_name[200]; + strcpy(res_name, argv[i]); + + StreamableResourceFile + file; + + file.Open(res_name); + + DEBUG_STREAM << res_name << ": v" << (int)file.versionArray[0] << '.' + << (int)file.versionArray[1] << '.' << (int)file.versionArray[2] << '.' + << (int)file.versionArray[3] << std::endl; + + if (file.labOnly == 1) + { + DEBUG_STREAM << "LAB ONLY RESOURCE!" << std::endl << std::flush; + } + + DEBUG_STREAM << std::endl << std::flush; + DEBUG_STREAM << "ID# Size Data\n" << std::flush; + DEBUG_STREAM << "---- ------ -----------------------------------------------------\n" << std::flush; + + for (int j=0; j<=file.GetMaxResourceID(); ++j) + { + DEBUG_STREAM << std::setw(4) << j << " " << std::flush; + ResourceDescription *resource = file.FindResourceDescription(j); + if (resource) + { + DEBUG_STREAM << std::setw(6) << resource->resourceSize << " " << std::flush; + resource->Lock(); + ListResource(resource); + resource->Unlock(); + } + else + { + DEBUG_STREAM << " Not Used" << std::flush; + } + DEBUG_STREAM << std::endl << std::flush; + } + } + return 0; +} + diff --git a/MUNGA/TOOL.h b/MUNGA/TOOL.h new file mode 100644 index 0000000..1d8f5e4 --- /dev/null +++ b/MUNGA/TOOL.h @@ -0,0 +1,224 @@ +#pragma once + +#include "notation.h" +#include "resource.h" +#include "controls.h" +#include "gaugalrm.h" +#include "audtools.h" +#include "entity.h" + +struct ModelData +{ + char pageName[100]; + char modelName[100]; + ResourceDescription::ResourceID videoResourceID; + ResourceDescription::ResourceID skeletonResourceID; + ResourceDescription::ResourceID audioResourceID; + ResourceDescription::ResourceID collisionID; + ResourceDescription::ResourceID gameResourceID; + ResourceDescription::ResourceID subsystemResourceID; + ResourceDescription::ResourceID controlsMappingsResourceID; + ResourceDescription::ResourceID damageZoneResourceID; + ResourceDescription::ResourceID gaugeImageResourceID; + ResourceDescription::ResourceID gaugeAlarmResourceID; + ResourceDescription::ResourceID gaugeMissionReviewResourceID; + ResourceDescription::ResourceID explosionTableResourceID; + RegisteredClass::ClassID classID; + + ResourceDescription::ResourceID resourceID; +}; + +struct + InstanceData +{ + char pageName[100]; + char modelName[100]; + + ResourceDescription::ResourceID resourceID; +}; + +struct + InstanceResource +{ + Origin origin; + ResourceDescription::ResourceID resourceID; +}; + +//########################################################################## +//######################### PlatformTool ############################# +//########################################################################## + +class PlatformTool +{ +public: + PlatformTool() + { + gaugeAlarmManager = NULL; + } + + + virtual ResourceDescription::ResourceID + CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateModelGaugeImageStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateModelGaugeMissionReviewStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + )=0; + + virtual ResourceDescription::ResourceID + CreateStaticAudioStreamResource( + ResourceFile *resource_file + )=0; + + typedef Logical + (*FindNameFunction)( + const char *control_name, + ControlsMapping *mapping + ); + virtual FindNameFunction + GetControlMappingFunction()=0; + + virtual Logical + ConvertStringToModeMask( + const char *string, + ModeMask *returned_value_ptr + ); + virtual Logical + ConvertStringToTechStatus( + const char *string, + int *returned_value_ptr + ); + + GaugeAlarmManager + *gaugeAlarmManager; // should be set at the topmost level +}; + +//########################################################################## +//######################## ApplicationTool ########################### +//########################################################################## + +class ApplicationTool +{ +protected: + PlatformTool* + platformTool; + + virtual Logical + CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + virtual void + CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + virtual ResourceDescription::ResourceID + CreateControlMappingStream( + const char *model_class, + const char *mapping_name, + NotationFile *mapping_file, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + )=0; + + virtual void + ListResource(ResourceDescription *resource); + + Logical + WriteMaps( + char *map_name, + NotationFile *notation_file, + NotationFile *ops_file, + StreamableResourceFile *file, + const ResourceDirectories *resource_directories, + int resource_id = -1 + ); + + Logical + WriteModels( + NotationFile *notation_file, + NotationFile *ops_file, + StreamableResourceFile *file, + const char *model_name, + const ResourceDirectories *resource_directories, + int resource_id = -1 + ); + + void + WriteOpsFile( + NotationFile *ops_file, + StreamableResourceFile *file, + const ResourceDirectories *resource_directories + ); + + Logical + WriteAnimationCycle( + NotationFile *animation_file, + StreamableResourceFile *file, + const char *animation_name + ); + + Logical + WriteAnimationTransition( + NotationFile *animation_file, + StreamableResourceFile *file, + const char *animation_name + ); + +public: + Logical + labOnly, + verboseMode; + + ApplicationTool(PlatformTool *platform) + {platformTool = platform;} + + int + BuildResources( + int argc, + char **argv, + AudioCreateSymbols &create_symbols, + Byte minor_version + ); + int + ListResources( + int argc, + char **argv + ); +}; diff --git a/MUNGA/TRACE.cpp b/MUNGA/TRACE.cpp new file mode 100644 index 0000000..f1f7b2c --- /dev/null +++ b/MUNGA/TRACE.cpp @@ -0,0 +1,566 @@ +#include "munga.h" +#pragma hdrstop + +#include "trace.h" +#include "filestrm.h" + +#if defined(TRACE_ON) + + //########################################################################## + //############################ Trace ################################# + //########################################################################## + + Byte + Trace::NextTraceID = 0; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Trace::Trace( + const char* name, + Type type + ) + { + traceNumber = NextTraceID++; + traceType = (Byte)type; + traceName = name; + + lastFrameActivity = 0; + lastFractionActivity = 0.0f; + + trace_manager.Add(this); + } + + #if defined(USE_TIME_ANALYSIS) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + Trace::PrintUsage(Scalar usage) + { + Check(this); + + DEBUG_STREAM << usage << std::flush; + } + #endif + + //########################################################################## + //########################### BitTrace ############################### + //########################################################################## + + Byte + BitTrace::NextActiveLine = 0; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + BitTrace::BitTrace(const char* name): + Trace(name, BitType) + { + activeLine = NextActiveLine++; + #if defined(USE_ACTIVE_PROFILE) + DEBUG_STREAM << name << " used trace line " << (int)activeLine + << "!\n"; + if (!IsLineValidImplementation(activeLine)) + { + Fail("Invalid active trace line!"); + } + #endif + + BitTrace::ResetTrace(); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::DumpTraceStatus() + { + Check(this); + DEBUG_STREAM << (int)activeLine << ((traceUp) ? " is On" : " is Off") << std::flush; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::ResetTrace() + { + #if defined(USE_TIME_ANALYSIS) + traceUp = False; + lastUpTime = 0.0; + totalUpTime = 0.0; + #endif + + #if defined(USE_ACTIVE_PROFILE) + ClearLineImplementation(activeLine); + #endif + } + + #if defined(USE_TIME_ANALYSIS) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::StartTiming() + { + Check(this); + totalUpTime = 0.0; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Scalar + BitTrace::CalculateUsage( + long frame, + Scalar fraction, + double sample_time + ) + { + if (traceUp) + { + totalUpTime += frame - lastFrameActivity; + totalUpTime += fraction - lastFractionActivity; + } + Scalar result = totalUpTime / sample_time; + Check_Fpu(); + DEBUG_STREAM << setprecision(4) << totalUpTime / GetTicksPerSecond() + << "s, "; + return result; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::PrintUsage(Scalar usage) + { + Check(this); + + DEBUG_STREAM << setprecision(4) << (usage*100.0f) << "% CPU" << std::flush; + #if defined(USE_ACTIVE_PROFILE) + DEBUG_STREAM << " (active on line " << (int)activeLine << ')' << std::flush; + #endif + } + + #endif + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::Set() + { + Check(this); + + if (!traceUp) + { + #if defined(USE_ACTIVE_PROFILE) + SetLineImplementation(activeLine); + #endif + + traceUp = True; + + #if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG) + long frame = Now().ticks; + Scalar fraction = Get_Frame_Percent_Used(); + #endif + + #if defined(USE_TIME_ANALYSIS) + lastFrameActivity = frame; + lastFractionActivity = fraction; + #endif + + #if defined(USE_TRACE_LOG) + // Check(traceManager); + IncrementSampleCount(); + MemoryStream *log = GetTraceLog(); + if (log) + { + Check(log); + TraceSample *sample = (TraceSample*)log->GetPointer(); + sample->sampleType = TraceSample::GoingUp; + sample->traceNumber = traceNumber; + sample->sampleFrame = (Word)frame; + sample->sampleFraction = fraction; + log->AdvancePointer(sizeof(*sample)); + } + #endif + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + BitTrace::Clear() + { + Check(this); + + if (traceUp) + { + traceUp = False; + + #if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG) + long frame = Now().ticks; + Scalar fraction = Get_Frame_Percent_Used(); + #endif + + #if defined(USE_TIME_ANALYSIS) + if (frame == lastFrameActivity && fraction < lastFractionActivity) + { + ++frame; + } + lastUpTime = frame - lastFrameActivity; + lastUpTime += fraction - lastFractionActivity; + Verify(lastUpTime >= 0.0f) + totalUpTime += lastUpTime; + Check_Fpu(); + #endif + + #if defined(USE_TRACE_LOG) + //Check(traceManager); + IncrementSampleCount(); + MemoryStream *log = GetTraceLog(); + if (log) + { + Check(log); + TraceSample *sample = (TraceSample*)log->GetPointer(); + sample->sampleType = TraceSample::GoingDown; + sample->traceNumber = traceNumber; + sample->sampleFrame = (Word)frame; + sample->sampleFraction = fraction; + log->AdvancePointer(sizeof(*sample)); + } + #endif + + #if defined(USE_ACTIVE_PROFILE) + ClearLineImplementation(activeLine); + #endif + } + } + + //########################################################################## + //######################## TraceManager ############################## + //########################################################################## + + TraceManager + trace_manager; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + TraceManager::TraceManager(): + traceChain(NULL) + { + sampleStartFrame = 0; + sampleStartFraction = 0.0f; + actualSampleCount = 0; + ignoredSampleCount = 0; + traceCount = 0; + activeTraceLog = NULL; + allocatedTraceLog = NULL; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + TraceManager::~TraceManager() + { + Check(this); + + if (allocatedTraceLog) + { + Check(allocatedTraceLog); + allocatedTraceLog->Rewind(); + TraceSample *samples = (TraceSample*)allocatedTraceLog->GetPointer(); + Unregister_Object(allocatedTraceLog); + delete allocatedTraceLog; + activeTraceLog = allocatedTraceLog = NULL; + + Unregister_Pointer(samples); + delete[] samples; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Logical + TraceManager::TestInstance() const + { + return True; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::Add(Trace *trace) + { + Check(this); + + traceCount = (Byte)(traceCount + 1); + traceChain.Add(trace); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::DumpTracesStatus() + { + ChainIteratorOf traces(traceChain); + Trace *trace; + + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + DEBUG_STREAM << trace->traceName << ": " << std::flush; + trace->DumpTraceStatus(); + DEBUG_STREAM << endl << std::flush; + } + DEBUG_STREAM << endl << std::flush; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::ResetTraces() + { + ChainIteratorOf traces(traceChain); + Trace *trace; + + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + trace->ResetTrace(); + } + + #if defined(USE_TRACE_LOG) + actualSampleCount = 0; + ignoredSampleCount = 0; + if (allocatedTraceLog) + { + allocatedTraceLog->Rewind(); + } + #endif + } + + #if defined(USE_TIME_ANALYSIS) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::StartTimingAnalysis() + { + sampleStartFrame = Now().ticks; + sampleStartFraction = Get_Frame_Percent_Used(); + + ChainIteratorOf traces(traceChain); + Trace *trace; + + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + trace->StartTiming(); + trace->lastFrameActivity = sampleStartFrame; + trace->lastFractionActivity = sampleStartFraction; + } + + #if defined(USE_TRACE_LOG) + actualSampleCount = 0; + ignoredSampleCount = 0; + if (allocatedTraceLog) + { + allocatedTraceLog->Rewind(); + } + #endif + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int + TraceManager::SnapshotTimingAnalysis(Logical print) + { + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + double time = now - sampleStartFrame; + time += fraction - sampleStartFraction; + if (time < SMALL) + { + return False; + } + + ChainIteratorOf traces(traceChain); + Trace *trace; + + DEBUG_STREAM << "Sample length: " << setprecision(4) + << time/GetTicksPerSecond() << "s\n"; + while ((trace = traces.ReadAndNext()) != NULL) + { + Check(trace); + + if (print) + { + DEBUG_STREAM << trace->traceName << ": " << std::flush; + Scalar usage = trace->CalculateUsage(now, fraction, time); + trace->PrintUsage(usage); + DEBUG_STREAM << endl << std::flush; + } + + trace->StartTiming(); + trace->lastFrameActivity = now; + trace->lastFractionActivity = fraction; + } + + sampleStartFrame = now; + sampleStartFraction = fraction; + return True; + } + #endif + + #if defined(USE_TRACE_LOG) + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::CreateTraceLog( + size_t max_trace_count, + Logical start_logging + ) + { + Check(this); + Verify(!allocatedTraceLog); + TraceSample *samples = new TraceSample[max_trace_count]; + Register_Pointer(samples); + allocatedTraceLog = + new MemoryStream(samples, max_trace_count*sizeof(TraceSample)); + Register_Object(allocatedTraceLog); + if (start_logging) + { + activeTraceLog = allocatedTraceLog; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::SaveTraceLog(const char* filename) + { + Check(this); + if (allocatedTraceLog) + { + Check(allocatedTraceLog); + + // + //-------------------------------------------------------- + // Rewind the memory stream and save it out in a disk file + //-------------------------------------------------------- + // + FileStream output(filename, True); + size_t size = allocatedTraceLog->GetBytesUsed(); + DEBUG_STREAM << ignoredSampleCount << " samples were ignored\n" << std::flush; + if (size > 0) + { + DEBUG_STREAM << "Writing " << actualSampleCount + << " samples to trace log..."; + Byte trace_count = GetTraceCount(); + output << trace_count; + + ChainIteratorOf traces(traceChain); + Trace *trace; + while ((trace = traces.ReadAndNext()) != NULL) + { + output << trace->traceType; + const char* p = trace->traceName; + do + { + output << *p; + } while (*p++); + } + + output << size; + allocatedTraceLog->Rewind(); + output.WriteBytes(allocatedTraceLog->GetPointer(), size); + DEBUG_STREAM << "trace log written\n" << std::flush; + } + + // + //------------------- + // Release the memory + //------------------- + // + TraceSample *samples = (TraceSample*)allocatedTraceLog->GetPointer(); + Unregister_Object(allocatedTraceLog); + delete allocatedTraceLog; + activeTraceLog = allocatedTraceLog = NULL; + + Unregister_Pointer(samples); + delete[] samples; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::MarkTraceLog() + { + Check(this); + + if (activeTraceLog) + { + Check(activeTraceLog); + + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + TraceSample *sample = (TraceSample*)activeTraceLog->GetPointer(); + sample->sampleType = TraceSample::Marker; + sample->sampleFrame = (Word)now; + sample->sampleFraction = fraction; + sample->traceNumber = 0; + activeTraceLog->AdvancePointer(sizeof(*sample)); + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::SuspendTraceLogging() + { + Check(this); + + if (activeTraceLog) + { + Check(activeTraceLog); + + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + TraceSample *sample = (TraceSample*)activeTraceLog->GetPointer(); + sample->sampleType = TraceSample::SuspendSampling; + sample->sampleFrame = (Word)now; + sample->sampleFraction = fraction; + sample->traceNumber = 0; + activeTraceLog->AdvancePointer(sizeof(*sample)); + activeTraceLog = NULL; + } + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void + TraceManager::ResumeTraceLogging() + { + Check(this); + + if (allocatedTraceLog && !activeTraceLog) + { + Check(allocatedTraceLog); + activeTraceLog = allocatedTraceLog; + + long now = Now().ticks; + float fraction = Get_Frame_Percent_Used(); + + TraceSample *sample = (TraceSample*)activeTraceLog->GetPointer(); + sample->sampleType = TraceSample::ResumeSampling; + sample->sampleFrame = (Word)now; + sample->sampleFraction = fraction; + sample->traceNumber = 0; + activeTraceLog->AdvancePointer(sizeof(*sample)); + } + } + + #endif + +#endif + diff --git a/MUNGA/TRACE.h b/MUNGA/TRACE.h new file mode 100644 index 0000000..2502d74 --- /dev/null +++ b/MUNGA/TRACE.h @@ -0,0 +1,297 @@ +#pragma once + +#include "plug.h" +#include "chain.h" +#include "time.h" +#include "config.h" + +#if defined(TRACE_ON) + +struct TraceSample +{ + Scalar sampleFraction; + Word sampleFrame; + Byte traceNumber; + Byte sampleType; + + enum Type + { + GoingUp = 0, + GoingDown, + Marker, + IntegerSnapshot, + ScalarSnapshot, + SuspendSampling, + ResumeSampling + }; +}; + +template struct SnapshotOf : public TraceSample +{ + T snapShot; +}; + +class Trace : public Plug +{ + friend class TraceManager; + +public: + enum Type + { + BitType, + IntegerType, + ScalarType + }; + +protected: + static Byte NextTraceID; + + const char *traceName; + long lastFrameActivity; + Scalar lastFractionActivity; + Byte traceNumber; + Byte traceType; + + Trace(const char* name, Type type); + + MemoryStream *GetTraceLog(); + void IncrementSampleCount(); + + virtual void DumpTraceStatus()=0; + virtual void ResetTrace()=0; + +#if defined(USE_TIME_ANALYSIS) + virtual void StartTiming()=0; + virtual Scalar CalcuateUsage(long frame, Scalar fraction, double sample_time)=0; + virtual void PrintUsage(Scalar usage); +#endif +}; + +class BitTrace : public Trace +{ +protected: + static Byte NextActiveLine; + + Logical traceUp; + double lastUpTime, totalUpTime; + Byte activeLine; + + #if defined(USE_ACTIVE_PROFILE) + static void SetLineImplementation(Byte line); + static void ClearLineImplementation(Byte line); + static Logical IsLineValidImplementation(Byte line); + #endif + + void DumpTraceStatus(); + void ResetTrace(); + #if defined(USE_TIME_ANALYSIS) + void StartTiming(); + Scalar CalculateUsage(long frame, Scalar fraction, double sample_time); + void PrintUsage(Scalar usage); + #endif + +public: + BitTrace(const char *name); + + void Set(); + void Clear(); + + double GetLastUpTime() + { + Check(this); + return lastUpTime; + } + + double GetTotalUpTime() + { + Check(this); + return totalUpTime; + } +}; + +template class TraceOf : public Trace +{ +protected: + double weightedSum; + T currentValue; + + TraceSample::Type sampleType; + + void DumpTraceStatus(); + void ResetTrace(); + #if defined(USE_TIME_ANALYSIS) + void StartTiming(); + Scalar CalculateUsage(long frame, Scalar fraction, double sample_time); + void PrintUsage(Scalar usage); + #endif + +public: + TraceOf(const char* name, const T& initial_value, Type trace_type, TraceSample::Type sample_type); + + void TakeSnapshot(const T& value); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +template TraceOf::TraceOf(const char* name, const T& initial_value, Type trace_type, TraceSample::Type sample_type) : Trace(name, trace_type) +{ + currentValue = initial_value; + sampleType = sample_type; + TraceOf::ResetTrace(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +template void TraceOf::DumpTraceStatus() +{ + Check(this); + DEBUG_STREAM << currentValue << std::flush; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +template void TraceOf::ResetTrace() +{ + #if defined(USE_TIME_ANALYSIS) + weightedSum = 0.0; + #endif +} + +#if defined(USE_TIME_ANALYSIS) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template void TraceOf::StartTiming() + { + Check(this); + weightedSum = 0.0; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template Scalar TraceOf::CalculateUsage(long frame, Scalar fraction, double sample_time) + { + double last_part = frame - lastFrameActivity; + last_part += fraction - lastFractionActivity; + weightedSum += last_part * currentValue; + Scalar result = weightedSum / sample_time; + Check_Fpu(); + weightedSum = 0.0; + return result; + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + template void TraceOf::PrintUsage(Scalar usage) + { + Check(this); + + DEBUG_STREAM << usage << std::flush; + } + +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +template void TraceOf::TakeSnapshot(const T& value) +{ + Check(this); + + #if defined(USE_TIME_ANALYSIS) || defined(USE_TRACE_LOG) + long frame = Now().ticks; + Scalar fraction = Get_Frame_Percent_Used(); + #endif + + #if defined(USE_TIME_ANALYSIS) + double last_part = frame - lastFrameActivity; + last_part += fraction - lastFractionActivity; + weightedSum += last_part * currentValue; + lastFrameActivity = frame; + lastFractionActivity = fraction; + #endif + + currentValue = value; + + #if defined(USE_TRACE_LOG) + IncrementSampleCount(); + MemoryStream *log = GetTraceLog(); + if (log) + { + Check(log); + SnapshotOf *sample = (SnapshotOf*)log->GetPointer(); + sample->sampleType = (Byte)sampleType; + sample->traceNumber = traceNumber; + sample->sampleFrame = (Word)frame; + sample->sampleFraction = fraction; + sample->snapShot = currentValue; + log->AdvancePointer(sizeof(*sample)); + } + #endif +} + +//####################################################################### +//##################### TraceManager ############################## +//####################################################################### + +class TraceManager SIGNATURED +{ + friend class Trace; + +protected: + ChainOf traceChain; + long sampleStartFrame; + Scalar sampleStartFraction; + int actualSampleCount, ignoredSampleCount; + MemoryStream *allocatedTraceLog, *activeTraceLog; + Byte traceCount; + + void Add(Trace *trace); + +public: + TraceManager(); + ~TraceManager(); + + Byte GetTraceCount() + { + Check(this); + return traceCount; + } + + void DumpTracesStatus(); + void ResetTraces(); + + #if defined(USE_TIME_ANALYSIS) + void StartTimingAnalysis(); + int SnapshotTimingAnalysis(Logical print = false); + #endif + + #if defined(USE_TRACE_LOG) + void CreateTraceLog(size_t max_trace_samples, Logical start_sampling); + void SaveTraceLog(const char* filename); + void MarkTraceLog(); + void SuspendTraceLogging(); + void ResumeTraceLogging(); + #endif + + Logical TestInstance() const; +}; + +extern TraceManager trace_manager; + +inline MemoryStream* Trace::GetTraceLog() +{ + Check(this); + Check(&trace_manager); + return trace_manager.activeTraceLog; +} + +inline void Trace::IncrementSampleCount() +{ + Check(this); + Check(&trace_manager); + if (!trace_manager.activeTraceLog) + ++trace_manager.ignoredSampleCount; + else + ++trace_manager.actualSampleCount; +} + +# endif diff --git a/MUNGA/TRACSTUB.cpp b/MUNGA/TRACSTUB.cpp new file mode 100644 index 0000000..caf26e7 --- /dev/null +++ b/MUNGA/TRACSTUB.cpp @@ -0,0 +1,22 @@ +#include "munga.h" +#pragma hdrstop + +void* Get_Caller(int) +{ + return NULL; +} + +#if defined(USE_ACTIVE_PROFILE) + void BitTrace::SetLineImplementation(Byte) + { + } + + void BitTrace::ClearLineImplementation(Byte) + { + } + + Logical BitTrace::IsLineValidImplementation(Byte) + { + return True; + } +#endif diff --git a/MUNGA/TREE.cpp b/MUNGA/TREE.cpp new file mode 100644 index 0000000..ccf8cff --- /dev/null +++ b/MUNGA/TREE.cpp @@ -0,0 +1,845 @@ +#include "munga.h" +#pragma hdrstop + +#include "tree.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeNode ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// TreeNode +//########################################################################### +// +TreeNode::TreeNode( + Tree *tree, + Plug *plug +): + Link(tree, plug) +{ + less = NULL; + greater = NULL; + parent = NULL; +} + +// +//########################################################################### +// ~TreeNode +//########################################################################### +// +TreeNode::~TreeNode() +{ + Tree *tree = Cast_Object(Tree*, socket); + + Check(this); + Check(tree); + + // + //------------------------------------------- + // Notify iterators that deletion is occuring + //------------------------------------------- + // + tree->SendIteratorMemo(PlugRemoved, this); + + // + //----------------------------------- + // Tell the tree to release this node + //----------------------------------- + // + tree->SeverFromTreeNode(this); + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (tree->GetReleaseNode() != NULL) + { + Check(tree->GetReleaseNode()); + tree->GetReleaseNode()->ReleaseLinkHandler(tree, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + TreeNode::TestInstance() const +{ + Link::TestInstance(); + + if (less != NULL) + { + Check_Signature(less); + } + if (greater != NULL) + { + Check_Signature(greater); + } + if (parent != NULL) + { + Check_Signature(parent); + } + return True; +} + +// +//########################################################################### +// SetupTreeLinks +//########################################################################### +// +void + TreeNode::SetupTreeLinks( + TreeNode *less, + TreeNode *greater, + TreeNode *parent + ) +{ + this->less = less; + this->greater = greater; + this->parent = parent; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ Tree ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// Tree +//########################################################################### +// +Tree::Tree( + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + root = NULL; +} + +// +//########################################################################### +// ~Tree +//########################################################################### +// +Tree::~Tree() +{ + SetReleaseNode(NULL); + while (root != NULL) + { + Unregister_Object(root); + delete root; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + Tree::TestInstance() const +{ + SortedSocket::TestInstance(); + + // + // Check root if not null + // + if (root != NULL) + { + Check(root); + } + return True; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + Tree::AddImplementation( + Plug *plug + ) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + Tree::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + Check(this); + Check(plug); + + /* + * Verify that value has not been added + */ + Verify(HasUniqueEntries() ? SearchForValue(value) == NULL : (Logical)True); + + /* + * Make new tree node + */ + TreeNode *node; + + node = MakeTreeNode(plug, value); + Register_Object(node); + + /* + * Add to the tree and send iterators memo to + * update pointers + */ + AddTreeNode(node); + SendIteratorMemo(PlugAdded, node); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + Tree::FindImplementation( + const void *value + ) +{ + TreeNode *node; + + if ((node = SearchForValue(value)) != NULL) + { + Check(node); + return node->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// MakeTreeNode +//########################################################################### +// +TreeNode* + Tree::MakeTreeNode( + Plug*, + const void* + ) +{ + Fail("Tree::MakeTreeNode - Shoule never reach here"); + return NULL; +} + +// +//########################################################################### +// CompareTreeNodes +//########################################################################### +// +int + Tree::CompareTreeNodes( + TreeNode*, + TreeNode* + ) +{ + Fail("Tree::CompareTreeNodes - Shoule never reach here"); + return 0; +} + +// +//########################################################################### +// CompareValueToTreeNode +//########################################################################### +// +int + Tree::CompareValueToTreeNode( + const void*, + TreeNode* + ) +{ + Fail("Tree::CompareValueToTreeNode - Shoule never reach here"); + return 0; +} + +// +//########################################################################### +// AddTreeNode +//########################################################################### +// +void + Tree::AddTreeNode( + TreeNode *newNode + ) +{ + Check(this); + Check(newNode); + + /* + * If root is NULL this is the first item + */ + if (root == NULL) + { + newNode->SetupTreeLinks(NULL, NULL, NULL); + root = newNode; + return; + } + + /* + * Search for insertion point + */ + TreeNode *node; + + node = root; + while (node != NULL) + { + Check(node); + + if (CompareTreeNodes(newNode, node) < 0) + { + if (node->less == NULL) + { + newNode->SetupTreeLinks(NULL, NULL, node); + node->less = newNode; + break; + } + else + node = node->less; + } + else + { + if (node->greater == NULL) + { + newNode->SetupTreeLinks(NULL, NULL, node); + node->greater = newNode; + break; + } + else + node = node->greater; + } + } +} + +// +//########################################################################### +// SeverFromTreeNode +//########################################################################### +// +void + Tree::SeverFromTreeNode( + TreeNode *node + ) +{ + Check(this); + Check(node); + + if (node->greater == NULL) + { + if (node->less == NULL) + { + // + //-------------------------------------------------------------------- + // The node has no subtrees + //-------------------------------------------------------------------- + // + if (node == root) + { + // + // Tree is now empty, set root to null + // + root = NULL; + } + else + { + // + // Set appropiate branch to NULL + // + Check(node->parent); + if (node->parent->less == node) + node->parent->less = NULL; + else + node->parent->greater = NULL; + } + } + else + { + // + //-------------------------------------------------------------------- + // The node has a less subtree + //-------------------------------------------------------------------- + // + Check(node->less); + + if (node == root) + { + // + // Node is root... Set subtree to new root + // + root = node->less; + node->less->parent = NULL; + } + else + { + // + // Node is not root + // Set parents pointer to subtree + // + Check( node->parent ); + if (node->parent->less == node) + { + node->parent->less = node->less; + } + else + { + node->parent->greater = node->less; + } + // + // Set subtree parent to node parent + // + node->less->parent = node->parent; + } + } + } + else { + if (node->less == NULL) + { + // + //-------------------------------------------------------------------- + // The node has a greater subtree + //-------------------------------------------------------------------- + // + Check( node->greater ); + if (node == root) + { + // + // Node is root + // Set subtree to new root + // + root = node->greater; + // + // Set new root to have null parent + // + node->greater->parent = NULL; + } + else + { + // + // Node is not root + // Set parents pointer to subtree + // + Check( node->parent ); + if (node->parent->less == node) + node->parent->less = node->greater; + else + node->parent->greater = node->greater; + // + // Set subtree parent to node parent + // + node->greater->parent = node->parent; + } + } + else + { + // + //-------------------------------------------------------------------- + // The node has lesser and greater sub-trees + //-------------------------------------------------------------------- + // + TreeNode *successor; + + Check(node->less); + Check(node->greater); + + successor = node->greater; + while (successor->less != NULL) + { + successor = successor->less; + Check(successor); + } + + // + // Set successor's parent to subtree + // + Check(successor->parent); + if (successor->parent->less == successor) + successor->parent->less = successor->greater; + else + successor->parent->greater = successor->greater; + + // + // Set successor's subtree to parent + // + if (successor->greater != NULL) + { + Check(successor->greater); + successor->greater->parent = successor->parent; + } + + // + // Place at node + // + successor->parent = node->parent; + successor->less = node->less; + successor->greater = node->greater; + + if (root == node) + { + // + // Node was root + // + root = successor; + } + else + { + // + // Set nodes parent to successor + // + Check(successor->parent); + if (successor->parent->less == node) + successor->parent->less = successor; + else + successor->parent->greater = successor; + } + + // + // Set subtrees parent to successor + // + if (successor->greater != NULL) + { + Check(successor->greater); + successor->greater->parent = successor; + } + if (successor->less != NULL) + { + Check(successor->less); + successor->less->parent = successor; + } + } + } +} + +// +//########################################################################### +// SearchForValue +//########################################################################### +// +TreeNode* + Tree::SearchForValue( + const void *value + ) +{ + TreeNode *node; + int ret; + + node = root; + while (node != NULL) + { + Check(node); + if ((ret = CompareValueToTreeNode(value, node)) == 0) + break; + node = (ret < 0) ? node->less : node->greater; + } + return node; +} + +// +//########################################################################### +// TreeIterator +//########################################################################### +// +TreeIterator::TreeIterator(Tree *tree): + SortedIterator(tree) +{ + First(); +} + +// +//########################################################################### +//########################################################################### +// +TreeIterator::~TreeIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + TreeIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + if (currentNode != NULL) + { + Check(currentNode); + } + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + TreeIterator::First() +{ + TreeNode *node; + + node = Cast_Object(Tree*, socket)->root; + if (node != NULL) + { + Check(node); + while (node->less != NULL) + { + node = node->less; + Check(node); + } + } + currentNode = node; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + TreeIterator::Last() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + TreeIterator::Next() +{ + TreeNode *node; + + if ((node = currentNode) == NULL) + return; + + Check(node); + if (node->greater != NULL) + { + node = node->greater; + Check(node); + while (node->less != NULL) + { + node = node->less; + Check(node); + } + currentNode = node; + return; + } + + currentNode = NULL; + while (node->parent != NULL) + { + Check(node->parent); + if (node == node->parent->less) + { + currentNode = node->parent; + return; + } + node = node->parent; + Check(node); + } +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + TreeIterator::Previous() +{ + // + // Should never reach here + // + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif +} + +#if 0 +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *TreeIterator::ReadAndNextImplementation() +{ + void *plug; + + if ((plug = GetCurrentImplementation()) != NULL) + { + Next(); + } + return plug; +} +#endif + +#if 0 +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *TreeIterator::ReadAndPreviousImplementation() +{ + #ifdef __BCPLUSPLUS__ + #pragma warn -ccc + Verify(False); + #pragma warn +ccc + #endif + return(NULL); +} +#endif + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *TreeIterator::GetCurrentImplementation() +{ + if (currentNode != NULL) + { + Check(currentNode); + return currentNode->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + TreeIterator::GetSize() +{ + TreeIterator iterator(Cast_Object(Tree*, socket)); + CollectionSize i = 0; + + while (iterator.ReadAndNextImplementation() != NULL) + { + i++; + } + return(i); +} + +#if 0 +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *TreeIterator::GetNthImplementation( + CollectionSize index + ) +{ + CollectionSize i = 0; + void *plug; + + First(); + while ((plug = GetCurrentImplementation()) != NULL) + { + if (i == index) + return plug; + Next(); + i++; + } + return NULL; +} +#endif + +// +//########################################################################### +// Remove +//########################################################################### +// +void + TreeIterator::Remove() +{ + if (currentNode != NULL) + { + Unregister_Object(currentNode); + delete currentNode; + } +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + TreeIterator::FindImplementation( + const void *value + ) +{ + TreeNode *node; + + if ((node = Cast_Object(Tree*, socket)->SearchForValue(value)) != NULL) + { + Check(node); + return (currentNode = node)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + TreeIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + if (memo == PlugRemoved) + { + if (content == currentNode) + Next(); + } +} + +#if defined(TEST_CLASS) +# include "tree.tcp" +#endif diff --git a/MUNGA/TREE.h b/MUNGA/TREE.h new file mode 100644 index 0000000..76e775e --- /dev/null +++ b/MUNGA/TREE.h @@ -0,0 +1,262 @@ +#pragma once + +#include "node.h" +#include "srtskt.h" +#include "memblock.h" + +class Tree; +class TreeIterator; + +class TreeNode : public Link +{ + friend class Tree; + friend class TreeIterator; + +public: + ~TreeNode(); + Logical TestInstance() const; + +protected: + TreeNode(Tree *tree, Plug *plug); + +private: + void SetupTreeLinks(TreeNode *less, TreeNode *greater, TreeNode *parent); + + TreeNode *less; + TreeNode *greater; + TreeNode *parent; +}; + +#define TREENODE_MEMORYBLOCK_ALLOCATION (100) + +template class TreeNodeOf : public TreeNode +{ +public: + TreeNodeOf(Tree *tree, Plug *plug, const V &value); + ~TreeNodeOf(); + + void* operator new(size_t); + void operator delete(void *where); + + V GetValue() { return value; } + V* GetValuePointer() { return &value; } + +private: + static MemoryBlock *allocatedMemory; + static CollectionSize allocationCount; + + V value; +}; + +template MemoryBlock* TreeNodeOf::allocatedMemory = NULL; +template CollectionSize TreeNodeOf::allocationCount = 0; + +template TreeNodeOf::TreeNodeOf(Tree *tree, Plug *plug, const V &value) : TreeNode(tree, plug) +{ + this->value = value; +} + +template TreeNodeOf::~TreeNodeOf() +{ +} + +#if 0 + template void* TreeNodeOf::operator new(size_t) + { + if (allocatedMemory == NULL) + allocatedMemory = new MemoryBlock(sizeof(TreeNodeOf), TREENODE_MEMORYBLOCK_ALLOCATION, TREENODE_MEMORYBLOCK_ALLOCATION); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void TreeNodeOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + } +#else + template void* TreeNodeOf::operator new(size_t) + { + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = new MemoryBlock(sizeof(TreeNodeOf), TREENODE_MEMORYBLOCK_ALLOCATION, TREENODE_MEMORYBLOCK_ALLOCATION, "TreeNodeOf"); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void TreeNodeOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); + } +#endif + +class Tree : public SortedSocket +{ + friend class TreeNode; + friend class TreeIterator; + +public: + Tree(Node *node, Logical has_unique_entries); + ~Tree(); + + Logical TestInstance() const; + static void TestClass(); + static void ProfileClass(); + +protected: + void AddImplementation(Plug *); + void AddValueImplementation(Plug *plug, const void *value); + Plug *FindImplementation(const void *value); + +private: + virtual TreeNode* + MakeTreeNode(Plug *plug, const void *value); + virtual int CompareTreeNodes(TreeNode *link1, TreeNode *link2); + virtual int CompareValueToTreeNode(const void *value, TreeNode *link); + + void AddTreeNode(TreeNode *node); + void SeverFromTreeNode(TreeNode *node); + TreeNode* SearchForValue(const void *value); + + TreeNode *root; +}; + +template class TreeOf : public Tree +{ +public: + TreeOf(Node *node, Logical has_unique_entries); + ~TreeOf(); + + void AddValue(T plug, const V &value) { AddValueImplementation(plug, &value); } + T Find(const V &value) { return (T)FindImplementation(&value); } + +private: + TreeNode *MakeTreeNode(Plug *plug, const void *value) { return new TreeNodeOf(this, plug, *(V*)value); } + int CompareTreeNodes(TreeNode *link1, TreeNode *link2); + int CompareValueToTreeNode(const void *value, TreeNode *link); +}; + +template TreeOf::TreeOf(Node *node, Logical has_unique_entries) : Tree(node, has_unique_entries) +{ +} + +template TreeOf::~TreeOf() +{ +} + +#if 0 + template int TreeOf::CompareTreeNodes(TreeNode *node1, TreeNode *node2) + { + V result = Cast_Object(TreeNodeOf*, node1)->GetValue() - Cast_Object(TreeNodeOf*, node2)->GetValue(); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } +#else + template int TreeOf::CompareTreeNodes(TreeNode *node1, TreeNode *node2) + { + V *ptr1 = Cast_Object(TreeNodeOf*, node1)->GetValuePointer(); + V *ptr2 = Cast_Object(TreeNodeOf*, node2)->GetValuePointer(); + + Check_Pointer(ptr1); + Check_Pointer(ptr2); + + if (*ptr1 == *ptr2) + return 0; + else + return ((*ptr1 > *ptr2) ? 1 : -1); + } +#endif + +#if 0 + template int TreeOf::CompareValueToTreeNode(const void *value, TreeNode *node) + { + Check_Pointer(value); + + V result = *(V*)value - Cast_Object(TreeNodeOf*, node)->GetValue(); + + if (result == (V)0) + return 0; + return (result > (V)0) ? 1 : -1; + } +#else + template int TreeOf::CompareValueToTreeNode(const void *value, TreeNode *node) + { + Check_Pointer(value); + + V *ptr = Cast_Object(TreeNodeOf*, node)->GetValuePointer(); + Check_Pointer(ptr); + + if (*(V*)value == *ptr) + return 0; + else + return (*(V*)value > *ptr) ? 1 : -1; + } +#endif + +class TreeIterator : public SortedIterator +{ +public: + TreeIterator(Tree *tree); + ~TreeIterator(); + Logical TestInstance() const; + + void First(); + void Next(); + CollectionSize GetSize(); + void Remove(); + +protected: + void* GetCurrentImplementation(); + Plug* FindImplementation(const void *value); + +protected: + TreeNode *currentNode; + +private: + void Last(); // Marked as private so that clients do not use it + void Previous(); // Marked as private so that clients do not use it + + void ReceiveMemo(IteratorMemo memo, void *content); +}; + +template class TreeIteratorOf : public TreeIterator +{ +public: + TreeIteratorOf(TreeOf *tree); + TreeIteratorOf(TreeOf &tree); + ~TreeIteratorOf(); + + T ReadAndNext() { return (T)ReadAndNextImplementation(); } + T GetCurrent() { return (T)GetCurrentImplementation(); } + T GetNth(CollectionSize index) { return (T)GetNthImplementation(index); } + T Find(const V &value) { return (T)FindImplementation(&value); } + V GetValue() { return Cast_Object(TreeNodeOf*, currentNode)->GetValue(); } +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ TreeIteratorOf templates ~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +template TreeIteratorOf::TreeIteratorOf(TreeOf *tree) : TreeIterator(tree) +{ +} + +template TreeIteratorOf::TreeIteratorOf(TreeOf &tree) : TreeIterator(&tree) +{ +} + +template TreeIteratorOf::~TreeIteratorOf() +{ +} \ No newline at end of file diff --git a/MUNGA/UNITVEC.cpp b/MUNGA/UNITVEC.cpp new file mode 100644 index 0000000..24d281c --- /dev/null +++ b/MUNGA/UNITVEC.cpp @@ -0,0 +1,36 @@ +#include "munga.h" +#pragma hdrstop + +#include "unitvec.h" + +UnitVector& UnitVector::Lerp(const UnitVector& /*v1*/, const UnitVector& /*v2*/, Scalar /*t*/) +{ + Check_Pointer(this); + Tell("UnitVector::Lerp stubbed out!\n"); + return *this; +} + +Logical UnitVector::TestInstance() const +{ + Scalar length = Vector3D::LengthSquared(); + Scalar diff = 1.0f - length; + if (!Small_Enough(diff, 2e-5)) + { + length = x*x + y*y + z*z; + diff = 1.0f - length; + if (!Small_Enough(diff, 2e-5)) + { + Dump(*this); + Dump(length); + Dump(x*x + y*y + z*z); + Dump(diff); + return false; + } + } + return true; +} + +#if defined(TEST_CLASS) + #include "unitvec.tcp" +#endif + diff --git a/MUNGA/UNITVEC.h b/MUNGA/UNITVEC.h new file mode 100644 index 0000000..31128bf --- /dev/null +++ b/MUNGA/UNITVEC.h @@ -0,0 +1,64 @@ +#pragma once + +#include "vector3d.h" + +class LinearMatrix; + +class UnitVector : public Vector3D +{ +public: + UnitVector() {} + UnitVector(Scalar x, Scalar y, Scalar z) : Vector3D(x, y, z) {} + + UnitVector& operator=(const UnitVector &vector) + { + Check(&vector); + Vector3D::operator=(vector); + return *this; + } + UnitVector& operator=(const Vector3D& v) + { + Vector3D::Normalize(v); + return *this; + } + + UnitVector& Negate(const UnitVector &v) + { + Check(&v); + Vector3D::Negate(v); + return *this; + } + + Scalar operator*(const Vector3D& v) const { return Vector3D::operator*(v); } + + UnitVector& Multiply(const UnitVector &v, const LinearMatrix &m); + UnitVector& operator*=(const LinearMatrix &m); + UnitVector& MultiplyByInverse(const UnitVector &v, const LinearMatrix &m) + { + Vector3D::MultiplyByInverse(v, m); + return *this; + } + + UnitVector& Lerp(const UnitVector& v1, const UnitVector& v2, Scalar t); + + Logical TestInstance() const; + static Logical TestClass(); + +private: + static const UnitVector identity; + UnitVector& Negate(const Vector3D &V); + UnitVector& Add(const Vector3D& V1,const Vector3D& V2); + UnitVector& operator+=(const Vector3D& V); + UnitVector& Subtract(const Vector3D& V1,const Vector3D& V2); + UnitVector& operator-=(const Vector3D& V); + UnitVector& Cross(const Vector3D& V1,const Vector3D& V2); + UnitVector& Multiply(const Vector3D& V,Scalar Scale); + UnitVector& operator*=(Scalar Value); + UnitVector& Multiply(const Vector3D& V1,const Vector3D& V2); + UnitVector& operator*=(const Vector3D &V); + UnitVector& Multiply(const Vector3D &Source, const AffineMatrix &M); + UnitVector& MultiplyByInverse(const Vector3D &Source, const LinearMatrix &M); + UnitVector& Divide(const Vector3D& V,Scalar Scale); + UnitVector& operator/=(Scalar Value); + UnitVector& Combine(const Vector3D& V1,Scalar t1,const Vector3D& V2,Scalar t2); +}; diff --git a/MUNGA/UPDATE.cpp b/MUNGA/UPDATE.cpp new file mode 100644 index 0000000..1ff108b --- /dev/null +++ b/MUNGA/UPDATE.cpp @@ -0,0 +1,242 @@ +#include "munga.h" +#pragma hdrstop + +#include "update.h" +#include "app.h" +#include "hostmgr.h" +#include "interest.h" +#include "entity.h" + +#if defined(TRACE_UPDATE_REPLICANTS) + static BitTrace Update_Replicants("Update Replicants"); + #define SET_UPDATE_REPLICANTS() Update_Replicants.Set() + #define CLEAR_UPDATE_REPLICANTS() Update_Replicants.Clear() +#else + #define SET_UPDATE_REPLICANTS() + #define CLEAR_UPDATE_REPLICANTS() +#endif + +#if defined(TRACE_UPDATE_MASTERS) + static BitTrace Update_Masters("Update Masters"); + #define SET_UPDATE_MASTERS() Update_Masters.Set() + #define CLEAR_UPDATE_MASTERS() Update_Masters.Clear() +#else + #define SET_UPDATE_MASTERS() + #define CLEAR_UPDATE_MASTERS() +#endif + +MemoryBlock *SimulationEncore::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(SimulationEncore), 10, 10, "Simulation Encores"); + return &allocatedMemory; +} + +SimulationEncore::SimulationEncore( + Simulation *sim, + Simulation::Encore callback +) +{ + encoreSimulation = sim; + encoreCallback = callback; + runWatchers = True; +} + +SimulationEncore::~SimulationEncore() +{ +} + +// +//############################################################################# +//############################################################################# +// +UpdateManager::UpdateManager(): + simulationEncores(NULL) +{ +} + +// +//############################################################################# +//############################################################################# +// +UpdateManager::~UpdateManager() +{ + ChainIteratorOf encores(simulationEncores); + SimulationEncore *encore; + while ((encore = encores.ReadAndNext()) != NULL) + { + Unregister_Object(encore); + delete encore; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + UpdateManager::TestInstance() const +{ + Node::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + UpdateManager::Execute(Time target_render_time) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Execute the replicants and masters that are interesting and dynamic + //-------------------------------------------------------------------------- + // + Check(application); + Check(application->GetHostManager()); + + HostManager::DynamicReplicantEntityIterator + replicant_entity_iterator(application->GetHostManager()); + HostManager::DynamicMasterEntityIterator + master_entity_iterator(application->GetHostManager()); + + // + //-------------------------------------------------------------------------- + // Execute the replicants + //-------------------------------------------------------------------------- + // + SET_UPDATE_REPLICANTS(); + + Entity + *replicant; + + while ((replicant = replicant_entity_iterator.ReadAndNext()) != NULL) + { + Check(replicant); + if (replicant->IsReplicantExecutable()) + { + replicant->Execute(target_render_time); + } + } + + CLEAR_UPDATE_REPLICANTS(); + + // + //-------------------------------------------------------------------------- + // Execute the master entities, if they need to be updated then send + // update messages, and notify the interest manager of moved entities + //-------------------------------------------------------------------------- + // + SET_UPDATE_MASTERS(); + + Entity + *entity; + Entity::UpdateMessage + *update_message; + + while ((entity = master_entity_iterator.ReadAndNext()) != NULL) + { + Check(entity); + + // + //----------------------------------------------------------------------- + // If the entity is not interesting then skip it + //----------------------------------------------------------------------- + // + if (!entity->IsInteresting() || !entity->IsNonReplicantExecutable()) + { + continue; + } + + // + //----------------------------------------------------------------------- + // Run the execute method + //----------------------------------------------------------------------- + // + update_message = entity->Execute(target_render_time); + + // + //----------------------------------------------------------------------- + // Update the interest zone id + //----------------------------------------------------------------------- + // + Check(application); + Check(application->GetInterestManager()); + application->GetInterestManager()->EntityUpdateInterestZone(entity); + + // + //----------------------------------------------------------------------- + // If update message is not null then send the change + //----------------------------------------------------------------------- + // + if (update_message != NULL) + { + Check(update_message); + + Check(application); + application->GetInterestManager()->EntityUpdateReplicants( + entity, + update_message + ); + } + } + + // + //-------------------------------------------------------------------------- + // Lastly, run through and do any requested encores + //-------------------------------------------------------------------------- + // + ChainIteratorOf + encores(simulationEncores); + SimulationEncore + *encore; + + while ((encore = encores.ReadAndNext()) != NULL) + { + Check(encore); + Check(encore->encoreSimulation); + (encore->encoreSimulation->*encore->encoreCallback)(); + if (encore->runWatchers) + { + encore->encoreSimulation->ExecuteWatchers(); + encore->encoreSimulation->ClearWatcherDelay(); + } + Unregister_Object(encore); + delete encore; + } + CLEAR_UPDATE_MASTERS(); +} + +// +//############################################################################# +//############################################################################# +// +void + UpdateManager::RequestEncore( + Simulation *simulation, + Simulation::Encore encore + ) +{ + // + //---------------------------------------------------------------------- + // Make sure that we only run the watcher on a given simulation once per + // frame + //---------------------------------------------------------------------- + // + ChainIteratorOf encores(simulationEncores); + SimulationEncore *i; + while ((i = encores.ReadAndNext()) != NULL) + { + if (i->encoreSimulation == simulation && i->runWatchers) + { + i->runWatchers = False; + break; + } + } + + SimulationEncore *request = new SimulationEncore(simulation, encore); + Register_Object(request); + simulationEncores.Add(request); +} diff --git a/MUNGA/UPDATE.h b/MUNGA/UPDATE.h new file mode 100644 index 0000000..c9b08df --- /dev/null +++ b/MUNGA/UPDATE.h @@ -0,0 +1,64 @@ +#pragma once + +#include "node.h" +#include "time.h" +#include "memblock.h" +#include "simulate.h" + +class UpdateManager; + +class SimulationEncore : public Plug +{ + friend class UpdateManager; + +private: + static MemoryBlock* GetAllocatedMemory(); + + void* operator new(size_t) { return GetAllocatedMemory()->New(); } + void operator delete(void *where) { GetAllocatedMemory()->Delete(where); } + + Simulation *encoreSimulation; + Simulation::Encore encoreCallback; + Logical runWatchers; + + SimulationEncore(Simulation *sim, Simulation::Encore callback); + ~SimulationEncore(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ UpdateManager ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class UpdateManager : public Node +{ +public: + // + //-------------------------------------------------------------------- + // Construction, Destruction + //-------------------------------------------------------------------- + // + UpdateManager(); + ~UpdateManager(); + + Logical TestInstance() const; + + // + //-------------------------------------------------------------------- + // Execute + // + // Perform update management functions + //-------------------------------------------------------------------- + // + void Execute(Time target_render_time); + + // + //---------------------------------------------------------------------- + // CreateEncore + // + // Registers a callback to be executed after all entity performances are + // completed + //---------------------------------------------------------------------- + // + void RequestEncore(Simulation *simulation, Simulation::Encore encore); + +protected: + ChainOf simulationEncores; +}; diff --git a/MUNGA/VCHAIN.cpp b/MUNGA/VCHAIN.cpp new file mode 100644 index 0000000..d6cc5d5 --- /dev/null +++ b/MUNGA/VCHAIN.cpp @@ -0,0 +1,631 @@ +#include "munga.h" +#pragma hdrstop + +#include "vchain.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChainLink ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// VChainLink +//########################################################################### +// +VChainLink::VChainLink( + VChain *vchain, + Plug *plug +): + Link(vchain, plug) +{ + next = NULL; + prev = NULL; +} + +// +//########################################################################### +// ~VChainLink +//########################################################################### +// +VChainLink::~VChainLink() +{ + VChain *vchain = Cast_Object(VChain*, socket); + + // + //------------------------------------------- + // Notify iterators that deletion is occuring + //------------------------------------------- + // + vchain->SendIteratorMemo(PlugRemoved, this); + + // + //--------------------------- + // Remove from existing links + //--------------------------- + // + if (prev != NULL) + { + Check(prev); + prev->next = next; + } + else + { + Check(vchain); + vchain->head = next; + } + if (next != NULL) + { + Check(next); + next->prev = prev; + } + else + { + Check(vchain); + vchain->tail = prev; + } + prev = next = NULL; + + // + //------------------------------------------ + // Remove this link from any plug references + //------------------------------------------ + // + ReleaseFromPlug(); + + // + //------------------------------------------------------------- + // Tell the node to release this link. Note that this link + // is not referenced by the plug or the chain at this point in + // time. + //------------------------------------------------------------- + // + if (vchain->GetReleaseNode() != NULL) + { + Check(vchain->GetReleaseNode()); + vchain->GetReleaseNode()->ReleaseLinkHandler(vchain, plug); + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + VChainLink::TestInstance() const +{ + Link::TestInstance(); + + if (next != NULL) + { + Check_Signature(next); + } + if (prev != NULL) + { + Check_Signature(prev); + } + + return True; +} + +// +//########################################################################### +// SetupVChainLinks +//########################################################################### +// +void + VChainLink::SetupVChainLinks( + VChainLink *next, + VChainLink *prev + ) +{ + this->next = next; + this->prev = prev; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ VChain ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +// VChain +//########################################################################### +// +VChain::VChain( + Node *node, + Logical has_unique_entries +): + SortedSocket(node, has_unique_entries) +{ + head = NULL; + tail = NULL; +} + +// +//########################################################################### +// ~VChain +//########################################################################### +// +VChain::~VChain() +{ + SetReleaseNode(NULL); + while (head != NULL) + { + Unregister_Object(head); + delete head; + } +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + VChain::TestInstance() const +{ + SortedSocket::TestInstance(); + + if (head != NULL) + { + Check(head); + } + if (tail != NULL) + { + Check(tail); + } + + return True; +} + +// +//########################################################################### +// MakeVChainLink +//########################################################################### +// +VChainLink + *VChain::MakeVChainLink( + Plug*, + const void* + ) +{ + Fail("VChain::MakeVChainLink - Should never reach here"); + return NULL; +} + +// +//########################################################################### +// CompareVChainLinks +//########################################################################### +// +int + VChain::CompareVChainLinks( + VChainLink*, + VChainLink* + ) +{ + Fail("VChain::CompareVChainLinks - Should never reach here"); + return 0; +} + +// +//########################################################################### +// CompareValueToVChainLink +//########################################################################### +// +int + VChain::CompareValueToVChainLink( + const void*, + VChainLink* + ) +{ + Fail("VChain::CompareValueToVChainLink - Should never reach here"); + return 0; +} + +// +//########################################################################### +// AddImplementation +//########################################################################### +// +void + VChain::AddImplementation( + Plug *plug + ) +{ + AddValueImplementation(plug, NULL); +} + +// +//########################################################################### +// AddValueImplementation +//########################################################################### +// +void + VChain::AddValueImplementation( + Plug *plug, + const void *value + ) +{ + VChainLink *link; + + // + //------------------------------------------------------------- + // Verify that value has not been added + //------------------------------------------------------------- + // + Verify(HasUniqueEntries() ? (SearchForValue(value) == NULL) : (Logical)True); + + // + //------------------------------------------------------------- + // Make new vchain link + //------------------------------------------------------------- + // + link = MakeVChainLink(plug, value); + Register_Object(link); + + // + //------------------------------------------------------------- + // Find insertion point for the new link + //------------------------------------------------------------- + // + if (head == NULL) + { + link->SetupVChainLinks(NULL, NULL); + head = link; + tail = link; + } + else + { + VChainLink *greater_link; + + Check(head); + Check(tail); + + for ( + greater_link = head; + greater_link != NULL; + greater_link = greater_link->next + ) + { + Check(greater_link); + if (CompareValueToVChainLink(value, greater_link) < 0) + break; + } + + if (greater_link == NULL) + { + // + // Add after tail + // + link->SetupVChainLinks(NULL, tail); + tail->next = link; + tail = link; + } + else if (greater_link == head) + { + // + // Add before head + // + link->SetupVChainLinks(head, NULL); + head->prev = link; + head = link; + } + else + { + // + // Add before greater_link + // + link->SetupVChainLinks(greater_link, greater_link->prev); + greater_link->prev->next = link; + greater_link->prev = link; + } + } + + SendIteratorMemo(PlugAdded, link); +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + VChain::FindImplementation( + const void *value + ) +{ + VChainLink *link; + + if ((link = SearchForValue(value)) != NULL) + { + Check(link); + return link->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// SearchForValue +//########################################################################### +// +VChainLink* + VChain::SearchForValue( + const void *value + ) +{ + VChainLink *link; + int ret; + + for (link = head; link != NULL; link = link->next) + { + Check(link); + if ((ret = CompareValueToVChainLink(value, link)) == 0) + break; + if (ret < 0) + return(NULL); + } + return link; +} + +// +//########################################################################### +// VChainIterator +//########################################################################### +// +VChainIterator::VChainIterator(VChain *vchain): + SortedIterator(vchain) +{ + Check(vchain); + currentLink = vchain->head; +} + +// +//########################################################################### +// VChainIterator +//########################################################################### +// +VChainIterator::VChainIterator(const VChainIterator *iterator): + SortedIterator(Cast_Object(VChain*, iterator->socket)) +{ + Check(iterator); + currentLink = iterator->currentLink; +} + +// +//########################################################################### +//########################################################################### +// +VChainIterator::~VChainIterator() +{ +} + +// +//########################################################################### +// TestInstance +//########################################################################### +// +Logical + VChainIterator::TestInstance() const +{ + SortedIterator::TestInstance(); + + if (currentLink != NULL) + { + Check(currentLink); + } + + return True; +} + +// +//########################################################################### +// First +//########################################################################### +// +void + VChainIterator::First() +{ + currentLink = Cast_Object(VChain*, socket)->head; +} + +// +//########################################################################### +// Last +//########################################################################### +// +void + VChainIterator::Last() +{ + currentLink = Cast_Object(VChain*, socket)->tail; +} + +// +//########################################################################### +// Next +//########################################################################### +// +void + VChainIterator::Next() +{ + Check(currentLink); + currentLink = currentLink->next; +} + +// +//########################################################################### +// Previous +//########################################################################### +// +void + VChainIterator::Previous() +{ + Check(currentLink); + currentLink = currentLink->prev; +} + +// +//########################################################################### +// ReadAndNextImplementation +//########################################################################### +// +void + *VChainIterator::ReadAndNextImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->GetPlug(); + currentLink = currentLink->next; + return plug; + } + return NULL; +} + +// +//########################################################################### +// ReadAndPreviousImplementation +//########################################################################### +// +void + *VChainIterator::ReadAndPreviousImplementation() +{ + if (currentLink != NULL) + { + Plug *plug; + + Check(currentLink); + plug = currentLink->plug; + currentLink = currentLink->prev; + return plug; + } + return NULL; +} + +// +//########################################################################### +// GetCurrentImplementation +//########################################################################### +// +void + *VChainIterator::GetCurrentImplementation() +{ + if (currentLink != NULL) + { + Check(currentLink); + return currentLink->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// GetSize +//########################################################################### +// +CollectionSize + VChainIterator::GetSize() +{ + VChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(VChain*, socket)->head; + link != NULL; + link = link->next + ) + { + Check(link); + count++; + } + return count; +} + +// +//########################################################################### +// GetNthImplementation +//########################################################################### +// +void + *VChainIterator::GetNthImplementation( + CollectionSize index + ) +{ + VChainLink *link; + CollectionSize count; + + count = 0; + for ( + link = Cast_Object(VChain*, socket)->head; + link != NULL; + link = link->next + ) + { + Check(link); + if (count == index) + { + currentLink = link; + return currentLink->GetPlug(); + } + count++; + } + return NULL; +} + +// +//########################################################################### +// Remove +//########################################################################### +// +void + VChainIterator::Remove() +{ + Check(currentLink); + Unregister_Object(currentLink); + delete currentLink; +} + +// +//########################################################################### +// FindImplementation +//########################################################################### +// +Plug* + VChainIterator::FindImplementation( + const void *value + ) +{ + VChainLink *link; + + if ((link = Cast_Object(VChain*, socket)->SearchForValue(value)) != NULL) + { + Check(link); + return (currentLink = link)->GetPlug(); + } + return NULL; +} + +// +//########################################################################### +// ReceiveMemo +//########################################################################### +// +void + VChainIterator::ReceiveMemo( + IteratorMemo memo, + void *content + ) +{ + if (memo == PlugRemoved) + { + if (content == currentLink) + { + Next(); + } + } +} + +#if defined(TEST_CLASS) +# include "vchain.tcp" +#endif diff --git a/MUNGA/VCHAIN.h b/MUNGA/VCHAIN.h new file mode 100644 index 0000000..e2e5d93 --- /dev/null +++ b/MUNGA/VCHAIN.h @@ -0,0 +1,295 @@ +#pragma once + +#include "node.h" +#include "srtskt.h" +#include "memblock.h" + +class VChain; +class VChainIterator; + +class VChainLink : public Link +{ + friend class VChain; + friend class VChainIterator; + +public: + ~VChainLink(); + Logical TestInstance() const; + +protected: + VChainLink(VChain *vchain, Plug *plug); + +private: + void SetupVChainLinks(VChainLink *next, VChainLink *prev); + + VChainLink *next; + VChainLink *prev; +}; + +#define VCHAINLINK_MEMORYBLOCK_ALLOCATION (100) + +template class VChainLinkOf : public VChainLink +{ +public: + VChainLinkOf(VChain *vchain, Plug *plug, const V &value); + ~VChainLinkOf(); + + void* operator new(size_t); + void operator delete(void *where); + + V GetValue() { return value; } + V* GetValuePointer() { return &value; } + +private: + static MemoryBlock *allocatedMemory; + static CollectionSize allocationCount; + + V value; +}; + +template MemoryBlock* VChainLinkOf::allocatedMemory = NULL; +template CollectionSize VChainLinkOf::allocationCount = 0; + +template VChainLinkOf::VChainLinkOf(VChain *vchain, Plug *plug, const V &value) + : VChainLink(vchain, plug) +{ + this->value = value; +} + +template VChainLinkOf::~VChainLinkOf() {} + +#if 0 + template void *VChainLinkOf::operator new(size_t) + { + if (allocatedMemory == NULL) + allocatedMemory = new MemoryBlock(sizeof(VChainLinkOf), VCHAINLINK_MEMORYBLOCK_ALLOCATION, VCHAINLINE_MEMORYBLOCK_ALLOCATION); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void VChainLinkOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + } +#else + template void *VChainLinkOf::operator new(size_t) + { + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = new MemoryBlock(sizeof(VChainLinkOf), VCHAINLINK_MEMORYBLOCK_ALLOCATION, VCHAINLINK_MEMORYBLOCK_ALLOCATION, "VChainLinkOf"); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void VChainLinkOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); + } +#endif + +class VChain : public SortedSocket +{ + friend class VChainLink; + friend class VChainIterator; + +public: + VChain(Node *node, Logical has_unique_entries); + ~VChain(); + + Logical TestInstance() const; + static Logical TestClass(); + static Logical ProfileClass(); + +protected: + void AddImplementation(Plug *); + void AddValueImplementation(Plug *plug, const void *value); + Plug *FindImplementation(const void *value); + +private: + virtual VChainLink *MakeVChainLink(Plug *plug, const void *value); + virtual int CompareVChainLinks(VChainLink *link1, VChainLink *link2); + virtual int CompareValueToVChainLink(const void *value, VChainLink *link); + + VChainLink *SearchForValue(const void *value); + + VChainLink *head; + VChainLink *tail; +}; + +#define VCHAIN_MEMORYBLOCK_ALLOCATION (100) + +template class VChainOf : public VChain +{ +public: + VChainOf(Node *node, Logical has_unique_entries); + ~VChainOf(); + + void *operator new(size_t); + void operator delete(void *where); + + void AddValue(T plug, const V &value) { AddValueImplementation(Cast_Object(Plug*, plug), &value); } + T Find(const V &value) { return (T)FindImplementation(&value); } + +private: + VChainLink *MakeVChainLink(Plug *plug, const void *value) { return new VChainLinkOf(this, plug, *(V*)value); } + int CompareVChainLinks(VChainLink *link1, VChainLink *link2); + int CompareValueToVChainLink(const void *value, VChainLink *link); + + static MemoryBlock *allocatedMemory; + static CollectionSize allocationCount; +}; + +template MemoryBlock* VChainOf::allocatedMemory = NULL; +template CollectionSize VChainOf::allocationCount = 0; + +template VChainOf::VChainOf(Node *node, Logical has_unique_entries) + : VChain(node, has_unique_entries) +{ +} + +template VChainOf::~VChainOf() +{ +} + +template int VChainOf::CompareVChainLinks(VChainLink *link1, VChainLink *link2) +{ + V *ptr1 = Cast_Object(VChainLinkOf*, link1)->GetValuePointer(); + V *ptr2 = Cast_Object(VChainLinkOf*, link2)->GetValuePointer(); + + Check_Pointer(ptr1); + Check_Pointer(ptr2); + + if (*ptr1 == *ptr2) + return 0; + else + return ((*ptr1 > *ptr2) ? 1 : -1); +} + +template int VChainOf::CompareValueToVChainLink(const void *value, VChainLink *link) +{ + Check_Pointer(value); + + V *ptr = Cast_Object(VChainLinkOf*, link)->GetValuePointer(); + Check_Pointer(ptr); + + if (*(V*)value == *ptr) + return 0; + else + return (*(V*)value > *ptr) ? 1 : -1; +} + +#if 0 + template void *VChainOf::operator new(size_t) + { + if (allocatedMemory == NULL) + allocatedMemory = new MemoryBlock(sizeof(VChainOf), VCHAIN_MEMORYBLOCK_ALLOCATION, VCHAIN_MEMORYBLOCK_ALLOCATION); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void VChainOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + } +#else + template void *VChainOf::operator new(size_t) + { + Verify(allocationCount >= 0); + if (allocationCount++ == 0) + { + allocatedMemory = new MemoryBlock(sizeof(VChainOf), VCHAIN_MEMORYBLOCK_ALLOCATION, VCHAIN_MEMORYBLOCK_ALLOCATION, "VChainOf"); + Register_Object(allocatedMemory); + } + Verify(allocationCount < INT_MAX); + Check(allocatedMemory); + return allocatedMemory->New(); + } + + template void VChainOf::operator delete(void *where) + { + Check(allocatedMemory); + allocatedMemory->Delete(where); + if (--allocationCount == 0) + { + Unregister_Object(allocatedMemory); + delete allocatedMemory; + allocatedMemory = NULL; + } + Verify(allocationCount >= 0); + } +#endif + +class VChainIterator : public SortedIterator +{ +public: + VChainIterator(VChain *vchain); + VChainIterator(const VChainIterator *iterator); + ~VChainIterator(); + Logical TestInstance() const; + + void First(); + void Last(); + void Next(); + void Previous(); + CollectionSize GetSize(); + void Remove(); + +protected: + void *ReadAndNextImplementation(); + void *ReadAndPreviousImplementation(); + void *GetCurrentImplementation(); + void *GetNthImplementation(CollectionSize index); + Plug *FindImplementation(const void *value); + +protected: + VChainLink *currentLink; + +private: + void ReceiveMemo(IteratorMemo memo, void *content); +}; + +template class VChainIteratorOf : public VChainIterator +{ +public: + VChainIteratorOf(VChainOf *vchain); + VChainIteratorOf(VChainOf &vchain); + VChainIteratorOf(const VChainIteratorOf &iterator); + ~VChainIteratorOf(); + + T ReadAndNext() { return (T)ReadAndNextImplementation(); } + T ReadAndPrevious() { return (T)ReadAndPrevousImplementation(); } + T GetCurrent() { return (T)GetCurrentImplementation(); } + T GetNth(CollectionSize index) { return (T)GetNthImplementation(index); } + T Find(const V &value) { return (T)FindImplementation(&value); } + V GetValue() { return Cast_Object(VChainLinkOf*, currentLink)->GetValue(); } +}; + +template VChainIteratorOf::VChainIteratorOf(VChainOf *vchain) : VChainIterator(vchain) +{ +} + +template VChainIteratorOf::VChainIteratorOf(VChainOf &vchain) : VChainIterator(&vchain) +{ +} + +template VChainIteratorOf::VChainIteratorOf(const VChainIteratorOf &iterator) : VChainIterator(&iterator) +{ +} + +template VChainIteratorOf::~VChainIteratorOf() +{ +} \ No newline at end of file diff --git a/MUNGA/VDATA.cpp b/MUNGA/VDATA.cpp new file mode 100644 index 0000000..4438e5b --- /dev/null +++ b/MUNGA/VDATA.cpp @@ -0,0 +1,97 @@ +#include "munga.h" +#pragma hdrstop + +#include "vdata.h" +#include "objstrm.h" + +//############################################################################# +//####################### RegisteredClass ############################### +//############################################################################# + +RegisteredClass::RegisteredClass(ClassID class_id) +{ + classID = class_id; +} + +RegisteredClass::~RegisteredClass() +{ +} + +RegisteredClass::RegisteredClass(ObjectStream *stream) +{ + ObjectID object_ID; + + MemoryStream_Read(stream, &classID); + Verify(classID != NullClassID); + MemoryStream_Read(stream, &object_ID); +} + +void RegisteredClass::BuildFromPage(ObjectStream *stream, NameList*, ClassID class_ID, ObjectID object_ID) +{ + *stream << class_ID << object_ID; +} + +Logical RegisteredClass::TestInstance() const +{ + return true; +} + +// +//############################################################################# +// GetClassID +//############################################################################# +// +RegisteredClass::ClassID RegisteredClass::GetClassID(const CString &class_name_string) +{ + // + //-------------------------------------------------------------------------- + // HACK - Class name lookup could be perfromed via registration, for now, + // use if statements + //-------------------------------------------------------------------------- + // + #define COMPARE_AND_RETURN(class_name) if (!strcmp(class_name_string, #class_name)) return class_name##ClassID; + + COMPARE_AND_RETURN(AudioStateTrigger); + COMPARE_AND_RETURN(AudioMotionScale); + COMPARE_AND_RETURN(AudioRenderer); + COMPARE_AND_RETURN(AudioLocation); + COMPARE_AND_RETURN(AudioMotionTrigger); + COMPARE_AND_RETURN(AudioControlMixer); + COMPARE_AND_RETURN(AudioHingeScale); + COMPARE_AND_RETURN(AudioControlSmoother); + COMPARE_AND_RETURN(AudioResourceSelector); + COMPARE_AND_RETURN(L4AudioCollisionTrigger); + COMPARE_AND_RETURN(AudioResourceIndex); + COMPARE_AND_RETURN(AudioScalarScale); + COMPARE_AND_RETURN(AudioControlSend); + COMPARE_AND_RETURN(L4AudioLocation); + COMPARE_AND_RETURN(DirectPatchSource); + COMPARE_AND_RETURN(Dynamic3DPatchSource); + COMPARE_AND_RETURN(PatchResource); + COMPARE_AND_RETURN(Static3DPatchSource); + COMPARE_AND_RETURN(AudioControlMultiplier); + COMPARE_AND_RETURN(AudioSampleAndHold); + COMPARE_AND_RETURN(AudioScalarTrigger); + COMPARE_AND_RETURN(AudioEnumerationTrigger); + COMPARE_AND_RETURN(AudioIntegerTrigger); + COMPARE_AND_RETURN(AudioLogicalTrigger); + COMPARE_AND_RETURN(AudioControlsButtonTrigger); + COMPARE_AND_RETURN(ExplosionResourceTable); + COMPARE_AND_RETURN(AudioIdleWatcher); + COMPARE_AND_RETURN(AudioControlEvent); + COMPARE_AND_RETURN(AudioControlSequence); + COMPARE_AND_RETURN(AudioControlSplitter); + COMPARE_AND_RETURN(AudioLFO); + COMPARE_AND_RETURN(AudioEnumerationDeltaTrigger); + COMPARE_AND_RETURN(AudioScalarDeltaTrigger); + COMPARE_AND_RETURN(AudioLevelOfDetail); + COMPARE_AND_RETURN(PatchLevelOfDetail); + COMPARE_AND_RETURN(AudioMessageWatcher); + COMPARE_AND_RETURN(AudioControlsButtonMessageWatcher); + + // + // Etc... + // + + return NullClassID; +} diff --git a/MUNGA/VDATA.h b/MUNGA/VDATA.h new file mode 100644 index 0000000..6f6a616 --- /dev/null +++ b/MUNGA/VDATA.h @@ -0,0 +1,303 @@ +#pragma once + +#include "memstrm.h" + +class CString; +class ObjectStream; +class NameList; + +typedef unsigned long ObjectID; +const ObjectID NullObjectID = 0; + +typedef unsigned long RegisteredClassMemoryAddress; + +class RegisteredClass SIGNATURED +{ +public: + enum ClassID + { + // + //-------------- + // Munga classes + //-------------- + // + NullClassID = -1, + TrivialClassID = 0, + TrivialPlugClassID, + TrivialNodeClassID, + TrivialComponentClassID, + AttributeWatcherOfClassID, + ReceiverAttributeWatcherOfClassID, + MessageTapClassID, + DerivationClassID, + TrivialReceiverClassID, + EventClassID, + NetworkEventClassID, + GeneralEventQueueClassID, + EventQueueClassID, + DeferredEventQueueClassID, + TrivialModelClassID, + TrivialSubsystemClassID, + TrivialEntityClassID, + NetworkManagerClassID, + EntityManagerClassID, + EntityAttributeHandlerReferenceClassID, + PersistentReferenceClassID, + InterestManagerClassID, + HostManagerClassID, + ControlsInstanceClassID, + ControlsMappingGroupClassID, + ControlsOwnerClassID, + ControlsManagerClassID, + TrivialMoverClassID, + AudioStateTriggerClassID, + AudioMotionScaleClassID, + AudioRendererClassID, + AudioLocationClassID, + ApplicationClassID, + EntityGroupClassID, + GaugeConnectionClassID, + GaugeClassID, + GaugeRendererClassID, + CollisionAssistantClassID, + RendererManagerClassID, + AudioMotionTriggerClassID, + AudioMotionRandomTriggerClassID, + TerrainClassID, + UnscalableTerrainClassID, + AudioControlMixerClassID, + AudioHingeScaleClassID, + AudioControlSmootherClassID, + AudioControlMultiplierClassID, + AudioResourceSelectorClassID, + DropZoneClassID, + ExplosionClassID, + PlayerClassID, + JointSubsystemClassID, + AudioResourceIndexClassID, + AudioScalarScaleClassID, + AudioControlSendClassID, + GaugeEntityListClassID, + DirectControlsInstanceClassID, + EventControlsInstanceClassID, + AudioSampleAndHoldClassID, + AudioScalarTriggerClassID, + AudioEnumerationTriggerClassID, + AudioIntegerTriggerClassID, + AudioLogicalTriggerClassID, + EyeCandyClassID, + WarehouseObjectClassID, + WarehouseBinClassID, + AudioControlsButtonTriggerClassID, + IcomClassID, + IcomManagerClassID, + CameraShipClassID, + CameraDirectorClassID, + ExplosionResourceTableClassID, + ApplicationTaskClassID, + AudioIdleWatcherClassID, + AudioControlEventClassID, + AudioControlSequenceClassID, + AudioControlSplitterClassID, + ApplicationManagerClassID, + DamageZoneClassID, + AudioLFOClassID, + AudioEnumerationDeltaTriggerClassID, + AudioScalarDeltaTriggerClassID, + ControlsStringClassID, + ControlsStringManagerClassID, + AudioEntityClassID, + AudioLevelOfDetailClassID, + LandmarkClassID, + ScenarioRoleClassID, + TeamClassID, + AudioMessageWatcherClassID, + AudioControlsButtonMessageWatcherClassID, + GaugeAlarmManagerClassID, + GaugeAlarmClassID, + LightClassID, + CulturalIconClassID, + DoorFrameClassID, + DoorClassID, + + // + //--------------------------------- + // Class ID's for Munga LBE classes + //--------------------------------- + // + L4AudioLocationClassID = 1000, + DirectPatchSourceClassID, + Dynamic3DPatchSourceClassID, + L4ApplicationClassID, + PatchResourceClassID, + Static3DPatchSourceClassID, + L4AudioCollisionTriggerClassID, + L4GaugeImageManagerClassID, + L4ControlsManagerClassID, + L4IcomClassID, + L4IcomManagerClassID, + PatchLevelOfDetailClassID, + + // + //---------------------- + // Class ID's for RP + //---------------------- + // + RPL4ApplicationClassID = 2000, + VTVClassID, + RivetClassID, + DemolitionPackClassID, + BoosterClassID, + RivetGunClassID, + LaserDrillClassID, + DemolitionPackDropperClassID, + ChuteClassID, + ScoreZoneClassID, + VTVPowerClassID, + ThrusterClassID, + ControlsMapperClassID, + CrusherClassID, + BlockerClassID, + RunnerClassID, + RPDirectorClassID, + RPTeamClassID, + RPPlayerClassID, + + // + //------------------ + // Class ID's for BT + //------------------ + // + BTL4ApplicationClassID = 3000, + MechClassID, + MissileClassID, + MechSubsystemClassID, + HeatableSubsystemClassID, + CondenserClassID, + HeatSinkClassID, + HeatWatcherClassID, + ReservoirClassID, + GeneratorClassID, + PoweredSubsystemClassID, + SensorClassID, + GyroscopeClassID, + TorsoClassID, + MyomersClassID, + CapacitorClassID, + EmitterClassID, + LaserClassID, + ParticleCannonClassID, + AmmoBinClassID, + AmmoFeederClassID, + ProjectileWeaponClassID, + GaussRifleClassID, + BallisticWeaponClassID, + MissileLauncherClassID, + ProjectileClassID, + SeekerClassID, + SubsystemMessageManagerClassID, + PPCClassID, + PowerWatcherClassID, + HUDClassID, + RadarClassID, + SearchlightClassID, + ThermalSightClassID, + BTTeamClassID, + BTPlayerClassID, + BTDirectorClassID, + MechTechClassID, + TurretClassID, + + // + //------------------ + // Class ID's for ND + //------------------ + // + NDL4ApplicationClassID = 4000, + AirplaneClassID, + BulletClassID, + MachineGunClassID, + NDDirectorClassID, + NDTeamClassID, + NDPlayerClassID, + + // + //---------------------- + // Class ID's for Tools + //---------------------- + // + ShapeClassID = 60000, + ShapeGroupListClassID, + ShapeGroupClassID, + ShapePlaneClassID, + ShapePolygonClassID, + ShapeLineClassID, + ShapePointClassID, + VertexReferenceClassID, + VertexClassID, + MaterialLibraryClassID, + MaterialReferenceClassID, + MaterialClassID, + TargaImageClassID, + ShapeListClassID, + SkeletonClassID, + SkeletonJointClassID, + SkeletonSiteClassID, + SkeletonSegmentClassID, + ModelClassID, + + // + //--------------------------------- + // Class ID's for Munga W4 classes + //--------------------------------- + // + + W4ApplicationClassID = 70000, + W4ControlsManagerClassID, + + // + //------------- + // end of list + //------------- + // + MaxClassID + }; + +public: + RegisteredClass(ClassID class_id = TrivialClassID); + RegisteredClass(ObjectStream *stream); + virtual ~RegisteredClass(); + + Logical TestInstance() const; + +public: + ClassID GetClassID(); + + static ClassID GetClassID(const CString &class_name_string); + + RegisteredClassMemoryAddress GetMemoryAddress(); + +public: + static void BuildFromPage(ObjectStream *stream, NameList *name_list, ClassID class_ID, ObjectID object_ID); + +private: + ClassID classID; +}; + +inline RegisteredClass::ClassID RegisteredClass::GetClassID() +{ + Check(this); + return classID; +} + +inline RegisteredClassMemoryAddress RegisteredClass::GetMemoryAddress() +{ + Check(this); + return (RegisteredClassMemoryAddress)this; +} + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, RegisteredClass::ClassID *output) +{ return stream->ReadBytes(output, sizeof(*output)); } + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const RegisteredClass::ClassID *input) +{ return stream->WriteBytes(input, sizeof(*input)); } \ No newline at end of file diff --git a/MUNGA/VECTOR2D.h b/MUNGA/VECTOR2D.h new file mode 100644 index 0000000..68cfab6 --- /dev/null +++ b/MUNGA/VECTOR2D.h @@ -0,0 +1,286 @@ +#pragma once + +#include "scalar.h" +#include + +template class Vector2DOf +{ +public: + #if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile Vector2DOf *p); + #endif + +// static const Vector2DOf +// identity; + + T x, y; + + Vector2DOf() {} + Vector2DOf(T x, T y) : x(x), y(y) {} + + friend Logical Small_Enough(const Vector2DOf &v, Scalar e); + Logical operator!() const { return Small_Enough(*this,SMALL); } + + friend Logical Close_Enough(const Vector2DOf &v1, const Vector2DOf &v2, Scalar e); + Logical operator==(const Vector2DOf& v) const { return Close_Enough(*this,v,SMALL); } + Logical operator!=(const Vector2DOf& v) const { return !Close_Enough(*this,v,SMALL); } + + const T& operator[](size_t index) const + { + Check(this); + Warn(index>Y_Axis); + return (&x)[index]; + } + T& operator[](size_t index) + { + Check(this); + Warn(index>Y_Axis); + return (&x)[index]; + } + + // + //----------------------------------------------------------------------- + // The following operators all assume that this points to the destination + // of the operation results + //----------------------------------------------------------------------- + // + Vector2DOf& Negate(const Vector2DOf &v); + + Vector2DOf& Add(const Vector2DOf& v1, const Vector2DOf& v2); + Vector2DOf& operator+=(const Vector2DOf& v) { return Add(*this,v); } + + Vector2DOf& Subtract(const Vector2DOf& v1, const Vector2DOf& v2); + Vector2DOf& operator-=(const Vector2DOf& v) { return Subtract(*this,v); } + + T operator*(const Vector2DOf& v) const + { + Check(this); + Check(&v); + return x*v.x + y*v.y; + } + + Vector2DOf& Multiply(const Vector2DOf& v, T Scale); + Vector2DOf& operator*=(T v) { return Multiply(*this,v); } + + Vector2DOf& Multiply(const Vector2DOf& v1, const Vector2DOf& v2); + Vector2DOf& operator*=(const Vector2DOf &v) { return Multiply(*this,v); } + + Vector2DOf& Divide(const Vector2DOf& v, T scale); + Vector2DOf& operator/=(T v) { return Divide(*this,v); } + + Vector2DOf& Divide(const Vector2DOf& v1, const Vector2DOf& v2); + Vector2DOf& operator/=(const Vector2DOf &v) { return Divide(*this,v); } + + T LengthSquared() const + { + Check(this); + return operator*(*this); + } + T Length() const + { + Check(this); + return (T)Sqrt(LengthSquared()); + } + + Vector2DOf& Normalize(const Vector2DOf &v); + +#if 0 + Vector2DOf& Combine(const Vector2DOf& v1, Scalar t1, const Vector2DOf& v2, Scalar t2); + + Vector2DOf& Lerp(const Vector2DOf& v1, const Vector2DOf& v2, Scalar t) + { + return Combine(v1,1.0f-t,v2,t); + } +#endif + + friend std::ostream& operator<<(std::ostream& stream, const Vector2DOf& v); + Logical TestInstance() const; +}; + +#if defined(USE_SIGNATURE) + template int Is_Signature_Bad(const volatile Vector2DOf *) + { + return False; + } +#endif + +// template const Vector2DOf +// Vector2DOf::identity(0.0f,0.0f); + +template inline Logical + Small_Enough(const Vector2DOf &v,Scalar e) +{ + Check(&v); + return Small_Enough(v.x,e) && Small_Enough(v.y,e); +} + +//REMOVED: RB 1/15/07 +//template Logical +// Close_Enough( +// const Vector2DOf &v1, +// const Vector2DOf &v2, +// Scalar e +// ) +//{ +// Check(&v1); +// Check(&v2); +// return Close_Enough(v1.x,v2.x,e) && Close_Enough(v1.y,v2.y,e); +//} + +inline Logical Close_Enough(const Vector2DOf &v1, const Vector2DOf &v2, Scalar e) +{ + Check(&v1); + Check(&v2); + return Close_Enough(v1.x, v2.x,e) && Close_Enough(v1.y, v2.y,e); +} + +inline Logical Close_Enough(const Vector2DOf &v1, const Vector2DOf &v2, Scalar e) +{ + Check(&v1); + Check(&v2); + return Close_Enough(v1.x, v2.x,e) && Close_Enough(v1.y, v2.y,e); +} + +template inline Vector2DOf& + Vector2DOf::Negate(const Vector2DOf &v) +{ + Check(this); + Check(&v); + x = -v.x; + y = -v.y; + return *this; +} + +template inline Vector2DOf& + Vector2DOf::Add( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) +{ + Check(this); + Check(&v1); + Check(&v2); + x = v1.x + v2.x; + y = v1.y + v2.y; + return *this; +} + +template inline Vector2DOf& + Vector2DOf::Subtract( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) +{ + Check(this); + Check(&v1); + Check(&v2); + x = v1.x - v2.x; + y = v1.y - v2.y; + return *this; +} + +template inline Vector2DOf& + Vector2DOf::Multiply( + const Vector2DOf& v, + T scale + ) +{ + Check(this); + Check(&v); + x = v.x * scale; + y = v.y * scale; + return *this; +} + +template inline Vector2DOf& + Vector2DOf::Multiply( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) +{ + Check(this); + Check(&v1); + Check(&v2); + x = v1.x * v2.x; + y = v1.y * v2.y; + return *this; +} + +template inline Vector2DOf& + Vector2DOf::Divide( + const Vector2DOf& v, + T scale + ) +{ + Check(this); + Check(&v); + Verify(!Small_Enough(scale)); + x = v.x / scale; + y = v.y / scale; + return *this; +} + +template inline Vector2DOf& + Vector2DOf::Divide( + const Vector2DOf& v1, + const Vector2DOf& v2 + ) +{ + Check(this); + Check(&v1); + Check(&v2); + Verify(!Small_Enough(v2.x)); + Verify(!Small_Enough(v2.y)); + x = v1.x / v2.x; + y = v1.y / v2.y; + return *this; +} + +template inline Vector2DOf& Vector2DOf::Normalize(const Vector2DOf &v) +{ + Check_Pointer(this); + Check(&v); + + T len = v.Length(); + Verify(!Small_Enough(len)); + + x = v.x/len; + y = v.y/len; + return *this; +} + +//template std::ostream& operator<<(std::ostream& stream, const Vector2DOf& v) +//{ +// Check(&v); +// return stream << '<' << v.x << ',' << v.y << '>'; +//} + +template inline Logical Vector2DOf::TestInstance() const +{ + return true; +} + +inline std::ostream& operator<<(std::ostream& stream, const Vector2DOf& v) +{ + Check(&v); + return stream << '<' << v.x << ',' << v.y << '>'; +} + +#if 0 +template Vector2DOf& + Combine( + const Vector2DOf& v1, + Scalar t1, + const Vector2DOf& v2, + Scalar t2 + ) +{ + Check(this); + Check(&v1); + Check(&v2); + + x = v1.x*t1 + v2.x*t2; + y = v1.y*t1 + v2.y*t2; + return *this; +} +#endif \ No newline at end of file diff --git a/MUNGA/VECTOR3D.cpp b/MUNGA/VECTOR3D.cpp new file mode 100644 index 0000000..886bb38 --- /dev/null +++ b/MUNGA/VECTOR3D.cpp @@ -0,0 +1,326 @@ +#pragma hdrstop +#include +#include "vector3d.h" +#include "linmtrx.h" +#include "cstr.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AbstractVector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile AbstractVector3D *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +AbstractVector3D& AbstractVector3D::operator=(const AbstractVector3D &vector) +{ + x = vector.x; + y = vector.y; + z = vector.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical Small_Enough(const AbstractVector3D &V, Scalar e) +{ + return Small_Enough(V.x,e) && Small_Enough(V.y,e) && Small_Enough(V.z,e); +} + +// +//########################################################################### +//########################################################################### +// +Logical Close_Enough(const AbstractVector3D &V1, const AbstractVector3D &V2, Scalar e) +{ + return Close_Enough(V1.x,V2.x,e) && Close_Enough(V1.y,V2.y,e) && Close_Enough(V1.z,V2.z,e); +} + +// +//########################################################################### +//########################################################################### +// +Logical AbstractVector3D::TestInstance() const +{ + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const Vector3D Vector3D::Identity(0.0f, 0.0f, 0.0f); + +// +//########################################################################### +//########################################################################### +// +inline Vector3D& Vector3D::operator = (const LBE3Vector3D &vector) +{ + x = vector.x; + y = vector.z; + z = vector.y; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +inline Vector3D& Vector3D::operator = (const TIVector3D &vector) +{ + x = vector.x; + y = vector.y; + z = -vector.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Negate(const Vector3D &V) +{ + x = -V.x; + y = -V.y; + z = -V.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Add(const Vector3D& V1, const Vector3D& V2) +{ + x = V1.x + V2.x; + y = V1.y + V2.y; + z = V1.z + V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::AddScaled(const Vector3D& V1, const Vector3D& V2, Scalar scale) +{ + x = V1.x + V2.x*scale; + y = V1.y + V2.y*scale; + z = V1.z + V2.z*scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Subtract(const Vector3D& V1, const Vector3D& V2) +{ + x = V1.x - V2.x; + y = V1.y - V2.y; + z = V1.z - V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Cross(const Vector3D& v1, const Vector3D& v2) +{ + Verify(this != &v1); + Verify(this != &v2); + + x = v1.y * v2.z - v1.z * v2.y; + y = v1.z * v2.x - v1.x * v2.z; + z = v1.x * v2.y - v1.y * v2.x; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Multiply(const Vector3D& V, Scalar Scale) +{ + x = V.x * Scale; + y = V.y * Scale; + z = V.z * Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Multiply(const Vector3D& V1, const Vector3D& V2) +{ + x = V1.x * V2.x; + y = V1.y * V2.y; + z = V1.z * V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Divide(const Vector3D& V, Scalar Scale) +{ + Verify(!Small_Enough(Scale)); + x = V.x / Scale; + y = V.y / Scale; + z = V.z / Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Divide(const Vector3D& V1, const Vector3D& V2) +{ + Verify(!Small_Enough(V2.x)); + Verify(!Small_Enough(V2.y)); + Verify(!Small_Enough(V2.z)); + x = V1.x / V2.x; + y = V1.y / V2.y; + z = V1.z / V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Multiply(const Vector3D& v, const AffineMatrix& m) +{ + Verify(this != &v); + + x = v.x * m(0,0) + v.y * m(1,0) + v.z * m(2,0); + y = v.x * m(0,1) + v.y * m(1,1) + v.z * m(2,1); + z = v.x * m(0,2) + v.y * m(1,2) + v.z * m(2,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::MultiplyByInverse(const Vector3D& v, const LinearMatrix& m) +{ + Verify(this != &v); + + x = v.x * m(0,0) + v.y * m(0,1) + v.z * m(0,2); + y = v.x * m(1,0) + v.y * m(1,1) + v.z * m(1,2); + z = v.x * m(2,0) + v.y * m(2,1) + v.z * m(2,2); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Normalize(const Vector3D &V) +{ + Scalar len = V.Length(); + Verify(len); + + x = V.x / len; + y = V.y / len; + z = V.z / len; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector3D& Vector3D::Combine(const Vector3D& V1, Scalar t1, const Vector3D& V2, Scalar t2) +{ + x = t1 * V1.x + t2 * V2.x; + y = t1 * V1.y + t2 * V2.y; + z = t1 * V1.z + t2 * V2.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +std::ostream& operator<<(std::ostream& Stream, const Vector3D& V) +{ + return Stream << std::setprecision(4) << '<' << V.x << ',' << V.y << ',' << V.z << '>'; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//########################################################################### +//########################################################################### +// +void Convert_From_Ascii(const char *str, Vector3D *vector_3D) +{ + Check_Signature(vector_3D); + + CString parse_string(str); + + vector_3D->x = atof(parse_string.GetNthToken(0)); + vector_3D->y = atof(parse_string.GetNthToken(1)); + vector_3D->z = atof(parse_string.GetNthToken(2)); +} + +// +//########################################################################### +//########################################################################### +// +LBE3Vector3D& LBE3Vector3D::operator=(const Vector3D& vector) +{ + x = vector.x; + y = vector.z; + z = vector.y; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +LBE3Vector3D& LBE3Vector3D::operator=(const TIVector3D &vector) +{ + x = vector.x; + y = -vector.z; + z = vector.y; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +TIVector3D& TIVector3D::operator=(const Vector3D &vector) +{ + x = vector.x; + y = vector.y; + z = -vector.z; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +TIVector3D& TIVector3D::operator=(const LBE3Vector3D &vector) +{ + x = vector.x; + y = vector.z; + z = -vector.y; + return *this; +} diff --git a/MUNGA/VECTOR3D.h b/MUNGA/VECTOR3D.h new file mode 100644 index 0000000..44d0411 --- /dev/null +++ b/MUNGA/VECTOR3D.h @@ -0,0 +1,267 @@ +#pragma once + +#include +#include "memstrm.h" +#include "scalar.h" + +class AbstractVector3D; +class Vector3D; +class LBE3Vector3D; +class TIVector3D; +class AffineMatrix; +class LinearMatrix; +class Matrix4x4; +class Point3D; + +enum Axes +{ + X_Axis, + Y_Axis, + Z_Axis, + W_Axis +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ AbstractVector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class AbstractVector3D +{ +public: + Scalar x, y , z; + +#if defined(USE_SIGNATURE) + friend int Is_Signature_Bad(const volatile AbstractVector3D *p); +#endif + + AbstractVector3D& operator = (const AbstractVector3D& v); + + friend Logical Small_Enough(const AbstractVector3D &v, Scalar e=SMALL); + Logical operator ! () const { return Small_Enough(*this, SMALL); } + + friend Logical Close_Enough(const AbstractVector3D &v1, const AbstractVector3D &v2, Scalar e=SMALL); + Logical operator == (const AbstractVector3D& v) const { return Close_Enough(*this, v, SMALL); } + Logical operator != (const AbstractVector3D& v) const { return !Close_Enough(*this,v,SMALL); } + Logical TestInstance() const; + +protected: + AbstractVector3D() {} + AbstractVector3D(Scalar x, Scalar y, Scalar z) : x(x), y(y), z(z) {} +}; + +inline MemoryStream& MemoryStream_Read(MemoryStream* stream, AbstractVector3D *output) +{ + return stream->ReadBytes(output, sizeof(*output)); +} + +inline MemoryStream& MemoryStream_Write(MemoryStream* stream, const AbstractVector3D *input) +{ + return stream->WriteBytes(input, sizeof(*input)); +} + +class LBE3Vector3D; +class TIVector3D; +class AffineMatrix; +class LinearMatrix; +class Matrix4x4; +class Point3D; + +class Vector3D : public AbstractVector3D +{ +public: + static const Vector3D Identity; + + // + // Constructors + // + Vector3D() {} + Vector3D(Scalar x, Scalar y, Scalar z) : AbstractVector3D(x,y,z) {} + + // + // Assignment operators + // + Vector3D& operator = (const Vector3D &vector) + { + AbstractVector3D::operator=(vector); + return *this; + } + + Vector3D& operator = (const LBE3Vector3D &vector); + Vector3D& operator = (const TIVector3D &vector); + + // Comparison operator (for sorting by length, GDU 1/26/96) + Logical operator > (const Vector3D &v) const + { + return LengthSquared() > v.LengthSquared(); + } + + Logical operator < (const Vector3D &v) const + { + return LengthSquared() < v.LengthSquared(); + } + + // + // Indexing operations + // + const Scalar& operator[](size_t index) const + { + Warn(index>Z_Axis); + return (&x)[index]; + } + + Scalar& operator[](size_t index) + { + Warn(index>Z_Axis); + return (&x)[index]; + } + + // + // The following operators all assume that this points to the destination + // of the operation results + // + Vector3D& Negate(const Vector3D &v); + + Vector3D& Add(const Vector3D& v1, const Vector3D& v2); + Vector3D& AddScaled(const Vector3D& v1, const Vector3D& v2, Scalar scale); + Vector3D& operator+=(const Vector3D& v) { return Add(*this,v); } + + Vector3D& Subtract(const Vector3D& v1, const Vector3D& v2); + Vector3D& operator -= (const Vector3D& v) { return Subtract(*this,v); } + + Scalar operator * (const Vector3D& v) const + { + Check(this); + Check(&v); + return x * v.x + y * v.y + z * v.z; + } + + Vector3D& Cross(const Vector3D& v1, const Vector3D& v2); + + Vector3D& Multiply(const Vector3D& v, Scalar Scale); + Vector3D& operator *= (Scalar v) + { + return Multiply(*this, v); + } + + Vector3D& Multiply(const Vector3D& v1, const Vector3D& v2); + Vector3D& operator *= (const Vector3D &v) + { + return Multiply(*this, v); + } + + Vector3D& Divide(const Vector3D& v, Scalar scale); + Vector3D& operator /= (Scalar v) + { + return Divide(*this,v); + } + + Vector3D& Divide(const Vector3D& v1, const Vector3D& v2); + Vector3D& operator /= (const Vector3D &v) + { + return Divide(*this, v); + } + + // + // Transform operators + // + Vector3D& Multiply(const Vector3D &v, const AffineMatrix &m); + Vector3D& operator *= (const AffineMatrix &m) + { + Vector3D src(*this); + return Multiply(src, m); + } + Vector3D& MultiplyByInverse(const Vector3D &v, const LinearMatrix &m); + + // + // Miscellaneous functions + // + Scalar LengthSquared() const + { + Check(this); + return x * x + y * y + z * z; + } + Scalar Length() const + { + return sqrt(LengthSquared()); + } + + Vector3D& Normalize(const Vector3D &v); + + Vector3D& Combine(const Vector3D& v1, Scalar t1, const Vector3D& v2, Scalar t2); + + // + // Template support + // + Vector3D& Lerp(const Vector3D& v1, const Vector3D& v2, Scalar t) + { + return Combine(v1, 1.0f - t, v2, t); + } + + // + // Support functions + // + friend std::ostream& operator << (std::ostream& stream, const Vector3D& v); + static Logical TestClass(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector3D functions ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +void Convert_From_Ascii(const char *str, Vector3D *vector_3D); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ LBE3Vector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class LBE3Vector3D : public AbstractVector3D +{ +public: + // + // Constructors + // + LBE3Vector3D() {} + LBE3Vector3D(Scalar x, Scalar y, Scalar z) : AbstractVector3D(x, y, z) {} + + // + // Assignment operators + // + LBE3Vector3D& operator = (const LBE3Vector3D &vector) + { + Check_Pointer(this); + Check(&vector); + AbstractVector3D::operator=(vector); + return *this; + } + LBE3Vector3D& operator = (const Vector3D& vector); + LBE3Vector3D& operator = (const TIVector3D &vector); + + // + // Support functions + // + friend std::ostream& operator << (std::ostream &stream, const LBE3Vector3D &vector); + static Logical TestClass(); +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ TIVector3D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class TIVector3D : public AbstractVector3D +{ +public: + // + // Constructors + // + TIVector3D() {} + TIVector3D(Scalar x, Scalar y, Scalar z) : AbstractVector3D(x,y,z) {} + + // + // Assignment operators + // + TIVector3D& operator = (const TIVector3D &vector) + { + AbstractVector3D::operator=(vector); + return *this; + } + TIVector3D& operator = (const Vector3D &vector); + TIVector3D& operator = (const LBE3Vector3D &vector); + + // + // Support functions + // + friend std::ostream& operator << (std::ostream &stream, const TIVector3D &vector); + static Logical TestClass(); +}; diff --git a/MUNGA/VECTOR4D.cpp b/MUNGA/VECTOR4D.cpp new file mode 100644 index 0000000..1023c57 --- /dev/null +++ b/MUNGA/VECTOR4D.cpp @@ -0,0 +1,365 @@ +#include "munga.h" +#pragma hdrstop + +#include "vector4d.h" +#include "matrix.h" +#include "point3d.h" +#include "affnmtrx.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector4D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +const Vector4D + Vector4D::Identity(0.0f,0.0f,0.0f,0.0f); + +#if defined(USE_SIGNATURE) + int + Is_Signature_Bad(const volatile Vector4D *) + { + return False; + } +#endif + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::operator=(const Vector4D &v) +{ + Check_Pointer(this); + Check(&v); + + x = v.x; + y = v.y; + z = v.z; + w = v.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::operator=(const Vector3D &v) +{ + Check_Pointer(this); + Check(&v); + + x = v.x; + y = v.y; + z = v.z; + w = 0.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::operator=(const Point3D &p) +{ + Check_Pointer(this); + Check(&p); + + x = p.x; + y = p.y; + z = p.z; + w = 1.0f; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Small_Enough(const Vector4D &V,Scalar e) +{ + Check(&V); + return + Small_Enough(V.x,e) + && Small_Enough(V.y,e) + && Small_Enough(V.z,e) + && Small_Enough(V.w,e); +} + +// +//########################################################################### +//########################################################################### +// +Logical + Close_Enough(const Vector4D &V1, const Vector4D &V2, Scalar e) +{ + Check(&V1); + Check(&V2); + return + Close_Enough(V1.x,V2.x,e) + && Close_Enough(V1.y,V2.y,e) + && Close_Enough(V1.z,V2.z,e) + && Close_Enough(V1.w,V2.w,e); +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Negate(const Vector4D &V) +{ + Check_Pointer(this); + Check(&V); + + x = -V.x; + y = -V.y; + z = -V.z; + w = -V.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Add(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x + V2.x; + y = V1.y + V2.y; + z = V1.z + V2.z; + w = V1.w + V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Subtract(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x - V2.x; + y = V1.y - V2.y; + z = V1.z - V2.z; + w = V1.w - V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply(const Vector4D& V,Scalar Scale) +{ + Check_Pointer(this); + Check(&V); + + x = V.x * Scale; + y = V.y * Scale; + z = V.z * Scale; + w = V.w * Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x * V2.x; + y = V1.y * V2.y; + z = V1.z * V2.z; + w = V1.w * V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Divide(const Vector4D& V,Scalar Scale) +{ + Check_Pointer(this); + Check(&V); + Verify(!Small_Enough(Scale)); + + x = V.x / Scale; + y = V.y / Scale; + z = V.z / Scale; + w = V.w / Scale; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Divide(const Vector4D& V1,const Vector4D& V2) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + Verify(!Small_Enough(V1.x)); + Verify(!Small_Enough(V1.y)); + Verify(!Small_Enough(V1.z)); + Verify(!Small_Enough(V1.w)); + + x = V1.x / V2.x; + y = V1.y / V2.y; + z = V1.z / V2.z; + w = V1.w / V2.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Vector4D& v, + const AffineMatrix& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + Verify(this != &v); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0) + v.w*m(3,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1) + v.w*m(3,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2) + v.w*m(3,2); + w = v.w; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Vector4D& v, + const Matrix4x4& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + Verify(this != &v); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0) + v.w*m(3,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1) + v.w*m(3,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2) + v.w*m(3,2); + w = v.x*m(0,3) + v.y*m(1,3) + v.z*m(2,3) + v.w*m(3,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Vector3D& v, + const Matrix4x4& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2); + w = v.x*m(0,3) + v.y*m(1,3) + v.z*m(2,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Multiply( + const Point3D& v, + const Matrix4x4& m + ) +{ + Check_Pointer(this); + Check(&v); + Check(&m); + + x = v.x*m(0,0) + v.y*m(1,0) + v.z*m(2,0) + m(3,0); + y = v.x*m(0,1) + v.y*m(1,1) + v.z*m(2,1) + m(3,1); + z = v.x*m(0,2) + v.y*m(1,2) + v.z*m(2,2) + m(3,2); + w = v.x*m(0,3) + v.y*m(1,3) + v.z*m(2,3) + m(3,3); + return *this; +} + +// +//########################################################################### +//########################################################################### +// +Vector4D& + Vector4D::Combine( + const Vector4D& V1, + Scalar t1, + const Vector4D& V2, + Scalar t2 + ) +{ + Check_Pointer(this); + Check(&V1); + Check(&V2); + + x = V1.x*t1 + V2.x*t2; + y = V1.y*t1 + V2.y*t2; + z = V1.z*t1 + V2.z*t2; + w = V1.w*t1 + V2.w*t2; + return *this; +} + +// +//########################################################################### +//########################################################################### +// +std::ostream& operator<<(std::ostream& Stream, const Vector4D& V) +{ + Check(&V); + return Stream << std::setprecision(4) << '<' << V.x << ',' + << V.y << ',' << V.z << ',' << V.w << '>'; +} + +// +//########################################################################### +//########################################################################### +// +Logical + Vector4D::TestInstance() const +{ + return True; +} + +#if defined(TEST_CLASS) +# include "vector4d.tcp" +#endif diff --git a/MUNGA/VECTOR4D.h b/MUNGA/VECTOR4D.h new file mode 100644 index 0000000..6b41b6b --- /dev/null +++ b/MUNGA/VECTOR4D.h @@ -0,0 +1,204 @@ +#pragma once + +#include "scalar.h" + +class Vector3D; +class Point3D; +class AffineMatrix; +class Matrix4x4; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Vector4D ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class Vector4D +{ + public: + Scalar + x, + y, + z, + w; + + #if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile Vector4D *); + #endif + + static const Vector4D + Identity; + + // + // Constructors + // + Vector4D() + {} + Vector4D( + Scalar X, + Scalar Y, + Scalar Z, + Scalar W) + {x=X; y=Y; z=Z; w=W;} + + // + // Assignment operators + // + Vector4D& + operator=(const Vector4D &v); + Vector4D& + operator=(const Vector3D &v); + Vector4D& + operator=(const Point3D &p); + + // + // Index operators + // + const Scalar& + operator[](size_t index) const + {Check_Pointer(this); Warn(index>W_Axis); return (&x)[index];} + Scalar& + operator[](size_t index) + {Check_Pointer(this); Warn(index>W_Axis); return (&x)[index];} + + friend Logical + Small_Enough(const Vector4D &v,Scalar e=SMALL); + Logical + operator!() const + {return Small_Enough(*this);} + + // + // "Close-enough" comparison operators + // + friend Logical + Close_Enough( + const Vector4D &v1, + const Vector4D &v2, + Scalar e=SMALL + ); + Logical + operator==(const Vector4D& v) const + {return Close_Enough(*this,v);} + Logical + operator!=(const Vector4D& v) const + {return !Close_Enough(*this,v);} + + // + // The following operators all assume that this points to the destination + // of the operation results + // + Vector4D& + Negate(const Vector4D &v); + + Vector4D& + Add( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator+=(const Vector4D& v) + {return Add(*this,v);} + + Vector4D& + Subtract( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator-=(const Vector4D& v) + {return Subtract(*this,v);} + + Scalar + operator*(const Vector4D& v) const + {Check(this); return x*v.x + y*v.y + z*v.z + w*v.w;} + + Vector4D& + Multiply( + const Vector4D& v, + Scalar scale + ); + Vector4D& + operator*=(Scalar v) + {return Multiply(*this,v);} + + Vector4D& + Multiply( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator*=(const Vector4D &v) + {return Multiply(*this,v);} + + Vector4D& + Divide( + const Vector4D& v, + Scalar scale + ); + Vector4D& + operator/=(Scalar v) + {return Divide(*this,v);} + + Vector4D& + Divide( + const Vector4D& v1, + const Vector4D& v2 + ); + Vector4D& + operator/=(const Vector4D &v) + {return Divide(*this,v);} + + // + // Transforms + // + Vector4D& + Multiply( + const Vector4D &v, + const AffineMatrix &m + ); + Vector4D& + operator*=(const AffineMatrix &M) + {Vector4D src(*this); return Multiply(src,M);} + Vector4D& Multiply( + const Vector4D &v, + const Matrix4x4 &m + ); + Vector4D& + operator*=(const Matrix4x4 &m) + {Vector4D src(*this); return Multiply(src,m);} + Vector4D& Multiply( + const Vector3D &v, + const Matrix4x4 &m + ); + Vector4D& Multiply( + const Point3D &p, + const Matrix4x4 &m + ); + + // + // Support functions + // + Scalar + LengthSquared() const + {return operator*(*this);} + Scalar + Length() const + {return Sqrt(LengthSquared());} + + Vector4D& + Combine( + const Vector4D& v1, + Scalar t1, + const Vector4D& v2, + Scalar t2 + ); + + Vector4D& + Lerp( + const Vector4D& v1, + const Vector4D& v2, + Scalar t + ) + {return Combine(v1,1.0f-t,v2,t);} + + friend std::ostream& operator<<(std::ostream& stream, const Vector4D& v); + Logical TestInstance() const; + static Logical TestClass(); +}; diff --git a/MUNGA/VERIFY.cpp b/MUNGA/VERIFY.cpp new file mode 100644 index 0000000..e02c714 --- /dev/null +++ b/MUNGA/VERIFY.cpp @@ -0,0 +1,198 @@ +#include "munga.h" +#pragma hdrstop + +#include "controls.h" +#include "gaugrend.h" +//#include "windows.h" + +#if defined(__BCPLUSPLUS__) +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +int _matherr(struct exception *a) +{ + switch (a->type) + { + case DOMAIN: + DEBUG_STREAM << "Domain" << std::flush; + break; + case SING: + DEBUG_STREAM << "Singularity" << std::flush; + break; + case UNDERFLOW: + DEBUG_STREAM << "Underflow" << std::flush; + break; + case OVERFLOW: + DEBUG_STREAM << "Overflow" << std::flush; + break; + case TLOSS: + DEBUG_STREAM << "Loss of Precision" << std::flush; + break; + } + DEBUG_STREAM << " error occurred in " << a->name << endl << std::flush; + DEBUG_STREAM << "arg1 = " << a->arg1 << endl << std::flush; + DEBUG_STREAM << "arg2 = " << a->arg2 << endl << std::flush; + DEBUG_STREAM << "retval = " << a->retval << endl << std::flush << std::flush; + return 0; +} +#else +int _matherr(struct exception *) +{ + _fpreset(); + return 1; +} +#endif + +extern "C" void _pure_error_() +{ + Fail("Pure virtual function called"); +} +#endif + + +// +//############################################################################# +// Fpu_Ok +// +// returns True if fpu has no errors, False if errors found +//############################################################################# +// +int + Fpu_Ok() +{ + unsigned int s = + _status87() & + ( + SW_INVALID | +// SW_DENORMAL | + SW_ZERODIVIDE | + SW_OVERFLOW +// SW_UNDERFLOW | +//VERIFY: SW_STACKFAULT + ); + if (s) + { + DEBUG_STREAM << "ERROR: FPU status=" << std::flush; + + if (s & SW_INVALID) + { + DEBUG_STREAM << "invalid " << std::flush; + } + if (s & SW_DENORMAL) + { + DEBUG_STREAM << "denormalized " << std::flush; + } + if (s & SW_ZERODIVIDE) + { + DEBUG_STREAM << "zeroDivide " << std::flush; + } + if (s & SW_OVERFLOW) + { + DEBUG_STREAM << "overflow " << std::flush; + } + if (s & SW_UNDERFLOW) + { + DEBUG_STREAM << "underflow " << std::flush; + } + /*if (s & SW_STACKFAULT) + { + DEBUG_STREAM << "stackFault" << std::flush; + }*/ + DEBUG_STREAM << "\n" << std::flush << std::flush; + return False; + } + else + { + return True; + } +} + +// +//############################################################################# +//############################################################################# +// +static Logical AlreadyFailed=False; + +void Verify_Failed(char *Message, char *File, int Line) +{ + if (!AlreadyFailed) + { + AlreadyFailed = True; + + DEBUG_STREAM << File << "(" << Line << "): Failed " << Message << "\n" << std::flush; + #if defined(USE_PROFILE_ANALYSIS) + Analysis_Named_Status(); + #endif + DEBUG_STREAM << "Failing to debugger\n" << std::flush << std::flush; + SystemClock::timer.Shutdown(); + ControlsManager::Shutdown(); + GaugeRenderer::EmergencyShutdown(); + *(int*)(0xFFFFFFFF) = 0; + } +} + +// +//############################################################################# +//############################################################################# +// +void + Fail_To_Debugger(char *Message, char *File, int Line) +{ + if (!AlreadyFailed) + { + AlreadyFailed = True; + + DEBUG_STREAM << File << "(" << Line << "): " << Message << "\n" << std::flush; + #if defined(USE_PROFILE_ANALYSIS) + Analysis_Named_Status(); + #endif + DEBUG_STREAM << "Failing to debugger\n" << std::flush << std::flush; + SystemClock::timer.Shutdown(); + ControlsManager::Shutdown(); + GaugeRenderer::EmergencyShutdown(); + *(int*)(0xFFFFFFFF) = 0; + } +} + +// +//############################################################################# +//############################################################################# +// +#if defined(USE_SIGNATURE) +Signature::Signature() +{ + #if DEBUG_LEVEL>0 + mark = magic; + #endif +} + +Signature::~Signature() +{ + #if DEBUG_LEVEL>0 + mark = noMagic; + #endif +} + +int + Is_Signature_Bad(const volatile Signature *p) +{ + #if DEBUG_LEVEL>0 + if (p->mark == Signature::magic) + { + return Signature::ok; + } + else if (p->mark == Signature::noMagic) + { + return Signature::destroyed; + } + else + { + return Signature::corrupted; + } + #else + return False; + #endif +} +#endif diff --git a/MUNGA/VERIFY.h b/MUNGA/VERIFY.h new file mode 100644 index 0000000..5307f8e --- /dev/null +++ b/MUNGA/VERIFY.h @@ -0,0 +1,41 @@ +#pragma once + +#if defined(__BCPLUSPLUS__) + extern int _matherr(struct exception *a); +#endif + +extern int Fpu_Ok(); +extern void Verify_Failed(char *message, char *file, int line); +//extern void Fail_To_Debugger(char *message, char *file, int line); + +class Signature +{ +private: +#if DEBUG_LEVEL>0 + enum Mark + { + ok, + destroyed, + corrupted, + noMagic=(int)0xAB135795L, + magic=(int)0xFFED1231L + } mark; +#endif + +protected: + Signature(); + ~Signature(); + +public: + friend int Is_Signature_Bad(const volatile Signature *p); +}; + +#if defined(USE_SIGNATURE) +# define SIGNATURED : public Signature +#else +# define SIGNATURED +# define Is_Signature_Bad(p) (false) +#endif + +#endif + diff --git a/MUNGA/VIDREND.cpp b/MUNGA/VIDREND.cpp new file mode 100644 index 0000000..268396b --- /dev/null +++ b/MUNGA/VIDREND.cpp @@ -0,0 +1,261 @@ +#include "munga.h" +#pragma hdrstop + +#include "vidrend.h" +#include "app.h" +#include "entity.h" + +#if defined(USE_ONE_VIDEO_TRACE) || defined(TRACE_VIDEO_RENDERER) + BitTrace Video_Renderer("Video Renderer"); +#endif + +#if !defined(USE_ONE_VIDEO_TRACE) +# if defined(TRACE_VIDEO_BECOME_INTERESTING) + BitTrace Video_Become_Interesting("Video Become Interesting"); +# endif + +# if defined(TRACE_VIDEO_BECOME_UNINTERESTING) + BitTrace Video_Become_Uninteresting("Video Become Uninteresting"); +# endif +#endif + +// +//############################################################################# +// Constructor for the video renderer +//############################################################################# +// +VideoRenderer::VideoRenderer( + RendererRate calibration_rate, + RendererComplexity calibration_complexity, + RendererPriority calibration_priority, + InterestType interest_type, + InterestDepth depth_calibration +): + Renderer( + calibration_rate, + calibration_complexity, + calibration_priority, + interest_type, + depth_calibration + ) +{ + Disconnected_Eye = False; +} +// +//############################################################################# +// Destructor for the video renderer +//############################################################################# +// +VideoRenderer::~VideoRenderer() +{ +} +// +//############################################################################# +// This creates the data structures and loads up data for an entity that has +// become interesting to the renderer. +//############################################################################# +// +void + VideoRenderer::NotifyOfNewInterestingEntity(Entity *interesting_entity) +{ + ResourceDescription + *video_resource; + ResourceFile + *this_resource_file; + ResourceDescription::ResourceID + this_resource_ID; + ViewFrom + view_this_entity_from; + // + // Check the newly interesting entity, then determine what kind of view we want + // to construct for it by seeing if it is the linked entity and checking to + // see if the eye is disconnected at a higher renderer level. + // + SET_VIDEO_BECOME_INTERESTING(); + Check(interesting_entity); + if(Disconnected_Eye) + { + view_this_entity_from = outsideEntity; + } + else + { + if(interesting_entity == GetLinkedEntity()) + { + view_this_entity_from = insideEntity; + } + else + { + view_this_entity_from = outsideEntity; + } + } + // + // Try to fetch this entity's video resource, if there isn't one, we still + // call make renderables as something up above us may have code to construct + // some effects independant of the resource file. + // + Check(application); + this_resource_file = application->GetResourceFile(); + Check(this_resource_file); + this_resource_ID = interesting_entity->GetResourceID(); + video_resource = this_resource_file->SearchList( + this_resource_ID, + ResourceDescription::VideoModelResourceType); + // + // Call the make renderables process to convert the resource script into a + // set of renderables for this entity. + // + if (video_resource) + { + video_resource->Lock(); + } + MakeEntityRenderables( + interesting_entity, + video_resource, + view_this_entity_from + ); + if (video_resource) + { + video_resource->Unlock(); + } + + CLEAR_VIDEO_BECOME_INTERESTING(); +} +// +//############################################################################# +// This handles killing off of an entity that has become uninteresting. +//############################################################################# +// +void + VideoRenderer::NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity) +{ + SET_VIDEO_BECOME_UNINTERESTING(); + // + // Destroy the dynamic entities that go with this uninteresting Entity + // in the reverse order that they were created. + // + { + Entity::DynamicVideoSocketIterator + iterator(uninteresting_entity); + Component + *component; + + Check(&iterator); + iterator.Last(); + while ((component = iterator.ReadAndPrevious()) != NULL) + { + Unregister_Object(component); + delete component; + } + } + + // + // Destroy the static entities that go with this uninteresting Entity + // in the reverse order that they were created. + // + { + Entity::StaticVideoSocketIterator + iterator(uninteresting_entity); + Component + *component; + + Check(&iterator); + iterator.Last(); + while ((component = iterator.ReadAndPrevious()) != NULL) + { + Unregister_Object(component); + delete component; + } + } + + #if 0 + // + // Destroy all the static and dynamic entities that go with this uninteresting Entity + // in the same order they were created. This caused some problems for DPL in the past + // but it may no longer be the case. + // + + Entity::DynamicVideoSocketIterator iterator(uninteresting_entity); + iterator.DeletePlugs(); + + Entity::StaticVideoSocketIterator static_iterator(uninteresting_entity); + static_iterator.DeletePlugs(); + + uninteresting_entity->DeleteVideoWatchers(); + #endif + + CLEAR_VIDEO_BECOME_UNINTERESTING(); +} +// +//############################################################################# +// Execute Method, performs the rendering of one frame +//############################################################################# +// +void + VideoRenderer::ExecuteImplementation( + RendererComplexity, + RendererOrigin::InterestingEntityIterator * + ) +{ + Tell("VideoRenderer::ExecuteImplementation has been called\n"); +} +// +//############################################################################# +// This process is supposed to make the renderables for an object, when a higher +// level of this virtual can't figure out how to make something it calls down +// to the level below it. If we reach here then nobody could figure out what +// to do so we can print an error or information message. +//############################################################################# +// +void + VideoRenderer::MakeEntityRenderables( + Entity* my_entity, // The entity we are dealing with + ResourceDescription*, // Pointer to the video resource + ViewFrom) // Type of reference (inside/outside...etc.) +{ + switch (my_entity->GetClassID()) + { + // + // Scorezones are allowed to have no graphics. + // + case ScoreZoneClassID: + break; + // + // Default case complains about missing graphics + // + default: + DEBUG_STREAM<<"Entity "<entityID<<" class"<GetClassID() << std::flush; + DEBUG_STREAM<<" couldn't figure out how to MakeEntityRenderables\n" << std::flush; + break; + } +} +// +//############################################################################# +// Startup the implementation of the Division video renderer +//############################################################################# +// +void + VideoRenderer::LoadMissionImplementation(Mission*) +{ + Tell("VideoRenderer::StartImplementation has been called\n"); +} +void + VideoRenderer::ShutdownImplementation() +{ + Tell("VideoRenderer::StopImplementation has been called\n"); +} +void + VideoRenderer::SuspendImplementation() +{ + Tell("VideoRenderer::SuspendImplementation has been called\n"); +} +void + VideoRenderer::ResumeImplementation() +{ + Tell("VideoRenderer::ResumeImplementation has been called\n"); +} + +Logical + VideoRenderer::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA/VIDREND.h b/MUNGA/VIDREND.h new file mode 100644 index 0000000..469db75 --- /dev/null +++ b/MUNGA/VIDREND.h @@ -0,0 +1,108 @@ +#pragma once + +#include "slot.h" +#include "chain.h" +#include "renderer.h" +#include + +#if defined(TRACE_VIDEO_RENDERER) || defined(USE_ONE_VIDEO_TRACE) +extern BitTrace Video_Renderer; +#endif + +#if defined(TRACE_VIDEO_RENDERER) +#define SET_VIDEO_RENDERER() Video_Renderer.Set() +#define CLEAR_VIDEO_RENDERER() Video_Renderer.Clear() +#else +#define SET_VIDEO_RENDERER() +#define CLEAR_VIDEO_RENDERER() +#endif + +#if defined(TRACE_VIDEO_BECOME_INTERESTING) +#if defined(USE_ONE_VIDEO_TRACE) +#define SET_VIDEO_BECOME_INTERESTING() Video_Renderer.Set() +#define CLEAR_VIDEO_BECOME_INTERESTING() Video_Renderer.Clear() +#else +extern BitTrace Video_Become_Interesting; +#define SET_VIDEO_BECOME_INTERESTING() Video_Become_Interesting.Set() +#define CLEAR_VIDEO_BECOME_INTERESTING()\ +Video_Become_Interesting.Clear() +#endif +#else +#define SET_VIDEO_BECOME_INTERESTING() +#define CLEAR_VIDEO_BECOME_INTERESTING() +#endif + +#if defined(TRACE_VIDEO_BECOME_UNINTERESTING) +#if defined(USE_ONE_VIDEO_TRACE) +#define SET_VIDEO_BECOME_UNINTERESTING() Video_Renderer.Set() +#define CLEAR_VIDEO_BECOME_UNINTERESTING() Video_Renderer.Clear() +#else +extern BitTrace Video_Become_Uninteresting; +#define SET_VIDEO_BECOME_UNINTERESTING()\ +Video_Become_Uninteresting.Set() +#define CLEAR_VIDEO_BECOME_UNINTERESTING()\ +Video_Become_Uninteresting.Clear() +#endif +#else +#define SET_VIDEO_BECOME_UNINTERESTING() +#define CLEAR_VIDEO_BECOME_UNINTERESTING() +#endif + +class VideoRenderer : public Renderer +{ +public: + VideoRenderer(RendererRate calibration_rate, RendererComplexity calibration_complexity, RendererPriority calibration_priority, InterestType interest_type, InterestDepth depth_calibration); + ~VideoRenderer(); + + Logical TestInstance() const; + + virtual void ConsolidateStaticObjects() = 0; + virtual std::vector MonitorsCreateAll(int &count) = 0; + + // + //-------------------------------------------------------------------- + // NotifyOfNewInterestingEntity + // + // This method tells the renderer that a new entity will be in it's + // interest list the next time the Execute method is called. + //-------------------------------------------------------------------- + // + void NotifyOfNewInterestingEntity(Entity *interesting_entity); + + void NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity); + + virtual int *GetSecondaryIndex() = 0; + virtual int *GetAux1Index() = 0; + virtual int *GetAux2Index() = 0; + +private: + void LoadMissionImplementation(Mission *mission); + void ShutdownImplementation(); + void SuspendImplementation(); + void ResumeImplementation(); + void ExecuteImplementation(RendererComplexity complexity_update, RendererOrigin::InterestingEntityIterator *iterator); + +protected: + + enum ViewFrom + { + outsideEntity, // The external view of an entity will be displayed + insideEntity, // The internal view of the entity will be displayed + collisionEntity // The collision solids of the entity will be displayed + }; + + // + //-------------------------------------------------------------------- + // MakeEntityRenderables + // + // This method is called to create the renderables for a given entity + // it must be provided by the hardware specific renderer. + //-------------------------------------------------------------------- + // + virtual void MakeEntityRenderables(Entity*, ResourceDescription*, ViewFrom); + + Logical Disconnected_Eye; // If this is true, we will construct an outside + // version of the viewpoint entity. This is so + // higher level renderers can fix the eye in one + // spot and watch the viewpoint entity drive around. +}; \ No newline at end of file diff --git a/MUNGA/WATCHER.cpp b/MUNGA/WATCHER.cpp new file mode 100644 index 0000000..45f0b32 --- /dev/null +++ b/MUNGA/WATCHER.cpp @@ -0,0 +1,192 @@ +#include "munga.h" +#pragma hdrstop + +#include "watcher.h" +#include "entity.h" +#include "cstr.h" +#include "objstrm.h" +#include "namelist.h" +#include "subsystm.h" + +//############################################################################# +//########################## AttributeWatcher ########################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +AttributeWatcher::~AttributeWatcher() +{ +} + +// +//############################################################################# +//############################################################################# +// +AttributeWatcher::AttributeWatcher( + PlugStream *stream, + Entity *entity +): + Component(stream) +{ + Check(stream); + Check(entity); + +#if 0 + // + // Get attribute ptr + // + int subsystem_ID; + DynamicMemoryStream_Read(stream, &subsystem_ID); + + Simulation *simulation; + if ((simulation = entity->GetSubsystem(subsystem_ID)) == NULL) + { + simulation = entity; + } + Check(simulation); + + Simulation::AttributeID attribute_ID; + DynamicMemoryStream_Read(stream, &attribute_ID); + attributePointer = simulation->GetAttributePointer(attribute_ID); + Check_Pointer(attributePointer); +#else + // + // HACK - Get attribute pointer using names + // + CString subsystem_name; + *stream >> subsystem_name; + + if ((simulation = entity->FindSubsystem(subsystem_name)) == NULL) + { + #if DEBUG_LEVEL>0 + { + CString entity_name("Entity"); + if (!(subsystem_name == entity_name)) + { + Dump(subsystem_name); + } + Verify(subsystem_name == entity_name); + } + #else + { + CString entity_name("Entity"); + if (!(subsystem_name == entity_name)) + { + DEBUG_STREAM << + "AttributeWatcher::AttributeWatcher - subsystem " << + subsystem_name << + "\n"; + Fail("AttributeWatcher::AttributeWatcher - subsystem not found\n"); + } + } + #endif + simulation = entity; + } + Check(simulation); + + CString attribute_name; + *stream >> attribute_name; + + #if DEBUG_LEVEL>2 + Tell("AttributeWatcher::AttributeWatcher - " << attribute_name << "\n"); + #endif + + attributePointer = simulation->GetAttributePointer(attribute_name); + + #if DEBUG_LEVEL>0 + if (attributePointer == NULL) + { + Dump(attribute_name); + } + #else + if (attributePointer == NULL) + { + DEBUG_STREAM << + "AttributeWatcher::AttributeWatcher - attribute " << + attribute_name << + "\n"; + Fail("AttributeWatcher::AttributeWatcher - attribute not found\n"); + } + #endif + + Check_Pointer(attributePointer); +#endif + + // + // Get other fields + // + *stream >> sendNotificationOnChange; + attributeChanged = False; +} + +// +//############################################################################# +// BuildFromPage +//############################################################################# +// +void + AttributeWatcher::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Component::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // HACK - Store attribute pointer using names + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, subsystem); + MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, attribute); + + // + // Store other fields + // + Logical send_notification_on_change = True; + *stream << send_notification_on_change; +} + +// +//############################################################################# +//############################################################################# +// +Logical + AttributeWatcher::TestInstance() const +{ + Component::TestInstance(); + Check(simulation); + Check_Pointer(attributePointer); + return True; +} + +// +//############################################################################# +//############################################################################# +// +Logical + AttributeWatcher::DidAttributeChange() +{ + if (attributeChanged) + { + attributeChanged = False; + return True; + } + return False; +} + +// +//############################################################################# +//############################################################################# +// +void + AttributeWatcher::SendNotificationOfChange() +{ + Fail("AttributeWatcher::SendNotificationOfChange - Should never reach here"); +} + +#ifdef TEST_CLASS +# include "watcher.tcp" +#endif diff --git a/MUNGA/WATCHER.h b/MUNGA/WATCHER.h new file mode 100644 index 0000000..289c053 --- /dev/null +++ b/MUNGA/WATCHER.h @@ -0,0 +1,311 @@ +#pragma once + +#include "cmpnnt.h" +#include "slot.h" +#include "memstrm.h" + +class PlugStream; +class Simulation; +class Entity; + +//########################################################################## +//########################### AttributeWatcher ####################### +//########################################################################## + +class AttributeWatcher: + public Component +{ +public: + // + //----------------------------------------------------------------------- + // Destructor + //----------------------------------------------------------------------- + // + ~AttributeWatcher(); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // DidAttributeChange + // + // Returns True if attribute has changed since the last time + // DidAttributeChange was called. + //----------------------------------------------------------------------- + // + Logical + DidAttributeChange(); + +protected: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AttributeWatcher( + PlugStream *stream, + Entity *entity + ); + + // + //----------------------------------------------------------------------- + // SendNotificationOfChange + //----------------------------------------------------------------------- + // + virtual void + SendNotificationOfChange(); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Protected data + //----------------------------------------------------------------------- + // + Simulation* + simulation; + void* + attributePointer; + Logical + attributeChanged; + Logical + sendNotificationOnChange; +}; + +//########################################################################## +//########################### AttributeWatcherOf ##################### +//########################################################################## + +template class AttributeWatcherOf: + public AttributeWatcher +{ +public: + ~AttributeWatcherOf(); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + T + GetCurrentValue() + {return currentValue;} + T* + GetCurrentPointer() + {return ¤tValue;} + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + void + Execute(); + + // + //----------------------------------------------------------------------- + // PrimeWatcher + //----------------------------------------------------------------------- + // + void + PrimeWatcher(); + +protected: + // + //----------------------------------------------------------------------- + // Constructor + //----------------------------------------------------------------------- + // + AttributeWatcherOf( + PlugStream *stream, + Entity *entity + ); + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +private: + // + //----------------------------------------------------------------------- + // InitializeCurrentValue + //----------------------------------------------------------------------- + // + void + InitializeCurrentValue(); + + // + //----------------------------------------------------------------------- + // GrabCurrentValue + //----------------------------------------------------------------------- + // + void + GrabCurrentValue(); + + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + virtual void + DumpValue(const T *attribute_ptr); + + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + T + currentValue; + #if DEBUG_LEVEL>0 + Logical + dumpValue; + #endif +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ AttributeWatcherOf templates ~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AttributeWatcherOf::~AttributeWatcherOf() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template + AttributeWatcherOf::AttributeWatcherOf( + PlugStream *stream, + Entity *entity + ): + AttributeWatcher(stream, entity) +{ + Check_Pointer(this); + + Logical dump_value; + + MemoryStream_Read(stream, &dump_value); + + #if DEBUG_LEVEL>0 + dumpValue = dump_value; + if (dumpValue) + { + Tell( + "AttributeWatcherOf::AttributeWatcherOf - " << + *(T*)attributePointer << + "\n" + ); + } + #endif + + InitializeCurrentValue(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AttributeWatcherOf::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + Check(stream); + Check(name_list); + + AttributeWatcher::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store dump_value + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, dump_value); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AttributeWatcherOf::PrimeWatcher() +{ + Check(this); + #if DEBUG_LEVEL>0 + if (dumpValue) + { + DumpValue((T*)attributePointer); + } + #endif + GrabCurrentValue(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AttributeWatcherOf::Execute() +{ + Check(this); + + Check_Pointer(attributePointer); + if (!(currentValue == *(T*)attributePointer)) + { + #if DEBUG_LEVEL>0 + if (dumpValue) + { + DumpValue((T*)attributePointer); + } + #endif + GrabCurrentValue(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AttributeWatcherOf::InitializeCurrentValue() +{ + Check_Pointer(attributePointer); + currentValue = *(T*)attributePointer; + Verify(currentValue == *(T*)attributePointer); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +template void + AttributeWatcherOf::GrabCurrentValue() +{ + InitializeCurrentValue(); + attributeChanged = True; + if (sendNotificationOnChange) + { + SendNotificationOfChange(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +#if DEBUG_LEVEL>0 +template void + AttributeWatcherOf::DumpValue(const T *attribute_ptr) +#else +template void + AttributeWatcherOf::DumpValue(const T*) +#endif +{ + Check_Pointer(attribute_ptr); + Tell((void *)attribute_ptr << " = " << *attribute_ptr << "\n"); +} diff --git a/MUNGA/WRHOUS.cpp b/MUNGA/WRHOUS.cpp new file mode 100644 index 0000000..19eeef8 --- /dev/null +++ b/MUNGA/WRHOUS.cpp @@ -0,0 +1,167 @@ +#include "munga.h" +#pragma hdrstop + +#include "wrhous.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//####################################################################### +// WarehouseObject +//####################################################################### +WarehouseObject::WarehouseObject( + const char *new_name, + Logical keep_forever +): + Plug(WarehouseObject::WarehouseObjectClassID) +{ + Test_Tell("WarehouseObject::WarehouseObject(" << new_name << "\n"); + Str_Copy(name, new_name, sizeof(name)); + resourceID = ResourceDescription::NullResourceType; + + referenceCount = 1; // at least one reference exists, otherwise no obj + keepForever = keep_forever; + Check_Fpu(); +} + +WarehouseObject::WarehouseObject( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever +): + Plug(WarehouseObject::WarehouseObjectClassID) +{ + Test_Tell("WarehouseObject::WarehouseObject(" << new_resource_id << "\n"); + name[0] = '\0'; + resourceID = new_resource_id; + + referenceCount = 1; // at least one reference exists, otherwise no obj + keepForever = keep_forever; + Check_Fpu(); +} + +WarehouseObject::~WarehouseObject() +{ + Check(this); + Check_Fpu(); +} + +Logical + WarehouseObject::TestInstance() const +{ + return True; +} + +//####################################################################### +// WarehouseBin +//####################################################################### +WarehouseBin::WarehouseBin() : + Node(WarehouseBin::WarehouseBinClassID), + instanceList(this) +{ + Test_Tell("WarehouseBin::WarehouseBin()\n"); + Check_Pointer(this); + + Check_Fpu(); +} + +WarehouseBin::~WarehouseBin() +{ + Check(this); +} + +Logical + WarehouseBin::TestInstance() const +{ + return True; +} + +WarehouseObject * + WarehouseBin::Find(const char *old_name) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + WarehouseObject + *object_instance; + + while ((object_instance=i.ReadAndNext()) != NULL) + { + Check(object_instance); + if (stricmp(object_instance->name, old_name) == 0) + { + Check_Fpu(); + return object_instance; + } + } + Check_Fpu(); + return NULL; +} + +WarehouseObject * + WarehouseBin::Find(ResourceDescription::ResourceID old_resource_id) +{ + Check(this); + + ChainIteratorOf + i(instanceList); + + WarehouseObject + *object_instance; + + while ((object_instance=i.ReadAndNext()) != NULL) + { + Check(object_instance); + if (object_instance->resourceID == old_resource_id) + { + Check_Fpu(); + return object_instance; + } + } + Check_Fpu(); + return NULL; +} + +//####################################################################### +// Warehouse +//####################################################################### +Warehouse::Warehouse() +{ + Test_Tell("Warehouse::Warehouse\n"); + Check_Pointer(this); +} + +Warehouse::~Warehouse() +{ + Test_Tell("Warehouse::~Warehouse\n"); + Check(this); + Purge(); + Check_Fpu(); +} + +void + Warehouse::Purge() +{ + Check(this); + + bitMapBin.Purge(); + pixelMap8Bin.Purge(); + palette8Bin.Purge(); + + Check_Fpu(); +} + + +Logical + Warehouse::TestInstance() const +{ + Check_Pointer(this); + return True; +} + diff --git a/MUNGA/WRHOUS.h b/MUNGA/WRHOUS.h new file mode 100644 index 0000000..2b0bfa8 --- /dev/null +++ b/MUNGA/WRHOUS.h @@ -0,0 +1,452 @@ +#pragma once + +#include "resource.h" +#include "chain.h" +#include "node.h" +#include "plug.h" +#include "graph2d.h" + +//####################################################################### +// WarehouseObject +//####################################################################### +class WarehouseObject : + public Plug +{ + friend class WarehouseBin; +public: + WarehouseObject( + const char *new_name, + Logical keep_forever = False + ); + + WarehouseObject( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever = False + ); + + ~WarehouseObject(); + + Logical + TestInstance() const; + + void + SetKeepForever(Logical keep_forever) + { + Check(this); + keepForever = keep_forever; + } + + Logical + GetKeepForever() + { + Check(this); + return keepForever; + } + + void + Reference() + { + Check(this); + ++referenceCount; + } + + Logical + Unreference() // returns True if no longer referenced + { + Check(this); + return (Logical) ((--referenceCount) <= 0); + } + + +protected: + char + name[32]; + ResourceDescription::ResourceID + resourceID; + int + referenceCount; + Logical + keepForever; +}; + +//----------------------------------------------------------------------- +// WarehouseObjectOf +//----------------------------------------------------------------------- +template class WarehouseObjectOf: + public WarehouseObject +{ +public: + WarehouseObjectOf( + const char *new_name, + T *new_pointer, + Logical keep_forever = False + ); + + WarehouseObjectOf( + ResourceDescription::ResourceID new_resource_id, + T *new_pointer, + Logical keep_forever = False + ); + + virtual ~WarehouseObjectOf(); + + Logical + TestInstance() const; + + T + *dataPointer; +}; + +template + WarehouseObjectOf::WarehouseObjectOf( + const char *new_name, + T *new_pointer, + Logical keep_forever + ): + WarehouseObject(new_name, keep_forever) + { + Register_Pointer(new_pointer); + dataPointer = new_pointer; + } + +template + WarehouseObjectOf::WarehouseObjectOf( + ResourceDescription::ResourceID new_resource_id, + T *new_pointer, + Logical keep_forever + ): + WarehouseObject(new_resource_id, keep_forever) + { + Register_Pointer(new_pointer); + dataPointer = new_pointer; + } + +template WarehouseObjectOf::~WarehouseObjectOf() + { + Check(dataPointer); + Unregister_Pointer(dataPointer); + delete dataPointer; + dataPointer = NULL; // safety check + } + +template Logical + WarehouseObjectOf::TestInstance() const + { + Check_Pointer(this); + Check_Pointer(dataPointer); + return WarehouseObject::TestInstance(); + } + +//####################################################################### +// WarehouseBin +//####################################################################### +class WarehouseBin : + public Node +{ +public: + WarehouseBin(); + ~WarehouseBin(); + Logical + TestInstance() const; + void + Add(WarehouseObject *new_object) + { + Check(this); + Check_Pointer(new_object); + instanceList.Add(new_object); + } + + void + Remove(void *old_object); + WarehouseObject * + Find(const char *name); + WarehouseObject * + Find(ResourceDescription::ResourceID new_resource_id); + +protected: + ChainOf + instanceList; +}; + + +template class WarehouseBinOf : + public WarehouseBin +{ + friend class WarehouseBin; +public: + WarehouseBinOf(); + ~WarehouseBinOf(); + + Logical + TestInstance() const; + + T* + Get( + const char *name, + Logical keep_forever = False + ); + + T* + Get( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever = False + ); + + T* + GetIfAlreadyExists( + const char *name + ); + + T* + GetIfAlreadyExists( + ResourceDescription::ResourceID new_resource_id + ); + + void + Release( + const char *name + ); + void + Release( + ResourceDescription::ResourceID new_resource_id + ); + + void + Purge(); +}; + +//-------------------------------------------------------------------- +template Logical + WarehouseBinOf::TestInstance() const +{ + Check_Pointer(this); + return WarehouseBin::TestInstance(); +} + +//-------------------------------------------------------------------- +template + WarehouseBinOf::WarehouseBinOf() + : WarehouseBin() +{ +} + +//-------------------------------------------------------------------- +template WarehouseBinOf::~WarehouseBinOf() +{ + Check(this); + + Purge(); // remove EVERYTHING unconditionally + Check_Fpu(); +} + +//-------------------------------------------------------------------- +template T* + WarehouseBinOf::Get( + const char *name, + Logical keep_forever + ) +{ + Check(this); + + WarehouseObjectOf + *instance = + (WarehouseObjectOf*) WarehouseBin::Find(name); + + if (instance != NULL) + { + instance->Reference(); + return instance->dataPointer; + } + else + { + T *new_object = T::Make(name); + + if (new_object != NULL) + { + Check(new_object); + // new_object is registered in the warehouseObject creator + instance = new WarehouseObjectOf( + name, + new_object, + keep_forever + ); + Register_Object(instance); + WarehouseBin::Add(instance); + return new_object; + } + } + return NULL; +} + +template T* + WarehouseBinOf::Get( + ResourceDescription::ResourceID new_resource_id, + Logical keep_forever + ) +{ + Check(this); + + WarehouseObjectOf + *instance = + (WarehouseObjectOf*) WarehouseBin::Find(new_resource_id); + + if (instance != NULL) + { + instance->Reference(); + return instance->dataPointer; + } + else + { + T *new_object = T::Make(new_resource_id); + + if (new_object != NULL) + { + Check(new_object); + // new_object is registered in the warehouseObject creator + instance = new WarehouseObjectOf( + new_resource_id, + new_object, + keep_forever + ); + Register_Object(instance); + WarehouseBin::Add(instance); + return new_object; + } + } + return NULL; +} + +//-------------------------------------------------------------------- +template T* + WarehouseBinOf::GetIfAlreadyExists( + const char *name + ) +{ + Check(this); + Check_Pointer(name); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf *) WarehouseBin::Find(name); + if (warehouse_object != NULL) + { + Check(warehouse_object); + warehouse_object->Reference(); + + Check(warehouse_object->dataPointer); + return warehouse_object->dataPointer; + } + return NULL; +} + +template T* + WarehouseBinOf::GetIfAlreadyExists( + ResourceDescription::ResourceID id + ) +{ + Check(this); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf*) WarehouseBin::Find(id); + if (warehouse_object != NULL) + { + Check(warehouse_object); + warehouse_object->Reference(); + + Check(warehouse_object->dataPointer); + return warehouse_object->dataPointer; + } + return NULL; +} + +//-------------------------------------------------------------------- +template void + WarehouseBinOf::Release( + const char *name + ) +{ + Check(this); + Check_Pointer(name); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf *) WarehouseBin::Find(name); + if (warehouse_object != NULL) + { + Check(warehouse_object); + if (warehouse_object->Unreference()) + { + if (warehouse_object->GetKeepForever() == False) + { + Unregister_Object(warehouse_object); + // the dataPointer is deregistered & deleted in the destructor + delete warehouse_object; + } + } + } +} + +template void + WarehouseBinOf::Release( + ResourceDescription::ResourceID id + ) +{ + Check(this); + + WarehouseObjectOf + *warehouse_object = (WarehouseObjectOf *) WarehouseBin::Find(id); + if (warehouse_object != NULL) + { + Check(warehouse_object); + if (warehouse_object->Unreference()) + { + if (warehouse_object->GetKeepForever() == False) + { + Unregister_Object(warehouse_object); + // the dataPointer is deregistered & deleted in the destructor + delete warehouse_object; + } + } + } +} + +template void + WarehouseBinOf::Purge() +{ + Check(this); + //------------------------------------------ + // Delete everything in the bin + //------------------------------------------ + ChainIteratorOf + i(instanceList); + + WarehouseObject + *object_instance; + + while ((object_instance=i.ReadAndNext()) != NULL) + { + Check(object_instance); + Unregister_Object(object_instance); + delete object_instance; + } + Check_Fpu(); +} + +//####################################################################### +// Warehouse +//####################################################################### +class Warehouse SIGNATURED +{ +public: + Warehouse(); + virtual ~Warehouse(); + Logical + TestInstance() const; + virtual void + Purge(); + + WarehouseBinOf + bitMapBin; + WarehouseBinOf + pixelMap8Bin; + WarehouseBinOf + palette8Bin; +}; diff --git a/MUNGA/cultural.h b/MUNGA/cultural.h new file mode 100644 index 0000000..230e88e --- /dev/null +++ b/MUNGA/cultural.h @@ -0,0 +1,352 @@ +#pragma once + +#include "terrain.h" +#include "memstrm.h" +#include "resource.h" +#include "notation.h" +#include "team.h" + +class ScenarioRole; + +//########################################################################## +//################## CulturalIcon::ModelResource ####################### +//########################################################################## + +struct CulturalIcon__ModelResource +{ + Scalar destroyedYTranslation; + Scalar timeDelay; + ResourceDescription::ResourceID explosionResourceID; + ResourceDescription::ResourceID crunchExplosionResourceID; + Logical sinkCollisionVolume, stoppingCollisionVolume; +}; + +//########################################################################## +//##################### Class CulturalIcon ########################## +//########################################################################## + +class CulturalIcon : + public UnscalableTerrain +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + + +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +public: + enum { + SetBurningStateMessageID = UnscalableTerrain::NextMessageID, + NextMessageID + }; + + void + TakeDamageMessageHandler(TakeDamageMessage *damage_message); + void + SetBurningStateMessageHandler(Message *burning_message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Collision Volume Support +// +protected: + + void + UpdateCollisionVolumes(); + + enum { + RemoveCollisionVolumeOnDeathBit = UnscalableTerrain::NextBit, + StoppingCollisionVolumeBit, + NextBit + }; + + enum { + RemoveCollisionVolumeOnDeathFlag = 1 << RemoveCollisionVolumeOnDeathBit, + StoppingCollisionVolumeFlag = 1 << StoppingCollisionVolumeBit + }; + + void + SetRemoveCollisionVolumeFlag() + {Check(this); simulationFlags |= RemoveCollisionVolumeOnDeathFlag;} + + Logical RemoveCollisionVolumeOnDeath() const + { + Check(this); + return (simulationFlags & RemoveCollisionVolumeOnDeathFlag) != 0; + } + + void + SetStoppingCollisionVolumeFlag() + {Check(this); simulationFlags |= StoppingCollisionVolumeFlag; } + + ResourceDescription::ResourceID + explosionResourceID; + + ResourceDescription::ResourceID + crunchExplosionResourceID; + + + Scalar + destroyedYTranslation; + + Scalar + timeDelay; + + +public: + + Logical IsStoppingCollisionVolume() const + { + Check(this); + return (simulationFlags&StoppingCollisionVolumeFlag) != 0; + } + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + + enum { + TeamNameAttributeID = UnscalableTerrain::NextAttributeID, + NextAttributeID + }; + + enum { + BurningState = UnscalableTerrain::StateCount, + WaitingToBurn, + StateCount + }; + + char + teamName[64]; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + + typedef CulturalIcon__ModelResource ModelResource; + + CulturalIcon( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~CulturalIcon(); + + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + Logical + TestInstance() const; + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static CulturalIcon* + Make(MakeMessage *creation_message); + + static int + CreateModelResource ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + + static int + CreateDamageZoneStream ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); +}; +//########################################################################## +//################## Landmark::MakeMessage ############################# +//########################################################################## +class Landmark__MakeMessage : + public CulturalIcon::MakeMessage +{ + public: + + int + landmarkID; + + char + roleName[64]; + char + landmarkName[64]; + char + teamName[64]; + + Landmark__MakeMessage(); + Landmark__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + char *team_name, + int landmark_ID, + CString role_name + + ) : + CulturalIcon::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + EntityID::Null, + resource_ID, + instance_flags, + origin + ), + landmarkID(landmark_ID) + { + Str_Copy(teamName, team_name, sizeof(teamName)); + Str_Copy(roleName, (const char*)role_name, sizeof(roleName)); + } +}; + +//########################################################################## +//################## Landmark::ModelResource ####################### +//########################################################################## + +struct Landmark__ModelResource : + public CulturalIcon::ModelResource +{ +#if 0 + ResourceDescription::ResourceID + roleResourceID; +#endif +}; +//########################################################################## +//##################### Class Landmark ########################## +//########################################################################## + +class Landmark : + public CulturalIcon +{ + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Shared Data support + // + public: + + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Message Support + // + private: + static const HandlerEntry MessageHandlerEntries[]; + + protected: + static MessageHandlerSet MessageHandlers; + + public: + + void + TakeDamageMessageHandler(TakeDamageMessage *damage_message); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Local Data support + // + protected: + + ScenarioRole + *scenarioRole; + + int + landmarkID; + + Team + *owningTeam; + + char + teamName[64]; + + public: + + const ScenarioRole* + GetScenarioRole() const + {Check(this); return scenarioRole; } + + void + SetScenarioRole(ScenarioRole *scenario_role) + { Check(this); scenarioRole = scenario_role; } + + int + GetLandmarkID() const + {Check(this); return landmarkID; } + + Team* + GetOwningTeam() + {Check(this); return owningTeam; } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor / Destructor support + // + public: + + typedef Landmark__MakeMessage MakeMessage; + typedef Landmark__ModelResource ModelResource; + + Landmark( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + + ~Landmark(); + + Logical + TestInstance() const; + + static Logical + CreateMakeMessage ( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + static Landmark* + Make(MakeMessage *creation_message); + + static int + CreateModelResource ( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + + +}; diff --git a/MUNGA_L4/DXUtils.cpp b/MUNGA_L4/DXUtils.cpp new file mode 100644 index 0000000..1492bfc --- /dev/null +++ b/MUNGA_L4/DXUtils.cpp @@ -0,0 +1,33 @@ +#include "DXUtils.h" + +#if defined(PIX_PROFILE) + +#include +#include +#include +#include +#include + +namespace D3DUtils +{ + // Class constructor. Takes the necessary information and + // composes a string that will appear in PIXfW. + ScopeProfiler::ScopeProfiler( WCHAR* Name, int Line ) + { + WCHAR wc[ MAX_PATH ]; + StringCchPrintf( wc, MAX_PATH, L"%s @ Line %d.\0", Name, Line ); + + D3DPERF_BeginEvent( D3DCOLOR_XRGB( rand() % 255, rand() % 255, rand() % 255 ), wc ); + srand( static_cast< unsigned >( time( NULL ) ) ); + } + + // Makes sure that the BeginEvent() has a matching EndEvent() + // if used via the macro in D3DUtils.h this will be called when + // the variable goes out of scope. + ScopeProfiler::~ScopeProfiler( ) + { + D3DPERF_EndEvent( ); + } +} + +#endif \ No newline at end of file diff --git a/MUNGA_L4/DXUtils.h b/MUNGA_L4/DXUtils.h new file mode 100644 index 0000000..9e33a51 --- /dev/null +++ b/MUNGA_L4/DXUtils.h @@ -0,0 +1,45 @@ +#pragma once + +#include +#include + +#if defined(DX_VERBOSE) +#pragma comment(lib, "DXErr.lib") +#ifndef V +#define V(x) { hr = (x); if( FAILED(hr) ) { DEBUG_STREAM << __FILE__ << "(" << __LINE__ << "): " << L#x << " FAILED! hr=" << DXGetErrorString(hr) << std::endl << std::flush; } } +#endif +#else +#define V(x) hr = (x) +#endif + +#if defined(PIX_PROFILE) + +// These first two macros are taken from the +// VStudio help files - necessary to convert the +// __FUNCTION__ symbol from char to wchar_t. +#define WIDEN2(x) L ## x +#define WIDEN(x) WIDEN2(x) + +// Only the first of these macro's should be used. The _INTERNAL +// one is so that the sp##id part generates "sp1234" type identifiers +// instead of always "sp__LINE__"... +#define PROFILE_BLOCK PROFILE_BLOCK_INTERNAL( __LINE__ ) +#define PROFILE_BLOCK_INTERNAL(id) D3DUtils::ScopeProfiler sp##id ( WIDEN(__FUNCTION__), __LINE__ ); + +// To avoid polluting the global namespace, +// all D3D utility functions/classes are wrapped +// up in the D3DUtils namespace. +namespace D3DUtils +{ + class ScopeProfiler + { + public: + ScopeProfiler( WCHAR *Name, int Line ); + ~ScopeProfiler( ); + + private: + ScopeProfiler( ); + }; +} + +#endif \ No newline at end of file diff --git a/MUNGA_L4/JOYSTICK.asm b/MUNGA_L4/JOYSTICK.asm new file mode 100644 index 0000000..2bff4c6 --- /dev/null +++ b/MUNGA_L4/JOYSTICK.asm @@ -0,0 +1,147 @@ +.list +;=========================================================================== +; File: PCjoystk.asm +; Project: MUNGA +; Contents: PC joystick interface +;--------------------------------------------------------------------------- +; Date Who Modification +; -------- --- ----------------------------------------------------------- +; ??/??/?? JMA Initial coding +; 12/01/95 CPB Made pretty, expanded to four analog inputs (2 sticks). +; 01/20/95 CPB Added PC_Joystick_Mask +;--------------------------------------------------------------------------- +; Copyright (C) 1995, Virtual World Entertainment, Inc. All rights reserved +; PROPRIETARY and CONFIDENTIAL +;=========================================================================== + include l4asm.inc + include pcdpmi.inc + +;=========================================================================== +; Equates +;=========================================================================== + +JOYPORT EQU 0201h +XBIT1 EQU 00000001b +YBIT1 EQU 00000010b +XBIT2 EQU 00000100b +YBIT2 EQU 00001000b +BTTNA1 EQU 00010000b +BTTNB1 EQU 00100000b +BTTNA2 EQU 01000000b +BTTNB2 EQU 10000000b + +ANALOGBITS EQU XBIT1+YBIT1+XBIT2+YBIT2 +BUTTONBITS EQU BTTNA1+BTTNB1+BTTNA2+BTTNB2 + +;=========================================================================== +; Data segment +;=========================================================================== +BEGIN_DATA + + PUBLIC PC_Joystick1_Raw_X,PC_Joystick1_Raw_Y + PUBLIC PC_Joystick2_Raw_X,PC_Joystick2_Raw_Y + PUBLIC PC_Joystick_Mask,PC_Joystick_Buttons + PC_Joystick1_Raw_X dw 0 + PC_Joystick1_Raw_Y dw 0 + PC_Joystick2_Raw_X dw 0 + PC_Joystick2_Raw_Y dw 0 + PC_Joystick_Mask db ANALOGBITS + PC_Joystick_Buttons db 0 + +END_DATA + +;=========================================================================== +; Code segment +;=========================================================================== +BEGIN_CODE + +;------------------------------------------------------------------------- +; PC_Joystick_Poll(void) +; Reads joystick values, places values into public memory locations +;------------------------------------------------------------------------- +; Enter: +; (void) +;------------------------------------------------------------------------- +; Returns: +; (void) +;------------------------------------------------------------------------- +BEGIN_C_PROC PC_Joystick_Update + + BUILD_STACK_FRAME + + ;-------------------------------------------------------------- + ; Disable interrupts, saving the old state of interrupts + ;-------------------------------------------------------------- + DPMI_DISABLE_SAVE_INT ;pushes ax! + ;-------------------------------------------------------------- + ; Set up for timing loop + ;-------------------------------------------------------------- + mov dx,JOYPORT + xor cx,cx + ;-------------------------------------------------------------- + ; Clear the port and start reading + ;-------------------------------------------------------------- + mov ah,PC_Joystick_Mask ;load AH with all bits set, clear al + xor al,al + out dx,al ;trigger the timers + +check_again: + ;-------------------------------------------------------------- + ; Read the port, check for changes + ;-------------------------------------------------------------- + in al,dx ;read the status bits + and al,PC_Joystick_Mask ;remove non-analog bits + + xor al,ah ;check for a change + jz short no_change ;no change, hang out + ;-------------------------------------------------------------- + ; See what changed + ;-------------------------------------------------------------- + test al,XBIT1 + jz short no_x1_change + mov PC_Joystick1_Raw_X,cx +no_x1_change: + test al,YBIT1 + jz short no_y1_change + mov PC_Joystick1_Raw_Y,cx +no_y1_change: + test al,XBIT2 + jz short no_x2_change + mov PC_Joystick2_Raw_X,cx +no_x2_change: + test al,YBIT2 + jz short no_y2_change + mov PC_Joystick2_Raw_Y,cx +no_y2_change: + ;-------------------------------------------------------------- + ; See if we have read all the bits + ;-------------------------------------------------------------- + xor ah,al + jz short read_done + ;-------------------------------------------------------------- + ; Increment the count and check again + ;-------------------------------------------------------------- +no_change: + inc cx + cmp cx,2048 ;arbitrary limit + jnz check_again + ;-------------------------------------------------------------- + ; All done with analog values. Re-enable interrupts + ;-------------------------------------------------------------- +read_done: + DPMI_RESTORE_PREV_INT ;pops ax! + ;-------------------------------------------------------------- + ; Read the buttons + ;-------------------------------------------------------------- + in al,dx ;read the status bits + not al ;invert the bits (so 1=closed) + and al,BUTTONBITS ;remove extraneous bits + mov PC_Joystick_Buttons,al ;save the result + ;-------------------------------------------------------------- + ; Return + ;-------------------------------------------------------------- +END_C_PROC + +END_CODE + + END diff --git a/MUNGA_L4/L4APP.H b/MUNGA_L4/L4APP.H new file mode 100644 index 0000000..6791b4d --- /dev/null +++ b/MUNGA_L4/L4APP.H @@ -0,0 +1,232 @@ +//===========================================================================// +// File: l4app.hpp // +// Project: MUNGA Brick: L4Application // +// Contents: Interface specification for L4Application // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 01/21/95 ECH Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide. // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#pragma once + +#include "..\munga\app.h" +#include "..\munga\APPMGR.h" + +class DPLRenderer; +class L4AudioRenderer; +class L4GaugeRenderer; +class L4NetworkManager; +class LBE4ControlsManager; +class L4IcomManager; + +//########################################################################## +//######################## L4Application ############################# +//########################################################################## + +class L4Application: + public Application +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, and Testing +// +public: + L4Application( + HINSTANCE hInstance, + HWND hWnd, + ResourceFile *resource_file, + ApplicationID application_ID, + ClassID class_ID=L4ApplicationClassID, + SharedData &shared_data=DefaultData + ); + ~L4Application(); + + Logical + TestInstance() const; + + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + + bool IsDead() {return mIsDead;} + void SetIsDead(bool isDead) {mIsDead = isDead;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Command line parsing +// +public: + typedef Logical + (*TokenParser)(int *argument, int argc, LPWSTR argv[]); + static Logical + ParseToken( + int *argument, + int argc, + LPWSTR argv[] + ); + static Logical + ParseCommandLine( + int argc, + LPWSTR argv[], + TokenParser parser = &L4Application::ParseToken + ); + + static int GetMissionReviewMode() { return missionReviewMode; } + static HINSTANCE GetAppInstance() { return mhInstance; } + static HWND GetMainWindow() { return ghWnd; } + static unsigned int GetScreenWidth() { return mScreenWidth; } + static unsigned int GetScreenHeight() { return mScreenHeight; } + static bool GetFullscreen() { return mFullscreen; } + static Logical GetSeeSolids() { return seeSolids; } + static unsigned long GetNetworkCommonFlatAddress() { return networkCommonFlatAddress; } + static CString GetEggNotationFileName() { return eggNotationFileName; } + static CString GetSpoolFileName() { return spoolFileName; } + static CString GetRIOPlaybackFileName() { return rioPlaybackFileName; } + static CString GetRIORecordingFileName() { return rioRecordingFileName; } + +protected: + static HINSTANCE mhInstance; + static unsigned int mScreenWidth; + static unsigned int mScreenHeight; + static bool mFullscreen; + static Logical seeSolids; + static CString eggNotationFileName; + static CString spoolFileName; + static unsigned long networkCommonFlatAddress; + static int missionReviewMode; + static CString rioPlaybackFileName; + static CString rioRecordingFileName; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execution control +// +public: + void + Initialize(); + void + InitializeTillConsole(); + + Entity* + MakeAndLinkViewpointEntity(Entity__MakeMessage *message); + + Entity* + MakeViewpointEntity(Entity__MakeMessage *message); + + void + Terminate(); + + void + TeslaCoil(Logical lights_on); + + void + PilotIllumination(Logical lights_on); // includes 'Tesla coil' + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Module accesors +// +public: + DPLRenderer* + GetVideoRenderer(); + + L4AudioRenderer* + GetAudioRenderer(); + + L4GaugeRenderer* + GetGaugeRenderer(); + + L4NetworkManager* + GetNetworkManager() + {return (L4NetworkManager*)Application::GetNetworkManager();} + LBE4ControlsManager* + GetControlsManager() + {return (LBE4ControlsManager*)Application::GetControlsManager();} + L4IcomManager* + GetIntercomManager() + {return (L4IcomManager*)Application::GetIntercomManager();} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public data +// +public: + char + *divisionParameters; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Module Creation +// +protected: + ModeManager* + MakeModeManager(); + + ControlsManager* + MakeControlsManager(); + + IcomManager* + MakeIntercomManager(); + + NetworkManager* + MakeNetworkManager(); + + VideoRenderer* + MakeVideoRenderer(); + + AudioRenderer* + MakeAudioRenderer(); + + GaugeRenderer* + MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum + { + LightsOutMessageID = Application::NextMessageID, + NextMessageID + }; + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + LightsOutMessageHandler(Receiver::Message *message); + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + void // HACK - the 'int' is actually 'ControlsKey' + KeyCommandMessageHandler(ReceiverDataMessageOf *message); + +private: + bool mIsDead; +}; + +extern L4Application * &l4_application; + +//~~~~~~~~~~~~~~~~~~~~~ L4Application inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline DPLRenderer* + L4Application::GetVideoRenderer() + { + Check(this); + return (DPLRenderer*)videoRenderer; + } + +inline L4AudioRenderer* + L4Application::GetAudioRenderer() + { + Check(this); + return (L4AudioRenderer*)audioRenderer; + } + +inline L4GaugeRenderer* + L4Application::GetGaugeRenderer() + { + Check(this); + return (L4GaugeRenderer*)gaugeRenderer; + } \ No newline at end of file diff --git a/MUNGA_L4/L4APP.cpp b/MUNGA_L4/L4APP.cpp new file mode 100644 index 0000000..e54e4f1 --- /dev/null +++ b/MUNGA_L4/L4APP.cpp @@ -0,0 +1,904 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "..\munga\camship.h" +#include "..\munga\appmsg.h" +#include "l4app.h" +#include "l4ctrl.h" +#include "l4icom.h" +#include "l4video.h" +#include "l4audrnd.h" +#include "l4grend.h" +#include "l4net.h" +#include "l4mppr.h" +#include "..\munga\player.h" +#include "..\munga\mission.h" +#include +#include + +L4Application*& + l4_application = (L4Application*&)application; + +const Receiver::HandlerEntry + L4Application::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(L4Application, RunMission), + MESSAGE_ENTRY(L4Application, StopMission), + MESSAGE_ENTRY(L4Application, LightsOut), + MESSAGE_ENTRY(L4Application, KeyCommand) +}; + +Receiver::MessageHandlerSet& L4Application::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(L4Application::MessageHandlerEntries), L4Application::MessageHandlerEntries, Application::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Virtual Data support +// +Derivation* L4Application::GetClassDerivations() +{ + static Derivation classDerivations(Application::GetClassDerivations(), "L4Application"); + return &classDerivations; +} + +L4Application::SharedData + L4Application::DefaultData( + L4Application::GetClassDerivations(), + L4Application::GetMessageHandlers() + ); + +//########################################################################## +//################## L4Application Static Data ####################### +//########################################################################## + +HINSTANCE L4Application::mhInstance = NULL; +unsigned int L4Application::mScreenWidth = 800; +unsigned int L4Application::mScreenHeight = 600; +bool L4Application::mFullscreen = true; +Logical L4Application::seeSolids = False; +CString L4Application::eggNotationFileName; +CString L4Application::spoolFileName; +unsigned long L4Application::networkCommonFlatAddress; +Logical L4Application::missionReviewMode = False; +CString L4Application::rioPlaybackFileName; +CString L4Application::rioRecordingFileName; + +// +//############################################################################# +// ParseCommandLine +//############################################################################# +// +Logical + L4Application::ParseToken( + int *arguement, + int argc, + LPWSTR argv[] + ) +{ + USES_CONVERSION; + Check_Pointer(argv); + + if (!stricmp(W2A(argv[*arguement]), "-egg")) + { + if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') + { + eggNotationFileName = W2A(argv[++(*arguement)]); + } + else + { + DEBUG_STREAM << "\nEgg file not specified after -egg\n" << std::flush << std::flush; + return False; + } + } + + else if (!stricmp(W2A(argv[*arguement]), "-spool")) + { + if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') + { + spoolFileName = W2A(argv[++(*arguement)]); + } + else + { + DEBUG_STREAM << "\nSpool file not specified after -spool\n" << std::flush << std::flush; + return False; + } + } + + else if (!stricmp(W2A(argv[*arguement]), "-net")) + { + if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') + { + networkCommonFlatAddress = atol(W2A(argv[++(*arguement)])); + } + else + { + DEBUG_STREAM << "\nAddress not specified after -net\n" << std::flush; + return False; + } + } + + else if (!stricmp(W2A(argv[*arguement]), "-r")) + { + if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') + { + rioRecordingFileName = W2A(argv[++(*arguement)]); + CString playback = GetRIOPlaybackFileName(); + if (playback && strlen(playback)) + { + DEBUG_STREAM << "\nPlayback already specified!\n" << std::flush; + return False; + } + } + else + { + DEBUG_STREAM << "\nRecording file not specified after -r\n" << std::flush; + return False; + } + } + + else if (!stricmp(W2A(argv[*arguement]), "-p")) + { + if ((*arguement+1) < argc && W2A(argv[*arguement+1])[0] != '-') + { + rioPlaybackFileName = W2A(argv[++(*arguement)]); + CString recording = GetRIORecordingFileName(); + if (recording && strlen(recording)) + { + DEBUG_STREAM << "\nRecording already specified!\n" << std::flush; + return False; + } + } + else + { + DEBUG_STREAM << "\nPlayback file not specified after -egg\n" << std::flush; + return False; + } + } + + else if (!stricmp(W2A(argv[*arguement]), "-solids")) + { + seeSolids = True; + } + + else if (!stricmp(W2A(argv[*arguement]), "-res")) + { + if ((*arguement+2) < argc && W2A(argv[*arguement+1])[0] != '-' && W2A(argv[*arguement+2])[0] != '-') + { + mScreenWidth = atoi(W2A(argv[++(*arguement)])); + mScreenHeight = atoi(W2A(argv[++(*arguement)])); + } + else + { + DEBUG_STREAM << "\nScreen width and height not specified after -res\n" << std::flush; + return False; + } + } + else if (!stricmp(W2A(argv[*arguement]), "-windowed")) + { + mFullscreen = false; + } + + else if ( + !stricmp(W2A(argv[*arguement]), "-h") || !stricmp(W2A(argv[*arguement]), "-help") + ) + { + DEBUG_STREAM << "\n" << argv[0] << + " -egg -net -solids -h -help\n"; + return False; + } + + return True; +} + +// +//############################################################################# +// ParseCommandLine +//############################################################################# +// +Logical + L4Application::ParseCommandLine( + int argc, + LPWSTR argv[], + TokenParser parser + ) +{ + USES_CONVERSION; + Check_Pointer(argv); + + // + // Process options + // + seeSolids = False; + eggNotationFileName = ""; + networkCommonFlatAddress = NULL; + missionReviewMode = 0; + suppressGauges = FALSE; + + if (argc > 1) + { + for (int i = 1; i < argc; ++i) + { + if (!stricmp(W2A(argv[i]), "-lc")) + { + suppressGauges = TRUE; + } else if (!stricmp(W2A(argv[i]), "-mr")) + { + suppressGauges = TRUE; + missionReviewMode = 1; + } else if (!(*parser)(&i, argc, argv)) + { + return False; + } + } + } + return True; +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + L4Application::TestInstance() const +{ + if (!IsDerivedFrom(*GetClassDerivations())) + { + return False; + } + return True; +} + +// +//############################################################################# +// L4Application +//############################################################################# +// +L4Application::L4Application( + HINSTANCE hInstance, + HWND hWnd, + ResourceFile *resource_file, + ApplicationID application_ID, + ClassID class_ID, + SharedData &shared_data +): + Application(resource_file, application_ID, class_ID, shared_data), + mIsDead(false) +{ + mhInstance = hInstance; // this is a static member, the app instance should never change during execution + //ghWnd = hWnd; + divisionParameters = getenv("DPLARG"); +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + L4Application::Initialize() +{ + Check(this); + + InitializeTillConsole(); + + // + // Create the console host and socket + // + L4NetworkManager *net_mgr = GetNetworkManager(); + net_mgr->CreateConsoleHost(); +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + L4Application::InitializeTillConsole() +{ + Check(this); + + Application::Initialize(); +} + +// +//############################################################################# +// MakeModeManager +//############################################################################# +// +ModeManager* + L4Application::MakeModeManager() +{ + return new ModeManager((ModeMask)ModeManager::ModeAlwaysActive); // Normally called at top level!! +} + +// +//############################################################################# +// MakeNetworkManager +//############################################################################# +// +NetworkManager* + L4Application::MakeNetworkManager() +{ + return new L4NetworkManager; +} + +// +//############################################################################# +// MakeControlsManager +//############################################################################# +// +ControlsManager* + L4Application::MakeControlsManager() +{ + LBE4ControlsManager *manager = new LBE4ControlsManager(); + Check(manager); + manager->keyboardGroup[LBE4ControlsManager::KeyboardPC].Add(ModeManager::ModeAlwaysActive, this, KeyCommandMessageID, this); + return manager; +} + +// +//############################################################################# +// MakeIntercomManager +//############################################################################# +// +IcomManager* + L4Application::MakeIntercomManager() +{ + L4IcomManager + *manager = new L4IcomManager(); + Check(manager); + + return manager; +} + +// +//############################################################################# +// MakeVideoRenderer +//############################################################################# +// +VideoRenderer* + L4Application::MakeVideoRenderer() +{ + if (divisionParameters) + { + return + new DPLRenderer( + ghWnd, + mScreenWidth, + mScreenHeight, + mFullscreen, + VisualInterestType, + DefaultInterestDepth + ); + } + return NULL; +} + +// +//############################################################################# +// MakeAudioRenderer +//############################################################################# +// +AudioRenderer* + L4Application::MakeAudioRenderer() +{ +/* char *blaster1, *blaster2; + + blaster1 = getenv(FRONT_CARD_ENV_VAR); + blaster2 = getenv(REAR_CARD_ENV_VAR); + + if (blaster1 != NULL && blaster2 != NULL) + { + return new L4AudioRenderer(DefaultRendererRate, False); + } + return NULL;*/ + + return new L4AudioRenderer(DefaultRendererRate, False); +} + +// +//############################################################################# +// MakeGaugeRenderer +//############################################################################# +// +GaugeRenderer* + L4Application::MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index) +{ + char *mode_string = getenv("L4GAUGE"); + if (mode_string != NULL) + { + return new L4GaugeRenderer(!mFullscreen, secondaryIndex, aux1Index, aux2Index); + } + return NULL; +} + +// +//############################################################################# +// Terminate +//############################################################################# +// +void + L4Application::Terminate() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Turn off illumination + //-------------------------------------------------------------------------- + // + PilotIllumination(False); + + // + // Call inherited method + // + Application::Terminate(); +} + +// +//############################################################################# +// ~L4Application +//############################################################################# +// +L4Application::~L4Application() +{ +} + +// +//############################################################################# +// MakeAndLinkViewpointEntity +//############################################################################# +// +Entity* + L4Application::MakeAndLinkViewpointEntity(Entity::MakeMessage* message) +{ + Check(this); + Check(message); + + Application::MakeAndLinkViewpointEntity(message); + + // + //-------------------------------------------------------------------------- + // Turn on lights for pilot + // (turned off by RunMissionMessageHandler) + //-------------------------------------------------------------------------- + // + PilotIllumination(True); + + // + //-------------------------------------------------------------------------- + // Return viewpoint entity + //-------------------------------------------------------------------------- + // + return GetViewpointEntity(); +} + +// +//############################################################################# +// MakeViewpointEntity +//############################################################################# +// +Entity* + L4Application::MakeViewpointEntity(Entity::MakeMessage *message) +{ + Entity *viewing_entity; + viewing_entity = NULL; + switch(message->classToCreate) + { + case CameraShipClassID: + viewing_entity = CameraShip::Make((CameraShip::MakeMessage*)message); + Check(viewing_entity); + CameraShip *viewing_camera = Cast_Object(CameraShip*, viewing_entity); + Check(viewing_camera); + + // + // Create controls mapping object + // + CameraControlsMapper + *camera_mapper; + + Verify(GetControlsManager() != NULL); + CameraControlsMapper::SubsystemResource control_subsystem_resource; + Str_Copy( + control_subsystem_resource.subsystemName, + "ControlsMapper", + sizeof(control_subsystem_resource.subsystemName) + ); + control_subsystem_resource.classID = TrivialSubsystemClassID; + control_subsystem_resource.subsystemModelSize = + sizeof(control_subsystem_resource); + + LBE4ControlsManager* controls = GetControlsManager(); + Check(controls); + switch (controls->primaryControlType) + { + case LBE4ControlsManager::PrimaryThrustMaster: + Tell("L4Application::MakeViewpointEntity, using ThrustMaster\n"); + camera_mapper = + new CameraThrustmasterMapper( + viewing_camera, + CameraShip::ControlsMapperSubsystem, + &control_subsystem_resource + ); + Register_Object(camera_mapper); + viewing_camera->SetMappingSubsystem(camera_mapper); + break; + + case LBE4ControlsManager::PrimaryRIO: + Tell("L4Application::MakeViewpointEntity, using RIO\n"); + camera_mapper = + new CameraRIOMapper( + viewing_camera, + CameraShip::ControlsMapperSubsystem, + &control_subsystem_resource + ); + Register_Object(camera_mapper); + viewing_camera->SetMappingSubsystem(camera_mapper); + break; + default: + Fail("L4Application::MakeViewpointEntity, *** NO MAPPER! ***\n"); + break; + } + + // + //------------------------------------------- + // Create gauges for this entity + //------------------------------------------- + // + if (GetGaugeRenderer() != NULL) + { + L4GaugeRenderer *gauge_renderer = GetGaugeRenderer(); + Check(gauge_renderer); + + gauge_renderer->ConfigureForModel( + "Init", + viewing_entity + ); + } + break; + } + return viewing_entity; +} + +// +//############################################################################# +// RunMissionMessageHandler +//############################################################################# +// +void + L4Application::RunMissionMessageHandler(RunMissionMessage *message) +{ + Check(this); + Verify(message->messageID == RunMissionMessageID); + + // + //-------------------------------------------------------------------------- + // If the application is already running then ignore this message + //-------------------------------------------------------------------------- + // + switch (GetApplicationState()) + { + case RunningMission: + break; + + // + //------------------------------------- + // Start the playback if it is required + //------------------------------------- + // + case LaunchingMission: + { + LBE4ControlsManager *controls = GetControlsManager(); + Check(controls); + if (controls->IsRecording()) + { + controls->StartRecording(); + } + else if (controls->IsPlayingBack()) + { + controls->StartPlayback(); + } + } + break; + + case WaitingForLaunch: + PilotIllumination(False); + break; + + default: + Fail("Application::RunMissionMessageHandler - Not ready to run!\n"); + break; + } + + // + //-------------------------------------------------------------------------- + // Call previous handler + //-------------------------------------------------------------------------- + // + Application::RunMissionMessageHandler(message); +} +// +//############################################################################# +// StopMissionMessageHandler +//############################################################################# +// +void + L4Application::StopMissionMessageHandler(StopMissionMessage *message) +{ + Check(this); + Verify(message->messageID == StopMissionMessageID); + + // + //-------------------------------------------------------------------------- + // Call inherited handler + //-------------------------------------------------------------------------- + // + Application::StopMissionMessageHandler(message); + + // + //-------------------------------------------------------------------------- + // Turn on illumination + //-------------------------------------------------------------------------- + // + PilotIllumination(True); + + // + //-------------------------------------------------------------------------- + // Post a delayed message to ourselves to turn off the illumination + //-------------------------------------------------------------------------- + // + Receiver::Message + lights_out_message(LightsOutMessageID, sizeof(Receiver::Message)); + + Time + event_time; + + event_time = Now(); + event_time += 30.0f; + + Post( + LowEventPriority, // priority + this, // target + &lights_out_message, // message + event_time // when + ); +} + +// +//############################################################################# +// KeyCommandMessageHandler +//############################################################################# +// +void + L4Application::KeyCommandMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + switch (message->dataContents) + { + //-------------------------------------------- + // FrameDump from Division card to Targa file + //-------------------------------------------- + case PCK_ALT_F: + { + DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); + if (dpl_renderer) + { + Check(dpl_renderer); + dpl_renderer->DPLFrameDump(True); // True indicates antialiased + } + break; + } + + //------------------------------------ + // Report current free memory in card + //------------------------------------ + case PCK_ALT_K: + { + //STUBBED: HEAP RB 1/20/07 + /*DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); + if (dpl_renderer) + { + Check(dpl_renderer); + dpl_renderer->DPLReportFreeMemory(DEBUG_STREAM) << std::flush; + } + DEBUG_STREAM << UserHeap::MainStorage.GetTotalHeapLeft() << '(' + << UserHeap::MainStorage.GetBiggestHeapLeft() + << " contiguous) bytes of MUNGA core left\n" + << UserHeap::MainStorage.GetHeapUsed() << " bytes of heap used\n"; + #if defined(USE_MEMORY_ANALYSIS) + DEBUG_STREAM << UserHeap::MainStorage.GetLowestTotalHeapLeft() + << " bytes minimum available so far\n" + << UserHeap::MainStorage.GetMostHeapUsed() + << " bytes maximum used so far\n"; + #endif + MemoryBlockBase::UsageReport();*/ + break; + } + + //------------------------------------ + // Report current event queue + //------------------------------------ + case 'E': + { + Check(application); + application->DumpEventQueue(); + break; + } + + //--------------------------------------- + // Report performance statistics (Alt-?) + //--------------------------------------- + case PCK_ALT_SLASH: + { + DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); + if (dpl_renderer) + { + Check(dpl_renderer); + dpl_renderer->DPLReportPerfStats(DEBUG_STREAM); + } + break; + } + //-------------------------- + // Toggle Wireframe display + //-------------------------- + case PCK_ALT_W: + { + DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); + if (dpl_renderer) + { + Check(dpl_renderer); + dpl_renderer->DPLToggleWireframe(); + } + break; + } + //-------------------------- + // Toggle "Predator-vision" + //-------------------------- + case PCK_ALT_V: + { + DPLRenderer *dpl_renderer = l4_application->GetVideoRenderer(); + if (dpl_renderer) + { + Check(dpl_renderer); + dpl_renderer->DPLTogglePVision(); + } + break; + } + //-------------------------------------------------------------- + // Toggle transparency dither pattern between random and static + //-------------------------------------------------------------- + case PCK_ALT_R: + //----------------------------- + // Report position of eyepoint + //----------------------------- + case PCK_ALT_P: + DEBUG_STREAM << "Function net yet enabled.\n" << std::flush; + break; + //------------------------------ + // Pass event on to Application + //------------------------------ + default: + Application::KeyCommandMessageHandler(message); + break; + } +} + +// +//############################################################################# +// LightsOutMessageHandler +//############################################################################# +// +#if DEBUG_LEVEL == 0 +void + L4Application::LightsOutMessageHandler(Receiver::Message */*message*/) +{ +#else +void + L4Application::LightsOutMessageHandler(Receiver::Message *message) +{ + Check(this); + Verify(message->messageID == LightsOutMessageID); +#endif + // + //-------------------------------------------------------------------------- + // Turn off illumination + //-------------------------------------------------------------------------- + // + PilotIllumination(False); +} + +// +//############################################################################# +// TeslaCoil +//############################################################################# +// +void + L4Application::TeslaCoil(Logical light_on) +{ + Check(controlsManager); + + if (light_on) + { + ((LBE4ControlsManager *) controlsManager)->SetLamp( + LBE4ControlsManager::LampTesla1, + RIO::solid + RIO::state1Bright + RIO::state2Bright + ); + ((LBE4ControlsManager *) controlsManager)->SetLamp( + LBE4ControlsManager::LampTesla2, + RIO::solid + RIO::state1Bright + RIO::state2Bright + ); + ((LBE4ControlsManager *) controlsManager)->SetLamp( + LBE4ControlsManager::LampTesla3, + RIO::solid + RIO::state1Bright + RIO::state2Bright + ); + } + else + { + ((LBE4ControlsManager *) controlsManager)->SetLamp(LBE4ControlsManager::LampTesla1, RIO::solid + RIO::state1Off + RIO::state2Off); + ((LBE4ControlsManager *) controlsManager)->SetLamp(LBE4ControlsManager::LampTesla2, RIO::solid + RIO::state1Off + RIO::state2Off); + ((LBE4ControlsManager *) controlsManager)->SetLamp(LBE4ControlsManager::LampTesla3, RIO::solid + RIO::state1Off + RIO::state2Off); + } +} + +// +//############################################################################# +// PilotIllumination +//############################################################################# +// +void + L4Application::PilotIllumination(Logical light_on) +{ + Check(controlsManager); + + TeslaCoil(light_on); + + if (light_on) + { + //-------------------------------------------- + // Turn on floor light + //-------------------------------------------- + ((LBE4ControlsManager *) controlsManager)->SetLamp( + LBE4ControlsManager::LampFloor, + RIO::solid + RIO::state1Bright + RIO::state2Bright + ); + //-------------------------------------------- + // Ramp all aux screens to white + //-------------------------------------------- + L4GaugeRenderer *gauge_renderer = GetGaugeRenderer(); + if (gauge_renderer != NULL) + { + Check(gauge_renderer); + gauge_renderer->FadeToWhite(1.5); + } + } + else + { + //-------------------------------------------- + // Turn off floor light + //-------------------------------------------- + ((LBE4ControlsManager *) controlsManager)->SetLamp( + LBE4ControlsManager::LampFloor, + RIO::solid + RIO::state1Off + RIO::state2Off + ); + //-------------------------------------------- + // Ramp all aux screens to normal + //-------------------------------------------- + L4GaugeRenderer *gauge_renderer = GetGaugeRenderer(); + if (gauge_renderer != NULL) + { + Check(gauge_renderer); + gauge_renderer->FadeToNormal(1.5); + } + } +} + +#ifdef TEST_CLASS +# include "l4app.tcp" +#endif diff --git a/MUNGA_L4/L4AUDHDW.cpp b/MUNGA_L4/L4AUDHDW.cpp new file mode 100644 index 0000000..c678ccc --- /dev/null +++ b/MUNGA_L4/L4AUDHDW.cpp @@ -0,0 +1,990 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4audhdw.h" + +//#if defined(AUDIO_HARDWARE) +// #include "sos\bc4\sosmawe.h" +//#endif + +#if defined(TRACE_AUDIO_RENDERER_MIDI) + BitTrace Audio_Renderer_MIDI("Audio Renderer MIDI"); +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MPU Emulation ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define _inp inportb +#define _outp outportb + +#define MPUPort(x) ((x)+mpuAddx) +#define SBCPort(x) ((x)+srcAddx) + +/* DSP defines */ +#define MPU_ACK_OK 0xfe +#define MPU_RESET_CMD 0xff +#define MPU_ENTER_UART 0x3f + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDIMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + MIDIMessage::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +std::ostream& + operator << ( + std::ostream &strm, + const MIDIMessage &midi_message + ) +{ + Check(&midi_message); + + strm << "["; + strm << (int)(midi_message.message[0] & 0x0F) << ","; + strm << (int)(midi_message.message[0] >> 4) << ","; + strm << (int)midi_message.message[1] << ","; + strm << (int)midi_message.message[2] << "]"; + + return strm; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +/*AudioChannel::AudioChannel( + AudioChannelType audio_channel_type, + MIDIChannel midi_channel, + AudioCard *audio_card +) +{ + audioChannelType = audio_channel_type; + midiChannel = midi_channel; + voicesUsed = 0; + Check(audio_card); + audioCard = audio_card; +} + +// +//############################################################################# +//############################################################################# +// +AudioChannel::~AudioChannel() +{ + Verify(voicesUsed == 0); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioChannel::TestInstance() const +{ + Plug::TestInstance(); + Verify(voicesUsed >=0 && voicesUsed <= AWE_VOICE_COUNT); + Check(audioCard); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// AudioCard +//############################################################################# +// +AudioCard::AudioCard(): + idleChannelSocket(NULL), + percussionChannelSocket(NULL) +{ + MIDIChannel channel; + + idleVoices = AWE_VOICE_COUNT; + for (channel = 0; channel < AWE_CHANNEL_COUNT; channel++) + { + AudioChannel *audio_channel; + + if (channel == AWE_PERCUSSIVE_CHANNEL) + { + audio_channel = + new AudioChannel( + PercussionAudioChannelType, + channel, + this + ); + Register_Object(audio_channel); + Check(&percussionChannelSocket); + percussionChannelSocket.Add(audio_channel); + } + else + { + audio_channel = + new AudioChannel( + InstrumentAudioChannelType, + channel, + this + ); + Register_Object(audio_channel); + Check(&idleChannelSocket); + idleChannelSocket.Add(audio_channel); + } + } +} + +// +//############################################################################# +// ~AudioCard +//############################################################################# +// +AudioCard::~AudioCard() +{ + // + // Delete the idle channels + // + { + ChainIteratorOf iterator(&idleChannelSocket); + + Check(&iterator); + Verify(idleVoices == AWE_VOICE_COUNT); + Verify(iterator.GetSize() == AWE_CHANNEL_COUNT - 1); + iterator.DeletePlugs(); + } + + // + // Delete the percussive channel + // + { + ChainIteratorOf iterator(&percussionChannelSocket); + + Check(&iterator); + Verify(idleVoices == AWE_VOICE_COUNT); + Verify(iterator.GetSize() == 1); + iterator.DeletePlugs(); + } +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioCard::TestInstance() const +{ + Node::TestInstance(); + Verify(idleVoices >= 0 && idleVoices <= AWE_VOICE_COUNT); + Check(&idleChannelSocket); + return True; +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + AudioCard::Initialize() +{ +#ifdef AUDIO_HARDWARE + Tell("AudioCard::Initialize - Start\n"); + + WORD wError; + + // + // Set the selector of the pointer to the driver memory for the + // MIDI driver to _NULL. this will tell the load driver routine + // to allocate new memory for the MIDI driver + // + #if defined(__BCPLUSPLUS__) + sSOSMIDIInitDriver.lpDriverMemory.sel = _NULL; + #else + sSOSMIDIInitDriver.lpDriverMemory = _NULL; + #endif + + // + // Setup the port for the MIDI driver to use + // + // sSOSMIDIHardware.wPort = _MIDI_DRIVER_PORT; + sSOSMIDIHardware.wPort = emuAddx; + + // + // Load and initialize the MIDI driver + // + wError = sosMIDIInitDriver( + _MIDI_DRIVER_TYPE, + &sSOSMIDIHardware, + &sSOSMIDIInitDriver, + &wDriverHandle + ); + if (wError) + { + std::cout << sosGetErrorString(wError); + Fail("AudioCard::Initialize - sosMIDIInitDriver failed\n"); + } + + Tell("AudioCard::Initialize - Finish\n"); +#endif +} + +// +//############################################################################# +// Close +//############################################################################# +// +void + AudioCard::Close() +{ +#ifdef AUDIO_HARDWARE + Check(this); + + sosMIDIAWE32ReleaseSBKFiles(wDriverHandle); + + // + // Reset the midi driver + // + sosMIDIResetDriver(wDriverHandle); + + // + // Uninitialize the midi driver and tell it to free the memory allocated + // for the driver + // + sosMIDIUnInitDriver(wDriverHandle, _TRUE); +#endif +} + +// +//############################################################################# +// GetEnvironmentSettings +//############################################################################# +// +void + AudioCard::GetEnvironmentSettings(char *env_str) +{ + WORD src_addx = 0xffff; + WORD irq_interrupt = 0xffff; + WORD dma_channel = 0xffff; + WORD mpu_addx = 0xffff; + WORD emu_addx = 0xffff; + + const char *sz_blaster; + + sz_blaster = getenv(env_str); + Check_Pointer(sz_blaster); + + while (*sz_blaster) { + if (*sz_blaster == 'a' || *sz_blaster == 'A') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + src_addx = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'i' || *sz_blaster == 'I') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + irq_interrupt = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'd' || *sz_blaster == 'D') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + dma_channel = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'e' || *sz_blaster == 'E') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + emu_addx = GetHexWord(&sz_blaster); + } + } + if (*sz_blaster == 'p' || *sz_blaster == 'P') { + ++sz_blaster; + if (*sz_blaster) { + if (*sz_blaster == ':') + ++sz_blaster; + mpu_addx = GetHexWord(&sz_blaster); + } + } + + // + // Skip until blank or end of string + // + while (*sz_blaster && *sz_blaster != ' ') + ++sz_blaster; + while (*sz_blaster == ' ') + ++sz_blaster; + } + + if (emu_addx == 0xffff) + emu_addx = (WORD)(src_addx + 0x400); + + srcAddx = src_addx; + irqInterrupt = irq_interrupt; + dmaChannel = dma_channel; + mpuAddx = mpu_addx; + emuAddx = emu_addx; + + #if DEBUG_LEVEL>0 + Tell("AudioCard::GetEnvironmentSettings: " << env_str << "\n"); + #if 0 + Dump(srcAddx); + Dump(irqInterrupt); + Dump(dmaChannel); + Dump(mpuAddx); + Dump(emuAddx); + #endif + printf(" srcAddx = %x\n", (unsigned)srcAddx); + printf(" irqInterrupt = %x\n", (unsigned)irqInterrupt); + printf(" dmaChannel = %x\n", (unsigned)dmaChannel); + printf(" mpuAddx = %x\n", (unsigned)mpuAddx); + printf(" emuAddx = %x\n", (unsigned)emuAddx); + #endif +} + +// +//############################################################################# +// InitMIDIReceive +// Initializes Sound Blaster to ready to receive data state. +//############################################################################# +// +Logical + AudioCard::InitMIDIReceive() +{ +#if 0 + volatile DWORD dwCount; + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; + _inp(MPUPort(0)); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; + _inp(MPUPort(0)); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_ENTER_UART); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x80) --dwCount; + if (!dwCount) return True; + if (_inp(MPUPort(0)) != MPU_ACK_OK) return True; + + // mask MPU-401 interrupt + _outp(SBCPort(0x4), 0x83); + _outp(SBCPort(0x5), _inp(SBCPort(0x5)) & ~0x04); +#endif + return False; +} + +// +//############################################################################# +// CloseMIDIReceive +//############################################################################# +// +void + AudioCard::CloseMIDIReceive() +{ +#if 0 + volatile DWORD dwCount; + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + for (dwCount=0; dwCount<0x2000; dwCount++) ; + _inp(MPUPort(0)); + + for (dwCount=0; dwCount<0x2000; dwCount++) ; + dwCount = 0x2000; + while (dwCount && _inp(MPUPort(1)) & 0x40) --dwCount; + _outp(MPUPort(1), MPU_RESET_CMD); + for (dwCount=0; dwCount<0x2000; dwCount++) ; + _inp(MPUPort(0)); +#endif +} + +// +//############################################################################# +// IsMIDIAvailable +//############################################################################# +// +Logical + AudioCard::IsMIDIAvailable() +{ +#if 0 + return ((_inp(MPUPort(1)) & 0x80) == 0); +#endif + return False; +} + +// +//############################################################################# +// GetMIDIByte +//############################################################################# +// +MIDIValue + AudioCard::GetMIDIByte() +{ +#if 0 + return (_inp(MPUPort(0))); +#endif + return (MIDIValue)0; +} + +// +//############################################################################# +// InitializeChannels +//############################################################################# +// +void + AudioCard::InitializeChannels() +{ + Check(this); + + // + // Initialize idle channels + // + { + ChainIteratorOf iterator(&idleChannelSocket); + AudioChannel *channel; + + Check(&iterator); + Verify(iterator.GetSize() == (AWE_CHANNEL_COUNT-1)); + while ((channel = iterator.ReadAndNext()) != NULL) + { + Check(channel); + channel->SendPitchBendRange(MIDI_PITCH_BEND_RANGE); + } + } + + // + // Initialize percussive channels + // + { + ChainIteratorOf iterator(&percussionChannelSocket); + AudioChannel *channel; + + Check(&iterator); + Verify(iterator.GetSize() == 1); + channel = iterator.GetCurrent(); + Check(channel); + channel->SendPitchBendRange(MIDI_PITCH_BEND_RANGE); + } +} + +// +//############################################################################# +// LoadSBK +//############################################################################# +// +int + AudioCard::LoadSBK(const char *file_name) +{ +#ifdef AUDIO_HARDWARE + Check(this); + Check_Pointer(file_name); + + int ret; + + Tell("AudioCard::LoadSBK - " << file_name << "\n"); + ret = sosMIDIAWE32SetSBKFile(wDriverHandle, file_name); + Verify_And_Dump(ret >= 0, ret); + Tell("AudioCard::LoadSBK - Finished\n"); + return ret; +#else + return 1; +#endif +} + +// +//############################################################################# +// ReleaseAllBanks +//############################################################################# +// +void + AudioCard::ReleaseAllBanks() +{ +#ifdef AUDIO_HARDWARE + Check(this); + sosMIDIAWE32ReleaseSBKFiles(wDriverHandle); +#endif +} + +// +//############################################################################# +// MIDI methods +//############################################################################# +// + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendPitchBend( + MIDIChannel channel, + MIDIPitchBend pitch_bend + ) +{ + MIDIMessage + message( + MIDI_PITCH_BEND_STATUS, + channel, + (MIDIValue)((pitch_bend+8192)%128), + (MIDIValue)((pitch_bend+8192)/128) + ); + SendMIDIMessage(&message, 3); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendPitchBendRange( + MIDIChannel channel, + MIDIValue sensitivity + ) +{ + SendController(channel, (MIDIValue)101, (MIDIValue)0); + SendController(channel, (MIDIValue)100, (MIDIValue)0); + SendController(channel, (MIDIValue)6, sensitivity); +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendNRPN( + MIDIChannel channel, + MIDIValue param_number, + MIDINRPNValue value + ) +{ + // + // Set sound parameter + // + SendController(channel, (MIDIValue)99, (MIDIValue)127); + SendController(channel, (MIDIValue)98, param_number); + + // + // Set parameter value + // + SendController(channel, (MIDIValue)6, (MIDIValue)((value+8192)/128) ); + SendController(channel, (MIDIValue)38, (MIDIValue)((value+8192)%128) ); +} + +// +//############################################################################# +//############################################################################# +// +#define SYSEX_MACRO_LENGTH 11 + +Byte + chorus_sysex[SYSEX_MACRO_LENGTH] = + { + 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x38, 0x00, 0x00, 0xF7 + }; + +Byte + reverb_sysex[SYSEX_MACRO_LENGTH] = + { + 0xF0, 0x41, 0x10, 0x42, 0x12, 0x40, 0x01, 0x30, 0x00, 0x00, 0xF7 + }; + +void + AudioCard::SelectEffect( + MIDIEffectType type, + MIDIValue effect + ) +{ + switch (type) + { + case ChorusMIDIEffectType: + chorus_sysex[8] = effect; + SendSysex(chorus_sysex, SYSEX_MACRO_LENGTH); + break; + + case ReverbMIDIEffectType: + reverb_sysex[8] = effect; + SendSysex(reverb_sysex, SYSEX_MACRO_LENGTH); + break; + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendSysex( + void *data, + size_t length + ) +{ +#ifdef AUDIO_HARDWARE + WORD wError; + + // + // Note - HMI can specify sysex channel via F0, F1, ..., FF + // + #if defined(__BCPLUSPLUS__) + wError = sosMIDISendMIDIData( + wDriverHandle, + (char*)data, + length + ); + #else + wError = sosMIDISendMIDIData( + wDriverHandle, + (Byte*)data, + length + ); + #endif + if (wError != _ERR_NO_ERROR) + { + Fail("AudioCard::SendSysex - wError != _ERR_NO_ERROR"); + } +#endif +} + +#if 0 +// +//############################################################################# +//############################################################################# +// +void + AudioCard::SendMIDIMessage(MIDIMessage *midi_message) +{ +#ifdef AUDIO_HARDWARE + SET_AUDIO_RENDERER_MIDI(); + + Check(midi_message); + + #if 0 + long now = Now(); + Tell(now << "\t" << (int)srcAddx << "\t" << *midi_message << "\t"); + Tell(idleVoices << "\n"); + #endif + + switch (midi_message->message[0] >> 4) { + case MIDI_NOTE_ON_STATUS: + case MIDI_NOTE_OFF_STATUS: + case MIDI_POLYKEY_STATUS: + case MIDI_CONTROLLER_STATUS: + case MIDI_PITCH_BEND_STATUS: + #if DEBUG_LEVEL>0 + { + Word wError = sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 3 + ); + Verify(wError == _ERR_NO_ERROR); + } + #else + sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 3 + ); + #endif + break; + + case MIDI_PROGRAM_CHANGE_STATUS: + case MIDI_CHANNEL_PRESSURE_STATUS: + #if DEBUG_LEVEL>0 + { + Word wError = sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 2 + ); + Verify(wError == _ERR_NO_ERROR); + } + #else + sosMIDISendMIDIData( + wDriverHandle, + (char*)midi_message->message, + 2 + ); + #endif + break; + + default: + // + // Should never reach here + // + Fail("Should never reach here"); + break; + } + CLEAR_AUDIO_RENDERER_MIDI(); +#endif +} +#endif + +// +//############################################################################# +// Channel methods +//############################################################################# +// + +// +//############################################################################# +//############################################################################# +// +AudioChannel* + AudioCard::RequestAudioChannel(AudioVoiceCount voice_count) +{ + Check(this); + + // + // Monitor resource usage + // + #if 0 + #if DEBUG_LEVEL>0 + { + ChainIteratorOf iterator(&idleChannelSocket); + + if (voice_count > idleVoices || iterator.GetSize() == 0) + { + Tell("RequestAudioChannel - voices: " << idleVoices); + Tell(" channels: " << iterator.GetSize()); + Tell("\n"); + } + } + #endif + #endif + + // + // Are there enough voices to allocate + // + if (voice_count > idleVoices) + return NULL; + + // + // Allocate a channel + // + ChainIteratorOf iterator(&idleChannelSocket); + AudioChannel *audio_channel; + + Check(&iterator); + if ((audio_channel = iterator.GetCurrent()) != NULL) + { + Check(audio_channel); + iterator.Remove(); + idleVoices -= voice_count; + audio_channel->SetVoicesUsed(voice_count); + + return audio_channel; + } + return NULL; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioCard::ReleaseAudioChannel(AudioChannel *audio_channel) +{ + Check(this); + Check(audio_channel); + + #if 0 + Tell("AudioCard::ReleaseAudioChannel - Released channel\n"); + Tell(" "); + Dump((int)audio_channel->GetChannelNumber()); + #endif + + // + // Add to idle list + // + idleVoices += audio_channel->GetVoicesUsed(); + Verify(idleVoices > 0 && idleVoices <= AWE_VOICE_COUNT); + audio_channel->SetVoicesUsed(0); + + idleChannelSocket.Add(audio_channel); +} + +// +//############################################################################# +// GetHexWord +//############################################################################# +// +WORD + AudioCard::GetHexWord(const char ** s) +{ + WORD n = 0; + + while (**s) { + if (**s >= '0' && **s <= '9') + n = (WORD)(n * 16 + (*(*s)++ - '0')); + else + if (**s >= 'a' && **s <= 'f') + n = (WORD)(n * 16 + (*(*s)++ - 'a') + 10); + else + if (**s >= 'A' && **s <= 'F') + n = (WORD)(n * 16 + (*(*s)++ - 'A') + 10); + else + break; + } + return n; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// AudioHardware +//############################################################################# +// +AudioHardware::AudioHardware() +{ +} + +// +//############################################################################# +// ~AudioHardware +//############################################################################# +// +AudioHardware::~AudioHardware() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioHardware::TestInstance() const +{ + Node::TestInstance(); + Check(&frontCard); + Check(&rearCard); + return True; +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + AudioHardware::Initialize() +{ +#ifdef AUDIO_HARDWARE + Tell("AudioHardware::Initialize - Start\n"); + + #if 0 + // + // initialize the TIMER system and tell it to call the DOS timer + // at a rate of 19 times/second. the actual rate is 18.2, but + // 19 is a good approximation. + // + if (getenv(TIMER_ENV) == NULL) // L4Time is not setting up timer + { + sosTIMERInitSystem(_TIMER_DOS_RATE, _SOS_DEBUG_NORMAL); + } + #endif + + // + // initialize the MIDI system + // + sosMIDIInitSystem((PSTR)_SOS_DRIVER_PATH, _SOS_DEBUG_NORMAL); + + // + // initialize the cards + // + frontCard.GetEnvironmentSettings(FRONT_CARD_ENV_VAR); + rearCard.GetEnvironmentSettings(REAR_CARD_ENV_VAR); + frontCard.Initialize(); + rearCard.Initialize(); + + // + // Setup standard channel attributes + // + frontCard.InitializeChannels(); + rearCard.InitializeChannels(); + + Tell("AudioHardware::Initialize - Finish\n"); +#endif +} + +// +//############################################################################# +// Close +//############################################################################# +// +void + AudioHardware::Close() +{ +#ifdef AUDIO_HARDWARE + Check(this); + + // + // Close the cards + // + frontCard.Close(); + rearCard.Close(); + + #if 0 + // + // Uninitialize the TIMER system and pass it the value to write to the + // timer chip to reset the timer, 0 is equivalent to 18.2 times/second + // which is the DOS clock rate. the calculation for the value to pass + // is 1193180/RATE. + // + if (getenv(TIMER_ENV) == NULL) // L4Time is not setting up timer + { + sosTIMERUnInitSystem(0); + } + sosTIMERUnInitSystem(0); + #endif + + // + // Uninitialize the MIDI system + // + sosMIDIUnInitSystem(); +#endif +}*/ + +#ifdef TEST_CLASS +# include "l4audhdw.tcp" +#endif diff --git a/MUNGA_L4/L4AUDHDW.h b/MUNGA_L4/L4AUDHDW.h new file mode 100644 index 0000000..5ee0f38 --- /dev/null +++ b/MUNGA_L4/L4AUDHDW.h @@ -0,0 +1,530 @@ +#pragma once + +#include "..\munga\style.h" +#include "..\munga\node.h" +#include "..\munga\schain.h" +#include "..\munga\audio.h" +#include "openal/al.h" + +struct SourceSet +{ + int count; + ALuint sources[5]; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI types ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef unsigned char MIDIStatus; +typedef unsigned char MIDIChannel; +typedef unsigned char MIDIValue; +typedef int MIDIPitchBend; +typedef int MIDINRPNValue; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI status ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define MIDI_CHANNEL_COUNT (16) + +#define MIDI_NOTE_OFF_STATUS ((MIDIValue)0x8) // 8 +#define MIDI_NOTE_ON_STATUS ((MIDIValue)0x9) // 9 +#define MIDI_POLYKEY_STATUS ((MIDIValue)0xa) // 10 +#define MIDI_CONTROLLER_STATUS ((MIDIValue)0xb) // 11 +#define MIDI_PROGRAM_CHANGE_STATUS ((MIDIValue)0xc) // 12 +#define MIDI_CHANNEL_PRESSURE_STATUS ((MIDIValue)0xd) // 13 +#define MIDI_PITCH_BEND_STATUS ((MIDIValue)0xe) // 14 + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI controllers ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define MIDI_MAX_CONTROL_VALUE ((MIDIValue)127) +#define MIDI_MIN_CONTROL_VALUE ((MIDIValue)0) + +#define MIDI_LEFT_PAN_VALUE ((MIDIValue)0) +#define MIDI_CENTER_PAN_VALUE ((MIDIValue)63) +#define MIDI_RIGHT_PAN_VALUE ((MIDIValue)127) + +#define MIDI_VOLUME_CONTROL ((MIDIValue)7) +#define MIDI_PAN_CONTROL ((MIDIValue)10) +#define MIDI_REVERB_CONTROL ((MIDIValue)91) +#define MIDI_CHORUS_CONTROL ((MIDIValue)93) +#define MIDI_CONTROL_RESET ((MIDIValue)121) + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI notes ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define MIDI_DEFAULT_NOTE ((MIDIValue)60) + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDI pitch ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define MIDI_PITCH_BEND_MAX ((MIDIPitchBend)8191) +#define MIDI_PITCH_BEND_RANGE ((MIDIValue)24) +#define MIDI_PITCH_BEND_CENTS (24*100) +#define MIDI_PITCH_PER_CENTS ((Scalar)MIDI_PITCH_BEND_MAX / (Scalar)MIDI_PITCH_BEND_CENTS) + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE NRPN ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define AWE_VOL_ATTACK_TIME_NRPN ((MIDIValue)11) +#define AWE_PITCH_NRPN ((MIDIValue)16) +#define AWE_FILTER_CUTOFF_NRPN ((MIDIValue)21) + +#define AWE_VOL_ATTACK_TIME_RANGE ((MIDINRPNValue)5940) // 0...5.9 secs +#define AWE_FILTER_CUTOFF_RANGE ((MIDINRPNValue)127) // 100...8000 Hz + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE effects ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef enum +{ + ChorusMIDIEffectType, + ReverbMIDIEffectType +} MIDIEffectType; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AWE resources ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define AWE_VOICE_COUNT (32) +#define AWE_CHANNEL_COUNT (16) +#define AWE_PERCUSSIVE_CHANNEL (9) + +// +// Driver type to use +// +#define _MIDI_DRIVER_TYPE _MIDI_AWE32 + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ MIDIMessage ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define MIDI_MESSAGE_SIZE (3) + +class MIDIMessage SIGNATURED +{ + friend class AudioCard; + friend std::ostream& operator << (std::ostream &strm, const MIDIMessage &midi_message); + +public: + MIDIMessage(MIDIStatus status, MIDIChannel channel, MIDIValue byte1, MIDIValue byte2 = 0); + ~MIDIMessage() {} + + Logical TestInstance() const; + +private: + MIDIValue message[MIDI_MESSAGE_SIZE]; +}; + +inline MIDIMessage::MIDIMessage(MIDIStatus status, MIDIChannel channel, MIDIValue byte1, MIDIValue byte2) +{ + message[0] = (MIDIValue)((status << 4) | channel); + message[1] = byte1; + message[2] = byte2; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef enum +{ + InstrumentAudioChannelType = 0, + PercussionAudioChannelType +} AudioChannelType; + +class AudioCard; + +/*class AudioChannel : public Plug +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioChannel(AudioChannelType audio_channel_type, MIDIChannel midi_channel, AudioCard *audio_card); + ~AudioChannel(); + + Logical TestInstance() const; + + // + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- + // + AudioChannelType GetAudioChannelType() { return audioChannelType; } + MIDIChannel GetChannelNumber() { return midiChannel; } + void SetVoicesUsed(AudioVoiceCount voices_used) { voicesUsed = voices_used; } + AudioVoiceCount GetVoicesUsed() { return voicesUsed; } + + // + //-------------------------------------------------------------------- + // MIDI methods + //-------------------------------------------------------------------- + // + void SendNoteOn(MIDIValue key, MIDIValue velocity); + MIDIValue myPreset; + MIDIValue myBank; + void SendNoteOff(MIDIValue key, MIDIValue velocity); + void SendProgramChange(MIDIValue program); + void SendController(MIDIValue controller, MIDIValue value); + void SendPolyKeyPressure(MIDIValue key, MIDIValue value); + void SendChannelPressure(MIDIValue value); + void SendPitchBend(MIDIPitchBend pitch_bend); + void SendPitchBendRange(MIDIValue sensitivity); + void SendNRPN(MIDIValue paramNumber, MIDINRPNValue value); + void SelectEffect(MIDIEffectType type, MIDIValue effect); + void SelectBank(MIDIValue bank); + + // + //-------------------------------------------------------------------- + // Release + //-------------------------------------------------------------------- + // + void Release(); + +private: + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + AudioChannelType + audioChannelType; + MIDIChannel midiChannel; + AudioVoiceCount voicesUsed; + AudioCard *audioCard; +};*/ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +/*class AudioCard : public Node +{ + friend class AudioHardware; + +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioCard(); + ~AudioCard(); + + Logical TestInstance() const; + + // + //-------------------------------------------------------------------- + // Public methods + //-------------------------------------------------------------------- + // + void Initialize(); + void Close(); + void GetEnvironmentSettings(char *env_str); + + Logical InitMIDIReceive(); + void CloseMIDIReceive(); + Logical IsMIDIAvailable(); + MIDIValue GetMIDIByte(); + + void InitializeChannels(); + int LoadSBK(const char *file_name); + void ReleaseAllBanks(); + + // + //-------------------------------------------------------------------- + // MIDI methods + //-------------------------------------------------------------------- + // + void SendNoteOn(MIDIChannel channel, MIDIValue key, MIDIValue velocity); + void SendNoteOff(MIDIChannel channel, MIDIValue key, MIDIValue velocity); + void SendProgramChange(MIDIChannel channel, MIDIValue program); + void SendController(MIDIChannel channel, MIDIValue controller, MIDIValue value); + void SendPolyKeyPressure(MIDIChannel channel, MIDIValue key, MIDIValue value); + void SendChannelPressure(MIDIChannel channel, MIDIValue value); + void SendPitchBendRange(MIDIChannel channel, MIDIValue sensitivity); + void SendPitchBend(MIDIChannel channel, MIDIPitchBend pitch_bend); + void SendSysex(void *data, size_t length); + void SendNRPN(MIDIChannel channel, MIDIValue paramNumber, MIDINRPNValue value); + void SelectEffect(MIDIEffectType type, MIDIValue effect); + void SelectBank(MIDIChannel channel, MIDIValue bank); + void SendMIDIMessage(MIDIMessage *midi_message, Word length); + + // + //-------------------------------------------------------------------- + // Channel methods + //-------------------------------------------------------------------- + // + AudioChannel* RequestAudioChannel(AudioVoiceCount voice_count); + void ReleaseAudioChannel(AudioChannel *audio_channel); + +private: + // + //-------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------- + // + WORD GetHexWord(const char ** s); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + + // + // Card addresses + // + WORD srcAddx; + WORD irqInterrupt; + WORD dmaChannel; + WORD mpuAddx; + WORD emuAddx; + + // + // Structure for the MIDI driver initialization function + // Structure for the MIDI driver hardware + // + #ifdef AUDIO_HARDWARE + _SOS_MIDI_INIT_DRIVER sSOSMIDIInitDriver; + _SOS_MIDI_HARDWARE sSOSMIDIHardware; + #endif + + // + // Handle for the loaded MIDI driver + // + WORD wDriverHandle; + + // + // Number of free voices + // + AudioVoiceCount + idleVoices; + + // + // Idle channels + // + ChainOf idleChannelSocket; + ChainOf percussionChannelSocket; +};*/ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +/*class AudioHardware : public Node +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor, Testing + //-------------------------------------------------------------------- + // + AudioHardware(); + ~AudioHardware(); + + Logical TestInstance() const; + static Logical TestClass(); + static Logical ProfileClass(); + + // + //-------------------------------------------------------------------- + // Public methods + //-------------------------------------------------------------------- + // + void Initialize(); + void Close(); + + // + //-------------------------------------------------------------------- + // Card Access + //-------------------------------------------------------------------- + // + AudioCard* GetFrontCard(); + + AudioCard* GetRearCard(); + +private: + // + //-------------------------------------------------------------------- + // Private methods + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + AudioCard frontCard; + AudioCard rearCard; +};*/ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioCard inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +/*inline void AudioCard::SendMIDIMessage(MIDIMessage *midi_message, Word length) +{ +#ifdef AUDIO_HARDWARE + SET_AUDIO_RENDERER_MIDI(); + + Check_Signature(midi_message); + #if DEBUG_LEVEL>0 + switch (midi_message->message[0] >> 4) + { + case MIDI_NOTE_ON_STATUS: + case MIDI_NOTE_OFF_STATUS: + case MIDI_POLYKEY_STATUS: + case MIDI_CONTROLLER_STATUS: + case MIDI_PITCH_BEND_STATUS: + Verify(length == 3); + break; + + case MIDI_PROGRAM_CHANGE_STATUS: + case MIDI_CHANNEL_PRESSURE_STATUS: + Verify(length == 2); + break; + default: + Fail("Should never reach here"); + break; + } + #endif + + #if DEBUG_LEVEL>0 + { + Word wError = sosMIDISendMIDIData(wDriverHandle, (char*)midi_message->message, length); + Verify(wError == _ERR_NO_ERROR); + } + #else + sosMIDISendMIDIData(wDriverHandle, (char*)midi_message->message, length); + #endif + CLEAR_AUDIO_RENDERER_MIDI(); +#endif +} + +// +//-------------------------------------------------------------------- +// MIDI methods +//-------------------------------------------------------------------- +// +inline void AudioCard::SendNoteOn(MIDIChannel channel, MIDIValue key, MIDIValue velocity) +{ + MIDIMessage message(MIDI_NOTE_ON_STATUS, channel, key, velocity); + SendMIDIMessage(&message, 3); +} + +inline void AudioCard::SendNoteOff(MIDIChannel channel, MIDIValue key, MIDIValue velocity) +{ + MIDIMessage message(MIDI_NOTE_OFF_STATUS, channel, key, velocity); + SendMIDIMessage(&message, 3); +} + +inline void AudioCard::SendProgramChange(MIDIChannel channel, MIDIValue program) +{ + MIDIMessage message(MIDI_PROGRAM_CHANGE_STATUS, channel, program); + SendMIDIMessage(&message, 2); +} + +inline void AudioCard::SendController(MIDIChannel channel, MIDIValue controller, MIDIValue value) +{ + MIDIMessage message(MIDI_CONTROLLER_STATUS, channel, controller, value); + SendMIDIMessage(&message, 3); +} + +inline void AudioCard::SendPolyKeyPressure(MIDIChannel channel, MIDIValue key, MIDIValue value) +{ + MIDIMessage message(MIDI_POLYKEY_STATUS, channel, key, value); + SendMIDIMessage(&message, 3); +} + +inline void AudioCard::SendChannelPressure(MIDIChannel channel, MIDIValue value) +{ + MIDIMessage message(MIDI_CHANNEL_PRESSURE_STATUS, channel, value); + SendMIDIMessage(&message, 2); +} + +inline void AudioCard::SelectBank(MIDIChannel channel, MIDIValue bank) +{ + SendController(channel, (MIDIValue)0, bank); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannel inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//-------------------------------------------------------------------- +// MIDI methods +//-------------------------------------------------------------------- +// +inline void AudioChannel::SendNoteOn(MIDIValue key, MIDIValue velocity) +{ + DEBUG_STREAM << "Sending note " << (int)key << " for bank " << (int)myBank << ", preset " << (int)myPreset << "." << std::endl << std::flush; + //Check(audioCard); + //audioCard->SendNoteOn(midiChannel,key,velocity); +} + +inline void AudioChannel::SendNoteOff(MIDIValue key, MIDIValue velocity) +{ + Check(audioCard); + audioCard->SendNoteOff(midiChannel,key,velocity); +} + +inline void AudioChannel::SendProgramChange(MIDIValue program) +{ + Check(audioCard); + myPreset = program; + audioCard->SendProgramChange(midiChannel,program); +} + +inline void AudioChannel::SendController(MIDIValue controller, MIDIValue value) +{ + Check(audioCard); + audioCard->SendController(midiChannel,controller,value); +} + +inline void AudioChannel::SendPolyKeyPressure(MIDIValue key, MIDIValue value) +{ + Check(audioCard); + audioCard->SendPolyKeyPressure(midiChannel,key,value); +} + +inline void AudioChannel::SendChannelPressure(MIDIValue value) +{ + Check(audioCard); + audioCard->SendChannelPressure(midiChannel,value); +} + +inline void AudioChannel::SendPitchBend(MIDIPitchBend pitch_bend) +{ + Check(audioCard); + audioCard->SendPitchBend(midiChannel,pitch_bend); +} + +inline void AudioChannel::SendPitchBendRange(MIDIValue sensitivity) +{ + Check(audioCard); + audioCard->SendPitchBendRange(midiChannel,sensitivity); +} + +inline void AudioChannel::SelectEffect(MIDIEffectType type, MIDIValue effect) +{ + Check(audioCard); + audioCard->SelectEffect(type,effect); +} + +inline void AudioChannel::SendNRPN(MIDIValue paramNumber, MIDINRPNValue value) +{ + Check(audioCard); + audioCard->SendNRPN(midiChannel,paramNumber,value); +} + +inline void AudioChannel::SelectBank(MIDIValue bank) +{ + Check(audioCard); + myBank = bank; + audioCard->SelectBank(midiChannel,bank); +} + +inline void AudioChannel::Release() +{ + Check(audioCard); + audioCard->ReleaseAudioChannel(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~ AudioHardware inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +inline AudioCard* AudioHardware::GetFrontCard() +{ + Check(this); + return &frontCard; +} + +inline AudioCard* AudioHardware::GetRearCard() +{ + Check(this); + return &rearCard; +}*/ diff --git a/MUNGA_L4/L4AUDIO.cpp b/MUNGA_L4/L4AUDIO.cpp new file mode 100644 index 0000000..9932a79 --- /dev/null +++ b/MUNGA_L4/L4AUDIO.cpp @@ -0,0 +1,2190 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4audio.h" +#include "l4audlvl.h" +#include "l4app.h" +#include "l4audrnd.h" +#include "..\munga\namelist.h" +#include "..\munga\player.h" +#include "..\rp\vtv.h" + +//############################################################################# +//####################### L4AudioSpatialization ######################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +L4AudioSpatialization::L4AudioSpatialization() +{ + azimuthOfSource = 0.0f; + + frontLeftScale = 0.0f; + frontRightScale = 0.0f; + rearLeftScale = 0.0f; + rearRightScale = 0.0f; + + frontLeftDelay = 0.0f; + frontRightDelay = 0.0f; + rearLeftDelay = 0.0f; + rearRightDelay = 0.0f; + + quadrant = Quadrant1; +} + +// +//############################################################################# +//############################################################################# +// +L4AudioSpatialization::~L4AudioSpatialization() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioSpatialization::TestInstance() const +{ + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSpatialization::CalculateSpatialization(Radian azimuth_of_source) +{ + azimuthOfSource = azimuth_of_source; + + // + //--------------------------------------------------------------- + // Make azimuth usable for channel volume calculations + //--------------------------------------------------------------- + // + #define DEG_90 (90.0f*(RAD_PER_DEG)) + #define DEG_180 (180.0f*(RAD_PER_DEG)) + #define DEG_360 (360.0f*(RAD_PER_DEG)) + + azimuthOfSource = DEG_180 + azimuthOfSource; + if (azimuthOfSource > DEG_180) + azimuthOfSource = azimuthOfSource - DEG_360; + Verify( + azimuthOfSource <= DEG_180 && + azimuthOfSource >= -DEG_180 + ); + + // + //--------------------------------------------------------------- + // Channel volume scale and ITD calculations + //--------------------------------------------------------------- + // + + // + // Get audio head constants + // + L4AudioRenderer *audio_renderer; + AudioHead *audio_head; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + // + // Init channel volume scale variables + // + const Radian azimuth_max = 45.0*RAD_PER_DEG; // HACK - should come from audio.ini + Scalar tangent_ratio; + + frontLeftScale = 0.0f; + frontRightScale = 0.0f; + rearLeftScale = 0.0f; + rearRightScale = 0.0f; + + // + // Init ITD parameters + // + const Scalar itd_delay = audio_head->GetITDDifference(); + + frontLeftDelay = 0.0f; + frontRightDelay = 0.0f; + rearLeftDelay = 0.0f; + rearRightDelay = 0.0f; + + // + //--------------------------------------------------------------- + // Quadrant 1 + //--------------------------------------------------------------- + // + if ( + azimuthOfSource > -azimuth_max && + azimuthOfSource < azimuth_max + ) + { + quadrant = Quadrant1; + + // volume scale + Verify(!Small_Enough(tan(azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(azimuth_max)) * 0.5f; + + frontLeftScale = Sqrt(0.5f + tangent_ratio); + frontRightScale = Sqrt(0.5f - tangent_ratio); + Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f); + Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > 0.0f) + { + frontLeftDelay = itd_delay * tangent_ratio * 2.0f; + } + else + { + frontRightDelay = itd_delay * -tangent_ratio * 2.0f; + } + } + // + //--------------------------------------------------------------- + // Quadrant 2 + //--------------------------------------------------------------- + // + else if ( + azimuthOfSource > azimuth_max && + azimuthOfSource < (DEG_180 - azimuth_max) + ) + { + quadrant = Quadrant2; + + // volume scale + azimuthOfSource = azimuthOfSource - DEG_90; + + Verify(!Small_Enough(tan(DEG_90 - azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(DEG_90 - azimuth_max)) * 0.5f; + + rearLeftScale = Sqrt(0.5f + tangent_ratio); + frontLeftScale = Sqrt(0.5f - tangent_ratio); + Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f); + Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > 0.0f) + { + rearLeftDelay = itd_delay * tangent_ratio * 2.0f; + } + else + { + frontLeftDelay = itd_delay * -tangent_ratio * 2.0f; + } + } + // + //--------------------------------------------------------------- + // Quadrant 3 + //--------------------------------------------------------------- + // + else if ( + azimuthOfSource > (DEG_180 - azimuth_max) || + azimuthOfSource < (-DEG_180 + azimuth_max) + ) + { + quadrant = Quadrant3; + + // volume scale + azimuthOfSource = azimuthOfSource - DEG_180; + + Verify(!Small_Enough(tan(azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(azimuth_max)) * 0.5f; + + rearRightScale = Sqrt(0.5f + tangent_ratio); + rearLeftScale = Sqrt(0.5f - tangent_ratio); + Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f); + Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > -azimuth_max) + { + rearLeftDelay = -(itd_delay * tangent_ratio * 2.0f); + } + else + { + rearRightDelay = -(itd_delay * -tangent_ratio * 2.0f); + } + + #if 0 + Tell( + "azimuthOfSource " << azimuthOfSource << + " rearRightDelay " << rearRightDelay << + " rearLeftDelay " << rearLeftDelay << + "\n" + ); + #endif + } + // + //--------------------------------------------------------------- + // Quadrant 4 + //--------------------------------------------------------------- + // + else + { + quadrant = Quadrant4; + + Verify( + azimuthOfSource > (-DEG_180 + azimuth_max) && + azimuthOfSource < -azimuth_max + ); + + // volume scale + azimuthOfSource = azimuthOfSource + DEG_90; + + Verify(!Small_Enough(tan(DEG_90 - azimuth_max))); + tangent_ratio = + (tan(azimuthOfSource) / tan(DEG_90 - azimuth_max)) * 0.5f; + + frontRightScale = Sqrt(0.5f + tangent_ratio); + rearRightScale = Sqrt(0.5f - tangent_ratio); + Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f); + Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f); + + // pitch offset + if (azimuthOfSource > 0.0f) + { + frontRightDelay = itd_delay * tangent_ratio * 2.0f; + } + else + { + rearRightDelay = itd_delay * -tangent_ratio * 2.0f; + } + } + + #if 0 + Tell( + "FL " << frontLeftScale << + " FR " << frontRightScale << + " RL " << rearLeftScale << + " RR " << rearRightScale << + "\n" + ); + #endif + + #if 0 + Tell( + "Quadrant " << quadrant << + " FL " << frontLeftDelay << + " FR " << frontRightDelay << + " RL " << rearLeftDelay << + " RR " << rearRightDelay << + "\n" + ); + #endif + + Verify(frontLeftScale >= 0.0f && frontLeftScale <= 1.0f); + Verify(frontRightScale >= 0.0f && frontRightScale <= 1.0f); + Verify(rearLeftScale >= 0.0f && rearLeftScale <= 1.0f); + Verify(rearRightScale >= 0.0f && rearRightScale <= 1.0f); +} + +//############################################################################# +//######################### L4AudioLocation ############################# +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +L4AudioLocation::L4AudioLocation( + PlugStream *stream, + Entity *entity +): + AudioLocation(stream, entity) +{ + L4AudioLocationX(); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioLocation::L4AudioLocationX() +{ + // + // Get audio renderer frame duration + // + Check(application) + L4AudioRenderer *audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + + Time frame_duration = + audio_renderer->GetCalibrationFrameDuration(); + + // + // Init ITD pitch offset variables + // + lastITDFrameTime = Now(); + lastITDFrameTime -= frame_duration; + + currentFrontLeftDelay = 0.0f; + currentFrontRightDelay = 0.0f; + currentRearLeftDelay = 0.0f; + currentRearRightDelay = 0.0f; + + frontLeftITDPitchOffset = 0.0f; + frontRightITDPitchOffset = 0.0f; + rearLeftITDPitchOffset = 0.0f; + rearRightITDPitchOffset = 0.0f; +} + +// +//############################################################################# +//############################################################################# +// +L4AudioLocation::~L4AudioLocation() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioLocation::TestInstance() const +{ + AudioLocation::TestInstance(); + Check(&spatialization); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioLocation::UpdateSpatialModelImplementation(AudioHead *audio_head) +{ + Check(this); + Check(audio_head); + + // + //--------------------------------------------------------------- + // Call inherited method + //--------------------------------------------------------------- + // + AudioLocation::UpdateSpatialModelImplementation(audio_head); + + // + //--------------------------------------------------------------- + // Catch case of head == source + //--------------------------------------------------------------- + // + if (IsHeadSource()) + { + spatialization.frontLeftScale = 1.0f; + spatialization.frontRightScale = 1.0f; + spatialization.rearLeftScale = 1.0f; + spatialization.rearRightScale = 1.0f; + + frontLeftITDPitchOffset = 0.0f; + frontRightITDPitchOffset = 0.0f; + rearLeftITDPitchOffset = 0.0f; + rearRightITDPitchOffset = 0.0f; + return; + } + + // + //--------------------------------------------------------------- + // Calculate channel spatialization + //--------------------------------------------------------------- + // + spatialization.CalculateSpatialization(GetAzimuthOfSource()); + + // + //--------------------------------------------------------------- + // Calculate ITD pitch offsets + //--------------------------------------------------------------- + // + const Scalar itd_pitch_offset_constant = + 0.003831f / 0.000002f; // period / delay // HACK - should come from audio head + + Time itd_delta_time; + + itd_delta_time = Now(); + itd_delta_time -= lastITDFrameTime; + lastITDFrameTime = Now(); + + frontLeftITDPitchOffset = 0.0f; + frontRightITDPitchOffset = 0.0f; + rearLeftITDPitchOffset = 0.0f; + rearRightITDPitchOffset = 0.0f; + + if (!Small_Enough((Scalar)itd_delta_time)) + { + if (currentFrontLeftDelay != spatialization.frontLeftDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + frontLeftITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.frontLeftDelay - currentFrontLeftDelay) / + (Scalar)itd_delta_time; + currentFrontLeftDelay = spatialization.frontLeftDelay; + } + if (currentFrontRightDelay != spatialization.frontRightDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + frontRightITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.frontRightDelay - currentFrontRightDelay) / + (Scalar)itd_delta_time; + currentFrontRightDelay = spatialization.frontRightDelay; + } + if (currentRearLeftDelay != spatialization.rearLeftDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + rearLeftITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.rearLeftDelay - currentRearLeftDelay) / + (Scalar)itd_delta_time; + currentRearLeftDelay = spatialization.rearLeftDelay; + } + if (currentRearRightDelay != spatialization.rearRightDelay) + { + Verify(!Small_Enough((Scalar)itd_delta_time)); + + rearRightITDPitchOffset = + itd_pitch_offset_constant * + (spatialization.rearRightDelay - currentRearRightDelay) / + (Scalar)itd_delta_time; + currentRearRightDelay = spatialization.rearRightDelay; + } + } + + #if 0 + Tell( + "Quadrant " << spatialization.quadrant << + " FL " << frontLeftITDPitchOffset << + " FR " << frontRightITDPitchOffset << + " RL " << rearLeftITDPitchOffset << + " RR " << rearRightITDPitchOffset << + "\n" + ); + #endif + + // + //--------------------------------------------------------------- + // Check for source "between ears" + //--------------------------------------------------------------- + // + const Scalar ear_radius = + audio_head->GetDistanceBetweenEars() * 0.5; + Scalar distance_to_source_listener_plane = + GetDistanceToSourceListenerPlane(); + + if (distance_to_source_listener_plane < ear_radius) + { + Verify(!Small_Enough(ear_radius)); + + const Scalar proportion = + 0.5f * + (ear_radius - distance_to_source_listener_plane) / + ear_radius; + + Scalar powerA, powerB; + + #if DEBUG_LEVEL>0 + if (!(proportion >= 0.0f && proportion <= 1.0f)) + { + Dump(ear_radius); + Dump(distance_to_source_listener_plane); + Dump(proportion); + } + Verify(proportion >= 0.0f && proportion <= 1.0f); + #endif + + powerA = Sqrt(1.0f - proportion); + powerB = Sqrt(proportion); + Verify(powerA >= 0.0f && powerA <= 1.0f); + Verify(powerB >= 0.0f && powerB <= 1.0f); + + switch (spatialization.quadrant) + { + case L4AudioSpatialization::Quadrant1: + spatialization.rearLeftScale = spatialization.frontLeftScale * powerB; + spatialization.rearRightScale = spatialization.frontRightScale * powerB; + + spatialization.frontLeftScale *= powerA; + spatialization.frontRightScale *= powerA; + break; + + case L4AudioSpatialization::Quadrant2: + spatialization.rearRightScale = spatialization.rearLeftScale * powerB; + spatialization.frontRightScale = spatialization.frontLeftScale * powerB; + + spatialization.rearLeftScale *= powerA; + spatialization.frontLeftScale *= powerA; + break; + + case L4AudioSpatialization::Quadrant3: + spatialization.frontRightScale = spatialization.rearRightScale * powerB; + spatialization.frontLeftScale = spatialization.rearLeftScale * powerB; + + spatialization.rearRightScale *= powerA; + spatialization.rearLeftScale *= powerA; + break; + + case L4AudioSpatialization::Quadrant4: + spatialization.frontLeftScale = spatialization.frontRightScale * powerB; + spatialization.rearLeftScale = spatialization.rearRightScale * powerB; + + spatialization.frontRightScale *= powerA; + spatialization.rearRightScale *= powerA; + break; + } + + #if 0 + Tell( + "FL " << spatialization.frontLeftScale << + " FR " << spatialization.frontRightScale << + " RL " << spatialization.rearLeftScale << + " RR " << spatialization.rearRightScale << + "\n" + ); + #endif + } + + Verify(spatialization.frontLeftScale >= 0.0f && spatialization.frontLeftScale <= 1.0f); + Verify(spatialization.frontRightScale >= 0.0f && spatialization.frontRightScale <= 1.0f); + Verify(spatialization.rearLeftScale >= 0.0f && spatialization.rearLeftScale <= 1.0f); + Verify(spatialization.rearRightScale >= 0.0f && spatialization.rearRightScale <= 1.0f); +} + +//############################################################################# +//######################### AudioChannelSet ############################# +//############################################################################# + +//AudioChannelSet AudioChannelSet::Null; + +// +//############################################################################# +//############################################################################# +// +/*AudioChannelSet::AudioChannelSet() +{ + for (int i = 0; i < AudioChannelSetSize; i++) + { + channels[i] = NULL; + enables[i] = False; + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + AudioChannelSet::TestInstance() const +{ + for (int i = 0; i < AudioChannelSetSize; i++) + { + if (channels[i] != NULL) + { + Verify(enables[i] == True); + Check(channels[i]); + } + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + AudioChannelSet::EnableAll() +{ + // + // Must set all channels to null and all enables to True + // + for (int i = 0; i < AudioChannelSetSize; i++) + { + channels[i] = NULL; + enables[i] = True; + } +} + +// +//############################################################################# +//############################################################################# +// +void + AudioChannelSet::ReleaseAll() +{ + // + // Must release all channels without changing enable values + // + for (int i = 0; i < AudioChannelSetSize; i++) + { + if (channels[i] != NULL) + { + Check(channels[i]); + channels[i]->Release(); + channels[i] = NULL; + } + } +}*/ + +//############################################################################# +//########################## L4AudioSource ############################## +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +L4AudioSource::L4AudioSource( + PlugStream *stream, + Entity *entity +): + AudioSource(stream, entity) +{ + channelSet.count = GetAudioVoiceCount(); + L4AudioSourceX(); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::L4AudioSourceX() +{ +} + +// +//############################################################################# +//############################################################################# +// +L4AudioSource::~L4AudioSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioSource::TestInstance() const +{ + AudioSource::TestInstance(); + Check(&channelSet); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::StopMessageImplementation() +{ + Check(this); + + AudioSource::StopMessageImplementation(); + + // + // Request stop from renderer + // + Check(application); + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())-> + StopRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::SetAudioChannelSet(const SourceSet &audio_channel_set) +{ + Check(this); + channelSet = audio_channel_set; +} + +// +//############################################################################# +//############################################################################# +// +SourceSet* + L4AudioSource::GetAudioChannelSet() +{ + Check(this); + return &channelSet; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioSource::ReleaseChannels() +{ + Check(this); + //How do I release the sources, man? + application->GetAudioRenderer()->ReleaseSourceSet(channelSet); + + for (int i=0; i < channelSet.count; i++) + { + channelSet.sources[i] = 0; + } + //channelSet.ReleaseAll(); +} + +//############################################################################# +//######################## DirectPatchSource ############################ +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +DirectPatchSource::DirectPatchSource( + PlugStream *stream, + Entity *entity +): + L4AudioSource(stream, entity) +{ + MemoryStream_Read(stream, &audioPosition); +// channel = NULL; +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + L4AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, position); +} + +// +//############################################################################# +//############################################################################# +// +DirectPatchSource::~DirectPatchSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + DirectPatchSource::TestInstance() const +{ + L4AudioSource::TestInstance(); +/* if (channel != NULL) + { + Check(channel); + }*/ + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::StartMessageImplementation() +{ + Check(this); + + L4AudioSource::StartMessageImplementation(); + + // + //-------------------------------------------------------------------------- + // Init channel set to requested channels + //-------------------------------------------------------------------------- + // +/* channelSet = AudioChannelSet::Null; + switch (audioPosition) + { + case FrontDirectPatchPosition: + case FrontLeftDirectPatchPosition: + case FrontRightDirectPatchPosition: + channelSet.EnableFrontLeft(True); + break; + + case RearDirectPatchPosition: + case RearLeftDirectPatchPosition: + case RearRightDirectPatchPosition: + channelSet.EnableRearLeft(True); + break; + }*/ + + // + //-------------------------------------------------------------------------- + // Request start from renderer + //-------------------------------------------------------------------------- + // + Check(application); + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())-> + StartRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::StartImplementation() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------------- + // + L4AudioSource::StartImplementation(); + + // + //-------------------------------------------------------------------------- + // Remember the channel + //-------------------------------------------------------------------------- + // +/* Verify(channel == NULL); + switch (audioPosition) + { + case FrontDirectPatchPosition: + case FrontLeftDirectPatchPosition: + case FrontRightDirectPatchPosition: + channel = channelSet.GetFrontLeft(); + break; + + case RearDirectPatchPosition: + case RearLeftDirectPatchPosition: + case RearRightDirectPatchPosition: + channel = channelSet.GetRearLeft(); + break; + } + Check(channel);*/ + + // + //-------------------------------------------------------------------------- + // Setup the channel + //-------------------------------------------------------------------------- + // + ExecuteWatchers(); + + // + // Turn the volume down while setting up the channel + // +// channel->SendController(MIDI_VOLUME_CONTROL, MIDI_MIN_CONTROL_VALUE); + + // + // Set the channel to the bank and program + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->SetDistance(GetDistanceToSource()); + patch_resource->SetupPatch(channelSet); + + // + // Set the channel to default control values + // +// channel->SendController(MIDI_REVERB_CONTROL, MIDI_MIN_CONTROL_VALUE); +// channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE); + +/* switch (audioPosition) + { + case FrontDirectPatchPosition: + case RearDirectPatchPosition: + channel->SendController(MIDI_PAN_CONTROL, MIDI_CENTER_PAN_VALUE); + break; + case FrontLeftDirectPatchPosition: + case RearLeftDirectPatchPosition: + channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE); + break; + case FrontRightDirectPatchPosition: + case RearRightDirectPatchPosition: + channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE); + break; + }*/ + + // + // Set midi history to default control values + // + lastMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastMIDIPitchBend = 0; // Set by force update + lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch load + + // + //-------------------------------------------------------------------------- + // Calculate attack time, velocity, and execute model + //-------------------------------------------------------------------------- + // + MIDIValue midi_velocity = + CalculateSourceAttackVolumeScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (UseSourceAttackTime()) + { + MIDINRPNValue midi_attack_time = + CalculateSourceAttackTime() * + (Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f; + +// channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time); + } + + ExecuteModel(True); + + // + //-------------------------------------------------------------------------- + // Start note + //-------------------------------------------------------------------------- + // + //TODO: Start OpenAL source playing +// channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity); + patch_resource->PlayNote(channelSet); + + #if 0 + Tell("On " << (int)GetCurrentNoteValue() << "\n"); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::StopImplementation() +{ + Check(this); + + //TODO: Stop OpenAL source playing + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->StopNote(channelSet); + + // + // Stop note + // +// Check(channel); +// channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE); +// channel = NULL; +} + +// +//############################################################################# +//############################################################################# +// +void + DirectPatchSource::ExecuteModel(Logical force_update) +{ + Check(this); + + //TODO: Probably don't have to do anything in this function- maybe watch + //to mess with looping appropriately. + + // + //-------------------------------------------------------------------------- + // Apply pitch offset + //-------------------------------------------------------------------------- + // + const MIDIPitchBend pitch_resolution = 12; // HACK - should come from audio.ini + AudioPitchCents pitch_offset; + + pitch_offset = CalculateSourcePitchOffset(); + double relativePitch = pow(2.0,pitch_offset/1200.0); + Clamp(relativePitch,0.5,2.0); + + // + //-------------------------------------------------------------------------- + // Apply filter scale + //-------------------------------------------------------------------------- + // + if (UseSourceBrightnessScale()) + { + const MIDINRPNValue filter_resolution = 2;// HACK - should come from audio.ini + Scalar filter_scale; + PatchResource *patch_resource; + MIDINRPNValue max_midi_filter_cutoff; + MIDINRPNValue midi_filter_cutoff; + MIDINRPNValue filter_difference; + + filter_scale = CalculateSourceBrightnessScale(); + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + max_midi_filter_cutoff = patch_resource->GetMaxMIDIFilterCutoff(); + midi_filter_cutoff = filter_scale * (Scalar)max_midi_filter_cutoff + 0.5f; + filter_difference = lastMIDIFilterCutoff - midi_filter_cutoff; + + if (Abs(filter_difference) >= filter_resolution) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + } + } + + // + //-------------------------------------------------------------------------- + // Apply volume scale + //-------------------------------------------------------------------------- + // + Scalar volume_scale; + const MIDIValue volume_resolution = 2; // HACK - should come from audio.ini + + volume_scale = CalculateSourceVolumeScale(); + L4AudioLocation *audio_location = Cast_Object(L4AudioLocation*, GetAudioLocation()); + Check(application); + L4AudioRenderer *audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + AudioHead *audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + for (int i=0; i < channelSet.count; i++) + { + alSourcef(channelSet.sources[i],AL_MAX_DISTANCE,audio_location->getMaxDistance(audio_head)); + alSourcef(channelSet.sources[i], AL_GAIN, volume_scale); + } +} + +//############################################################################# +//###################### Dynamic3DPatchSource ########################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +Dynamic3DPatchSource::Dynamic3DPatchSource( + PlugStream *stream, + Entity *entity +): + L4AudioSource(stream, entity) +{ +} + +Logical +Dynamic3DPatchSource::IsAudioSourceClipped(AudioHead *audio_head) +{ + if (AudioSource::IsAudioSourceClipped(audio_head) || l4_application->GetMissionPlayer()->GetPlayerVehicle()->GetSimulationState() == VTV::BurningState) + { + return true; + } else + { + return false; + } +} + +// +//############################################################################# +//############################################################################# +// +Dynamic3DPatchSource::~Dynamic3DPatchSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + Dynamic3DPatchSource::TestInstance() const +{ + L4AudioSource::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::StartMessageImplementation() +{ + Check(this); + + L4AudioSource::StartMessageImplementation(); + + // + // Init channel set to requested channels + // +// channelSet.EnableAll(); + + // + // Request start from renderer + // + Check(application); + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())-> + StartRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::StartImplementation() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------------- + // + L4AudioSource::StartImplementation(); + + // + //-------------------------------------------------------------------------- + // Get application, renderer and head pointers + //-------------------------------------------------------------------------- + // + L4AudioRenderer *audio_renderer; + AudioHead *audio_head; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + // + //-------------------------------------------------------------------------- + // Setup the channel + //-------------------------------------------------------------------------- + // + ExecuteWatchers(); + + // + // Turn the volume down while setting up the channels + // + + // + // Set the channels to the bank and program + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->SetDistance(GetDistanceToSource()); + patch_resource->SetupPatch(channelSet); + + /*patch_resource->SetDistance(GetDistanceToSource()); + for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + patch_resource->SetupPatch(channel); + }*/ + + // + // Set the channels to default control values + // + //MIDIValue midi_reverb_level = + // audio_head->GetGlobalReverbScale() * + // (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + +/* for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendController(MIDI_REVERB_CONTROL, midi_reverb_level); + channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE); + }*/ + + // + // Set the channels to correct pan + // +/* channel = channelSet.GetFrontLeft(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE); + + channel = channelSet.GetFrontRight(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE); + + channel = channelSet.GetRearLeft(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_LEFT_PAN_VALUE); + + channel = channelSet.GetRearRight(); + Check(channel); + channel->SendController(MIDI_PAN_CONTROL, MIDI_RIGHT_PAN_VALUE);*/ + + // + // Set midi history to default control values + // + /*lastFrontLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastFrontRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastFrontLeftMIDIPitchBend = 0; // Set by force update + lastFrontRightMIDIPitchBend = 0; // Set by force update + lastRearLeftMIDIPitchBend = 0; // Set by force update + lastRearRightMIDIPitchBend = 0; // Set by force update + lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch + + // + //-------------------------------------------------------------------------- + // Calculate attack time, velocity, and execute model + //-------------------------------------------------------------------------- + // + MIDIValue midi_velocity = + CalculateSourceAttackVolumeScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (UseSourceAttackTime()) + { + MIDINRPNValue midi_attack_time = + CalculateSourceAttackTime() * + (Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f; + + for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time); + } + }*/ + + ExecuteModel(True); + + // + //-------------------------------------------------------------------------- + // Start note + //-------------------------------------------------------------------------- + // + + //TODO: Start OpenAL source + +/* for (i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity); + }*/ + patch_resource->PlayNote(channelSet); +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::StopImplementation() +{ + Check(this); + + // + // Stop note + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->StopNote(channelSet); + + /* AudioChannel *channel; + for (int i = 0; i < AudioChannelSetSize; i++) + { + channel = channelSet.GetNth(i); + Check(channel); + channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE); + }*/ +} + +// +//############################################################################# +//############################################################################# +// +void + Dynamic3DPatchSource::ExecuteModel(Logical force_update) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Call inherited method + //-------------------------------------------------------------------------- + // + L4AudioSource::Execute(); + + // + //-------------------------------------------------------------------------- + // Get audio resource + //-------------------------------------------------------------------------- + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + + // + //-------------------------------------------------------------------------- + // Get audio location + //-------------------------------------------------------------------------- + // + L4AudioLocation *audio_location; + L4AudioRenderer *audio_renderer; + AudioHead *audio_head; + + audio_location = Cast_Object(L4AudioLocation*, GetAudioLocation()); + Check(audio_location); + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + // + //-------------------------------------------------------------------------- + // Render spatial model + //-------------------------------------------------------------------------- + // + + //TODO: Sync location info to OpenAL sources + Vector3D pos; + + Vector3D locationPosition = audio_location->GetLinkedEntity()->localOrigin.linearPosition; + Vector3D headPosition = audio_head->GetHeadEntity()->localOrigin.linearPosition; + + pos.Subtract(locationPosition, headPosition); + + float posMag = pos.Length(); + + pos.MultiplyByInverse(pos, audio_head->GetHeadEntity()->localToWorld); + + Vector3D relative_velocity; + relative_velocity.MultiplyByInverse( + audio_location->GetLinkedEntity()->GetWorldLinearVelocity(), + audio_head->GetHeadEntity()->localToWorld + ); + Check(&relative_velocity); + + Scalar volume_scale = CalculateSourceVolumeScale(); + + Scalar pitch_offset; + + pitch_offset = CalculateSourcePitchOffset(); + + double relativePitch = pow(2.0,pitch_offset/1200.0); + Clamp(relativePitch,0.5,2.0); + + for (int i=0; i < channelSet.count; i++) + { + alSource3f(channelSet.sources[i],AL_POSITION,pos.x,pos.y,pos.z); + alSourcef(channelSet.sources[i], AL_GAIN, volume_scale); + alSource3f(channelSet.sources[i],AL_VELOCITY,-relative_velocity.x,-relative_velocity.y,-relative_velocity.z); + alSourcef(channelSet.sources[i],AL_MAX_DISTANCE,audio_location->getMaxDistance(audio_head)); + } + +} + +// +//############################################################################# +//############################################################################# +// +AudioControlValue + Dynamic3DPatchSource::CalculateSourceVolumeScale() +{ + Check(this); + + // + // Call inherited method to calculate volume scale + // + Scalar + volume_scale = L4AudioSource::CalculateSourceVolumeScale(); + return volume_scale; + + // + // Update the spatial model that will result in the value + // for distance related volume attenuation + // + /*Check(application); + Check(application->GetAudioRenderer()); + UpdateSpatialModel(application->GetAudioRenderer()->GetAudioHead()); + + // + // Apply distance attenuation to the volume scale + // + Check(GetAudioLocation()); + volume_scale *= GetAudioLocation()->GetDistanceVolumeScale(); + return volume_scale;*/ +} + +//############################################################################# +//####################### Static3DPatchSource ########################### +//############################################################################# + +// +//############################################################################# +//############################################################################# +// +Static3DPatchSource::Static3DPatchSource( + PlugStream *stream, + Entity *entity +): + L4AudioSource(stream, entity), + position(0.0f, 0.0f, 0.0f) +{ + MemoryStream_Read(stream, &useInternalSpatialization); +} + +Logical Static3DPatchSource::IsAudioSourceClipped(AudioHead *audio_head) +{ + if (AudioSource::IsAudioSourceClipped(audio_head) || l4_application->GetMissionPlayer()->GetPlayerVehicle()->GetSimulationState() == VTV::BurningState) + { + return true; + } else + { + return false; + } +} + +// +//############################################################################# +//############################################################################# +// +Static3DPatchSource::~Static3DPatchSource() +{ +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + L4AudioSource::BuildFromPage(stream, name_list, class_ID, object_ID); + + if (name_list->FindData("use_internal") != NULL) + { + MEM_STRM_WRITE_ENTRY(*stream, name_list, Logical, use_internal); + } + else + { + Logical use_internal = True; + MemoryStream_Write(stream, &use_internal); + } +} + +// +//############################################################################# +//############################################################################# +// +Logical + Static3DPatchSource::TestInstance() const +{ + L4AudioSource::TestInstance(); + if (useInternalSpatialization) + { + Check(&internalSpatialization); + } + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::SetPosition(const Vector3D &vector3D) +{ + position = vector3D; +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::StartMessageImplementation() +{ + Check(this); + + L4AudioSource::StartMessageImplementation(); + + // + //-------------------------------------------------------------------------- + // Get audio renderer + //-------------------------------------------------------------------------- + // + L4AudioRenderer *audio_renderer; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + + // + //-------------------------------------------------------------------------- + // Update spatial parameters + //-------------------------------------------------------------------------- + // + if (useInternalSpatialization) + { + // + //----------------------------------------------------------------------- + // Calculate azimuth of position + //----------------------------------------------------------------------- + // + Radian azimuth_of_source; + + if (Small_Enough(position.x) && Small_Enough(position.z)) + { + azimuth_of_source = 0.0f; + } + else + { + Verify(!(Small_Enough(position.x) && Small_Enough(position.z))); + azimuth_of_source = Arctan(position.x, position.z); + } + Verify(azimuth_of_source <= PI && azimuth_of_source >= -PI); + + internalSpatialization.CalculateSpatialization(azimuth_of_source); + } + else + { + UpdateSpatialModel(audio_renderer->GetAudioHead()); + Cast_Object(L4AudioLocation*, GetAudioLocation())->GetSpatialization( + &internalSpatialization + ); + } + + // + //-------------------------------------------------------------------------- + // Init channel set to required channels + //-------------------------------------------------------------------------- + // +/* channelSet.EnableFrontLeft(False); + channelSet.EnableFrontRight(False); + channelSet.EnableRearLeft(False); + channelSet.EnableRearRight(False); + + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + channelSet.EnableFrontLeft(True); + break; + + case L4AudioSpatialization::Quadrant2: + channelSet.EnableFrontLeft(True); + channelSet.EnableRearLeft(True); + break; + + case L4AudioSpatialization::Quadrant3: + channelSet.EnableRearLeft(True); + break; + + case L4AudioSpatialization::Quadrant4: + channelSet.EnableFrontRight(True); + channelSet.EnableRearRight(True); + break; + }*/ + + // + //-------------------------------------------------------------------------- + // Request start from renderer + //-------------------------------------------------------------------------- + // + //audio_renderer->StartRequest(this); + (static_cast(application->GetAudioRenderer()))->StartRequest(this); + // Cast_Object(L4AudioRenderer*, application->GetAudioRenderer())-> + // StartRequest(this); +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::StartImplementation() +{ + Check(this); + + L4AudioSource::StartImplementation(); + + // + //-------------------------------------------------------------------------- + // Get audio head constants + //-------------------------------------------------------------------------- + // + L4AudioRenderer *audio_renderer; + AudioHead *audio_head; + + Check(application); + audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + // + //-------------------------------------------------------------------------- + // Setup the channel + //-------------------------------------------------------------------------- + // + ExecuteWatchers(); + + // + // Turn the volume down while setting up the channels + // + int i; +/* AudioChannel *channel; + + for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendController(MIDI_VOLUME_CONTROL, MIDI_MIN_CONTROL_VALUE); + } + }*/ + + // + // Set the channels to the bank and program + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->SetDistance(GetDistanceToSource()); + patch_resource->SetupPatch(channelSet); + /*for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + patch_resource->SetupPatch(channel); + } + }*/ + + // + // Set the channels to default control values + // + /*MIDIValue midi_reverb_level = + audio_head->GetGlobalReverbScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f;*/ + + /*for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendController(MIDI_REVERB_CONTROL, midi_reverb_level); + channel->SendController(MIDI_CHORUS_CONTROL, MIDI_MIN_CONTROL_VALUE); + } + }*/ + + // + // Set the channels to correct pan + // + + /* + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + { + const Radian azimuth_max = + 45.0*RAD_PER_DEG; // HACK - should come from head + const Scalar slope = + -(Scalar)MIDI_MAX_CONTROL_VALUE / (2.0f * azimuth_max); + const Scalar intercept = + (MIDI_MAX_CONTROL_VALUE * 0.5f); + MIDIValue + midi_pan; + + midi_pan = slope * GetAzimuthOfSource() + intercept; + Check(channelSet.GetFrontLeft()); + channelSet.GetFrontLeft()->SendController( + MIDI_PAN_CONTROL, + midi_pan + ); + } + break; + + case L4AudioSpatialization::Quadrant2: + { + Check(channelSet.GetFrontLeft()); + Check(channelSet.GetRearLeft()); + channelSet.GetFrontLeft()->SendController( + MIDI_PAN_CONTROL, + MIDI_MIN_CONTROL_VALUE + ); + channelSet.GetRearLeft()->SendController( + MIDI_PAN_CONTROL, + MIDI_MIN_CONTROL_VALUE + ); + } + break; + + case L4AudioSpatialization::Quadrant3: + { + const Radian azimuth_max = + 45.0*RAD_PER_DEG; // HACK - should come from head + const Scalar slope = + (Scalar)MIDI_MAX_CONTROL_VALUE / (2.0f * azimuth_max); + const Scalar intercept = + (MIDI_MAX_CONTROL_VALUE * 0.5f); + MIDIValue + midi_pan; + + midi_pan = slope * GetAzimuthOfSource() + intercept; + Check(channelSet.GetRearLeft()); + channelSet.GetRearLeft()->SendController( + MIDI_PAN_CONTROL, + midi_pan + ); + } + break; + + case L4AudioSpatialization::Quadrant4: + { + Check(channelSet.GetFrontRight()); + Check(channelSet.GetRearRight()); + channelSet.GetFrontRight()->SendController( + MIDI_PAN_CONTROL, + MIDI_MAX_CONTROL_VALUE + ); + channelSet.GetRearRight()->SendController( + MIDI_PAN_CONTROL, + MIDI_MAX_CONTROL_VALUE + ); + } + break; + }*/ + + // + // Set midi history to default control values + // + /*lastFrontLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastFrontRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearLeftMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastRearRightMIDIVolume = MIDI_MIN_CONTROL_VALUE; + lastMIDIPitchBend = 0; // Set by force update + lastMIDIFilterCutoff = MIDI_MAX_CONTROL_VALUE; // Set by patch + + // + //-------------------------------------------------------------------------- + // Calculate attack time, velocity, and execute model + //-------------------------------------------------------------------------- + // + MIDIValue midi_velocity = + CalculateSourceAttackVolumeScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (UseSourceAttackTime()) + { + MIDINRPNValue midi_attack_time = + CalculateSourceAttackTime() * + (Scalar)AWE_VOL_ATTACK_TIME_RANGE + 0.5f; + + for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendNRPN(AWE_VOL_ATTACK_TIME_NRPN, midi_attack_time); + } + } + }*/ + + ExecuteModel(True); + + // + //-------------------------------------------------------------------------- + // Start note + //-------------------------------------------------------------------------- + // + + //TODO: Start OpenAL source playing + + /*for (i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendNoteOn(GetCurrentNoteValue(), midi_velocity); + } + }*/ + patch_resource->PlayNote(channelSet); + +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::StopImplementation() +{ + Check(this); + + // + //------------------------------------------------------------ + // Stop note + //------------------------------------------------------------ + // + + //TODO: Stop OpenAL source playing + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + patch_resource->StopNote(channelSet); + + /*AudioChannel *channel; + + for (int i = 0; i < AudioChannelSetSize; i++) + { + if ((channel = channelSet.GetNth(i)) != NULL) + { + Check(channel); + channel->SendNoteOff(GetCurrentNoteValue(), MIDI_MIN_CONTROL_VALUE); + } + }*/ +} + +// +//############################################################################# +//############################################################################# +// +void + Static3DPatchSource::ExecuteModel(Logical force_update) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get audio resource + //-------------------------------------------------------------------------- + // + PatchResource *patch_resource; + + patch_resource = Cast_Object(PatchResource*, GetAudioResource()); + Check(patch_resource); + + Scalar volume_scale = CalculateSourceVolumeScale(); + L4AudioLocation *audio_location = Cast_Object(L4AudioLocation*, GetAudioLocation()); + Check(application); + L4AudioRenderer *audio_renderer = + Cast_Object(L4AudioRenderer*, application->GetAudioRenderer()); + Check(audio_renderer); + AudioHead *audio_head = audio_renderer->GetAudioHead(); + Check(audio_head); + + Scalar pitch_offset; + + pitch_offset = CalculateSourcePitchOffset(); + double relativePitch = pow(2.0,pitch_offset/1200.0); + Clamp(relativePitch,0.5,2.0); + + Vector3D relative_position; + Vector3D relative_velocity; + + if (useInternalSpatialization) + { + relative_position = position; + } else + { + relative_position = audio_location->GetVectorToSource(); + } + + //Static models have their position freely available as relative positions and stand still + for (int i=0; i < channelSet.count; i++) + { + alSourcef(channelSet.sources[i], AL_GAIN, volume_scale); + alSource3f(channelSet.sources[i],AL_POSITION,relative_position.x,relative_position.y,relative_position.z); + alSourcef(channelSet.sources[i],AL_MAX_DISTANCE,audio_location->getMaxDistance(audio_head)); + } + + // + //-------------------------------------------------------------------------- + // Render spatial model + //-------------------------------------------------------------------------- + // + /*AudioChannel *front_left_channel = channelSet.GetFrontLeft(); + AudioChannel *front_right_channel = channelSet.GetFrontRight(); + AudioChannel *rear_left_channel = channelSet.GetRearLeft(); + AudioChannel *rear_right_channel = channelSet.GetRearRight();*/ + + //TODO: Update spatial stuff? + + // + // Apply volume scale offset + // + //Scalar volume_scale = CalculateSourceVolumeScale(); + + // + // Apply pitch offset and calculate MIDI pitch bend + // + /*Scalar pitch_offset; + MIDIPitchBend midi_pitch_bend; + + pitch_offset = CalculateSourcePitchOffset(); + midi_pitch_bend = pitch_offset * MIDI_PITCH_PER_CENTS + 0.5f; + Clamp(midi_pitch_bend, -MIDI_PITCH_BEND_MAX, MIDI_PITCH_BEND_MAX); + + // + // Apply high frequency scale and calculate NRPN filter cutoff + // + Scalar filter_scale; + MIDINRPNValue max_midi_filter_cutoff; + MIDINRPNValue midi_filter_cutoff; + + filter_scale = CalculateSourceBrightnessScale(); + max_midi_filter_cutoff = patch_resource->GetMaxMIDIFilterCutoff(); + midi_filter_cutoff = filter_scale * (Scalar)max_midi_filter_cutoff + 0.5f; + + // + //-------------------------------------------------------------------------- + // Send pitch bend + //-------------------------------------------------------------------------- + // + const MIDIPitchBend pitch_resolution = 2; + MIDIPitchBend pitch_difference = midi_pitch_bend - lastMIDIPitchBend; + + if (Abs(pitch_difference) >= pitch_resolution || force_update) + { + lastMIDIPitchBend = midi_pitch_bend; + + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + Check(front_left_channel); + front_left_channel->SendPitchBend(midi_pitch_bend); + break; + + case L4AudioSpatialization::Quadrant2: + Check(front_left_channel); + front_left_channel->SendPitchBend(midi_pitch_bend); + Check(rear_left_channel); + rear_left_channel->SendPitchBend(midi_pitch_bend); + break; + + case L4AudioSpatialization::Quadrant3: + Check(rear_left_channel); + rear_left_channel->SendPitchBend(midi_pitch_bend); + break; + + case L4AudioSpatialization::Quadrant4: + Check(front_right_channel); + front_right_channel->SendPitchBend(midi_pitch_bend); + Check(rear_right_channel); + rear_right_channel->SendPitchBend(midi_pitch_bend); + break; + } + } + + // + //-------------------------------------------------------------------------- + // Send NRPN filter cutoff + //-------------------------------------------------------------------------- + // + if (UseSourceBrightnessScale()) + { + const MIDIValue filter_resolution = 2; + MIDINRPNValue filter_difference; + + filter_difference = midi_filter_cutoff - lastMIDIFilterCutoff; + + if (Abs(filter_difference) >= filter_resolution) + { + lastMIDIFilterCutoff = midi_filter_cutoff; + + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + Check(front_left_channel); + front_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + + case L4AudioSpatialization::Quadrant2: + Check(front_left_channel); + front_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + Check(rear_left_channel); + rear_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + + case L4AudioSpatialization::Quadrant3: + Check(rear_left_channel); + rear_left_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + + case L4AudioSpatialization::Quadrant4: + Check(front_right_channel); + front_right_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + Check(rear_right_channel); + rear_right_channel->SendNRPN( + AWE_FILTER_CUTOFF_NRPN, + midi_filter_cutoff + ); + break; + } + } + } + + // + //-------------------------------------------------------------------------- + // Send MIDI volume + //-------------------------------------------------------------------------- + // + switch (GetQuadrant()) + { + case L4AudioSpatialization::Quadrant1: + { + MIDIValue front_left_midi_volume = + volume_scale * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (front_left_midi_volume != lastFrontLeftMIDIVolume) + { + lastFrontLeftMIDIVolume = front_left_midi_volume; + Check(front_left_channel); + front_left_channel->SendController( + MIDI_VOLUME_CONTROL, + front_left_midi_volume + ); + } + } + break; + + case L4AudioSpatialization::Quadrant2: + { + MIDIValue front_left_midi_volume = + volume_scale * GetFrontLeftScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + MIDIValue rear_left_midi_volume = + volume_scale * GetRearLeftScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (front_left_midi_volume != lastFrontLeftMIDIVolume) + { + lastFrontLeftMIDIVolume = front_left_midi_volume; + Check(front_left_channel); + front_left_channel->SendController( + MIDI_VOLUME_CONTROL, + front_left_midi_volume + ); + } + if (rear_left_midi_volume != lastRearLeftMIDIVolume) + { + lastRearLeftMIDIVolume = rear_left_midi_volume; + Check(rear_left_channel); + rear_left_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_left_midi_volume + ); + } + } + break; + + case L4AudioSpatialization::Quadrant3: + { + MIDIValue rear_left_midi_volume = + volume_scale * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (rear_left_midi_volume != lastRearLeftMIDIVolume) + { + lastRearLeftMIDIVolume = rear_left_midi_volume; + Check(rear_left_channel); + rear_left_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_left_midi_volume + ); + } + } + break; + + case L4AudioSpatialization::Quadrant4: + { + MIDIValue front_right_midi_volume = + volume_scale * GetFrontRightScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + MIDIValue rear_right_midi_volume = + volume_scale * GetRearRightScale() * + (Scalar)MIDI_MAX_CONTROL_VALUE + 0.5f; + + if (front_right_midi_volume != lastFrontRightMIDIVolume) + { + lastFrontRightMIDIVolume = front_right_midi_volume; + Check(front_right_channel); + front_right_channel->SendController( + MIDI_VOLUME_CONTROL, + front_right_midi_volume + ); + } + if (rear_right_midi_volume != lastRearRightMIDIVolume) + { + lastRearRightMIDIVolume = rear_right_midi_volume; + Check(rear_right_channel); + rear_right_channel->SendController( + MIDI_VOLUME_CONTROL, + rear_right_midi_volume + ); + } + } + break; + }*/ +} diff --git a/MUNGA_L4/L4AUDIO.h b/MUNGA_L4/L4AUDIO.h new file mode 100644 index 0000000..b0eaa1e --- /dev/null +++ b/MUNGA_L4/L4AUDIO.h @@ -0,0 +1,801 @@ +#pragma once + +#include "l4audhdw.h" +#include "..\munga\audio.h" +#include "..\munga\audloc.h" +#include "..\munga\audsrc.h" + +//########################################################################## +//####################### L4AudioSpatialization ###################### +//########################################################################## + +class L4AudioSpatialization SIGNATURED +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public types +// +public: + enum Quadrant + { + Quadrant1, + Quadrant2, + Quadrant3, + Quadrant4 + }; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Contstruction, Destruction, & Testing +// +public: +L4AudioSpatialization(); + ~L4AudioSpatialization(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Spatialization calculations & results +// +public: + void + CalculateSpatialization(Radian azimuth_of_source); + + Radian + azimuthOfSource; + + Scalar + frontLeftScale, + frontRightScale, + rearLeftScale, + rearRightScale; + + Scalar + frontLeftDelay, + frontRightDelay, + rearLeftDelay, + rearRightDelay; + + Quadrant + quadrant; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~ L4AudioSpatialization inlines ~~~~~~~~~~~~~~~~~~~~ + +inline MemoryStream& + MemoryStream_Read( + MemoryStream* stream, + L4AudioSpatialization::Quadrant *ptr + ) +{ + return stream->ReadBytes(ptr, sizeof(*ptr)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream* stream, + const L4AudioSpatialization::Quadrant *ptr + ) +{ + return stream->WriteBytes(ptr, sizeof(*ptr)); +} + +//########################################################################## +//######################### L4AudioLocation ########################## +//########################################################################## + +class L4AudioLocation: + public AudioLocation +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + L4AudioLocation( + PlugStream *stream, + Entity *entity + ); + void + L4AudioLocationX(); + ~L4AudioLocation(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Spatialization Accessors +// +public: + void + GetSpatialization(L4AudioSpatialization *the_spatialization) + {*the_spatialization = spatialization;} + + L4AudioSpatialization::Quadrant + GetQuadrant() + {return spatialization.quadrant;} + + Scalar + GetFrontLeftScale() + {return spatialization.frontLeftScale;} + Scalar + GetFrontRightScale() + {return spatialization.frontRightScale;} + Scalar + GetRearLeftScale() + {return spatialization.rearLeftScale;} + Scalar + GetRearRightScale() + {return spatialization.rearRightScale;} + + Scalar + GetFrontLeftITDPitchOffset() + {return frontLeftITDPitchOffset;} + Scalar + GetFrontRightITDPitchOffset() + {return frontRightITDPitchOffset;} + Scalar + GetRearLeftITDPitchOffset() + {return rearLeftITDPitchOffset;} + Scalar + GetRearRightITDPitchOffset() + {return rearRightITDPitchOffset;} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Spatialization Implementation +// +public: + void + UpdateSpatialModelImplementation(AudioHead *audio_head); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + L4AudioSpatialization + spatialization; + + Time + lastITDFrameTime; + + Scalar + currentFrontLeftDelay, + currentFrontRightDelay, + currentRearLeftDelay, + currentRearRightDelay; + + AudioPitchCents + frontLeftITDPitchOffset, + frontRightITDPitchOffset, + rearLeftITDPitchOffset, + rearRightITDPitchOffset; +}; + +//########################################################################## +//######################### AudioChannelSet ########################## +//########################################################################## + +/*#define AUDIO_CHANNEL_SET_LENGTH (4) + +typedef int AudioChannelSetIndex; +const AudioChannelSetIndex AudioChannelSetSize = AUDIO_CHANNEL_SET_LENGTH; + +class AudioChannelSet SIGNATURED +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, & Testing +// +public: + AudioChannelSet(); + ~AudioChannelSet() {} + + Logical + TestInstance() const; + +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + RegisteredClass::ClassID class_ID, + ObjectID object_ID + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Channel accesors +// +public: + void + SetFrontLeft(AudioChannel *audio_channel); + void + SetFrontRight(AudioChannel *audio_channel); + void + SetRearLeft(AudioChannel *audio_channel); + void + SetRearRight(AudioChannel *audio_channel); + + AudioChannel* + GetFrontLeft(); + AudioChannel* + GetFrontRight(); + AudioChannel* + GetRearLeft(); + AudioChannel* + GetRearRight(); + + void + SetNth( + AudioChannelSetIndex index, + AudioChannel *audio_channel + ); + AudioChannel* + GetNth(AudioChannelSetIndex index); + + void + ReleaseAll(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Enable accesors +// +public: + void + EnableFrontLeft(Logical flag); + void + EnableFrontRight(Logical flag); + void + EnableRearLeft(Logical flag); + void + EnableRearRight(Logical flag); + + Logical + IsFrontLeftEnabled(); + Logical + IsFrontRightEnabled(); + Logical + IsRearLeftEnabled(); + Logical + IsRearRightEnabled(); + + void + EnableNth( + AudioChannelSetIndex index, + Logical flag + ); + void + EnableAll(); + Logical + IsNthEnabled(AudioChannelSetIndex index); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Null channel set +// +public: + static AudioChannelSet + Null; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + AudioChannel + *channels[AUDIO_CHANNEL_SET_LENGTH]; + Logical + enables[AUDIO_CHANNEL_SET_LENGTH]; +};*/ + +//########################################################################## +//########################## L4AudioSource ########################### +//########################################################################## + +class L4AudioSource: + public AudioSource +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destruction, Testing +// +public: + ~L4AudioSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AudioChannelSet methods +// +public: +/* void + SetAudioChannelSet(const AudioChannelSet &audio_channel_set); + const AudioChannelSet* + GetAudioChannelSet(); + + void + ReleaseChannels();*/ + + void SetAudioChannelSet(const SourceSet &source_set); + SourceSet *GetAudioChannelSet(); + void ReleaseChannels(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected Constuction +// +protected: + L4AudioSource( + PlugStream *stream, + Entity *entity + ); + void + L4AudioSourceX(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected Implementations +// +protected: + void + StopMessageImplementation(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected Data +// +protected: + /*AudioChannelSet + channelSet;*/ + + SourceSet channelSet; +}; + +//########################################################################## +//######################## DirectPatchSource ######################### +//########################################################################## + +enum DirectPatchPosition +{ + FrontDirectPatchPosition = 0, + RearDirectPatchPosition = 1, + FrontLeftDirectPatchPosition = 2, + FrontRightDirectPatchPosition = 3, + RearLeftDirectPatchPosition = 4, + RearRightDirectPatchPosition = 5 +}; + +class DirectPatchSource: + public L4AudioSource +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + DirectPatchSource( + PlugStream *stream, + Entity *entity + ); + ~DirectPatchSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// State implementations +// +public: + void + StartImplementation(); + void + StopImplementation(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected Implementations +// +protected: + void + StartMessageImplementation(); + + void + ExecuteModel(Logical force_update); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + DirectPatchPosition + audioPosition; +/* AudioChannel + *channel;*/ + + MIDIValue + lastMIDIVolume; + MIDIPitchBend + lastMIDIPitchBend; + MIDINRPNValue + lastMIDIFilterCutoff; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ DirectPatchSource inlines ~~~~~~~~~~~~~~~~~~~~ + +inline MemoryStream& + MemoryStream_Read( + MemoryStream *stream, + DirectPatchPosition *ptr + ) +{ + return stream->ReadBytes(ptr, sizeof(*ptr)); +} + +inline MemoryStream& + MemoryStream_Write( + MemoryStream *stream, + const DirectPatchPosition *ptr + ) +{ + return stream->WriteBytes(ptr, sizeof(*ptr)); +} + +//########################################################################## +//###################### Dynamic3DPatchSource ######################## +//########################################################################## + +class Dynamic3DPatchSource: + public L4AudioSource +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + Dynamic3DPatchSource( + PlugStream *stream, + Entity *entity + ); + ~Dynamic3DPatchSource(); + + Logical + TestInstance() const; + + virtual Logical IsAudioSourceClipped(AudioHead *audio_head); + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Mix levels +// +public: + AudioControlValue + CalculateSourceVolumeScale(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// State implementations +// +public: + void + StartImplementation(); + void + StopImplementation(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected implementations +// +protected: + void + StartMessageImplementation(); + + void + ExecuteModel(Logical force_update); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + MIDIValue + lastFrontLeftMIDIVolume, + lastFrontRightMIDIVolume, + lastRearLeftMIDIVolume, + lastRearRightMIDIVolume; + + MIDIPitchBend + lastFrontLeftMIDIPitchBend, + lastFrontRightMIDIPitchBend, + lastRearLeftMIDIPitchBend, + lastRearRightMIDIPitchBend; + + MIDINRPNValue + lastMIDIFilterCutoff; +}; + +//########################################################################## +//####################### Static3DPatchSource ######################## +//########################################################################## + +class Static3DPatchSource: + public L4AudioSource +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + Static3DPatchSource( + PlugStream *stream, + Entity *entity + ); + ~Static3DPatchSource(); + + Logical + TestInstance() const; + + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + virtual Logical IsAudioSourceClipped(AudioHead *audio_head); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// SetPosition +// +public: + void + SetPosition(const Vector3D &vector3D); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// State implementations +// +public: + void + StartImplementation(); + void + StopImplementation(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected implementations +// +protected: + void + StartMessageImplementation(); + + void + ExecuteModel(Logical force_update); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Methods +// +private: + L4AudioSpatialization::Quadrant + GetQuadrant(); + Radian + GetAzimuthOfSource(); + + Scalar + GetFrontLeftScale(); + Scalar + GetFrontRightScale(); + Scalar + GetRearLeftScale(); + Scalar + GetRearRightScale(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + Vector3D + position; + + Logical + useInternalSpatialization; + L4AudioSpatialization + internalSpatialization; + + MIDIValue + lastFrontLeftMIDIVolume, + lastFrontRightMIDIVolume, + lastRearLeftMIDIVolume, + lastRearRightMIDIVolume; + + MIDIPitchBend + lastMIDIPitchBend; + + MIDINRPNValue + lastMIDIFilterCutoff; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~ Static3DPatchSource inlines ~~~~~~~~~~~~~~~~~~~~~ + +inline L4AudioSpatialization::Quadrant + Static3DPatchSource::GetQuadrant() +{ + return internalSpatialization.quadrant; +} + +inline Radian + Static3DPatchSource::GetAzimuthOfSource() +{ + return internalSpatialization.azimuthOfSource; +} + +inline Scalar + Static3DPatchSource::GetFrontLeftScale() +{ + return internalSpatialization.frontLeftScale; +} + +inline Scalar + Static3DPatchSource::GetFrontRightScale() +{ + return internalSpatialization.frontRightScale; +} + +inline Scalar + Static3DPatchSource::GetRearLeftScale() +{ + return internalSpatialization.rearLeftScale; +} + +inline Scalar + Static3DPatchSource::GetRearRightScale() +{ + return internalSpatialization.rearRightScale; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~ AudioChannelSet inlines ~~~~~~~~~~~~~~~~~~~~~~ + +/*inline void + AudioChannelSet::SetFrontLeft(AudioChannel *audio_channel) +{ + Check(this); + channels[0] = audio_channel; +} + +inline void + AudioChannelSet::SetFrontRight(AudioChannel *audio_channel) +{ + Check(this); + channels[1] = audio_channel; +} + +inline void + AudioChannelSet::SetRearLeft(AudioChannel *audio_channel) +{ + Check(this); + channels[2] = audio_channel; +} + +inline void + AudioChannelSet::SetRearRight(AudioChannel *audio_channel) +{ + Check(this); + channels[3] = audio_channel; +} + +inline AudioChannel* + AudioChannelSet::GetFrontLeft() +{ + Check(this); + return channels[0]; +} + +inline AudioChannel* + AudioChannelSet::GetFrontRight() +{ + Check(this); + return channels[1]; +} + +inline AudioChannel* + AudioChannelSet::GetRearLeft() +{ + Check(this); + return channels[2]; +} + +inline AudioChannel* + AudioChannelSet::GetRearRight() +{ + Check(this); + return channels[3]; +} + +inline void + AudioChannelSet::SetNth( + AudioChannelSetIndex index, + AudioChannel *audio_channel + ) +{ + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + channels[index] = audio_channel; +} + +inline AudioChannel* + AudioChannelSet::GetNth(AudioChannelSetIndex index) +{ + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + return channels[index]; +} + +inline void + AudioChannelSet::EnableFrontLeft(Logical flag) +{ + Check(this); + enables[0] = flag; +} + +inline void + AudioChannelSet::EnableFrontRight(Logical flag) +{ + Check(this); + enables[1] = flag; +} + +inline void + AudioChannelSet::EnableRearLeft(Logical flag) +{ + Check(this); + enables[2] = flag; +} + +inline void + AudioChannelSet::EnableRearRight(Logical flag) +{ + Check(this); + enables[3] = flag; +} + +inline Logical + AudioChannelSet::IsFrontLeftEnabled() +{ + Check(this); + return enables[0]; +} + +inline Logical + AudioChannelSet::IsFrontRightEnabled() +{ + Check(this); + return enables[1]; +} + +inline Logical + AudioChannelSet::IsRearLeftEnabled() +{ + Check(this); + return enables[2]; +} + +inline Logical + AudioChannelSet::IsRearRightEnabled() +{ + Check(this); + return enables[3]; +} + +inline void + AudioChannelSet::EnableNth( + AudioChannelSetIndex index, + Logical flag + ) +{ + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + enables[index] = flag; +} + +inline Logical + AudioChannelSet::IsNthEnabled(AudioChannelSetIndex index) +{ + Check(this); + Verify(index >=0 && index < AUDIO_CHANNEL_SET_LENGTH); + return enables[index]; +}*/ diff --git a/MUNGA_L4/L4AUDLVL.cpp b/MUNGA_L4/L4AUDLVL.cpp new file mode 100644 index 0000000..35baa6b --- /dev/null +++ b/MUNGA_L4/L4AUDLVL.cpp @@ -0,0 +1,312 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4audlvl.h" +#include "l4audres.h" +#include "..\munga\audrend.h" +#include "..\munga\objstrm.h" +#include "..\munga\namelist.h" +#include "openal/al.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if DEBUG_LEVEL>0 + TableOf + PatchLevelOfDetail::patchTableSocket(NULL, True); +#endif + +// +//############################################################################# +//############################################################################# +// +PatchLevelOfDetail::PatchLevelOfDetail(PlugStream *stream): + AudioLevelOfDetail(stream) +{ + MemoryStream_Read(stream, &bankID); + MemoryStream_Read(stream, &patchID); + MemoryStream_Read(stream, &maxMIDIFilterCutoff); + + Warn(GetVoiceCount() > 4); // HACK - AWE appears to only play 1st 4 voices + + #ifdef LAB_ONLY + setupCount = 0; + #endif + + // + // Keep table of created patchs to verify that duplicates + // are not created, could move this to tool time + // + #if DEBUG_LEVEL>0 + unsigned int index_value = (bankID * 1000) + patchID; + if (patchTableSocket.Find(index_value) != NULL) + { + Dump((int)bankID); + Dump((int)patchID); + } + Verify(patchTableSocket.Find(index_value) == NULL); + patchTableSocket.AddValue(this, index_value); + #endif +} + +// +//############################################################################# +//############################################################################# +// +void + PatchLevelOfDetail::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioLevelOfDetail::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, SBKBankID, bank_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, SBKPatchID, patch_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, MIDINRPNValue, max_filter_cutoff); +} + +// +//############################################################################# +//############################################################################# +// +PatchLevelOfDetail::~PatchLevelOfDetail() +{ + #ifdef LAB_ONLY + cout << "PatchLevelOfDetail::~PatchLevelOfDetail\t"; + cout << (int)bankID << ":" << (int)patchID << "\t"; + cout << "setupCount=\t" << setupCount << "\n"; + #endif + + /*if (m_numSources > 0 && m_sources != NULL) + { + for (int i=0; i < m_numSources; i++) + { + //Detach buffer + alSourcei(m_sources[i],AL_BUFFER,0); + //Stop source + ALenum state; + alGetSourcei(m_sources[i],AL_SOURCE_STATE,&state); + if (state == AL_PLAYING) + { + alSourceStop(m_sources[i]); + } + } + + //Destroy all sources + alDeleteSources(m_numSources,m_sources); + }*/ +} + +// +//############################################################################# +//############################################################################# +// +Logical + PatchLevelOfDetail::TestInstance() const +{ + AudioLevelOfDetail::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + PatchLevelOfDetail::SetupPatch(SourceSet sourceSet) +{ +// Check(this); +//// Check(channel); +// +// #ifdef LAB_ONLY +// setupCount++; +// #endif + SAMPLEINFO info; + + //Attach buffers + for (int i=0; i < sourceSet.count; i++) + { + info = PRESET_getSampleInfo(bankID,patchID,i); + if (info.bufferIndex >= 0) + { + ALenum sourceState; + alGetSourcei(sourceSet.sources[i], AL_SOURCE_STATE, &sourceState); + + if (sourceState == AL_INITIAL) + { + alSourcei(sourceSet.sources[i],AL_BUFFER,AL_getBuffer(info.bufferIndex)); + alSourcei(sourceSet.sources[i],AL_SOURCE_RELATIVE,AL_TRUE); + + AudioRenderer *render = application->GetAudioRenderer(); + AudioHead *head = render->GetAudioHead(); + + alSource3f(sourceSet.sources[i],AL_POSITION,0,0,0); + alSource3f(sourceSet.sources[i],AL_VELOCITY,0,0,0); + + if (info.loop == ForceStatic) + { + alSourcei(sourceSet.sources[i],AL_LOOPING,0); + } else + { + alSourcei(sourceSet.sources[i],AL_LOOPING,1); + } + } + } + } + + // + // Set the channel to the bank and program, reset patch controls + // +/* channel->SelectBank(bankID); + channel->SendProgramChange(patchID); + channel->SendController(MIDI_CONTROL_RESET, MIDI_MAX_CONTROL_VALUE);*/ + + //TODO: Sync up OpenAL source info appropriately + + /*#if 0 + Tell((int)bankID << ":" << (int)patchID << "\n"); + #endif*/ +} + +void PatchLevelOfDetail::PlayNote(SourceSet sourceSet) +{ + if (sourceSet.count > 0 && sourceSet.sources != NULL) + { + alGetError(); + //DEBUG_STREAM << "Playing bank " << (int)bankID << ", patch " << (int)patchID << std::endl; + + for (int i = 0; i < sourceSet.count; i++) + { + ALenum state; + alGetSourcei(sourceSet.sources[i], AL_SOURCE_STATE, &state); + + if (state != AL_PLAYING) + { + alSourcePlay(sourceSet.sources[i]); + } + + ALenum error = alGetError(); + if (error != AL_NO_ERROR) + { + DEBUG_STREAM << "Playing hit an error: " << error << std::endl; + return; + } + } + } +} + +void PatchLevelOfDetail::StopNote(SourceSet sourceSet) +{ + if (sourceSet.count >0 && sourceSet.sources != NULL) + { + alSourceStopv(sourceSet.count, sourceSet.sources); + alSourceRewindv(sourceSet.count, sourceSet.sources); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +//############################################################################# +// +PatchResource::PatchResource(PlugStream *stream): + AudioResource(stream) +{ +} + +// +//############################################################################# +//############################################################################# +// +void + PatchResource::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioResource::BuildFromPage(stream, name_list, class_ID, object_ID); +} + +// +//############################################################################# +//############################################################################# +// +PatchResource::~PatchResource() +{ +} + +// +//############################################################################# +//############################################################################# +// +Logical + PatchResource::TestInstance() const +{ + AudioResource::TestInstance(); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + PatchResource::SetupPatch(SourceSet sourceSet) +{ + Check(this); +// Check(channel); + + PatchLevelOfDetail *patch_level_of_detail = + Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail()); + + Check(patch_level_of_detail); + patch_level_of_detail->SetupPatch(sourceSet); +} + +void PatchResource::PlayNote(SourceSet sourceSet) +{ + Check(this); +// Check(channel); + + PatchLevelOfDetail *patch_level_of_detail = + Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail()); + + Check(patch_level_of_detail); + patch_level_of_detail->PlayNote(sourceSet); +} + +void PatchResource::StopNote(SourceSet sourceSet) +{ + Check(this); +// Check(channel); + + PatchLevelOfDetail *patch_level_of_detail = + Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail()); + + Check(patch_level_of_detail); + patch_level_of_detail->StopNote(sourceSet); +} + +// +//############################################################################# +//############################################################################# +// +MIDINRPNValue + PatchResource::GetMaxMIDIFilterCutoff() +{ + Check(this); + + PatchLevelOfDetail *patch_level_of_detail = + Cast_Object(PatchLevelOfDetail*, GetAudioLevelOfDetail()); + + Check(patch_level_of_detail); + return patch_level_of_detail->GetMaxMIDIFilterCutoff(); +} diff --git a/MUNGA_L4/L4AUDLVL.h b/MUNGA_L4/L4AUDLVL.h new file mode 100644 index 0000000..73dca59 --- /dev/null +++ b/MUNGA_L4/L4AUDLVL.h @@ -0,0 +1,169 @@ +#pragma once + +#include "..\munga\audlvl.h" +#include "l4audhdw.h" +#include "openal/al.h" + +enum SampleChannel +{ + CHANNEL_LEFT, + CHANNEL_RIGHT, + CHANNEL_CENTER +}; + +enum SampleLoop +{ + LoopAtWill, //Will play once or loop as desired + ForceStatic, //Plays only once even if looped + LoopAlways, //Ramp up and then down + SampleLoopMax +}; + +struct SAMPLEINFO +{ + int bufferIndex; + bool implemented; + const char *file; + SampleChannel chan; + SampleLoop loop; +}; + +struct PRESETINFO +{ + int sampleNum; + SAMPLEINFO samples[5]; + bool is3d; +}; + +extern PRESETINFO allPresets[2][100]; + +bool PRESET_isImplemented(int bank, int preset); +int PRESET_getNumSamples(int bank, int preset); +SAMPLEINFO PRESET_getSampleInfo(int bank, int preset, int sampleInd); +void PRESET_setBufferIndex(int bank, int preset, int sampleInd, int index); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchLevelOfDetail ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +typedef MIDIValue SBKPatchID; +typedef MIDIValue SBKBankID; + +class PatchLevelOfDetail: + public AudioLevelOfDetail +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + PatchLevelOfDetail(PlugStream *stream); + ~PatchLevelOfDetail(); + + void PlayNote(SourceSet sourceSet); + void StopNote(SourceSet sourceSet); + + Logical + TestInstance() const; + + virtual AudioVoiceCount + GetVoiceCount() + {return PRESET_getNumSamples(bankID,patchID);} + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + void + SetupPatch(SourceSet sourceSet); + + MIDINRPNValue + GetMaxMIDIFilterCutoff() + {return maxMIDIFilterCutoff;} + +private: + // + //----------------------------------------------------------------------- + // Private data + //----------------------------------------------------------------------- + // + SBKBankID + bankID; + SBKPatchID + patchID; + MIDINRPNValue + maxMIDIFilterCutoff; + + #ifdef LAB_ONLY + int + setupCount; + #endif + + // + // Keep table of created patchs to verify that duplicates + // are not created + // + #if DEBUG_LEVEL>0 + static TableOf + patchTableSocket; + #endif +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ PatchResource ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class PatchResource: + public AudioResource +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + PatchResource(PlugStream *stream); + ~PatchResource(); + + void PlayNote(SourceSet sourceSet); + void StopNote(SourceSet sourceSet); + + Logical + TestInstance() const; + + // + //----------------------------------------------------------------------- + // BuildFromPage + //----------------------------------------------------------------------- + // + static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ); + + // + //----------------------------------------------------------------------- + // Accessors + //----------------------------------------------------------------------- + // + void + SetupPatch(SourceSet sourceSet); + + MIDINRPNValue + GetMaxMIDIFilterCutoff(); +}; + diff --git a/MUNGA_L4/L4AUDRES.cpp b/MUNGA_L4/L4AUDRES.cpp new file mode 100644 index 0000000..4244eb6 --- /dev/null +++ b/MUNGA_L4/L4AUDRES.cpp @@ -0,0 +1,1115 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4audres.h" +#include "l4audhdw.h" +#include "l4audio.h" +#include "l4audlvl.h" +#include "l4audwtr.h" +#include "..\munga\audcmp.h" +#include "..\munga\audseq.h" +#include "..\munga\audrend.h" +#include "..\munga\namelist.h" +#include "..\munga\app.h" +#include "..\munga\notation.h" +#include "openal\al.h" +#include "sndfile.h" + +ALuint *g_buffers; +int g_numBuffers; + +//############################################################################# +//####################### AudioObjectStream ############################# +//############################################################################# + +// +//############################################################################# +// AudioObjectStream +//############################################################################# +// +AudioObjectStream::AudioObjectStream( + ResourceDescription *resource_description, + Entity *the_entity +): + PlugStream(resource_description) +{ + entity = the_entity; +} + +// +//############################################################################# +// AudioObjectStream +//############################################################################# +// +AudioObjectStream::AudioObjectStream() +{ + entity = NULL; +} + +// +//############################################################################# +// ~AudioObjectStream +//############################################################################# +// +AudioObjectStream::~AudioObjectStream() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + AudioObjectStream::TestInstance() const +{ + PlugStream::TestInstance(); + if (entity != NULL) + { + Check(entity); + } + return True; +} + +// +//############################################################################# +// MakeObjectImplementation +//############################################################################# +// +RegisteredClass* + AudioObjectStream::MakeObjectImplementation(Enumeration class_ID) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + + // + //----------------------------------------------------------------------- + // HACK - Constructors should be referenced through registration, for + // now just use a switch statement + //----------------------------------------------------------------------- + // + RegisteredClass *object; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::PatchLevelOfDetailClassID: + object = new PatchLevelOfDetail(this); + break; + + case RegisteredClass::PatchResourceClassID: + object = new PatchResource(this); + break; + + case RegisteredClass::AudioResourceIndexClassID: + object = new AudioResourceIndex(this); + break; + + // + // Location and sources ... + // + case RegisteredClass::L4AudioLocationClassID: + object = new L4AudioLocation(this, entity); + break; + + case RegisteredClass::DirectPatchSourceClassID: + object = new DirectPatchSource(this, entity); + break; + + case RegisteredClass::Dynamic3DPatchSourceClassID: + object = new Dynamic3DPatchSource(this, entity); + break; + + case RegisteredClass::Static3DPatchSourceClassID: + object = new Static3DPatchSource(this, entity); + break; + + // + // Audio components ... + // + case RegisteredClass::AudioControlMixerClassID: + object = new AudioControlMixer(this, entity); + break; + + case RegisteredClass::AudioControlMultiplierClassID: + object = new AudioControlMultiplier(this, entity); + break; + + case RegisteredClass::AudioResourceSelectorClassID: + object = new AudioResourceSelector(this, entity); + break; + + case RegisteredClass::AudioControlSmootherClassID: + object = new AudioControlSmoother(this, entity); + break; + + case RegisteredClass::AudioSampleAndHoldClassID: + object = new AudioSampleAndHold(this, entity); + break; + + case RegisteredClass::AudioControlSendClassID: + object = new AudioControlSend(this, entity); + break; + + case RegisteredClass::AudioControlSequenceClassID: + object = new AudioControlSequence(this, entity); + break; + + case RegisteredClass::AudioControlSplitterClassID: + object = new AudioControlSplitter(this, entity); + break; + + case RegisteredClass::AudioLFOClassID: + object = new AudioLFO(this, entity); + break; + + // + // Audio watchers ... + // + case RegisteredClass::AudioMotionTriggerClassID: + object = new AudioMotionTrigger(this, entity); + break; + + case RegisteredClass::AudioMotionScaleClassID: + object = new AudioMotionScale(this, entity); + break; + + case RegisteredClass::AudioHingeScaleClassID: + object = new AudioHingeScale(this, entity); + break; + + case RegisteredClass::AudioScalarTriggerClassID: + object = new AudioScalarTrigger(this, entity); + break; + + case RegisteredClass::AudioScalarScaleClassID: + object = new AudioScalarScale(this, entity); + break; + + case RegisteredClass::AudioLogicalTriggerClassID: + object = new AudioLogicalTrigger(this, entity); + break; + + case RegisteredClass::AudioEnumerationTriggerClassID: + object = new AudioEnumerationTrigger(this, entity); + break; + + case RegisteredClass::AudioIntegerTriggerClassID: + object = new AudioIntegerTrigger(this, entity); + break; + + case RegisteredClass::AudioControlsButtonTriggerClassID: + object = new AudioControlsButtonTrigger(this, entity); + break; + + case RegisteredClass::AudioStateTriggerClassID: + object = new AudioStateTrigger(this, entity); + break; + + case RegisteredClass::AudioIdleWatcherClassID: + object = new AudioIdleWatcher(this, entity); + break; + + case RegisteredClass::AudioEnumerationDeltaTriggerClassID: + object = new AudioEnumerationDeltaTrigger(this, entity); + break; + + case RegisteredClass::AudioScalarDeltaTriggerClassID: + object = new AudioScalarDeltaTrigger(this, entity); + break; + + case RegisteredClass::L4AudioCollisionTriggerClassID: + object = new L4AudioCollisionTrigger(this, entity); + break; + + case RegisteredClass::AudioMessageWatcherClassID: + object = new AudioMessageWatcher(this, entity); + break; + + case RegisteredClass::AudioControlsButtonMessageWatcherClassID: + object = new AudioControlsButtonMessageWatcher(this, entity); + break; + + // + // Inherited behavior + // + default: + object = PlugStream::MakeObjectImplementation(class_ID); + break; + } + return object; +} + +// +//############################################################################# +// CreatedObjectImplementation +//############################################################################# +// +void + AudioObjectStream::CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ) +{ + Check(this); + Check(object); + Verify(object_ID != NullObjectID); + + // + // std::Decide which index to add object to + // + switch (object->GetClassID()) + { + case RegisteredClass::PatchLevelOfDetailClassID: + case RegisteredClass::PatchResourceClassID: + case RegisteredClass::AudioResourceIndexClassID: + AddGlobalPlug(Cast_Object(Plug*, object), object_ID); + break; + + default: + AddLocalPlug(Cast_Object(Plug*, object), object_ID); + break; + } +} + +// +//############################################################################# +// BuildFromPageImplementation +//############################################################################# +// +void + AudioObjectStream::BuildFromPageImplementation( + NameList *name_list, + Enumeration class_ID_enumeration, + ObjectID object_ID + ) +{ + Check(this); + Verify(class_ID_enumeration != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + + // + //----------------------------------------------------------------------- + // HACK - Page interpreters should be referenced through registration, + // for now just use a switch statement + //----------------------------------------------------------------------- + // + RegisteredClass::ClassID + class_ID = (RegisteredClass::ClassID)class_ID_enumeration; + + switch (class_ID) + { + // + // Static resources ... + // + case RegisteredClass::PatchLevelOfDetailClassID: + PatchLevelOfDetail::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::PatchResourceClassID: + PatchResource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioResourceIndexClassID: + AudioResourceIndex::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Location and sources ... + // + case RegisteredClass::L4AudioLocationClassID: + L4AudioLocation::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::DirectPatchSourceClassID: + DirectPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::Dynamic3DPatchSourceClassID: + Dynamic3DPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::Static3DPatchSourceClassID: + Static3DPatchSource::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Audio components ... + // + case RegisteredClass::AudioControlMixerClassID: + AudioControlMixer::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlMultiplierClassID: + AudioControlMultiplier::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioResourceSelectorClassID: + AudioResourceSelector::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSmootherClassID: + AudioControlSmoother::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioSampleAndHoldClassID: + AudioSampleAndHold::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSendClassID: + AudioControlSend::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSequenceClassID: + AudioControlSequence::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlSplitterClassID: + AudioControlSplitter::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioLFOClassID: + AudioLFO::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Audio watchers ... + // + case RegisteredClass::AudioMotionTriggerClassID: + AudioMotionTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioMotionScaleClassID: + AudioMotionScale::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioHingeScaleClassID: + AudioHingeScale::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioScalarTriggerClassID: + AudioScalarTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioScalarScaleClassID: + AudioScalarScale::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioLogicalTriggerClassID: + AudioLogicalTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioEnumerationTriggerClassID: + AudioEnumerationTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioIntegerTriggerClassID: + AudioIntegerTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlsButtonTriggerClassID: + AudioControlsButtonTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioStateTriggerClassID: + AudioStateTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioIdleWatcherClassID: + AudioIdleWatcher::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioEnumerationDeltaTriggerClassID: + AudioEnumerationDeltaTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioScalarDeltaTriggerClassID: + AudioScalarDeltaTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::L4AudioCollisionTriggerClassID: + L4AudioCollisionTrigger::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioMessageWatcherClassID: + AudioMessageWatcher::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + case RegisteredClass::AudioControlsButtonMessageWatcherClassID: + AudioControlsButtonMessageWatcher::BuildFromPage(this, name_list, class_ID, object_ID); + break; + + // + // Inherited behavior + // + default: + PlugStream::BuildFromPageImplementation(name_list, class_ID, object_ID); + break; + } +} + +// +//############################################################################# +// BuiltFromPageImplementation +//############################################################################# +// +void + AudioObjectStream::BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name + ) +{ + Check(this); + Verify(class_ID != RegisteredClass::NullClassID); + Verify(object_ID != NullObjectID); + Check(&object_name); + + // + // std::Decide which index to add object to + // + if (object_name.Length() == 0) + return; + + switch (class_ID) + { + case RegisteredClass::PatchLevelOfDetailClassID: + case RegisteredClass::PatchResourceClassID: + case RegisteredClass::AudioResourceIndexClassID: + AddGlobalObjectID(object_ID, object_name); + break; + + default: + AddLocalObjectID(object_ID, object_name); + break; + } +} + +//############################################################################# +//###################### L4AudioResourceManager ######################### +//############################################################################# + +// +//############################################################################# +// L4AudioResourceManager +//############################################################################# +// +L4AudioResourceManager::L4AudioResourceManager() +{ + g_buffers = NULL; + g_numBuffers = 0; +} + +// +//############################################################################# +// ~L4AudioResourceManager +//############################################################################# +// +L4AudioResourceManager::~L4AudioResourceManager() +{ +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + L4AudioResourceManager::TestInstance() const +{ + Node::TestInstance(); + return True; +} + +// +//############################################################################# +// PreloadResources +//############################################################################# +// +void + L4AudioResourceManager::PreloadResources( + NotationFile *notation_file + ) +{ + Check(this); + Check(notation_file); + //Check(audio_hardware); + + //Determine how many loadable samples exist + g_numBuffers=0; + + for(int i=1; i <= 2; i++) + { + for (int j=0; j < 100; j++) + { + if (PRESET_isImplemented(i,j)) + { + g_numBuffers += PRESET_getNumSamples(i,j); + } + } + } + + //Generate the buffers + if (g_numBuffers > 0) + { + //Generate buffers + alGetError(); + g_buffers = new ALuint[g_numBuffers]; + alGenBuffers(g_numBuffers,g_buffers); + ALenum error; + if ((error = alGetError()) != AL_NO_ERROR) + { + DEBUG_STREAM << "OpenAL has encountered an error while initializing the buffers." << std::endl; + delete [] g_buffers; + g_buffers = NULL; + g_numBuffers = 0; + } + } + + int bufferInd = 0; + //Load buffers + for(int i=1; i<=2 && bufferInd < g_numBuffers; i++) + { + for(int j=0; j<100 && bufferInd < g_numBuffers; j++) + { + if (PRESET_isImplemented(i,j)) + { + for (int k=0; k < PRESET_getNumSamples(i,j) && bufferInd < g_numBuffers; k++) + { + SAMPLEINFO info = PRESET_getSampleInfo(i,j,k); + + //Load WAV to buffer + char *data; + int size; + + //Open WAV + char fullname[50]; + strcpy_s(fullname,50,"AUDIO\\"); + strcat_s(fullname,50,info.file); + SF_INFO *sfInfo = new SF_INFO[2]; + //SF_INFO is working different than expected! + sfInfo->format = 0; + SNDFILE *file = sf_open(fullname,SFM_READ,sfInfo); + + if (file == NULL) + { + DEBUG_STREAM << "Failed to open." << std::endl; + } + + unsigned long formatBits = 0; + unsigned long sampleRate = sfInfo->samplerate; + size = sfInfo->frames; + + bool isMono = (sfInfo->channels == 1); + + if (sfInfo->format & SF_FORMAT_PCM_S8) + { + formatBits = 8; + } else if (sfInfo->format & SF_FORMAT_PCM_16) + { + formatBits = 16; + } else + { + DEBUG_STREAM << "BAD FORMAT" << std::endl; + } + + ALenum format; + if (formatBits == 8) + { + if (isMono) + { + format = AL_FORMAT_MONO8; + } else + { + size *= 2; + format = AL_FORMAT_STEREO8; + } + } else if (formatBits == 16) + { + size *= 2; + if (isMono) + { + format = AL_FORMAT_MONO16; + } else + { + size *= 2; + format = AL_FORMAT_STEREO16; + } + } + + ALsizei alSampleRate = sampleRate; + + //Load size & data + delete [] sfInfo; + data = new char[size]; + sf_read_raw(file,data,size); + sf_close(file); + + //Feed the buffer + alBufferData(g_buffers[bufferInd],format,data,size,alSampleRate); + PRESET_setBufferIndex(i,j,k,bufferInd); + bufferInd++; + + delete [] data; + } + } + } + } + + // + //---------------------------------------------------------------------- + // Load the sound banks + //---------------------------------------------------------------------- + // + /*NameList *name_list; + NameList::Entry *entry; + + Verify(notation_file->EntryCount("AudioResources") >= 2); + + name_list = notation_file->MakeEntryList("AudioResources"); + Register_Object(name_list); + entry = name_list->GetFirstEntry(); + Check(entry); + while (entry != NULL) + { + Check(entry); + if (entry->IsName("front_audio_resource")) + { + Check_Pointer(entry->GetChar()); + Check(audio_hardware->GetFrontCard()); + audio_hardware->GetFrontCard()->LoadSBK(entry->GetChar()); + } + else + { + Verify(entry->IsName("rear_audio_resource")); + Check_Pointer(entry->GetChar()); + Check(audio_hardware->GetRearCard()); + audio_hardware->GetRearCard()->LoadSBK(entry->GetChar()); + } + entry = entry->GetNextEntry(); + } + Unregister_Object(name_list); + delete name_list;*/ + + // + //---------------------------------------------------------------------- + // Create static audio objects + //---------------------------------------------------------------------- + // + + // + // Get static audio stream resource + // + ResourceDescription *resource_description; + + Check(application); + Check(application->GetResourceFile()); + resource_description = + application->GetResourceFile()->FindResourceDescription( + "StaticAudioStream", + ResourceDescription::StaticAudioStreamResourceType + ); + Check(resource_description); + resource_description->Lock(); + + // + // Parse the audio object stream + // + AudioObjectStream audio_object_stream(resource_description, NULL); + + Check(&audio_object_stream); + audio_object_stream.CreateObjects(); + resource_description->Unlock(); +} + +ALuint AL_getBuffer(int index) +{ + return g_buffers[index]; +} + +// +//############################################################################# +// UnloadResources +//############################################################################# +// +void + L4AudioResourceManager::UnloadResources( + ) +{ + Check(this); +// Check(audio_hardware); + + //Unload wav data + if (g_numBuffers > 0) + { + alGetError(); + alDeleteBuffers(g_numBuffers,g_buffers); + ALenum error = alGetError(); + if (error != AL_NO_ERROR) + { + DEBUG_STREAM << "OpenAL reached an error when attempting to delete its buffers." << std::endl; + } + } + + // + //---------------------------------------------------------------------- + // Release banks + //---------------------------------------------------------------------- + // +// Check(audio_hardware->GetFrontCard()); +// audio_hardware->GetFrontCard()->ReleaseAllBanks(); +// Check(audio_hardware->GetRearCard()); +// audio_hardware->GetRearCard()->ReleaseAllBanks(); +} + +// +//############################################################################# +// CreateStaticAudioStreamResource +//############################################################################# +// +ResourceDescription::ResourceID + L4AudioResourceManager::CreateStaticAudioStreamResource( + ResourceFile *resource_file + ) +{ + Check(resource_file); + + // + //---------------------------------------------------------------------- + // Open the notation file for the static stream resource + //---------------------------------------------------------------------- + // + Tell("Opening Audio Script audio\\static.scp\n"); + NotationFile notation_file("audio\\static.scp"); + Check(¬ation_file); + + // + //---------------------------------------------------------------------- + // Build the static audio object stream + //---------------------------------------------------------------------- + // + AudioObjectStream audio_object_stream; + + Check(&audio_object_stream); + audio_object_stream.BuildFromNotationFile(¬ation_file, resource_file); + Tell("Closed Audio Script\n"); + + // + //---------------------------------------------------------------------- + // Add the resource + //---------------------------------------------------------------------- + // + ResourceDescription *res_description; + + res_description = + resource_file->AddResourceMemoryStream( + "StaticAudioStream", + ResourceDescription::StaticAudioStreamResourceType, + 1, + ResourceDescription::Preload, + &audio_object_stream + ); + Check(res_description); + return res_description->resourceID; +} + +// +//############################################################################# +// CreateEntityAudioObjects +//############################################################################# +// +void + L4AudioResourceManager::CreateEntityAudioObjects( + Entity *entity, + AudioRepresentation audio_representation + ) +{ + Check(this); + Check(entity); + Verify( + audio_representation == InternalAudioRepresentation || + audio_representation == ExternalAudioRepresentation + ); + + // + //------------------------------------------------------------------------ + // Read the audio resource for this entity + //------------------------------------------------------------------------ + // + ResourceDescription *audio_resource_description; + + Check(application); + Check(application->GetResourceFile()); + audio_resource_description = + application->GetResourceFile()->SearchList( + entity->GetResourceID(), + ResourceDescription::AudioStreamListResourceType + ); + if (audio_resource_description == NULL) + return; + + // + //------------------------------------------------------------------------ + // Read the appropriate resource for an internal or external + // representation + //------------------------------------------------------------------------ + // + ResourceDescription *stream_resource_description; + + Check(application); + Check(application->GetResourceFile()); + Check(audio_resource_description); + stream_resource_description = + application->GetResourceFile()->SearchList( + audio_resource_description->resourceID, + (audio_representation == InternalAudioRepresentation) ? + ResourceDescription::InternalAudioStreamResourceType : + ResourceDescription::ExternalAudioStreamResourceType + ); + if (stream_resource_description == NULL) + return; + Check(stream_resource_description); + stream_resource_description->Lock(); + audio_resource_description->Lock(); + + // + //------------------------------------------------------------------------ + // Make the audio object stream + //------------------------------------------------------------------------ + // + AudioObjectStream + audio_object_stream( + stream_resource_description, + entity + ); + + Check(&audio_object_stream); + audio_object_stream.CreateObjects(); + stream_resource_description->Unlock(); + audio_resource_description->Unlock(); +} + +// +//############################################################################# +// DestroyEntityAudioObjects +//############################################################################# +// +void + L4AudioResourceManager::DestroyEntityAudioObjects(Entity *entity) +{ + Check(this); + Check(entity); + + // + //-------------------------------------------------------------------------- + // Stop and delete all audio objects + //-------------------------------------------------------------------------- + // + Entity::AudioSocketIterator + iterator(entity); + Component + *component; + AudioComponent + *audio_component; + + Check(&iterator); + while ((component = iterator.ReadAndNext()) != NULL) + { + audio_component = Cast_Object(AudioComponent*, component); + Check(audio_component); + audio_component->ReceiveControl(StopAudioControlID, 0.0f); + audio_component->ReceiveControl(FlushMessagesAudioControlID, 0.0f); + } + iterator.DeletePlugs(); +} + +// +//############################################################################# +// CreateModelAudioResource +//############################################################################# +// +ResourceDescription::ResourceID + L4AudioResourceManager::CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories* + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + + const char *script_name = NULL; + ResourceDescription::ResourceID resource_id_list[3]; + size_t list_length = 0; + + resource_id_list[0] = ResourceDescription::NullResourceID; + resource_id_list[1] = ResourceDescription::NullResourceID; + resource_id_list[2] = ResourceDescription::NullResourceID; + + // + //-------------------------------------------------------------------------- + // Check for the external audio script + //-------------------------------------------------------------------------- + // + if (model_file->GetEntry("audio", "external", &script_name)) + { + // + // See if the resource already exists + // + ResourceDescription *res_description = + resource_file->FindResourceDescription( + script_name, + ResourceDescription::ExternalAudioStreamResourceType + ); + + // + //----------------------------------------------------------------------- + // If not, create it + //----------------------------------------------------------------------- + // + if (res_description == NULL) + { + // + // Make the file name + // + CString file_name(script_name); + CString prefix("audio\\"); + + file_name = prefix + file_name; + + // + // Build the memory stream + // + Tell("Opening Audio Script " << file_name << "\n"); + NotationFile script_file(file_name); + AudioObjectStream audio_object_stream; + + Check(&script_file); + Check(&audio_object_stream); + audio_object_stream.BuildFromNotationFile(&script_file, resource_file); + Tell("Closed Audio Script\n"); + + // + // Add the resource + // + res_description = + resource_file->AddResourceMemoryStream( + script_name, + ResourceDescription::ExternalAudioStreamResourceType, + 1, + ResourceDescription::Preload, + &audio_object_stream + ); + } + Check(res_description); + resource_id_list[list_length++] = res_description->resourceID; + } + + // + //-------------------------------------------------------------------------- + // Check for the internal audio script + //-------------------------------------------------------------------------- + // + if (model_file->GetEntry("audio", "internal", &script_name)) + { + // + // See if the resource already exists + // + ResourceDescription *res_description = + resource_file->FindResourceDescription( + script_name, + ResourceDescription::InternalAudioStreamResourceType + ); + + // + // If not, create it + // + if (res_description == NULL) + { + // + // Make the file name + // + CString file_name(script_name); + CString prefix("audio\\"); + + file_name = prefix + file_name; + + // + // Build the memory stream + // + Tell("Opening Audio Script " << file_name << "\n"); + NotationFile script_file(file_name); + AudioObjectStream audio_object_stream; + + Check(&script_file); + Check(&audio_object_stream); + audio_object_stream.BuildFromNotationFile(&script_file, resource_file); + Tell("Closed Audio Script\n"); + + // + // Add the resource + // + res_description = + resource_file->AddResourceMemoryStream( + script_name, + ResourceDescription::InternalAudioStreamResourceType, + 1, + ResourceDescription::Preload, + &audio_object_stream + ); + } + Check(res_description); + resource_id_list[list_length++] = res_description->resourceID; + } + + // + //-------------------------------------------------------------------------- + // Check for the audio entity model + //-------------------------------------------------------------------------- + // + const char *audio_entity_model = NULL; + + if (model_file->GetEntry("audio", "model", &audio_entity_model)) + { + // + // The resource should already exist + // + ResourceDescription *res_description = + resource_file->FindResourceDescription( + audio_entity_model, + ResourceDescription::ModelListResourceType + ); + if (res_description == NULL) + { + std::cout << "audio_entity_model == " << audio_entity_model; + Fail("L4AudioResourceManager::CreateModelAudioStreamResource - model not found"); + } + Check(res_description); + resource_id_list[list_length++] = res_description->resourceID; + } + + // + //-------------------------------------------------------------------------- + // If either script has been created, then create the resource list + //-------------------------------------------------------------------------- + // + if (list_length > 0) + { + ResourceDescription *res_description = + resource_file->AddResourceList( + model_name, + ResourceDescription::AudioStreamListResourceType, + 1, + ResourceDescription::Preload, + resource_id_list, + list_length + ); + Check(res_description); + return res_description->resourceID; + } + return ResourceDescription::NullResourceID; +} diff --git a/MUNGA_L4/L4AUDRES.h b/MUNGA_L4/L4AUDRES.h new file mode 100644 index 0000000..e6408fa --- /dev/null +++ b/MUNGA_L4/L4AUDRES.h @@ -0,0 +1,163 @@ +#pragma once + +#include "..\munga\objstrm.h" +#include "..\munga\entity.h" +#include "..\munga\audio.h" +#include "openal/al.h" + +ALuint AL_getBuffer(int index); +extern ALuint *g_buffers; +extern int g_numBuffers; + + +//class AudioHardware; + +//########################################################################## +//###################### AudioObjectStream ########################### +//########################################################################## + +class AudioObjectStream: +public PlugStream +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction and testing +// +public: + AudioObjectStream(); + AudioObjectStream( + ResourceDescription *resource_description, + Entity *entity + ); + ~AudioObjectStream(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +private: + RegisteredClass* + MakeObjectImplementation(Enumeration class_ID); + + void + CreatedObjectImplementation( + RegisteredClass *object, + ObjectID object_ID + ); + + void + BuildFromPageImplementation( + NameList *entry_list, + Enumeration class_ID, + ObjectID object_ID + ); + + void + BuiltFromPageImplementation( + Enumeration class_ID, + ObjectID object_ID, + const CString &object_name_string + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: +Entity *entity; +}; + +//########################################################################## +//#################### L4AudioResourceManager ######################## +//########################################################################## + +class L4AudioResourceManager: + public Node +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + L4AudioResourceManager(); + ~L4AudioResourceManager(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Static audio object methods +// +public: + // + //-------------------------------------------------------------------- + // PreloadResources + //-------------------------------------------------------------------- + // + void + PreloadResources( + NotationFile *notation_file + ); + + // + //-------------------------------------------------------------------- + // UnloadResources + //-------------------------------------------------------------------- + // + void + UnloadResources( + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Static audio object methods - tool support +// +public: + // + //-------------------------------------------------------------------- + // CreateStaticAudioStreamResource + //-------------------------------------------------------------------- + // + static ResourceDescription::ResourceID + CreateStaticAudioStreamResource( + ResourceFile *resource_file + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Dynamic audio object methods +// +public: + // + //-------------------------------------------------------------------- + // CreateEntityAudioObjects + //-------------------------------------------------------------------- + // + void + CreateEntityAudioObjects( + Entity *entity, + AudioRepresentation audio_representation + ); + + // + //-------------------------------------------------------------------- + // DestroyEntityAudioObjects + //-------------------------------------------------------------------- + // + void + DestroyEntityAudioObjects(Entity *entity); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Dynamic audio object methods - tool support +// +public: + // + //-------------------------------------------------------------------- + // CreateModelAudioStreamResource + //-------------------------------------------------------------------- + // + static ResourceDescription::ResourceID + CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); +}; diff --git a/MUNGA_L4/L4AUDRND.cpp b/MUNGA_L4/L4AUDRND.cpp new file mode 100644 index 0000000..9521f87 --- /dev/null +++ b/MUNGA_L4/L4AUDRND.cpp @@ -0,0 +1,1417 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4audrnd.h" +#include "..\munga\notation.h" +#include "openal/alc.h" + +// +//############################################################################# +// L4AudioRenderer +//############################################################################# +// +L4AudioRenderer::L4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode +): + AudioRenderer(render_rate), + runningAudioSourceSocket(NULL, False), + dormantAudioSourceSocket(NULL), + mixingAudioSourceSocket(NULL, False) +{ + missionReviewMode = mission_review_mode; + nextCalculateMixFrame = NullAudioFrameCount; +} + +// +//############################################################################# +// ~L4AudioRenderer +//############################################################################# +// +L4AudioRenderer::~L4AudioRenderer() +{ + //Close OpenAL + ALCcontext *context = alcGetCurrentContext(); + ALCdevice *device = alcGetContextsDevice(context); + alcMakeContextCurrent(NULL); + alcDestroyContext(context); + alcCloseDevice(device); + + + // + //---------------------------------------------------------------------- + // Verify that all of entities have become uninteresting + //---------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.GetSize() == 0); + } + { + DormantSourceIterator iterator(&dormantAudioSourceSocket); + Verify(iterator.GetSize() == 0); + } + #endif + + // + //---------------------------------------------------------------------- + // Unload resources + //---------------------------------------------------------------------- + // + Check(&audioResourceManager); +// audioResourceManager.UnloadResources(&audioHardware); + + // + //---------------------------------------------------------------------- + // Close audio hardware + //---------------------------------------------------------------------- + // +// Check(&audioHardware); +// audioHardware.Close(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + L4AudioRenderer::TestInstance() const +{ + AudioRenderer::TestInstance(); + + Check(&audioHardware); + Check(&runningAudioSourceSocket); + Check(&dormantAudioSourceSocket); + Check(&mixingAudioSourceSocket); + + return True; +} + +// +//############################################################################# +// Initialize +//############################################################################# +// +void + L4AudioRenderer::Initialize() +{ + Check(this); + + // + //---------------------------------------------------------------------- + // Call inherited method + //---------------------------------------------------------------------- + // + AudioRenderer::Initialize(); + + // + //---------------------------------------------------------------------- + // Get the audio head + //---------------------------------------------------------------------- + // + AudioHead *audio_head = GetAudioHead(); + Check(audio_head); + + // + //---------------------------------------------------------------------- + // Open the audio renderer notation file + //---------------------------------------------------------------------- + // + int ret; + CString audio_file_name; + + if (missionReviewMode) + { + audio_file_name = "audio\\audiomr.ini"; + } + else + { + audio_file_name = "audio\\audio.ini"; + } + + NotationFile notation_file(audio_file_name); + Check(¬ation_file); + + // + //---------------------------------------------------------------------- + // Define clipping sphere (m) + //---------------------------------------------------------------------- + // + Scalar clipping_radius; + + ret = notation_file.GetEntry( + "AudioRenderer", + "clipping_radius", + &clipping_radius + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - clipping_radius not defined"); + } + Check(audio_head); + audio_head->DefineClippingSphere(clipping_radius); + + // + //---------------------------------------------------------------------- + // Distance to speakers or width of head entity (m) + //---------------------------------------------------------------------- + // + Scalar distance_between_ears; + ret = notation_file.GetEntry( + "AudioRenderer", + "distance_between_ears", + &distance_between_ears + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - distance_between_ears not defined"); + } + Check(audio_head); + audio_head->SetDistanceBetweenEars(distance_between_ears); + + // + //---------------------------------------------------------------------- + // Define amplitude rolloff characteristics + //---------------------------------------------------------------------- + // + Scalar amplitude_rolloff; + Scalar amplitude_rolloff_knee; + Scalar amplitude_rolloff_distance_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "amplitude_rolloff", + &litude_rolloff + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - amplitude_rolloff not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "amplitude_rolloff_distance_scale", + &litude_rolloff_distance_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - amplitude_rolloff_distance_scale not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "amplitude_rolloff_knee", + &litude_rolloff_knee + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - amplitude_rolloff_knee not defined"); + } + + Check(audio_head); + audio_head->ControlAmplitudeRollOff( + amplitude_rolloff, + amplitude_rolloff_knee, + amplitude_rolloff_distance_scale + ); + + // + //---------------------------------------------------------------------- + // Define high frequency rolloff characteristics + //---------------------------------------------------------------------- + // + Scalar high_frequency_rolloff; + Scalar high_frequency_rolloff_knee; + Scalar high_frequency_rolloff_distance_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "high_frequency_rolloff", + &high_frequency_rolloff + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - high_frequency_rolloff not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "high_frequency_rolloff_knee", + &high_frequency_rolloff_knee + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - high_frequency_rolloff_knee not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "high_frequency_rolloff_distance_scale", + &high_frequency_rolloff_distance_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - high_frequency_rolloff_distance_scale not defined"); + } + + Check(audio_head); + audio_head->ControlHighFrequencyRollOff( + high_frequency_rolloff, + high_frequency_rolloff_knee, + high_frequency_rolloff_distance_scale + ); + + // + //---------------------------------------------------------------------- + // Define Doppler characterisitics + //---------------------------------------------------------------------- + // + Scalar doppler_range; + Scalar speed_of_sound; + + ret = notation_file.GetEntry( + "AudioRenderer", + "doppler_range", + &doppler_range + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - doppler_range not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "speed_of_sound", + &speed_of_sound + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - speed_of_sound not defined"); + } + + Check(audio_head); + audio_head->ControlDopplerEffect( + doppler_range, + speed_of_sound + ); + + // + //---------------------------------------------------------------------- + // Define source compression characterisitics + //---------------------------------------------------------------------- + // + Scalar compression_exponent; + Scalar compression_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "compression_exponent", + &compression_exponent + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - compression_exponent not defined"); + } + ret = notation_file.GetEntry( + "AudioRenderer", + "compression_scale", + &compression_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - compression_scale not defined"); + } + + Check(audio_head); + audio_head->ControlSourceCompression( + compression_exponent, + compression_scale + ); + + // + //---------------------------------------------------------------------- + // Set ITD difference + //---------------------------------------------------------------------- + // + Scalar itd_difference; + + ret = notation_file.GetEntry( + "AudioRenderer", + "itd_difference", + &itd_difference + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - itd_difference not defined"); + } + + Check(audio_head); + audio_head->SetITDDifference(itd_difference); + + // + //---------------------------------------------------------------------- + // Set global reverb scale + //---------------------------------------------------------------------- + // + Scalar global_reverb_scale; + + ret = notation_file.GetEntry( + "AudioRenderer", + "global_reverb_scale", + &global_reverb_scale + ); + if (!ret) + { + Fail("L4AudioRenderer::Initialize - global_reverb_scale not defined"); + } + + Check(audio_head); + audio_head->SetGlobalReverbScale(global_reverb_scale); + + // + //---------------------------------------------------------------------- + // Initialize the audio hardware + //---------------------------------------------------------------------- + // +// Check(&audioHardware); +// audioHardware.Initialize(); + + //Start OpenAL + ALCdevice *device = alcOpenDevice(NULL); + if (device) + { + ALCcontext *context = alcCreateContext(device,NULL); + alcMakeContextCurrent(context); + } + + // + //---------------------------------------------------------------------- + // Preload resources + //---------------------------------------------------------------------- + // + Check(&audioResourceManager); + audioResourceManager.PreloadResources(¬ation_file); +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + L4AudioRenderer::NotifyOfNewInterestingEntity(Entity *interesting_entity) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_CREATE_OBJECTS(); + + Check(this); + Check(interesting_entity); + + Entity *linked_entity = GetLinkedEntity(); + Check(linked_entity); + + AudioRepresentation audio_representation = + (AudioRepresentation)interesting_entity->GetAudioRepresentation( + linked_entity + ); + + Check(&audioResourceManager); + audioResourceManager.CreateEntityAudioObjects( + interesting_entity, + audio_representation + ); + + CLEAR_AUDIO_RENDERER_CREATE_OBJECTS(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntity +//############################################################################# +// +void + L4AudioRenderer::NotifyOfBecomingUninterestingEntity( + Entity *uninteresting_entity + ) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_DESTROY_OBJECTS(); + + Check(this); + Check(uninteresting_entity); + + Check(&audioResourceManager); + audioResourceManager.DestroyEntityAudioObjects(uninteresting_entity); + + CLEAR_AUDIO_RENDERER_DESTROY_OBJECTS(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +// LoadMissionImplementation +//############################################################################# +// +void + L4AudioRenderer::LoadMissionImplementation(Mission*) +{ + Check(this); +} + +// +//############################################################################# +// ShutdownImplementation +//############################################################################# +// +void + L4AudioRenderer::ShutdownImplementation() +{ + Check(this); +} + +// +//############################################################################# +// SuspendImplementation +//############################################################################# +// +void + L4AudioRenderer::SuspendImplementation() +{ + Check(this); +} + +// +//############################################################################# +// ResumeImplementation +//############################################################################# +// +void + L4AudioRenderer::ResumeImplementation() +{ + Check(this); +} + +// +//############################################################################# +// StartRequest +//############################################################################# +// +void + L4AudioRenderer::StartRequest(L4AudioSource *audio_source) +{ + Check(this); + Check(audio_source); + + // + //-------------------------------------------------------------------------- + // Verify that the source is stopped + //-------------------------------------------------------------------------- + // + Verify(audio_source->GetAudioSourceState() == StoppedAudioSourceState); + + // + //-------------------------------------------------------------------------- + // Request audio resources + //-------------------------------------------------------------------------- + // + Logical + resources_available; +/* AudioChannelSet + channel_set_result;*/ + SourceSet *source_result = audio_source->GetAudioChannelSet(); + + resources_available = + RequestAudioResources( + audio_source, + source_result + ); + if (!resources_available) + { + if (audio_source->GetAudioRenderType() == SustainedAudioRenderType) + { + // + // Set state to dormant and add the source to the dormant list + // + audio_source->AssignAudioSourceState(DormantAudioSourceState); + dormantAudioSourceSocket.Add(audio_source); + } + return; + } + + // + //-------------------------------------------------------------------------- + // Start the audio source + //-------------------------------------------------------------------------- + // + + // + // Update source spatial model + // Set channel set of source + // Source start implementation + // Set state of source to running + // + audio_source->UpdateSpatialModel(GetAudioHead()); + audio_source->SetAudioChannelSet(*source_result); + audio_source->StartImplementation(); + audio_source->AssignAudioSourceState(RunningAudioSourceState); + + // + // Add source to the running list and the mixing list + // + runningAudioSourceSocket.AddValue( + audio_source, + audio_source->CalculateAudioWeighting() + ); + if ( + audio_source->GetAudioSourceMixPresence() != + ManualAudioSourceMixPresence + ) + { + mixingAudioSourceSocket.AddValue( + audio_source, + audio_source->GetAudioSourceMixPresence() + ); + } + #ifdef LAB_ONLY + sourceStartCount++; + #endif +} + +// +//############################################################################# +// StopRequest +//############################################################################# +// +void + L4AudioRenderer::StopRequest(L4AudioSource *audio_source) +{ + Check(this); + Check(audio_source); + + // + //-------------------------------------------------------------------------- + // Verify that the source is not stopped + //-------------------------------------------------------------------------- + // + Verify(audio_source->GetAudioSourceState() != StoppedAudioSourceState); + + // + //-------------------------------------------------------------------------- + // If state of the source is dormant or suspended + // Then set source to stop state and remove from dormant list + //-------------------------------------------------------------------------- + // + if ( + audio_source->GetAudioSourceState() == DormantAudioSourceState || + audio_source->GetAudioSourceState() == SuspendedAudioSourceState + ) + { + // + // Set state of source to stopped + // Verify that source is in dormant list + // Remove source from dormant list + // Verify that source is not in dormant list + // + audio_source->AssignAudioSourceState(StoppedAudioSourceState); + #if DEBUG_LEVEL>0 + { + DormantSourceIterator iterator(&dormantAudioSourceSocket); + Verify(iterator.IsPlugMember(audio_source) == True); + } + #endif + PlugIterator remover(audio_source); + remover.RemoveSocket(&dormantAudioSourceSocket); + #if DEBUG_LEVEL>0 + { + DormantSourceIterator iterator(&dormantAudioSourceSocket); + Verify(iterator.IsPlugMember(audio_source) == False); + } + #endif + return; + } + + // + //-------------------------------------------------------------------------- + // Stop the source + //-------------------------------------------------------------------------- + // + AudioSourceStopMaintenance(audio_source); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +void + L4AudioRenderer::ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ) +{ + SET_AUDIO_RENDERER(); + SET_AUDIO_RENDERER_EXECUTE(); + + Check(this); + + AudioRenderer::ExecuteImplementation(complexity_update, iterator); + CalculateMix(); + RunningSourceCheckup(); + // RunningAudioSourceSort(); + DormantSourceCheckup(); + + CLEAR_AUDIO_RENDERER_EXECUTE(); + CLEAR_AUDIO_RENDERER(); +} + +// +//############################################################################# +// CalculateMix +//############################################################################# +// +void + L4AudioRenderer::CalculateMix() +{ + SET_AUDIO_CALCULATE_MIX(); + + // + //-------------------------------------------------------------------------- + // Is this the next calculate mix frame + //-------------------------------------------------------------------------- + // + #if 0 + if (nextCalculateMixFrame > GetAudioFrameCount()) + { + CLEAR_AUDIO_CALCULATE_MIX(); + return; + } + nextCalculateMixFrame = GetAudioFrameCount() + DefaultAudioFrameDelay; + #endif + + // + //-------------------------------------------------------------------------- + // Calculate the compression volume scaling + // + // For each source, calculate the amount to scale its volume by + // according to those sources which have a higher mix presence + //-------------------------------------------------------------------------- + // + { + AudioControlValue + compression_scale = 1.0f; + AudioControlValue + compression_effect = 0.0f; + AudioSourceMixPresence + current_mix_presence = MedAudioSourceMixPresence; + + MixingSourceIterator + iterator(&mixingAudioSourceSocket); + L4AudioSource + *audio_source; + + Check(GetAudioHead()); + Scalar comp_scale = GetAudioHead()->GetSourceCompressionScale(); + Scalar comp_exp = GetAudioHead()->GetSourceCompressionExponent(); + + // + // Get mix presence of the first source + // + if ((audio_source = iterator.GetCurrent()) != NULL) + { + Check(audio_source); + current_mix_presence = audio_source->GetAudioSourceMixPresence(); + } + + // + //----------------------------------------------------------------------- + // For each audio source, calculate the compression scale + //----------------------------------------------------------------------- + // + while ((audio_source = iterator.ReadAndNext()) != NULL) + { + Check(audio_source); + + // + //-------------------------------------------------------------------- + // If the mix presence of this source is greater then the last + // source then we have stepped to a lower mix presence. + //-------------------------------------------------------------------- + // + if ( + current_mix_presence != + audio_source->GetAudioSourceMixPresence() + ) + { + Verify( + current_mix_presence < + audio_source->GetAudioSourceMixPresence() + ); + current_mix_presence = audio_source->GetAudioSourceMixPresence(); + + // + // Calculate the compression scale for this mix presence + // + // scale = 1 - ((comp_scale*x)^comp_exp) + // + compression_scale = + 1.0f - pow(comp_scale * compression_effect, comp_exp); + Verify(compression_scale >= 0.0f && compression_scale <= 1.0f); + } + + // + //-------------------------------------------------------------------- + // Set the compression scale for this source + //-------------------------------------------------------------------- + // + audio_source->SetVolumeCompressionScale(compression_scale); + + // + //-------------------------------------------------------------------- + // Calculate the compression effect for this source + //-------------------------------------------------------------------- + // + AudioControlValue source_compression_effect; + + source_compression_effect = + audio_source->CalculateSourceCompressionEffect(); + Verify( + source_compression_effect >= 0.0f && + source_compression_effect <= 1.0f + ); + + // + //-------------------------------------------------------------------- + // Update the compression effect for this mix presence + //-------------------------------------------------------------------- + // + compression_effect = + Max(compression_effect, source_compression_effect); + Verify(compression_effect >= 0.0f && compression_effect <= 1.0f); + + #if 0 + Tell( + "compression_effect " << compression_effect << + " : compression_scale " << compression_scale << "\n" + ); + #endif + } + } + CLEAR_AUDIO_CALCULATE_MIX(); +} + +// +//############################################################################# +// RunningSourceCheckup +//############################################################################# +// +void + L4AudioRenderer::RunningSourceCheckup() +{ + SET_AUDIO_RUNNING_SOURCES(); + + // + //-------------------------------------------------------------------------- + // Iterate through all running sources + //-------------------------------------------------------------------------- + // + ChainOf + resort_socket(NULL); + RunningSourceIterator + running_iterator(&runningAudioSourceSocket); + L4AudioSource + *audio_source; + + while ((audio_source = running_iterator.GetCurrent()) != NULL) + { + Check(audio_source); + + // + //----------------------------------------------------------------------- + // If the source does not require maintenance then skip it + //----------------------------------------------------------------------- + // + if (!audio_source->RequiresMaintenance(GetAudioHead())) + { + running_iterator.Next(); + continue; + } + + //Update object position + + + // + //----------------------------------------------------------------------- + // If the source is clipped then either stop or suspend + //----------------------------------------------------------------------- + // + if (audio_source->IsAudioSourceClipped(GetAudioHead())) + { + if (audio_source->GetAudioRenderType() == TransientAudioRenderType) + { + AudioSourceStopMaintenance(audio_source); + } + else + { + Verify( + audio_source->GetAudioRenderType() == + SustainedAudioRenderType + ); + AudioSourceSuspendMaintenance(audio_source); + } + continue; + } + + // + //----------------------------------------------------------------------- + // If the source is finished playing then stop it + //----------------------------------------------------------------------- + // + if (audio_source->IsFinishedPlaying()) + { + AudioSourceStopMaintenance(audio_source); + continue; + } + + + + // + //----------------------------------------------------------------------- + // Execute + //----------------------------------------------------------------------- + // + SET_AUDIO_EXECUTE_SOURCES(); + audio_source->Execute(); + CLEAR_AUDIO_EXECUTE_SOURCES(); + + // + //----------------------------------------------------------------------- + // Add to resort list if weight has changed + //----------------------------------------------------------------------- + // + if ( + audio_source->CalculateAudioWeighting() != + running_iterator.GetValue() + ) + { + running_iterator.Remove(); + resort_socket.Add(audio_source); + } + else + { + running_iterator.Next(); + } + } + + // + //-------------------------------------------------------------------------- + // Sort resort socket back into running socket + //-------------------------------------------------------------------------- + // + ChainIteratorOf + resort_iterator(&resort_socket); + + while ((audio_source = resort_iterator.ReadAndNext()) != NULL) + { + Check(audio_source); + Verify(running_iterator.IsPlugMember(audio_source) == False); + runningAudioSourceSocket.AddValue( + audio_source, + audio_source->CalculateAudioWeighting() + ); + } + + CLEAR_AUDIO_RUNNING_SOURCES(); +} + +// +//############################################################################# +// DormantSourceCheckup +//############################################################################# +// +void + L4AudioRenderer::DormantSourceCheckup() +{ + SET_AUDIO_DORMANT_SOURCES(); + + // + //-------------------------------------------------------------------------- + // Assemble the request socket + //-------------------------------------------------------------------------- + // + VChainOf + resume_request_socket(NULL, False); + DormantSourceIterator + dormant_iterator(&dormantAudioSourceSocket); + L4AudioSource + *audio_source; + + while ((audio_source = dormant_iterator.ReadAndNext()) != NULL) + { + Check(audio_source); + + // + // If the suspend gate is not up then it can not resume + // + if (!audio_source->CanResume(GetAudioHead())) + continue; + + // + // If the audio source is clipped then it can not resume + // + if (audio_source->IsAudioSourceClipped(GetAudioHead())) + continue; + + // + // Add to request socket + // + resume_request_socket.AddValue( + audio_source, + audio_source->CalculateAudioWeighting() + ); + } + + // + //-------------------------------------------------------------------------- + // Iterate through request socket + //-------------------------------------------------------------------------- + // + VChainIteratorOf + resume_request_iterator(&resume_request_socket); + + while ((audio_source = resume_request_iterator.GetCurrent()) != NULL) + { + Check(audio_source); + + // + // Request audio resources + // +/* AudioChannelSet + channel_set_result;*/ + + SourceSet *source_result = audio_source->GetAudioChannelSet(); + + if (!RequestAudioResources(audio_source, + source_result) + ) + break; + + // + // Remove from dormant list and request list + // + PlugIterator remover(audio_source); + remover.RemoveSocket(&dormantAudioSourceSocket); + AudioWeighting audio_weighting = resume_request_iterator.GetValue(); + resume_request_iterator.Remove(); + + // + // Update Spatial model + // + audio_source->UpdateSpatialModel(GetAudioHead()); + + // + // Set channel set of source + // Source resume implementation + // Set state of source to running + // + audio_source->SetAudioChannelSet(*source_result); + audio_source->ResumeImplementation(); + audio_source->AssignAudioSourceState(RunningAudioSourceState); + + // + // Put on running socket and mixing socket + // + runningAudioSourceSocket.AddValue(audio_source, audio_weighting); + if ( + audio_source->GetAudioSourceMixPresence() != + ManualAudioSourceMixPresence + ) + { + mixingAudioSourceSocket.AddValue( + audio_source, + audio_source->GetAudioSourceMixPresence() + ); + } + } + CLEAR_AUDIO_DORMANT_SOURCES(); +} + +// +//############################################################################# +// AudioSourceStopMaintenance +//############################################################################# +// +void + L4AudioRenderer::AudioSourceStopMaintenance(L4AudioSource *source) +{ + Check(source); + Verify(source->GetAudioSourceState() == RunningAudioSourceState); + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == True); + } + #endif + + source->StopImplementation(); + source->AssignAudioSourceState(StoppedAudioSourceState); + source->ReleaseChannels(); + + PlugIterator remover(source); + remover.RemoveSocket(&runningAudioSourceSocket); + remover.RemoveSocket(&mixingAudioSourceSocket); + + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == False); + } + #endif +} + +// +//############################################################################# +// AudioSourceSuspendMaintenance +//############################################################################# +// +void + L4AudioRenderer::AudioSourceSuspendMaintenance(L4AudioSource *source) +{ + Check(source); + Verify(source->GetAudioRenderType() == SustainedAudioRenderType); + Verify(source->GetAudioSourceState() == RunningAudioSourceState); + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == True); + } + #endif + + source->SuspendImplementation(); + source->AssignAudioSourceState(SuspendedAudioSourceState); + source->ReleaseChannels(); + + PlugIterator remover(source); + remover.RemoveSocket(&runningAudioSourceSocket); + remover.RemoveSocket(&mixingAudioSourceSocket); + + #if DEBUG_LEVEL>0 + { + RunningSourceIterator iterator(&runningAudioSourceSocket); + Verify(iterator.IsPlugMember(source) == False); + } + #endif + + dormantAudioSourceSocket.Add(source); +} + +// +//############################################################################# +// RequestAudioResources +//############################################################################# +// +Logical + L4AudioRenderer::RequestAudioResources( + L4AudioSource *audio_source, + SourceSet *source_result + ) +{ + Check(this); + Check(audio_source); + Check(source_result); + + // + //-------------------------------------------------------------------------- + // This source must be within the culling volume + //-------------------------------------------------------------------------- + // + if (audio_source->IsAudioSourceClipped(GetAudioHead())) + return False; + + // + //-------------------------------------------------------------------------- + // Request audio channels for this source + //-------------------------------------------------------------------------- + // + Logical + resources_available; + + source_result = audio_source->GetAudioChannelSet(); + Check(source_result); + + resources_available = + RequestAudioChannels( + audio_source->GetAudioVoiceCount(), + source_result + ); + + // + //-------------------------------------------------------------------------- + // If audio channels are not available then check running sources for + // lower weight sources + //-------------------------------------------------------------------------- + // + if (!resources_available) + { + RunningSourceIterator + iterator(&runningAudioSourceSocket); + L4AudioSource + *running_audio_source; + AudioWeighting + audio_source_weighting; + + iterator.Last(); + running_audio_source = iterator.GetCurrent(); + audio_source_weighting = audio_source->CalculateAudioWeighting(); + + // + //----------------------------------------------------------------------- + // while + // request for channels is not satisfied and + // there exist running sources that have lower weighting + //----------------------------------------------------------------------- + // + while ( + !resources_available && + running_audio_source != NULL && + audio_source_weighting < iterator.GetValue() // Actual value is inverted + ) + { + Check(running_audio_source); + Verify( + running_audio_source->GetAudioSourcePriority() <= + audio_source->GetAudioSourcePriority() + ); + + // + //-------------------------------------------------------------------- + // Collect Statistics + //-------------------------------------------------------------------- + // + #ifdef LAB_ONLY + if ( + running_audio_source->GetAudioSourcePriority() < + audio_source->GetAudioSourcePriority() + ) + { + resourceStealPriorityCount++; + } + else + { + Verify( + running_audio_source->GetAudioSourcePriority() == + audio_source->GetAudioSourcePriority() + ); + Warn( + running_audio_source->CalculateSourceVolumeScale() >= + audio_source->CalculateSourceVolumeScale() + ); + resourceStealVolumeCount++; + } + AudioTime duration_cutoff(0.1f); + if ( + running_audio_source->GetCurrentRunningTime() <= + duration_cutoff + ) + { + stealShortDurationCount++; + } + resourceStealCount++; + #endif + + // + //-------------------------------------------------------------------- + // If running source is transient + // Then stop the source + // Else suspend the source + //-------------------------------------------------------------------- + // + if ( + running_audio_source->GetAudioRenderType() == + TransientAudioRenderType + ) + { + AudioSourceStopMaintenance(running_audio_source); + } + else + { + Verify( + running_audio_source->GetAudioRenderType() == + SustainedAudioRenderType + ); + AudioSourceSuspendMaintenance(running_audio_source); + } + + // + //-------------------------------------------------------------------- + // Request resources again + //-------------------------------------------------------------------- + // + resources_available = + RequestAudioChannels( + audio_source->GetAudioVoiceCount(), + source_result + ); + + iterator.Last(); + running_audio_source = iterator.GetCurrent(); + } + } + return resources_available; +} + +// +//############################################################################# +// RequestAudioChannels +//############################################################################# +// +Logical + L4AudioRenderer::RequestAudioChannels( + int voices_requested, + SourceSet *source_request + ) +{ + Check(this); + Check(source_request); + + //Do we have enough? + int requested = source_request->count; + + bool failed = true; + + alGetError(); + + for (int i = 0; i < requested; i++) + { + if (!alIsSource(source_request->sources[i])) + { + alGenSources(1, source_request->sources + i); + } + } + + ALenum error = alGetError(); + if (error == AL_NO_ERROR) + { + failed = false; + } + + if (failed) + { + return False; + } + + return True; + + // + //---------------------------------------------------------------------- + // Attempt to allocate channels from audio hardware + //---------------------------------------------------------------------- + // +/* AudioChannel *channel; + Logical success = False; + AudioCard *front_card = GetFrontCard(); + AudioCard *rear_card = GetRearCard(); + + Check(front_card); + Check(rear_card); + + while (True) + { + if (channel_set_request->IsFrontLeftEnabled()) + { + if ((channel = + front_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetFrontLeft(channel); + } + + if (channel_set_request->IsFrontRightEnabled()) + { + if ((channel = + front_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetFrontRight(channel); + } + + if (channel_set_request->IsRearLeftEnabled()) + { + if ((channel = + rear_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetRearLeft(channel); + } + + if (channel_set_request->IsRearRightEnabled()) + { + if ((channel = + rear_card->RequestAudioChannel(voices_requested)) == NULL) + break; + Check(channel); + channel_set_request->SetRearRight(channel); + } + + success = True; + break; + } + + // + //---------------------------------------------------------------------- + // If did not succeed then release allocated channels + //---------------------------------------------------------------------- + // + if (!success) + { + channel_set_request->ReleaseAll(); + return False; + } + + // + //---------------------------------------------------------------------- + // else, return allocated channels + //---------------------------------------------------------------------- + // + return True;*/ +} + +void L4AudioRenderer::ReleaseSourceSet(SourceSet &sourceSet) +{ + for (int i = 0; i < sourceSet.count; i++) + { + ALenum state; + alGetSourcei(sourceSet.sources[i], AL_SOURCE_STATE, &state); + + if (state == AL_PLAYING) + { + alSourceStop(sourceSet.sources[i]); + } + } + + alDeleteSources(sourceSet.count, sourceSet.sources); + + for (int i = 0; i < sourceSet.count; i++) + { + sourceSet.sources[i] = -1; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer profile bits ~~~~~~~~~~~~~~~~~~~~~~~~~ + +#if defined(TRACE_AUDIO_RENDERER_RUNNING_SOURCES) + BitTrace Audio_Renderer_Running_Sources("Audio Renderer Running Sources"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_RUNNING_SORT) + BitTrace Audio_Renderer_Running_Sort("Audio Renderer Running Sort"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_CALCULATE_MIX) + BitTrace Audio_Renderer_Calculate_Mix("Audio Renderer Calculate Mix"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_EXECUTE_SOURCES) + BitTrace Audio_Renderer_Execute_Sources("Audio Renderer Execute Sources"); +#endif + +#if defined(TRACE_AUDIO_RENDERER_DORMANT_SOURCES) + BitTrace Audio_Renderer_Dormant_Sources("Audio Renderer Dormant Sources"); +#endif diff --git a/MUNGA_L4/L4AUDRND.h b/MUNGA_L4/L4AUDRND.h new file mode 100644 index 0000000..e5aeee5 --- /dev/null +++ b/MUNGA_L4/L4AUDRND.h @@ -0,0 +1,207 @@ +#pragma once + +#include "..\munga\audrend.h" +#include "l4audhdw.h" +#include "l4audio.h" +#include "l4audres.h" +#include "openal/al.h" + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class L4AudioRenderer: + public AudioRenderer +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction, Testing +// +public: + L4AudioRenderer( + RendererRate render_rate, + Logical mission_review_mode + ); + ~L4AudioRenderer(); + + Logical + TestInstance() const; + + virtual void ReleaseSourceSet(SourceSet &sourceSet); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Renderer support +// +public: + void + Initialize(); +public: + + void + NotifyOfNewInterestingEntity(Entity *interesting_entity); + void + NotifyOfBecomingUninterestingEntity(Entity *uninteresting_entity); + +protected: + void + ExecuteImplementation( + RendererComplexity complexity_update, + RendererOrigin::InterestingEntityIterator *iterator + ); + +private: + void + LoadMissionImplementation(Mission *mission); + void + ShutdownImplementation(); + void + SuspendImplementation(); + void + ResumeImplementation(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Audio hardware accessors +// +public: +/* AudioCard* + GetFrontCard(); + AudioCard* + GetRearCard();*/ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Audio Source support +// +public: + void + StartRequest(L4AudioSource *audio_source); + void + StopRequest(L4AudioSource *audio_source); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + void + CalculateMix(); + void + RunningSourceCheckup(); + //void + // RunningAudioSourceSort(); + void + DormantSourceCheckup(); + void + AudioSourceStopMaintenance(L4AudioSource *source); + void + AudioSourceSuspendMaintenance(L4AudioSource *source); + + Logical + RequestAudioResources( + L4AudioSource *audio_source, + SourceSet *source_result + ); + Logical + RequestAudioChannels( + AudioVoiceCount voices_requested, + SourceSet *source_request + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + Logical + missionReviewMode; + +/* AudioHardware + audioHardware;*/ + L4AudioResourceManager + audioResourceManager; + + AudioFrameCount + nextCalculateMixFrame; + + typedef VChainOf + RunningSourceSocket; + typedef VChainIteratorOf + RunningSourceIterator; + + RunningSourceSocket + runningAudioSourceSocket; + + typedef ChainOf + DormantSourceSocket; + typedef ChainIteratorOf + DormantSourceIterator; + + DormantSourceSocket + dormantAudioSourceSocket; + + typedef VChainOf + MixingSourceSocket; + typedef VChainIteratorOf + MixingSourceIterator; + + MixingSourceSocket + mixingAudioSourceSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer inlines ~~~~~~~~~~~~~~~~~~~~~~~~ + +/*inline AudioCard* + L4AudioRenderer::GetFrontCard() +{ + Check(this); + return audioHardware.GetFrontCard(); +} + +inline AudioCard* + L4AudioRenderer::GetRearCard() +{ + Check(this); + return audioHardware.GetRearCard(); +}*/ + +//~~~~~~~~~~~~~~~~~~~~~~ L4AudioRenderer profile macros ~~~~~~~~~~~~~~~~~~~~ + +#if defined(TRACE_AUDIO_RENDERER_RUNNING_SOURCES) + extern BitTrace Audio_Renderer_Running_Sources; + #define SET_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Set() + #define CLEAR_AUDIO_RUNNING_SOURCES() Audio_Renderer_Running_Sources.Clear() +#else + #define SET_AUDIO_RUNNING_SOURCES() + #define CLEAR_AUDIO_RUNNING_SOURCES() +#endif + +#if defined(TRACE_AUDIO_RENDERER_RUNNING_SORT) + extern BitTrace Audio_Renderer_Running_Sort; + #define SET_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Set() + #define CLEAR_AUDIO_RUNNING_SORT() Audio_Renderer_Running_Sort.Clear() +#else + #define SET_AUDIO_RUNNING_SORT() + #define CLEAR_AUDIO_RUNNING_SORT() +#endif + +#if defined(TRACE_AUDIO_RENDERER_CALCULATE_MIX) + extern BitTrace Audio_Renderer_Calculate_Mix; + #define SET_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Set() + #define CLEAR_AUDIO_CALCULATE_MIX() Audio_Renderer_Calculate_Mix.Clear() +#else + #define SET_AUDIO_CALCULATE_MIX() + #define CLEAR_AUDIO_CALCULATE_MIX() +#endif + +#if defined(TRACE_AUDIO_RENDERER_EXECUTE_SOURCES) + extern BitTrace Audio_Renderer_Execute_Sources; + #define SET_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Set() + #define CLEAR_AUDIO_EXECUTE_SOURCES() Audio_Renderer_Execute_Sources.Clear() +#else + #define SET_AUDIO_EXECUTE_SOURCES() + #define CLEAR_AUDIO_EXECUTE_SOURCES() +#endif + +#if defined(TRACE_AUDIO_RENDERER_DORMANT_SOURCES) + extern BitTrace Audio_Renderer_Dormant_Sources; + #define SET_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Set() + #define CLEAR_AUDIO_DORMANT_SOURCES() Audio_Renderer_Dormant_Sources.Clear() +#else + #define SET_AUDIO_DORMANT_SOURCES() + #define CLEAR_AUDIO_DORMANT_SOURCES() +#endif diff --git a/MUNGA_L4/L4AUDTUL.cpp b/MUNGA_L4/L4AUDTUL.cpp new file mode 100644 index 0000000..a03b87d --- /dev/null +++ b/MUNGA_L4/L4AUDTUL.cpp @@ -0,0 +1,59 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4audres.h" +#include "l4tool.h" +#include "l4audio.h" + +ResourceDescription::ResourceID + L4Tool::CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + return + L4AudioResourceManager::CreateModelAudioStreamResource( + resource_file, + model_name, + model_file, + directories + ); +} + +ResourceDescription::ResourceID + L4Tool::CreateStaticAudioStreamResource( + ResourceFile *resource_file + ) +{ + return + L4AudioResourceManager::CreateStaticAudioStreamResource( + resource_file + ); +} + +// +//############################################################################# +//############################################################################# +// +void L4AudioCreateSymbols::WriteEntryStream(std::ofstream &symbol_file) +{ + AudioCreateSymbols::WriteEntryStream(symbol_file); + + #define WRITE_ENTRY(name)\ + {\ + Verify(symbol_file);\ + symbol_file << #name;\ + symbol_file << "=";\ + symbol_file << name;\ + symbol_file << "\n";\ + } + + WRITE_ENTRY(FrontDirectPatchPosition); + WRITE_ENTRY(RearDirectPatchPosition); + WRITE_ENTRY(FrontLeftDirectPatchPosition); + WRITE_ENTRY(FrontRightDirectPatchPosition); + WRITE_ENTRY(RearLeftDirectPatchPosition); + WRITE_ENTRY(RearRightDirectPatchPosition); +} diff --git a/MUNGA_L4/L4AUDWTR.cpp b/MUNGA_L4/L4AUDWTR.cpp new file mode 100644 index 0000000..b03bf48 --- /dev/null +++ b/MUNGA_L4/L4AUDWTR.cpp @@ -0,0 +1,187 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4audwtr.h" +#include "..\munga\objstrm.h" +#include "..\munga\namelist.h" + +//############################################################################# +//######################## L4AudioCollisionTrigger ###################### +//############################################################################# + +#if 0 +L4AudioCollisionTrigger::L4AudioCollisionTrigger( + StateIndicator *state_attribute_ptr, + Normal *normal_attribute_ptr, + Static3DPatchSource *audio_source, + Enumeration trigger_state, + AudioControlID control_ID, + AudioControlValue control_value, + Logical dump_value +): + AudioStateWatcher( + state_attribute_ptr, + audio_source, + L4AudioCollisionTriggerClassID, + dump_value + ) +{ + Check(normal_attribute_ptr); + normalAttributePtr = normal_attribute_ptr; + triggerState = trigger_state; + controlID = control_ID; + controlValue = control_value; + + PrimeWatcher(); +} +#endif + +// +//############################################################################# +//############################################################################# +// +L4AudioCollisionTrigger::~L4AudioCollisionTrigger() +{ +} + +// +//############################################################################# +//############################################################################# +// +L4AudioCollisionTrigger::L4AudioCollisionTrigger( + PlugStream *stream, + Entity *entity +): + AudioStateWatcher(stream, entity) +{ + // + // HACK - Get "normal" attribute pointer with names + // + CString attribute_name; + void *attribute_ptr; + + MemoryStream_Read(stream, &attribute_name); + Check(entity); + attribute_ptr = entity->GetAttributePointer(attribute_name); + normalAttributePtr = Cast_Object(Normal*, attribute_ptr); + + // + // Get other fields + // + MemoryStream_Read(stream, &triggerState); + MemoryStream_Read(stream, &controlID); + MemoryStream_Read(stream, &controlValue); + + PrimeWatcher(); +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioCollisionTrigger::BuildFromPage( + PlugStream *stream, + NameList *name_list, + ClassID class_ID, + ObjectID object_ID + ) +{ + AudioStateWatcher::BuildFromPage(stream, name_list, class_ID, object_ID); + + // + // HACK - Store "normal" attribute pointer with names + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, CString, normal_attribute); + + // + // Store fields + // + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, trigger_state); + MEM_STRM_WRITE_ENTRY(*stream, name_list, Enumeration, control_ID); + MEM_STRM_WRITE_ENTRY(*stream, name_list, AudioControlValue, control_value); +} + +// +//############################################################################# +//############################################################################# +// +Logical + L4AudioCollisionTrigger::TestInstance() const +{ + AudioStateWatcher::TestInstance(); + Check(normalAttributePtr); + return True; +} + +// +//############################################################################# +//############################################################################# +// +void + L4AudioCollisionTrigger::StateChanged( + Enumeration, + Enumeration new_state + ) +{ + if (new_state == triggerState) + { + // + // Get static 3D source + // + AudioComponent *audio_component; + Static3DPatchSource *audio_source; + + Check(&audioComponentSocket); + audio_component = audioComponentSocket.GetCurrent(); + Check(audio_component); + audio_source = Cast_Object(Static3DPatchSource*, audio_component); + Check(audio_source); + + // + // Get collision direction + // + Vector3D collision_direction(0.0f, 0.0f, 0.0f); + + Check(normalAttributePtr); + collision_direction -= *normalAttributePtr; + Check(&collision_direction); + audio_source->SetPosition(collision_direction); + + // + // Send control value + // + #if 1 + audio_component->ReceiveControl(controlID, controlValue); + #else + audio_component->PostReceiveControl(controlID, controlValue); + #endif + } +} + +// +//############################################################################# +//############################################################################# +// +#if DEBUG_LEVEL>0 +void + L4AudioCollisionTrigger::DumpValue(const StateIndicator *state_attribute_ptr) +#else +void + L4AudioCollisionTrigger::DumpValue(const StateIndicator*) +#endif +{ + // + // Get collision direction + // + Vector3D collision_direction(0.0f, 0.0f, 0.0f); + + Check(normalAttributePtr); + collision_direction -= *normalAttributePtr; + Check(&collision_direction); + + Tell( + "*state_attribute_ptr = " << *state_attribute_ptr << " : " << + "collision_direction = " << collision_direction << "\n" + ); +} diff --git a/MUNGA_L4/L4AUDWTR.h b/MUNGA_L4/L4AUDWTR.h new file mode 100644 index 0000000..dbb9b70 --- /dev/null +++ b/MUNGA_L4/L4AUDWTR.h @@ -0,0 +1,87 @@ +#pragma once + +#include "..\munga\audwthr.h" +#include "l4audio.h" +#include "..\munga\normal.h" + +//########################################################################## +//##################### L4AudioCollisionTrigger ###################### +//########################################################################## + +class L4AudioCollisionTrigger: + public AudioStateWatcher +{ +public: + // + //-------------------------------------------------------------------- + // Constructor, Destructor + //-------------------------------------------------------------------- + // + #if 0 + L4AudioCollisionTrigger( + StateIndicator *state_attribute_ptr, + Normal *normal_attribute_ptr, + Static3DPatchSource *audio_source, + Enumeration trigger_state, + AudioControlID control_ID, + AudioControlValue control_value, + Logical dump_value + ); + #endif + L4AudioCollisionTrigger( + PlugStream *stream, + Entity *entity + ); + ~L4AudioCollisionTrigger(); + + Logical + TestInstance() const; + + // + //-------------------------------------------------------------------- + // BuildFromPage + //-------------------------------------------------------------------- + // +static void + BuildFromPage( + PlugStream *stream, + NameList *name_list, + RegisteredClass::ClassID class_ID, + ObjectID object_ID + ); + +protected: + // + //-------------------------------------------------------------------- + // StateChanged + //-------------------------------------------------------------------- + // + void + StateChanged( + Enumeration old_state, + Enumeration new_state + ); + +private: + // + //----------------------------------------------------------------------- + // DumpValue + //----------------------------------------------------------------------- + // + void + DumpValue(const StateIndicator *state_attribute_ptr); + + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + Normal* + normalAttributePtr; + Enumeration + triggerState; + AudioControlID + controlID; + AudioControlValue + controlValue; +}; diff --git a/MUNGA_L4/L4CTLTUL.cpp b/MUNGA_L4/L4CTLTUL.cpp new file mode 100644 index 0000000..3452309 --- /dev/null +++ b/MUNGA_L4/L4CTLTUL.cpp @@ -0,0 +1,10 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4ctrl.h" +#include "l4tool.h" + +PlatformTool::FindNameFunction L4Tool::GetControlMappingFunction() +{ + return &LBE4ControlsManager::SetControlMappingID; +} \ No newline at end of file diff --git a/MUNGA_L4/L4CTRL.cpp b/MUNGA_L4/L4CTRL.cpp new file mode 100644 index 0000000..3dbd041 --- /dev/null +++ b/MUNGA_L4/L4CTRL.cpp @@ -0,0 +1,2592 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4ctrl.h" +#include "l4keybd.h" +#include "l4app.h" +#include "l4dinput.h" +#include "..\munga\appmgr.h" +#include "dxutils.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) Tell(n << std::flush); +#else +# define Test_Tell(n) +#endif + +static const char *initFileName = "JOYSTICK.INI"; +#define RIO_SPOOL_SIZE 12000 + +//########################################################################### +//########################### Button type table ############################# +//########################################################################### +#define DARKBTN (char) 0 +#define AUTOBTN (char) 1 +#define MAPBTN (char) 2 + +#define DI_TRIGGER 0 +#define DI_THUMB1 2 +#define DI_THUMB2 1 +#define DI_THUMB3 3 +#define DI_THROTTLE 10 + +static char + buttonType[LBE4ControlsManager::ButtonCount] = +{ + AUTOBTN, // ButtonAuxLowerLeft8=0x00 + AUTOBTN, // ButtonAuxLowerLeft7 + AUTOBTN, // ButtonAuxLowerLeft6, + AUTOBTN, // ButtonAuxLowerLeft5, + AUTOBTN, // ButtonAuxLowerLeft4, + AUTOBTN, // ButtonAuxLowerLeft3, + AUTOBTN, // ButtonAuxLowerLeft2, + AUTOBTN, // ButtonAuxLowerLeft1, + + AUTOBTN, // ButtonAuxLowerRight8=0x08 + AUTOBTN, // ButtonAuxLowerRight7, + AUTOBTN, // ButtonAuxLowerRight6, + AUTOBTN, // ButtonAuxLowerRight5, + AUTOBTN, // ButtonAuxLowerRight4, + AUTOBTN, // ButtonAuxLowerRight3, + AUTOBTN, // ButtonAuxLowerRight2, + AUTOBTN, // ButtonAuxLowerRight1, + + AUTOBTN, // ButtonSecondary1=0x10 + AUTOBTN, // ButtonSecondary2, + AUTOBTN, // ButtonSecondary3, + AUTOBTN, // ButtonSecondary4, + AUTOBTN, // ButtonSecondary5, + AUTOBTN, // ButtonSecondary6, + DARKBTN, // + DARKBTN, // + AUTOBTN, // ButtonSecondary7=0x18 + AUTOBTN, // ButtonSecondary8, + AUTOBTN, // ButtonSecondary9, + AUTOBTN, // ButtonSecondary10, + AUTOBTN, // ButtonSecondary11, + AUTOBTN, // ButtonSecondary12, + DARKBTN, // + DARKBTN, // + + AUTOBTN, // ButtonAuxUpperCenter8=0x20 + AUTOBTN, // ButtonAuxUpperCenter7, + AUTOBTN, // ButtonAuxUpperCenter6, + AUTOBTN, // ButtonAuxUpperCenter5, + AUTOBTN, // ButtonAuxUpperCenter4, + AUTOBTN, // ButtonAuxUpperCenter3, + AUTOBTN, // ButtonAuxUpperCenter2, + AUTOBTN, // ButtonAuxUpperCenter1, + + AUTOBTN, // ButtonAuxUpperLeft8=0x28 + AUTOBTN, // ButtonAuxUpperLeft7, + AUTOBTN, // ButtonAuxUpperLeft6, + AUTOBTN, // ButtonAuxUpperLeft5, + AUTOBTN, // ButtonAuxUpperLeft4, + AUTOBTN, // ButtonAuxUpperLeft3, + AUTOBTN, // ButtonAuxUpperLeft2, + AUTOBTN, // ButtonAuxUpperLeft1, + + AUTOBTN, // ButtonAuxUpperRight8=0x30 + AUTOBTN, // ButtonAuxUpperRight7, + AUTOBTN, // ButtonAuxUpperRight6, + AUTOBTN, // ButtonAuxUpperRight5, + AUTOBTN, // ButtonAuxUpperRight4, + AUTOBTN, // ButtonAuxUpperRight3, + AUTOBTN, // ButtonAuxUpperRight2, + AUTOBTN, // ButtonAuxUpperRight1, + + AUTOBTN, // ButtonPanic=0x38, + DARKBTN, // + DARKBTN, // + DARKBTN, // + DARKBTN, // ButtonDoor=0x3C, + DARKBTN, // + DARKBTN, // + + DARKBTN, // ButtonThrottle1=0x3F, + MAPBTN, // ButtonJoystickTrigger=0x40 + MAPBTN, // ButtonJoystickHatDown=0x41 + MAPBTN, // ButtonJoystickHatUp=0x42 + MAPBTN, // ButtonJoystickHatRight=0x43 + MAPBTN, // ButtonJoystickHatLeft=0x44 + MAPBTN, // ButtonJoystickPinky=0x45 + MAPBTN, // ButtonJoystickThumbLow=0x46 + MAPBTN // ButtonJoystickThumbHigh=0x47 +}; + +//########################################################################### +//############################ Joystick classes ############################# +//########################################################################### +Joystick::Joystick() +{ + NotationFile + init(initFileName); + + channel[0] = new FilterChannel( + &init, + FilterChannel::joystickXName, + 10,20,30 // bogus values in case file didn't previously exist + ); + Check(channel[0]); + + channel[1] = new FilterChannel( + &init, + FilterChannel::joystickYName, + 10,20,30 // bogus values in case file didn't previously exist + ); + Check(channel[1]); + + ButtonReleased = Joystick::NoButton; + ButtonPressed = Joystick::NoButton; + Check_Fpu(); +} + +Joystick::~Joystick() +{ + Check(this); + + NotationFile + init(initFileName); + + //------------------------------------------- + // Save DOS timestamp + //------------------------------------------- + time_t + dos_time; + time(&dos_time); + init.SetEntry("operator", "time", ctime(&dos_time)); + + for(int i=0; i<2; ++i) + { + Check(channel[i]); + delete channel[i]; + channel[i] = NULL; + } + Check_Fpu(); +} + +void + Joystick::BeginAlignment() +{ + Check(this); + for(int i=0; i<2; ++i) + { + Check(channel[i]); + channel[i]->BeginAlignment(); + } + Check_Fpu(); +} + +void + Joystick::EndAlignment() +{ + Check(this); + //------------------------------------------------------------ + // If channel was never adjusted, synthesize reasonable values + //------------------------------------------------------------ + NotationFile + init(initFileName); + EndAndSaveAlignment(&init); + + Check_Fpu(); +} + +void + Joystick::EndAndSaveAlignment(NotationFile *init_file) +{ + Check(this); + Check(init_file); + for(int i=0; i<2; ++i) + { + Check(channel[i]); + channel[i]->EndAlignment(init_file); + } + Check_Fpu(); +} + +void + Joystick::Update() +{ + Fail("Joystick::Update should not be called!\n"); +} + +void + Joystick::SetDeadBand(Scalar dead_band) +{ + Check(this); + for(int i=0; i<2; ++i) + { + Check(channel[i]); + channel[i]->SetDeadBand(dead_band); + } + Check_Fpu(); +} + +OrdinaryJoystick::OrdinaryJoystick() +{ + //STUBBED: JOYSTICK RB 1/14/07 + //PC_Joystick_Mask = PCJ_Standard_Mask; + //ExtendedValue.x = (Scalar) 0; + //ExtendedValue.y = (Scalar) 0; + //Check_Fpu(); +} + +OrdinaryJoystick::~OrdinaryJoystick() +{ + Check_Fpu(); +} + +void OrdinaryJoystick::Update() +{ + //STUBBED: JOYSTICK RB 1/14/07 + //int newButtons, changedButtons; + + //Check(this); + //// + ////--------------------------------------------------- + //// Update analog values + ////--------------------------------------------------- + //// + //PC_Joystick_Update(); + //Check(channel[0]); + //Value.x = channel[0]->Update(PC_Joystick1_Raw_X); + //Check(channel[1]); + //Value.y = channel[1]->Update(PC_Joystick1_Raw_Y); + //// + ////--------------------------------------------------- + //// Handle button changes + ////--------------------------------------------------- + //// + //newButtons = (int) PC_Joystick_Buttons; + //changedButtons = newButtons ^ oldButtons; + + //ButtonPressed = Joystick::NoButton; + //ButtonReleased = Joystick::NoButton; + + //if (changedButtons) + //{ + // if (changedButtons & PCJ_Standard_Button1) + // { + // if (newButtons & PCJ_Standard_Button1) + // { + // ButtonPressed |= Joystick::Trigger; + // } + // else + // { + // ButtonReleased |= Joystick::Trigger; + // } + // } + // if (changedButtons & PCJ_Standard_Button2) + // { + // if (newButtons & PCJ_Standard_Button2) + // { + // ButtonPressed |= Joystick::Thumb3; + // } + // else + // { + // ButtonReleased |= Joystick::Thumb3; + // } + // } + //} + //oldButtons = newButtons; + //Check_Fpu(); +} + +Logical + Joystick::TestInstance() const +{ + return True; +} + +FlightStickPro::FlightStickPro() +{ + //STUBBED: JOYSTICK RB 1/14/07 + //NotationFile + // init(initFileName); + + //throttle = new FilterChannel( + // &init, + // FilterChannel::throttleName, + // 10,30 // bogus values in case file doesn't exist + //); + + //Check(throttle); + + //PC_Joystick_Mask = PCJ_FSP_Mask; + //ExtendedValue.x = (Scalar) 0; + //Check_Fpu(); +} + +FlightStickPro::~FlightStickPro() +{ + Check(this); + + NotationFile + init(initFileName); + //------------------------------------------- + // Save DOS timestamp + //------------------------------------------- + time_t + dos_time; + time(&dos_time); + init.SetEntry("operator", "time", ctime(&dos_time)); + + Check(throttle); + delete throttle; + throttle = NULL; + + Check_Fpu(); +} + +void FlightStickPro::Update() +{ + //STUBBED: JOYSTICK RB 1/14/07 + //int newButtons; + + //Check(this); + //// + ////--------------------------------------------------- + //// Update analog values + ////--------------------------------------------------- + //// + //PC_Joystick_Update(); + //Check(channel[0]); + //Value.x = channel[0]->Update(PC_Joystick1_Raw_X); + //Check(channel[1]); + //Value.y = channel[1]->Update(PC_Joystick1_Raw_Y); + + //// Note inverted direction (below) for throttle + + //Check(throttle); + //ExtendedValue.y = 1.0 - throttle->Update(PC_Joystick2_Raw_Y); + //// + ////--------------------------------------------------- + //// Handle button changes + ////--------------------------------------------------- + //// + //newButtons = int (PC_Joystick_Buttons); + + //ButtonPressed = Joystick::NoButton; + //ButtonReleased = Joystick::NoButton; + + //if (newButtons != oldButtons) + //{ + // switch(oldButtons) + // { + // case PCJ_FSP_Up: ButtonReleased = Joystick::HatUp; break; + // case PCJ_FSP_Down: ButtonReleased = Joystick::HatDown; break; + // case PCJ_FSP_Left: ButtonReleased = Joystick::HatLeft; break; + // case PCJ_FSP_Right: ButtonReleased = Joystick::HatRight; break; + // case PCJ_FSP_Trigger: ButtonReleased = Joystick::Trigger; break; + // case PCJ_FSP_LButton: ButtonReleased = Joystick::Thumb3; break; + // case PCJ_FSP_RButton: ButtonReleased = Joystick::Thumb1; break; + // case PCJ_FSP_CButton: ButtonReleased = Joystick::Thumb2; break; + // } + // switch(newButtons) + // { + // case PCJ_FSP_Up: ButtonPressed = Joystick::HatUp; break; + // case PCJ_FSP_Down: ButtonPressed = Joystick::HatDown; break; + // case PCJ_FSP_Left: ButtonPressed = Joystick::HatLeft; break; + // case PCJ_FSP_Right: ButtonPressed = Joystick::HatRight; break; + // case PCJ_FSP_Trigger: ButtonPressed = Joystick::Trigger; break; + // case PCJ_FSP_LButton: ButtonPressed = Joystick::Thumb3; break; + // case PCJ_FSP_RButton: ButtonPressed = Joystick::Thumb1; break; + // case PCJ_FSP_CButton: ButtonPressed = Joystick::Thumb2; break; + // } + // oldButtons = newButtons; + //} + //Check_Fpu(); +} + +void + FlightStickPro::BeginAlignment() +{ + Check(this); + Check(throttle); + throttle->BeginAlignment(); + + Joystick::BeginAlignment(); + Check_Fpu(); +} + +void + FlightStickPro::EndAlignment() +{ + Check(this); + + NotationFile + init(initFileName); + + Check(throttle); + throttle->EndAlignment(&init); + + Joystick::EndAndSaveAlignment(&init); + + Check_Fpu(); +} + +BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) +{ + ThrustMaster *joystick = (ThrustMaster*)pContext; + if (FAILED(joystick->mDI->CreateDevice(pdidInstance->guidInstance, &joystick->mJoystick, NULL))) + return DIENUM_CONTINUE; + + return DIENUM_STOP; +} + +BOOL CALLBACK EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) +{ + ThrustMaster *joystick = (ThrustMaster*)pvRef; + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = lpddoi->dwType; + diprg.lMax = diprg.lMax = 0; + + if (lpddoi->guidType == GUID_XAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->xAxisMin = diprg.lMin; + joystick->xAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_YAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->yAxisMin = diprg.lMin; + joystick->yAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_ZAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->zAxisMin = diprg.lMin; + joystick->zAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_RxAxis) + { + } + else if (lpddoi->guidType == GUID_RyAxis) + { + } + else if (lpddoi->guidType == GUID_RzAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->rzAxisMin = diprg.lMin; + joystick->rzAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_Slider) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->zAxisMin = diprg.lMin; + joystick->zAxisMax = diprg.lMax; + } + } + + return DIENUM_CONTINUE; +} + +ThrustMaster::ThrustMaster(HINSTANCE hInstance, HWND hWnd) +{ + //STUBBED: JOYSTICK RB 1/14/07 + ExtendedValue.x = (Scalar) 0; + ExtendedValue.y = (Scalar) 0; + hatMax = 0; + prevHatState = 0; + + mDI = NULL; + mJoystick = NULL; + + if (SUCCEEDED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&mDI, NULL))) + { + mDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, DIEDFL_ATTACHEDONLY); + if (mJoystick) + if (SUCCEEDED(mJoystick->SetDataFormat(&c_dfDIJoystick2))) + if (SUCCEEDED(mJoystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND))) + if (SUCCEEDED(mJoystick->EnumObjects(EnumAxesCallback, this, DIDFT_AXIS))) + return; + } + + if (mDI) + { + mDI->Release(); + mDI = NULL; + } + if (mJoystick) + { + mJoystick->Release(); + mJoystick = NULL; + } +} + +ThrustMaster::~ThrustMaster() +{ + Check_Fpu(); +} + +bool ThrustMaster::Poll() +{ + HRESULT hr; + if (mJoystick) + { + V( mJoystick->Poll() ); + if (FAILED(hr)) + { + V( mJoystick->Acquire() ); + while (hr == DIERR_INPUTLOST) + V( mJoystick->Acquire() ); + return false; + } + + V( mJoystick->GetDeviceState(sizeof(DIJOYSTATE2), &mJoystate) ); + if (FAILED(hr)) + return false; + } + + return true; +} + +void ThrustMaster::Update() +{ + if (!Poll()) + return; + + // + //--------------------------------------------------- + // Update analog values + //--------------------------------------------------- + // + Value.x = ((Scalar)(mJoystate.lX - xAxisMin) / (Scalar)(xAxisMax - xAxisMin)) * 2.0f - 1.0f; + Value.y = ((Scalar)(mJoystate.lY - yAxisMin) / (Scalar)(yAxisMax - yAxisMin)) * 2.0f - 1.0f; + LONG z = (mJoystate.lZ == 0 ? mJoystate.rglSlider[0] : mJoystate.lZ); + ExtendedValue.y = 1.0f - (Scalar)(z - zAxisMin) / (Scalar)(zAxisMax - zAxisMin); + // full left rotation = 0, center rotation = 1/2 range, full right = full range + LONG rot = (Scalar)(mJoystate.lRz - rzAxisMin); + Scalar half = (Scalar)(rzAxisMax - rzAxisMin) / 2.0f; + Rotation.x = (Scalar)0; + Rotation.y = (Scalar)0; + if (rot <= half) + Rotation.x = ((half - rot) / half) * 470.0; + else + Rotation.y = ((rot - half) / half) * 470.0; + + // + //--------------------------------------------------- + // Handle button changes + //--------------------------------------------------- + // + ButtonPressed = Joystick::NoButton; + ButtonReleased = Joystick::NoButton; + + int newButtons = 0; + if (mJoystate.rgbButtons[DI_TRIGGER]) + newButtons |= Joystick::Trigger; + if (mJoystate.rgbButtons[DI_THUMB1]) + newButtons |= Joystick::Thumb1; + if (mJoystate.rgbButtons[DI_THUMB2]) + newButtons |= Joystick::Thumb2; + if (mJoystate.rgbButtons[DI_THUMB3]) + newButtons |= Joystick::Thumb3; + if (mJoystate.rgbButtons[DI_THROTTLE]) + newButtons |= Joystick::Throttle; + if (mJoystate.rgdwPOV[0] == 0) + newButtons |= Joystick::HatUp; + if (mJoystate.rgdwPOV[0] == 9000) + newButtons |= Joystick::HatRight; + if (mJoystate.rgdwPOV[0] == 18000) + newButtons |= Joystick::HatDown; + if (mJoystate.rgdwPOV[0] == 27000) + newButtons |= Joystick::HatLeft; + + ButtonPressed = (oldButtons ^ newButtons) & newButtons; + ButtonReleased = (oldButtons ^ newButtons) & oldButtons; + oldButtons = newButtons; +} + + +//######################################################################### +//########################## LBE4ControlsManager ########################## +//######################################################################### + +//--------------------------------------------------------------------------- +// Class derivation +//--------------------------------------------------------------------------- +Derivation* LBE4ControlsManager::GetClassDerivations() +{ + static Derivation classDerivations(ControlsManager::GetClassDerivations(), "L4ControlsManager"); + return &classDerivations; +} + +//--------------------------------------------------------------------------- +// Message support +//--------------------------------------------------------------------------- +//const Receiver::HandlerEntry +// LBE4ControlsManager::MessageHandlerEntries[]= +//{ +// MESSAGE_ENTRY(LBE4ControlsManager,BeginCalibration), +// MESSAGE_ENTRY(LBE4ControlsManager,EndCalibration) +//}; +// +//Receiver::MessageHandlerSet +// LBE4ControlsManager::MessageHandlers( +// ELEMENTS(LBE4ControlsManager::MessageHandlerEntries), +// LBE4ControlsManager::MessageHandlerEntries, +// ControlsManager::MessageHandlers +// ); +//--------------------------------------------------------------------------- +// Shared data +//--------------------------------------------------------------------------- +LBE4ControlsManager::SharedData + LBE4ControlsManager::DefaultData( + LBE4ControlsManager::GetClassDerivations(), + LBE4ControlsManager::GetMessageHandlers() + ); +// +//############################################################################ +// LBE4ControlsManager +// +// Creator method +//---------------------------------------------------------------------------- +// Enter: virtualDataPtr +//############################################################################ +// +LBE4ControlsManager::LBE4ControlsManager(): + ControlsManager(L4ControlsManagerClassID, DefaultData) +{ + Check_Pointer(this); + // + //------------------------------------------------------------------------- + // configure + //------------------------------------------------------------------------- + // + flags.mouseExists = 0; + flags.keyboardExists = 0; + flags.joystickExists = 0; + flags.RIOExists = 0; + + virtualJoystickX = 0; + virtualJoystickY = 0; + + lastJoystickUpdate = 0.0f; + joystickType = LBE4ControlsManager::none; + + mousePointer = NULL; + joystickPointer = NULL; + rioPointer = NULL; + lastRioRequest = 0L; + primaryControlType = LBE4ControlsManager::None; + + char *controlString = getenv("L4CONTROLS"); + + if (controlString != NULL) + { + // + //------------------------------------------------- + // parse environment variable, build configuration + //------------------------------------------------- + // + char + temp[128]; + char + *dest; + char + c; + int + noMore(0); + + do + { + // + // Get the next token + // Can't use strtok(), because RIO::RIO uses it, + // and it's not re-entrant. + // + + dest = temp; + if (noMore) + { + *dest = '\0'; + } + else + { + do + { + switch(c=*controlString++) + { + case '\0': + case '\n': + noMore = 1; + // deliberately falls through into next case + + case ',': + case ';': + c = '\0'; + // deliberately falls through into default case + + default: + *dest++=c; + break; + } + } + while (c != '\0'); + } + + //Win32 Serial support: ADB 06/30/07 + if(strncmp(temp, "RIO", 3) == 0) + { + if(strncmp(temp, "RIO:COM", 7) == 0) + { + int l = strlen(temp+4) + 5; + char* comm = new char[l]; + strcpy(comm, "\\\\.\\"); + strcpy(comm+4, temp+4); + rioPointer = new RIO(comm);//temp + 4); + Check(rioPointer); + Register_Object(rioPointer); + flags.RIOExists = 1; + primaryControlType = LBE4ControlsManager::PrimaryRIO; + delete comm; + } + else + { + rioPointer = new RIO("COM1"); + Check(rioPointer); + Register_Object(rioPointer); + flags.RIOExists = 1; + primaryControlType = LBE4ControlsManager::PrimaryRIO; + } + } + else if (strcmpi(temp, "KEYBOARD") == 0) + { + flags.keyboardExists = 1; + } + else if (strcmpi(temp, "MOUSE") == 0) + { + if (!flags.mouseExists) + { + flags.mouseExists = 1; + mousePointer = new Mouse; + Check(mousePointer); + Register_Object(mousePointer); + if (mousePointer->Errors) + { + Unregister_Object(mousePointer); + delete mousePointer; + mousePointer = NULL; + flags.mouseExists = 0; + } else + { + primaryControlType = LBE4ControlsManager::PrimaryThrustMaster; + } + } + } + else if (strcmpi(temp, "JOYSTICK") == 0) + { + flags.joystickExists = 1; + joystickType = LBE4ControlsManager::ordinary; + joystickPointer = new OrdinaryJoystick(); + Register_Object(joystickPointer); + primaryControlType = LBE4ControlsManager::PrimaryGenericJoystick; + } + else if (strcmpi(temp, "FLIGHTSTICKPRO") == 0) + { + flags.joystickExists = 1; + joystickType = LBE4ControlsManager::flightstickPro; + joystickPointer = new FlightStickPro(); + Register_Object(joystickPointer); + primaryControlType = LBE4ControlsManager::PrimaryFlightStickPro; + } + else if (strcmpi(temp, "THRUSTMASTER") == 0) + { + flags.joystickExists = 1; + joystickType = LBE4ControlsManager::thrustMaster; + joystickPointer = new ThrustMaster(ApplicationManager::GetCurrentManager()->GetHInstance(), ApplicationManager::GetCurrentManager()->GetHWnd()); + Register_Object(joystickPointer); + primaryControlType = LBE4ControlsManager::PrimaryThrustMaster; + } + else if (strcmpi(temp, "DIJOYSTICK") == 0) + { + joystickPointer = new DIJoystick(ApplicationManager::GetCurrentManager()->GetHInstance(), ApplicationManager::GetCurrentManager()->GetHWnd()); + if (((DIJoystick*)joystickPointer)->IsValid()) + { + flags.joystickExists = 1; + joystickType = LBE4ControlsManager::directInputJoystick; + Register_Object(joystickPointer); + primaryControlType = LBE4ControlsManager::PrimaryThrustMaster; + } + else + { + delete joystickPointer; + joystickPointer = NULL; + } + } + } + while (temp[0] != '\0'); + } + + //-------------------------------------------------- + // Clear all lamps (and reset analog I/O) + //-------------------------------------------------- + if (rioPointer != NULL) + { + Check(rioPointer); + rioPointer->GeneralReset(); + } + //-------------------------------------------------- + // Get mode mask for updating + //-------------------------------------------------- + Check(application); + Check(application->GetModeManager()); + ModeMask + mode_mask = application->GetModeManager()->GetModeMask(); + //-------------------------------------------------- + // Initialize scalar group + //-------------------------------------------------- + { + int + i; + ControlsScalar + initial_scalar = 0.0; + + for(i=0; iRewind(); + RIOStreamEvent + *start = (RIOStreamEvent*)rioStream->GetPointer(); + + Unregister_Object(rioStream); + delete rioStream; + + Unregister_Pointer(start); + delete[] start; + + rioStream = NULL; + streamEnabled = False; + } + + //-------------------------------------------------- + // Delete mouse + //-------------------------------------------------- + if (mousePointer != NULL) + { + Check(mousePointer); + Unregister_Object(mousePointer); + delete mousePointer; + mousePointer = NULL; + } + //-------------------------------------------------- + // Delete joystick + //-------------------------------------------------- + if (joystickPointer != NULL) + { + Check(joystickPointer); + Unregister_Object(joystickPointer); + delete joystickPointer; + joystickPointer = NULL; + } + //-------------------------------------------------- + // Delete string manager temporary groups + //-------------------------------------------------- + ExitControlsMode(); + //-------------------------------------------------- + // Delete RIO AFTER buttons! + // ...the 'autoManager' button class sends + // lamp commands when deleted. + //-------------------------------------------------- + if (rioPointer != NULL) + { + Check(rioPointer); + Unregister_Object(rioPointer); + delete rioPointer; + rioPointer = NULL; + } + + Check_Fpu(); +} + +// +//############################################################################# +// LocalShutdown +//############################################################################# +// +void + LBE4ControlsManager::LocalShutdown() +{ + Check_Pointer(this); + + if (rioPointer != NULL) + { + Check(rioPointer); + Unregister_Object(rioPointer); + delete rioPointer; + + rioPointer = NULL; + } + + ControlsManager::LocalShutdown(); + Check_Fpu(); +} + +// +//############################################################################ +// Remove +// +// Remove all controlsInstance records bearing the given ID +//############################################################################ +// +void + LBE4ControlsManager::Remove(ModeMask mode_mask) +{ + int i; + + Check(this); + for(i=0; i= 0); + Verify(lamp_number < LBE4ControlsManager::LampCount); + + rioPointer->SetLamp(lamp_number, (RIO::LampState) state); + } + Check_Fpu(); +} + +// +//############################################################################ +// Execute +// +// Execution method +//############################################################################ +// +void + LBE4ControlsManager::Execute() +{ + ControlsJoystick virtual_joystick; + ControlsKey keyValue; + ControlsMouse mouseValue; + static Scalar mouseWheel = 0.0; + Logical new_RIO_values(False); + Logical mouseMoved = false; + Logical mouseWheelMoved = false; + static int oldX = 0; + static int oldY = 0; + + Check(this); + //-------------------------------------------------- + // Get mode mask for updating + //-------------------------------------------------- + Check(application); + Check(application->GetModeManager()); + ModeMask + mode_mask = application->GetModeManager()->GetModeMask(); + //------------------------------------------------------------------------- + // Process operator control mode + //------------------------------------------------------------------------- + // ManageControlsMode(); + + //------------------------------------------------------------------------- + // Process RIO + //------------------------------------------------------------------------- + if (flags.RIOExists) + { + Check(rioPointer); + + RIO::RIOEvent rio_event; + // + //------------------------------------ + // Request analog update + // (held down to 5 Hz unless reply + // is received: reply allows another + // request to be sent next invocation) + //------------------------------------ + // + if (!playbackMode) + { + //Scalar + // delta_t(Now() - lastRioRequest); + //Scalar + // limit; + //static Logical + // first_time = True; + + //ADB 10/01/07 + static DWORD last_check = GetTickCount(); + DWORD limit = 15000; + + if(application->GetApplicationState() == Application::RunningMission) + { + //Posible Bug: ADB 03/30/07 + //limit = 15.0; // 0.2 + limit = 50;//reduced to improve responsiveness + } + //else + //{ + // //limit = 15.0; + // limit = 15000; + //} + + //if (first_time) + //{ + // first_time = False; + //} + //else + { + DWORD this_check = GetTickCount(); + //if(this_check - last_check >= 1000) + //DEBUG_STREAM << "No Request in " << (this_check - last_check) << "ms." << std::endl << std::flush; + + if((this_check - last_check) >= limit) + //if (delta_t >= limit) // 5 Hz minimum rate, in case of no reply + { + //------------------------- + // Debugging aid + //------------------------- + //long time_in_ticks; + + //time_in_ticks = lastRioRequest; + //if (time_in_ticks != 0L) + //{ + // DEBUG_STREAM << "LBE4ControlsManager::Execute, lost RIO analog request\n"; + + //STUBBED: JOYSTICK RB 1/14/07 + /*extern Logical + iThinkIRQIsOn; + + extern int + pcspakCharactersSent; + + DEBUG_STREAM << + "iThinkIRQIsOn =" << iThinkIRQIsOn << + ", actual state =" << PCSPAKIRQState() << + ", characters sent =" << pcspakCharactersSent << "\n";*/ + //} + + rioPointer->RequestAnalogUpdate(); + //lastRioRequest = Now(); + last_check = this_check; + } + //------------------------- + // Debugging aid + //------------------------- + //else if (delta_t < 0.0) + //{ + // DEBUG_STREAM << + // "LBE4ControlsManager::Execute, delta_t went negative (" << + // delta_t << ")\n"; + + // rioPointer->RequestAnalogUpdate(); + // lastRioRequest = Now(); + //} + } + } + + // + //------------------------------------ + // Process events + //------------------------------------ + // + while (GetNextRIOEvent(&rio_event)) + { + ProcessRIOEvent(rio_event, &new_RIO_values); + } + } + + // + //------------------------------------------------------------------------- + // Read physical joystick inputs, filter the values + //------------------------------------------------------------------------- + // + if (flags.joystickExists) + { + Scalar delta_t = (Scalar)Now() - lastJoystickUpdate; + + if (delta_t > .05) + { + Check(joystickPointer); + joystickPointer->Update(); + joystickPointer->Value.x = -joystickPointer->Value.x; // HACK!!! + + lastJoystickUpdate = Now(); + } + } + + // + //------------------------------------------------------------------------- + // Read physical mouse inputs, generate virtual joystick values + //------------------------------------------------------------------------- + // + if (flags.mouseExists) + { + Check(mousePointer); + //OLD WAY: mousePointer->ReadCounters(&mouseValue.x, &mouseValue.y); + //NEW WAY + /*MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (msg.message == WM_MOUSEMOVE) + { + mouseMoved = true; + + GetMessage(&msg, NULL, 0, 0); + int x = (msg.lParam & 0xFFFF); + int y = (msg.lParam & 0xFFFF0000) >> 16; + mouseValue.x = x - oldX; + mouseValue.y = y - oldY; + oldX = x; + oldY = y; + + virtualJoystickX += mouseValue.x; + virtualJoystickY += mouseValue.y; + + #define MAXEXTENT 400 // This is a guess. We'll have to try it and see. + + if (virtualJoystickX > MAXEXTENT) { virtualJoystickX = MAXEXTENT; } + if (virtualJoystickX < -MAXEXTENT) { virtualJoystickX = -MAXEXTENT; } + virtual_joystick.x = (Scalar) virtualJoystickX / (Scalar) MAXEXTENT; + + if (virtualJoystickY > MAXEXTENT) { virtualJoystickY = MAXEXTENT; } + if (virtualJoystickY < -MAXEXTENT) { virtualJoystickY = -MAXEXTENT; } + virtual_joystick.y = (Scalar) virtualJoystickY / (Scalar) MAXEXTENT; + }*/ + //else if (msg.message == 0x020A /*WM_MOUSEWHEEL*/) + /*{ + #define MAXEXTENT 1200.0f // Just a guess + + mouseWheelMoved = true; + GetMessage(&msg, NULL, 0, 0); + //mouseWheel = (signed int)((msg.wParam & 0xFFFF0000) >> 16) * 1.0f; + int delta = (mouseWheel * MAXEXTENT) + ((short)HIWORD(msg.wParam)); + + if (delta > MAXEXTENT) + delta = MAXEXTENT; + if (delta < 0.0f) + delta = 0.0f; + + mouseWheel = delta / MAXEXTENT; + } + }*/ + } + + // + //------------------------------------------------------------------------- + // Update the scalar mapping groups using the analog values + //------------------------------------------------------------------------- + // + if (flags.RIOExists && new_RIO_values) + { + Check(rioPointer); + + Check(&scalarGroup[LBE4ControlsManager::ScalarThrottle]); + scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( + &rioPointer->Throttle, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarLeftPedal]); + scalarGroup[LBE4ControlsManager::ScalarLeftPedal].Update( + &rioPointer->LeftPedal, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarRightPedal]); + scalarGroup[LBE4ControlsManager::ScalarRightPedal].Update( + &rioPointer->RightPedal, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickX]); + scalarGroup[LBE4ControlsManager::ScalarJoystickX].Update( + &rioPointer->JoystickX, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickY]); + scalarGroup[LBE4ControlsManager::ScalarJoystickY].Update( + &rioPointer->JoystickY, mode_mask + ); + } + else if (flags.joystickExists) + { + scalarGroup[LBE4ControlsManager::ScalarLeftPedal].Update( + &joystickPointer->Rotation.x, mode_mask + ); + + scalarGroup[LBE4ControlsManager::ScalarRightPedal].Update( + &joystickPointer->Rotation.y, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarThrottle]); + scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( + &joystickPointer->ExtendedValue.y, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickX]); + scalarGroup[LBE4ControlsManager::ScalarJoystickX].Update( + &joystickPointer->Value.x, mode_mask + ); + + Check(&scalarGroup[LBE4ControlsManager::ScalarJoystickY]); + scalarGroup[LBE4ControlsManager::ScalarJoystickY].Update( + &joystickPointer->Value.y, mode_mask + ); + } + + if (flags.mouseExists) + { + if (mouseMoved) + { + Check(&scalarGroup[LBE4ControlsManager::ScalarMouseX]); + scalarGroup[LBE4ControlsManager::ScalarMouseX].Update( + &virtual_joystick.x, mode_mask + ); + Check(&scalarGroup[LBE4ControlsManager::ScalarMouseY]); + scalarGroup[LBE4ControlsManager::ScalarMouseY].Update( + &virtual_joystick.y, mode_mask + ); + } + else + { + Scalar clear = 0; + scalarGroup[LBE4ControlsManager::ScalarMouseX].Update(&clear, mode_mask); + scalarGroup[LBE4ControlsManager::ScalarMouseY].Update(&clear, mode_mask); + } + if (mouseWheelMoved) + { + scalarGroup[LBE4ControlsManager::ScalarThrottle].Update( + &mouseWheel, mode_mask + ); + } + } + + // + //------------------------------------------------------------------------- + // Update the joystick mapping groups using the analog values + //------------------------------------------------------------------------- + // + if (flags.RIOExists && new_RIO_values) + { + Check(rioPointer); + + ControlsJoystick + stick; + + stick.x = rioPointer->JoystickX; + stick.y = rioPointer->JoystickY; + + Check(&joystickGroup[LBE4ControlsManager::JoystickPhysical]); + joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( + &stick, mode_mask + ); + } + else if (flags.joystickExists) + { + Check(&joystickGroup[LBE4ControlsManager::JoystickPhysical]); + joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( + &joystickPointer->Value, mode_mask + ); + } + + if (flags.mouseExists && mouseMoved) + { + Check(&joystickGroup[LBE4ControlsManager::JoystickVirtual]); + /*joystickGroup[LBE4ControlsManager::JoystickVirtual].Update( + &virtual_joystick, mode_mask + );*/ + joystickGroup[LBE4ControlsManager::JoystickPhysical].Update( + &virtual_joystick, mode_mask + ); + } + + // + //------------------------------------------------------------------------- + // Update the PC keyboard mapping group + //------------------------------------------------------------------------- + // + if (flags.keyboardExists) + { + //RB 1/20/07 + //keyValue = (ControlsKey) PC_Keyboard_Read(); + MSG msg; + if (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) + { + if (msg.message == WM_SYSKEYUP || msg.message == WM_KEYUP || msg.message == WM_CHAR) + { + GetMessage(&msg, NULL, 0, 0); + TranslateMessage(&msg); + keyValue = (msg.wParam & VK_MASK); + if (msg.message == WM_SYSKEYUP) + keyValue |= ALT_BIT; + keyboardGroup[KeyboardPC].ForceUpdate(&keyValue, mode_mask); + stringManager.Update(KeyboardPC, keyValue); + } + } + } + + // + //------------------------------------------------------------------------- + // Update the button mapping groups + //------------------------------------------------------------------------- + // + + // + //-------------------------- + // Joystick buttons + //-------------------------- + // + if (flags.joystickExists) + { + int i; + ControlsButton b; + + Check(joystickPointer); + + i = joystickPointer->ButtonReleased; + if(i != Joystick::NoButton) + { + if (i & Joystick::Trigger) + { + b = - ButtonJoystickTrigger - 1; + buttonGroup[ButtonJoystickTrigger].Update(&b, mode_mask); + } + if (i & Joystick::Thumb1) + { + b = - ButtonJoystickPinky - 1; + buttonGroup[ButtonJoystickPinky].Update(&b, mode_mask); + } + if (i & Joystick::Thumb2) + { + b = - ButtonJoystickThumbLow - 1; + buttonGroup[ButtonJoystickThumbLow].Update(&b, mode_mask); + } + if (i & Joystick::Thumb3) + { + b = - ButtonJoystickThumbHigh - 1; + buttonGroup[ButtonJoystickThumbHigh].Update(&b, mode_mask); + } + if (i & Joystick::Throttle) + { + b = - ButtonThrottle1 - 1; + buttonGroup[ButtonThrottle1].Update(&b, mode_mask); + } + if (i & Joystick::HatUp) + { + b = - ButtonJoystickHatUp - 1; + buttonGroup[ButtonJoystickHatUp].Update(&b, mode_mask); + } + if (i & Joystick::HatDown) + { + b = - ButtonJoystickHatDown - 1; + buttonGroup[ButtonJoystickHatDown].Update(&b, mode_mask); + } + if (i & Joystick::HatLeft) + { + b = - ButtonJoystickHatLeft - 1; + buttonGroup[ButtonJoystickHatLeft].Update(&b, mode_mask); + } + if (i & Joystick::HatRight) + { + b = - ButtonJoystickHatRight - 1; + buttonGroup[ButtonJoystickHatRight].Update(&b, mode_mask); + } + } + + i = joystickPointer->ButtonPressed; + if(i != Joystick::NoButton) + { + if (i & Joystick::Trigger) + { + b = ButtonJoystickTrigger + 1; + buttonGroup[ButtonJoystickTrigger].Update(&b, mode_mask); + } + if (i & Joystick::Thumb1) + { + b = ButtonJoystickPinky + 1; + buttonGroup[ButtonJoystickPinky].Update(&b, mode_mask); + } + if (i & Joystick::Thumb2) + { + b = ButtonJoystickThumbLow + 1; + buttonGroup[ButtonJoystickThumbLow].Update(&b, mode_mask); + } + if (i & Joystick::Thumb3) + { + b = ButtonJoystickThumbHigh + 1; + buttonGroup[ButtonJoystickThumbHigh].Update(&b, mode_mask); + } + if (i & Joystick::Throttle) + { + b = ButtonThrottle1 - 1; + buttonGroup[ButtonThrottle1].Update(&b, mode_mask); + } + if (i & Joystick::HatUp) + { + b = ButtonJoystickHatUp + 1; + buttonGroup[ButtonJoystickHatUp].Update(&b, mode_mask); + } + if (i & Joystick::HatDown) + { + b = ButtonJoystickHatDown + 1; + buttonGroup[ButtonJoystickHatDown].Update(&b, mode_mask); + } + if (i & Joystick::HatLeft) + { + b = ButtonJoystickHatLeft + 1; + buttonGroup[ButtonJoystickHatLeft].Update(&b, mode_mask); + } + if (i & Joystick::HatRight) + { + b = ButtonJoystickHatRight + 1; + buttonGroup[ButtonJoystickHatRight].Update(&b, mode_mask); + } + } + } + + // + //-------------------------- + // Mouse buttons + //-------------------------- + // + if (flags.mouseExists) + { + int i, j, k; + ControlsButton b; + + k = mousePointer->ButtonCount; + + for(i=0, j=LBE4ControlsManager::ButtonMouseLeft; iButtonPressed(i)) + { + b = (ControlsButton) (j+1); + buttonGroup[j].Update(&b, mode_mask); + } + + if (mousePointer->ButtonReleased(i)) + { + b = (ControlsButton) (-j-1); + buttonGroup[j].Update(&b, mode_mask); + } + } + // + //------------------------------------------------------------------------- + // Update the mouse mapping group + //------------------------------------------------------------------------- + // + mouseGroup[0].Update(&mouseValue, mode_mask); + } + + // Tell("LBE4ControlsManager::Execute ends\n" << std::flush); + Check_Fpu(); +} + +// +//############################################################################ +// BeginAlignJoystick +// +// Start alignment process for joystick and analog inputs +//############################################################################ +// +void + LBE4ControlsManager::BeginAlignJoystick() +{ + Check(this); + + if (flags.joystickExists) + { + Check(joystickPointer); + joystickPointer->BeginAlignment(); + } + Check_Fpu(); +} + +// +//############################################################################ +// EndAlignJoystick +// +// End alignment process for joystick and analog inputs +//############################################################################ +// +void + LBE4ControlsManager::EndAlignJoystick() +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->ForceCenterJoystick(); + } + + if (flags.joystickExists) + { + Check(joystickPointer); + joystickPointer->EndAlignment(); + } + Check_Fpu(); +} + +void + LBE4ControlsManager::CenterRIOJoystick() +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->ForceCenterJoystick(); + } + + Check_Fpu(); +} + +void + LBE4ControlsManager::SetJoystickDeadBand(Scalar dead_band) +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->SetJoystickDeadBand(dead_band); + } + + if (flags.joystickExists) + { + Check(joystickPointer); + joystickPointer->SetDeadBand(dead_band); + } + + Check_Fpu(); +} + +void + LBE4ControlsManager::SetThrottleDeadBand(Scalar dead_band) +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->SetThrottleDeadBand(dead_band); + } + Check_Fpu(); +} + +void + LBE4ControlsManager::SetPedalsDeadBand(Scalar dead_band) +{ + Check(this); + + if (flags.RIOExists) + { + Check(rioPointer); + rioPointer->SetPedalsDeadBand(dead_band); + } + Check_Fpu(); +} + +const char* + LBE4ControlsManager::GetLampName(int lamp_number) +{ + const char + *lamp_name[] = + { + "AuxLowerRight8", + "AuxLowerRight7", + "AuxLowerRight6", + "AuxLowerRight5", + "AuxLowerRight4", + "AuxLowerRight3", + "AuxLowerRight2", + "AuxLowerRight1", + "AuxLowerLeft8", + "AuxLowerLeft7", + "AuxLowerLeft6", + "AuxLowerLeft5", + "AuxLowerLeft4", + "AuxLowerLeft3", + "AuxLowerLeft2", + "AuxLowerLeft1", + "Secondary1", //=0x10 + "Secondary2", + "Secondary3", + "Secondary4", + "Secondary5", + "Secondary6", + "TeslaRelay3", + "undefined_0x17", + "Secondary7", //=0x18 + "Secondary8", + "Secondary9", + "Secondary10", + "Secondary11", + "Secondary12", + "TeslaRelay1", + "TeslaRelay2", + "AuxUpperCenter8", //=0x20 + "AuxUpperCenter7", + "AuxUpperCenter6", + "AuxUpperCenter5", + "AuxUpperCenter4", + "AuxUpperCenter3", + "AuxUpperCenter2", + "AuxUpperCenter1", + "AuxUpperLeft8", //=0x28 + "AuxUpperLeft7", + "AuxUpperLeft6", + "AuxUpperLeft5", + "AuxUpperLeft4", + "AuxUpperLeft3", + "AuxUpperLeft2", + "AuxUpperLeft1", + "AuxUpperRight8", //=0x30 + "AuxUpperRight7", + "AuxUpperRight6", + "AuxUpperRight5", + "AuxUpperRight4", + "AuxUpperRight3", + "AuxUpperRight2", + "AuxUpperRight1", + "PanicButton", //=0x38 + "IcomAmpEnableRelay",//=0x39 + "IcomIncRelay", //=0x3A + "IcomPTTRelay", //=0x03B + "IcomDecRelay", //=0x3C + "undefined_0x3D", //=0x3D unimplemented convenience lamp + "FloorEntry" //=0x3E + }; + + if (lamp_number >= LampCount) + { + return "overrange"; + } + else if (lamp_number < 0) + { + return "underrange"; + } + else + { + return lamp_name[lamp_number]; + } +} + + +#define ID_ENTRY(name,group)\ + { #name , LBE4ControlsManager::##group, LBE4ControlsManager::##name } + +struct { + const char* controlName; + Enumeration + controlsGroup, + controlsElement; +} + Control_IDs[]= +{ + //----------------------------------------------- + // Throttle + //----------------------------------------------- + ID_ENTRY(ScalarThrottle,ScalarGroup), + ID_ENTRY(ButtonThrottle1,ButtonGroup), + + //----------------------------------------------- + // Pedals + //----------------------------------------------- + ID_ENTRY(ScalarLeftPedal,ScalarGroup), + ID_ENTRY(ScalarRightPedal,ScalarGroup), + + //----------------------------------------------- + // Joystick + //----------------------------------------------- + ID_ENTRY(JoystickPhysical,JoystickGroup), + ID_ENTRY(ButtonJoystickHatUp,ButtonGroup), + ID_ENTRY(ButtonJoystickHatDown,ButtonGroup), + ID_ENTRY(ButtonJoystickHatLeft,ButtonGroup), + ID_ENTRY(ButtonJoystickHatRight,ButtonGroup), + ID_ENTRY(ButtonJoystickTrigger,ButtonGroup), + ID_ENTRY(ButtonJoystickThumbHigh,ButtonGroup), + ID_ENTRY(ButtonJoystickThumbLow,ButtonGroup), + ID_ENTRY(ButtonJoystickPinky,ButtonGroup), + + //----------------------------------------------- + // Secondary buttons + //----------------------------------------------- + ID_ENTRY(ButtonSecondary1,ButtonGroup), + ID_ENTRY(ButtonSecondary2,ButtonGroup), + ID_ENTRY(ButtonSecondary3,ButtonGroup), + ID_ENTRY(ButtonSecondary4,ButtonGroup), + ID_ENTRY(ButtonSecondary5,ButtonGroup), + ID_ENTRY(ButtonSecondary6,ButtonGroup), + ID_ENTRY(ButtonSecondary7,ButtonGroup), + ID_ENTRY(ButtonSecondary8,ButtonGroup), + ID_ENTRY(ButtonSecondary9,ButtonGroup), + ID_ENTRY(ButtonSecondary10,ButtonGroup), + ID_ENTRY(ButtonSecondary11,ButtonGroup), + ID_ENTRY(ButtonSecondary12,ButtonGroup), + + //----------------------------------------------- + // Upper left auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxUpperLeft8,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft7,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft6,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft5,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft4,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft3,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft2,ButtonGroup), + ID_ENTRY(ButtonAuxUpperLeft1,ButtonGroup), + + //----------------------------------------------- + // Center auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxUpperCenter8,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter7,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter6,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter5,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter4,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter3,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter2,ButtonGroup), + ID_ENTRY(ButtonAuxUpperCenter1,ButtonGroup), + + //----------------------------------------------- + // Upper right auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxUpperRight8,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight7,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight6,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight5,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight4,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight3,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight2,ButtonGroup), + ID_ENTRY(ButtonAuxUpperRight1,ButtonGroup), + + //----------------------------------------------- + // Lower left auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxLowerLeft8,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft7,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft6,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft5,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft4,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft3,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft2,ButtonGroup), + ID_ENTRY(ButtonAuxLowerLeft1,ButtonGroup), + + //----------------------------------------------- + // Lower right auxiliary + //----------------------------------------------- + ID_ENTRY(ButtonAuxLowerRight8,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight7,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight6,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight5,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight4,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight3,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight2,ButtonGroup), + ID_ENTRY(ButtonAuxLowerRight1,ButtonGroup), + + //----------------------------------------------- + // Miscellaneous buttons + //----------------------------------------------- + ID_ENTRY(ButtonPanic,ButtonGroup), + ID_ENTRY(ButtonDoor,ButtonGroup) +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + LBE4ControlsManager::SetControlMappingID( + const char *control_name, + ControlsMapping *mapping + ) +{ + Check_Pointer(control_name); + Check_Pointer(mapping); + + int i; + for (i=0; icontrolsGroup = Control_IDs[i].controlsGroup; + mapping->controlsElement = Control_IDs[i].controlsElement; + break; + } + } + Check_Fpu(); + return i < ELEMENTS(Control_IDs); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Lamp * + LBE4ControlsManager::MakeLinkedLamp( + int element, + ModeMask mode_mask + ) +{ + Check(this); + Check(application); + + if (application->GetGaugeRenderer() == NULL) + { + return NULL; + } + else + { + Check(application->GetGaugeRenderer()); + + //------------------------------------------ + // Create the lamp + //------------------------------------------ + L4LampManager + *lamp_manager = (L4LampManager *) application-> + GetGaugeRenderer()->GetLampManager(); + Check(lamp_manager); + + Lamp + *lamp = new L4Lamp( + element, + mode_mask, + lamp_manager + ); + Register_Object(lamp); + //------------------------------------------ + // Add button mapping to lamp + //------------------------------------------ + buttonGroup[element].Add( + mode_mask, + &((L4Lamp *)lamp)->automaticValue, + lamp + ); + + Check_Fpu(); + return lamp; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::CreateStreamedMappings( + Entity *player, + const int *control_mappings + ) +{ + Check(this); + Check_Pointer(control_mappings); + + int + controls_count = *control_mappings; + ++control_mappings; + + ControlsMapping + *mapping = (ControlsMapping*)control_mappings; + Simulation + *subsystem; + void + *attribute; + + for (int i=0; iGetSimulation(mapping->subsystemID); + Verify(subsystem); + + // + //--------------------------- + // Handle the direct mappings + //--------------------------- + // + int + element = mapping->controlsElement; + ModeMask + mode_mask = mapping->modeMask; + + if (mapping->mappingType == ControlsMapping::DirectMapping) + { + attribute = subsystem->GetAttributePointer(mapping->attributeID); + switch (mapping->controlsGroup) + { + case ScalarGroup: + scalarGroup[element].Add( + mode_mask, + (ControlsScalar*)attribute, + subsystem + ); + break; + case JoystickGroup: + joystickGroup[element].Add( + mode_mask, + (ControlsJoystick*)attribute, + subsystem + ); + break; + case ButtonGroup: + //---------------------------------------------- + // Add button + //---------------------------------------------- + buttonGroup[element].Add( + mode_mask, + (ControlsButton*)attribute, + subsystem + ); + //---------------------------------------------- + // Create associated lamp + //---------------------------------------------- + if(buttonType[element] == AUTOBTN) + { +# if DEBUG_LEVEL > 0 + Lamp * + lamp = +# endif + MakeLinkedLamp(element, mode_mask); + +# if DEBUG_LEVEL > 0 + if (lamp != NULL) + { + Check(lamp); + } +# endif + } + break; + default: + Fail("Unknown mapping group!\n"); + break; + } + } + + // + //-------------------------------------------------- + // Otherwise, it is an event mapping, so set that up + //-------------------------------------------------- + // + else if (mapping->mappingType == ControlsMapping::EventMapping) + { + Receiver::MessageID + msg_id = mapping->messageID; + + switch (mapping->controlsGroup) + { + case ScalarGroup: + scalarGroup[element].Add(mode_mask,subsystem,msg_id,subsystem); + break; + case JoystickGroup: + joystickGroup[element].Add(mode_mask,subsystem,msg_id,subsystem); + break; + case ButtonGroup: + //---------------------------------------------- + // Add button + //---------------------------------------------- + buttonGroup[element].Add( + mode_mask, + subsystem, + msg_id, + subsystem + ); + //---------------------------------------------- + // Create associated lamp + //---------------------------------------------- + if(buttonType[element] == AUTOBTN) + { +# if DEBUG_LEVEL > 0 + Lamp * + lamp = +# endif + MakeLinkedLamp(element, mode_mask); + +# if DEBUG_LEVEL > 0 + if (lamp != NULL) + { + Check(lamp); + } +# endif + } + break; + default: + Fail("Unknown mapping group!\n"); + break; + } + } + else + { + Fail("Unknown mapping type!\n"); + } + mapping = (ControlsMapping*)((char*)mapping + sizeof(ControlsMapping)); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::EnterControlsMode( + L4ControlsMode new_mode, + Scalar time_until_exit, + Receiver::MessageID message_on_exit + ) +{ + Check(this); + l4ControlsMode = new_mode; + + exitModeTime = ((Scalar) Now()) + time_until_exit; + exitMessageID = message_on_exit; + + SetLamp(LampPanic, RIO::flashFast+RIO::state1Off+RIO::state2Bright); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::ExitControlsMode() +{ + Check(this); + + l4ControlsMode = normalMode; + + int + i; + + for(i=0; i= exitModeTime) + { + Receiver::Message + message(exitMessageID, sizeof(Receiver__Message)); + + Dispatch(&message); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LBE4ControlsManager::TestInstance() const +{ + Verify(IsDerivedFrom(*GetClassDerivations())); + return ControlsManager::TestInstance(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LBE4ControlsManager::AnalogHasChanged() +{ + Check(this); + + Logical + result = False; + + if (rioPointer != NULL) + { + Check(rioPointer); + + result = (rioPointer->Throttle != previousThrottle); + result |= (rioPointer->LeftPedal != previousPedalLeft); + result |= (rioPointer->RightPedal != previousPedalRight); + result |= (rioPointer->JoystickX != previousJoystickX); + result |= (rioPointer->JoystickY != previousJoystickY); + + if (result) + { + previousThrottle = rioPointer->Throttle; + previousPedalLeft = rioPointer->LeftPedal; + previousPedalRight = rioPointer->RightPedal; + previousJoystickX = rioPointer->JoystickX; + previousJoystickY = rioPointer->JoystickY; + } + } + + Check_Fpu(); + return result; +} + +Logical + LBE4ControlsManager::GetNextRIOEvent(RIO::RIOEvent *rio_event) +{ + // + //------------------------------------------------- + // If we aren't in playback mode, read the real RIO + //------------------------------------------------- + // + if (!playbackMode) + { + Logical + result = rioPointer->GetNextEvent(rio_event); + //---------------------------------------------------------------------- + // If the RIO stream exists, and a rio event was added, + // store this event in the rioStream + //---------------------------------------------------------------------- + if (result && streamEnabled) + { + Check(rioStream); + if (rioStream->GetBytesRemaining() >= sizeof(RIOStreamEvent)) + { + Check(rioStream); + RIOStreamEvent + *event = (RIOStreamEvent*)rioStream->GetPointer(); + Check_Pointer(event); + + event->timeStamp.ticks = Now().ticks - streamStart.ticks; + + if (rio_event->Type == RIO::AnalogEvent) + { + if (AnalogHasChanged()) + { +DEBUG_STREAM << "AnalogEvent at" << event->timeStamp.ticks << "\n"; +DEBUG_STREAM << "Pointer=" << std::hex << event << std::dec << "\n"; + //---------------------------- + // Set the event type + //---------------------------- + event->eventType = analog; + //---------------------------- + // Get the analog state + //---------------------------- + event->data.analog.throttle = rioPointer->Throttle; + event->data.analog.pedalLeft = rioPointer->LeftPedal; + event->data.analog.pedalRight = rioPointer->RightPedal; + event->data.analog.joystickX = rioPointer->JoystickX; + event->data.analog.joystickY = rioPointer->JoystickY; + //---------------------------- + // Save the event + //---------------------------- + rioStream->AdvancePointer(sizeof(RIOStreamEvent)); + } + } + else + { +DEBUG_STREAM << "DigitalEvent at" << event->timeStamp.ticks << "\n"; +DEBUG_STREAM << "Pointer=" << std::hex << event << std::dec << "\n"; + //---------------------------- + // Set the event type + //---------------------------- + event->eventType = digital; + //---------------------------- + // Save the event + //---------------------------- + event->data.rioEvent = *rio_event; + rioStream->AdvancePointer(sizeof(RIOStreamEvent)); + } + } + } + return result; + } + + // + //---------------------------------------------------------------------- + // Otherwise, we are in playback mode, so get the next record out of the + // memory block + //---------------------------------------------------------------------- + // + else if (streamEnabled) + { + Check(rioStream); + if (rioStream->GetBytesRemaining() >= sizeof(RIOStreamEvent)) + { + RIOStreamEvent + *event = (RIOStreamEvent*)rioStream->GetPointer(); + + Check_Pointer(event); + Time + now; + + now.ticks = Now().ticks - streamStart.ticks; + + if (event->timeStamp.ticks <= now.ticks) + { +DEBUG_STREAM << "Event timestamp=" << event->timeStamp.ticks << "\n"; + switch(event->eventType) + { + case analog: +DEBUG_STREAM << "AnalogEvent\n"; + //---------------------------- + // Send event type ONLY + //---------------------------- + rio_event->Type = RIO::AnalogEvent; + //---------------------------- + // Restore the analog state + //---------------------------- + rioPointer->Throttle = event->data.analog.throttle; + rioPointer->LeftPedal = event->data.analog.pedalLeft; + rioPointer->RightPedal = event->data.analog.pedalRight; + rioPointer->JoystickX = event->data.analog.joystickX; + rioPointer->JoystickY = event->data.analog.joystickY; + break; + + case digital: +DEBUG_STREAM << "DigitalEvent\n"; + //---------------------------- + // Send the entire event + //---------------------------- + *rio_event = event->data.rioEvent; + break; + } + rioStream->AdvancePointer(sizeof(RIOStreamEvent)); + return True; + } + } + } + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::ProcessRIOEvent( + RIO::RIOEvent &rio_event, + Logical *new_RIO_values + ) +{ + //-------------------------------------------------- + // Get mode mask for updating + //-------------------------------------------------- + Check(application); + Check(application->GetModeManager()); + ModeMask + mode_mask = application->GetModeManager()->GetModeMask(); + ControlsButton temp; + + switch(rio_event.Type) + { + case RIO::ButtonPressedEvent: + Verify(rio_event.Data.Unit >= 0); + Verify(rio_event.Data.Unit < ButtonCount); + temp = rio_event.Data.Unit + 1; + + Check(&buttonGroup[rio_event.Data.Unit]); + buttonGroup[rio_event.Data.Unit].Update(&temp, mode_mask); + //---------------------------------------- + // Save 'pressed' mode mask for 'release' + //---------------------------------------- + buttonActivateModeMask[rio_event.Data.Unit] = mode_mask; + break; + + case RIO::ButtonReleasedEvent: + Verify(rio_event.Data.Unit >= 0); + Verify(rio_event.Data.Unit < ButtonCount); + temp = -rio_event.Data.Unit - 1; + + Check(&buttonGroup[rio_event.Data.Unit]); + //---------------------------------------- + // Use 'pressed' mode mask for 'release' + //---------------------------------------- + buttonGroup[rio_event.Data.Unit].Update( + &temp, + buttonActivateModeMask[rio_event.Data.Unit] + ); + break; + + case RIO::KeyEvent: + { + Verify(rio_event.Data.Keyboard.Unit >= 0); + Verify(rio_event.Data.Keyboard.Unit < KeyboardCount); + //-------------------------------------- + // Convert key to ASCII + //-------------------------------------- + ControlsKey + new_key = rio_event.Data.Keyboard.Key; + if (new_key <= 9) + { + new_key += '0'; + } + else + { + new_key += 'A'-10; + } + Test_Tell( + "LBE4ControlsManager::Execute, new_key=" << (int) new_key << + "\n" + ); + + Check(&keyboardGroup[rio_event.Data.Keyboard.Unit]); + keyboardGroup[rio_event.Data.Keyboard.Unit]. + ForceUpdate(&new_key, mode_mask); + + Check(&stringManager); + stringManager.Update( + rio_event.Data.Keyboard.Unit, + new_key + ); + } + break; + + case RIO::AnalogEvent: + lastRioRequest = 0L; // force another RIO update request + *new_RIO_values = True; + break; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::SaveRecording(const char* file_name) +{ + Check(this); + Check_Pointer(file_name); + Check(rioStream); + + FileStream + output(file_name, True); + size_t + length = rioStream->GetBytesUsed(); + if (length) + { + rioStream->Rewind(); + + output << length; + output << *rioStream; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LBE4ControlsManager::LoadPlayback(const char* file_name) +{ + Check(this); + Check_Pointer(file_name); + + FileStream + input(file_name); + Verify(input.IsFileOpened()); + + // + //------------------------------- + // Figure out how big the file is + //------------------------------- + // + size_t + spool_size = 0; + input >> spool_size; + Verify(spool_size); + Verify(spool_size <= RIO_SPOOL_SIZE * sizeof(RIOStreamEvent)); + + RIOStreamEvent + *events = new RIOStreamEvent[RIO_SPOOL_SIZE]; + Register_Pointer(events); + + Verify(rioStream == NULL); + rioStream = new MemoryStream(events, spool_size); + Register_Object(rioStream); + + input.ReadBytes(events, spool_size); +} + +#if defined(TEST_CLASS) +# include "l4ctrl.tcp" +#endif diff --git a/MUNGA_L4/L4CTRL.h b/MUNGA_L4/L4CTRL.h new file mode 100644 index 0000000..9743d37 --- /dev/null +++ b/MUNGA_L4/L4CTRL.h @@ -0,0 +1,668 @@ +#pragma once + +#include "..\munga\controls.h" +#include "l4rio.h" +#include "l4keybd.h" +#include "l4mouse.h" +#include "l4joystk.h" +#include "l4lamp.h" +#include "..\munga\time.h" +#include "..\munga\entity.h" + +#include + +class LBE4ControlsManager; +class L4MappableButtonManager; + +//######################################################################## +//############################ Joystick classes ########################## +//######################################################################## +class Joystick; +class OrdinaryJoystick; +class FlightStickPro; +class ThrustMaster; + +class Joystick SIGNATURED +{ + friend class LBE4ControlsManager; + friend class OrdinaryJoystick; + friend class FlightStickPro; + friend class ThrustMaster; + +protected: + Joystick(); + +public: + virtual ~Joystick(); + virtual void + BeginAlignment(); + virtual void + EndAlignment(); + virtual void + Update(); + void + SetDeadBand(Scalar amount_of_deadband); + Logical + TestInstance() const; + +protected: + virtual void + EndAndSaveAlignment(NotationFile *init_file); +public: + enum ButtonState { + NoButton = 0, + Trigger = 0x01, + Thumb1 = 0x02, + Thumb2 = 0x04, + Thumb3 = 0x08, + HatUp = 0x10, + HatDown = 0x20, + HatLeft = 0x40, + HatRight = 0x80, + Throttle = 0x100 + }; + Vector2DOf Value; + Vector2DOf ExtendedValue; + Vector2DOf Rotation; + int ButtonReleased; + int ButtonPressed; + +protected: + FilterChannel *channel[2]; + int oldButtons; +}; + +class OrdinaryJoystick: + public Joystick +{ +public: + OrdinaryJoystick(); + ~OrdinaryJoystick(); + void Update(); +}; + +class FlightStickPro: + public Joystick +{ +public: + FlightStickPro(); + ~FlightStickPro(); + void Update(); + void + BeginAlignment(); + void + EndAlignment(); +protected: + FilterChannel + *throttle; +}; + +class ThrustMaster: + public Joystick +{ + friend BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); + friend BOOL CALLBACK EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef); + +public: + ThrustMaster(HINSTANCE hInstance, HWND hWnd); + ~ThrustMaster(); + void Update(); + + int hatMax, prevHatState; + +private: + bool Poll(); + + LPDIRECTINPUT8 mDI; + LPDIRECTINPUTDEVICE8 mJoystick; + DIJOYSTATE2 mJoystate; + + LONG xAxisMin, xAxisMax; + LONG yAxisMin, yAxisMax; + LONG zAxisMin, zAxisMax; + LONG rzAxisMin, rzAxisMax; +}; + + + +enum RioStreamEventType +{ + analog, + digital +}; + +struct RIOStreamEvent +{ + Time timeStamp; + + RioStreamEventType eventType; + + union + { + struct + { + Scalar + joystickX, + joystickY, + throttle, + pedalLeft, + pedalRight; + } + analog; + + RIO::RIOEvent rioEvent; + } + data; +}; + +//######################################################################### +//########################## LBE4ControlsManager ########################## +//######################################################################### + +class LBE4ControlsManager: + public ControlsManager +{ + friend class L4MappableButtonManager; // allows access to 'groupEnable' + + //------------------------------------------------------------------- + // Shared data support + //------------------------------------------------------------------- +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + //------------------------------------------------------------------- + // Message support + //------------------------------------------------------------------- +// public: +// enum { +// BeginCalibrationMessageID=ControlsManager::NextMessageID, +// EndCalibrationMessageID, +// NextMessageID +// }; +// private: +// static const HandlerEntry MessageHandlerEntries[]; +// protected: +// static MessageHandlerSet MessageHandlers; + + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- +public: + LBE4ControlsManager(); + ~LBE4ControlsManager(); + + static Logical + TestClass(); + Logical + TestInstance() const; + + void + LocalShutdown(); + + void + Execute(); + + //------------------------------------------------------------------- + // Message handlers + //------------------------------------------------------------------- +// void +// BeginCalibrationMessageHandler(Receiver::Message *message); +// void +// EndCalibrationMessageHandler(Receiver::Message *message); +// + //------------------------------------------------------------------- + // Control mapping methods + //------------------------------------------------------------------- + + void + Remove(ModeMask mode_mask); + + static int + SetControlMappingID( + const char *control_name, + ControlsMapping *mapping + ); + void + CreateStreamedMappings( + Entity *player, + const int *control_mappings + ); + + //------------------------------------------------------------------- + // Lamps + //------------------------------------------------------------------- + + // Commonly used combinations + enum + { + LampSolidOff = RIO::solid + RIO::state1Off + RIO::state2Off, + LampSolidDim = RIO::solid + RIO::state1Dim + RIO::state2Dim, + LampSolidBright = RIO::solid + RIO::state1Bright + RIO::state2Bright + }; + + // This is the order of the mapped lamps + // See also "GetLampName" + enum { + LampAuxLowerRight8=0x00, // Lower left auxiliary panel buttons + LampAuxLowerRight7, + LampAuxLowerRight6, + LampAuxLowerRight5, + LampAuxLowerRight4, + LampAuxLowerRight3, + LampAuxLowerRight2, + LampAuxLowerRight1, + + LampAuxLowerLeft8=0x08, // Lower right auxiliary panel buttons + LampAuxLowerLeft7, + LampAuxLowerLeft6, + LampAuxLowerLeft5, + LampAuxLowerLeft4, + LampAuxLowerLeft3, + LampAuxLowerLeft2, + LampAuxLowerLeft1, + + LampSecondary1=0x10, // Secondary panel buttons + LampSecondary2, + LampSecondary3, + LampSecondary4, + LampSecondary5, + LampSecondary6, + LampTesla1, // top? of three solid-state relays + LampTesla2, // middle? of three solid-state relays + + LampSecondary7=0x18, + LampSecondary8, + LampSecondary9, + LampSecondary10, + LampSecondary11, + LampSecondary12, + LampTesla3, // bottom of three solid-state relays + + LampAuxUpperCenter8=0x20, // Upper center auxiliary panel buttons + LampAuxUpperCenter7, + LampAuxUpperCenter6, + LampAuxUpperCenter5, + LampAuxUpperCenter4, + LampAuxUpperCenter3, + LampAuxUpperCenter2, + LampAuxUpperCenter1, + + LampAuxUpperLeft8=0x28, // Upper left auxiliary panel buttons + LampAuxUpperLeft7, + LampAuxUpperLeft6, + LampAuxUpperLeft5, + LampAuxUpperLeft4, + LampAuxUpperLeft3, + LampAuxUpperLeft2, + LampAuxUpperLeft1, + + LampAuxUpperRight8=0x30, // Upper right auxiliary panel buttons + LampAuxUpperRight7, + LampAuxUpperRight6, + LampAuxUpperRight5, + LampAuxUpperRight4, + LampAuxUpperRight3, + LampAuxUpperRight2, + LampAuxUpperRight1, + + LampIcomDecRelay = 0x38, + LampIcomAmpEnable = 0x39, + LampIcomIncRelay = 0x3A, + LampIcomPTTRelay = 0x03B, + + LampPanic=0x3D, + LampFloor=0x3E, // floor lamp (entry/exit) + LampUnused=0x3F, // unimplemented convenience lamp + + LampCount // the total number of defined lamps + }; + + Lamp * + MakeLinkedLamp( + int element, + ModeMask mode_mask = ModeManager::ModeAlwaysActive + ); + + void + SetLamp( + int lamp_number, + int state + ); + + static const char* + GetLampName(int lamp_number); + //------------------------------------------------------------------- + // Control groups + // Each control belongs to one of several groups (as in the + // enum below). + //------------------------------------------------------------------- + + enum { + ScalarGroup, + JoystickGroup, + KeyboardGroup, + ButtonGroup, + MouseGroup + }; + + //------------------------------------------------------------- + // Scalars + //------------------------------------------------------------- + + // This is the order of the mapped scalars + enum { + ScalarThrottle, + ScalarLeftPedal, ScalarRightPedal, + ScalarJoystickX, ScalarJoystickY, // 'real' joystick values + ScalarMouseX, ScalarMouseY, // 'virtual' joystick values + ScalarCount + }; + + ControlsUpdateManager + scalarGroup[ScalarCount]; + +public: + void + SetThrottleDeadBand(Scalar dead_band); + void + SetPedalsDeadBand(Scalar dead_band); + //------------------------------------------------------------- + // Joysticks + //------------------------------------------------------------- + void + BeginAlignJoystick(); + void + EndAlignJoystick(); + void + CenterRIOJoystick(); + void + SetJoystickDeadBand(Scalar dead_band); + + + // This is the order of the mapped joysticks + enum { + JoystickPhysical, // the 'real' joystick + JoystickVirtual, // a 'virtual' joystick driven by the PC mouse + JoystickCount + }; + + ControlsUpdateManager + joystickGroup[JoystickCount]; + + enum JoystickType + { + none, ordinary, flightstickPro, thrustMaster, directInputJoystick + }; + + JoystickType + joystickType; + +protected: + Joystick + *joystickPointer; + int + virtualJoystickX, virtualJoystickY; + Scalar + lastJoystickUpdate; + +public: + //------------------------------------------------------------- + // Keyboards + //------------------------------------------------------------- + + // This is the order of the mapped keyboards + enum { + KeyboardPilot, // internal keypad used by the pilot + KeyboardExternal, // external keypad used by an operator + KeyboardPC, // PC keyboard + KeyboardCount + }; + + ControlsUpdateManager + keyboardGroup[KeyboardCount]; + + //------------------------------------------------------------- + // Buttons + //------------------------------------------------------------- + + // This is the order of the buttons + enum { + ButtonAuxLowerRight8=0x00, // Lower left auxiliary panel buttons + ButtonAuxLowerRight7, + ButtonAuxLowerRight6, + ButtonAuxLowerRight5, + ButtonAuxLowerRight4, + ButtonAuxLowerRight3, + ButtonAuxLowerRight2, + ButtonAuxLowerRight1, + + ButtonAuxLowerLeft8=0x08, // Lower right auxiliary panel buttons + ButtonAuxLowerLeft7, + ButtonAuxLowerLeft6, + ButtonAuxLowerLeft5, + ButtonAuxLowerLeft4, + ButtonAuxLowerLeft3, + ButtonAuxLowerLeft2, + ButtonAuxLowerLeft1, + + ButtonSecondary1=0x10, // Secondary panel buttons + ButtonSecondary2, + ButtonSecondary3, + ButtonSecondary4, + ButtonSecondary5, + ButtonSecondary6, + + ButtonSecondary7=0x18, + ButtonSecondary8, + ButtonSecondary9, + ButtonSecondary10, + ButtonSecondary11, + ButtonSecondary12, + + ButtonAuxUpperCenter8=0x20,// Upper center auxiliary panel buttons + ButtonAuxUpperCenter7, + ButtonAuxUpperCenter6, + ButtonAuxUpperCenter5, + ButtonAuxUpperCenter4, + ButtonAuxUpperCenter3, + ButtonAuxUpperCenter2, + ButtonAuxUpperCenter1, + + ButtonAuxUpperLeft8=0x28, // Upper left auxiliary panel buttons + ButtonAuxUpperLeft7, + ButtonAuxUpperLeft6, + ButtonAuxUpperLeft5, + ButtonAuxUpperLeft4, + ButtonAuxUpperLeft3, + ButtonAuxUpperLeft2, + ButtonAuxUpperLeft1, + + ButtonAuxUpperRight8=0x30, // Upper right auxiliary panel buttons + ButtonAuxUpperRight7, + ButtonAuxUpperRight6, + ButtonAuxUpperRight5, + ButtonAuxUpperRight4, + ButtonAuxUpperRight3, + ButtonAuxUpperRight2, + ButtonAuxUpperRight1, + + ButtonIcomHeadPluggedIn = 0x39, + ButtonIcomSensor = 0x3A, + ButtonIcomMikePluggedIn = 0x3B, + ButtonDoor=0x3C, + ButtonPanic=0x3D, + + ButtonThrottle1=0x3F, + + ButtonJoystickTrigger=0x40, // Joystick trigger button + FirstMappableButton=ButtonJoystickTrigger, + ButtonJoystickHatDown=0x41, // Joystick trigger hat down + ButtonJoystickHatUp=0x42, // Joystick trigger hat up + ButtonJoystickHatRight=0x43, // Joystick trigger hat left + ButtonJoystickHatLeft=0x44, // Joystick trigger hat left + + ButtonJoystickPinky=0x45, // Joystick lowest button + ButtonJoystickThumbLow=0x46, // Joystick middle thumb button + ButtonJoystickThumbHigh=0x47, // Joystick upper thumb button (by hat) + LastMappableButton=ButtonJoystickThumbHigh, + + // The PC keyboard buttons will eventually + // be added here. + + ButtonMouseLeft, // left mouse button + ButtonMouseRight, // right mouse button + ButtonMouseCenter, // center mouse button (if available) + + + ButtonCount // defines number of buttons + }; + ControlsUpdateManager + buttonGroup[ButtonCount]; +protected: + ModeMask + buttonActivateModeMask[ButtonCount]; + + //------------------------------------------------------------- + // Mouse + //------------------------------------------------------------- +public: + ControlsUpdateManager + mouseGroup[1]; // Yes, only one mouse. Get real. + +protected: + Mouse + *mousePointer; + +public: + //------------------------------------------------------------- + // Strings (matched keyboard input) + //------------------------------------------------------------- + ControlsStringManager + stringManager; + +public: + //------------------------------------------------------------------- + // RIO data + //------------------------------------------------------------------- + RIO + *rioPointer; + +protected: + Time + lastRioRequest; + +public: + //------------------------------------------------------------------- + // Current IO type + //------------------------------------------------------------------- + enum IOType + { + None = 0, + PrimaryGenericJoystick, + PrimaryThrustMaster, + PrimaryFlightStickPro, + PrimaryRIO, + PrimaryDirectInputJoystick + }; + + IOType + primaryControlType; + + //------------------------------------------------------------------- + // Existence flags + //------------------------------------------------------------------- + struct { + unsigned int mouseExists:1; + unsigned int keyboardExists:1; + unsigned int joystickExists:1; + unsigned int RIOExists:1; + }flags; + + //------------------------------------------------------------------- + // Operator controls + //------------------------------------------------------------------- +protected: + enum L4ControlsMode + { + normalMode = 0, + calibrationMode + }; + + void + EnterControlsMode( + L4ControlsMode new_mode, + Scalar time_until_exit, + Receiver::MessageID message_on_exit + ); + + void + ExitControlsMode(); + + void + ManageControlsMode(); + + L4ControlsMode + l4ControlsMode; + Time + exitModeTime; + Receiver::MessageID + exitMessageID; + + enum + { + maxStringIDs = 16 + }; + + ControlsStringID + temporaryStringID[maxStringIDs]; + +// +//-------------------- +// RIO Stream Spoofing +//-------------------- +// +public: + Logical + GetNextRIOEvent(RIO::RIOEvent *rio_event); + void + ProcessRIOEvent( + RIO::RIOEvent &rio_event, + Logical *new_RIO_values + ); + + void + StartRecording() + {Check(this); streamStart = Now(); streamEnabled=True;} + void + SaveRecording(const char* file_name); + void + LoadPlayback(const char* file_name); + void + StartPlayback() + {Check(this); streamStart = Now(); streamEnabled=True;} + + Logical + IsRecording() + {return rioStream && !playbackMode;} + Logical + IsPlayingBack() + {return rioStream && playbackMode;} + Logical + AnalogHasChanged(); + +protected: + MemoryStream + *rioStream; + Time + streamStart; + Logical + playbackMode; + Logical + streamEnabled; + Scalar + previousJoystickX, + previousJoystickY, + previousThrottle, + previousPedalLeft, + previousPedalRight; +}; diff --git a/MUNGA_L4/L4D3D.cpp b/MUNGA_L4/L4D3D.cpp new file mode 100644 index 0000000..aaf363a --- /dev/null +++ b/MUNGA_L4/L4D3D.cpp @@ -0,0 +1,464 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4d3d.h" +#include "L4VIDEO.h" +#include + +int gNumBatches = 0; + +bool d3d_OBJECT::mLastTextureScrollState = false; +L4TEXOP::WrapType d3d_OBJECT::mLastWrapU = L4TEXOP::WrapType::REPEAT; +L4TEXOP::WrapType d3d_OBJECT::mLastWrapV = L4TEXOP::WrapType::REPEAT; +bool d3d_OBJECT::mLastTexturingState = true; +long d3d_OBJECT::mNextID = 1; +stdext::hash_map d3d_OBJECT::mTextureCache; + +void chgext(char *filePath, const char *newExtension) +{ + int len = strlen(filePath); + for (int i=len-1; i>=0; i--) + { + if (filePath[i] == '.') + { + strcpy(&filePath[i + 1], newExtension); + return; + } + } +} + +void d3d_OBJECT::ResetState(LPDIRECT3DDEVICE9 device) +{ + d3d_OBJECT::mLastTextureScrollState = false; + device->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + + d3d_OBJECT::mLastWrapU = L4TEXOP::WrapType::REPEAT; + device->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); + + d3d_OBJECT::mLastWrapV = L4TEXOP::WrapType::REPEAT; + device->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); + + d3d_OBJECT::mLastTexturingState = true; + device->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + device->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + device->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); +} + +d3d_OBJECT *d3d_OBJECT::LoadObject(LPDIRECT3DDEVICE9 device, char *fileName) +{ + char fullPath[512]; + sprintf(fullPath, "VIDEO\\%s", fileName); + chgext(fullPath, "x"); + + //Get a ref to the renderer + DPLRenderer *renderer = l4_application->GetVideoRenderer(); + + LPD3DXMESH mesh; + LPD3DXBUFFER materialBuffer, adjacencyBuffer; + DWORD materialCount; + + HRESULT hr = D3DXLoadMeshFromXA(fullPath, D3DXMESH_MANAGED, device, &adjacencyBuffer, &materialBuffer, NULL, &materialCount, &mesh); + if (FAILED(hr)) + { + chgext(fullPath, "sph"); + return d3d_OBJECT::LoadSpheres(device, fullPath); + } + + chgext(fullPath, "det"); + FILE *detFile = fopen(fullPath, "rb"); + int numDetailOps = 0; + int *detailOps = NULL; + + bool isSky = false; + + if (detFile != NULL) + { + fread(&numDetailOps, sizeof(int), 1, detFile); + + detailOps = new int[numDetailOps]; + fread(detailOps, sizeof(int), numDetailOps, detFile); + fclose(detFile); + } + + chgext(fullPath, "sky"); + FILE *skyFile = fopen(fullPath, "rb"); + + if (skyFile != NULL) + { + isSky = true; + fclose(skyFile); + } + + d3d_OBJECT *object = new d3d_OBJECT(device, mesh, (DWORD*)adjacencyBuffer->GetBufferPointer(), materialCount); + + D3DXMATERIAL *materials = (D3DXMATERIAL*)materialBuffer->GetBufferPointer(); + + int nextDetailOp = 0; + + for (DWORD i = 0; i < materialCount; i++) + { + chgext(fullPath, "BGF"); + + string path(fullPath); + + string actualPath = path.substr(path.find("\\") + 1); + std::transform(actualPath.begin(), actualPath.end(), actualPath.begin(), toupper); + const char *matName = opMaterialName(actualPath.c_str(), i); + char *replaceMatName = NULL; + char *replaceTexName = NULL; + + if (matName != NULL) + { + char *tmpMatName = new char[strlen(matName) + 1]; + strcpy_s(tmpMatName, strlen(matName) + 1, matName); + + replaceMatName = substituteMaterial(tmpMatName); + } + + object->mDrawOps[i].material = materials[i].MatD3D; + + if (replaceMatName != NULL) + { + hash_map::const_iterator iter = gReplacementData->find(string(replaceMatName)); + + ReplacementMaterialData data = (*iter).second; + + object->mDrawOps[i].material.Diffuse.r = data.r; + object->mDrawOps[i].material.Diffuse.g = data.g; + object->mDrawOps[i].material.Diffuse.b = data.b; + + replaceTexName = new char[data.texName.size() + 1]; + strcpy_s(replaceTexName, data.texName.size() + 1, data.texName.c_str()); + + delete [] replaceMatName; + } + + //TODO: set ambient of material; doesn't come back from .X file + object->mDrawOps[i].material.Ambient = object->mDrawOps[i].material.Diffuse; + + object->mDrawOps[i].texture.texture = NULL; + if (materials[i].pTextureFilename || replaceTexName) + { + char textureFilename[512]; + + if (replaceTexName) + { + sprintf(textureFilename, "VIDEO\\%s.png", replaceTexName); + delete [] replaceTexName; + } else + { + sprintf(textureFilename, "VIDEO\\%s", materials[i].pTextureFilename); + } + object->mDrawOps[i].texture = LoadTexture(device, textureFilename); + } + + if (nextDetailOp < numDetailOps && detailOps[nextDetailOp] == i) + { + object->mDrawOps[i].drawAsDecal = true; + nextDetailOp++; + } + + if (abs(object->mDrawOps[i].material.Diffuse.a - 1.0f) > 0.0001f) + { + object->mDrawOps[i].alphaTest = true; + } + + object->mDrawOps[i].drawAsSky = isSky; + + if (isSky) + { + object->mDrawOps[i].material.Ambient.r *= renderer->GetCloudRed(); + object->mDrawOps[i].material.Ambient.g *= renderer->GetCloudGreen(); + object->mDrawOps[i].material.Ambient.b *= renderer->GetCloudBlue(); + object->mDrawOps[i].material.Diffuse.r *= renderer->GetCloudRed(); + object->mDrawOps[i].material.Diffuse.g *= renderer->GetCloudGreen(); + object->mDrawOps[i].material.Diffuse.b *= renderer->GetCloudBlue(); + object->mDrawOps[i].material.Emissive.r = renderer->GetCloudEmitRed(); + object->mDrawOps[i].material.Emissive.g = renderer->GetCloudEmitGreen(); + object->mDrawOps[i].material.Emissive.b = renderer->GetCloudEmitBlue(); + } + } + + materialBuffer->Release(); + + return object; +} + +d3d_OBJECT* d3d_OBJECT::LoadSpheres(LPDIRECT3DDEVICE9 device, char *fileName) +{ + FILE *file; + float emissionColor[3]; + int vertexCount; + + if ((file = fopen(fileName, "rb")) == NULL) + return NULL; + + fread(emissionColor, sizeof(float), 3, file); + fread(&vertexCount, sizeof(int), 1, file); + + d3d_OBJECT *object = new d3d_OBJECT(device, vertexCount); + void *buffer = NULL; + + object->mVB->Lock(0, 0, &buffer, 0); + + fread(buffer, sizeof(L4POINTVERTEX), vertexCount, file); + + D3DXVECTOR3 center(0, 0, 0); + D3DXComputeBoundingSphere((D3DXVECTOR3*)buffer, vertexCount, sizeof(L4POINTVERTEX), ¢er, &object->mRadius); + + object->mVB->Unlock(); + + object->mDrawOps[0].material.Emissive.r = emissionColor[0]; + object->mDrawOps[0].material.Emissive.g = emissionColor[1]; + object->mDrawOps[0].material.Emissive.b = emissionColor[2]; + object->mDrawOps[0].material.Emissive.a = 1.0f; + + fclose(file); + + return object; +} + +L4TEXOP d3d_OBJECT::LoadTexture(LPDIRECT3DDEVICE9 device, const char *fileName) +{ + L4TEXOP texOp; + FILE *file; + if (mTextureCache.find(fileName) == mTextureCache.end()) + { + struct + { unsigned char minify; + unsigned char magnify; + unsigned char alpha; + unsigned char wrap_u; + unsigned char wrap_v; + bool doScroll; + float scrollUDelta; + float scrollVDelta; + } fileTexOp; + + char metFileName[512]; + strcpy(metFileName, fileName); + chgext(metFileName, "met"); + + memset(&texOp, 0, sizeof(L4TEXOP)); + if ((file = fopen(metFileName, "rb")) != NULL) + { + fread(&fileTexOp, sizeof(fileTexOp), 1, file); + fclose(file); + + texOp.wrap_u = (L4TEXOP::WrapType)fileTexOp.wrap_u; + texOp.wrap_v = (L4TEXOP::WrapType)fileTexOp.wrap_v; + texOp.doScroll = fileTexOp.doScroll; + texOp.scrollUDelta = fileTexOp.scrollUDelta; + texOp.scrollVDelta = fileTexOp.scrollVDelta; + } + + D3DXCreateTextureFromFileA(device, fileName, &texOp.texture); + + mTextureCache.insert(std::pair(std::string(fileName), texOp)); + } + else + texOp = mTextureCache[std::string(fileName)]; + + texOp.texture->AddRef(); + return texOp; +} + +d3d_OBJECT::d3d_OBJECT(LPDIRECT3DDEVICE9 device, int vertCount) + : mDevice(device), + mVertCount(vertCount), + mDrawOpCount(1), + mImmune(false), + mVB(NULL), + mMesh(NULL), + mDrawOps(NULL), + mLocalToWorld(), + mOrigin(), + mRadius(0.0f), + mID(mNextID++) +{ + HRESULT hr; + + hr = device->CreateVertexBuffer(vertCount * sizeof(L4POINTVERTEX), D3DUSAGE_WRITEONLY, L4POINTVERTEX_FVF, D3DPOOL_MANAGED, &mVB, NULL); + + mDrawOps = new L4DRAWOP(); + memset(mDrawOps, 0, sizeof(L4DRAWOP)); + + memset(mNext, 0, sizeof(mNext)); + memset(mPrev, 0, sizeof(mPrev)); + + D3DXMatrixIdentity(&mLocalToWorld); +} + +d3d_OBJECT::d3d_OBJECT(LPDIRECT3DDEVICE9 device, LPD3DXMESH mesh, DWORD *adjacencyBuffer, int drawOpCount) + : mDevice(device), + mVertCount(-1), + mDrawOpCount(drawOpCount), + mImmune(false), + mVB(NULL), + mMesh(mesh), + mLocalToWorld(), + mOrigin(), + mRadius(0.0f), + mID(mNextID++) +{ + mDrawOps = new L4DRAWOP[drawOpCount]; + memset(mDrawOps, 0, sizeof(L4DRAWOP) * drawOpCount); + + if (adjacencyBuffer != NULL) + { + //Null adjacency buffer means the mesh should have already been optimized + mesh->OptimizeInplace(D3DXMESHOPT_ATTRSORT | D3DXMESHOPT_VERTEXCACHE, adjacencyBuffer, NULL, NULL, NULL); + } + + DWORD vertCount = mesh->GetNumVertices(); + DWORD vertStride = mesh->GetNumBytesPerVertex(); + + D3DXVECTOR3 *data; + D3DXVECTOR3 center(0, 0, 0); + mesh->LockVertexBuffer(D3DLOCK_READONLY, (LPVOID*)&data); + D3DXComputeBoundingSphere(data, vertCount, vertStride, ¢er, &mRadius); + mesh->UnlockVertexBuffer(); + + memset(mNext, 0, sizeof(mNext)); + memset(mPrev, 0, sizeof(mPrev)); + + D3DXMatrixIdentity(&mLocalToWorld); +} + +d3d_OBJECT::~d3d_OBJECT() +{ + if (mVB) + { + mVB->Release(); + mVB = NULL; + } + if (mDrawOps) + { + delete[] mDrawOps; + mDrawOps = NULL; + } +} + +void d3d_OBJECT::Draw(int pass, const D3DXMATRIX *viewTransform, Time targetRenderFrame) +{ + // set our world transform + mDevice->SetTransform(D3DTS_WORLD, &mLocalToWorld); + + if (mMesh != NULL && pass != PASS_SPHERE) + return DrawMesh(pass, viewTransform, targetRenderFrame); + else if (mMesh == NULL && mVB != NULL && pass == PASS_SPHERE) + return DrawSpheres(pass, viewTransform); +} + +void d3d_OBJECT::DrawMesh(int pass, const D3DXMATRIX *viewTransform, Time targetRenderFrame) +{ + for (int iOp = 0; iOp < mDrawOpCount; iOp++) + { + L4DRAWOP *drawOp = &mDrawOps[iOp]; + + if (drawOp->alphaTest != (pass == PASS_ALPHABLEND)) + continue; + + if (drawOp->drawAsDecal != (pass == PASS_DECAL)) + continue; + + if (drawOp->drawAsSky != (pass == PASS_SKY)) + continue; + + mDevice->SetMaterial(&drawOp->material); + +#ifndef RP3_EMULATE + SetTextureScrolling(&(drawOp->texture), targetRenderFrame); + SetTexture(drawOp->texture.texture); +#endif + + gNumBatches++; + mMesh->DrawSubset(iOp); + } +} + +void d3d_OBJECT::DrawSpheres(int pass, const D3DXMATRIX *viewTransform) +{ + mDevice->SetFVF(L4POINTVERTEX_FVF); + mDevice->SetStreamSource(0, mVB, 0, sizeof(L4POINTVERTEX)); + mDevice->SetMaterial(&mDrawOps[0].material); + SetTexture(NULL); + mDevice->DrawPrimitive(D3DPT_POINTLIST, 0, mVertCount); +} + +void d3d_OBJECT::SetTextureScrolling(const L4TEXOP *texture, Time targetRenderFrame) +{ + if (d3d_OBJECT::mLastTextureScrollState != texture->doScroll) + { + // the texture scrolling state has changed + if (texture->doScroll) + { + mDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_COUNT2); + SetTextureAddressing(texture->wrap_u, texture->wrap_v); + } + else + { + mDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + SetTextureAddressing(L4TEXOP::WrapType::REPEAT, L4TEXOP::WrapType::REPEAT); + } + d3d_OBJECT::mLastTextureScrollState = texture->doScroll; + } + + // if the texture is supposed to be scrolled then + // we have to set the transforms regardless of state + if (texture->doScroll) + { + Scalar time = (Scalar)targetRenderFrame; + + D3DXMATRIX translate; + D3DXMatrixIdentity(&translate); + translate._31 = -texture->scrollUDelta * time; + translate._32 = texture->scrollVDelta * time; + mDevice->SetTransform(D3DTS_TEXTURE0, &translate); + } +} + +void d3d_OBJECT::SetTextureAddressing(L4TEXOP::WrapType wrap_u, L4TEXOP::WrapType wrap_v) +{ + if (wrap_u != d3d_OBJECT::mLastWrapU) + { + d3d_OBJECT::mLastWrapU = wrap_u; + if (wrap_u == L4TEXOP::REPEAT) + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); + else if (wrap_u == L4TEXOP::CLAMP) + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_CLAMP); + else if (wrap_u == L4TEXOP::SELECT) + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_BORDER); + } + if (wrap_v != d3d_OBJECT::mLastWrapV) + { + d3d_OBJECT::mLastWrapV = wrap_v; + if (wrap_v == L4TEXOP::REPEAT) + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); + else if (wrap_v == L4TEXOP::CLAMP) + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_CLAMP); + else if (wrap_v == L4TEXOP::SELECT) + mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_BORDER); + } +} + +void d3d_OBJECT::SetTexture(LPDIRECT3DTEXTURE9 texture) +{ + bool texturingOn = (texture != NULL); + if (texturingOn != d3d_OBJECT::mLastTexturingState) + { + d3d_OBJECT::mLastTexturingState = texturingOn; + if (texturingOn) + { + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + } + else + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_DISABLE); + } + if (texture != NULL) + { + mDevice->SetTexture(0, texture); + } +} \ No newline at end of file diff --git a/MUNGA_L4/L4D3D.h b/MUNGA_L4/L4D3D.h new file mode 100644 index 0000000..d3ec379 --- /dev/null +++ b/MUNGA_L4/L4D3D.h @@ -0,0 +1,151 @@ +#pragma once + +#include +#include +#include + +#define L4VERTEX_FVF (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE | D3DFVF_NORMAL) +#define L4POINTVERTEX_FVF (D3DFVF_XYZ) +#define L4VERTEX_2D_FVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE) +#define L4VERTEX_2D_TEX_FVF (D3DFVF_XYZRHW | D3DFVF_DIFFUSE | D3DFVF_TEX1) + +#define PASS_OPAQUE 0 +#define PASS_DECAL 1 +#define PASS_ALPHABLEND 2 +#define PASS_SPHERE 3 +#define PASS_SKY 4 +#define PASS_TOTAL_COUNT 5 + +struct L4VERTEX +{ + float x, y, z; + float nx, ny, nz; + DWORD color; + float u, v; +}; + +struct L4POINTVERTEX +{ + float x, y, z; +}; + +struct L4VERTEX_2D +{ + float x, y, z, rhw; + DWORD color; +}; + +struct L4VERTEX_2D_TEX +{ + float x, y, z, rhw; + DWORD color; + float u, v; +}; + +struct L4TEXOP +{ + enum WrapType + { + REPEAT, + CLAMP, + SELECT + } wrap_u, wrap_v; + + LPDIRECT3DTEXTURE9 texture; + + bool doScroll; + float scrollUDelta; + float scrollVDelta; +}; + +struct L4RAMP +{ + float r0, g0, b0; + float r1, g1, b1; +}; + +struct L4DRAWOP +{ + D3DMATERIAL9 material; + L4TEXOP texture; + bool alphaTest; + bool drawAsDecal; + bool drawAsSky; +}; + +class d3d_OBJECT +{ +public: + d3d_OBJECT(LPDIRECT3DDEVICE9 device, int vertCount); + d3d_OBJECT(LPDIRECT3DDEVICE9 device, LPD3DXMESH mesh, DWORD *adjacencyBuffer, int drawOpCount); + ~d3d_OBJECT(); + + inline LPDIRECT3DDEVICE9 GetDevice() { return mDevice; } + inline int GetVertCount() { return mVertCount; } + inline int GetDrawOpCount() { return mDrawOpCount; } + inline L4DRAWOP* GetDrawOp(int index) { return &(mDrawOps[index]); } + + void Draw(int pass, const D3DXMATRIX *viewTransform, Time targetRenderFrame); + + inline void SetRadius(float radius) { mRadius = radius; } + inline void SetOrigin(L4POINTVERTEX origin) { mOrigin = origin; } + inline void SetImmune(bool immune) { mImmune = immune; } + inline void SetLocalToWorld(D3DXMATRIX localToWorld) { mLocalToWorld = localToWorld; } + + inline float GetRadius() { return mRadius; } + inline L4POINTVERTEX GetOrigin() { return mOrigin; } + inline bool GetImmune() { return mImmune; } + inline D3DXMATRIX GetLocalToWorld() { return mLocalToWorld; } + inline LPD3DXMESH GetMesh() { return mMesh; } + + inline d3d_OBJECT* GetNext(int pass) { return mNext[pass + 1]; } + inline d3d_OBJECT* GetPrevious( int pass) { return mPrev[pass + 1]; } + inline void SetNext(d3d_OBJECT *next, int pass) { mNext[pass + 1] = next; } + inline void SetPrevious(d3d_OBJECT *previous, int pass) { mPrev[pass + 1] = previous; } + + static void ResetState(LPDIRECT3DDEVICE9 device); + static d3d_OBJECT* LoadObject(LPDIRECT3DDEVICE9 device, char *fileName); + static L4TEXOP LoadTexture(LPDIRECT3DDEVICE9 device, const char *fileName); + +private: + static d3d_OBJECT* LoadSpheres(LPDIRECT3DDEVICE9 device, char *fileName); + + LPDIRECT3DDEVICE9 mDevice; + inline void SetVB(LPDIRECT3DVERTEXBUFFER9 buffer) { mVB = buffer; } + void DrawMesh(int pass, const D3DXMATRIX *viewTransform, Time targetRenderFrame); + void DrawSpheres(int pass, const D3DXMATRIX *viewTransform); + + long mID; + + // vertex based + int mVertCount; + LPDIRECT3DVERTEXBUFFER9 mVB; + + // mesh based + LPD3DXMESH mMesh; + + int mDrawOpCount; + L4DRAWOP* mDrawOps; + + bool mImmune; + D3DXMATRIX mLocalToWorld; + L4POINTVERTEX mOrigin; + float mRadius; + + d3d_OBJECT *mNext[PASS_TOTAL_COUNT + 1]; + d3d_OBJECT *mPrev[PASS_TOTAL_COUNT + 1]; + + void SetTextureScrolling(const L4TEXOP *texture, Time targetRenderFrame); + void SetTextureAddressing(L4TEXOP::WrapType wrap_u, L4TEXOP::WrapType wrap_v); + void SetTexture(LPDIRECT3DTEXTURE9 texture); + // state information for optimizing renderstate changes + static bool mLastTextureScrollState; + static L4TEXOP::WrapType mLastWrapU; + static L4TEXOP::WrapType mLastWrapV; + static bool mLastTexturingState; + + static long mNextID; + static stdext::hash_map< std::string , L4TEXOP > mTextureCache; +}; + +extern int gNumBatches; diff --git a/MUNGA_L4/L4DINPUT.cpp b/MUNGA_L4/L4DINPUT.cpp new file mode 100644 index 0000000..c63c08a --- /dev/null +++ b/MUNGA_L4/L4DINPUT.cpp @@ -0,0 +1,194 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4dinput.h" + +#define DI_TRIGGER 0 +#define DI_THUMB1 2 +#define DI_THUMB2 1 +#define DI_THUMB3 3 + +DIJoystick::DIJoystick(HINSTANCE hInstance, HWND hWnd) +{ + mDI = NULL; + mJoystick = NULL; + + if (SUCCEEDED(DirectInput8Create(hInstance, DIRECTINPUT_VERSION, IID_IDirectInput8, (void**)&mDI, NULL))) + { + mDI->EnumDevices(DI8DEVCLASS_GAMECTRL, EnumJoysticksCallback, this, DIEDFL_ATTACHEDONLY); + if (mJoystick) + if (SUCCEEDED(mJoystick->SetDataFormat(&c_dfDIJoystick2))) + if (SUCCEEDED(mJoystick->SetCooperativeLevel(hWnd, DISCL_EXCLUSIVE | DISCL_BACKGROUND))) + if (SUCCEEDED(mJoystick->EnumObjects(EnumAxesCallback, this, DIDFT_AXIS))) + return; + } + + if (mDI) + { + mDI->Release(); + mDI = NULL; + } + if (mJoystick) + { + mJoystick->Release(); + mJoystick = NULL; + } +} + +DIJoystick::~DIJoystick() +{ + if (mJoystick) + { + mJoystick->Unacquire(); + mJoystick->Release(); + mJoystick = NULL; + } + + if (mDI) + { + mDI->Release(); + mDI = NULL; + } +} + +BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext) +{ + DIJoystick *joystick = (DIJoystick*)pContext; + if (FAILED(joystick->mDI->CreateDevice(pdidInstance->guidInstance, &joystick->mJoystick, NULL))) + return DIENUM_CONTINUE; + + return DIENUM_STOP; +} + +BOOL CALLBACK EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef) +{ + DIJoystick *joystick = (DIJoystick*)pvRef; + DIPROPRANGE diprg; + diprg.diph.dwSize = sizeof(DIPROPRANGE); + diprg.diph.dwHeaderSize = sizeof(DIPROPHEADER); + diprg.diph.dwHow = DIPH_BYID; + diprg.diph.dwObj = lpddoi->dwType; + diprg.lMax = diprg.lMax = 0; + + if (lpddoi->guidType == GUID_XAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->xAxisMin = diprg.lMin; + joystick->xAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_YAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->yAxisMin = diprg.lMin; + joystick->yAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_ZAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->zAxisMin = diprg.lMin; + joystick->zAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_RxAxis) + { + } + else if (lpddoi->guidType == GUID_RyAxis) + { + } + else if (lpddoi->guidType == GUID_RzAxis) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->rzAxisMin = diprg.lMin; + joystick->rzAxisMax = diprg.lMax; + } + } + else if (lpddoi->guidType == GUID_Slider) + { + if (SUCCEEDED(joystick->mJoystick->GetProperty(DIPROP_RANGE, &diprg.diph))) + { + joystick->zAxisMin = diprg.lMin; + joystick->zAxisMax = diprg.lMax; + } + } + + return DIENUM_CONTINUE; +} + +bool DIJoystick::Poll() +{ + HRESULT hr; + if (mJoystick) + { + hr = mJoystick->Poll(); + if (FAILED(hr)) + { + DEBUG_STREAM << "Poll failed: HR = " << hr << std::endl << std::flush; + hr = mJoystick->Acquire(); + while (hr == DIERR_INPUTLOST) + { + DEBUG_STREAM << "Acquire failed: HR = " << hr << std::endl << std::flush; + hr = mJoystick->Acquire(); + } + return false; + } + + if (FAILED(hr = mJoystick->GetDeviceState(sizeof(DIJOYSTATE2), &mJoystate))) + { + DEBUG_STREAM << "GetState failed: HR = " << hr << std::endl << std::flush; + return false; + } + } + + return true; +} + +void DIJoystick::Update() +{ + if (Poll()) + { + // Handle analog data + Value.x = ((Scalar)(mJoystate.lX - xAxisMin) / (Scalar)(xAxisMax - xAxisMin)) * 2.0f - 1.0f; + Value.y = ((Scalar)(mJoystate.lY - yAxisMin) / (Scalar)(yAxisMax - yAxisMin)) * 2.0f - 1.0f; + LONG z = (mJoystate.lZ == 0 ? mJoystate.rglSlider[0] : mJoystate.lZ); + ExtendedValue.y = 1.0f - (Scalar)(z - zAxisMin) / (Scalar)(zAxisMax - zAxisMin); + // full left rotation = 0, center rotation = 1/2 range, full right = full range + LONG rot = (Scalar)(mJoystate.lRz - rzAxisMin); + Scalar half = (Scalar)(rzAxisMax - rzAxisMin) / 2.0f; + Rotation.x = (Scalar)0; + Rotation.y = (Scalar)0; + if (rot <= half) + Rotation.x = ((half - rot) / half) * 470.0; + else + Rotation.y = ((rot - half) / half) * 470.0; + + // Handle button changes + int newButtons = 0; + if (mJoystate.rgbButtons[DI_TRIGGER]) + newButtons |= Joystick::Trigger; + if (mJoystate.rgbButtons[DI_THUMB1]) + newButtons |= Joystick::Thumb1; + if (mJoystate.rgbButtons[DI_THUMB2]) + newButtons |= Joystick::Thumb2; + if (mJoystate.rgbButtons[DI_THUMB3]) + newButtons |= Joystick::Thumb3; + if (mJoystate.rgdwPOV[0] == 0) + newButtons |= Joystick::HatUp; + if (mJoystate.rgdwPOV[0] == 9000) + newButtons |= Joystick::HatRight; + if (mJoystate.rgdwPOV[0] == 18000) + newButtons |= Joystick::HatDown; + if (mJoystate.rgdwPOV[0] == 27000) + newButtons |= Joystick::HatLeft; + + ButtonPressed = (oldButtons ^ newButtons) & newButtons; + ButtonReleased = (oldButtons ^ newButtons) & oldButtons; + oldButtons = newButtons; + } +} + diff --git a/MUNGA_L4/L4DINPUT.h b/MUNGA_L4/L4DINPUT.h new file mode 100644 index 0000000..1fe912e --- /dev/null +++ b/MUNGA_L4/L4DINPUT.h @@ -0,0 +1,29 @@ +#pragma once +#include "l4ctrl.h" +#include + +class DIJoystick : public Joystick +{ + friend BOOL CALLBACK EnumJoysticksCallback(const DIDEVICEINSTANCE* pdidInstance, VOID* pContext); + friend BOOL CALLBACK EnumAxesCallback(LPCDIDEVICEOBJECTINSTANCE lpddoi, LPVOID pvRef); + +public: + DIJoystick(HINSTANCE hInstance, HWND hWnd); + ~DIJoystick(); + + bool IsValid() { return (mDI != NULL); } + bool Poll(); + + // inherited + void Update(); + +private: + LPDIRECTINPUT8 mDI; + LPDIRECTINPUTDEVICE8 mJoystick; + DIJOYSTATE2 mJoystate; + + LONG xAxisMin, xAxisMax; + LONG yAxisMin, yAxisMax; + LONG zAxisMin, zAxisMax; + LONG rzAxisMin, rzAxisMax; +}; \ No newline at end of file diff --git a/MUNGA_L4/L4DPLMEM.cpp b/MUNGA_L4/L4DPLMEM.cpp new file mode 100644 index 0000000..20fe570 --- /dev/null +++ b/MUNGA_L4/L4DPLMEM.cpp @@ -0,0 +1,48 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4video.h" + +extern "C" +{ + void *dpl_malloc(int n_bytes); + void *dpl_calloc(size_t n, size_t n_bytes); + void dpl_free(void *ptr); + void dpl_free_all(); +}; + +void *dpl_malloc(int n_bytes) +{ + /*STUBBED: DPL RB 1/20/07 + Check_Pointer(DPLRenderer::DPLHeap); + return DPLRenderer::DPLHeap->Allocate(n_bytes); + */ + return NULL; +} + +void *dpl_calloc(size_t n, size_t n_bytes) +{ + /*STUBBED: DPL RB 1/20/07 + Check_Pointer(DPLRenderer::DPLHeap); + void *p = DPLRenderer::DPLHeap->Allocate(n * n_bytes); + memset(p, 0x0, n_bytes * n); + return p; + */ + return NULL; +} + +void dpl_free(void *ptr) +{ + /*STUBBED: DPL RB 1/20/07 + Check_Pointer(DPLRenderer::DPLHeap); + DPLRenderer::DPLHeap->Release(ptr); + */ +} + +void dpl_free_all() +{ + /*STUBBED: DPL RB 1/20/07 + Check_Pointer(DPLRenderer::DPLHeap); + DPLRenderer::DPLHeap->ReleaseAll(); + */ +} diff --git a/MUNGA_L4/L4GAUGE.cpp b/MUNGA_L4/L4GAUGE.cpp new file mode 100644 index 0000000..72f1ca2 --- /dev/null +++ b/MUNGA_L4/L4GAUGE.cpp @@ -0,0 +1,5161 @@ +#include "mungal4.h" +#pragma hdrstop + +#define PRELOAD_ART + +#include "..\munga\player.h" +#include "l4app.h" +#include "l4gauge.h" +#include "l4grend.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) std::cout << n +#else +# define Test_Tell(n) +#endif + + +LookupTable + configureChannels[] = + { + {"red", L4GraphicsPort::RedChannel}, + {"green", L4GraphicsPort::GreenChannel}, + {"blue", L4GraphicsPort::BlueChannel}, + {"rgb", L4GraphicsPort::AllChannels}, + + {"direct", L4GraphicsPort::DirectColor}, + {"blank", L4GraphicsPort::BlankColor}, + + {"redtransparent", L4GraphicsPort::RedChannelTransparentZero}, + {"greentransparent", L4GraphicsPort::GreenChannelTransparentZero}, + {"bluetransparent", L4GraphicsPort::BlueChannelTransparentZero}, + {"rgbtransparent", L4GraphicsPort::AllChannelsTransparentZero}, + {NULL, -1} + }; + +LookupTable + configurePalettes[] = + { + {"native", SVGA16::NativePalette}, + {"clut0", SVGA16::SecondaryPalette}, + {"clut1", SVGA16::AuxiliaryPalette1}, + {"clut2", SVGA16::AuxiliaryPalette2}, + {NULL, -1} + }; + +LookupTable + configureFormat[] = + { + {"unsigned", NumericDisplay::unsignedFormat}, + {"signed", NumericDisplay::signedFormat}, + {"signedBlankedZeros", NumericDisplay::signedBlankedZerosFormat}, + {"absolute", NumericDisplay::absoluteFormat}, + {"time", NumericDisplay::timeFormat}, + {NULL, -1} + }; + +LookupTable + configureDirection[] = + { + {"left", WipeGaugeScalar::wipeLeft}, + {"down", WipeGaugeScalar::wipeDown}, + {"right", WipeGaugeScalar::wipeRight}, + {"up", WipeGaugeScalar::wipeUp}, + {NULL, -1} + }; + +char + *nameCopy(const char *old_name) +{ + Check_Pointer(old_name); + + char + *copy = strdup(old_name); + Register_Pointer(copy); + + return copy; +} + +//########################################################################### +// NumericDisplay +//########################################################################### +NumericDisplay::NumericDisplay( + L4Warehouse *the_warehouse, + int x_position, int y_position, + const char *font_name, + int number_of_digits, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color +) +{ + Check_Pointer(this); + + //------------------------------------------------------------ + // Save the font name + //------------------------------------------------------------ + digitMapName = nameCopy(font_name); + //------------------------------------------------------------ + // Order the font from the warehouse (pre-load for future use) + //------------------------------------------------------------ + Check(the_warehouse); + warehouse = the_warehouse; + + Check_Pointer(digitMapName); + + BitMap + *digit_map = warehouse->bitMapBin.Get(digitMapName); + //----------------------------------------------------------- + // Calculate font-specific values + //----------------------------------------------------------- + if (digit_map == NULL) + { + digitWidth = 0; + digitHeight = 0; + } + else + { + Check(digit_map); + digitWidth = (digit_map->Data.Size.x+1)/totalDigitsPerFont; + digitHeight = digit_map->Data.Size.y; + } + //----------------------------------------------------------- + // Set internal values + //----------------------------------------------------------- + if (number_of_digits < 1) + { + number_of_digits = 1; + } + + if (format == timeFormat) + { + if (number_of_digits > 8) + { + number_of_digits = 8; + } + largestValue = (Scalar) (99*60*60); + } + else + { + if (number_of_digits > maxDigits) + { + number_of_digits = maxDigits; + } + largestValue = (Scalar) (pow(10.0f, number_of_digits)-1.0); + } + + numberOfDigits = number_of_digits; + format = requested_format; + backgroundColor = background_color; + foregroundColor = foreground_color; + offsetX = x_position; + offsetY = y_position; + erased = True; + + ForceUpdate(); // ensure initialization + + //------------------------------------------------------------ + // Done with the font, release it + //------------------------------------------------------------ +# if !defined(PRELOAD_ART) + Check_Pointer(warehouse); + warehouse->bitMapBin.Release(digitMapName); +# endif + + Check_Fpu(); +} + +NumericDisplay::~NumericDisplay() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded art + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + warehouse->bitMapBin.Release(digitMapName); +# endif + //------------------------------------------------------------ + // Delete the font name + //------------------------------------------------------------ + Unregister_Pointer(digitMapName); + delete[] digitMapName; + digitMapName = NULL; + + Check_Fpu(); +} + +Logical + NumericDisplay::TestInstance() const +{ + return True; +} + +void + NumericDisplay::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "NumericDisplay:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; + std::cout << temp << "foregroundColor=" << foregroundColor << "\n"; + std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n"; + std::cout << temp << "format ="; + switch(format) + { + case unsignedFormat: std::cout << "unsignedFormat\n"; break; + case signedFormat: std::cout << "signedFormat\n"; break; + case signedBlankedZerosFormat: std::cout << "signedBlankedZerosFormat\n"; break; + case absoluteFormat: std::cout << "absoluteFormat\n"; break; + case timeFormat: std::cout << "timeFormat\n"; break; + default: + std::cout << "**OUT OF RANGE**\n"; + } + + Check_Fpu(); +} + +void + NumericDisplay::ForceUpdate() +{ + Check(this); + //----------------------------------------------------------- + // Force update by clearing previous value and digits + //----------------------------------------------------------- + previousValue = -1.2345f; + + for(int i=0; ibitMapBin.Get(digitMapName); + + if (digit_map != NULL) + { + // + //----------------------------------------------------------- + // Get absolute value if required + //----------------------------------------------------------- + // + if(format == absoluteFormat) + { + if (current_value < 0.0) + { + current_value = - current_value; + } + } + Check_Fpu(); + + // + //----------------------------------------------------------- + // Draw only if value has changed + //----------------------------------------------------------- + // + if (previousValue != current_value) + { + previousValue = current_value; + + int + test_value((int) (current_value+.5)), + digit_height(digit_map->Data.Size.y), + i, + x, + sx; + Check_Fpu(); + + char + buffer[maxDigits+1], + *buffer_pointer; + + // + //-------------------------------------------------------- + // Get absolute value, limit to maximum + //-------------------------------------------------------- + // + if (test_value < 0) + { + test_value = - test_value; + } + + if (test_value > (int) largestValue) + { + test_value = (int) largestValue; + } + Check_Fpu(); + + // + //-------------------------------------------------------- + // Build buffer + //-------------------------------------------------------- + // + buffer_pointer = &buffer[numberOfDigits-1]; + + switch (format) + { + case absoluteFormat: + case unsignedFormat: + case signedBlankedZerosFormat: + for(i=numberOfDigits-1; i>=0; --i) + { + *buffer_pointer-- = (char) (test_value % 10); + test_value /= 10; + } + Check_Fpu(); + break; + + case signedFormat: + for(i=numberOfDigits-2; i>=0; --i) + { + *buffer_pointer-- = (char) (test_value % 10); + test_value /= 10; + } + *buffer_pointer = (char) + ((current_value >= 0.0) ? plusDigit : minusDigit); + Check_Fpu(); + break; + + case timeFormat: + { + int + n, + state; + + state = 0; + for(i=numberOfDigits; i>0; ) + { + switch(state++) + { + case 0: // seconds + case 1: // minutes + n = test_value % 60; + test_value /= 60; + break; + + case 2: // hours + n = test_value % 24; + test_value /= 24; + break; + + case 3: // days + n = test_value % 100; + break; + + default: // Oh, come on now! + n = 0; + break; + } + Check_Fpu(); + if (--i >= 0) + { + *buffer_pointer-- = (char) (n % 10); + } + if (--i >= 0) + { + *buffer_pointer-- = (char) (n / 10); + } + if (--i >= 0) + { + *buffer_pointer-- = (char) colonDigit; + } + } + } + break; + } + Check_Fpu(); + + // + //-------------------------------------------------------- + // Draw digits from buffer + //-------------------------------------------------------- + // + Logical + blanked = True; + + char + this_digit; + + for( + i=0, x=offsetX, buffer_pointer=buffer; + iMoveToAbsolute(x, offsetY); + //----------------------------------------------------- + // If blanked, draw filled rectangle + //----------------------------------------------------- + if (this_digit == blankedDigit) + { + graphics_view->SetColor(backgroundColor); + graphics_view->DrawFilledRectangleToRelative( + digitWidth, + digit_height + ); + } + //----------------------------------------------------- + // Else draw character + //----------------------------------------------------- + else + { + sx = digitWidth*this_digit; + + graphics_view->SetColor(foregroundColor); + graphics_view->DrawBitMapOpaque( + backgroundColor, + 0, //rotation + digit_map, + sx, 0, sx+digitWidth-1, digit_height + ); + } + } + } + } + } + //----------------------------------------------------------- + // Unlock the font: we're done + //----------------------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(digitMapName); + + Check_Fpu(); +} + +void + NumericDisplay::Erase( + GraphicsView *graphics_view + ) +{ + Check(this); + + if (!erased) + { + erased = True; + + graphics_view->SetColor(backgroundColor); + graphics_view->MoveToAbsolute(offsetX, offsetY); + graphics_view->DrawFilledRectangleToRelative( + digitWidth*numberOfDigits, + digitHeight + ); + } + Check_Fpu(); +} + + +//########################################################################### +// NumericDisplayScalar +//########################################################################### +MethodDescription + NumericDisplayScalar::methodDescription = + { + "numeric", + NumericDisplayScalar::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // font name + { ParameterDescription::typeInteger, NULL }, // # of digits + { ParameterDescription::typeString, NULL }, // format + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // foreground + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + NumericDisplayScalar::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // font name + parameterList[4].CheckIt(ParameterDescription::typeInteger); // # of digs + parameterList[5].CheckIt(ParameterDescription::typeString); // format + parameterList[6].CheckIt(ParameterDescription::typeColor); // background + parameterList[7].CheckIt(ParameterDescription::typeColor); // foreground + parameterList[8].CheckIt(ParameterDescription::typeAttribute); // value name +# endif + + Test_Tell("NumericDisplayScalar::Make\n"); + Check(gauge_renderer); + + int + number_format = configureFormat[0].Search( + parameterList[5].data.string + ); + + if (number_format < 0) + { + Test_Tell("NumericDisplayScalar::Make format NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + NumericDisplayScalar + *numeric_display = +# endif + new NumericDisplayScalar( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, //font name + parameterList[4].data.integer, //int number_of_chars + (NumericDisplay::NumericFormat) number_format, + parameterList[6].data.integer, //int background_color + parameterList[7].data.integer, //int foreground_color + (Scalar *) parameterList[8].data.attributePointer + + // HACK!!!! The (Scalar *) is VERY dangerous! + ); + Register_Object(numeric_display); + + //-------------------------------------------------------- + // Make sure the font was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL) + { + Test_Tell("NumericDisplayScalar::Missing font\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[3].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("NumericDisplayScalar::Make OK\n"); + Check_Fpu(); + return True; +} + +NumericDisplayScalar::NumericDisplayScalar( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, //BitMap *font, + int number_of_digits, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + Scalar *value_pointer, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + // graphics_port may be NULL! + Check_Pointer(value_pointer); + //----------------------------------------------------------- + // Set internal values + //----------------------------------------------------------- + numericDisplay = new NumericDisplay( + (L4Warehouse *) renderer->warehousePointer, + 0,0, + font_name, + number_of_digits, + requested_format, + background_color, + foreground_color + ); + Register_Object(numericDisplay); + + localView.SetPositionWithinPort(left, bottom, right, top); + + // + //----------------------------------------------------------- + // Build connection to value + //----------------------------------------------------------- + // + GaugeConnection + *connection; + + connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Register_Object(connection); + AddConnection(connection); + Check_Fpu(); +} + +NumericDisplayScalar::~NumericDisplayScalar() +{ + Check(this); + + //------------------------------------------------- + // Destroy the numeric display + //------------------------------------------------- + if (numericDisplay != NULL) + { + Unregister_Object(numericDisplay); + delete numericDisplay; + numericDisplay = NULL; + } + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + NumericDisplayScalar::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + NumericDisplayScalar::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "NumericDisplayScalar:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + GraphicGauge::ShowInstance(temp); + Check(numericDisplay); + numericDisplay->ShowInstance(temp); + Check_Fpu(); +} + +void + NumericDisplayScalar::BecameActive() +{ + Check(this); + Check(numericDisplay); + numericDisplay->ForceUpdate(); + Check_Fpu(); +} + +void + NumericDisplayScalar::SetColors(int bg_color, int fg_color) +{ + Check(this); + numericDisplay->SetColors(bg_color, fg_color); + Check_Fpu(); +} + +void + NumericDisplayScalar::Execute() +{ + Check(this); + Check(numericDisplay); + numericDisplay->Draw(&localView, currentValue); + Check_Fpu(); +} + +//########################################################################### +// NumericDisplaySpeed +// +// - Converts input in meters per second to display as kilometers per hour +//########################################################################### +MethodDescription + NumericDisplaySpeed::methodDescription = + { + "numericSpeed", + NumericDisplaySpeed::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // font name + { ParameterDescription::typeInteger, NULL }, // # of digits + { ParameterDescription::typeString, NULL }, // format + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // foreground + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + NumericDisplaySpeed::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // font name + parameterList[4].CheckIt(ParameterDescription::typeInteger); // # of digs + parameterList[5].CheckIt(ParameterDescription::typeString); // format + parameterList[6].CheckIt(ParameterDescription::typeColor); // background + parameterList[7].CheckIt(ParameterDescription::typeColor); // foreground + parameterList[8].CheckIt(ParameterDescription::typeAttribute); // value name +# endif + + Test_Tell("NumericDisplaySpeed::Make\n"); + + int + number_format = configureFormat[0].Search( + parameterList[5].data.string + ); + + if (number_format < 0) + { + Test_Tell("NumericDisplaySpeed::Make format NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + NumericDisplaySpeed + *numeric_display = +# endif + new NumericDisplaySpeed( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, //font name + parameterList[4].data.integer, //int number_of_chars + (NumericDisplay::NumericFormat) number_format, + parameterList[6].data.integer, //int background_color + parameterList[7].data.integer, //int foreground_color + (Scalar *) parameterList[8].data.attributePointer + + // HACK!!!! The (Scalar *) is VERY dangerous! + ); + + Register_Object(numeric_display); + + //-------------------------------------------------------- + // Make sure the font was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL) + { + Test_Tell("NumericDisplaySpeed::Missing font\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[3].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("NumericDisplaySpeed::Make OK\n"); + Check_Fpu(); + return True; +} + +NumericDisplaySpeed::NumericDisplaySpeed( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, + int number_of_digits, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + Scalar *value_pointer +): + NumericDisplayScalar( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + left, bottom, right, top, + font_name, + number_of_digits, + requested_format, + background_color, foreground_color, + value_pointer + ) +{ + Check_Fpu(); +} + +void + NumericDisplaySpeed::Execute() +{ + Check(this); + + Scalar + value = currentValue*(Scalar)3.6; + + Check(numericDisplay); + numericDisplay->Draw(&localView, fabs(value)); + Check_Fpu(); +} + +//########################################################################### +// NumericDisplayInteger +//########################################################################### +MethodDescription + NumericDisplayInteger::methodDescription = + { + "numericInteger", + NumericDisplayInteger::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // font name + { ParameterDescription::typeInteger, NULL }, // # of digits + { ParameterDescription::typeString, NULL }, // format + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // foreground + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + NumericDisplayInteger::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // font + parameterList[4].CheckIt(ParameterDescription::typeInteger); // # of digs + parameterList[5].CheckIt(ParameterDescription::typeString); // format + parameterList[6].CheckIt(ParameterDescription::typeColor); // background + parameterList[7].CheckIt(ParameterDescription::typeColor); // foreground + parameterList[8].CheckIt(ParameterDescription::typeAttribute); // value name +# endif + + Test_Tell("NumericDisplayInteger::Make\n"); + + int + number_format = configureFormat[0].Search( + parameterList[5].data.string + ); + + if (number_format < 0) + { + Test_Tell("NumericDisplayInteger::Make format NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + NumericDisplayInteger + *numeric_display = +# endif + new NumericDisplayInteger( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, //font name + parameterList[4].data.integer, //int number_of_chars + (NumericDisplay::NumericFormat) number_format, + parameterList[6].data.integer, //int background_color + parameterList[7].data.integer, //int foreground_color + (int *) parameterList[8].data.attributePointer + + // HACK!!!! The (int *) is VERY dangerous! + ); + Register_Object(numeric_display); + + //-------------------------------------------------------- + // Make sure the font was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL) + { + Test_Tell("NumericDisplayInteger::Missing font\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[3].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("NumericDisplayInteger::Make OK\n"); + Check_Fpu(); + return True; +} + +NumericDisplayInteger::NumericDisplayInteger( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, + int number_of_digits, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + int *value_pointer, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + // graphics_port may be NULL! + Check_Pointer(value_pointer); + Check(renderer); + //----------------------------------------------------------- + // Set internal values + //----------------------------------------------------------- + numericDisplay = new NumericDisplay( + (L4Warehouse *) renderer->warehousePointer, + 0,0, + font_name, + number_of_digits, + requested_format, + background_color, + foreground_color + ); + Register_Object(numericDisplay); + + localView.SetPositionWithinPort(left, bottom, right, top); + //----------------------------------------------------------- + // Build connection to value + //----------------------------------------------------------- + GaugeConnection + *connection; + + connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Register_Object(connection); + AddConnection(connection); + Check_Fpu(); +} + +NumericDisplayInteger::~NumericDisplayInteger() +{ + Check(this); + + if (numericDisplay != NULL) + { + Unregister_Object(numericDisplay); + delete numericDisplay; + numericDisplay = NULL; + } + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + NumericDisplayInteger::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + NumericDisplayInteger::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "NumericDisplayInteger:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + GraphicGauge::ShowInstance(temp); + Check(numericDisplay); + numericDisplay->ShowInstance(temp); + Check_Fpu(); +} + +void + NumericDisplayInteger::BecameActive() +{ + Check(this); + Check(numericDisplay); + numericDisplay->ForceUpdate(); + Check_Fpu(); +} + +void + NumericDisplayInteger::SetColors(int bg_color, int fg_color) +{ + Check(this); + numericDisplay->SetColors(bg_color, fg_color); + Check_Fpu(); +} + +void + NumericDisplayInteger::Execute() +{ + Check(this); + Check(numericDisplay); + numericDisplay->Draw(&localView, (Scalar) currentValue); + Check_Fpu(); +} + +//########################################################################### +// DigitalClock +//########################################################################### +MethodDescription + DigitalClock::methodDescription = + { + "digitalClock", + DigitalClock::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // font name + { ParameterDescription::typeInteger, NULL }, // # of digits + { ParameterDescription::typeString, NULL }, // format + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // foreground + //{ ParameterDescription::typeEmpty, NULL }, + { ParameterDescription::typeEmpty, NULL } + } + }; + +Logical + DigitalClock::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // font name + parameterList[4].CheckIt(ParameterDescription::typeInteger); // # of digs + parameterList[5].CheckIt(ParameterDescription::typeString); // format + parameterList[6].CheckIt(ParameterDescription::typeColor); // background + parameterList[7].CheckIt(ParameterDescription::typeColor); // foreground +# endif + + Test_Tell("DigitalClock::Make\n"); + + int + number_format = configureFormat[0].Search( + parameterList[5].data.string + ); + + if (number_format < 0) + { + Test_Tell("DigitalClock::Make format NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + DigitalClock + *digital_clock = +# endif + new DigitalClock( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, //font name + parameterList[4].data.integer, //int number_of_chars + (NumericDisplay::NumericFormat) number_format, + parameterList[6].data.integer, //int background_color + parameterList[7].data.integer //int foreground_color + ); + + Register_Object(digital_clock); + + //-------------------------------------------------------- + // Make sure the font was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL) + { + Test_Tell("DigitalClock::Missing font\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[3].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("DigitalClock::Make OK\n"); + Check_Fpu(); + return True; +} + +DigitalClock::DigitalClock( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, + int number_of_digits, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + // graphics_port may be NULL! + Check(renderer); + + Verify((right - left - 1) >= 0); + Verify((top - bottom - 1) >= 0); + // + //----------------------------------------------------------- + // Set internal values + //----------------------------------------------------------- + // + numericDisplay = new NumericDisplay( + (L4Warehouse *) renderer->warehousePointer, + 0,0, + font_name, + number_of_digits, + requested_format, + background_color, + foreground_color + ); + Register_Object(numericDisplay); + + localView.SetPositionWithinPort(left, bottom, right, top); + + Check_Fpu(); +} + +DigitalClock::~DigitalClock() +{ + Check(this); + + if (numericDisplay != NULL) + { + Unregister_Object(numericDisplay); + delete numericDisplay; + numericDisplay = NULL; + } + Check_Fpu(); +} + +Logical + DigitalClock::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + DigitalClock::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "DigitalClock:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "numericDisplay=" << numericDisplay << "\n"; + Gauge::ShowInstance(temp); + Check(numericDisplay); + numericDisplay->ShowInstance(temp); + Check_Fpu(); +} + +void + DigitalClock::BecameActive() +{ + Check(this); + Check(numericDisplay); + numericDisplay->ForceUpdate(); + Check_Fpu(); +} + +void + DigitalClock::Execute() +{ + Check(this); + Check(numericDisplay); + Check(application); + + // HACK!!! + // Something subtle and mysterious is happening here... + //...and ONLY in the OPT version (which won't show source in the debugger!) + // + // If I try to fold the 'GetSecondsRemainingInGame()' call + // into the 'Draw' method, the clock will show an extra + // 60 seconds in the game! + // Perhaps some invisible type conversion is occurring. + + Scalar + seconds_remaining = application->GetSecondsRemainingInGame(); + numericDisplay->Draw(&localView, seconds_remaining); + Check_Fpu(); +} + + +//########################################################################### +// BackgroundConfig +//########################################################################### +Logical + MakeConfig( + int /*display_port_index*/, + Vector2DOf /*position*/, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = MakeConfigMethodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeInteger);// port + parameterList[1].CheckIt(ParameterDescription::typeString); // name + parameterList[2].CheckIt(ParameterDescription::typeInteger);// rotation + parameterList[3].CheckIt(ParameterDescription::typeInteger);// bits + parameterList[4].CheckIt(ParameterDescription::typeString); // palette ID + parameterList[5].CheckIt(ParameterDescription::typeString); // channel ID + parameterList[6].CheckIt(ParameterDescription::typeString); // palette name +# endif + + Test_Tell("BackgroundConfig::Make\n"); + + char + *palette_type = parameterList[4].data.string, + *enable_type = parameterList[5].data.string, + *palette_name = parameterList[6].data.string; + + //------------------------------------------------- + // Get palette ID type + //------------------------------------------------- + int + palette_ID = configurePalettes[0].Search(palette_type); + + if (palette_ID < 0) + { + DEBUG_STREAM << + "configure palette_ID '" << palette_type << "' NOT FOUND\n"; + return False; + } + + //------------------------------------------------- + // Get channel enable type + //------------------------------------------------- + int + enable_ID = configureChannels[0].Search(enable_type); + + if (enable_ID < 0) + { + DEBUG_STREAM << + "configure enable_ID '" << enable_type << "' NOT FOUND\n"; + return False; + } + + int + port_number = parameterList[0].data.integer; + const char + *port_name = parameterList[1].data.string; + int + rotation = parameterList[2].data.integer; + int + new_bits = parameterList[3].data.integer; + + Logical + ignore_palette_flag = (stricmp(palette_name, "NULL") == 0); + //------------------------------------------------------------ + // Get, lock pixelmap from warehouse + //------------------------------------------------------------ + //Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + Palette8 + *palette; + + if (ignore_palette_flag) + { + palette = NULL; + } + else + { + palette = warehouse->palette8Bin.Get(palette_name); + if (palette == NULL) + { + DEBUG_STREAM << + "MakeConfig missing palette '" << palette_name << "'\n"; + Check_Fpu(); + return False; + } + Check(palette); + } + //------------------------------------------------- + // Build the port + //------------------------------------------------- + //Check(renderer); + ((L4GaugeRenderer *)gauge_renderer)->BuildGraphicsPort( + port_number, + port_name, + rotation, + new_bits, + (SVGA16::PaletteID) palette_ID, + (L4GraphicsPort::ChannelEnableID) enable_ID, + palette + ); + //------------------------------------------------- + // Release the palette (we're done with it) + //------------------------------------------------- + if (!ignore_palette_flag) + { + warehouse->palette8Bin.Release(palette_name); + } + + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("MakeConfig OK\n"); + Check_Fpu(); + return True; +} + +MethodDescription + MakeConfigMethodDescription = + { + "configure", + MakeConfig, + { + { ParameterDescription::typeInteger, NULL }, // graphicsPort # + { ParameterDescription::typeString, NULL }, // name + { ParameterDescription::typeInteger, NULL }, // rotation + { ParameterDescription::typeInteger, NULL }, // bits + { ParameterDescription::typeString, NULL }, // palette ID + { ParameterDescription::typeString, NULL }, // channel ID + { ParameterDescription::typeString, NULL }, // palette name + PARAMETER_DESCRIPTION_END + } + }; + +//########################################################################### +// MakeExternConfig +//########################################################################### +Logical + MakeExternConfig( + int /*display_port_index*/, + Vector2DOf /*position*/, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = MakeExternConfigMethodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeInteger);// port # + parameterList[1].CheckIt(ParameterDescription::typeString); // name + parameterList[2].CheckIt(ParameterDescription::typeInteger);// bits +# endif + + Test_Tell("MakeExternConfig\n"); + + //------------------------------------------------- + // Build the port + //------------------------------------------------- + //Check(renderer); + ((L4GaugeRenderer *)gauge_renderer)->BuildExternalGraphicsPort( + parameterList[0].data.integer, // int port_number, + parameterList[1].data.string, // const char *name, + parameterList[2].data.integer // int bitAllocation + ); + + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("MakeExternConfig OK\n"); + Check_Fpu(); + return True; +} + +MethodDescription + MakeExternConfigMethodDescription = + { + "externalConfigure", + MakeExternConfig, + { + { ParameterDescription::typeInteger, NULL }, // graphicsPort # + { ParameterDescription::typeString, NULL }, // name + { ParameterDescription::typeInteger, NULL }, // bits + PARAMETER_DESCRIPTION_END + } + }; + +//########################################################################### +// BackgroundReconfig +//########################################################################### +MethodDescription + BackgroundReconfig::methodDescription = + { + "reconfigure", + BackgroundReconfig::Make, + { + { ParameterDescription::typeModeMask, NULL },// mode mask + { ParameterDescription::typeInteger, NULL }, // graphicsPort # + { ParameterDescription::typeString, NULL }, // palette ID + { ParameterDescription::typeString, NULL }, // channel ID + { ParameterDescription::typeString, NULL }, // palette + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BackgroundReconfig::Make( + int /*display_port_index*/, + Vector2DOf /*position*/, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeModeMask);// mode mask + parameterList[1].CheckIt(ParameterDescription::typeInteger);// port # + parameterList[2].CheckIt(ParameterDescription::typeString); // palette ID + parameterList[3].CheckIt(ParameterDescription::typeString); // channel ID + parameterList[4].CheckIt(ParameterDescription::typeString); // palette name +# endif + + Test_Tell("BackgroundReconfig::Make\n"); + + char + *palette_type = parameterList[2].data.string, + *enable_type = parameterList[3].data.string, + *palette_name = parameterList[4].data.string; + + //------------------------------------------------- + // Get palette ID type + //------------------------------------------------- + int + palette_ID = configurePalettes[0].Search(palette_type); + + if (palette_ID < 0) + { + DEBUG_STREAM << + "reconfigure palette_ID '" << palette_type << "' NOT FOUND\n"; + return False; + } + + //------------------------------------------------- + // Get channel enable type + //------------------------------------------------- + int + enable_ID = configureChannels[0].Search(enable_type); + + if (enable_ID < 0) + { + DEBUG_STREAM << + "reconfigure enable_ID '" << enable_type << "' NOT FOUND\n"; + return False; + } + + //------------------------------------------------- + // Create object + //------------------------------------------------- + BackgroundReconfig + *bg = + new BackgroundReconfig( + parameterList[0].data.modeMask, // mode mask + (L4GaugeRenderer *) gauge_renderer, + parameterList[1].data.integer, // port # + palette_ID, + enable_ID, + palette_name // palette name + ); + + Register_Object(bg); + + //----------------------------------------------------------- + // Make sure the palette was properly placed in the warehouse + //----------------------------------------------------------- + if (!bg->ignorePaletteFlag) + { + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(palette_name) == NULL) + { + DEBUG_STREAM << + "BackgroundReconfig missing palette '" << palette_name << "'\n"; + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(palette_name); + } + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("BackgroundReconfig::Make OK\n"); + Check_Fpu(); + return True; +} + +BackgroundReconfig::BackgroundReconfig( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + int port_number, + int palette_ID, + int enable_ID, + const char *palette_name, + const char *identification_string +): + GaugeBackground( + mode_mask, + renderer, + 0, + identification_string + ) +{ + portNumber = port_number; + paletteID = palette_ID; + enableID = enable_ID; + paletteName = nameCopy(palette_name); + ignorePaletteFlag = (stricmp(paletteName, "NULL") == 0); + + //---------------------------------------------------------- + // Preload the palette + //---------------------------------------------------------- +# if defined(PRELOAD_ART) + if (!ignorePaletteFlag) + { + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + warehouse->palette8Bin.Get(paletteName); + } +# endif + + Check_Fpu(); +} + +BackgroundReconfig::~BackgroundReconfig() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded art + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + if (!ignorePaletteFlag) + { + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + warehouse->palette8Bin.Release(paletteName); + } +# endif + //------------------------------------------------------------ + // Delete the names + //------------------------------------------------------------ + Unregister_Pointer(paletteName); + delete[] paletteName; + paletteName = NULL; + + Check_Fpu(); +} + +void + BackgroundReconfig::BecameActive() +{ + Check(this); + //------------------------------------------------------------ + // Get, lock pixelmap from warehouse + //------------------------------------------------------------ + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + Palette8 + *palette; + + if (ignorePaletteFlag) + { + palette = NULL; + } + else + { + palette = warehouse->palette8Bin.Get(paletteName); + Check(palette); + } + //------------------------------------------------- + // Remap the port + //------------------------------------------------- + Check(renderer); + ((L4GaugeRenderer *)renderer)->RemapGraphicsPort( + portNumber, // int port_number, + (SVGA16::PaletteID) paletteID, + (L4GraphicsPort::ChannelEnableID) enableID, + palette + ); + //------------------------------------------------- + // Release the palette (we're done with it) + //------------------------------------------------- + if (!ignorePaletteFlag) + { + warehouse->palette8Bin.Release(paletteName); + } + Check_Fpu(); +} + +//########################################################################### +// BackgroundLine +//########################################################################### +MethodDescription + BackgroundLine::methodDescription = + { + "bgLine", + BackgroundLine::Make, + { + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeInteger, NULL }, // 1=thick + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeColor, NULL }, // color + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BackgroundLine::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[1].CheckIt(ParameterDescription::typeInteger); // thick + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeColor); // color +# endif + + Test_Tell("BackgroundLine::Make\n"); + +# if DEBUG_LEVEL > 0 + BackgroundLine + *bg = +# endif + new BackgroundLine( + parameterList[0].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + parameterList[1].data.integer, // thick + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.color + ); + + Register_Object(bg); + + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("BackgroundLine::Make OK\n"); + Check_Fpu(); + return True; +} + +BackgroundLine::BackgroundLine( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int thick_flag, + int left, int bottom, int right, int top, + int color, + const char *identification_string +): + GraphicGaugeBackground( + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + + endpoints.bottomLeft.x = left; + endpoints.bottomLeft.y = bottom; + endpoints.topRight.x = right; + endpoints.topRight.y = top; + + thickFlag = thick_flag; + + localView.SetColor(color); + Check_Fpu(); +} + +void + BackgroundLine::BecameActive() +{ + Check(this); + //--------------------------------------------- + // Draw it + //--------------------------------------------- + localView.MoveToAbsolute(endpoints.bottomLeft.x, endpoints.bottomLeft.y); + + if (thickFlag) + { + localView.DrawThickLineToAbsolute( + endpoints.topRight.x, endpoints.topRight.y + ); + } + else + { + localView.DrawLineToAbsolute( + endpoints.topRight.x, endpoints.topRight.y + ); + } + Check_Fpu(); +} + +//########################################################################### +// BackgroundRect +//########################################################################### +MethodDescription + BackgroundRect::methodDescription = + { + "bgRect", + BackgroundRect::Make, + { + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeColor, NULL }, // color + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BackgroundRect::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[1].CheckIt(ParameterDescription::typeVector); // size + parameterList[2].CheckIt(ParameterDescription::typeColor); // color +# endif + + Test_Tell("BackgroundRect::Make\n"); + +# if DEBUG_LEVEL > 0 + BackgroundRect + *bg = +# endif + new BackgroundRect( + parameterList[0].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + position.x + parameterList[1].data.vector.x, + position.y + parameterList[1].data.vector.y, + parameterList[2].data.color + ); + + Register_Object(bg); + + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("BackgroundRect::Make OK\n"); + Check_Fpu(); + return True; +} + +BackgroundRect::BackgroundRect( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int top, int right, + int color, + const char *identification_string +): + GraphicGaugeBackground( + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + + endpoints.bottomLeft.x = left; + endpoints.bottomLeft.y = bottom; + endpoints.topRight.x = right; + endpoints.topRight.y = top; + + localView.SetColor(color); + Check_Fpu(); +} + +void + BackgroundRect::BecameActive() +{ + Check(this); + //--------------------------------------------- + // Draw it + //--------------------------------------------- + localView.MoveToAbsolute( + endpoints.bottomLeft.x, endpoints.bottomLeft.y + ); + localView.DrawRectangleToAbsolute( + endpoints.topRight.x, endpoints.topRight.y + ); + Check_Fpu(); +} + +//########################################################################### +// BackgroundFilledRect +//########################################################################### +MethodDescription + BackgroundFilledRect::methodDescription = + { + "bgFilledRect", + BackgroundFilledRect::Make, + { + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeColor, NULL }, // color + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BackgroundFilledRect::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[1].CheckIt(ParameterDescription::typeVector); // size + parameterList[2].CheckIt(ParameterDescription::typeColor); // color +# endif + + Test_Tell("BackgroundFilledRect::Make\n"); + + BackgroundFilledRect + *bg = + new BackgroundFilledRect( + parameterList[0].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + position.x + parameterList[1].data.vector.x, + position.y + parameterList[1].data.vector.y, + parameterList[2].data.color + ); + + Register_Object(bg); + + //--------------------------------------------------------------- + // Everything's ok: if 'always active', run once and then kill it + //--------------------------------------------------------------- + if ( + parameterList[0].data.modeMask == + (ModeMask) ModeManager::ModeAlwaysActive + ) + { + bg->BecameActive(); + + Unregister_Object(bg); + delete bg; + } + Test_Tell("BackgroundFilledRect::Make OK\n"); + Check_Fpu(); + return True; +} + +BackgroundFilledRect::BackgroundFilledRect( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int top, int right, + int color, + const char *identification_string +): + GraphicGaugeBackground( + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + + endpoints.bottomLeft.x = left; + endpoints.bottomLeft.y = bottom; + endpoints.topRight.x = right; + endpoints.topRight.y = top; + + localView.SetColor(color); + Check_Fpu(); +} + +void + BackgroundFilledRect::BecameActive() +{ + Check(this); + //--------------------------------------------- + // Draw it + //--------------------------------------------- + localView.MoveToAbsolute( + endpoints.bottomLeft.x, endpoints.bottomLeft.y + ); + localView.DrawFilledRectangleToAbsolute( + endpoints.topRight.x, endpoints.topRight.y + ); + Check_Fpu(); +} + +//########################################################################### +// BackgroundPixelMap +//########################################################################### +MethodDescription + BackgroundPixelmap::methodDescription = + { + "bgPixelMap", + BackgroundPixelmap::Make, + { + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeString, NULL }, // pixelmap name + { ParameterDescription::typeInteger, NULL }, // 1=opaque + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BackgroundPixelmap::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[1].CheckIt(ParameterDescription::typeString); // map name + parameterList[2].CheckIt(ParameterDescription::typeInteger); // opaque +# endif + + Test_Tell("BackgroundPixelmap::Make\n"); + + const char + *name = parameterList[1].data.string; + + BackgroundPixelmap + *bg = + new BackgroundPixelmap( + parameterList[0].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + name, //font name + parameterList[2].data.integer + ); + + Register_Object(bg); + + //-------------------------------------------------------- + // Make sure the map was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->pixelMap8Bin.Get(name) == NULL) + { + DEBUG_STREAM << + "BackgroundPixelmap::Missing image '" << name << "\n"; + Check_Fpu(); + return False; + } + else + { + warehouse->pixelMap8Bin.Release(name); + } + + //--------------------------------------------------------------- + // Everything's ok: if 'always active', run once and then kill it + //--------------------------------------------------------------- + if ( + parameterList[0].data.modeMask == + (ModeMask) ModeManager::ModeAlwaysActive + ) + { + bg->BecameActive(); + + Unregister_Object(bg); + delete bg; + } + Test_Tell("BackgroundPixelmap::Make OK\n"); + Check_Fpu(); + return True; +} + +BackgroundPixelmap::BackgroundPixelmap( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *pixelmap_name, + int opaque_flag, + const char *identification_string +): + GraphicGaugeBackground( + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + //------------------------------------------------------------ + // Save the map name + //------------------------------------------------------------ + pixelMapName = nameCopy(pixelmap_name); + opaqueFlag = opaque_flag; + //------------------------------------------------------------ + // Set origin + //------------------------------------------------------------ + localView.SetOrigin(left, bottom); + //------------------------------------------------------------ + // Order the font from the warehouse (pre-load for future use) + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + Check_Pointer(pixelMapName); + warehouse->pixelMap8Bin.Get(pixelMapName); +# endif + + Check_Fpu(); +} + +BackgroundPixelmap::~BackgroundPixelmap() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded art + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + Check_Pointer(pixelMapName); + warehouse->pixelMap8Bin.Release(pixelMapName); +# endif + //------------------------------------------------------------ + // Delete the map name + //------------------------------------------------------------ + Unregister_Pointer(pixelMapName); + delete[] pixelMapName; + pixelMapName = NULL; + + Check_Fpu(); +} + +Logical + BackgroundPixelmap::TestInstance() const +{ + Check_Pointer(pixelMapName); + return GraphicGaugeBackground::TestInstance(); +} + +void + BackgroundPixelmap::BecameActive() +{ + Check(this); + //--------------------------------------------- + // Get the image + //--------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + PixelMap8 + *map = warehouse->pixelMap8Bin.Get(pixelMapName); + + //--------------------------------------------- + // Draw it + //--------------------------------------------- + if (map != NULL) + { + Check(map); + localView.MoveToAbsolute(0,0); + localView.DrawPixelMap8(opaqueFlag, 0, map); + } + //--------------------------------------------- + // Release the image + //--------------------------------------------- + Check(warehouse); + warehouse->pixelMap8Bin.Release(pixelMapName); + Check_Fpu(); +} + +//########################################################################### +// BackgroundBitMap +//########################################################################### +MethodDescription + BackgroundBitmap::methodDescription = + { + "bgBitMap", + BackgroundBitmap::Make, + { + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeString, NULL }, // bitmap name + { ParameterDescription::typeInteger, NULL }, // 1=opaque + { ParameterDescription::typeColor, NULL }, // fg color + { ParameterDescription::typeColor, NULL }, // bg color(opaque) + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BackgroundBitmap::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[1].CheckIt(ParameterDescription::typeString); // map name + parameterList[2].CheckIt(ParameterDescription::typeInteger); // opaque + parameterList[3].CheckIt(ParameterDescription::typeColor); // fg color + parameterList[4].CheckIt(ParameterDescription::typeColor); // bg color +# endif + + Test_Tell("BackgroundBitMap::Make\n"); + + const char + *name = parameterList[1].data.string; + + BackgroundBitmap + *bg = + new BackgroundBitmap( + parameterList[0].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + name, //font name + parameterList[2].data.integer, + parameterList[3].data.color, + parameterList[4].data.color + ); + + Register_Object(bg); + + //-------------------------------------------------------- + // Make sure the map was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(name) == NULL) + { + DEBUG_STREAM << + "BackgroundBitmap::Missing image '" << name << "\n"; + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(name); + } + + //--------------------------------------------------------------- + // Everything's ok: if 'always active', run once and then kill it + //--------------------------------------------------------------- + if ( + parameterList[0].data.modeMask == + (ModeMask) ModeManager::ModeAlwaysActive + ) + { + bg->BecameActive(); + + Unregister_Object(bg); + delete bg; + } + Test_Tell("BackgroundBitmap::Make OK\n"); + Check_Fpu(); + return True; +} + +BackgroundBitmap::BackgroundBitmap( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int opaque_flag, + int fg_color, + int bg_color, + const char *identification_string +): + GraphicGaugeBackground( + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + //------------------------------------------------------------ + // Save the map name + //------------------------------------------------------------ + bitMapName = nameCopy(bitmap_name); + opaqueFlag = opaque_flag; + foregroundColor = fg_color; + backgroundColor = bg_color; + //------------------------------------------------------------ + // Set origin + //------------------------------------------------------------ + localView.SetOrigin(left, bottom); + //------------------------------------------------------------ + // Order the map from the warehouse (pre-load for future use) + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + Check_Pointer(bitMapName); + warehouse->bitMapBin.Get(bitMapName); +# endif + + Check_Fpu(); +} + +BackgroundBitmap::~BackgroundBitmap() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded art + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + Check_Pointer(bitMapName); + warehouse->bitMapBin.Release(bitMapName); +# endif + //------------------------------------------------------------ + // Delete the map name + //------------------------------------------------------------ + Unregister_Pointer(bitMapName); + delete[] bitMapName; + bitMapName = NULL; + + Check_Fpu(); +} + +Logical + BackgroundBitmap::TestInstance() const +{ + Check_Pointer(bitMapName); + return GraphicGaugeBackground::TestInstance(); +} + +void + BackgroundBitmap::BecameActive() +{ + Check(this); + //--------------------------------------------- + // Get the image + //--------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + BitMap + *map = warehouse->bitMapBin.Get(bitMapName); + + //--------------------------------------------- + // Draw it + //--------------------------------------------- + if (map != NULL) + { + Check(map); + localView.MoveToAbsolute(0,0); + localView.SetColor(foregroundColor); + + if (opaqueFlag) + { + localView.DrawBitMapOpaque(backgroundColor, 0, map); + } + else + { + localView.DrawBitMap(0, map); + } + } + //--------------------------------------------- + // Release the image + //--------------------------------------------- + Check(warehouse); + warehouse->pixelMap8Bin.Release(bitMapName); + Check_Fpu(); +} + +//########################################################################### +// RankAndScore +//########################################################################### + +#define RNSCHARWIDTH 6 +#define RNSCHARHEIGHT 8 +#define RNSSCOREDIGITS 8 +#define RNSRANK_X 2 +#define RNSLINE_X (RNSRANK_X+RNSCHARWIDTH+2) +#define RNSSCORE_X (RNSLINE_X+2) +#define RNS_Y 2 +#define RNSWIDTH (2+RNSCHARWIDTH+5+(RNSCHARWIDTH*RNSSCOREDIGITS)+2) +#define RNSHEIGHT (2+RNSCHARHEIGHT+2) + +MethodDescription + RankAndScore::methodDescription = + { + "rankAndScore", + RankAndScore::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeString, NULL }, // font name + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // foreground + PARAMETER_DESCRIPTION_END + } + }; + +Logical + RankAndScore::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeString); // font + parameterList[3].CheckIt(ParameterDescription::typeColor); // background + parameterList[4].CheckIt(ParameterDescription::typeColor); // foreground +# endif + + Test_Tell("RankAndScore::Make\n"); + +# if DEBUG_LEVEL > 0 + RankAndScore + *rank_and_score = +# endif + new RankAndScore( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + parameterList[2].data.string, //font name + parameterList[3].data.integer, //int background_color + parameterList[4].data.integer //int foreground_color + ); + + Register_Object(rank_and_score); + + //-------------------------------------------------------- + // Make sure the font was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL) + { + Test_Tell("RankAndScore::Missing font\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[2].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("RankAndScore::Make OK\n"); + Check_Fpu(); + return True; +} + +RankAndScore::RankAndScore( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *font_name, + int foreground_color, int background_color, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + Check(renderer); + // + //----------------------------------------------------------- + // Set internal values + //----------------------------------------------------------- + // + numericDisplayRank = new NumericDisplay( + (L4Warehouse *) renderer->warehousePointer, + RNSRANK_X,RNS_Y, + font_name, + 1, + NumericDisplay::unsignedFormat, + background_color, + foreground_color + ); + Register_Object(numericDisplayRank); + + numericDisplayScore = new NumericDisplay( + (L4Warehouse *) renderer->warehousePointer, + RNSSCORE_X,RNS_Y, + font_name, + RNSSCOREDIGITS, + NumericDisplay::signedBlankedZerosFormat, + background_color, + foreground_color + ); + Register_Object(numericDisplayScore); + + localView.SetPositionWithinPort( + left,bottom, + left+RNSWIDTH+1,bottom+RNSHEIGHT+1 + ); + + linkedEntity = NULL; + foregroundColor = foreground_color; + backgroundColor = background_color; + + Check_Fpu(); +} + +RankAndScore::~RankAndScore() +{ + Check(this); + + if (linkedEntity != NULL) + { + Player + *player; + + Check(linkedEntity); + player = linkedEntity->GetPlayerLink(); + Check(player); + //--------------------------------------- + // Truncate the score (no rounding) + //--------------------------------------- + DEBUG_STREAM << + "~RankAndScore: I think my score is " << + (int)(player->currentScore) << "\n"; + } + + if (numericDisplayRank != NULL) + { + Unregister_Object(numericDisplayRank); + delete numericDisplayRank; + numericDisplayRank = NULL; + } + if (numericDisplayScore != NULL) + { + Unregister_Object(numericDisplayScore); + delete numericDisplayScore; + numericDisplayScore = NULL; + } + + Check_Fpu(); +} + +Logical + RankAndScore::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + RankAndScore::ShowInstance(char */*indent*/) +{ +} + +void + RankAndScore::BecameActive() +{ + Check(this); + + previousState = False; + + Check(numericDisplayRank); + Check(numericDisplayScore); + + numericDisplayRank->ForceUpdate(); + numericDisplayScore->ForceUpdate(); + + Check_Fpu(); +} + +void + RankAndScore::LinkToEntity(Entity *entity) +{ + Test_Tell("RankAndScore::LinkToEntity\n" << std::flush); + Check(this); + + linkedEntity = entity; + Check_Fpu(); +} + +void + RankAndScore::Execute() +{ + Check(this); + Check(numericDisplayRank); + Check(numericDisplayScore); + + Check(application); + Logical + currentState = + (application->GetApplicationState() == Application::RunningMission); + + if (previousState != currentState) + { + previousState = currentState; + + if (currentState == True) + { + //------------------------------------------- + // Draw background + //------------------------------------------- + localView.SetColor(backgroundColor); + localView.MoveToAbsolute(1,1); + localView.DrawFilledRectangleToAbsolute(RNSWIDTH-1,RNSHEIGHT-1); + + localView.SetColor(foregroundColor); + localView.MoveToAbsolute(0,0); + localView.DrawRectangleToAbsolute(RNSWIDTH,RNSHEIGHT); + localView.MoveToAbsolute(RNSLINE_X,0); + localView.DrawLineToAbsolute(RNSLINE_X,RNSHEIGHT); + } + } + + if (currentState == True) + { + //------------------------------------------- + // Get 'our' placement + //------------------------------------------- + if (linkedEntity != NULL) + { + Player + *player; + + Check(linkedEntity); + player = linkedEntity->GetPlayerLink(); + Check(player); + //--------------------------------------- + // Truncate the score (no rounding) + //--------------------------------------- + int + integer_score = (int)(player->currentScore); + //--------------------------------------- + // Update displays + //--------------------------------------- + numericDisplayRank->Draw( + &localView, + player->playerRanking+1 + ); + numericDisplayScore->Draw( + &localView, + (Scalar) integer_score + ); + } + } + Check_Fpu(); +} + +//########################################################################### +// WipeGaugeScalar +//########################################################################### +WipeGaugeScalar::WipeGaugeScalar( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + Direction direction, + Scalar min, + Scalar max, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + // graphics_port may be NULL! + // + //----------------------------------------------------------- + // Initialize internal values + //----------------------------------------------------------- + // + width = right - left - 1; + height = top - bottom - 1; + Verify(width >= 0); + Verify(height >= 0); + + previousValue = -1234; + previousSize.MakeEmpty(); + + wipeDirection = direction; + minimumValue = min; + maximumValue = max - min; + Verify(maximumValue != 0); + + localView.SetPositionWithinPort(left, bottom, right, top); + + Check_Fpu(); +} + + +WipeGaugeScalar::~WipeGaugeScalar() +{ + Check(this); + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + WipeGaugeScalar::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + WipeGaugeScalar::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "WipeGaugeScalar:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "previousSize =" << previousSize << "\n"; + GraphicGauge::ShowInstance(temp); + Check_Fpu(); +} + +void + WipeGaugeScalar::BecameActive() +{ + Check(this); + forceUpdateFlag = True; + Check_Fpu(); +} + +void + WipeGaugeScalar::Execute() +{ + Check(this); + + int + new_value; + + Scalar + q; + + Rectangle2D + rectangle; + + // + //----------------------------------------------------------- + // Calculate new_value + //----------------------------------------------------------- + // + if (currentValue < minimumValue) + { + currentValue = minimumValue; + } + + currentValue -= minimumValue; + + if (currentValue > maximumValue) + { + currentValue = maximumValue; + } + + Verify(maximumValue != 0); + q = currentValue / maximumValue; + + if (q > 1.0) + { + q = 1.0; + } + else if (q < -1.0) + { + q = -1.0; + } + // + //----------------------------------------------------------- + // Update display + //----------------------------------------------------------- + // + switch(wipeDirection) + { + case wipeLeft: + new_value = width - (int) (width*q + .5); + + if (forceUpdateFlag) + { + forceUpdateFlag = False; + + rectangle.topRight.x = width; + rectangle.topRight.y = height; + rectangle.bottomLeft.x = new_value; + rectangle.bottomLeft.y = 0; + + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + + rectangle.topRight.x = new_value-1; + rectangle.bottomLeft.x = 0; + + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + else if (new_value > previousValue) + { + rectangle.topRight.x = new_value-1; + rectangle.topRight.y = height; + rectangle.bottomLeft.x = previousValue; + rectangle.bottomLeft.y = 0; + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + else if (previousValue > new_value) + { + rectangle.topRight.x = previousValue-1; + rectangle.topRight.y = height; + rectangle.bottomLeft.x = new_value; + rectangle.bottomLeft.y = 0; + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + previousValue = new_value; + } + break; + + case wipeDown: + new_value = height - (int) (height*q + .5); + + if (forceUpdateFlag) + { + forceUpdateFlag = False; + + rectangle.topRight.x = width; + rectangle.topRight.y = height; + rectangle.bottomLeft.x = 0; + rectangle.bottomLeft.y = new_value; + + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + + rectangle.topRight.y = new_value-1; + rectangle.bottomLeft.y = 0; + + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + else if (new_value > previousValue) + { + rectangle.topRight.x = width; + rectangle.topRight.y = new_value+1; + rectangle.bottomLeft.x = 0; + rectangle.bottomLeft.y = previousValue; + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + else if (previousValue > new_value) + { + rectangle.topRight.x = width; + rectangle.topRight.y = previousValue+1; + rectangle.bottomLeft.x = 0; + rectangle.bottomLeft.y = new_value; + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + previousValue = new_value; + } + break; + + case wipeRight: + new_value = (int) (width*q + .5); + + if (forceUpdateFlag) + { + forceUpdateFlag = False; + + rectangle.topRight.x = new_value; + rectangle.topRight.y = height; + rectangle.bottomLeft.x = 0; + rectangle.bottomLeft.y = 0; + + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + + rectangle.topRight.x = width; + rectangle.bottomLeft.x = new_value+1; + + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + else if (new_value > previousValue) + { + rectangle.topRight.x = new_value; + rectangle.topRight.y = height; + rectangle.bottomLeft.x = previousValue+1; + rectangle.bottomLeft.y = 0; + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + previousValue = new_value; + } + else if (previousValue > new_value) + { + rectangle.topRight.x = previousValue; + rectangle.topRight.y = height; + rectangle.bottomLeft.x = new_value+1; + rectangle.bottomLeft.y = 0; + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + break; + + case wipeUp: + new_value = (int) (height*q + .5); + + if (forceUpdateFlag) + { + forceUpdateFlag = False; + + rectangle.topRight.x = width; + rectangle.topRight.y = new_value; + rectangle.bottomLeft.x = 0; + rectangle.bottomLeft.y = 0; + + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + + rectangle.topRight.y = height; + rectangle.bottomLeft.y = new_value+1; + + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + else if (previousValue < new_value) + { + rectangle.topRight.x = width; + rectangle.topRight.y = new_value; + rectangle.bottomLeft.x = 0; + rectangle.bottomLeft.y = previousValue; + if (!rectangle.IsEmpty()) + { + DrawActive(&rectangle); + } + previousValue = new_value; + } + else if (previousValue > new_value) + { + rectangle.topRight.x = width; + rectangle.topRight.y = previousValue; + rectangle.bottomLeft.x = 0; + rectangle.bottomLeft.y = new_value; + if (!rectangle.IsEmpty()) + { + DrawInactive(&rectangle); + } + previousValue = new_value; + } + break; + } + Check_Fpu(); +} + +void + WipeGaugeScalar::DrawActive( + Rectangle2D */*rectangle*/ + ) +{ + Fail("WipeGaugeScalar::DrawActive is not overridden"); +} + +void + WipeGaugeScalar::DrawInactive( + Rectangle2D */*rectangle*/ + ) +{ + Fail("WipeGaugeScalar::DrawInactive is not overridden"); +} + +//########################################################################### +// BarGraphSolidScalar +//########################################################################### +MethodDescription + BarGraphSolidScalar::methodDescription = + { + "solidbar", + BarGraphSolidScalar::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeColor, NULL }, // foreground + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeString, NULL }, // direction + { ParameterDescription::typeScalar, NULL }, // min + { ParameterDescription::typeScalar, NULL }, // max + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BarGraphSolidScalar::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeColor); // foreground + parameterList[4].CheckIt(ParameterDescription::typeColor); // background + parameterList[5].CheckIt(ParameterDescription::typeString); // direction + parameterList[6].CheckIt(ParameterDescription::typeScalar); // min + parameterList[7].CheckIt(ParameterDescription::typeScalar); // max + parameterList[8].CheckIt(ParameterDescription::typeAttribute); // attribute +# endif + + Test_Tell("BarGraphSolidScalar::Make\n"); + + int + direction = configureDirection[0].Search( + parameterList[5].data.string + ); + + if (direction < 0) + { + Test_Tell("BarGraphSolidScalar::Make direction NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + BarGraphSolidScalar + *bar_graph = +# endif + new BarGraphSolidScalar( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // unsigned int owner_ID + display_port_index, // int graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.color, // int foreground_color + parameterList[4].data.color, // int background_color + (WipeGaugeScalar::Direction) direction, + parameterList[6].data.scalar, // Scalar min, + parameterList[7].data.scalar, // Scalar max, + (Scalar *) parameterList[8].data.attributePointer // Scalar *valptr + // HACK!!!! The (Scalar *) is VERY dangerous! + ); + + Register_Object(bar_graph); + + Test_Tell("BarGraphSolidScalar::Make OK\n"); + Check_Fpu(); + return True; +} + +BarGraphSolidScalar::BarGraphSolidScalar( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + int foreground_color, int background_color, + WipeGaugeScalar::Direction direction, + Scalar min, + Scalar max, + Scalar *value_pointer, + const char *identification_string +): + WipeGaugeScalar( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + left, bottom, right, top, + direction, + min, + max, + identification_string + ) +{ + backgroundColor = background_color; + foregroundColor = foreground_color; + + // + //----------------------------------------------------------- + // Build connection to value + // (if NULL, it's assumed that a derived object built the + // connection for us) + //----------------------------------------------------------- + // + if (value_pointer != NULL) + { + GaugeConnection + *connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Register_Object(connection); + AddConnection(connection); + } + Check_Fpu(); +} + +BarGraphSolidScalar::~BarGraphSolidScalar() +{ + Check(this); + Check_Fpu(); +} + +Logical + BarGraphSolidScalar::TestInstance() const +{ + return WipeGaugeScalar::TestInstance(); +} + +void + BarGraphSolidScalar::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "BarGraphSolidScalar:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "foregroundColor=" << foregroundColor << "\n"; + std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; + WipeGaugeScalar::ShowInstance(temp); + Check_Fpu(); +} + +void + BarGraphSolidScalar::DrawActive( + Rectangle2D *rectangle + ) +{ + localView.SetColor(foregroundColor); + localView.MoveToAbsolute( + rectangle->bottomLeft.x, + rectangle->bottomLeft.y + ); + localView.DrawFilledRectangleToAbsolute( + rectangle->topRight.x, + rectangle->topRight.y + ); + Check_Fpu(); +} + +void + BarGraphSolidScalar::DrawInactive( + Rectangle2D *rectangle + ) +{ + localView.SetColor(backgroundColor); + localView.MoveToAbsolute( + rectangle->bottomLeft.x, + rectangle->bottomLeft.y + ); + localView.DrawFilledRectangleToAbsolute( + rectangle->topRight.x, + rectangle->topRight.y + ); + Check_Fpu(); +} + + +//########################################################################### +// BarGraphBitMapScalar +//########################################################################### +MethodDescription + BarGraphBitMapScalar::methodDescription = + { + "bitmapbar", + BarGraphBitMapScalar::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // bit map name + { ParameterDescription::typeColor, NULL }, // foreground + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeString, NULL }, // direction + { ParameterDescription::typeScalar, NULL }, // min + { ParameterDescription::typeScalar, NULL }, // max + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BarGraphBitMapScalar::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // image name + parameterList[4].CheckIt(ParameterDescription::typeColor); // foreground + parameterList[5].CheckIt(ParameterDescription::typeColor); // background + parameterList[6].CheckIt(ParameterDescription::typeString); // direction + parameterList[7].CheckIt(ParameterDescription::typeScalar); // min + parameterList[8].CheckIt(ParameterDescription::typeScalar); // max + parameterList[9].CheckIt(ParameterDescription::typeAttribute); +# endif + + Test_Tell("BarGraphBitMapScalar::Make\n"); + + int + direction = configureDirection[0].Search( + parameterList[6].data.string + ); + + if (direction < 0) + { + Test_Tell("BarGraphBitMapScalar::Make direction NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + BarGraphBitMapScalar + *bar_graph = +# endif + new BarGraphBitMapScalar( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // owner_ID*/ + display_port_index, // graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, // BitMap name + parameterList[4].data.color, // int fg_color + parameterList[5].data.color, // int bg_color + (WipeGaugeScalar::Direction) direction, + parameterList[7].data.scalar, // Scalar min, + parameterList[8].data.scalar, // Scalar max, + (Scalar *) parameterList[9].data.attributePointer// Scalar *val_ptr + // HACK!!!! The (Scalar *) is VERY dangerous! + ); + + Register_Object(bar_graph); + //--------------------------------------------------------- + // Make sure the image was properly placed in the warehouse + //--------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL) + { + Test_Tell("BarGraphBitMapScalar::Missing bitmap\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[3].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("BarGraphBitMapScalar::Make OK\n"); + Check_Fpu(); + return True; +} + +BarGraphBitMapScalar::BarGraphBitMapScalar( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *bitmap_name, //BitMap *bit_map, + int foreground_color, int background_color, + WipeGaugeScalar::Direction direction, + Scalar min, + Scalar max, + Scalar *value_pointer, + const char *identification_string +): + WipeGaugeScalar( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + left, bottom, right, top, + direction, + min, + max, + identification_string + ) +{ + //------------------------------------------------------------ + // Save the bitmap name + //------------------------------------------------------------ + bitMapName = nameCopy(bitmap_name); + //------------------------------------------------------------- + // Save colors + //------------------------------------------------------------- + backgroundColor = background_color; + foregroundColor = foreground_color; + //------------------------------------------------------------- + // Order the image from the warehouse (pre-load for future use) + //------------------------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + Check_Pointer(bitMapName); + + ((L4Warehouse *)renderer->warehousePointer)->bitMapBin.Get(bitMapName); +# endif + //----------------------------------------------------------- + // Build connection to value + // (if NULL, it's assumed that a derived object built the + // connection for us) + //----------------------------------------------------------- + if (value_pointer != NULL) + { + GaugeConnection + *connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Register_Object(connection); + AddConnection(connection); + } + Check_Fpu(); +} + +BarGraphBitMapScalar::~BarGraphBitMapScalar() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded art + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + Check_Pointer(bitMapName); + ((L4Warehouse *)renderer->warehousePointer)-> + bitMapBin.Release(bitMapName); +# endif + //------------------------------------------------------------ + // Delete the bitmap name + //------------------------------------------------------------ + Unregister_Pointer(bitMapName); + delete[] bitMapName; + bitMapName = NULL; + + Check_Fpu(); +} + +Logical + BarGraphBitMapScalar::TestInstance() const +{ + return WipeGaugeScalar::TestInstance(); +} + +void + BarGraphBitMapScalar::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "BarGraphBitMapScalar:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "bitMapName= " << bitMapName << "\n"; + std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; + WipeGaugeScalar::ShowInstance(temp); + Check_Fpu(); +} + +void + BarGraphBitMapScalar::DrawActive( + Rectangle2D *rectangle + ) +{ + //----------------------------------------------------------- + // Get and lock the image so that we may use it + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + + Check_Pointer(bitMapName); + BitMap + *bit_map = renderer->warehousePointer->bitMapBin.Get(bitMapName); + //----------------------------------------------------------- + // Draw the image + //----------------------------------------------------------- + if (bit_map != NULL) + { + Check(bit_map); + localView.SetColor(foregroundColor); + + localView.MoveToAbsolute( + rectangle->bottomLeft.x, + rectangle->bottomLeft.y + ); + + localView.DrawBitMapOpaque( + backgroundColor, + 0, // rotation + bit_map, + rectangle->bottomLeft.x, + rectangle->bottomLeft.y, + rectangle->topRight.x, + rectangle->topRight.y + ); + } + //----------------------------------------------------------- + // Unlock the image: we're done + //----------------------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(bitMapName); + + Check_Fpu(); +} + +void + BarGraphBitMapScalar::DrawInactive( + Rectangle2D *rectangle + ) +{ + Check(this); + + localView.SetColor(backgroundColor); + + localView.MoveToAbsolute( + rectangle->bottomLeft.x, + rectangle->bottomLeft.y + ); + + localView.DrawFilledRectangleToAbsolute( + rectangle->topRight.x, + rectangle->topRight.y + ); + + Check_Fpu(); +} + +//########################################################################### +// BarGraphPixelMapScalar +//########################################################################### +MethodDescription + BarGraphPixelMapScalar::methodDescription = + { + "pixelbar", + BarGraphPixelMapScalar::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // pixel map name + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeString, NULL }, // direction + { ParameterDescription::typeScalar, NULL }, // min + { ParameterDescription::typeScalar, NULL }, // max + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + BarGraphPixelMapScalar::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // foreground + parameterList[4].CheckIt(ParameterDescription::typeColor); // background + parameterList[5].CheckIt(ParameterDescription::typeString); // direction + parameterList[6].CheckIt(ParameterDescription::typeScalar); // min + parameterList[7].CheckIt(ParameterDescription::typeScalar); // max + parameterList[8].CheckIt(ParameterDescription::typeAttribute); +# endif + + Test_Tell("BarGraphPixelMapScalar::Make\n"); + + int + direction = configureDirection[0].Search( + parameterList[5].data.string + ); + + if (direction < 0) + { + Test_Tell("BarGraphPixelMapScalar::Make direction NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + BarGraphPixelMapScalar + *bar_graph = +# endif + new BarGraphPixelMapScalar( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // owner_ID*/ + display_port_index, // graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, // PixelMap name + parameterList[4].data.color, // int bg_color + (WipeGaugeScalar::Direction) direction, + parameterList[6].data.scalar, // Scalar min, + parameterList[7].data.scalar, // Scalar max, + (Scalar *) parameterList[8].data.attributePointer //Scalar *valptr + // HACK!!!! The (Scalar *) is VERY dangerous! + ); + + Register_Object(bar_graph); + //--------------------------------------------------------- + // Make sure the image was properly placed in the warehouse + //--------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL) + { + Test_Tell("BarGraphPixelMapScalar::Missing pixelmap\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[3].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("BarGraphPixelMapScalar::Make OK\n"); + Check_Fpu(); + return True; +} + +BarGraphPixelMapScalar::BarGraphPixelMapScalar( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *pixelmap_name, //PixelMap8 *pixel_map, + int background_color, + WipeGaugeScalar::Direction direction, + Scalar min, + Scalar max, + Scalar *value_pointer, + const char *identification_string +): + WipeGaugeScalar( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + left, bottom, right, top, + direction, + min, + max, + identification_string + ) +{ + //------------------------------------------------------------- + // Make local copy of map name + //------------------------------------------------------------- + Check_Pointer(pixelmap_name); + pixelMapName = nameCopy(pixelmap_name); + Check_Pointer(pixelMapName); + //------------------------------------------------------------- + // Save background color + //------------------------------------------------------------- + backgroundColor = background_color; + //------------------------------------------------------------- + // Order the image from the warehouse (pre-load for future use) + //------------------------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + + ((L4Warehouse *) renderer->warehousePointer)-> + pixelMap8Bin.Get(pixelMapName); +# endif + //----------------------------------------------------------- + // Build connection to value + // (if NULL, it's assumed that a derived object built the + // connection for us) + //----------------------------------------------------------- + // + if (value_pointer != NULL) + { + GaugeConnection + *connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Register_Object(connection); + AddConnection(connection); + } + Check_Fpu(); +} + +BarGraphPixelMapScalar::~BarGraphPixelMapScalar() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded image + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + Check_Pointer(pixelMapName); + + ((L4Warehouse *) renderer->warehousePointer)-> + pixelMap8Bin.Get(pixelMapName); +# endif + //------------------------------------------------------------ + // Delete the map name + //------------------------------------------------------------ + Unregister_Pointer(pixelMapName); + delete[] pixelMapName; + pixelMapName = NULL; + + Check_Fpu(); +} + +Logical + BarGraphPixelMapScalar::TestInstance() const +{ + return WipeGaugeScalar::TestInstance(); +} + +void + BarGraphPixelMapScalar::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "BarGraphPixelMapScalar:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "pixelMapName= " << pixelMapName << "\n"; + std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; + WipeGaugeScalar::ShowInstance(temp); + Check_Fpu(); +} + +void + BarGraphPixelMapScalar::DrawActive( + Rectangle2D *rectangle + ) +{ + //----------------------------------------------------------- + // Get and lock the image so that we may use it + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + + Check_Pointer(pixelMapName); + PixelMap8 + *pixel_map = renderer->warehousePointer->pixelMap8Bin.Get(pixelMapName); + //----------------------------------------------------------- + // Draw the image + //----------------------------------------------------------- + if (pixel_map != NULL) + { + Check(pixel_map); + + localView.MoveToAbsolute( + rectangle->bottomLeft.x, + rectangle->bottomLeft.y + ); + + localView.DrawPixelMap8( + False, // opaque, + 0, // rotation + pixel_map, + rectangle->bottomLeft.x, + rectangle->bottomLeft.y, + rectangle->topRight.x, + rectangle->topRight.y + ); + } + //----------------------------------------------------------- + // Unlock the image: we're done + //----------------------------------------------------------- + Check(warehouse); + warehouse->pixelMap8Bin.Release(pixelMapName); + + Check_Fpu(); +} + +void + BarGraphPixelMapScalar::DrawInactive( + Rectangle2D *rectangle + ) +{ + //----------------------------------------------------------- + // Get and lock the image so that we may use it + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + + Check_Pointer(pixelMapName); + PixelMap8 + *pixel_map = renderer->warehousePointer->pixelMap8Bin.Get(pixelMapName); + //----------------------------------------------------------- + // Draw the image + //----------------------------------------------------------- + if (pixel_map != NULL) + { + Check(pixel_map); + + localView.SetColor(backgroundColor); + + localView.MoveToAbsolute( + rectangle->bottomLeft.x, + rectangle->bottomLeft.y + ); + + localView.DrawPixelMap8SingleColor( + 0, // rotation + pixel_map, + rectangle->bottomLeft.x, + rectangle->bottomLeft.y, + rectangle->topRight.x, + rectangle->topRight.y + ); + } + //----------------------------------------------------------- + // Unlock the image: we're done + //----------------------------------------------------------- + Check(warehouse); + warehouse->pixelMap8Bin.Release(pixelMapName); + + Check_Fpu(); +} + +//####################################################################### +// ColorState +//####################################################################### +MethodDescription + ColorState::methodDescription= + { + "colorState", + ColorState::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeString, NULL }, // bitmap name + { ParameterDescription::typeColor, NULL }, // color 0 + { ParameterDescription::typeScalar, NULL }, // 0...a + { ParameterDescription::typeColor, NULL }, // color 1 + { ParameterDescription::typeScalar, NULL }, // a...b + { ParameterDescription::typeColor, NULL }, // color 2 + { ParameterDescription::typeScalar, NULL }, // b...c + { ParameterDescription::typeColor, NULL }, // color 3 + { ParameterDescription::typeScalar, NULL }, // c...d + { ParameterDescription::typeColor, NULL }, // color 4 (+) + { ParameterDescription::typeInteger, NULL }, // zone # + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + ColorState::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeString); // bitmap name + parameterList[3].CheckIt(ParameterDescription::typeColor); // first color + parameterList[4].CheckIt(ParameterDescription::typeScalar); // first range + parameterList[5].CheckIt(ParameterDescription::typeColor); // second color + parameterList[6].CheckIt(ParameterDescription::typeScalar); // second range + parameterList[7].CheckIt(ParameterDescription::typeColor); // third color + parameterList[8].CheckIt(ParameterDescription::typeScalar); // third range + parameterList[9].CheckIt(ParameterDescription::typeColor); // fourth color + parameterList[10].CheckIt(ParameterDescription::typeScalar);// fourth range + parameterList[11].CheckIt(ParameterDescription::typeColor); // fifth color + parameterList[12].CheckIt(ParameterDescription::typeInteger); // zone # + parameterList[13].CheckIt(ParameterDescription::typeAttribute); +# endif + + Test_Tell("ColorState::Make\n"); + +# if DEBUG_LEVEL > 0 + ColorState + *color_state = +# endif + new ColorState( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // unsigned int owner_ID + display_port_index, // int graphics_port_number + position.x, position.y, + parameterList[2].data.string, + parameterList[3].data.color, + parameterList[4].data.scalar, + parameterList[5].data.color, + parameterList[6].data.scalar, + parameterList[7].data.color, + parameterList[8].data.scalar, + parameterList[9].data.color, + parameterList[10].data.scalar, + parameterList[11].data.color, + parameterList[12].data.integer, + (DamageZone ***) parameterList[13].data.attributePointer + // HACK!!!! The cast above is VERY dangerous! + ); + + Register_Object(color_state); + //--------------------------------------------------------- + // Make sure the image was properly placed in the warehouse + //--------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL) + { + Test_Tell("ColorState::Missing pixelmap\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[2].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("ColorState::Make OK\n"); + Check_Fpu(); + return True; +} + +ColorState::ColorState( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int first_color, + Scalar first_bin, + int second_color, + Scalar second_bin, + int third_color, + Scalar third_bin, + int fourth_color, + Scalar fourth_bin, + int fifth_color, + int zone_number, + DamageZone ***value_pointer, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("ColorState creator\n" << std::flush); + Check(renderer); + //------------------------------------------------------------ + // Save the map name + //------------------------------------------------------------ + bitMapName = nameCopy(bitmap_name); + //------------------------------------------------------------- + // Order the image from the warehouse (pre-load for future use) + //------------------------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + Check_Pointer(bitMapName); + + ((L4Warehouse *)renderer->warehousePointer)-> + bitMapBin.Get(bitMapName); +# endif + //------------------------------------------------------------- + // Initialize values + //------------------------------------------------------------- + localView.SetOrigin(left, bottom); + + color[0] = first_color; + color[1] = second_color; + color[2] = third_color; + color[3] = fourth_color; + color[4] = fifth_color; + + bin[0] = first_bin; + bin[1] = second_bin; + bin[2] = third_bin; + bin[3] = fourth_bin; + + Test_Tell("value_pointer=" << value_pointer << "\n" << std::flush); + Check_Pointer(value_pointer); + DamageZone + **array_pointer = *value_pointer; + Test_Tell("array_pointer=" << array_pointer << "\n" << std::flush); + Check_Pointer(array_pointer); + + Test_Tell("zone_number=" << zone_number << "\n" << std::flush); + damagePointer = array_pointer[zone_number]; + Test_Tell("damagePointer=" << damagePointer << "\n" << std::flush); + Check(damagePointer); + + Check_Fpu(); +} + +ColorState::~ColorState() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded art + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + Check_Pointer(bitMapName); + ((L4Warehouse *)renderer->warehousePointer)-> + bitMapBin.Release(bitMapName); +# endif + //------------------------------------------------------------ + // Delete the map name + //------------------------------------------------------------ + Unregister_Pointer(bitMapName); + delete[] bitMapName; + bitMapName = NULL; + + Check_Fpu(); +} + +Logical + ColorState::TestInstance() const +{ + return True; +} + +void + ColorState::ShowInstance(char */*indent*/) +{ + Check_Fpu(); +} + +void + ColorState::BecameActive() +{ + Check(this); + + previousState = -1; +} + +void + ColorState::Execute() +{ + Check(this); + + //----------------------------------------------------------- + // Get and lock the image so that we may use it + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + + Check_Pointer(bitMapName); + BitMap + *bit_map = renderer->warehousePointer->bitMapBin.Get(bitMapName); + //----------------------------------------------------------- + // Draw the image + //----------------------------------------------------------- + if (bit_map != NULL) + { + Check(bit_map); + Check(damagePointer); + Scalar + value(damagePointer->damageLevel); + int + i; + //---------------------------------------- + // Find current bin + //---------------------------------------- + for(i=0; i<4; ++i) + { + if (value < bin[i]) + { + break; + } + } + //---------------------------------------- + // If different, draw it + //---------------------------------------- + if (i != previousState) + { + previousState = i; + + localView.SetColor(color[i]); + localView.DrawBitMap(0, bit_map); + } + } + //----------------------------------------------------------- + // Unlock the image: we're done + //----------------------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(bitMapName); + + Check_Fpu(); +} + +//####################################################################### +// TwoState +//####################################################################### +MethodDescription + TwoState::methodDescription= + { + "twoState", + TwoState::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeString, NULL }, // bitmap name + { ParameterDescription::typeColor, NULL }, // color 0 + { ParameterDescription::typeColor, NULL }, // color 1 + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + TwoState::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeString); // bitmap name + parameterList[3].CheckIt(ParameterDescription::typeColor); // first color + parameterList[4].CheckIt(ParameterDescription::typeColor); // second color + parameterList[5].CheckIt(ParameterDescription::typeAttribute); +# endif + + Test_Tell("TwoState::Make\n"); + +# if DEBUG_LEVEL > 0 + TwoState + *two_state = +# endif + new TwoState( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + parameterList[2].data.string, //bitmap name + parameterList[3].data.color, + parameterList[4].data.color, + (int *) parameterList[5].data.attributePointer + // HACK!!!! The cast above is VERY dangerous! + ); + + Register_Object(two_state); + //--------------------------------------------------------- + // Make sure the image was properly placed in the warehouse + //--------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL) + { + Test_Tell("TwoState::Missing bitmap\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[2].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("TwoState::Make OK\n"); + Check_Fpu(); + return True; +} + +TwoState::TwoState( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int first_color, + int second_color, + int *value_pointer, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("TwoState creator\n" << std::flush); + Check_Pointer(this); + + //------------------------------------------------------------ + // Save the bitmap name + //------------------------------------------------------------ + bitMapName = nameCopy(bitmap_name); + //------------------------------------------------------------- + // Order the image from the warehouse (pre-load for future use) + //------------------------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + Check_Pointer(bitMapName); + + ((L4Warehouse *)renderer->warehousePointer)-> + bitMapBin.Get(bitMapName); +# endif + //----------------------------------------------------------- + // Initialize values + //----------------------------------------------------------- + localView.SetOrigin(left, bottom); + + color[0] = first_color; + color[1] = second_color; + //----------------------------------------------------------- + // Build connection to value + //----------------------------------------------------------- + GaugeConnection + *connection; + + connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Register_Object(connection); + AddConnection(connection); + + Check_Fpu(); +} + +TwoState::~TwoState() +{ + Check(this); + //------------------------------------------------------------ + // Unlock preloaded art + //------------------------------------------------------------ +# if defined(PRELOAD_ART) + Check(renderer); + Check(renderer->warehousePointer); + Check_Pointer(bitMapName); + ((L4Warehouse *)renderer->warehousePointer)-> + bitMapBin.Release(bitMapName); +# endif + //------------------------------------------------------------ + // Delete the bitmap name + //------------------------------------------------------------ + Unregister_Pointer(bitMapName); + delete[] bitMapName; + bitMapName = NULL; + + Check_Fpu(); +} + +Logical + TwoState::TestInstance() const +{ + return True; +} + +void + TwoState::ShowInstance(char */*indent*/) +{ + Check_Fpu(); +} + +void + TwoState::BecameActive() +{ + Check(this); + previousState = -1; + Check_Fpu(); +} + +void + TwoState::Execute() +{ + Check(this); + //----------------------------------------------------------- + // Get and lock the image so that we may use it + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + + Check_Pointer(bitMapName); + BitMap + *bit_map = renderer->warehousePointer->bitMapBin.Get(bitMapName); + //----------------------------------------------------------- + // Draw the image + //----------------------------------------------------------- + if (bit_map != NULL) + { + Check(bit_map); + + int + new_value; + + if (currentValue > 0) + { + new_value = 1; + } + else + { + new_value = 0; + } + + if (new_value != previousState) + { + previousState = new_value; + + localView.SetColor(color[new_value]); + localView.DrawBitMap(0, bit_map); + } + } + //----------------------------------------------------------- + // Unlock the image: we're done + //----------------------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(bitMapName); + + Check_Fpu(); +} + +//########################################################################### +// NumericDisplayScalarTwoState +//########################################################################### +MethodDescription + NumericDisplayScalarTwoState ::methodDescription = + { + "numericIntegerTwoState", + NumericDisplayScalarTwoState::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // font name + { ParameterDescription::typeInteger, NULL }, // # of digits + { ParameterDescription::typeString, NULL }, // format + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // foreground + { ParameterDescription::typeAttribute, NULL }, // attribute for number + { ParameterDescription::typeAttribute, NULL }, // attribute for logical + PARAMETER_DESCRIPTION_END + } + }; + +Logical + NumericDisplayScalarTwoState::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // font + parameterList[4].CheckIt(ParameterDescription::typeInteger); // # of digs + parameterList[5].CheckIt(ParameterDescription::typeString); // format + parameterList[6].CheckIt(ParameterDescription::typeColor); // background + parameterList[7].CheckIt(ParameterDescription::typeColor); // foreground + parameterList[8].CheckIt(ParameterDescription::typeAttribute); // value name + parameterList[9].CheckIt(ParameterDescription::typeAttribute); // second value name +# endif + + Test_Tell("NumericDisplayScalarTwoState::Make\n"); + + int + number_format = configureFormat[0].Search( + parameterList[5].data.string + ); + + if (number_format < 0) + { + Test_Tell("NumericDisplayScalarTwoState::Make format NOT FOUND\n"); + Check_Fpu(); + return False; + } + +# if DEBUG_LEVEL > 0 + NumericDisplayScalarTwoState + *numeric_display = +# endif + new NumericDisplayScalarTwoState( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, //font name + parameterList[4].data.integer, //int number_of_chars + (NumericDisplay::NumericFormat) number_format, + parameterList[6].data.integer, //int background_color + parameterList[7].data.integer, //int foreground_color + (Scalar *) parameterList[8].data.attributePointer, + (int *) parameterList[9].data.attributePointer // second (logical) value + // HACK!!!! The (Scalar *) is VERY dangerous! + // HACK!!!! The (int *) is VERY dangerous! + ); + Register_Object(numeric_display); + + //-------------------------------------------------------- + // Make sure the font was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[3].data.string) == NULL) + { + Test_Tell("NumericDisplayScalarTwoState::Missing font\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[3].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("NumericDisplayScalarTwoState::Make OK\n"); + Check_Fpu(); + return True; +} + +NumericDisplayScalarTwoState::NumericDisplayScalarTwoState( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, + int number_of_digits, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + Scalar *value_pointer, + int *logical_pointer, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + // graphics_port may be NULL! + Check_Pointer(value_pointer); + Check(renderer); + //----------------------------------------------------------- + // Set internal values + //----------------------------------------------------------- + numericDisplay = new NumericDisplay( + (L4Warehouse *) renderer->warehousePointer, + 0,0, + font_name, + number_of_digits, + requested_format, + background_color, + foreground_color + ); + Register_Object(numericDisplay); + + localView.SetPositionWithinPort(left, bottom, right, top); + + color[0] = background_color; + color[1] = foreground_color; + //----------------------------------------------------------- + // Build connection to value + //----------------------------------------------------------- + GaugeConnection + *value_connection; + + GaugeConnection + *logical_connection; + + value_connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Register_Object(value_connection); + AddConnection(value_connection); + + + logical_connection = new + GaugeConnectionDirectOf(0, ¤tLogical, logical_pointer); + Register_Object(logical_connection); + AddConnection(logical_connection); + + previousValue = currentValue; + Check_Fpu(); +} + +NumericDisplayScalarTwoState::~NumericDisplayScalarTwoState() +{ + Check(this); + + if (numericDisplay != NULL) + { + Unregister_Object(numericDisplay); + delete numericDisplay; + numericDisplay = NULL; + } + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + NumericDisplayScalarTwoState::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + NumericDisplayScalarTwoState::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "NumericDisplayScalarTwoState:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + GraphicGauge::ShowInstance(temp); + Check(numericDisplay); + numericDisplay->ShowInstance(temp); + Check_Fpu(); +} + +void + NumericDisplayScalarTwoState::BecameActive() +{ + Check(this); + Check(numericDisplay); + previousState = -1; + numericDisplay->ForceUpdate(); + Check_Fpu(); +} + +#if 0 +void + NumericDisplayScalarTwoState::SetColors(int bg_color, int fg_color) +{ + Check(this); + numericDisplay->SetColors(bg_color, fg_color); + Check_Fpu(); +} +#endif + +void + NumericDisplayScalarTwoState::Execute() +{ + Check(this); + Check(numericDisplay); + + int new_logical; + if (currentLogical > 0) + { + new_logical = 1; + } + else + { + new_logical = 0; + } + + // Draw if state has changed. NumericDisplay only redraws if value has changed + if (new_logical != previousState || currentValue != previousValue) + { + previousState = new_logical; + previousValue = currentValue; + if (currentLogical > 0) + { + numericDisplay->Draw(&localView,currentValue); + } + else + { + numericDisplay->Erase(&localView); + } + } + Check_Fpu(); +} + + + +//####################################################################### +// SegmentArc +//####################################################################### +SegmentArc::SegmentArc( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int center_x, int center_y, + Scalar inner0, Scalar outer0, + Scalar inner1, Scalar outer1, + Scalar deg0, Scalar deg1, + int number_of_segs_and_direction, + int background_color, + int foreground_color, + Logical use_thick_lines, + const char *identification_string +) : + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("SegmentArc creator\n" << std::flush); + Check_Pointer(this); + + + backgroundColor = background_color; + foregroundColor = foreground_color; + numberOfSegments = number_of_segs_and_direction; + startAngle = deg0*(2.0*M_PI)/360; + innerRadius = inner0; + outerRadius = outer0; + useThickLines = use_thick_lines; + + if (numberOfSegments < 0) + { + numberOfSegments = - numberOfSegments; + } + Verify(numberOfSegments > 0); + + Scalar + total_angle = (deg1*(2.0*M_PI)/360) - startAngle; + + if (number_of_segs_and_direction > 0) + { + if (total_angle < 0.0) + { + total_angle += (2.0*M_PI); + } + } + else + { + if (total_angle > 0.0) + { + total_angle -= (2.0*M_PI); + } + } + deltaAngle = (total_angle)/numberOfSegments; + deltaInnerRadius = (inner1 - inner0)/numberOfSegments; + deltaOuterRadius = (outer1 - outer0)/numberOfSegments; + + localView.SetOrigin(center_x, center_y); + + Check_Fpu(); +} + +SegmentArc::~SegmentArc() +{ + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + SegmentArc::TestInstance() const +{ + return True; +} + +void + SegmentArc::ShowInstance(char */*indent*/) +{ + + std::cout << "SegmentArc\n"; + std::cout << " backgroundColor = " << backgroundColor << "\n"; + std::cout << " foregroundColor = " << foregroundColor << "\n"; + std::cout << " numberOfSegments = " << numberOfSegments << "\n"; + std::cout << " startAngle = " << startAngle << "\n"; + std::cout << " deltaAngle = " << deltaAngle << "\n"; + std::cout << " deltaInnerRadius = " << deltaInnerRadius << "\n"; + std::cout << " deltaOuterRadius = " << deltaOuterRadius << "\n"; + std::cout << " previousSegment = " << previousSegment << "\n"; + Check_Fpu(); +} + +void + SegmentArc::BecameActive() +{ + Check(this); + + previousSegment = 0; +} + +void + SegmentArc::Execute() +{ + Check(this); + + if (currentValue < (Scalar) 0) + { + currentValue = (Scalar) 0; + } + else if (currentValue > (Scalar) 1) + { + currentValue = (Scalar) 1; + } + + Verify(numberOfSegments > 0); + + int + i, + new_segment = (int) (currentValue * numberOfSegments + .5); + Scalar + inner_radius, + delta_inner, + outer_radius, + delta_outer, + segment_angle, + delta_angle, + segment_sin, + segment_cos; + + if (new_segment != previousSegment) + { + if (new_segment > previousSegment) + { + localView.SetColor(foregroundColor); + + i = new_segment - previousSegment; // how many segments + + inner_radius = innerRadius + (previousSegment * deltaInnerRadius); + outer_radius = outerRadius + (previousSegment * deltaOuterRadius); + segment_angle = startAngle + (previousSegment * deltaAngle); + } + else + { + localView.SetColor(backgroundColor); + + i = previousSegment - new_segment; // how many segments + + inner_radius = innerRadius + (new_segment * deltaInnerRadius); + outer_radius = outerRadius + (new_segment * deltaOuterRadius); + segment_angle = startAngle + (new_segment * deltaAngle); + } + + delta_outer = deltaOuterRadius; + delta_inner = deltaInnerRadius; + delta_angle = deltaAngle; + + for(; i>=0; --i) + { + segment_sin = sin(segment_angle); + segment_cos = cos(segment_angle); + + localView.MoveToAbsolute( + (int)(segment_sin*inner_radius + .5), + (int)(segment_cos*inner_radius + .5) + ); + + if (useThickLines) + { + localView.DrawThickLineToAbsolute( + (int)(segment_sin*outer_radius + .5), + (int)(segment_cos*outer_radius + .5) + ); + } + else + { + localView.DrawLineToAbsolute( + (int)(segment_sin*outer_radius + .5), + (int)(segment_cos*outer_radius + .5) + ); + } + + inner_radius += delta_inner; + outer_radius += delta_outer; + segment_angle += delta_angle; + } + + previousSegment = new_segment; + } + Check_Fpu(); +} + +//####################################################################### +// SegmentArcNormalized +//####################################################################### +MethodDescription + SegmentArcNormalized::methodDescription = + { + "segmentArc", + SegmentArcNormalized::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeScalar, NULL }, // inner 0 + { ParameterDescription::typeScalar, NULL }, // outer 0 + { ParameterDescription::typeScalar, NULL }, // inner 1 + { ParameterDescription::typeScalar, NULL }, // outer 1 + { ParameterDescription::typeScalar, NULL }, // deg 0 + { ParameterDescription::typeScalar, NULL }, // deg 1 + { ParameterDescription::typeInteger, NULL }, // segs + { ParameterDescription::typeColor, NULL }, // fg + { ParameterDescription::typeColor, NULL }, // bg + { ParameterDescription::typeAttribute, NULL }, // attribute + PARAMETER_DESCRIPTION_END + } + }; + +Logical + SegmentArcNormalized::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // rate ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeScalar); // inner0 + parameterList[3].CheckIt(ParameterDescription::typeScalar); // outer0 + parameterList[4].CheckIt(ParameterDescription::typeScalar); // inner1 + parameterList[5].CheckIt(ParameterDescription::typeScalar); // outer1 + parameterList[6].CheckIt(ParameterDescription::typeScalar); // deg0 + parameterList[7].CheckIt(ParameterDescription::typeScalar); // deg1 + parameterList[8].CheckIt(ParameterDescription::typeInteger); // segs&dir + parameterList[9].CheckIt(ParameterDescription::typeColor); // bg color + parameterList[10].CheckIt(ParameterDescription::typeColor); // fg color + parameterList[11].CheckIt(ParameterDescription::typeAttribute); +# endif + + Test_Tell("SegmentArcNormalized::Make\n"); + +# if DEBUG_LEVEL > 0 + SegmentArcNormalized + *arc = +# endif + new SegmentArcNormalized( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // unsigned int owner_ID + display_port_index, // int graphics_port_number + position.x, position.y, + parameterList[2].data.scalar, // inner0 + parameterList[3].data.scalar, // outer0 + parameterList[4].data.scalar, // inner1 + parameterList[5].data.scalar, // outer1 + parameterList[6].data.scalar, // deg0 + parameterList[7].data.scalar, // deg1 + parameterList[8].data.integer, // segs & dir + parameterList[9].data.color, // bg + parameterList[10].data.color, // fg + (Scalar *) parameterList[11].data.attributePointer, + True // use thick lines + + // HACK - cast is VERY DANGEROUS! + ); + + Register_Object(arc); + + Test_Tell("SegmentArcNormalized::Make OK\n"); + Check_Fpu(); + return True; +} + +SegmentArcNormalized::SegmentArcNormalized( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int center_x, int center_y, + Scalar inner0, Scalar outer0, + Scalar inner1, Scalar outer1, + Scalar deg0, Scalar deg1, + int number_of_segs_and_direction, + int background_color, + int foreground_color, + Scalar *value_pointer, + Logical use_thick_lines, + const char *identification_string +) : + SegmentArc( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + center_x, center_y, + inner0, outer0, + inner1, outer1, + deg0, deg1, + number_of_segs_and_direction, + background_color, + foreground_color, + use_thick_lines, + identification_string + ) +{ + Test_Tell("SegmentArcNormalized creator\n" << std::flush); + Check_Pointer(this); + + //----------------------------------------------------------- + // Build connection to value + //----------------------------------------------------------- + GaugeConnection + *connection; + + connection = new + GaugeConnectionDirectOf(0, ¤tValue, value_pointer); + Check(connection); + Register_Object(connection); + + AddConnection(connection); + + Check_Fpu(); +} diff --git a/MUNGA_L4/L4GAUGE.h b/MUNGA_L4/L4GAUGE.h new file mode 100644 index 0000000..9e8a278 --- /dev/null +++ b/MUNGA_L4/L4GAUGE.h @@ -0,0 +1,1162 @@ +#pragma once + +#include "..\munga\gaugrend.h" +#include "..\munga\gauge.h" +#include "l4wrhous.h" +#include "l4vb16.h" + +extern char + *nameCopy(const char *old_name); +// +//-------------------------------------------------------------------------- +// NumericDisplay +// +// - displays a formatted numeric value. +// allowed formats are: +// unsignedFormat which displays an unsigned value of (N) digits +// signedFormat which displays + or - and (N-1) digits +// timeFormat which pairs of digits seperated by colons: HH:MM:SS +// ...where N = number_of_chars (below). +//-------------------------------------------------------------------------- +// +class NumericDisplay SIGNATURED +{ +public: + enum NumericFormat + { + unsignedFormat, + signedFormat, + signedBlankedZerosFormat, + absoluteFormat, + timeFormat + }; + + NumericDisplay( + L4Warehouse *warehouse, + int x_position, int y_position, + const char *font_name, //BitMap *font_bitmap, + int number_of_digits, + NumericFormat requested_format, + int background_color, int foreground_color + ); + + ~NumericDisplay(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + ForceUpdate(); + + void + SetColors( + int bg_color, + int fg_color + ); + void + Draw( + GraphicsView *graphics_view, + Scalar current_value + ); + void + Erase( + GraphicsView *graphics_view + ); + enum + { + maxDigits = 16 + }; + + enum + { + blankedDigit = 127, + plusDigit=10, + minusDigit, + decimalDigit, + colonDigit, + totalDigitsPerFont + }; +protected: + +L4Warehouse + *warehouse; +char + *digitMapName; +int + digitWidth, + digitHeight, + numberOfDigits, + backgroundColor, + foregroundColor, + offsetX, + offsetY; +NumericFormat + format; +Scalar + largestValue, + previousValue; +Logical + erased; +char + previousDigit[maxDigits]; +}; + +// +//-------------------------------------------------------------------------- +// NumericDisplayScalar +// +// - displays a formatted numeric value as a gauge. +//-------------------------------------------------------------------------- +// +class NumericDisplayScalar : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + NumericDisplayScalar( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, //BitMap *font_bitmap, + int number_of_chars, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + Scalar *value_pointer, + const char *identification_string = "NumericDisplayScalar" + ); + + ~NumericDisplayScalar(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + SetColors( + int bg_color, + int fg_color + ); + void + Execute(); + +protected: + NumericDisplay + *numericDisplay; + Scalar + currentValue; +}; + +// +//-------------------------------------------------------------------------- +// NumericDisplaySpeed +// +// - converts Scalar input(MPS) to be displayed as KPH +//-------------------------------------------------------------------------- +// +class NumericDisplaySpeed : + public NumericDisplayScalar +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + NumericDisplaySpeed( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, //BitMap *font_bitmap, + int number_of_chars, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + Scalar *value_pointer + ); + + void + Execute(); +}; + +// +//-------------------------------------------------------------------------- +// NumericDisplayInteger +// +// - displays a formatted numeric value as a gauge. +//-------------------------------------------------------------------------- +// +class NumericDisplayInteger : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + NumericDisplayInteger( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, //BitMap *font_bitmap, + int number_of_chars, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + int *value_pointer, + const char *identification_string = "NumericDisplayInteger" + ); + + ~NumericDisplayInteger(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + SetColors( + int bg_color, + int fg_color + ); + void + Execute(); + +protected: + NumericDisplay + *numericDisplay; + int + currentValue; +}; + +// +//-------------------------------------------------------------------------- +// DigitalClock +// +//-------------------------------------------------------------------------- +// +class DigitalClock : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + DigitalClock( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, //BitMap *font_bitmap, + int number_of_chars, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + const char *identification_string = "DigitalClock" + ); + + ~DigitalClock(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + BecameActive(); + + void + Execute(); + +protected: + NumericDisplay + *numericDisplay; +}; + +class RankAndScore : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + RankAndScore( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *font_name, + int background_color, int foreground_color, + const char *identification_string = "RankAndScore" + ); + + ~RankAndScore(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + LinkToEntity(Entity *entity); + void + BecameActive(); + void + Execute(); + +protected: + NumericDisplay + *numericDisplayRank, + *numericDisplayScore; + Entity + *linkedEntity; + Logical + previousState; + int + foregroundColor, + backgroundColor; +}; + +//########################################################################## +// MakeConfig +//########################################################################## +extern MethodDescription + MakeConfigMethodDescription; + +//########################################################################## +// MakeExternConfig +//########################################################################## +extern MethodDescription + MakeExternConfigMethodDescription; + +//########################################################################## +// BackgroundReconfig +//########################################################################## +class BackgroundReconfig : + public GaugeBackground +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BackgroundReconfig( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + int port_number, + int palette_ID, + int enable_ID, + const char *palette_name, + const char *identification_string = "BackgroundReconfig" + ); + + ~BackgroundReconfig(); + + void + BecameActive(); +protected: + + Logical + ignorePaletteFlag; + int + portNumber, + paletteID, + enableID; + char + *paletteName; +}; + +//-------------------------------------------------------------------------- +// BackgroundLine +//-------------------------------------------------------------------------- +class BackgroundLine : + public GraphicGaugeBackground +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BackgroundLine( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int thick, + int left, int bottom, int right, int top, + int color, + const char *identification_string = "BackgroundLine" + ); + + void + BecameActive(); +protected: + int + thickFlag; + Rectangle2D + endpoints; +}; + +//-------------------------------------------------------------------------- +// BackgroundRect +//-------------------------------------------------------------------------- +class BackgroundRect : + public GraphicGaugeBackground +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BackgroundRect( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + int color, + const char *identification_string = "BackgroundRect" + ); + + void + BecameActive(); +protected: + Rectangle2D + endpoints; +}; + +//-------------------------------------------------------------------------- +// BackgroundFilledRect +//-------------------------------------------------------------------------- +class BackgroundFilledRect : + public GraphicGaugeBackground +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BackgroundFilledRect( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + int color, + const char *identification_string = "BackgroundFilledRect" + ); + + void + BecameActive(); +protected: + Rectangle2D + endpoints; +}; + +//-------------------------------------------------------------------------- +// BackgroundPixelmap +//-------------------------------------------------------------------------- +class BackgroundPixelmap : + public GraphicGaugeBackground +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BackgroundPixelmap( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *pixelmap_name, + int opaque_flag, + const char *identification_string = "BackgroundPixelmap" + ); + + ~BackgroundPixelmap(); + + Logical + TestInstance() const; + + void + BecameActive(); +protected: + char + *pixelMapName; + int + opaqueFlag; +}; + +//-------------------------------------------------------------------------- +// BackgroundBitmap +//-------------------------------------------------------------------------- +class BackgroundBitmap : + public GraphicGaugeBackground +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BackgroundBitmap( + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int opaque_flag, + int foreground_color, + int background_color = 0, + const char *identification_string = "BackgroundBitmap" + ); + + ~BackgroundBitmap(); + + Logical + TestInstance() const; + void + BecameActive(); + +protected: + char + *bitMapName; + int + foregroundColor, + backgroundColor, + opaqueFlag; +}; + +// +//-------------------------------------------------------------------------- +// WipeGaugeScalar +// +// - Base class for "wipe"-style instruments, where a parameter causes +// a rectangular area to change size. +//-------------------------------------------------------------------------- +// +class WipeGaugeScalar : + public GraphicGauge +{ +public: + enum Direction { + wipeLeft, + wipeDown, + wipeRight, + wipeUp + }; + + void + BecameActive(); + +protected: + WipeGaugeScalar( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + Direction direction, + Scalar min, + Scalar max, + const char *identification_string = "WipeGaugeScalar" + ); + + virtual ~WipeGaugeScalar(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + Execute(); + +protected: + virtual void + DrawActive( + Rectangle2D *rectangle + ); + + virtual void + DrawInactive( + Rectangle2D *rectangle + ); + + Direction + wipeDirection; + int + width, + height, + previousValue; + Rectangle2D + previousSize; + Scalar + minimumValue, + currentValue, + maximumValue; + Logical + forceUpdateFlag; +}; + +// +//-------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------- +// +class BarGraphSolidScalar : + public WipeGaugeScalar +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BarGraphSolidScalar( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + int foreground_color, int background_color, + WipeGaugeScalar::Direction direction, + Scalar min, + Scalar max, + Scalar *value_pointer, + const char *identification_string = "BarGraphSolidScalar" + ); + + ~BarGraphSolidScalar(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + +protected: + void + DrawActive( + Rectangle2D *rectangle + ); + + void + DrawInactive( + Rectangle2D *rectangle + ); + + int + backgroundColor, + foregroundColor; +}; + +// +//-------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------- +// +class BarGraphBitMapScalar : + public WipeGaugeScalar +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BarGraphBitMapScalar( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *bitmap_name, + int foreground_color, + int background_color, + WipeGaugeScalar::Direction direction, + Scalar min, + Scalar max, + Scalar *value_pointer, + const char *identification_string = "BarGraphBitMapScalar" + ); + + ~BarGraphBitMapScalar(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + +protected: + void + DrawActive( + Rectangle2D *rectangle + ); + + void + DrawInactive( + Rectangle2D *rectangle + ); + + char + *bitMapName; + int + foregroundColor, + backgroundColor; +}; + +// +//-------------------------------------------------------------------------- +// +//-------------------------------------------------------------------------- +// +class BarGraphPixelMapScalar : + public WipeGaugeScalar +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + BarGraphPixelMapScalar( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *pixelmap_name, + int background_color, + WipeGaugeScalar::Direction direction, + Scalar min, + Scalar max, + Scalar *value_pointer, + const char *identification_string = "BarGraphPixelMapScalar" + ); + + ~BarGraphPixelMapScalar(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + +protected: + void + DrawActive( + Rectangle2D *rectangle + ); + + void + DrawInactive( + Rectangle2D *rectangle + ); + + char + *pixelMapName; + int + backgroundColor; +}; + +//####################################################################### +// ColorState +//####################################################################### +class ColorState : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + ColorState( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int first_color, + Scalar first_bin, + int second_color, + Scalar second_bin, + int third_color, + Scalar third_bin, + int fourth_color, + Scalar fourth_bin, + int fifth_color, + int damage_zone, + DamageZone ***value_pointer, + const char *identification_string = "ColorState" + ); + + ~ColorState(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + Execute(); + +protected: + int + previousState, + color[5]; + char + *bitMapName; + DamageZone + *damagePointer; + Scalar + bin[4]; +}; + +//####################################################################### +// TwoState +//####################################################################### +class TwoState : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + TwoState( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int first_color, + int second_color, + int *value_pointer, + const char *identification_string = "TwoState" + ); + + ~TwoState(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + Execute(); + +protected: + int + previousState, + color[2]; + int + currentValue; + char + *bitMapName; +}; + + +// +//-------------------------------------------------------------------------- +// NumericDisplayScalarTwoState +// +// - displays a formatted numeric value as a gauge. +// - can be turned on or off +//-------------------------------------------------------------------------- +// +class NumericDisplayScalarTwoState : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + NumericDisplayScalarTwoState( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, int right, int top, + const char *font_name, //BitMap *font_bitmap, + int number_of_chars, + NumericDisplay::NumericFormat requested_format, + int background_color, int foreground_color, + Scalar *value_pointer, + int *logical_pointer, + const char *identification_string = "NumericDisplayScalarTwoState" + ); + + ~NumericDisplayScalarTwoState(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + + #if 0 + void + SetColors( + int bg_color, + int fg_color + ); + #endif + void + Execute(); + +protected: + NumericDisplay + *numericDisplay; + int + previousState, previousValue, + color[2]; + Scalar + currentValue; + int + currentLogical; + +}; + + +//####################################################################### +// SegmentArc +//####################################################################### +class SegmentArc : + public GraphicGauge +{ +public: + SegmentArc( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int center_x, int center_y, + Scalar inner0, Scalar outer0, + Scalar inner1, Scalar outer1, + Scalar deg0, Scalar deg1, + int number_of_segs_and_direction, + int background_color, + int foreground_color, + Logical use_thick_lines = True, + const char *identification_string = "SegmentArc" + ); + + ~SegmentArc(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + Execute(); + +protected: + int + backgroundColor, + foregroundColor, + numberOfSegments, + previousSegment; + Logical + useThickLines; + Scalar + currentValue, + startAngle, + deltaAngle, + innerRadius, + outerRadius, + deltaInnerRadius, + deltaOuterRadius; +}; + +//####################################################################### +// SegmentArcNormalized +//####################################################################### +class SegmentArcNormalized : + public SegmentArc +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + SegmentArcNormalized( + GaugeRate new_rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int center_x, int center_y, + Scalar inner0, Scalar outer0, + Scalar inner1, Scalar outer1, + Scalar deg0, Scalar deg1, + int number_of_segs_and_direction, + int background_color, + int foreground_color, + Scalar *value_pointer, + Logical use_thick_lines = True, + const char *identification_string = "SegmentArcNormalized" + ); +}; diff --git a/MUNGA_L4/L4GAUIMA.cpp b/MUNGA_L4/L4GAUIMA.cpp new file mode 100644 index 0000000..6660110 --- /dev/null +++ b/MUNGA_L4/L4GAUIMA.cpp @@ -0,0 +1,1665 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "..\munga\fileutil.h" +#include "l4gauima.h" +#include "l4app.h" +#include "..\munga\notation.h" +#include "..\munga\namelist.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) std::cout << n << std::flush +#else +# define Test_Tell(n) +#endif + + +//############################################################################ +// GroupAttribute +// - this is a private class used nowhere else. +// It is initialized from a .GAT notation file, after which it +// holds a list of attribute group names with associated color and +// attribute fields. It may then be searched to find the values for +// that attribute group. +//############################################################################ +class GroupAttribute SIGNATURED +{ +public: + enum + { + nameLength=64 + }; + + int color; + int attribute; + char name[nameLength]; + + GroupAttribute + *next; + + GroupAttribute(const char *new_name, int new_color, int new_attrib); + ~GroupAttribute() + {} + + Logical + TestInstance() const + { return True; } + + static Logical + Initialize(const char *gat_file_name); + static void + Terminate(); + static Logical + Search(const char *name, int *color, int *attribute); +protected: + static + GroupAttribute + *head; +}; + +GroupAttribute + *GroupAttribute::head; + +GroupAttribute::GroupAttribute( + const char *new_name, + int new_color, + int new_attrib +) +{ + Test_Tell( + "GroupAttribute::GroupAttribute(" << new_name << + ", " << new_color << + ", " << new_attrib << + ")\n" + ); + Check_Pointer(this); + Check_Pointer(new_name); + + name[0] = '\0'; // safety check + Str_Copy(name, new_name, nameLength-1); + name[nameLength-1] = '\0'; + + color = new_color; + attribute = new_attrib; + + next = head; + head = this; + Check_Fpu(); +} + +Logical + GroupAttribute::Initialize(const char *gat_filename) +{ + Test_Tell("GroupAttribute::Initialize(" << gat_filename << ")\n"); + Check_Pointer(gat_filename); + + Logical + result = False; + + //------------------------------------------------------------- + // Open the associated .GAT file + //------------------------------------------------------------- + NotationFile + *gat_file = new NotationFile(gat_filename); + Check(gat_file); + Register_Object(gat_file); + + //------------------------------------------------------------- + // Create group, attribute, color name lists + //------------------------------------------------------------- + NameList + *color_namelist = gat_file->MakeEntryList("colors"); + if (color_namelist == NULL) + { + DEBUG_STREAM << gat_filename << " has no 'colors' page!" << std::endl; + } + + NameList + *attribute_namelist = gat_file->MakeEntryList("attributes"); + if (attribute_namelist == NULL) + { + DEBUG_STREAM << gat_filename << " has no 'attributes' page!" << std::endl; + } + + NameList + *group_namelist = gat_file->MakeEntryList("groups"); + if (group_namelist == NULL) + { + DEBUG_STREAM << gat_filename << " has no 'groups' page!" << std::endl; + } + + if ( + (attribute_namelist != NULL) && + (color_namelist != NULL) && + (group_namelist != NULL) + ) + { + //------------------------------------------------------------- + // Register the name lists + //------------------------------------------------------------- + Register_Object(color_namelist); + Register_Object(attribute_namelist); + Register_Object(group_namelist); + //------------------------------------------------------------- + // Clear the chain header + //------------------------------------------------------------- + head = NULL; + //------------------------------------------------------------- + // For all group names, build a GroupAttribute object + //------------------------------------------------------------- + NameList::Entry + *group_entry, + *color_entry, + *attribute_entry; + int + i, + new_attribute, + new_color; + Logical + found; + + for ( + group_entry = group_namelist->GetFirstEntry(); + group_entry != NULL; + group_entry = group_entry->GetNextEntry() + ) + { + Check(group_entry); + + char + buffer[256]; + char + *dest, + *text = group_entry->GetChar(); + + new_attribute = 0; + new_color = 0; + + if (text == NULL) + { + DEBUG_STREAM << text << " is an empty .GAT group!" << std::endl; + } + else + { + //------------------------------------------------------------- + // Skip white space + //------------------------------------------------------------- + while (*text != '\0') + { + while (isspace(*text)) + { + ++text; + } + //------------------------------------------------------------- + // Parse out one name + //------------------------------------------------------------- + for ( + i=0,dest=buffer; + i<(sizeof(buffer)-1); + ++i,++dest,++text + ) + { + if (!isalnum(*text)) + { + break; + } + + *dest = *text; + } + *dest = '\0'; + + Test_Tell("attribute item= <" << buffer << ">\n"); + //------------------------------------------------------------- + // Search color list for name + //------------------------------------------------------------- + found = False; + + for ( + color_entry = color_namelist->GetFirstEntry(); + color_entry != NULL; + color_entry = color_entry->GetNextEntry() + ) + { + Check(color_entry); + if (strcmp(color_entry->GetName(), buffer) == 0) + { + Check_Pointer(color_entry->GetData()); + new_color = color_entry->GetAtoi(); + Test_Tell("color=" << new_color << "\n"); + found = True; + break; + } + } + if (! found) + { + //---------------------------------------------------------- + // Search attribute list for name + //---------------------------------------------------------- + found = False; + + for ( + attribute_entry =attribute_namelist->GetFirstEntry(); + attribute_entry != NULL; + attribute_entry = attribute_entry->GetNextEntry() + ) + { + Check(attribute_entry); + if (strcmp(attribute_entry->GetName(), buffer) == 0) + { + Check_Pointer(attribute_entry->GetData()); + new_attribute |= attribute_entry->GetAtoi(); + Test_Tell( + "attribute=" << std::hex << new_attribute << std::dec << ">\n" + ); + found = True; + break; + } + } + if (! found) + { + DEBUG_STREAM << + "Attribute '" << buffer << "' not found!" << std::endl; + } + } + } + } + Check(group_entry); + Check_Pointer(group_entry->GetName()); + +# if DEBUG_LEVEL == 0 + new GroupAttribute( + group_entry->GetName(), + new_color, + new_attribute + ); +# else + GroupAttribute + *group_attribute = + new GroupAttribute( + group_entry->GetName(), + new_color, + new_attribute + ); + Check(group_attribute); + Register_Object(group_attribute); + Test_Tell("object created\n"); +# endif + } + //------------------------------------------------------------- + // Release the name lists + //------------------------------------------------------------- + Test_Tell("loop finished, deleting namelists\n"); + Check(color_namelist); + Unregister_Object(color_namelist); + delete color_namelist; + + Check(attribute_namelist); + Unregister_Object(attribute_namelist); + delete attribute_namelist; + + Check(group_namelist); + Unregister_Object(group_namelist); + delete group_namelist; + + result = True; + } + //------------------------------------------------------------- + // Release the notation file + //------------------------------------------------------------- + Test_Tell("deleting .GAT notation file\n"); + Check(gat_file); + Unregister_Object(gat_file); + delete gat_file; + + Test_Tell("returning " << result <<"\n"); + Check_Fpu(); + return result; +} + +void + GroupAttribute::Terminate() +{ + Test_Tell("GroupAttribute::Terminate\n"); + GroupAttribute + *group_attribute, + *next; + + for( + group_attribute= head; + group_attribute != NULL; + group_attribute = next + ) + { + Check(group_attribute); + next = group_attribute->next; + + Unregister_Object(group_attribute); + delete group_attribute; + } + + head = NULL; + Test_Tell("Termination completed\n"); + Check_Fpu(); +} + + +Logical + GroupAttribute::Search(const char *name, int *color_dest, int *attrib_dest) +{ + Test_Tell("GroupAttribute::Search("<< name <<")\n"); + GroupAttribute + *group_attribute; + + for( + group_attribute= head; + group_attribute != NULL; + group_attribute = group_attribute->next + ) + { + Check(group_attribute); + if ( + strncmp( + name, + group_attribute->name, + GroupAttribute::nameLength + ) == 0 + ) + { + Test_Tell("Found!\n"); + *color_dest = group_attribute->color; + *attrib_dest = group_attribute->attribute; + Check_Fpu(); + return True; + } + } + Check_Fpu(); + return False; +} + +//############################################################################ +// L4GaugeImage +//############################################################################ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +L4GaugeImage * + L4GaugeImage::Make(const char */*file_name*/) +{ + return NULL; // Gauge images come exclusively from resources +} + +L4GaugeImage * + L4GaugeImage::Make(ResourceDescription::ResourceID new_resource_id) +{ + Check(application); + Check(application->GetResourceFile()); + + L4GaugeImage + *image = NULL; + //------------------------------------------- + // Attempt to find the specified resource + //------------------------------------------- + ResourceDescription + *stream_resource_description = + application->GetResourceFile()->SearchList( + new_resource_id, + ResourceDescription::GaugeImageStreamResourceType + ); + + if (stream_resource_description == NULL) + { + Tell( + "L4GaugeImage::Make: resource ID '" << new_resource_id << + "' does not exist\n" + ); + } + else + { + //------------------------------------------- + // Found it, open a DynamicMemoryStream + //------------------------------------------- + Check(stream_resource_description); + stream_resource_description->Lock(); + MemoryStream + memory_stream( + stream_resource_description->resourceAddress, + stream_resource_description->resourceSize + ); + if (stream_resource_description->resourceAddress == NULL) + { + Tell("L4GaugeImage::Make: couldn't open stream\n"); + } + else + { + //------------------------------------------- + // Create the object + //------------------------------------------- + image = new L4GaugeImage(&memory_stream); + } + stream_resource_description->Unlock(); + } + Check_Fpu(); + return image; +} + +L4GaugeImage::L4GaugeImage(MemoryStream *mem_stream) +{ + Test_Tell("L4GaugeImage::L4GaugeImage\n"); + Check_Pointer(this); + Check(mem_stream); + + int + i; + + //------------------------------------------------------------- + // Read the number of vertices + //------------------------------------------------------------- + MemoryStream_Read(mem_stream, &vertexCount); + Verify(vertexCount > 0); + //------------------------------------------------------------- + // Allocate the vertex array + //------------------------------------------------------------- + vertexArray = new Point3D[vertexCount]; + Check_Pointer(vertexArray); + Register_Pointer(vertexArray); + //------------------------------------------------------------- + // Read in the vertex values + //------------------------------------------------------------- + for(i=0; i 0); + //------------------------------------------------------------- + // Allocate the LOD scales + //------------------------------------------------------------- + LODScales = new Scalar[LODCount]; + Check_Pointer(LODScales); + Register_Pointer(LODScales); + //------------------------------------------------------------- + // Read the LOD scales + //------------------------------------------------------------- + for(i=0; iGetEntry("gauge", "image", &gauge_filename) != 0) + { + //------------------------------------------------------------- + // It does, attempt to open the given notation file + //------------------------------------------------------------- + Tell("Opening gauge image " << gauge_filename << "\n"); + + char *gim_filename = + MakePathedFilename(directories->gaugeDirectory, gauge_filename); + Register_Pointer(gim_filename); + + NotationFile + *gim_file = new NotationFile(gim_filename); + Check(gim_file); + Register_Object(gim_file); + + //-------------------------------------------------------- + // Search for the name of the .GAT file + //-------------------------------------------------------- + const char + *gat_entry; + + if (gim_file->GetEntry("object", "gatfile", &gat_entry) == 0) + { + DEBUG_STREAM << "Missing .gat specification!" << std::endl; + } + else + { + //------------------------------------------------------------- + // Create the GroupAttribute data + //------------------------------------------------------------- + char *gat_filename = + MakePathedFilename(directories->gaugeDirectory, gat_entry); + Register_Pointer(gat_filename); + + if (GroupAttribute::Initialize(gat_filename)) + { + //------------------------------------------------------------- + // Create a dynamic memory stream, write out the data + // (note: the call to L4GaugeImage::DynamicMemoryStreamWrite() + // internally calls the dynamic stream writes for all of the + // 'owned' sub-parts as well) + //------------------------------------------------------------- + DynamicMemoryStream + *gim_stream = new DynamicMemoryStream(); + + Check(gim_stream); + Register_Object(gim_stream); + + if ( + L4GaugeImage::MemoryStreamWrite( + gim_stream, + gim_file + ) == True + ) + { + //------------------------------------------------------------- + // Create the resource description, assign an ID + //------------------------------------------------------------- + ResourceDescription + *res_desc_stream = + resource_file->ResourceFile::AddResourceMemoryStream( + model_name, + ResourceDescription::GaugeImageStreamResourceType, + 1, + ResourceDescription::Preload, + gim_stream + ); + + Check(res_desc_stream); + res_id = res_desc_stream->resourceID; + } + + //------------------------------------------------------------- + // Release the GroupAttribute data + //------------------------------------------------------------- + GroupAttribute::Terminate(); + + Check(gim_stream); + Unregister_Object(gim_stream); + delete gim_stream; + } + Check_Pointer(gat_filename); + Unregister_Pointer(gat_filename); + delete gat_filename; + } + //------------------------------------------------------------- + // Release variables + //------------------------------------------------------------- + Check(gim_file); + Unregister_Object(gim_file); + delete gim_file; + + Check_Pointer(gim_filename); + Unregister_Pointer(gim_filename); + delete gim_filename; + + Tell("Closed gauge image\n" << std::flush); + } + //------------------------------------------------------------- + // Return the new ResourceID + //------------------------------------------------------------- + Test_Tell("res_id = " << res_id << "\n"); + Check_Fpu(); + return res_id; +} + + +Logical + L4GaugeImage::MemoryStreamWrite( + MemoryStream *mem_stream, + NotationFile *gim_file + ) +{ + Test_Tell(" L4GaugeImage::MemoryStreamWrite(" << mem_stream << + ", " << gim_file << + ")\n" + ); + Check(mem_stream); + Check(gim_file); + + int + i; + //------------------------------------------------------------- + // 'result' is set to False if an error occurs. + //------------------------------------------------------------- + Logical + result = True; + //------------------------------------------------------------- + // Write the vertices + //------------------------------------------------------------- + NameList + *vertex_list = gim_file->MakeEntryList("vertices"); + + if (vertex_list == NULL) + { + DEBUG_STREAM << "No 'vertices' page in the .GIM file!" << std::endl; + result = False; + } + else + { + Check(vertex_list); + Register_Object(vertex_list); + //------------------------------------------------------------- + // Get the number of vertices + //------------------------------------------------------------- + int + vertex_count = vertex_list->EntryCount(); + + Test_Tell("vertex_count = " << vertex_count << "\n"); + if (vertex_count <= 0) + { + DEBUG_STREAM << + "The 'vertices' page in the .GIM file has no entries!" <GetFirstEntry(); + + for (int i=0; iGetChar(), &point_3d); + Test_Tell(" " << point_3d << "\n"); + MemoryStream_Write(mem_stream, &point_3d); + + vertex_entry = vertex_entry->GetNextEntry(); + } + } + //------------------------------------------------------------- + // Delete the vertex list + //------------------------------------------------------------- + Check(vertex_list); + Unregister_Object(vertex_list); + delete vertex_list; + } + + //------------------------------------------------------------- + // Write the levels of detail + //------------------------------------------------------------- + if (result == True) + { + NameList + *lod_namelist = gim_file->MakeEntryList("lods"); + + if (lod_namelist == NULL) + { + DEBUG_STREAM << "No 'lods' page in the .GIM file!" << std::endl; + result = False; + } + else + { + Check(lod_namelist); + Register_Object(lod_namelist); + //------------------------------------------------------------- + // Get the number of LOD's + //------------------------------------------------------------- + int + lod_count = lod_namelist->EntryCount(); + Test_Tell("lod_count = " << lod_count << "\n"); + if (lod_count <= 0) + { + DEBUG_STREAM << + "The 'lod' page in the .GIM file has no entries!" << std::endl; + result = False; + } + else + { + //------------------------------------------------------------- + // Write the number of LOD's to the stream + //------------------------------------------------------------- + MemoryStream_Write(mem_stream, &lod_count); + //------------------------------------------------------------- + // Write the LOD scales + //------------------------------------------------------------- + NameList::Entry + *scale_entry; + Scalar + scale; + + const char + *text; + + scale_entry = lod_namelist->GetFirstEntry(); + for (i=0; iGetChar(); + if (text == NULL) + { + DEBUG_STREAM << "Missing scale value!" << std::endl; + result = False; + break; + } + scale = (Scalar) atof(text); + + Test_Tell(" " << scale << "\n"); + MemoryStream_Write(mem_stream, &scale); + + scale_entry = scale_entry->GetNextEntry(); + } + //------------------------------------------------------------- + // Write the LOD lists + //------------------------------------------------------------- + scale_entry = lod_namelist->GetFirstEntry(); + for (i=0; iGetName() + ); + + if (result == False) + { + break; + } + + scale_entry = scale_entry->GetNextEntry(); + } + } + } + //------------------------------------------------------------- + // Delete the LOD list + //------------------------------------------------------------- + Check(lod_namelist); + Unregister_Object(lod_namelist); + delete lod_namelist; + } + Check_Fpu(); + return result; +} + + +void + L4GaugeImage::Draw( + Scalar LOD_value, // smaller = more detail (1.0 = 'normal') + Scalar scale_value, // metersPerPixel + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + int boxed_color + ) +{ + Test_Tell( + "L4GaugeImage::Draw(" << scale_value << + ", " << graphics_view << + ", " << default_color << + ", " << localToView << + ", " << boxed_color << + ")\n" + ); + Check(this); + Check(graphics_view); + // localToView allowed to be NULL + Check_Pointer(LODScales); + Check_Pointer(LODList); + +# define VERTEX_ALLOTMENT 100 // HACK - I'm guessing this is big enough. + + Verify(vertexCount <= VERTEX_ALLOTMENT); + + static + Point3D + local_vertex_array[VERTEX_ALLOTMENT]; + + static + Logical + local_flag_array[VERTEX_ALLOTMENT]; + + int + lod_index; + + if (localToView == NULL) + { + return; + } + //------------------------------------------------------------- + // Find LOD index + //------------------------------------------------------------- + for(lod_index=0; lod_indexDraw( + graphics_view, + default_color, + localToView, + vertexArray, + local_vertex_array, + local_flag_array, + scale_value, + boxed_color + ); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Instance +// +Logical + L4GaugeImage::TestInstance() const +{ + return True; +} +//############################################################################ +// L4GaugeImageList +//############################################################################ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +L4GaugeImageList::L4GaugeImageList(MemoryStream *mem_stream) +{ + Test_Tell("L4GaugeImageList::L4GaugeImageList\n"); + Check_Pointer(this); + Check(mem_stream); + + int + i; + + //------------------------------------------------------------- + // Read the number of primitives from the stream + //------------------------------------------------------------- + MemoryStream_Read(mem_stream, &primitiveCount); + Verify(primitiveCount > 0); + //------------------------------------------------------------- + // Allocate the primitive list + //------------------------------------------------------------- + primitiveList = new L4GaugeImagePrimitive*[primitiveCount]; + Check_Pointer(primitiveList); + Register_Pointer(primitiveList); + //------------------------------------------------------------- + // Read the primitives + //------------------------------------------------------------- + for(i=0; iMakeEntryList(page_name); + + if (primitive_list == NULL) + { + DEBUG_STREAM << "Can't find the '" << page_name << "' page in the .GIM file!" + << std::endl; + result = False; + } + else + { + Check(primitive_list); + Register_Object(primitive_list); + //------------------------------------------------------------- + // Get the number of primitives + //------------------------------------------------------------- + int + primitive_count = primitive_list->EntryCount(); + + Test_Tell(" primitive_count = " << primitive_count << "\n"); + if (primitive_count <= 0) + { + DEBUG_STREAM << "The '"<GetFirstEntry(); + for (i=0; iGetName(), + primitive_entry->GetChar() + ); + + if (result == False) + { + break; + } + + primitive_entry = primitive_entry->GetNextEntry(); + } + } + //------------------------------------------------------------- + // Delete the primitive list + //------------------------------------------------------------- + Check(primitive_list); + Unregister_Object(primitive_list); + delete primitive_list; + } + Check_Fpu(); + return result; +} + + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Test Support +// +Logical + L4GaugeImageList::TestInstance() const +{ + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4GaugeImageList::Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + int boxed_color + ) +{ + Test_Tell( + "L4GaugeImageList::Draw(" << graphics_view << + ", " << default_color << + ", " << localToView << + ", " << untransformed_vertex_array << + ", " << transformed_vertex_array << + ", " << transformed_flag_array << + ", " << scale_factor << + ", " << boxed_color << + ")\n" + ); + Check(this); + Check(graphics_view); + Check(&localToView); + Check_Pointer(untransformed_vertex_array); + Check_Pointer(transformed_vertex_array); + Check_Pointer(transformed_flag_array); + + Check_Pointer(primitiveList); + + int + i; + L4GaugeImagePrimitive + **array_pointer = primitiveList; + + if (boxed_color != 0) + { + //-------------------------------------------------------- + // Initialize bounding box + //-------------------------------------------------------- + Rectangle2D + bounds(9999,9999,-9999,-9999); + //-------------------------------------------------------- + // Draw primitives, collect bounding data + //-------------------------------------------------------- + for(i=0; iDraw( + graphics_view, + default_color, + localToView, + untransformed_vertex_array, + transformed_vertex_array, + transformed_flag_array, + scale_factor, + &bounds + ); + } + //-------------------------------------------------------- + // Draw the bounding box + //-------------------------------------------------------- + graphics_view->SetColor(boxed_color); + + graphics_view->MoveToAbsolute( + bounds.bottomLeft.x-4, + bounds.bottomLeft.y-4 + ); + graphics_view->DrawRectangleToAbsolute( + bounds.topRight.x+4, + bounds.topRight.y+4 + ); + } + else + { + //-------------------------------------------------------- + // Just draw it + //-------------------------------------------------------- + for(i=0; iDraw( + graphics_view, + default_color, + localToView, + untransformed_vertex_array, + transformed_vertex_array, + transformed_flag_array, + scale_factor, + NULL + ); + } + } + Check_Fpu(); +} + +//############################################################################ +// L4GaugeImagePrimitive +//############################################################################ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +L4GaugeImagePrimitive::L4GaugeImagePrimitive(MemoryStream *mem_stream) +{ + Test_Tell("L4GaugeImagePrimitive::L4GaugeImagePrimitive\n"); + Check_Pointer(this); + Check(mem_stream); + + int + i, + n; + //-------------------------------------------------------------- + // Read the primitive type ID, use the input stream accordingly + //-------------------------------------------------------------- + MemoryStream_Read(mem_stream, &n); + type = (primitiveType) n; + + switch(type) + { + case primitiveVector: + Test_Tell(" primitiveVector\n"); + //-------------------------------------------------------- + // Read the attribute and color + //-------------------------------------------------------- + MemoryStream_Read(mem_stream, &color); + MemoryStream_Read(mem_stream, &attributes); + Test_Tell(" color = " << color << "\n"); + Test_Tell(" attributes = " << std::hex << attributes << std::dec << "\n"); + //-------------------------------------------------------- + // Read the vertex index count + //-------------------------------------------------------- + MemoryStream_Read(mem_stream, &data.vector.indexCount); + Test_Tell(" indexCount = " << data.vector.indexCount << "\n"); + Verify(data.vector.indexCount > 0); + //-------------------------------------------------------- + // Allocate the index table + //-------------------------------------------------------- + data.vector.indexList = new int[data.vector.indexCount]; + Check_Pointer(data.vector.indexList); + Register_Pointer(data.vector.indexList); + //-------------------------------------------------------- + // Read the indices + //-------------------------------------------------------- + for(i=0; i 0) + int + check_length = strlen(data)+1; +# endif + + while(*scan != '\0') + { + Verify((scan-data) < check_length); + //-------------------------------------------------------- + // Skip white space + //-------------------------------------------------------- + while (isspace(*scan)) + { + ++scan; + } + //-------------------------------------------------------- + // Parse non-space string + //-------------------------------------------------------- + if (*scan == 'v') + { + int + n; + //-------------------------------------------------------- + // Convert to value, save in array + //-------------------------------------------------------- + ++scan; // ignore 'v' + for(n=0; isdigit(*scan); ++scan) + { + n = (n*10) + (*scan - '0'); + } + Test_Tell(" " << n << "\n"); + + if (index_count < MAX_INDICES) + { + index[index_count++] = n; + } + } + else if (*scan == 'a') + { + char + buffer[64], + *dest; + //-------------------------------------------------------- + // Collect the name + //-------------------------------------------------------- + for( + i=0, dest=buffer; + i<(sizeof(buffer)-1); + ++i,++scan,++dest + ) + { + if (isspace(*scan)) + { + break; + } + if (*scan == '\0') + { + break; + } + *dest = *scan; + } + *dest = '\0'; + //-------------------------------------------------------- + // Search for the name + //-------------------------------------------------------- + if ( + GroupAttribute::Search( + buffer, + &color_value, + &attribute_value + ) == False + ) + { + DEBUG_STREAM << "Couldn't find attribute group '" << + buffer << "'!" << std::endl; + } + } + } + //-------------------------------------------------------- + // Write the attributes + //-------------------------------------------------------- + Test_Tell(" color=" << color_value << "\n"); + MemoryStream_Write(mem_stream, &color_value); + Test_Tell(" attribute=" << attribute_value << "\n"); + MemoryStream_Write(mem_stream, &attribute_value); + //-------------------------------------------------------- + // Write the vertex index count + //-------------------------------------------------------- + if (index_count == 0) + { + DEBUG_STREAM << "No vertex indices in primitive!" << std::endl; + result = False; + } + else + { + Test_Tell(" index_count=" << index_count << "\n"); + MemoryStream_Write(mem_stream, &index_count); + //-------------------------------------------------------- + // Write the indices + //-------------------------------------------------------- + for(i=0; i < index_count; ++i) + { + MemoryStream_Write(mem_stream, &index[i]); + } + } + } + else + { + DEBUG_STREAM << "Unsupported primitive ("<< type_name << ") in .GIM file!" + << std::endl; + result = False; + } + Check_Fpu(); + return result; +} + + +//============================================================================ +// TestInstance +//============================================================================ +Logical + L4GaugeImagePrimitive::TestInstance() const +{ + return True; +} +//============================================================================ +// Draw +//============================================================================ +void + L4GaugeImagePrimitive::Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + Rectangle2D *bounds + ) +{ + Test_Tell( + "L4GaugeImagePrimitive::Draw(" << graphics_view << + ", " << default_color << + ", " << localToView << + ", " << untransformed_vertex_array << + ", " << transformed_vertex_array << + ", " << transformed_flag_array << + ", " << scale_factor << + ", " << bounds << + ")\n" + ); + + Check(this); + Check(graphics_view); + Check(&localToView); + Check_Pointer(untransformed_vertex_array); + Check_Pointer(transformed_vertex_array); + Check_Pointer(transformed_flag_array); + + //----------------------------------------------- + // Draw primitive + //----------------------------------------------- + switch(type) + { + case primitiveVector: + if (data.vector.indexCount > 1) + { + //----------------------------------------------- + // Set color + //----------------------------------------------- + if (color != 0) + { + default_color = color; + } + graphics_view->SetColor(default_color); + + int + i, + *index_pointer(data.vector.indexList), + index; + Point3D + *dest; + //----------------------------------------------- + // Move to starting point + //----------------------------------------------- + index = *index_pointer++; + + dest = &transformed_vertex_array[index]; + + TransformVertex( + localToView, + untransformed_vertex_array[index], + dest, + transformed_flag_array[index], + scale_factor, + bounds + ); + + + Test_Tell("Start at " << index << "=" << *dest << "\n"); + graphics_view->MoveToAbsolute((int)dest->x,(int)dest->z); + //----------------------------------------------- + // Draw subsequent lines + //----------------------------------------------- + for(i=data.vector.indexCount-1; i>0; --i) + { + index = *index_pointer++; + + dest = &transformed_vertex_array[index]; + + TransformVertex( + localToView, + untransformed_vertex_array[index], + dest, + transformed_flag_array[index], + scale_factor, + bounds + ); + + Test_Tell("Draw to " << index << "=" << *dest << "\n"); + graphics_view->DrawLineToAbsolute((int)(dest->x),(int)(dest->z)); + } + } + break; + default: + Warn("L4GaugeImagePrimitive::Draw: Evil type_id!"); + break; + } + Check_Fpu(); +} + +void + L4GaugeImagePrimitive::TransformVertex( + AffineMatrix &local_to_view, + Point3D &untransformed_vertex, + Point3D *transformed_vertex, + Logical &transformed_flag, + Scalar scale_factor, + Rectangle2D *bounds + ) +{ + Check(this); + Check_Pointer(transformed_vertex); + + //----------------------------------------- + // Transform only if not already done + //----------------------------------------- + if (! transformed_flag) + { + if (attributes & attributeUnscaled) + { + //----------------------------------------- + // Unscaled: pre-multiply by scaling factor + //----------------------------------------- + Point3D + temp; + + temp = untransformed_vertex; + temp *= scale_factor; + Check_Fpu(); + + transformed_vertex->Multiply( + temp, + local_to_view + ); + Check_Fpu(); + } + else + { + //----------------------------------------- + // Normally scaled: transform the vertex + //----------------------------------------- + transformed_vertex->Multiply( + untransformed_vertex, + local_to_view + ); + Check_Fpu(); + } + + //----------------------------------------- + // Round, and fix 'y' sign + //----------------------------------------- + transformed_vertex->x += .5; + transformed_vertex->z = -transformed_vertex->z + .5; + + //----------------------------------------------- + // Set the 'transformed' flag + //----------------------------------------------- + transformed_flag = True; + } + + //----------------------------------------------- + // Accumulate bounds + //----------------------------------------------- + if (bounds != NULL) + { + if (transformed_vertex->x < bounds->bottomLeft.x) + { + bounds->bottomLeft.x = transformed_vertex->x; + } + if (transformed_vertex->x > bounds->topRight.x) + { + bounds->topRight.x = transformed_vertex->x; + } + + if (transformed_vertex->z < bounds->bottomLeft.y) + { + bounds->bottomLeft.y = transformed_vertex->z; + } + if (transformed_vertex->z > bounds->topRight.y) + { + bounds->topRight.y = transformed_vertex->z; + } + } + Check_Fpu(); +} diff --git a/MUNGA_L4/L4GAUIMA.h b/MUNGA_L4/L4GAUIMA.h new file mode 100644 index 0000000..ae913cd --- /dev/null +++ b/MUNGA_L4/L4GAUIMA.h @@ -0,0 +1,249 @@ +#pragma once + +#include "..\munga\entity.h" +#include "..\munga\affnmtrx.h" +#include "..\munga\graph2d.h" +#include "..\munga\memstrm.h" + +class L4GaugeImage; +class L4GaugeImageList; +class L4GaugeImagePrimitive; + +class L4GaugeImageListResource; +class L4GaugeImagePrimitiveResource; +class L4GaugeImageResource; + + + +//####################################################################### +// L4GaugeImage +//####################################################################### +class L4GaugeImage SIGNATURED +{ +public: + //-------------------------------------------------------------------- + // Create L4GaugeImage from memory stream + //-------------------------------------------------------------------- + L4GaugeImage(MemoryStream *mem_stream); + + static L4GaugeImage *Make(const char *file_name); + static L4GaugeImage *Make(ResourceDescription::ResourceID new_resource_id); + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + ~L4GaugeImage(); + //-------------------------------------------------------------------- + // TestInstance + //-------------------------------------------------------------------- + Logical + TestInstance() const; + + //-------------------------------------------------------------------- + // CreateL4GaugeImageStream + //-------------------------------------------------------------------- + static ResourceDescription::ResourceID + CreateL4GaugeImageStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + Draw( + Scalar LOD_value, // smaller = more detail (1.0 = 'normal') + Scalar scale_value, // metersPerPixel + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + int boxed_color = 0 + ); + +protected: + static Logical + MemoryStreamWrite( + MemoryStream *mem_stream, + NotationFile *gim_file + ); + + //==================================================================== + // Protected data + //==================================================================== + int + vertexCount, // number of vertices in vertexArray + LODCount; // number of seperate LOD's + Point3D + *vertexArray; // pointer to array of vertices + Scalar + *LODScales; // pointer to array of scalar 'scale' values + L4GaugeImageList + **LODList; + // LODList points to an array of pointers to + // L4GaugeImageLists. +}; + +//####################################################################### +// L4GaugeImageList +//####################################################################### +class L4GaugeImageList SIGNATURED +{ + friend class L4GaugeImage; + +protected: + //-------------------------------------------------------------------- + // Create L4GaugeList from memory stream + //-------------------------------------------------------------------- + L4GaugeImageList(MemoryStream *mem_stream); + + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + ~L4GaugeImageList(); + //-------------------------------------------------------------------- + // TestInstance + //-------------------------------------------------------------------- + Logical + TestInstance() const; + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + static Logical + MemoryStreamWrite( + MemoryStream *mem_stream, + NotationFile *gim_file, + const char *page_name + ); + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + int boxed_color + ); + + //==================================================================== + // Protected data + //==================================================================== + int + primitiveCount; // number of primitives in primitiveList + L4GaugeImagePrimitive + **primitiveList; + // primitiveList points to an array of pointers to + // L4GaugeImagePrimitives. +}; + +//####################################################################### +// L4GaugeImagePrimitive +//####################################################################### +class L4GaugeImagePrimitive SIGNATURED +{ + friend class L4GaugeImageList; + +protected: + //-------------------------------------------------------------------- + // Create L4GaugeImagePrimitive from memory stream + //-------------------------------------------------------------------- + L4GaugeImagePrimitive(MemoryStream *mem_stream); + static int + CreateL4GaugeImagePrimitiveResource( + NotationFile *gim_file, + const char *gim_name, + const ResourceDirectories *directories, + char *primitive_data, + L4GaugeImagePrimitiveResource *prim_res + ); + + //-------------------------------------------------------------------- + // Destructor + //-------------------------------------------------------------------- + ~L4GaugeImagePrimitive(); + //-------------------------------------------------------------------- + // TestInstance + //-------------------------------------------------------------------- + Logical + TestInstance() const; + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + static Logical + MemoryStreamWrite( + MemoryStream *mem_stream, + const char *type_name, + const char *data + ); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + Draw( + GraphicsView *graphics_view, + int default_color, + AffineMatrix &localToView, + Point3D *untransformed_vertex_array, + Point3D *transformed_vertex_array, + Logical *transformed_flag_array, + Scalar scale_factor, + Rectangle2D *bounds + ); + + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + void + TransformVertex( + AffineMatrix &local_to_view, + Point3D &untransformed_vertex, + Point3D *transformed_vertex, + Logical &transformed_flag, + Scalar scale_factor, + Rectangle2D *bounds + ); + + //-------------------------------------------------------------------- + // These are the supported attribute types. + //-------------------------------------------------------------------- + enum + { + attributeNormal=0, + attributeUnscaled=0x0001 + }; + //-------------------------------------------------------------------- + // These are the supported primitive types. + //-------------------------------------------------------------------- + enum primitiveType + { + primitiveVector=0, + numberOfTypes + }; + + //==================================================================== + // Protected data + //==================================================================== + int + attributes, // general attributes + color; // a specially parsed attribute + + primitiveType + type; // the primitive's type + + union + { + //-------------------------------- + // type = primitiveVector + //-------------------------------- + struct + { + int + indexCount, // the number of indices + *indexList; // pointer to an array of indices + } + vector; + } + data; + +}; diff --git a/MUNGA_L4/L4GAUTUL.cpp b/MUNGA_L4/L4GAUTUL.cpp new file mode 100644 index 0000000..3310b86 --- /dev/null +++ b/MUNGA_L4/L4GAUTUL.cpp @@ -0,0 +1,99 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4gauima.h" +#include "..\munga\gaugalrm.h" +#include "l4tool.h" + +ResourceDescription::ResourceID + L4Tool::CreateModelGaugeImageStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + return + L4GaugeImage::CreateL4GaugeImageStream( + resource_file, + model_name, + model_file, + directories + ); +} + +ResourceDescription::ResourceID + L4Tool::CreateModelGaugeMissionReviewStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories */*directories*/ + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + //Check_Pointer(directories); + + ResourceDescription::ResourceID + res_id = ResourceDescription::NullResourceID; + + //---------------------------------------------------------------------- + // Check to see if the model has a mission review page + //---------------------------------------------------------------------- + const char + *pixelmap_name; + + if ( + model_file->GetEntry( + "gaugeMissionReview", + "pixelmap", + &pixelmap_name + ) + ) + { + //------------------------------------------------------------- + // Create a dynamic memory stream, write out the data + //------------------------------------------------------------- + DynamicMemoryStream + *stream = new DynamicMemoryStream(); + + Check(stream); + Register_Object(stream); + + int + length = strlen(pixelmap_name); + MemoryStream_Write(stream, &length); + + for( ; length>0; --length, ++pixelmap_name) + { + MemoryStream_Write(stream, (char *) pixelmap_name); + } + //------------------------------------------------------------- + // Create the resource description, assign an ID + //------------------------------------------------------------- + ResourceDescription + *res_desc_stream = + resource_file->ResourceFile::AddResourceMemoryStream( + model_name, + ResourceDescription::GaugeMissionReviewStreamResourceType, + 1, + ResourceDescription::Preload, + stream + ); + + Check(res_desc_stream); + res_id = res_desc_stream->resourceID; + + Check(stream); + Unregister_Object(stream); + delete stream; + + std::cout << "GaugeMissionReview res_id = " << res_id << "\n"; + } + //------------------------------------------------------------- + // Return the new ResourceID + //------------------------------------------------------------- + Check_Fpu(); + return res_id; +} diff --git a/MUNGA_L4/L4GREND.cpp b/MUNGA_L4/L4GREND.cpp new file mode 100644 index 0000000..1d2c8fb --- /dev/null +++ b/MUNGA_L4/L4GREND.cpp @@ -0,0 +1,836 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4app.h" +#include "..\munga\time.h" +#include "l4grend.h" +#include "l4gauge.h" +#include "..\munga\mission.h" +#include "l4plasma.h" +#include "..\munga\notation.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n << std::flush +#else +# define Test_Tell(n) +#endif + +// +//############################################################################# +// L4MethodDescription list +//############################################################################# +// +MethodDescription + L4ChainToPrevious = METHOD_DESCRIPTION_CHAIN(NULL); // Null:end of chain + +MethodDescription + *L4MethodDescription[] = + { + &MakeConfigMethodDescription, + &MakeExternConfigMethodDescription, + &BackgroundReconfig::methodDescription, + &BackgroundLine::methodDescription, + &BackgroundRect::methodDescription, + &BackgroundFilledRect::methodDescription, + &BackgroundPixelmap::methodDescription, + &BackgroundBitmap::methodDescription, + &NumericDisplayScalar::methodDescription, + &NumericDisplaySpeed::methodDescription, + &NumericDisplayInteger::methodDescription, + &DigitalClock::methodDescription, + &RankAndScore::methodDescription, + &BarGraphSolidScalar::methodDescription, + &BarGraphPixelMapScalar::methodDescription, + &ColorState::methodDescription, + &TwoState::methodDescription, + &SegmentArcNormalized::methodDescription, + &L4ChainToPrevious + }; + +// +//############################################################################# +// L4GaugeRenderer +//############################################################################# +// +L4GaugeRenderer::L4GaugeRenderer(bool windowed, int *secondaryIndex, int *aux1Index, int *aux2Index): + GaugeRenderer() +{ + // + //--------------------------------------------------------------------- + // Ensure that graphicsDisplay is NULL + //--------------------------------------------------------------------- + // + graphicsDisplay = NULL; + externalDisplay = NULL; + + palettesAreActive = True; + scrambleVideoFlag = False; + + char + *mode_string = getenv("L4GAUGE"); + // + //--------------------------------------------------------------------- + // NOTE that L4Application::Initialize() searches for the environment + // variable "L4GAUGE" to determine whether or not to create + // a gauge renderer. + //--------------------------------------------------------------------- + // + if (mode_string != NULL) + { + // + //--------------------------------------------------------------------- + // Attempt to initialize external display + //--------------------------------------------------------------------- + // + char + *plasma_string = getenv("L4PLASMA"); + + if (plasma_string != NULL) + { + //Win32 Serial support: ADB 06/30/07 + //if (strnicmp(plasma_string, "COM2", 4) == 0) + //{ + // Tell("Plasma display created on COM2\n"); + // externalDisplay = new PlasmaDisplay(PCS_COM2); + //} + //else + //{ + // Tell("Plasma display created on COM1\n"); + // externalDisplay = new PlasmaDisplay(PCS_COM1); + //} + Tell("Plasma display created on "); Tell(plasma_string); Tell("\n"); + externalDisplay = new PlasmaDisplay(plasma_string); + + if (externalDisplay != NULL) + { + Register_Object(externalDisplay); + } + } + // + //--------------------------------------------------------------------- + // Attempt to initialize main display + //--------------------------------------------------------------------- + //------------------------------------------------- + // Search notation file for specified resolution + //------------------------------------------------- + // + NotationFile + notation_file("GAUGE\\L4GAUGE.INI"); + + if (!notation_file.PageExists(mode_string)) + { + Tell("L4GaugeRenderer::L4GaugeRenderer - '" << + mode_string << + "' not found in L4GAUGE.INI!\n" + ); + } + else + { + // + //------------------------------------------------- + // Requested resolution exists, read parameters + //------------------------------------------------- + // + int + mode(0), + width(640), + height(480), + page_size(64), + gran(64), + bpl(640*2), + pfp(0), + special(0), + q(0); + + q += notation_file.GetEntry(mode_string, "mode", &mode); + q += notation_file.GetEntry(mode_string, "width", &width); + q += notation_file.GetEntry(mode_string, "height", &height); + q += notation_file.GetEntry(mode_string, "sizeInKB", &page_size); + q += notation_file.GetEntry(mode_string, "granularityInKB", &gran); + q += notation_file.GetEntry(mode_string, "bytesPerLine", &bpl); + q += notation_file.GetEntry(mode_string, "pageFcnPtr", &pfp); + q += notation_file.GetEntry(mode_string, "special", &special); + + if (q == 8) + { + graphicsDisplay = new + SVGA16( + mode, + width, + height, + page_size, + gran, + bpl, + pfp, + special, + windowed, + secondaryIndex, + aux1Index, + aux2Index + ); + if (graphicsDisplay != NULL) + { + Register_Object(graphicsDisplay); + } + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// ~L4GaugeRenderer +//############################################################################# +// +L4GaugeRenderer::~L4GaugeRenderer() +{ +# if defined (LOCAL_TEST) + Tell("L4GaugeRenderer::~L4GaugeRenderer()\n"); +# endif + Check(this); + + int i; + + //---------------------------------------------------- + // Make sure all gauges removed first + //---------------------------------------------------- + Remove(0); + //---------------------------------------------------- + // Delete the graphics ports + //---------------------------------------------------- + for(i=0; iUpdatePalette(); + } + + Time newTime = Now(); + + Scalar diff = newTime - old; + + Check_Fpu(); +} + +// +//############################################################################# +// ExecuteImplementation +//############################################################################# +// +Logical + L4GaugeRenderer::ExecuteBackgroundDisplayUpdate() +{ + Check(this); + + Logical + result = False; // False == 'all done' + + //-------------------------------------------------------- + // Update external annunciator + // + // Allow the plasma display to continue if there's + // more background time available. + // + // This method is still called if taskmode is set to + // 'foreground'. If it's called in 'foreground' mode, + // it really means that we're still waiting for foreground + // to begin processing, so we might as well update the + // external display (if needed). + //-------------------------------------------------------- + if (externalDisplay != NULL) + { + Check(externalDisplay); + result = externalDisplay->Update(False); // returns 'False' if done + } + //------------------------------------------------------- + // Update display ONLY in 'copy' mode + //-------------------------------------------------------- + if (taskMode == copy) + { + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + + if (graphicsDisplay->Update(False) == False) + { + //-------------------------------------------------------- + // Tell executionImplementation that we're basically done. + //-------------------------------------------------------- + taskMode = foreground; + } + else + { + result = True; // We're not done yet! + } + } + } else if (l4_application->GetApplicationState() == Application::WaitingForEgg) + { + ((SVGA16*)graphicsDisplay)->Refresh(); + } + + return result; +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + L4GaugeRenderer::NotifyOfNewInterestingEntity( + Entity *interesting_entity + ) +{ + SET_GAUGE_RENDERER(); + Check(this); + Check(interesting_entity); + //---------------------------------------------- + // Make sure gaugeImage exists for entity + //---------------------------------------------- + Check(warehousePointer); + + ((L4Warehouse*)warehousePointer)->gaugeImageBin.Get( + interesting_entity->GetResourceID() + ); + //---------------------------------------------- + // Update gaugeRenderer + //---------------------------------------------- + GaugeRenderer::NotifyOfNewInterestingEntity(interesting_entity); + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); +} + +// +//############################################################################# +// NotifyOfBecomingUninterestingEntity +//############################################################################# +// +void + L4GaugeRenderer::NotifyOfBecomingUninterestingEntity( + Entity *uninteresting_entity + ) +{ + SET_GAUGE_RENDERER(); + Check(this); + Check(uninteresting_entity); + //---------------------------------------------- + // Remove gaugeImage if no longer used + //---------------------------------------------- + Check(warehousePointer); + + ((L4Warehouse*)warehousePointer)->gaugeImageBin.Release( + uninteresting_entity->GetResourceID() + ); + //---------------------------------------------- + // Update gaugeRenderer + //---------------------------------------------- + GaugeRenderer::NotifyOfBecomingUninterestingEntity(uninteresting_entity); + Check_Fpu(); + CLEAR_GAUGE_RENDERER(); +} + +// +//############################################################################# +// BuildGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::BuildGraphicsPort( + int port_number, + const char *name, + int rotation, + int bitAllocation, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ) +{ + Test_Tell("L4GaugeRenderer::BuildGraphicsPort\n"); + Check(this); + + if (graphicsDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + // + //--------------------------------------------------------- + // If it already exists, delete it + //--------------------------------------------------------- + // + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Test_Tell("...deleting existing port\n"); + Check(graphics_port); + Unregister_Object(graphics_port); + delete graphics_port; + } + // + //--------------------------------------------------------- + // Attempt to create it + //--------------------------------------------------------- + // + graphicsPort[port_number] = new L4GraphicsPort( + (Video16BitBuffered *) graphicsDisplay, + name, + rotation, + bitAllocation, + palette_ID, + enable_ID + ); + + graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + Test_Tell("...new port at " << graphics_port << "\n"); + // + //--------------------------------------------------------- + // If created, register it and build the palette + //--------------------------------------------------------- + // + if (graphics_port != NULL) + { + Check(graphics_port); + Register_Object(graphics_port); + // + // Set the palette for the port + // (Note: secondary uses lowest 8 bits) + // + if ((bitAllocation > 0) && (bitAllocation < 0x0100)) + { + Test_Tell("...secondary\n"); + graphics_port->SetSecondaryPalette(palette); + } + else + { + Test_Tell("...auxiliary\n"); + graphics_port->SetAuxiliaryPalette(); + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// RemapGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::RemapGraphicsPort( + int port_number, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ) +{ + Check(this); + Test_Tell("L4GaugeRenderer::RemapGraphicsPort\n"); + + if (graphicsDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + //--------------------------------------------------------- + // If it exists, change the palette ID and set the palette + //--------------------------------------------------------- + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Check(graphics_port); + // + // Set the palette ID + // + graphics_port->SetPaletteID(palette_ID); + graphics_port->SetEnableID(enable_ID); + + // + // Set the palette for the port + // (Note: secondary uses lowest 8 bits) + // + + int + bit_mask = graphics_port->GetBitMask(); + + if (bit_mask & 0x00FF) // must be secondary + { + Test_Tell("...secondary\n"); + Verify(palette != NULL); + graphics_port->SetSecondaryPalette(palette); + } + else + { + Test_Tell("...auxiliary\n"); + graphics_port->SetAuxiliaryPalette(); + } + } + } + Check_Fpu(); +} + +// +//############################################################################# +// BuildExternalGraphicsPort +//############################################################################# +// +void + L4GaugeRenderer::BuildExternalGraphicsPort( + int port_number, + const char *name, + int /*bitAllocation*/ + ) +{ + Check(this); + Test_Tell( + "L4GaugeRenderer::BuildExternalGraphicsPort(" << port_number << ")\n" + ); + + if (externalDisplay != NULL) + { + Test_Tell("...non-NULL display\n"); + Verify(port_number < maximumGraphicsPorts); + Verify(port_number >= 0); + Test_Tell("...port_number= " << port_number << "\n"); + // + //--------------------------------------------------------- + // If it already exists, delete it + //--------------------------------------------------------- + // + L4GraphicsPort + *graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + if (graphics_port != NULL) + { + Test_Tell("...deleting existing port\n"); + Check(graphics_port); + Unregister_Object(graphics_port); + delete graphics_port; + } + // + //--------------------------------------------------------- + // Attempt to create it + //--------------------------------------------------------- + // + graphicsPort[port_number] = new L4BytePort( + (Video8BitBuffered *) externalDisplay, + name, + 0 // rotation + ); + + graphics_port = (L4GraphicsPort *) graphicsPort[port_number]; + + Test_Tell("...new port at " << graphics_port << "\n"); + // + //--------------------------------------------------------- + // If created, register it + //--------------------------------------------------------- + // + if (graphics_port != NULL) + { + Check(graphics_port); + Register_Object(graphics_port); + } + } + Check_Fpu(); +} + +// +//############################################################################# +// FadeToWhite, FadeToGame +//############################################################################# +// +void + L4GaugeRenderer::FadeToWhite(Scalar number_of_seconds) +{ + Check(this); + Verify(number_of_seconds >= 0.0); // zero is allowed (instant change) + +// cout << "L4GaugeRenderer::FadeToWhite(" << number_of_seconds << ")\n"; + + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + ((SVGA16 *)graphicsDisplay)->FadeToWhite(number_of_seconds); + } + Check_Fpu(); +} + +void + L4GaugeRenderer::FadeToNormal(Scalar number_of_seconds) +{ + Check(this); + Verify(number_of_seconds >= 0.0); // zero is allowed (instant change) + +// cout << "L4GaugeRenderer::FadeToNormal(" << number_of_seconds << ")\n"; + + if (graphicsDisplay != NULL) + { + Check(graphicsDisplay); + ((SVGA16 *)graphicsDisplay)->FadeToPalettes(number_of_seconds); + } + Check_Fpu(); +} + +// +//############################################################################# +// Configure +//############################################################################# +// +void + L4GaugeRenderer::ConfigureForModel( + const char *configuration_name, + Entity *entity + ) +{ + Check(this); + Check_Pointer(configuration_name); + + Test_Tell( + "L4GaugeRenderer::ConfigureForModel(" << + configuration_name << ", " << + entity << ")\n" + ); + + Check(application); + Check(entity); + + Mission + *mission = application->GetCurrentMission(); + Check(mission); + + const char + *model_name = mission->GetGameModel(); + Check_Pointer(model_name); + + char + full_name[64]; + + Str_Copy(full_name, model_name, sizeof(full_name)); + Str_Cat(full_name, configuration_name, sizeof(full_name)); + + Test_Tell( + "L4GaugeRenderer::ConfigureForModel, full_name=" << full_name << + ")\n" + ); + + Configure(full_name, entity); + Check_Fpu(); +} + +// +//############################################################################# +// SpecialEffect +//############################################################################# +// +void + L4GaugeRenderer::SpecialEffect( + VideoEffectType type, + Scalar duration + ) +{ + Check(this); + + switch (type) + { + case scrambleVideo: + if (graphicsDisplay != NULL) + { + scrambleVideoFlag = True; + scrambleVideoTimeout = ((Scalar)Now()) + duration; + + Check(graphicsDisplay); + ((SVGA16*) graphicsDisplay)->FunkyVideo(True); + } + break; + + // other modes go here + + } + Check_Fpu(); +} + +void + L4GaugeRenderer::ProcessVideoEffects() +{ + Check(this); + Check(graphicsDisplay); + + Time + now = Now(); + + if (scrambleVideoFlag) + { + if (now >= scrambleVideoTimeout) + { + scrambleVideoFlag = False; + ((SVGA16*) graphicsDisplay)->FunkyVideo(False); + } + } + + Check_Fpu(); +} + +//-------------------------------------------------------------------- +// Profiling support +//-------------------------------------------------------------------- +Scalar + L4GaugeRenderer::GetCurrentFramePercentage() +{ + Check(this); + return Get_Frame_Percent_Used(); +} diff --git a/MUNGA_L4/L4GREND.h b/MUNGA_L4/L4GREND.h new file mode 100644 index 0000000..2b3646c --- /dev/null +++ b/MUNGA_L4/L4GREND.h @@ -0,0 +1,150 @@ +#pragma once + +#include "..\munga\gaugrend.h" +#include "l4vb16.h" +#include "l4plasma.h" +#include "l4gauima.h" +#include "l4wrhous.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4GaugeRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class L4GaugeRenderer: + public GaugeRenderer +{ +public: + + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + L4GaugeRenderer(bool windowed, int *secondaryIndex, int *aux1Gauge, int *aux2Gauge); + ~L4GaugeRenderer(); + + void + LocalEmergencyShutdown(); + + Logical + TestInstance() const; + + //-------------------------------------------------------------------- + // Profiling support + //-------------------------------------------------------------------- +protected: + Scalar + GetCurrentFramePercentage(); + //-------------------------------------------------------------------- + // GraphicsPort methods + //-------------------------------------------------------------------- +public: + void + BuildGraphicsPort( + int port_number, + const char *name, + int rotation, + int bitAllocation, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ); + + void + RemapGraphicsPort( + int port_number, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID enable_ID, + Palette8 *palette + ); + + void + BuildExternalGraphicsPort( + int port_number, + const char *name, + int bitAllocation + ); + + // + //-------------------------------------------------------------------- + // 'palette ramping' + //-------------------------------------------------------------------- + // + void + FadeToWhite(Scalar number_of_seconds); + void + FadeToNormal(Scalar number_of_seconds); + // + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- + // + GraphicsDisplay + *GetExternalDisplay() + { + Check(this); + return externalDisplay; + } + + // + //-------------------------------------------------------------------- + // Configuration + //-------------------------------------------------------------------- + // + void + ConfigureForModel( + const char *configuration_name, + Entity *entity + ); + // + //-------------------------------------------------------------------- + // ExecuteImplementation + //-------------------------------------------------------------------- + // +protected: + void + ExecuteForeground(); + Logical + ExecuteBackgroundDisplayUpdate(); + void + LoadMissionImplementation( + Mission *mission + ); + virtual void + NotifyOfNewInterestingEntity(Entity *entity); + virtual void + NotifyOfBecomingUninterestingEntity(Entity *entity); + void + ShutdownImplementation(); + void + SuspendImplementation(); + void + ResumeImplementation(); + // + //-------------------------------------------------------------------- + // Video effects + //-------------------------------------------------------------------- + // +public: + void + SpecialEffect(VideoEffectType type, Scalar duration); + +protected: + + void + ProcessVideoEffects(); + + // + //-------------------------------------------------------------------- + // Protected data + //-------------------------------------------------------------------- + // +protected: + Logical + palettesAreActive; + + GraphicsDisplay + *graphicsDisplay, + *externalDisplay; + + Logical + scrambleVideoFlag; + Time + scrambleVideoTimeout; +}; diff --git a/MUNGA_L4/L4HOST.H b/MUNGA_L4/L4HOST.H new file mode 100644 index 0000000..db6c19a --- /dev/null +++ b/MUNGA_L4/L4HOST.H @@ -0,0 +1,112 @@ +//===========================================================================// +// File: l4host.hpp // +// Project: MUNGA Brick: Connection Library // +// Contents: additional L4 data types and functions for hosts // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 04/09/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#pragma once + +#include "..\munga\host.h" +#include "..\munga\cstr.h" + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ L4Host ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +#define L4HOST_PAD_BUFFER_SIZE 4096 + + // + //-------------------------------------------------------------------- + // L4Host + // + // Derived from Host, so we can add a place to store the host's network + // socket pointer. + //-------------------------------------------------------------------- + // + + class L4Host: + public Host + { + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, and testing + //-------------------------------------------------------------------- + // + L4Host( + HostID host_ID, + HostType host_type, + const SOCKADDR_IN *network_address, + //WinSock support :ADB 01/06/07 + //unsigned long NetworkSocket, + SOCKET NetworkScocket, + const CString &net_name); + ~L4Host(); + // + //-------------------------------------------------------------------- + // Accessors + //-------------------------------------------------------------------- + // +#if 0 + enum ConnectionStatus + { + NoNetworkConnectionStatus, // Initial state, host just created with no net link + OpeningConnectionStatus, // Waiting for completion of an active open to this host + ListeningConnectionStatus, // Waiting for this host to connect to us + OnLineConnectionStatus // Host is on-line and ready + }; + ConnectionStatus + GetConnectStatus() + {return ConnectStatus;} + void + SetConnectStatus(ConnectionStatus new_status) + {ConnectStatus = new_status;} +#endif + //WinSock support :ADB 01/06/07 + //unsigned long GetNetworkSocket() + SOCKET GetNetworkSocket() + {return NetworkSocket;} + void + SetNetworkSocket(unsigned long net_socket) + {NetworkSocket = net_socket;} + CString + GetSymbolicName() + {return SymbolicName;} + // + // Nasty to make these things public but I'll have to clean them later + // + public: + #if defined(TRACE_SEND_BUFFER) + TraceOf + *sendBufferTrace; + char + sendBufferTraceName[50]; + #endif + char + pad_buffer[L4HOST_PAD_BUFFER_SIZE]; // a place to buffer up messages + unsigned short + pad_size, // total size of the pad buffer + pad_head, // circular buffer pointers for keeping track of the + pad_tail; // data in the pad buffer. + // + //-------------------------------------------------------------------- + // Private data + //-------------------------------------------------------------------- + // + private: + //WinSock support :ADB 01/06/07 + //unsigned long NetworkSocket; // address of the network socket this host uses + SOCKET NetworkSocket; // address of the network socket this host uses +#if 0 + ConnectionStatus + ConnectStatus; // current connection status +#endif + CString + SymbolicName; // Text version of net address from egg +}; \ No newline at end of file diff --git a/MUNGA_L4/L4HOST.cpp b/MUNGA_L4/L4HOST.cpp new file mode 100644 index 0000000..9f63199 --- /dev/null +++ b/MUNGA_L4/L4HOST.cpp @@ -0,0 +1,31 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4host.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for l4host +// +//WinSock support :RB 1/11/07 +L4Host::L4Host(HostID host_ID, HostType host_type, const SOCKADDR_IN *network_address, SOCKET network_socket, const CString &net_name) + : Host(host_ID, host_type, network_address), SymbolicName(net_name) +{ + NetworkSocket = network_socket; + // ConnectStatus = NoNetworkConnectionStatus; + pad_head = 0; + pad_tail = 0; + pad_size = L4HOST_PAD_BUFFER_SIZE; + #if defined(TRACE_SEND_BUFFER) + sprintf(sendBufferTraceName,"Send Buffer %d",network_address&0xff); + sendBufferTrace = new TraceOf(sendBufferTraceName, 0, Trace::IntegerType, TraceSample::IntegerSnapshot); + Register_Object(sendBufferTrace); + sendBufferTrace->TakeSnapshot(4096); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for l4host +// +L4Host::~L4Host() +{ +} diff --git a/MUNGA_L4/L4ICOM.cpp b/MUNGA_L4/L4ICOM.cpp new file mode 100644 index 0000000..21fb412 --- /dev/null +++ b/MUNGA_L4/L4ICOM.cpp @@ -0,0 +1,1026 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4icom.h" +#include "l4host.h" +#include "l4app.h" +#include "l4grend.h" +#include "..\munga\hostmgr.h" + +//----------------------------------------------------------- +// Timing values (in seconds) for CB button control +// All values derived experimentally +//----------------------------------------------------------- +#define SEEK_STEP_TIME 0.28 // seek step delay +#define NORMAL_STEP_TIME 0.05 // normal step delay +#define BEEP_TIME 0.2 // length of beep + +//----------------------------------------------------------- +// Special code & data to test recalibration: +// set to '1' to create and use 'home' button +//----------------------------------------------------------- +#if 1 +# define HOMETEST + static ControlsButton + resetButton; + enum + { + resetButtonNumber = LBE4ControlsManager::ButtonSecondary6 + }; +#endif +//----------------------------------------------------------- +// Debugging aid +//----------------------------------------------------------- +#if 0 +# define LOCAL_TEST +# define Test_Tell(n) cout << n << flush; +#else +# define Test_Tell(n) +#endif + +//----------------------------------------------------------- +// Button/lamp assignments +//----------------------------------------------------------- +static int + channelButtonNumber[L4Icom::numberOfChannels] = + { + LBE4ControlsManager::ButtonAuxUpperCenter1, + LBE4ControlsManager::ButtonAuxUpperCenter2, + LBE4ControlsManager::ButtonAuxUpperCenter3, + LBE4ControlsManager::ButtonAuxUpperCenter4, + LBE4ControlsManager::ButtonAuxUpperCenter5, + LBE4ControlsManager::ButtonAuxUpperCenter6, + LBE4ControlsManager::ButtonAuxUpperCenter7 + }; + +#if 0 + enum + { + // + // TEST I/O + // + pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8, + homeSensorInput = LBE4ControlsManager::ButtonPanic, + pttRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight5, + ampEnableOutput = LBE4ControlsManager::ButtonAuxLowerRight6, + IncrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight7, + DecrementRelayOutput = LBE4ControlsManager::ButtonAuxLowerRight8 + }; +#else + enum + { + // + // These are the "real" assignments + // + pttButtonNumber = LBE4ControlsManager::ButtonAuxUpperCenter8, + homeSensorInput = LBE4ControlsManager::ButtonIcomSensor, + pttRelayOutput = LBE4ControlsManager::LampIcomPTTRelay, + ampEnableOutput = LBE4ControlsManager::LampIcomAmpEnable, + IncrementRelayOutput = LBE4ControlsManager::LampIcomIncRelay, + DecrementRelayOutput = LBE4ControlsManager::LampIcomDecRelay + }; +#endif + +//----------------------------------------------------------- +// Handy routine to mute audio output +//----------------------------------------------------------- +void + amp_enable(LBE4ControlsManager * controls_manager, Logical on) +{ + controls_manager->SetLamp( + ampEnableOutput, + (on ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidOff + ) + ); + Check_Fpu(); +} + +//########################################################################## +//############################ L4Icom ################################ +//########################################################################## + +//--------------------------------------------------------------------- +// Creator +//--------------------------------------------------------------------- +L4Icom::L4Icom(HostID host_id, int channel_offset) +: +Icom(host_id,0) +{ + Test_Tell("L4Icom::L4Icom(" << host_id << ", " << channel_offset << ")\n"); + Check_Pointer(this); + //-------------------------------------- + // Initialize values + //-------------------------------------- + channelOffset = channel_offset; + + Check(application); + controlsManager = (LBE4ControlsManager *) + application->GetControlsManager(); + Check(controlsManager); + + hardwareChannel = Icom::undefinedChannel; + previousChannel = Icom::undefinedChannel; + previousPTTStatus = False; + //-------------------------------------- + // Clear controls inputs + //-------------------------------------- + homeSensor = 0; + channelButton = 0; + pttButton = 0; + //-------------------------------------- + // Enable only if allowed + //-------------------------------------- + char + *controlString(getenv("L4INTERCOM")); + + if (controlString != NULL) + { + //-------------------------------------- + // Seek channel 40, move to 1st channel + //-------------------------------------- + Recalibrate(); + } + else + { + //-------------------------------------- + // Don't even try. + //-------------------------------------- + state = disabled; + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Destructor +//--------------------------------------------------------------------- +L4Icom::~L4Icom() +{ + Test_Tell("L4Icom::~L4Icom()\n"); + Check(this); + //-------------------------------------- + // Make sure intercom is turned off + //-------------------------------------- + SetPTTStatusValue(False); + amp_enable(controlsManager, False); + //-------------------------------------- + // Make note of failure state + //-------------------------------------- + if (state == failed) + { + Tell("L4Icom::~L4Icom(), Icom had failed!\n"); + NotationFile + *failureFile = new NotationFile("FAILURE.LOG"); + Check(failureFile); + + failureFile->SetEntry("Intercom","seekError",1); + + delete failureFile; + } + //-------------------------------------- + // The plug automatically unlinks + // from the L4Icom Manager upon deletion. + //-------------------------------------- + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Test instance +//--------------------------------------------------------------------- +Logical + L4Icom::TestInstance() const +{ + Icom::TestInstance(); + Check_Fpu(); + return True; +} + +//--------------------------------------------------------------------- +// SetChannelValue +//--------------------------------------------------------------------- +void + L4Icom::SetChannelValue(int new_channel) +{ + Test_Tell("L4Icom::SetChannelValue(" << new_channel << ")\n"); + Check(this); + + if ((state != disabled) && (state != failed)) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + Icom::SetChannelValue(new_channel); + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Set PTTStatusValue +//--------------------------------------------------------------------- +void + L4Icom::SetPTTStatusValue(Logical new_ptt) +{ + Test_Tell("L4Icom::SetPTTStatusValue(" << new_ptt << ")\n"); + Check(this); + + if (state == onChannel) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + Icom::SetPTTStatusValue(new_ptt); + //-------------------------------------- + // Turn on/off PTT output and lamp + //-------------------------------------- + if (previousPTTStatus != PTTStatus) + { + previousPTTStatus = PTTStatus; + + Check(controlsManager); + int + relay_output = + PTTStatus ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidOff; + + controlsManager->SetLamp(pttRelayOutput, relay_output); + + controlsManager->SetLamp( + pttButtonNumber, + (PTTStatus ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidDim + ) + ); + } + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// SetPACaptiveValue +//--------------------------------------------------------------------- +void + L4Icom::SetPACaptiveValue(Logical new_pa) +{ + Test_Tell("L4Icom::SetPACaptiveValue(" << new_pa << ")\n"); + Check(this); + + //----------------------------------------------- + // If entering captivity, disable channel select + //----------------------------------------------- + if (new_pa && (!PACaptive)) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + Icom::SetPACaptiveValue(new_pa); + //-------------------------------------- + // turn off PTT lamp + //-------------------------------------- + controlsManager->SetLamp( + pttButtonNumber, + LBE4ControlsManager::LampSolidOff + ); + //-------------------------------------- + // Turn off channel indicators + //-------------------------------------- + ChannelSelectState(False); + } + //----------------------------------------------- + // If exiting captivity, enable channel select + //----------------------------------------------- + if ((!new_pa) && PACaptive) + { + //-------------------------------------- + // Call overridden method + //-------------------------------------- + // This must be done BEFORE + // attempting to set the PTT status! + // (hence the duplicated call) + //-------------------------------------- + Icom::SetPACaptiveValue(new_pa); + + ChannelSelectState(True); + previousPTTStatus = 2; // non-Logical value, forces update + SetPTTStatusValue(PTTStatus); // force hardware update + } + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Recalibrate +//--------------------------------------------------------------------- +void + L4Icom::Recalibrate() +{ + Test_Tell("L4Icom::Recalibrate()\n"); + Check(this); + + seekRequired = False; + timeAccumulator = 0.0; + seekCount = 84; // twice around plus a few more + ChannelSelectState(False); // Turn off selection lamps + amp_enable(controlsManager, False); // turn off the speaker + state = seek40; + + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// Update +//--------------------------------------------------------------------- +void + L4Icom::Update(Scalar delta_t) +{ + Test_Tell("L4Icom::Update(" << delta_t << ")\n"); + Check(this); + + //------------------------------------------------------------------ + // Do nothing if disabled or failed! + //------------------------------------------------------------------ + if ((state == disabled) || (state == failed)) + { + Check_Fpu(); + return; + } + //------------------------------------------------------------------ + // PTT control + //------------------------------------------------------------------ + if (state == onChannel) + { + if (pttButton > 0) + { + SetPTTStatus(True); + pttButton = 0; + } + else if (pttButton < 0) + { + SetPTTStatus(False); + pttButton = 0; + } + } + else if (previousPTTStatus) + { + SetPTTStatus(False); + } + + //------------------------------------------------------------------ + // Channel selection + //------------------------------------------------------------------ + if (channelSelectEnabled) + { + //-------------------------------------- + // Process button if pressed + //-------------------------------------- + if (channelButton > 0) + { + //-------------------------------------- + // Convert button press to icom channel + //-------------------------------------- + int + button_number = channelButton - 1, // convert to button number + new_channel = Icom::undefinedChannel; + + for(int i=0; i 0) + { + //------------------------------------------- + // Found 40! + //------------------------------------------- + Test_Tell("--> reachedChannel\n"); + hardwareChannel = (40-1); + state = reachedChannel; + //------------------------------------------- + // Display auxiliary intercom labels + //------------------------------------------- + { + Check(application); + + L4GaugeRenderer + *gauge_renderer = ((L4Application *)application)-> + GetGaugeRenderer(); + Check(gauge_renderer); + + gauge_renderer->Configure("intercomEnable", (Entity *) NULL); + } + //------------------------------------------- + // Everybody starts up on the 'first' channel + //------------------------------------------- + if (PACaptive) + { + channelBeforePA = channelOffset; + } + else + { + ChannelSelectState(True); + SetChannel(channelOffset); + } + //------------------------------------------- + // Update the lamp display + //------------------------------------------- + ChannelStatusUpdate(); + } + //------------------------------------------- + // Try next channel + //------------------------------------------- + else + { + DecrementChannel(); + } + } + break; + + //--------------------------------------------------- + case offChannel: + if (WaitedLongEnough(NORMAL_STEP_TIME)) + { + int + delta = channel - hardwareChannel; + if (delta == 0) + { + state = reachedChannel; + } + else + { + //------------------------------------------- + // Choose direction, modulo 40 + //------------------------------------------- + // channel = desired channel + // hardwareChannel = current channel + //------------------------------------------- + if (delta > 20) + { + delta -= 40; + } + else if (delta < -20) + { + delta += 40; + } + + if (delta < 0) + { + DecrementChannel(); + } + else + { + IncrementChannel(); + } + //------------------------------------------- + // Update the lamp display + //------------------------------------------- + ChannelStatusUpdate(); + } + } + break; + + //--------------------------------------------------- + // reachedChannel: this is a delay to allow to CB + // to finish "beeping" before the audio is turned on. + //--------------------------------------------------- + case reachedChannel: + if (WaitedLongEnough(BEEP_TIME)) + { + Test_Tell("L4Icom::Update, reachedChannel --> onChannel\n"); + amp_enable(controlsManager, True); + state = onChannel; + } + break; + //--------------------------------------------------- + case onChannel: + Test_Tell("L4Icom::Update, onChannel\n"); + + if (channel != hardwareChannel) + { + state = offChannel; + timeAccumulator = NORMAL_STEP_TIME; // bypass the delay + amp_enable(controlsManager, False); // mute the output + } + break; + //--------------------------------------------------- + case disabled: + case failed: + break; + } + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// LongEnough +//--------------------------------------------------------------------- +Logical + L4Icom::WaitedLongEnough(Scalar delay_time) +{ + Test_Tell("L4Icom::WaitedLongEnough(" << delay_time >> ") "); + Check(this); + + //------------------------------------------- + // Check to see if delayed long enough + //------------------------------------------- + if (timeAccumulator >= delay_time) + { + Test_Tell("long enough!\n"); + timeAccumulator = 0.0; + Check_Fpu(); + return True; + } + else + { + Test_Tell("\n"); + Check_Fpu(); + return False; + } +} + +//--------------------------------------------------------------------- +// IncrementChannel +//--------------------------------------------------------------------- +void + L4Icom::IncrementChannel() +{ + Test_Tell("L4Icom::IncrementChannel()\n"); + Check(this); + Check(controlsManager); + + //-------------------------------------- + // Increment the channel number counter + //-------------------------------------- + if (++hardwareChannel > (40-1)) + { + hardwareChannel = 0; + } + //-------------------------------------- + // Press the 'inc' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + IncrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // ...and again, for a fixed delay + //-------------------------------------- + controlsManager->SetLamp( + IncrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // Release the 'inc' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + IncrementRelayOutput, + LBE4ControlsManager::LampSolidOff + ); + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// DecrementChannel +//--------------------------------------------------------------------- +void + L4Icom::DecrementChannel() +{ + Test_Tell("L4Icom::DecrementChannel()\n"); + Check(this); + Check(controlsManager); + + //-------------------------------------- + // Decrement the channel number counter + //-------------------------------------- + if (--hardwareChannel < 0) + { + hardwareChannel = (40-1); + } + //-------------------------------------- + // Press the 'dec' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + DecrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // ...and again, for a fixed delay + //-------------------------------------- + controlsManager->SetLamp( + DecrementRelayOutput, + LBE4ControlsManager::LampSolidBright + ); + //-------------------------------------- + // Release the 'dec' button on the CB + //-------------------------------------- + controlsManager->SetLamp( + DecrementRelayOutput, + LBE4ControlsManager::LampSolidOff + ); + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// ChannelStatusUpdate +//--------------------------------------------------------------------- +void + L4Icom::ChannelStatusUpdate() +{ + Test_Tell("L4Icom::ChannelStatusUpdate()\n"); + Check(this); + Check(controlsManager); + + int + logical_channel_number; + + if (channelSelectEnabled) + { + //-------------------------------------- + // Has the channel changed? + //-------------------------------------- + if (previousChannel != hardwareChannel) + { + //---------------------------------------- + // Yes. Is the previous channel undefined? + //---------------------------------------- + if (previousChannel != Icom::undefinedChannel) + { + //-------------------------------------- + // No, set previous button to dim + //-------------------------------------- + logical_channel_number = previousChannel - channelOffset; + if (logical_channel_number < L4Icom::numberOfChannels) + { + controlsManager->SetLamp( + channelButtonNumber[logical_channel_number], + LBE4ControlsManager::LampSolidDim + ); + } + } + previousChannel = hardwareChannel; + //-------------------------------------- + // Is the new channel undefined? + //-------------------------------------- + if (previousChannel != Icom::undefinedChannel) + { + //-------------------------------------- + // No, set current button to bright + //-------------------------------------- + logical_channel_number = hardwareChannel - channelOffset; + if (logical_channel_number < L4Icom::numberOfChannels) + { + controlsManager->SetLamp( + channelButtonNumber[logical_channel_number], + LBE4ControlsManager::LampSolidBright + ); + } + } + } + } + Check_Fpu(); +} + +//--------------------------------------------------------------------- +// ChannelSelectState +//--------------------------------------------------------------------- +void + L4Icom::ChannelSelectState(Logical state) +{ + Test_Tell("L4Icom::ChannelStatusUpdate(" << state << ")\n"); + Check(this); + Check(controlsManager); + + int + i, + logical_channel_number; + + if ((state != disabled) && (state != failed)) + { + channelSelectEnabled = True; + + for(i=0; iSetLamp( + channelButtonNumber[i], + (i==logical_channel_number ? + LBE4ControlsManager::LampSolidBright : + LBE4ControlsManager::LampSolidDim + ) + ); + } + } + else + { + channelSelectEnabled = False; + + for(i=0; iSetLamp( + channelButtonNumber[i], + LBE4ControlsManager::LampSolidOff + ); + } + } + Check_Fpu(); +} + +//########################################################################## +//######################## L4IcomManager ############################# +//########################################################################## + +//-------------------------------------------------------------------------- +// Virtual Data support +// + +Derivation* L4IcomManager::GetClassDerivations() +{ + static Derivation classDerivations(IcomManager::GetClassDerivations(), "L4IcomManager"); + return &classDerivations; +} + +L4IcomManager::SharedData + L4IcomManager::DefaultData( + L4IcomManager::GetClassDerivations(), + L4IcomManager::GetMessageHandlers() + ); + +//-------------------------------------------------------------------------- +// Creator +// + +L4IcomManager::L4IcomManager( + SharedData &shared_data +): + IcomManager(shared_data), + localIcom(NULL) +{ + Test_Tell("L4IcomManager::L4IcomManager()\n"); + Check_Pointer(this); + + previousUpdateTime = Now(); + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +// Destructor +// +L4IcomManager::~L4IcomManager() +{ + Test_Tell("L4IcomManager::~L4IcomManager()\n"); + Check(this); + + // We don't need to delete the local Icom object: it's a member + // of the instanceList in the IcomManager class, which is deleted + // by the IcomManager destructor. + + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +Logical + L4IcomManager::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//-------------------------------------------------------------------------- +L4Icom * + L4IcomManager::MakeIcom(HostID host_id, int /*unit_number*/) +{ + Test_Tell("L4IcomManager::MakeIcom(" << host_id << ")\n"); + Check(this); + + //------------------------------------------ + // Create, register icom object + //------------------------------------------ + L4Icom + *icom = new L4Icom(host_id, 0); // HACK - eventually set channel offset based on cockpit group! + Check(icom); + Register_Object(icom); + //------------------------------------------ + // Add to global list + //------------------------------------------ + instanceList.Add(icom); + //------------------------------------------ + // Get local host ID + // (we need to do because the local host is + // created quite late in the whole process) + //------------------------------------------ + Check(application); + HostManager + *host_manager = application->GetHostManager(); + Check(host_manager); + Host + *local_host = host_manager->GetLocalHost(); + Check(local_host); + HostID + local_host_id = local_host->GetHostID(); + //------------------------------------------ + // If assigned to a local host, make + // this intercom object local as well + //------------------------------------------ + Test_Tell( + "L4IcomManager::MakeIcom local_host_id = " << local_host_id << "\n" + ); + Test_Tell( + "L4IcomManager::MakeIcom host_id = " << host_id << "\n" + ); + if (host_id == local_host_id) + { + Test_Tell("L4IcomManager::MakeIcom, set local icom\n"); + //----------------------------------------------------------------- + // Set localIcom socket + //----------------------------------------------------------------- + Verify(localIcom.GetCurrent() == NULL); + localIcom.AddPlug(icom); + //----------------------------------------------------------------- + // Add connections + //----------------------------------------------------------------- +#if 0 + Check(icom->controlsManager); + ControlsUpdateManager + *button_pointer; + //------------------------------------------ + // Add connection to home sensor + //------------------------------------------ + button_pointer = &icom->controlsManager->buttonGroup[homeSensorInput]; + Check(button_pointer); + button_pointer->Add( + ModeManager::ModeAlwaysActive, &icom->homeSensor, icom + ); + //------------------------------------------ + // Add connections to channel buttons + //------------------------------------------ + for(int i=0; icontrolsManager->buttonGroup[channelButtonNumber[i]]; + Check(button_pointer); + button_pointer->Add( + L4ModeManager::ModeIntercom, &icom->channelButton, icom + ); + icom->controlsManager->MakeLinkedLamp(channelButtonNumber[i]); + } +# if defined(HOMETEST) + //------------------------------------------ + // Add connection to reset button + //------------------------------------------ + button_pointer = + &icom->controlsManager->buttonGroup[resetButtonNumber]; + Check(button_pointer); + button_pointer->Add( + ModeManager::ModeAlwaysActive, &resetButton, icom + ); + + resetButton = 0; +# endif + //------------------------------------------ + // Add connection to PTT button + //------------------------------------------ + button_pointer = &icom->controlsManager->buttonGroup[pttButtonNumber]; + Check(button_pointer); + button_pointer->Add( + ModeManager::ModeAlwaysActive, &icom->pttButton, icom + ); + icom->controlsManager->MakeLinkedLamp(pttButtonNumber); +#endif + } + + Check_Fpu(); + return icom; +} + +//-------------------------------------------------------------------------- +void + L4IcomManager::LoadMission(Mission *mission) +{ + Check(this); + IcomManager::LoadMission(mission); + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + L4IcomManager::Shutdown() +{ + Check(this); + IcomManager::Shutdown(); + Check_Fpu(); +} + +//-------------------------------------------------------------------------- +void + L4IcomManager::Execute() +{ +// Test_Tell("L4IcomManager::Execute()\n"); + Check(this); + + Scalar + delta_t; + Time + right_now; + +# if defined(HOMETEST) + //------------------------------------------ + // If reset button pressed, recalibrate + //------------------------------------------ + if (resetButton > 0) + { + resetButton = 0; + + L4Icom + *local_icom = localIcom.GetCurrent(); + + if (local_icom != NULL) + { + std::cout << "L4IcomManager::Execute, Reset!!!!!\n"; + local_icom->Recalibrate(); + } + } +# endif + //------------------------------------------ + // Get time, generate delta_t + //------------------------------------------ + right_now = Now(); + delta_t = (Scalar) (right_now - previousUpdateTime); + + if (delta_t > 0.0) + { + previousUpdateTime = right_now; + //------------------------------------------ + // Process local icom object + //------------------------------------------ + L4Icom + *local_icom = localIcom.GetCurrent(); + + if (local_icom != NULL) + { + local_icom->Update(delta_t); + } + } + Check_Fpu(); +} diff --git a/MUNGA_L4/L4ICOM.h b/MUNGA_L4/L4ICOM.h new file mode 100644 index 0000000..6a75452 --- /dev/null +++ b/MUNGA_L4/L4ICOM.h @@ -0,0 +1,169 @@ +#pragma once + +#include "..\munga\icom.h" +#include "l4ctrl.h" +#include "..\munga\time.h" + +//########################################################################## +//############################ L4Icom ################################ +//########################################################################## +class L4Icom: + public Icom +{ + friend class L4IcomManager; + +public: + L4Icom(HostID host_id, int channel_offset); + ~L4Icom(); // base destructor is virtual + Logical + TestInstance() const; + + //-------------------------------------------------- + // Channel offset accessor + //-------------------------------------------------- + int + GetChannelOffset() + { + Check(this); + return channelOffset; + } + //-------------------------------------------------- + // public data + //-------------------------------------------------- + ControlsButton + pttButton; + + enum + { + numberOfChannels=7 + }; + +protected: + //-------------------------------------------------- + // These methods are used to locally set the value + // for the channel, PTT, and PA status. + // + // The difference between these methods and the + // public methods defined in the base class is that + // these methods are called by both the base class + // public routines and the event receiver to actually + // set the values involved. Making them virtual + // allows derived classes to be notified of changes + // (but also requires that all derived classes + // explicitly call the overridden methods!) + //-------------------------------------------------- + void + SetChannelValue(int new_channel); // base method is virtual + void + SetPTTStatusValue(Logical new_ptt); // base method is virtual + void + SetPACaptiveValue(Logical new_pa); // base method is virtual + //-------------------------------------------------- + // Recalibrate hardware + //-------------------------------------------------- + void + Recalibrate(); + //-------------------------------------------------- + // Hardware control method + //-------------------------------------------------- + void + Update(Scalar delta_t); + +private: + Logical + WaitedLongEnough(Scalar how_long); + void + IncrementChannel(); + void + DecrementChannel(); + void + ChannelStatusUpdate(); + void + ChannelSelectState(Logical state); + //-------------------------------------------------- + // Protected data + //-------------------------------------------------- +protected: + LBE4ControlsManager + *controlsManager; + + ControlsButton + homeSensor, + channelButton; + Scalar + timeAccumulator; + int + hardwareChannel, + previousChannel, + channelOffset, + seekCount; + int + previousPTTStatus; + Logical + channelSelectEnabled, + seekRequired; + enum + { + disabled = -2, + failed = -1, + seek40, + offChannel, + reachedChannel, + onChannel, + } + state; +}; + +//########################################################################## +//######################## L4IcomManager ############################# +//########################################################################## +class L4IcomManager: + public IcomManager +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + L4IcomManager( + SharedData &shared_data=DefaultData + ); + ~L4IcomManager(); // base destructor is virtual + + Logical + TestInstance() const; + + L4Icom * + MakeIcom(HostID host_id, int unit_number=0); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LoadMission, Shutdown methods +// ...these are declared virtual in ICOM.HPP and must chain back to +// the previous methods. +// +public: + void + LoadMission(Mission *mission); + void + Shutdown(); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Periodic update function +// + void + Execute(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// protected data +// +protected: + Time + previousUpdateTime; + + SlotOf + localIcom; +}; diff --git a/MUNGA_L4/L4JOYSTK.h b/MUNGA_L4/L4JOYSTK.h new file mode 100644 index 0000000..19e57b6 --- /dev/null +++ b/MUNGA_L4/L4JOYSTK.h @@ -0,0 +1,97 @@ +#pragma once + +#include "..\munga\style.h" + +#define PCJ1_Button1 0x10 +#define PCJ1_Button2 0x20 +#define PCJ2_Button1 0x40 +#define PCJ2_Button2 0x80 +#define PC_All_Buttons 0xF0 + +// These are used to build "mask" values, below +#define PCJ_AnalogChannel1 0x01 +#define PCJ_AnalogChannel2 0x02 +#define PCJ_AnalogChannel3 0x04 +#define PCJ_AnalogChannel4 0x08 +#define PC_All_Analog 0x0F + +// Definitions for standard old 2-axis joystick +#define PCJ_Standard_Button1 0x10 +#define PCJ_Standard_Button2 0x20 +#define PCJ_Standard_Mask PCJ_AnalogChannel1|PCJ_AnalogChannel2 + +// Definitions for Flightstick Pro (CH products) +// +// These states are mutually exclusive and ordered by decreasing +// priority (only the highest priority state is returned). +// Yes, this means that you cannot activate two states at a time: +// while you hold the "thumb joystick", you cannot fire. +#define PCJ_FSP_Up 0xF0 // "thumb joystick" up +#define PCJ_FSP_Down 0x70 // "thumb joystick" down +#define PCJ_FSP_Left 0x30 // "thumb joystick" left +#define PCJ_FSP_Right 0xB0 // "thumb joystick" right +#define PCJ_FSP_Trigger 0x10 // Trigger +#define PCJ_FSP_LButton 0x20 // Leftmost button +#define PCJ_FSP_RButton 0x40 // Rightmost button +#define PCJ_FSP_CButton 0x80 // Center button + +#define PCJ_FSP_Mask PCJ_AnalogChannel1 | PCJ_AnalogChannel2 | PCJ_AnalogChannel4 + +// Handy equates for reading the analog values +#define PCJ_FSP_X PC_Joystick1_Raw_X; +#define PCJ_FSP_Y PC_Joystick1_Raw_Y; +#define PCJ_FSP_Dial PC_Joystick2_Raw_Y; + +// Definitions for Thrustmaster +// +// The "hat" actually is connected to resistors on +// analog channel 3. +// Full value is open +// Up is low value +// Down is 1/2 value +// Left is 3/4 value +// Right is 1/4 value +// +#define PCJ_TM_Trigger 0x10 // Trigger +#define PCJ_TM_ThumbHigh 0x20 // Button next to "hat" +#define PCJ_TM_ThumbMid 0x40 // Button halfway down stick +#define PCJ_TM_ThumbLow 0x80 // Lowest thumb button + +#define PCJ_TM_Mask PCJ_AnalogChannel1|PCJ_AnalogChannel2|\ + PCJ_AnalogChannel4 + +// Handy equates for reading the analog values +#define PCJ_FSP_X PC_Joystick1_Raw_X; +#define PCJ_FSP_Y PC_Joystick1_Raw_Y; +#define PCJ_FSP_Dial PC_Joystick2_Raw_Y; + + +//extern "C" Word PC_Joystick1_Raw_X, PC_Joystick1_Raw_Y; +//extern "C" Word PC_Joystick2_Raw_X, PC_Joystick2_Raw_Y; +//extern "C" Byte PC_Joystick_Buttons; + +// +// The PC_Joystick_Mask defaults at power-up to all four channels. +// It should be set according to one of the PCJ_...Mask values from above. +// This will speed up joystick updates by ignoring unused analog channels. +// +//extern "C" Byte PC_Joystick_Mask; +// +//extern "C" void PC_Joystick_Update(void); +// +//extern "C" void test1(void); +//extern "C" void test2(Byte a, Word b, LWord l, char *p); +//extern "C" void test3(void); +//extern "C" void test4(Byte a, Word b, LWord l, char *p); + +// +// In watcom, force stack-based addressing +// + +#if defined(__WATCOMC__) + #pragma aux PC_Joystick_Update parm []; + #pragma aux test1 parm []; + #pragma aux test2 parm []; + #pragma aux test3 parm []; + #pragma aux test4 parm []; +#endif diff --git a/MUNGA_L4/L4KEYBD.cpp b/MUNGA_L4/L4KEYBD.cpp new file mode 100644 index 0000000..6d8d08d --- /dev/null +++ b/MUNGA_L4/L4KEYBD.cpp @@ -0,0 +1,24 @@ +#include "mungal4.h" +#pragma hdrstop + +#include +#include + +int PC_Keyboard_Read(void) +{ + int c; + + if (!kbhit()) // if keyboard has not been hit, return zero + { + return(0); + } + else + { + c = getch(); // keyboard was hit, get code + if (c == 0) // zero: next character is extended code + { + c = getch() | 0x0100; // flag as extended + } + return(c); // return the value + } +} diff --git a/MUNGA_L4/L4KEYBD.h b/MUNGA_L4/L4KEYBD.h new file mode 100644 index 0000000..e87d928 --- /dev/null +++ b/MUNGA_L4/L4KEYBD.h @@ -0,0 +1,138 @@ +#pragma once + +#include "..\munga\style.h" + +#define VK_MASK 0x00FF +#define CTRL_BIT 0x0100 +#define ALT_BIT 0x0200 +// +//---------------------------------------------------------------- +// Handy keycode definitions +//---------------------------------------------------------------- +// +# define PCK_ESC VK_ESCAPE // "escape" key +# define PCK_ENTER VK_RETURN // the ever-popular "enter" key +# define PCK_TAB VK_TAB // the obvious "tab" key +// +//---------------------------------------------------------------- +// Extended keycodes: function keys +//---------------------------------------------------------------- +// +# define PCK_F1 VK_F1 +# define PCK_F2 VK_F2 +# define PCK_F3 VK_F3 +# define PCK_F4 VK_F4 +# define PCK_F5 VK_F5 +# define PCK_F6 VK_F6 +# define PCK_F7 VK_F7 +# define PCK_F8 VK_F8 +# define PCK_F9 VK_F9 +# define PCK_F10 VK_F10 +# define PCK_F11 VK_F11 +# define PCK_F12 VK_F12 +// +//---------------------------------------------------------------- +// Extended keycodes: ctrl-function keys +//---------------------------------------------------------------- +// +# define PCK_CTL_F1 (CTRL_BIT | VK_F1) +# define PCK_CTL_F2 (CTRL_BIT | VK_F2) +# define PCK_CTL_F3 (CTRL_BIT | VK_F3) +# define PCK_CTL_F4 (CTRL_BIT | VK_F4) +# define PCK_CTL_F5 (CTRL_BIT | VK_F5) +# define PCK_CTL_F6 (CTRL_BIT | VK_F6) +# define PCK_CTL_F7 (CTRL_BIT | VK_F7) +# define PCK_CTL_F8 (CTRL_BIT | VK_F8) +# define PCK_CTL_F9 (CTRL_BIT | VK_F9) +# define PCK_CTL_F10 (CTRL_BIT | VK_F10) +# define PCK_CTL_F11 (CTRL_BIT | VK_F11) +# define PCK_CTL_F12 (CTRL_BIT | VK_F12) +// +//---------------------------------------------------------------- +// Extended keycodes: alt-function keys +//---------------------------------------------------------------- +// +# define PCK_ALT_F1 (ALT_BIT | VK_F1) +# define PCK_ALT_F2 (ALT_BIT | VK_F2) +# define PCK_ALT_F3 (ALT_BIT | VK_F3) +# define PCK_ALT_F4 (ALT_BIT | VK_F4) +# define PCK_ALT_F5 (ALT_BIT | VK_F5) +# define PCK_ALT_F6 (ALT_BIT | VK_F6) +# define PCK_ALT_F7 (ALT_BIT | VK_F7) +# define PCK_ALT_F8 (ALT_BIT | VK_F8) +# define PCK_ALT_F9 (ALT_BIT | VK_F9) +# define PCK_ALT_F10 (ALT_BIT | VK_F10) +# define PCK_ALT_F11 (ALT_BIT | VK_F11) +# define PCK_ALT_F12 (ALT_BIT | VK_F12) +// +//---------------------------------------------------------------- +// Extended keycodes: cursor keys (numeric keypad WITH NUMLOCK OFF!) +//---------------------------------------------------------------- +// +# define PCK_INS VK_INSERT +# define PCK_DEL VK_DELETE +# define PCK_HOME VK_HOME +# define PCK_UP VK_UP +# define PCK_PGUP VK_PRIOR +# define PCK_LEFT VK_LEFT +# define PCK_RIGHT VK_RIGHT +# define PCK_END VK_END +# define PCK_DOWN VK_DOWN +# define PCK_PGDN VK_NEXT +// +//---------------------------------------------------------------- +// Extended keycodes: ctrl-cursor keys +//---------------------------------------------------------------- +// +# define PCK_CTL_INS (CTRL_BIT | VK_INSERT) +# define PCK_CTL_DEL (CTRL_BIT | VK_DELETE) +# define PCK_CTL_HOME (CTRL_BIT | VK_HOME) +# define PCK_CTL_UP (CTRL_BIT | VK_UP) +# define PCK_CTL_PGUP (CTRL_BIT | VK_PRIOR) +# define PCK_CTL_LEFT (CTRL_BIT | VK_LEFT) +# define PCK_CTL_RIGHT (CTRL_BIT | VK_RIGHT) +# define PCK_CTL_END (CTRL_BIT | VK_END) +# define PCK_CTL_DOWN (CTRL_BIT | VK_DOWN) +# define PCK_CTL_PGDN (CTRL_BIT | VK_NEXT) +// +//---------------------------------------------------------------- +// Extended keycodes: alt-cursor keys +//---------------------------------------------------------------- +// +# define PCK_ALT_INS (ALT_BIT | VK_INSERT) +# define PCK_ALT_DEL (ALT_BIT | VK_DELETE) +# define PCK_ALT_HOME (ALT_BIT | VK_HOME) +# define PCK_ALT_UP (ALT_BIT | VK_UP) +# define PCK_ALT_PGUP (ALT_BIT | VK_PRIOR) +# define PCK_ALT_LEFT (ALT_BIT | VK_LEFT) +# define PCK_ALT_RIGHT (ALT_BIT | VK_RIGHT) +# define PCK_ALT_END (ALT_BIT | VK_END) +# define PCK_ALT_DOWN (ALT_BIT | VK_DOWN) +# define PCK_ALT_PGDN (ALT_BIT | VK_NEXT) +// +//---------------------------------------------------------------- +// Extended keycodes: alt-keys +//---------------------------------------------------------------- +// +# define PCK_ALT_W (ALT_BIT | 'W') +# define PCK_ALT_R (ALT_BIT | 'R') +# define PCK_ALT_P (ALT_BIT | 'P') +# define PCK_ALT_F (ALT_BIT | 'F') +# define PCK_ALT_K (ALT_BIT | 'K') +# define PCK_ALT_V (ALT_BIT | 'V') +# define PCK_ALT_SLASH (ALT_BIT | VK_OEM_2) // '/?' key + +// +//---------------------------------------------------------------- +// Extended keycodes: ctrl-keys +//---------------------------------------------------------------- +// +# define PCK_CTRL_W (CTRL_BIT | 'W') +# define PCK_CTRL_R (CTRL_BIT | 'R') +# define PCK_CTRL_P (CTRL_BIT | 'P') +# define PCK_CTRL_F (CTRL_BIT | 'F') +# define PCK_CTRL_K (CTRL_BIT | 'K') +# define PCK_CTRL_V (CTRL_BIT | 'V') +# define PCK_CTRL_SLASH (CTRL_BIT | VK_OEM_2) // '/?' key + +extern int PC_Keyboard_Read(void); // returns code or zero if no key diff --git a/MUNGA_L4/L4LAMP.cpp b/MUNGA_L4/L4LAMP.cpp new file mode 100644 index 0000000..711a3a0 --- /dev/null +++ b/MUNGA_L4/L4LAMP.cpp @@ -0,0 +1,389 @@ +#include "mungal4.h" +#pragma hdrstop + +#define PRELOAD_ART + +#include "..\munga\vdata.h" +#include "l4lamp.h" +#include "l4wrhous.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) cout << n +#else +# define Test_Tell(n) +#endif + +//######################################################################### +//############################# L4LampManager ############################# +//######################################################################### +L4LampManager::L4LampManager(LBE4ControlsManager *controls_manager): + LampManager() +{ + Check(controls_manager); + controlsManager = controls_manager; + + previousLampState = new int[LBE4ControlsManager::LampCount]; + Register_Pointer(previousLampState); + lampActiveFlag = new Logical[LBE4ControlsManager::LampCount]; + Register_Pointer(lampActiveFlag); + //----------------------------------------- + // Clear L4 lamp state tables + //----------------------------------------- + int + i; + + Check_Pointer(previousLampState); + for(i=0; i< LBE4ControlsManager::LampCount; ++i) + { + previousLampState[i] = RIO::solid + RIO::state1Off + RIO::state2Off; + } + Check_Fpu(); +} + +L4LampManager::~L4LampManager() +{ + Check(this); + + Unregister_Pointer(previousLampState); + delete[] previousLampState; + previousLampState = NULL; + + Unregister_Pointer(lampActiveFlag); + delete[] lampActiveFlag; + lampActiveFlag = NULL; + + Check_Fpu(); +} + +Logical + L4LampManager::TestInstance() const +{ + Check_Fpu(); + return LampManager::TestInstance(); +} + +void + L4LampManager::Update(ModeMask current_mode_mask) +{ + Check(this); + Logical + flush_inactive_lamps = (current_mode_mask != previousModeMask); + int + i; + + if (flush_inactive_lamps) + { + //--------------------------------------- + // Mark all lamps as inactive + //--------------------------------------- + Check_Pointer(lampActiveFlag); + for(i=0; i< LBE4ControlsManager::LampCount; ++i) + { + lampActiveFlag[i] = False; + } + } + //--------------------------------------- + // Update LampManager, set lamp outputs, + // and mark active lamps + //--------------------------------------- + LampManager::Update(current_mode_mask); + + if (flush_inactive_lamps) + { + //--------------------------------------- + // Turn off inactive lamps + //--------------------------------------- + Check_Pointer(lampActiveFlag); + for(i=0; i< LBE4ControlsManager::LampCount; ++i) + { + if (lampActiveFlag[i] == False) + { + AssertNewLampValue(i, RIO::solid+RIO::state1Off+RIO::state2Off); + } + } + } + Check_Fpu(); +} + +void + L4LampManager::AssertNewLampValue(int lamp_number, int lamp_value) +{ + Check(this); + + Verify(lamp_number >= 0); + Verify(lamp_number < LBE4ControlsManager::LampCount); + //-------------------------------------- + // Update external hardware + //-------------------------------------- + Check_Pointer(previousLampState); + if (previousLampState[lamp_number] != lamp_value) + { + previousLampState[lamp_number] = lamp_value; + //-------------------------------------- + // Send RIO command to update L4 lamp + //-------------------------------------- + Check(controlsManager); + controlsManager->SetLamp(lamp_number, lamp_value); + } + + Check_Fpu(); +} + +//######################################################################### +//################################ L4Lamp ################################# +//######################################################################### +L4Lamp::L4Lamp( + LampID lamp_number, + ModeMask mode_mask, + L4LampManager *lamp_manager +) : + Lamp(lamp_number, mode_mask, (LampManager *) lamp_manager) +{ + automatic = True; + automaticValue = (ControlsButton) 0; + previousAutomaticValue = automaticValue; + + SetState(LampStateDim); + + Check_Fpu(); +} + +L4Lamp::~L4Lamp() +{ + Check(this); + SetState(LampStateOff); + Check_Fpu(); +} + +Logical + L4Lamp::TestInstance() const +{ + return Lamp::TestInstance(); +} + +void + L4Lamp::SetAutomaticOperation(Logical automatic_flag) +{ + Check(this); + automatic = automatic_flag; + Check_Fpu(); +} + +void + L4Lamp::Update(Logical force_notification) +{ + Check(this); + + //-------------------------------------- + // Tell manager we're still active + //-------------------------------------- + if (lampID >= 0) + { + if (lampID < LBE4ControlsManager::LampCount) + { + Check_Pointer(((L4LampManager *)manager)->lampActiveFlag); + ((L4LampManager *)manager)->lampActiveFlag[lampID] = True; + } + } + //-------------------------------------- + // Update state if automatic + //-------------------------------------- + if (automatic) + { + if (previousAutomaticValue != automaticValue) + { + previousAutomaticValue = automaticValue; + + if (previousAutomaticValue > 0) + { + SetState(LampStateOn); + } + else + { + SetState(LampStateDim); + } + } + else if (force_notification) + { + NotifyOfStateChange(); + } + } + else if (force_notification) + { + NotifyOfStateChange(); + } + Check_Fpu(); +} + +void + L4Lamp::NotifyOfStateChange() +{ + Check(this); + Check((L4LampManager *) manager); + + int + output_value; + + if (alertActive) + { + switch(previousState) + { + default: + output_value = RIO::flashFast + RIO::state1Off + RIO::state2Dim; + break; + + case LampStateDim: + case LampStateOn: + output_value = RIO::flashFast + RIO::state1Dim + RIO::state2Bright; + break; + } + } + else + { + switch(previousState) + { + default: + output_value = RIO::solid + RIO::state1Off + RIO::state2Off; + break; + + case LampStateDim: + output_value = RIO::solid + RIO::state1Dim + RIO::state2Dim; + break; + + case LampStateOn: + output_value = RIO::solid + RIO::state1Bright + RIO::state2Bright; + break; + } + } + + ((L4LampManager *) manager)->AssertNewLampValue(lampID, output_value); + Check_Fpu(); +} + +//######################################################################### +//############################# L4VirtualLamp ############################# +//######################################################################### +L4GraphicLamp::L4GraphicLamp( + LampID lamp_id, + ModeMask mode_mask, + GaugeRenderer *the_renderer, + int graphics_port_number, + int left, int bottom, + const char *map_name, + int bg_color, int fg_color, + Logical opaque_flag +) : + GraphicLamp( + lamp_id, + mode_mask, + the_renderer->GetLampManager(), + the_renderer, + graphics_port_number + ) +{ + //-------------------------------------------- + // Build copy of map name + //-------------------------------------------- + Check_Pointer(map_name); + mapName = new char[strlen(map_name)+1]; + Register_Pointer(mapName); + strcpy(mapName, map_name); + //-------------------------------------------- + // Get the image + //-------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + warehouse->bitMapBin.Get(mapName); +# endif + + opaque = opaque_flag; + bgColor = bg_color; + fgColor = fg_color; + localView.SetOrigin(left, bottom); + Check_Fpu(); +} + +L4GraphicLamp::~L4GraphicLamp() +{ + Check(this); + Check_Pointer(mapName); + //-------------------------------------------- + // Release the preloaded image + //-------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + warehouse->bitMapBin.Release(mapName); +# endif + //-------------------------------------------- + // Delete the copy of the name + //-------------------------------------------- + Check_Pointer(mapName); + delete[] mapName; + mapName = NULL; + Check_Fpu(); +} + +Logical + L4GraphicLamp::TestInstance() const +{ + return GraphicLamp::TestInstance(); +} + +void + L4GraphicLamp::NotifyOfStateChange() +{ + Check(this); + //-------------------------------------------- + // Get the bitmap + //-------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + BitMap + *bitmap = warehouse->bitMapBin.Get(mapName); + + if (bitmap != NULL) + { + Check(bitmap); + //-------------------------------------------- + // Set the color + //-------------------------------------------- + if (previousState <= LampStateOff) + { + localView.SetColor(bgColor); + } + else + { + localView.SetColor(fgColor); + } + //-------------------------------------------- + // Draw the bitmap + //-------------------------------------------- + if (opaque) + { + localView.DrawBitMapOpaque(bgColor, 0, bitmap); + } + else + { + localView.DrawBitMap(0, bitmap); + } + //-------------------------------------------- + // Release the bitmap + //-------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(mapName); + } + Check_Fpu(); +} diff --git a/MUNGA_L4/L4LAMP.h b/MUNGA_L4/L4LAMP.h new file mode 100644 index 0000000..0e6c110 --- /dev/null +++ b/MUNGA_L4/L4LAMP.h @@ -0,0 +1,147 @@ +#pragma once + +class L4LampManager; +class L4Lamp; +class L4GraphicLamp; + +#include "..\munga\lamp.h" +#include "l4ctrl.h" + +//######################################################################### +//############################# L4LampManager ############################# +//######################################################################### +class L4LampManager: +public LampManager +{ + friend class L4Lamp; + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- +public: + L4LampManager(LBE4ControlsManager *controls_manager); + ~L4LampManager(); + + Logical + TestInstance() const; + + virtual void + Update(ModeMask current_mode_mask); + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- +protected: + void + AssertNewLampValue(int lamp_number, int lamp_value); + + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- +protected: + LBE4ControlsManager + *controlsManager; + int + *previousLampState; + Logical + *lampActiveFlag; +}; + +//######################################################################### +//################################ L4Lamp ################################# +//######################################################################### +class L4Lamp : + public Lamp +{ + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- +public: + enum + { + LampStateDim = Lamp::NextLampState, + NextLampState + }; + + L4Lamp( + LampID lamp_number, + ModeMask mode_mask, + L4LampManager *lamp_manager + ); + + ~L4Lamp(); + + Logical + TestInstance() const; + + void + SetAutomaticOperation(Logical automatic_flag = True); + +protected: + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- + void + Update(Logical force_notify_of_state_change = False); + void + NotifyOfStateChange(); + //---------------------------------------------------------------------- + // Public data + //---------------------------------------------------------------------- +public: + ControlsButton + automaticValue; // controls lampState if 'automatic' is true + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- +protected: + ControlsButton + previousAutomaticValue; + Logical + automatic; + int + alertValue; +}; + +//######################################################################### +//############################# L4GraphicLamp ############################# +//######################################################################### +class L4GraphicLamp : + public GraphicLamp +{ + //---------------------------------------------------------------------- + // Public methods + //---------------------------------------------------------------------- +public: + L4GraphicLamp( + LampID lamp_number, + ModeMask mode_mask, + GaugeRenderer *renderer, + int graphics_port_number, + int left, int bottom, + const char *bitmap_name, + int bg_color, int fg_color, + Logical opaque_flag = True + ); + + ~L4GraphicLamp(); + + Logical + TestInstance() const; + +protected: + //---------------------------------------------------------------------- + // Protected methods + //---------------------------------------------------------------------- + void + NotifyOfStateChange(); + //---------------------------------------------------------------------- + // Protected data + //---------------------------------------------------------------------- +protected: + Logical + opaque; + char + *mapName; + int + bgColor, + fgColor; +}; diff --git a/MUNGA_L4/L4MOUSE.cpp b/MUNGA_L4/L4MOUSE.cpp new file mode 100644 index 0000000..af59ab4 --- /dev/null +++ b/MUNGA_L4/L4MOUSE.cpp @@ -0,0 +1,191 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4mouse.h" + +#define MOUSEINT 0x33 + +// +//############################################################################ +// Creator - reset the driver and check for existence +// +//############################################################################ +// +Mouse::Mouse() +{ + /*STUBBED: RB 2/11/07 + Check_Pointer(this); + + // + //----------------------------------------------- + // Reset driver and read status + //----------------------------------------------- + // + __int16 _AX, _BX; + __asm + { + MOV AX, 0x00 + INT MOUSEINT + MOV _AX, AX + MOV _BX, BX + } + + // + //----------------------------------------------- + // AX will be zero if error, 0xFFFF if ok. + // BX is the number of buttons. + //----------------------------------------------- + // + if (_AX == 0xFFFF) + { + ButtonCount = _BX; + Errors = 0; + } + else + { + Errors = 1; + ButtonCount = 0; + } + Check_Fpu(); + */ + Errors = 0; +} + +Logical Mouse::TestInstance() const +{ + return True; +} + +// +//############################################################################ +// ReadCounters - return how many 'mickeys' the mouse has moved +// since the last call +//############################################################################ +// +void Mouse::ReadCounters(int *xp, int *yp) +{ + /* + Check(this); + Check_Pointer(xp); + Check_Pointer(yp); + + if (Errors) + { + *xp = 0; + *yp = 0; + } + else + { + // + //----------------------------------------------- + // Read motion counters + // RETURN: + // CX = UNSIGNED x counter, + // DX = UNSIGNED y counter. + // These must be converted to signed values. + //----------------------------------------------- + // + __int16 a, b; + __asm + { + MOV AX, 0xB + INT MOUSEINT + MOV a, CX + MOV b, DX + } + + if (a & 0x8000) + { + a |= (int)(~65535L); + } + if (b & 0x8000) + { + b |= (int)(~65535L); + } + + *xp = a; + *yp = b; + } + Check_Fpu(); + */ +} + +// +//############################################################################ +// ButtonPressed - return the number of times a given button was pressed +// since the last call +//############################################################################ +// +int Mouse::ButtonPressed(int buttonNum) +{ + /* + Check(this); + if (Errors) + { + return 0; + } + else + { + // + //----------------------------------------------- + // Read button press data + // RETURN: + // AX = current button states + // BX = number of times pressed since last call + //----------------------------------------------- + // + __int16 retVal; + __int16 _BX = buttonNum; + _asm + { + MOV AX, 0x05 + MOV BX, _BX + INT MOUSEINT + MOV retVal, BX + } + + return retVal; + } + */ + return 0; +} + +// +//############################################################################ +// ButtonReleased - return the number of times a given button was released +// since the last call +//############################################################################ +// +int Mouse::ButtonReleased(int buttonNum) +{ + /* + Check(this); + if (Errors) + { + return 0; + } + else + { + // + //----------------------------------------------- + // Read button press data + // RETURN: + // AX = current button states + // BX = number of times pressed since last call + //----------------------------------------------- + // + __int16 retVal; + __int16 _BX = buttonNum; + _asm + { + MOV AX, 0x06 + MOV BX, _BX + INT MOUSEINT + MOV retVal, BX + } + + return retVal; + } + */ + return 0; +} diff --git a/MUNGA_L4/L4MOUSE.h b/MUNGA_L4/L4MOUSE.h new file mode 100644 index 0000000..e48c824 --- /dev/null +++ b/MUNGA_L4/L4MOUSE.h @@ -0,0 +1,17 @@ +#pragma once + +#include "..\munga\style.h" + +class Mouse SIGNATURED +{ +public: + Mouse(); + ~Mouse() {} + void ReadCounters(int *xp, int *yp); + int ButtonPressed(int buttonNum); + int ButtonReleased(int buttonNum); + Logical TestInstance() const; + + int ButtonCount; // number of buttons on mouse + int Errors; // non-zero if bad things happened +}; \ No newline at end of file diff --git a/MUNGA_L4/L4MPPR.cpp b/MUNGA_L4/L4MPPR.cpp new file mode 100644 index 0000000..a4feac3 --- /dev/null +++ b/MUNGA_L4/L4MPPR.cpp @@ -0,0 +1,369 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4mppr.h" +#include "l4ctrl.h" +#include "l4keybd.h" +#include "..\munga\app.h" + +#define PEDAL_SCALE 2.0f + +//########################################################################## +//#################### CameraL4Mapper ####################### +//########################################################################## + +//############################################################################# +// Shared Data Support +// + +CameraL4Mapper::SharedData + CameraL4Mapper::DefaultData( + CameraL4Mapper::GetClassDerivations(), + CameraL4Mapper::MessageHandlers, + CameraL4Mapper::GetAttributeIndex(), + CameraL4Mapper::StateCount + ); + +Derivation* CameraL4Mapper::GetClassDerivations() +{ + static Derivation classDerivations(CameraControlsMapper::GetClassDerivations(), "CameraL4Mapper"); + return &classDerivations; +} + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + CameraL4Mapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(CameraL4Mapper, Keypress) +}; + +CameraL4Mapper::MessageHandlerSet + CameraL4Mapper::MessageHandlers( + ELEMENTS(CameraL4Mapper::MessageHandlerEntries), + CameraL4Mapper::MessageHandlerEntries, + CameraControlsMapper::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + CameraL4Mapper::KeypressMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + switch (message->dataContents) + { + case PCK_F1: + Tell("Aligning Joystick...\n"); + controls->BeginAlignJoystick(); + break; + case PCK_F2: + Tell("Joystick Aligned...\n"); + controls->EndAlignJoystick(); + break; + + case '>': + rightPedal = 1.0f; + break; + case '<': + leftPedal = 1.0f; + break; + case ' ': + leftPedal = rightPedal = 0.0f; + break; + + default: + CameraControlsMapper::KeypressMessageHandler(message); + break; + } +} + +//############################################################################# +// Model Support +// +void + CameraL4Mapper::InterpretControls(Scalar) +{ + // + //---------------------------------------- + // Sum the pedal inputs + //---------------------------------------- + // + pedalsPosition = rightPedal - leftPedal; + pedalsPosition *= PEDAL_SCALE; +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraL4Mapper::CameraL4Mapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data + ) + : CameraControlsMapper(owner, subsystem_ID, subsystem_resource, shared_data) +{ + SetPerformance(&CameraL4Mapper::InterpretControls); + + leftPedal = 0.0f; + rightPedal = 0.0f; + + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + controls + ->joystickGroup[LBE4ControlsManager::JoystickPhysical] + .Add(ModeManager::ModeAlwaysActive, &stickPosition, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickTrigger] + .Add(ModeManager::ModeAlwaysActive, &driveCamera, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickThumbHigh] + .Add(ModeManager::ModeAlwaysActive, &slideOrClamp, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft] + .Add( + ModeManager::ModeAlwaysActive, + this, + DecrementCameraMessageID, + this + ); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight] + .Add( + ModeManager::ModeAlwaysActive, + this, + IncrementCameraMessageID, + this + ); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickPinky] + .Add( + ModeManager::ModeAlwaysActive, + this, + DeleteCameraInstanceMessageID, + this + ); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickThumbLow] + .Add( + ModeManager::ModeAlwaysActive, + this, + CreateCameraInstanceMessageID, + this + ); + + controls + ->keyboardGroup[LBE4ControlsManager::KeyboardPC] + .Add( + ModeManager::ModeAlwaysActive, + this, + KeypressMessageID, + this + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraL4Mapper::~CameraL4Mapper() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraL4Mapper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//########################################################################## +//#################### CameraThrustmasterMapper ####################### +//########################################################################## + +//############################################################################# +// Shared Data Support +// + +CameraThrustmasterMapper::SharedData + CameraThrustmasterMapper::DefaultData( + CameraThrustmasterMapper::GetClassDerivations(), + CameraThrustmasterMapper::MessageHandlers, + CameraThrustmasterMapper::GetAttributeIndex(), + CameraThrustmasterMapper::StateCount + ); +Derivation* CameraThrustmasterMapper::GetClassDerivations() +{ static Derivation classDerivations(CameraL4Mapper::GetClassDerivations(), "CameraThrustmasterMapper"); + return &classDerivations; +} + + +//############################################################################# +// Model Support +// +void + CameraThrustmasterMapper::InterpretControls(Scalar time_slice) +{ + // + //---------------------------------------- + // Use the hat buttons to set the throttle + //---------------------------------------- + // + if (throttleUp > 0) + { + throttlePosition = 1.0f; + reverseThrust = 0; + } + else if (throttleDown > 0) + { + throttlePosition = 1.0f; + reverseThrust = 1; + } + else + { + throttlePosition = 0.0f; + reverseThrust = 0; + } + + CameraL4Mapper::InterpretControls(time_slice); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraThrustmasterMapper::CameraThrustmasterMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data + ) + : CameraL4Mapper(owner, subsystem_ID, subsystem_resource, shared_data) +{ + SetPerformance(&CameraThrustmasterMapper::InterpretControls); + + throttleUp = throttleDown = 0; + + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp] + .Add(ModeManager::ModeAlwaysActive, &throttleUp, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown] + .Add(ModeManager::ModeAlwaysActive, &throttleDown, this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraThrustmasterMapper::~CameraThrustmasterMapper() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraThrustmasterMapper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +//################################ RIOMapper ################################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +CameraRIOMapper::SharedData + CameraRIOMapper::DefaultData( + CameraRIOMapper::GetClassDerivations(), + CameraRIOMapper::MessageHandlers, + CameraRIOMapper::GetAttributeIndex(), + CameraRIOMapper::StateCount + ); + +Derivation* CameraRIOMapper::GetClassDerivations() +{ static Derivation classDerivations(CameraL4Mapper::GetClassDerivations(), "CameraRIOMapper"); + return &classDerivations; +} + + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraRIOMapper::CameraRIOMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + CameraL4Mapper(owner, subsystem_ID, subsystem_resource, shared_data) +{ + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + + // + //----------------- + // Throttle mapping + //----------------- + // + controls + ->scalarGroup[LBE4ControlsManager::ScalarThrottle] + .Add(ModeManager::ModeAlwaysActive, &throttlePosition, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonThrottle1] + .Add(ModeManager::ModeAlwaysActive, &reverseThrust, this); + + // + //-------------- + // Pedal mapping + //-------------- + // + controls + ->scalarGroup[LBE4ControlsManager::ScalarLeftPedal] + .Add(ModeManager::ModeAlwaysActive, &leftPedal, this); + + controls + ->scalarGroup[LBE4ControlsManager::ScalarRightPedal] + .Add(ModeManager::ModeAlwaysActive, &rightPedal, this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +CameraRIOMapper::~CameraRIOMapper() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraRIOMapper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/MUNGA_L4/L4MPPR.h b/MUNGA_L4/L4MPPR.h new file mode 100644 index 0000000..7d7b215 --- /dev/null +++ b/MUNGA_L4/L4MPPR.h @@ -0,0 +1,151 @@ +#pragma once + +#include "..\munga\controls.h" +#include "..\munga\cammppr.h" + +//########################################################################## +//#################### CameraL4Mapper ####################### +//########################################################################## +class CameraL4Mapper : + public CameraControlsMapper +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging Support +// +public: + void + KeypressMessageHandler(ReceiverDataMessageOf *message); + +protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (CameraL4Mapper::*Performance)(Scalar time_slice); + + void + InterpretControls(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + CameraL4Mapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); + ~CameraL4Mapper(); + + Logical + TestInstance() const; + +protected: + ControlsScalar + leftPedal, + rightPedal; +}; + +//########################################################################## +//#################### CameraThrustmasterMapper ####################### +//########################################################################## + +class CameraThrustmasterMapper : + public CameraL4Mapper +{ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (CameraThrustmasterMapper::*Performance)(Scalar time_slice); + + void + InterpretControls(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + CameraThrustmasterMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); + ~CameraThrustmasterMapper(); + + Logical + TestInstance() const; + +protected: + ControlsButton + throttleUp, + throttleDown; +}; + +//########################################################################## +//########################### CameraRIOMapper ######################## +//########################################################################## + +class CameraRIOMapper : + public CameraL4Mapper +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + CameraRIOMapper( + CameraShip *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); + ~CameraRIOMapper(); + + Logical + TestInstance() const; +}; diff --git a/MUNGA_L4/L4NET.CPP b/MUNGA_L4/L4NET.CPP new file mode 100644 index 0000000..cc460c5 --- /dev/null +++ b/MUNGA_L4/L4NET.CPP @@ -0,0 +1,3446 @@ +//===========================================================================// +// File: l4net.cpp // +// Project: MUNGA Brick: Network Manager // +// Contents: Interface specification for network brick // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/02/95 GAC Initial coding. // +// 04/08/95 GAC Netnow Removed, TCP/NetNub support added // +// NOTE: old netnow code is saved in L4NetNow.* // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#include "mungal4.h" +#pragma hdrstop + +#include "l4app.h" +#include "l4host.h" +#include "l4net.h" +#include "..\munga\mission.h" +#include "..\munga\notation.h" +//#include + + +#if defined(TRACE_SEND_PACKET) + static BitTrace Send_Packet("Send Packet"); + #define SET_SEND_PACKET() Send_Packet.Set() + #define CLEAR_SEND_PACKET() Send_Packet.Clear() +#else + #define SET_SEND_PACKET() + #define CLEAR_SEND_PACKET() +#endif + +#if defined(TRACE_CHECK_BUFFERS) + static BitTrace Check_Buffers("Check Buffers"); + #define SET_CHECK_BUFFERS() Check_Buffers.Set() + #define CLEAR_CHECK_BUFFERS() Check_Buffers.Clear() +#else + #define SET_CHECK_BUFFERS() + #define CLEAR_CHECK_BUFFERS() +#endif + +#if defined(TRACE_CALL_NETNUB) + static BitTrace Call_Netnub("Call Netnub"); + #define SET_CALL_NETNUB() Call_Netnub.Set() + #define CLEAR_CALL_NETNUB() Call_Netnub.Clear() +#else + #define SET_CALL_NETNUB() + #define CLEAR_CALL_NETNUB() +#endif + +#if defined(TRACE_LOST_DATA) + static BitTrace Lost_Data("Lost Data"); + #define SET_LOST_DATA() Lost_Data.Set() + #define CLEAR_LOST_DATA() Lost_Data.Clear() +#else + #define SET_LOST_DATA() + #define CLEAR_LOST_DATA() +#endif + +#define BATCHED_TRANSMIT True // true sends broadcast messages with a single call to netnub +#define BATCHED_RECEIVE True // true receives from all streams with a single call to netnub +#define REPORT_LOST_DATA False // Print a message if data is lost (may be toxic) + +#if !defined(MESSAGE_BUFFERING) + #define MESSAGE_BUFFERING True // true uses munga level buffering for dropped packets +#endif + +#define CONSOLE_NET_PORT 1501 // Port number the console will connect on +#define GAME_NET_PORT 1502 // Port number the game will connect on + +char GlobalEggFileName[80]; // NASTY HACK !!! should suffice till we get console up though + +//struct RMREG //real mode registers structure +//{ +//unsigned long +// edi, +// esi, +// ebp, +// reserved,//0 +// ebx, +// edx, +// ecx, +// eax; +//unsigned short +// flags, //0 +// es, +// ds, +// fs, //0 +// gs, //0 +// ip, +// cs, +// sp, +// ss; +//}; + +// +// !!!! this stuff is also nasty but is currently required to be global for the +// assembly language stuff to work properly. +// +//Netcom_Ptr +// Net_Common_Ptr = NULL; +// +//unsigned short +// *Buffer_Length_Ptr; // Where the network common buffer length field is located +// +//short +// *Function_Ptr, // Where the network common function field is located +// offs, // offset of Real Mode Netcom struct +// baseadr, // segment of Real Mode Netcom struct +// intno, +// RMFunction_Off, // Offset of function field for real mode structure +// RMBuffer_Length_Off; // Offset of buffer length field for real mode structure +//long +// RMverno; // Real mode version number +//// +//// !!!! These are the assembyly code functions we will be calling +//// +//extern "C" +//{ +// void mapRMBuff(void); //get selector for rm buffer +// void getRMNumbers(void); //get interr and version numbers from rm buffer +// void getRMBuff(void); //copy block from rm buffer +// void setRMBuff(void); //copy block to rm buffer +//}; + +//############################################################################# +// Shared Data Support +// +L4NetworkManager::SharedData + L4NetworkManager::DefaultData( + L4NetworkManager::GetClassDerivations(), + L4NetworkManager::GetMessageHandlers() + ); + +Derivation* L4NetworkManager::GetClassDerivations() +{ + static Derivation classDerivations(NetworkManager::GetClassDerivations(), "L4NetworkManager"); + return &classDerivations; +} + +//############################################################################# +// Messaging support +// +const Receiver::HandlerEntry + L4NetworkManager::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(L4NetworkManager,ReceiveEggFile), + MESSAGE_ENTRY(L4NetworkManager,AcknowledgeEggFile), + MESSAGE_ENTRY(L4NetworkManager,HostConnected), + MESSAGE_ENTRY(L4NetworkManager,HostDisconnected) +}; + +Receiver::MessageHandlerSet& L4NetworkManager::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(L4NetworkManager::MessageHandlerEntries), L4NetworkManager::MessageHandlerEntries, NetworkManager::GetMessageHandlers()); + return messageHandlers; +} + +// +//############################################################################# +// Code for the network manager class +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the L4NetworkManager +// +//WinSock support :ADB 01/06/07 +L4NetworkManager::L4NetworkManager(): + NetworkManager(DefaultData), + messageBuffer(this) +{ + unsigned long + network_common_flat_address; + + network_common_flat_address = + ((L4Application *)application)->GetNetworkCommonFlatAddress(); + lastHostIteratorPosition = 0; + nextOpenHostID = FirstLegalHostID+1; // Reserve first legal id for console + currentNetworkState = NormalState; + myConsoleHost = NULL; + eggAcknowledged = False; + networkStartupMode = SlaveMode; + numberOfMungaHostsConnected = 0; + numberOfConsoleHostsConnected = 0; + remoteHostCount = 0x7FFFFFFF; + wsaData = new WSADATA; + + // + // If there is no net common, set things up for single user mode + // + if(network_common_flat_address == 0) + { + //Net_Common_Ptr = NULL; + wsaData = NULL; + + // + //--------------------------------------------------------------------- + // Retrieve the egg as specified on the command line, and send it as an + // egg message + //--------------------------------------------------------------------- + // + const char* egg_name = l4_application->GetEggNotationFileName(); + if (!egg_name || !strlen(egg_name)) + { + DEBUG_STREAM << "ERROR: No source exists for egg!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + networkEggNotationFile = new NotationFile(egg_name); + Register_Object(networkEggNotationFile); + networkEggNotationFile->WriteFile("last.egg"); + currentNetworkState = NormalState; + + ReceiveEggFileMessage egg_message(-1, 10, "local egg", 10); + application->Post(DefaultEventPriority, this, &egg_message); + return; + } + + // + // Setup the local netcom structure and some pointers to things inside it + // + //Net_Common_Ptr = new Netcom; + //Register_Pointer(Net_Common_Ptr); + //Function_Ptr = &Net_Common_Ptr->Function; + //Buffer_Length_Ptr = &Net_Common_Ptr->Buffer_Length; + + int iResult = WSAStartup(MAKEWORD(2,2), wsaData); + if(iResult != NO_ERROR) + { + DEBUG_STREAM << "ERROR: WSAStartup() failed with " << iResult << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + } + consoleListenerSocket = NULL; + gameListenerSocket = NULL; + + // + // Setup the global pointers that the netnub real/protected mode interface + // requires to work. + // + //offs = (short)(network_common_flat_address & 0x0000000f); + //baseadr = (short)(network_common_flat_address>>4); + //mapRMBuff(); //get selector for baseadr + //RMFunction_Off = (short)(offs + // + sizeof(Net_Common_Ptr->Version_Number) + // + sizeof(Net_Common_Ptr->Interrupt_Number)); + //RMBuffer_Length_Off = (short)(RMFunction_Off + // + sizeof(Net_Common_Ptr->Function) + // + sizeof(Net_Common_Ptr->Status)); + + //getRMNumbers(); // get Interrupt_Number , Version_Number + //intno = Net_Common_Ptr->Interrupt_Number; + //RMverno = Net_Common_Ptr->Version_Number; + + // + // Check for right network common number + //// + //if(RMverno != NETCOM_VERSION) + //{ + // DEBUG_STREAM << "Netnub version " << RMverno + // << ", code version " << NETCOM_VERSION << endl; + // Fail("MUNGA was compiled with an old version of netnub.h"); + //} + + // + // Get my network address from the netnub (also verify's we are connected) + // + addresses = GetMyAddress(); + if(addresses == NULL) + { + DEBUG_STREAM<<"ERROR: GetMyAddress() failed!\n"; + WSACleanup(); + Fail("Unable to initialize the network"); + } + + // + // Force us into reliable mode + // + Mode(NetworkManager::ReliableMode); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::MakeNotationFileEgg This routine creates the console remote +// host +// +//WinSock support :ADB 01/06/07 +void L4NetworkManager::CreateConsoleHost() +{ + //unsigned long console_socket; + + // + // Die if there is no network common around + // + if (wsaData == NULL) + { + return; + } + + unsigned short networkPort = (unsigned short)((L4Application *)application)->GetNetworkCommonFlatAddress(); + + // + // Initialize a bunch of stuff to sane states + // + nextOpenHostID = FirstLegalHostID+1; // Reserve first legal id for console + networkStartupMode = SlaveMode; // We're a slave, (not a simulated console) + currentNetworkState = ConsoleOnly; // Only accept messages from the console + numberOfConsoleHostsConnected = 0; // Shouldn't be any consoles yet + numberOfMungaHostsConnected = 0; // No game machines either + + // + // Post a listen for a console with an unknown network address + // this will return a stream that the console will eventually be on + // + //WinSock support :ADB 01/06/07 + //console_socket = OpenConnection( + // NETNUB_TCP_LISTEN, + // CONSOLE_NET_PORT, // Local port + // 0, // Remote port (don't care in this case) + // 0); // Network address (don't care in this case) + consoleListenerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(consoleListenerSocket == INVALID_SOCKET) + { + DEBUG_STREAM << "ERROR: Could not create console listener socket; socket() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return; + } + sockaddr_in localEndpoint; + memset(&localEndpoint, 0, sizeof(localEndpoint)); + localEndpoint.sin_family = AF_INET; + localEndpoint.sin_port = htons(networkPort); + localEndpoint.sin_addr.S_un.S_addr = INADDR_ANY; + if(bind(consoleListenerSocket, (sockaddr*)&localEndpoint, sizeof(localEndpoint))) + { + DEBUG_STREAM << "ERROR: Could not bind console listener socket; bind() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return; + } + if(listen(consoleListenerSocket, 1)) + { + DEBUG_STREAM << "ERROR: Could not listen on console listener socket; listen() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return; + } + //set to non blocking + unsigned long enable = 1; + if(ioctlsocket(consoleListenerSocket, FIONBIO, &enable)) + { + DEBUG_STREAM << "ERROR: Could not set console listener socket to nonblocking; ioctlsocket() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return; + } + + // + // Register the console host with the host manager, this will insure it gets + // polled by CheckBuffers for connection. On connect we'll get a message + // routed to the network manager. Note that this host has an unspecified + // net address since we won't know it till the console connects. This + // must be the ONLY host we are listening for or things will fail!!! + // + SOCKADDR_IN address; + address.sin_family = AF_INET; + address.sin_addr.S_un.S_addr = NullNetworkAddress; + myConsoleHost = new L4Host( + FirstLegalHostID, + ConsoleHostType, + &address, // Don't know the net address till it connects. + INVALID_SOCKET, + "Console"); + + // + // Do the usual stuff to the host, register it, and have the host manager adopt it + // + Register_Object(myConsoleHost); + myConsoleHost->SetConnectStatus(L4Host::ListeningConnectionStatus); + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptRemoteHost(myConsoleHost); + networkEggNotationFile = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::LoadMission This routine is called when a mission starts to +// allow the network management system to do stuff (potentially establishing +// communications with all the participants and such like) +// +void + L4NetworkManager::StartConnecting(Mission *mission) +{ + int listen; // True if we should listen, false for connect + //WinSock support :ADB 01/06/07 + //unsigned long + SOCKET socket_ptr; // temporary place to store the socket for a host + SOCKADDR_IN net_address; // temporary place to store resolved net address + net_address.sin_family = AF_INET; + L4Host *my_l4host; + // the game port is the console listening port + 1 + unsigned short localGamePort = (unsigned short)((L4Application *)application)->GetNetworkCommonFlatAddress() + 1; + + // + // This should be entered with no network connections to other game hosts up, + // so we initialize this count to zero. + // + numberOfMungaHostsConnected = 0; + + // + // Create the host iterator for the mission egg + // + Mission::HostIterator mission_host_iterator(mission); + MissionHostData *mission_host_data; + + // + // If there is no net common, set things up for single user mode + // + //WinSock support :ADB 01/06/07 + //if (Net_Common_Ptr == NULL) + if(wsaData == NULL) + { + // + // Make the local host for single user testing, we give the host ID#1 + // and assign the first symbolic name in the egg to it. + // + mission_host_data = mission_host_iterator.ReadAndNext(); + Check(mission_host_data); + + SOCKADDR_IN address; + address.sin_family = AF_INET; + address.sin_family = NullNetworkAddress; + my_l4host = new L4Host( + 1, // Host ID + mission_host_data->GetHostType(), // Host Type + &address, // Net Address + INVALID_SOCKET, // Socket address + mission_host_data->GetAddressString()); + Register_Object(my_l4host); + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptLocalHost(my_l4host); + + // + //-------------------------------------------------------------------- + // Now, since this host creator is for stand-alone mode, send the load + // mission message to the application + //-------------------------------------------------------------------- + // + Check(application); + Application::Message + load_message( + Application::LoadMissionMessageID, + sizeof(Application::Message) + ); + application->Post(DefaultEventPriority, application, &load_message); + return; + } + + // + // Iterate through all the host addresses in the egg and create all the host + // structures, note that there MUST be an entry in the egg for us. + // + listen = False; + remoteHostCount = 0; + int bufferSize = sizeof(SOCKADDR_IN); + while ((mission_host_data = mission_host_iterator.ReadAndNext()) != NULL) + { + Check(mission_host_data); + + // + // Try to resolve this address to an IP address + // + CString host_name(mission_host_data->GetAddressString()); + //WinSock support :ADB 01/06/07 + //VERIFY: are these IP addresses? + //net_address = ResolveAddress(host_name); + //net_address = inet_addr((char *)host_name); + WSAStringToAddressA((LPSTR)host_name, AF_INET, NULL, (LPSOCKADDR)&net_address, &bufferSize); + if (net_address.sin_port == 0) + net_address.sin_port = htons(localGamePort); + + // + // See if this host is us or someone else + // + //WinSock support :ADB 01/06/07 + bool addressFound = false; + for(int i=0; iGetHostType(), + //WinSock support :ADB 01/06/07 + //address, + &net_address, + INVALID_SOCKET, + host_name); + Register_Object(my_l4host); + listen = True; + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptLocalHost(my_l4host); + } + else + { + // + // See what we should do to connect to this remote host (open or listen) + // + remoteHostCount++; + if(listen) + { + //WinSock support :ADB 01/06/07 + socket_ptr = OpenConnection(NETNUB_TCP_LISTEN, localGamePort, 0, net_address.sin_addr.S_un.S_addr); + } + else + socket_ptr = OpenConnection(NETNUB_TCP_OPEN, localGamePort, ntohs(net_address.sin_port), net_address.sin_addr.S_un.S_addr); + + if (!listen && socket_ptr == INVALID_SOCKET) + DEBUG_STREAM << "Could not open connection to " << host_name << ".\n" << std::flush; + + // + // Now we can create the remote host and get the application to adopt + // it + // + my_l4host = new L4Host( + nextOpenHostID, + mission_host_data->GetHostType(), + &net_address, + socket_ptr, + host_name); + Register_Object(my_l4host); + my_l4host->SetConnectStatus( + (listen) + ? L4Host::ListeningConnectionStatus + : L4Host::OpeningConnectionStatus + ); + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptRemoteHost(my_l4host); + } + nextOpenHostID++; + } + + // + // All the hosts are created, the connects/listens done. + // + if(networkStartupMode == SlaveMode) + { + // + // We are a slave (got our egg from the network) so we will + // acknowledge the egg now and wait for the connects to finish + // + #if defined(LAB_ONLY) + DEBUG_STREAM << "Sending egg Acknowledgement\n" << flush; + #endif + AcknowledgeEggFileMessage myAcknowledgeEgg; + Send( + &myAcknowledgeEgg, + NetworkClient::NetworkManagerClientID, + myConsoleHost->GetHostID() + ); + + // + //----------------------------------------------------------------------- + // Send the load mission message to the application... if an egg was sent + //----------------------------------------------------------------------- + // + if (numberOfMungaHostsConnected >= remoteHostCount) + { + Check(application); + Application::Message + load_message( + Application::LoadMissionMessageID, + sizeof(Application::Message) + ); + application->Post(DefaultEventPriority, application, &load_message); + } + } + +// Console simulator that would be here has been moved to end of file if needed + + else + { + Fail("host is in an illegal startup mode\n"); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Shutdown This routine is called when a mission ends to +// allow the network management system to do stuff (like disconnecting network +// connections between pods and so on) +// +Logical + L4NetworkManager::Shutdown() +{ + Host + *base_host; + L4Host + *my_l4host; + unsigned long + network_common_flat_address; + + network_common_flat_address = l4_application->GetNetworkCommonFlatAddress(); + + if (networkEggNotationFile) + { + Unregister_Object(networkEggNotationFile); + delete networkEggNotationFile; + networkEggNotationFile = NULL; + } + + // + // If there is no net common, all we do is deregister the local host and return + // + if(network_common_flat_address == 0) + { + // + // Deregister local host + // + base_host = application->GetHostManager()->OrphanLocalHost(); + my_l4host = Cast_Object(L4Host*, base_host); + Check(my_l4host); + Unregister_Object(my_l4host); + delete my_l4host; + return True; + } + + // + // If we get here there was a network setup, we must drop all connections + // deregister all the remote hosts and then deregister the local host. + // Start by closing all connections. + // + Check(application); + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + HostManager::RemoteHostIterator remote_hosts(host_mgr); + while ((base_host = remote_hosts.ReadAndNext()) != NULL) + { + my_l4host = Cast_Object(L4Host*, base_host); + Check(my_l4host); + + // + //------------------------------ + // Don't delete the console host + //------------------------------ + // + if (my_l4host->GetHostType() == ConsoleHostType) + { + continue; + } + + // + // Don't do a close if the system says we're not connected (means close was + // allready done by disconnect handler + // + if(my_l4host->GetConnectStatus() != Host::NoNetworkConnectionStatus) + { + CloseConnection(my_l4host->GetNetworkSocket()); + } + // deregister this host with the host manager + host_mgr->OrphanRemoteHost(my_l4host); + Unregister_Object(my_l4host); + delete my_l4host; + } + + // + // Deregister local host + // + base_host = host_mgr->OrphanLocalHost(); + if (base_host) + { + my_l4host = Cast_Object(L4Host*, base_host); + Check(my_l4host); + Unregister_Object(my_l4host); + delete my_l4host; + } + + // + // Reinitialize this in case we start another game + // + remoteHostCount = 0x7FFFFFFF; + nextOpenHostID = FirstLegalHostID+1; // Reserve first legal id for console + networkStartupMode = SlaveMode; // We're a slave, (not a simulated console) + currentNetworkState = ConsoleOnly; // Only accept messages from the console + numberOfConsoleHostsConnected = 0; // Shouldn't be any consoles yet + numberOfMungaHostsConnected = 0; // No game machines either + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the L4NetworkManager +// +L4NetworkManager::~L4NetworkManager() +{ + //WinSock support :ADB 01/06/07 + //if(Net_Common_Ptr) + if(wsaData) + { + Check(application); + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + HostManager::RemoteHostIterator remote_hosts(host_mgr); + Host *base_host; + while ((base_host = remote_hosts.ReadAndNext()) != NULL) + { + L4Host *my_l4host = Cast_Object(L4Host*, base_host); + Check(my_l4host); + + // + // Don't do a close if the system says we're not connected (means close was + // allready done by disconnect handler + // + if(my_l4host->GetConnectStatus() != Host::NoNetworkConnectionStatus) + { + CloseConnection(my_l4host->GetNetworkSocket()); + } + // deregister this host with the host manager + host_mgr->OrphanRemoteHost(my_l4host); + Unregister_Object(my_l4host); + delete my_l4host; + } + + WSACleanup(); + delete wsaData; + wsaData = NULL; + //Unregister_Pointer(Net_Common_Ptr); + //delete Net_Common_Ptr; + //Net_Common_Ptr = NULL; + } + + if(addresses) + delete[] addresses; + addresses = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::ReceiveEggFileMessageHandler +// +void + L4NetworkManager::ReceiveEggFileMessageHandler( + ReceiveEggFileMessage* EggMessage + ) +{ + #if defined(LAB_ONLY) + DEBUG_STREAM << "Received Egg message #" << EggMessage->sequenceNumber + << endl; + #endif + + // + // An egg sequence number of -1 means that the egg is posted locally, and + // should just call create mission + // + if (EggMessage->sequenceNumber == -1) + { + application->CreateMission(networkEggNotationFile); + return; + } + + if (EggMessage->sequenceNumber == 0) + { + // + // Make a buffer + // + eggTempBuffer = new char[EggMessage->notationFileLength]; + Register_Pointer(eggTempBuffer); + eggTempNext = 0; + } + + // + // Write the egg data into the buffer + // + memcpy( + (eggTempBuffer+eggTempNext), + EggMessage->notationData, + EggMessage->thisMessageLength + ); + eggTempNext += EggMessage->thisMessageLength; + + // + // If we don't have all the data, return and wait for more + // + if(eggTempNext < EggMessage->notationFileLength) + { + return; + } + + // + // We've got all the data, make the notation file + // + networkEggNotationFile = new NotationFile(); + Register_Object(networkEggNotationFile); + networkEggNotationFile->ReadText(eggTempBuffer, eggTempNext); + #if defined(LAB_ONLY) + DEBUG_STREAM << "Created egg\n"; + #endif + networkEggNotationFile->WriteFile("last.egg"); + currentNetworkState = NormalState; + + // + // Now turn the notation file into a mission + // + application->CreateMission(networkEggNotationFile); + + // + // Get rid of the ram buffer now that we're done with it + // + Unregister_Pointer(eggTempBuffer); + delete eggTempBuffer; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::AcknowledgeEggFileMessageHandler +// +void + L4NetworkManager::AcknowledgeEggFileMessageHandler( + AcknowledgeEggFileMessage* ) +{ + #if defined(LAB_ONLY) + DEBUG_STREAM << "\nReceived egg acknowledged message\n"; + #endif + eggAcknowledged = True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::HostConnectedMessageHandler +// +void + L4NetworkManager::HostConnectedMessageHandler( + HostConnectedMessage* HostConnected + ) +{ + // + // Get a pointer to the L4 host + // + Check(application); + Check(application->GetHostManager()); + Host* connected_host = + application->GetHostManager()->GetRemoteHost(HostConnected->hostID); + L4Host* l4connected_host = Cast_Object(L4Host*, connected_host); + Check(l4connected_host); + + // + // Set the host connection status to on line and increment the + // counter of hosts online. + // + l4connected_host->SetConnectStatus(L4Host::OnLineConnectionStatus); + switch(l4connected_host->GetHostType()) + { + case GameMachineHostType: + numberOfMungaHostsConnected++; + DEBUG_STREAM << "Connected to GameMachineHost at "; + break; + case CameraShipHostType: + numberOfMungaHostsConnected++; + DEBUG_STREAM << "Connected to CameraShipHost at "; + break; + case MissionReviewHostType: + numberOfMungaHostsConnected++; + DEBUG_STREAM << "Connected to MissionReviewHost at "; + break; + case ConsoleHostType: + numberOfConsoleHostsConnected++; + DEBUG_STREAM << "Connected to ConsoleHost at "; + break; + default: + Fail("L4NetworkManager::HostConnectedMessageHandler - unknown host type"); + break; + } + + // commenting out because Verify doesn't do anything anymore --RB 10/28/08 + //// + //// Cross check the network address with the one in the host (just in case) + //// + //Verify( + // l4connected_host->GetNetworkAddress() == HostConnected->networkAddress + //); + + char addressString[44]; + DWORD bufferSize = sizeof(addressString); + WSAAddressToStringA((LPSOCKADDR)&HostConnected->networkAddress, sizeof(SOCKADDR_IN), NULL, addressString, &bufferSize); + DEBUG_STREAM << addressString << std::endl << std::flush; + + if (numberOfMungaHostsConnected >= remoteHostCount) + { + DEBUG_STREAM << "All connections completed!\n" << std::flush; + Marker("MUNGA MARKER--All connections completed!\n"); + + // + //-------------------------------------------------------------------- + // Now, since this host creator is for stand-alone mode, send the load + // mission message to the application + //-------------------------------------------------------------------- + // + Check(application); + Application::Message + load_message( + Application::LoadMissionMessageID, + sizeof(Application::Message) + ); + application->Post(DefaultEventPriority, application, &load_message); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::HostDisconnectedMessageHandler +// This message should eventually be generated in CheckBuffers, right now it +// is actually sent over the network and is assumed only to be sent by the +// console just prior to it disconnecting. It clues us do locally close +// and destroy the console host so the game will start normally even if the +// console isn't around. +// +void L4NetworkManager::HostDisconnectedMessageHandler(HostDisconnectedMessage* HostDisconnected) +{ + // + // Get a pointer to the L4 host + // + Check(application->GetHostManager()); + Host* connected_host = application->GetHostManager()->GetRemoteHost(HostDisconnected->hostID); + L4Host* l4connected_host = Cast_Object(L4Host*, connected_host); + Check(l4connected_host); + // + // Set the host connection status to off line, get the network address so we + // can announce it later, then close the connection. + // + l4connected_host->SetConnectStatus(L4Host::NoNetworkConnectionStatus); + SOCKADDR_IN temp_net_address = *l4connected_host->GetNetworkAddress(); + CloseConnection(HostDisconnected->streamPointer); + // + // See what type of host it was that disconnected + // + switch(l4connected_host->GetHostType()) + { + case GameMachineHostType: + numberOfMungaHostsConnected--; + DEBUG_STREAM<<"\nDisconnected from GameMachineHost at "; + break; + case CameraShipHostType: + numberOfMungaHostsConnected--; + DEBUG_STREAM<<"\nDisconnected from CameraShipHost at "; + break; + case MissionReviewHostType: + numberOfMungaHostsConnected--; + DEBUG_STREAM<<"\nDisconnected from MissionReviewHost at "; + break; + case ConsoleHostType: + { + // + // Knock down the number of consoles online + // + numberOfConsoleHostsConnected--; + DEBUG_STREAM<<"\nDisconnected from ConsoleHost at "; + // + // Post a listen for a console so it can reconnect if it wants to. + // + shutdown(gameListenerSocket, SD_BOTH); + closesocket(gameListenerSocket); + gameListenerSocket = NULL; + //unsigned long console_socket = OpenConnection( + // NETNUB_TCP_LISTEN, + // ((L4Application *)application)->GetNetworkCommonFlatAddress(), // Local port + // 0, // Remote port (don't care in this case) + // 0); // Network address (don't care in this case) + // + // Destroy the console host and recreate it, this resets all the + // internal buffers and pointers so check_buffers won't go crazy + // + application->GetHostManager()->OrphanRemoteHost(l4connected_host); + Unregister_Object(l4connected_host); + delete l4connected_host; +#if 1 + CreateConsoleHost(); + /*SOCKADDR_IN address; + address.sin_family = AF_INET; + address.sin_family = NullNetworkAddress; + l4connected_host = new L4Host( + FirstLegalHostID, + ConsoleHostType, + &address, + console_socket, + "Console"); + Register_Object(l4connected_host); + l4connected_host->SetConnectStatus(L4Host::ListeningConnectionStatus); + application->GetHostManager()->AdoptRemoteHost(l4connected_host); + myConsoleHost = l4connected_host;*/ +#else + myConsoleHost = 0; +#endif + break; + } + default: + Fail("L4NetworkManager::HostDisconnectedMessageHandler - unknown host type"); + break; + } + + char addressString[44]; + DWORD bufferSize = sizeof(addressString); + WSAAddressToStringA((LPSOCKADDR)&temp_net_address, sizeof(SOCKADDR_IN), NULL, addressString, &bufferSize); + DEBUG_STREAM << addressString << "\n" << std::flush; +} + +#if MESSAGE_BUFFERING +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Send +// +void + L4NetworkManager::Send( + Message *message, + ClientID client_ID, + HostID host_ID + ) +{ + SET_SEND_PACKET(); + Check(this); + Check(message); + + // + //-------------------------------------------------------------------------- + // If the message buffer is not empty then add this new message into the + // buffer. Attempt to send a message. + //-------------------------------------------------------------------------- + // + if (!messageBuffer.IsEmpty()) + { + messageBuffer.AddSendRequest(host_ID, client_ID, message); + messageBuffer.AttemptToSend(); + } + + // + //-------------------------------------------------------------------------- + // The message buffer is empty so attempt to send the message. + //-------------------------------------------------------------------------- + // + else if (!SendMessageToNetnub(message, client_ID, host_ID)) + { + // + // Message was dropped, add this new message into the buffer + // + messageBuffer.AddSendRequest(host_ID, client_ID, message); + } + CLEAR_SEND_PACKET(); +} +#else +//WinSock support :ADB 01/06/07 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Send Handles sending a message to a specific network address +// which can NOT be us. +// +void L4NetworkManager::Send( + Message *message, + ClientID client, + HostID host_ID) +{ + int packet_size; + Host *local_host; + Host *base_host; + L4Host *l4host; + //SendPacketRequestPtr send_packet_request; // Format of the request we send to the NetNub + //SendPacketReturnPtr send_packet_return; + HostManager *our_host_manager; + NetworkPacket *my_temp_packet; // pointer to a place to build a network message + // + // Mark entry to the routine with an analysis call + // + SET_SEND_PACKET(); + // + // Check whatever incoming data needs checking, get a pointer to the host + // we are going to send to and make sure that host is online. + // + Check_Pointer(message); + Check(application); + our_host_manager = application->GetHostManager(); + Check(our_host_manager); + base_host = our_host_manager->GetRemoteHost(host_ID); + l4host = Cast_Object(L4Host*, base_host); + if(l4host->GetConnectStatus() != L4Host::OnLineConnectionStatus) + { + CLEAR_SEND_PACKET(); + return; + } + Verify(l4host->GetConnectStatus() == L4Host::OnLineConnectionStatus); + // + // figure out where to put the packet we're assembling + // + //send_packet_request = (SendPacketRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //send_packet_return = (SendPacketReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //my_temp_packet = (NetworkPacket*)send_packet_request->Send_Data; + // + // Build a MUNGA network packet in the netnub common block + // + if((false) || (message->messageLength < 8) || (false)) + //if((message->messageLength > MAX_SEND_DATA_SIZE) || (message->messageLength < 8) || (message->messageLength+sizeof(NetworkPacketHeader) > MAX_SEND_DATA_SIZE)) + { + char addressString[44]; + DWORD bufferSize = sizeof(addressString); + WSAAddressToStringA((LPSOCKADDR)l4host->GetNetworkAddress(), sizeof(SOCKADDR_IN), NULL, addressString, &bufferSize); + DEBUG_STREAM << addressString << " Requested to send a " << message->messageLength << " size packet\n" << std::flush; + Fail("Illegal transmit size\n"); + } + //Verify(message->messageLength + sizeof(NetworkPacketHeader) <= MAX_SEND_DATA_SIZE); + Verify(message->messageLength >= 8); + my_temp_packet = (NetworkPacket*)malloc(message->messageLength + sizeof(NetworkPacketHeader)); + memcpy(&my_temp_packet->messageData, message, message->messageLength); + my_temp_packet->clientID = client; + my_temp_packet->gameID = gameID; + my_temp_packet->timeStamp = Now(); + + // + // If the local host doesn't exist yet, we send back zero + // this lets the console get status before the local host is actually created + // + local_host = our_host_manager->GetLocalHost(); + if(local_host == NULL) + { + my_temp_packet->fromHost = 0; + } + else + { + Check(local_host); + my_temp_packet->fromHost = local_host->GetHostID(); + } + packet_size = message->messageLength + sizeof(NetworkPacketHeader); + // + // Fill in the NetNub common block with the rest of the data it needs for the call + // + //Net_Common_Ptr->Function = NETNUB_SEND_PACKET; + //Net_Common_Ptr->Buffer_Length = (short)SEND_BUFFER_SIZE(packet_size); + //send_packet_request->Socket_Ptr = l4host->GetNetworkSocket(); + //NetNub::SendCommand(); + send(l4host->GetNetworkSocket(), (char *)my_temp_packet, packet_size, 0); + free(my_temp_packet); + // Check for errors and abort if there were any + //#if defined(TRACE_SEND_BUFFER) + //l4host->sendBufferTrace->TakeSnapshot(send_packet_return->Send_Buffer_Used); + //#endif + //switch(Net_Common_Ptr->Status) + //{ + // case NETNUB_OK: + // break; + // case NETNUB_DATA_DUMPED: + // { + // SET_LOST_DATA(); + // #if REPORT_LOST_DATA + // unsigned long temp_net_address; + // temp_net_address = l4host->GetNetworkAddress(); + // DEBUG_STREAM<<"Data lost to "; + // DEBUG_STREAM<<((temp_net_address>>24) & 0xff)<<"."<<((temp_net_address>>16) & 0xff)<<"."; + // DEBUG_STREAM<<((temp_net_address>>8) & 0xff)<<"."<<(temp_net_address & 0xff)<<"\n"; + // DEBUG_STREAM<GetHostID(), + // l4host->GetNetworkSocket()); + // NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + // Check(client); + // client->ReceiveNetworkPacket(NULL, &myHostDisconnected); + // break; + // } + // default: + // { + // unsigned long temp_net_address; + // temp_net_address = l4host->GetNetworkAddress(); + // DEBUG_STREAM<<"Error "<Status<<" on "; + // DEBUG_STREAM<<((temp_net_address>>24) & 0xff)<<"."<<((temp_net_address>>16) & 0xff)<<"."; + // DEBUG_STREAM<<((temp_net_address>>8) & 0xff)<<"."<<(temp_net_address & 0xff)<<"\n"; + // DEBUG_STREAM<GetHostManager(); + Check(host_manager); + + receiving_host = Cast_Object(L4Host*, host_manager->GetRemoteHost(host_ID)); + if (receiving_host->GetConnectStatus() != L4Host::OnLineConnectionStatus) + { + return True; + } + Verify(receiving_host->GetConnectStatus() == L4Host::OnLineConnectionStatus); + + // + //-------------------------------------------------------------------------- + // Get the local host ID. If the local host doesn't exist yet, we use zero, + // this lets the console get status before the local host is actually + // created. + //-------------------------------------------------------------------------- + // + Host *local_host; + HostID local_host_ID; + + if((local_host = host_manager->GetLocalHost()) == NULL) + { + local_host_ID = 0; + } + else + { + Check(local_host); + local_host_ID = local_host->GetHostID(); + } + + // + //-------------------------------------------------------------------------- + // Verify that the size of the message is within bounds. + //-------------------------------------------------------------------------- + // + long munga_network_message_size; + + munga_network_message_size = sizeof(NetworkPacketHeader) + message->messageLength; + if((message->messageLength < 8) || (false)) + //if((message->messageLength < 8) || (munga_network_message_size > MAX_SEND_DATA_SIZE)) + { + char addressString[44]; + DWORD bufferSize = sizeof(addressString); + WSAAddressToStringA((LPSOCKADDR)local_host->GetNetworkAddress(), sizeof(SOCKADDR_IN), NULL, addressString, &bufferSize); + + DEBUG_STREAM << "L4NetworkManager::SendMessageToNetnub - " << addressString << "Requested to send a " << munga_network_message_size << " size message\n" << std::flush; + Fail("L4NetworkManager::SendMessageToNetnub - Illegal transmit size\n"); + return True; + } + Verify(SEND_BUFFER_SIZE(munga_network_message_size) <= SHARED_MEMORY_SIZE); + + // + //-------------------------------------------------------------------------- + // Build the send request and MUNGA network packet + //-------------------------------------------------------------------------- + // + //SendPacketRequestPtr send_packet_request; + NetworkPacket *network_packet; + + Check_Pointer(Net_Common_Ptr); + //send_packet_request = (SendPacketRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //network_packet = (NetworkPacket*)send_packet_request->Send_Data; + network_packet = (NetworkPacket*)malloc(munga_network_message_size); + + //send_packet_request->Socket_Ptr = receiving_host->GetNetworkSocket(); + network_packet->clientID = client_ID; + network_packet->gameID = gameID; + network_packet->fromHost = local_host_ID; + network_packet->timeStamp = Now(); + + Mem_Copy( + &network_packet->messageData, + message, + message->messageLength, + MAX_SEND_DATA_SIZE-sizeof(NetworkPacketHeader) + ); + + // + //-------------------------------------------------------------------------- + // Netnub call + //-------------------------------------------------------------------------- + // + //Check_Pointer(Net_Common_Ptr); + //#if defined(TRACE_SEND_BUFFER) + // SendPacketReturnPtr send_packet_return = + // (SendPacketReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //#endif + //Net_Common_Ptr->Buffer_Length = + // (unsigned short)SEND_BUFFER_SIZE(munga_network_message_size); + //Net_Common_Ptr->Function = + // NETNUB_SEND_PACKET; + //NetNub::SendCommand(); + send(receiving_host->GetNetworkSocket(), (char *)network_packet, munga_network_message_size, 0); + free(network_packet); + + #if defined(TRACE_SEND_BUFFER) + receiving_host->sendBufferTrace->TakeSnapshot( + send_packet_return->Send_Buffer_Used + ); + #endif + + // + //-------------------------------------------------------------------------- + // Check for errors + //-------------------------------------------------------------------------- + // + //switch(Net_Common_Ptr->Status) + //{ + //case NETNUB_OK: + // return True; + // + //case NETNUB_DATA_DUMPED: + // { + // SET_LOST_DATA(); + // #if REPORT_LOST_DATA + // unsigned long + // temp_net_address = receiving_host->GetNetworkAddress(); + // DEBUG_STREAM << "L4NetworkManager::SendMessageToNetnub - "; + // DEBUG_STREAM << "Data lost to "; + // DEBUG_STREAM << ((temp_net_address>>24) & 0xff)<<"."<< + // ((temp_net_address>>16) & 0xff)<<"."; + // DEBUG_STREAM << ((temp_net_address>>8) & 0xff)<<"."<< + // (temp_net_address & 0xff)<<"\n"; + // DEBUG_STREAM << flush; + // #endif + // CLEAR_LOST_DATA(); + // } + // return False; + // + //case NETNUB_STREAM_DISCONNECTED: + // { + // DEBUG_STREAM << "L4NetworkManager::SendMessageToNetnub - "; + // DEBUG_STREAM<<"Disconnect detected in send\n"; + // DEBUG_STREAM<GetHostID(), + // receiving_host->GetNetworkSocket() + // ); + // + // NetworkClient + // *client = GetNetworkClientPointer(NetworkManagerClientID); + // Check(client); + // client->ReceiveNetworkPacket(NULL, &myHostDisconnected); + // } + // return True; + // + //default: + // { + // unsigned long + // temp_net_address = receiving_host->GetNetworkAddress(); + + // DEBUG_STREAM << "L4NetworkManager::SendMessageToNetnub - "; + // DEBUG_STREAM << "Error "<Status<<" on "; + // DEBUG_STREAM << ((temp_net_address>>24) & 0xff)<<"."<< + // ((temp_net_address>>16) & 0xff)<<"."; + // DEBUG_STREAM << ((temp_net_address>>8) & 0xff)<<"."<< + // (temp_net_address & 0xff)<<"\n"; + // DEBUG_STREAM << flush; + // Fail("NetNub error in transmit\n"); + // } + // break; + //} + return True; +} + +#if MESSAGE_BUFFERING +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::ExclusiveBroadcast +// +void + L4NetworkManager::ExclusiveBroadcast( + Message *message, + ClientID client_ID + ) +{ + SET_SEND_PACKET(); + Check(this); + Check(message); + + // + //-------------------------------------------------------------------------- + // If the message buffer is not empty then add this new message into the + // buffer. One copy per host. + //-------------------------------------------------------------------------- + // + if (!messageBuffer.IsEmpty()) + { + Check(application); + Check(application->GetHostManager()); + + HostManager::RemoteHostIterator + remote_hosts(application->GetHostManager()); + Host + *host; + L4Host + *l4host; + + while ((host = remote_hosts.ReadAndNext()) != NULL) + { + l4host = Cast_Object(L4Host*, host); + Check(l4host); + + // + // only non-console hosts that are online + // + if( + (l4host->GetHostType() != ConsoleHostType) && + (l4host->GetConnectStatus() == L4Host::OnLineConnectionStatus) + ) + { + messageBuffer.AddSendRequest( + l4host->GetHostID(), + client_ID, + message + ); + } + } + messageBuffer.AttemptToSend(); + CLEAR_SEND_PACKET(); + return; + } + + // + //-------------------------------------------------------------------------- + // The message buffer is empty so attempt to send the message. + //-------------------------------------------------------------------------- + // + DroppedMessageHostSocket + dropped_message_host_socket(NULL); + + SendBatchedMessageToNetnub( + message, + client_ID, + &dropped_message_host_socket + ); + + // + //-------------------------------------------------------------------------- + // For each host the message was dropped, add a send request message + //-------------------------------------------------------------------------- + // + DroppedMessageHostIterator + iterator(&dropped_message_host_socket); + L4Host + *l4host; + + while((l4host = iterator.ReadAndNext()) != NULL) + { + Check(l4host); + messageBuffer.AddSendRequest( + l4host->GetHostID(), + client_ID, + message + ); + } + CLEAR_SEND_PACKET(); +} +#else +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// NetworkManager::ExclusiveBroadcast Broadcasts a message to everyone on the +// network execpt us. !!!! Reliable broadcasting is currently used, +// implimented by sending a point-to-point message to every destination. +// +void + L4NetworkManager::ExclusiveBroadcast( + Message *message, // what, + ClientID client // to + ) +{ +#if !BATCHED_TRANSMIT + Host + *this_host; + // + // Iterate through the host list, resolving network addresses, sending and + // making sure we don't send to ourselves. + // + Check(application); + Check(application->GetHostManager()); + + HostManager::RemoteHostIterator remote_hosts(application->GetHostManager()); + + while ((this_host = remote_hosts.ReadAndNext()) != NULL) + { + Check(this_host); + if(this_host->GetHostType() == ConsoleHostType) + { + continue; + } + + Send(message, client, this_host->GetHostID()); + } +#else + int + i, + host_count, // Number of hosts we will be sending to + packet_size; + Host + *this_host, + *local_host; + L4Host + *l4_host_list[MULTIPLE_SEND_PACKET_MAX], + *l4host; + MultipleSendPacketReturnPtr + multiple_send_packet_return; // Format of the reply we get from the NetNub + MultipleSendPacketRequestPtr + multiple_send_packet_request; // Format of the request we send to the NetNub + HostManager + *our_host_manager; + NetworkPacket + *my_temp_packet; // pointer to a place to build a network message + // + // Mark entry to the routine with an analysis call + // + SET_SEND_PACKET(); + // + // Make sure the application and host manager are valid + // + Check(application); + Check_Pointer(message); + our_host_manager = application->GetHostManager(); + Check(our_host_manager); + // + // Make a remote host iterator + // + HostManager::RemoteHostIterator remote_hosts(our_host_manager); + multiple_send_packet_request = (MultipleSendPacketRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + multiple_send_packet_return = (MultipleSendPacketReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + my_temp_packet = (NetworkPacket*)multiple_send_packet_request->Send_Data; + // + // Iterate through all the hosts we want to send to and add them to the + // NETNUB_MULTIPLE_SEND command structure + // + host_count = 0; + while ((this_host = remote_hosts.ReadAndNext()) != NULL) + { + // convert regular host to an L4host so we can get net info + l4host = Cast_Object(L4Host*, this_host); + Check(l4host); + // only broadcast to non-console hosts that are online + if((l4host->GetHostType() != ConsoleHostType) && + (l4host->GetConnectStatus() == L4Host::OnLineConnectionStatus)) + { + // Remember this host so we can match up errors with it later + l4_host_list[host_count] = l4host; + // Put the socket pointer for this host into the request structure + multiple_send_packet_request->Socket_Ptrs[host_count] = + l4host->GetNetworkSocket(); + host_count++; + if(host_count >= MULTIPLE_SEND_PACKET_MAX) + Fail("Tried to send to too many destinations\n"); + } + } + // + // Return if we didn't find anyone to send to + // + if(host_count == 0) + { + CLEAR_SEND_PACKET(); + return; + } + multiple_send_packet_request->Socket_Count = host_count; + // + // Check the packet to make sure it is of legal size + // + if( (message->messageLength > MAX_SEND_DATA_SIZE) || + (message->messageLength < 8) || + (message->messageLength+sizeof(NetworkPacketHeader) > MAX_SEND_DATA_SIZE)) + { + DEBUG_STREAM<<"Tried to send a "<messageLength<<" size packet\n"; + DEBUG_STREAM<messageData, message, message->messageLength); + my_temp_packet->clientID = client; + my_temp_packet->gameID = gameID; + my_temp_packet->timeStamp = Now(); + // + // If the local host doesn't exist yet, we send back zero as the from address + // this lets the console get status before the local host is actually created + // + local_host = our_host_manager->GetLocalHost(); + if(local_host == NULL) + { + my_temp_packet->fromHost = 0; + } + else + { + Check(local_host); + my_temp_packet->fromHost = local_host->GetHostID(); + } + // + // Fill in the NetNub common block with the rest of the data it needs for the call + // + packet_size = message->messageLength + sizeof(NetworkPacketHeader); + Net_Common_Ptr->Function = NETNUB_MULTIPLE_SEND; + Net_Common_Ptr->Buffer_Length = (short)MULTIPLE_SEND_BUFFER_SIZE(packet_size); + NetNub::SendCommand(); + #if !defined(TRACE_SEND_BUFFER) + if(Net_Common_Ptr->Status == NETNUB_OK) + { + CLEAR_SEND_PACKET(); + return; + } + #endif + // + // If we get this far an error was reported on one of the streams + // + for(i = 0; isendBufferTrace->TakeSnapshot(multiple_send_packet_return->Send_Buffer_Used[i]); + #endif + switch(multiple_send_packet_return->Errors[i]) + { + case NETNUB_OK: + break; + case NETNUB_DATA_DUMPED: + { + SET_LOST_DATA(); + #if REPORT_LOST_DATA + unsigned long temp_net_address = l4host->GetNetworkAddress(); + DEBUG_STREAM<<"Data lost to "; + DEBUG_STREAM<<((temp_net_address>>24) & 0xff)<<"."<<((temp_net_address>>16) & 0xff)<<"."; + DEBUG_STREAM<<((temp_net_address>>8) & 0xff)<<"."<<(temp_net_address & 0xff)<<"\n"; + DEBUG_STREAM<GetHostID(), + l4host->GetNetworkSocket()); + NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + Check(client); + client->ReceiveNetworkPacket(NULL, &myHostDisconnected); + break; + } + default: + { + unsigned long temp_net_address; + temp_net_address = l4host->GetNetworkAddress(); + DEBUG_STREAM<<"Error "<Status<<" on "; + DEBUG_STREAM<<((temp_net_address>>24) & 0xff)<<"."<<((temp_net_address>>16) & 0xff)<<"."; + DEBUG_STREAM<<((temp_net_address>>8) & 0xff)<<"."<<(temp_net_address & 0xff)<<"\n"; + DEBUG_STREAM<GetHostManager(); + Check(host_manager); + + // + //-------------------------------------------------------------------------- + // Get the local host ID. If the local host doesn't exist yet, we use zero, + // this lets the console get status before the local host is actually + // created. + //-------------------------------------------------------------------------- + // + Host + *local_host; + HostID + local_host_ID; + + if ((local_host = host_manager->GetLocalHost()) == NULL) + { + local_host_ID = 0; + } + else + { + Check(local_host); + local_host_ID = local_host->GetHostID(); + } + + // + //-------------------------------------------------------------------------- + // Verify that the size of the message is within bounds. + //-------------------------------------------------------------------------- + // + long + munga_network_message_size; + + munga_network_message_size = sizeof(NetworkPacketHeader)+message->messageLength; + //if((message->messageLength < 8) || (munga_network_message_size > MAX_SEND_DATA_SIZE)) + if((message->messageLength < 8) || (false)) + { + DEBUG_STREAM << "L4NetworkManager::SendBatchedMessageToNetnub - "; + DEBUG_STREAM << "Requested to send a " << + munga_network_message_size << " size message\n"; + DEBUG_STREAM << std::flush; + Fail("L4NetworkManager::SendBatchedMessageToNetnub - Illegal transmit size\n"); + return; + } + Verify(MULTIPLE_SEND_BUFFER_SIZE(munga_network_message_size) <= SHARED_MEMORY_SIZE); + + // + //-------------------------------------------------------------------------- + // Build the send request and MUNGA network packet + //-------------------------------------------------------------------------- + // + //MultipleSendPacketRequestPtr send_packet_request; + NetworkPacket *network_packet; + + Check_Pointer(Net_Common_Ptr); + //send_packet_request = (MultipleSendPacketRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //network_packet = (NetworkPacket*)send_packet_request->Send_Data; + network_packet = (NetworkPacket*)malloc(munga_network_message_size); + + // + // Fill in socket ptrs + // + HostManager::RemoteHostIterator remote_hosts(host_manager); + Host *host; + L4Host *l4host, *l4host_array[MULTIPLE_SEND_PACKET_MAX]; + int host_count; + + host_count = 0; + while ((host = remote_hosts.ReadAndNext()) != NULL) + { + l4host = Cast_Object(L4Host*, host); + Check(l4host); + + // + // only broadcast to non-console hosts that are online + // + if( + (l4host->GetHostType() != ConsoleHostType) && + (l4host->GetConnectStatus() == L4Host::OnLineConnectionStatus) + ) + { + if (host_count >= MULTIPLE_SEND_PACKET_MAX) + { + DEBUG_STREAM << "L4NetworkManager::SendBatchedMessageToNetnub - "; + Fail("Tried to send to too many destinations\n"); + return; + } + + // + // Remember this host so we can match up errors with it later + // + Verify(0 <= host_count && host_count < MULTIPLE_SEND_PACKET_MAX); + l4host_array[host_count] = l4host; + + // + // Put the socket pointer for this host into the request structure + // + Verify(0 <= host_count && host_count < MULTIPLE_SEND_PACKET_MAX); + //send_packet_request->Socket_Ptrs[host_count] = l4host->GetNetworkSocket(); + host_count++; + } + } + + // + // Return if there are no hosts to send to + // + //if((send_packet_request->Socket_Count = host_count) == 0) + if(host_count == 0) + return; + + // + // Fill out the munga network packet + // + network_packet->clientID = client_ID; + network_packet->gameID = gameID; + network_packet->fromHost = local_host_ID; + network_packet->timeStamp = Now(); + + Mem_Copy( + &network_packet->messageData, + message, + message->messageLength, + MAX_SEND_DATA_SIZE-sizeof(NetworkPacketHeader) + ); + + // + //-------------------------------------------------------------------------- + // Netnub call + //-------------------------------------------------------------------------- + // + //MultipleSendPacketReturn + // *send_packet_return; + // + //Check_Pointer(Net_Common_Ptr); + //send_packet_return = + // (MultipleSendPacketReturn*)Net_Common_Ptr->Shared_Memory_Buffer; + //Net_Common_Ptr->Buffer_Length = + // (unsigned short)MULTIPLE_SEND_BUFFER_SIZE(munga_network_message_size); + //Net_Common_Ptr->Function = + // NETNUB_MULTIPLE_SEND; + //NetNub::SendCommand(); + for(int i=0; iGetNetworkSocket(), (char *)network_packet, sizeof(network_packet), 0); + } + free(network_packet); + + //if (Net_Common_Ptr->Status == NETNUB_OK) + // return; + // + //// + ////-------------------------------------------------------------------------- + //// Parse return + ////-------------------------------------------------------------------------- + //// + //for (int i = 0; i < host_count; i++) + //{ + // Verify(0 <= i && i < MULTIPLE_SEND_PACKET_MAX); + // l4host = l4host_array[i]; + // Check(l4host); + // + // #if defined(TRACE_SEND_BUFFER) + // l4host->sendBufferTrace->TakeSnapshot( + // send_packet_return->Send_Buffer_Used[i] + // ); + // #endif + + // switch (send_packet_return->Errors[i]) + // { + // case NETNUB_OK: + // break; + // + // case NETNUB_DATA_DUMPED: + // { + // SET_LOST_DATA(); + // #if REPORT_LOST_DATA + // unsigned long + // temp_net_address = l4host->GetNetworkAddress(); + // + // DEBUG_STREAM << "L4NetworkManager::SendBatchedMessageToNetnub - "; + // DEBUG_STREAM << "Data lost to "; + // DEBUG_STREAM << ((temp_net_address>>24) & 0xff)<<"."<< + // ((temp_net_address>>16) & 0xff)<<"."; + // DEBUG_STREAM << ((temp_net_address>>8) & 0xff)<<"."<< + // (temp_net_address & 0xff)<<"\n"; + // DEBUG_STREAM << flush; + // #endif + // + // // + // // Add this host to the dropped message host socket + // // + // Check(dropped_message_host_socket); + // dropped_message_host_socket->Add(l4host); + // CLEAR_LOST_DATA(); + // } + // break; + // + // case NETNUB_STREAM_DISCONNECTED: + // { + // DEBUG_STREAM << "L4NetworkManager::SendBatchedMessageToNetnub - "; + // DEBUG_STREAM <<"Disconnect detected in send\n"; + // DEBUG_STREAM <GetHostID(), + // l4host->GetNetworkSocket() + // ); + // NetworkClient + // *client = GetNetworkClientPointer(NetworkManagerClientID); + // Check(client); + // client->ReceiveNetworkPacket(NULL, &myHostDisconnected); + // } + // break; + // + // default: + // { + // unsigned long + // temp_net_address = l4host->GetNetworkAddress(); + // DEBUG_STREAM << "L4NetworkManager::SendBatchedMessageToNetnub - "; + // DEBUG_STREAM <<"Error "<Status<<" on "; + // DEBUG_STREAM <<((temp_net_address>>24) & 0xff)<<"."<< + // ((temp_net_address>>16) & 0xff)<<"."; + // DEBUG_STREAM <<((temp_net_address>>8) & 0xff)<<"."<< + // (temp_net_address & 0xff)<<"\n"; + // DEBUG_STREAM <Shared_Memory_Buffer; + //next_socket_ptr = multiple_receive_packet->Socket_Ptrs; + //multiple_receive_packet_return = (MultipleReceivePacketReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //current_receive_ptr = multiple_receive_packet_return->Received_Data; + // + // Check some of the pointers we plan to use + // + Check(application); + Check(application->GetHostManager()); + // + // Make an iterator to take us through all the hosts + // + HostManager::RemoteHostIterator remote_hosts(application->GetHostManager()); + // + // See if there is ANY data available from the MUNGA buffers before we go + // looking for it from the network. + // + if(GetNextMungaPacket(network_packet,&remote_hosts)) + { + CLEAR_CHECK_BUFFERS(); + return True; + } + // + // Reset to the first host, then attempt to read from every host that has + // room in it's buffers for a packet + // + host_count = 0; + remote_hosts.First(); + while ((host = remote_hosts.ReadAndNext()) != NULL) + { + // get the host pointer and cast it over to an l4 host. This is done so we can + // bang directly on the pad buffers stored in the host. Yes, it's ugly but it will + // be fixed in the future !!!! GAC + remote_host = Cast_Object(L4Host*, host); + Check(remote_host); + // + // Our first priority is to check connection status on any hosts that we haven't + // connected to yet. If we encounter a host who has connected we immediately + // generate and return the appropriate message for transmission via routepacket + // + switch(remote_host->GetConnectStatus()) + { + case L4Host::NoNetworkConnectionStatus: + // + // No connection at all, we skip polling this guy for data + // + continue; + case L4Host::OpeningConnectionStatus: + { + SOCKADDR_IN stream_net_address, host_net_address; + // + // This checks a connection that was created with an active open. + // If there wasn't a connection, continue on to the next guy + // + if(!CheckSocket(remote_host->GetNetworkSocket(), &stream_net_address)) + continue; + + // + // Because we opened to a specific host address we should ALWAYS connect + // to the host we expected. If the address of the computer on the remote + // doesn't match the one we opened to, we scream loudly and fail. + // + host_net_address = *remote_host->GetNetworkAddress(); + if(!(stream_net_address == host_net_address)) + { + char addressString[44]; + DWORD bufferSize = sizeof(addressString); + WSAAddressToStringA((LPSOCKADDR)&stream_net_address, sizeof(SOCKADDR_IN), NULL, addressString, &bufferSize); + + DEBUG_STREAM << "Host " << addressString << std::flush; + + bufferSize = sizeof(addressString); + WSAAddressToStringA((LPSOCKADDR)&host_net_address, sizeof(SOCKADDR_IN), NULL, addressString, &bufferSize); + + DEBUG_STREAM << " client " << addressString << "\n"; + Fail("For an OPEN the host MUST match the client or something is really messed up\n"); + } + // + // Finish the process of opening the port up, then return False + // as if no packet was received + // + HostConnectedMessage myHostConnect( + remote_host->GetHostID(), + stream_net_address, + remote_host->GetNetworkSocket()); + NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + Check(client); + client->ReceiveNetworkPacket(NULL, &myHostConnect); + CLEAR_CHECK_BUFFERS(); + return(False); + } + case L4Host::ListeningConnectionStatus: + { + SOCKET tempSocket = INVALID_SOCKET; + + SOCKADDR_IN net_address; + memset(&net_address, 0, sizeof(SOCKADDR_IN)); + net_address.sin_family = AF_INET; + + if(remote_host->GetHostType() == ConsoleHostType) + { + if((tempSocket = accept(consoleListenerSocket, NULL, 0)) != INVALID_SOCKET) + { + closesocket(consoleListenerSocket); + consoleListenerSocket = INVALID_SOCKET; + } + } + else + { + if((tempSocket = accept(gameListenerSocket, NULL, 0)) == INVALID_SOCKET) + { + continue; + } + } + + remote_host->SetNetworkSocket(tempSocket); + if (!CheckSocket(remote_host->GetNetworkSocket(), &net_address)) + continue; + + char addressString[44]; + DWORD bufferSize = sizeof(addressString); + WSAAddressToStringA((LPSOCKADDR)&net_address, sizeof(SOCKADDR_IN), NULL, addressString, &bufferSize); + DEBUG_STREAM << "STATUS: socket accepted from " << addressString << "!\n" << std::flush; + + // + // The Waterloo TCP package has a problem with making connections. It always + // seems to connect people to the last socket that was listened on regardless + // of the port or net address settings. Because of this we have to make sure + // the connect we get belongs to the host we connected to, if it doesn't we + // have to find the right host and potentially swap the streams around. We + // also have to have a special case to handle listening for the console. Since + // we don't know the console machine's address in advance we (!!!!for now) + // assume we will only do a listen for the console if it's the only machine + // we're going to listen for. + // + Host *connect_host; + L4Host *connect_L4_host; + SOCKET swap_socket_ptr; + swap_socket_ptr = remote_host->GetNetworkSocket(); + if(net_address == *remote_host->GetNetworkAddress()) + { + // + // The address of the host that connected on this stream matched the one + // we were expecting (ie: port/network address filtering worked) so we + // just process it straight through. This should handle a host pretending + // to be a console and OPENing to another host. + // + HostConnectedMessage myHostConnect( + remote_host->GetHostID(), + net_address, + remote_host->GetNetworkSocket()); + NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + Check(client); + client->ReceiveNetworkPacket(NULL, &myHostConnect); + } + else if(remote_host->GetHostType() == ConsoleHostType) + { + // + // This handles a LISTEN for a console with an unspecified net address + // Because the console uses a different port number than the game does + // whatever connects to a console host should be correct. So whoever + // shows up on this host should be a console (or thinks it is) + // NOTE: We actually set the host's net address here, since we didn't + // know it in advance. + // + remote_host->SetNetworkAddress(&net_address); + HostConnectedMessage myHostConnect( + remote_host->GetHostID(), + net_address, + remote_host->GetNetworkSocket()); + NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + Check(client); + client->ReceiveNetworkPacket(NULL, &myHostConnect); + } + else + { + // + // The address of the host that connected didn't match the one we were + // expecting on this stream. So we have to find the right host and swap + // streams with them. + // + HostManager::RemoteHostIterator connect_hosts(application->GetHostManager()); + while ((connect_host = connect_hosts.ReadAndNext()) != NULL) + { + connect_L4_host = Cast_Object(L4Host*, connect_host); + if(connect_L4_host->GetConnectStatus() != L4Host::ListeningConnectionStatus) + { + // skip hosts that are not currently listening since they are not + // candidates for swapping. + continue; + } + // + // If the address of this guy matches the address of the person who just + // connected, we swap their stream pointers + // + if(*connect_L4_host->GetNetworkAddress() == net_address) + { + remote_host->SetNetworkSocket(connect_L4_host->GetNetworkSocket()); + connect_L4_host->SetNetworkSocket(swap_socket_ptr); + HostConnectedMessage myHostConnect( + connect_L4_host->GetHostID(), + net_address, + connect_L4_host->GetNetworkSocket()); + NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + Check(client); + client->ReceiveNetworkPacket(NULL, &myHostConnect); + CLEAR_CHECK_BUFFERS(); + return False; + } + } + } + CLEAR_CHECK_BUFFERS(); + return False; + } + case L4Host::OnLineConnectionStatus: + // OnLine hosts just fall through so they can be polled + break; + default: + Fail("Host had illegal connection status\n"); + break; + } +#if !BATCHED_RECEIVE + // + // If we get this far the host is on line, if there is room to do a receive + // into this buffer then do one. + // + //unsigned long *next_status_ptr = &(multiple_receive_packet_return->Status[0]); + space_left = (short)(remote_host->pad_size - remote_host->pad_tail); + if(space_left >= MAX_RECEIVE_DATA_SIZE) + { + // there was sufficient room for a receive to happen, so do it + // Setup the request in the common area + //Net_Common_Ptr->Function = NETNUB_RECEIVE_PACKET; + //Net_Common_Ptr->Buffer_Length = sizeof(ReceivePacketRequest); + //receive_packet_request = (ReceivePacketRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //receive_packet_request->Socket_Ptr = remote_host->GetNetworkSocket(); + // call the network server + //NetShare(); + void* buffer = malloc(space_left); + int received = recv(remote_host->GetNetworkSocket(), (char*)buffer, space_left, 0); + // if we received data, copy it over into the buffer for this host + //switch(Net_Common_Ptr->Status) + if(received > 0) + { + //case NETNUB_RECEIVED_PACKET: + // copy the received data over to the host's data buffer + Mem_Copy( + &remote_host->pad_buffer[remote_host->pad_tail], + //Net_Common_Ptr->Shared_Memory_Buffer, + buffer, + //Net_Common_Ptr->Buffer_Length, + received, + space_left); + //remote_host->pad_tail += Net_Common_Ptr->Buffer_Length; + remote_host->pad_tail += received; + //break; + } + //case NETNUB_OK: + else if(received == SOCKET_ERROR) + { + //this indicates that no data is available and the socket is non blocking + //break; + DWORD error = WSAGetLastError(); + switch (error) + { + case WSAECONNRESET: + // this will cause us to execute our disconnect code + received = 0; + break; + case WSAEWOULDBLOCK: + // this is expected when there is no data + break; + default: + DEBUG_STREAM << "L4NetworkManager::CheckBuffers: Socket recv returned an unexpected error: WSAGetLastError = " << error << std::endl << std::flush; + } + } + // case NETNUB_STREAM_DISCONNECTED: + if(received == 0) + { + { + HostDisconnectedMessage myHostDisconnected( + remote_host->GetHostID(), + remote_host->GetNetworkSocket()); + NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + Check(client); + client->ReceiveNetworkPacket(NULL, &myHostDisconnected); + //break; + } + } + //default: + free(buffer); + } + } +#else + // + // If we get this far the host is on line, see if there is room to do a + // receive into it's buffer. + // + space_left = (short)( remote_host->pad_size - remote_host->pad_tail); + if(space_left >= MAX_RECEIVE_DATA_SIZE) + { + // + // There is room, add it to the list of hosts + // + l4_host_list[host_count++] = remote_host; + *(next_socket_ptr++) = remote_host->GetNetworkSocket(); +// DEBUG_STREAM<<"Add stream "<GetNetworkSocket()<<"\n"; + } + } + // + // Finish the request to netnub, then send it down + // + if(host_count == 0) + { + CLEAR_CHECK_BUFFERS(); + return False; + } +// DEBUG_STREAM<<"Sending command to read "<Socket_Count = host_count; + Net_Common_Ptr->Function = NETNUB_MULTIPLE_RECEIVE; + Net_Common_Ptr->Buffer_Length = sizeof(MultipleReceivePacketRequest); + NetNub::SendCommand(); + // + // If NETNUB_OK comes back in status, it means we have no data and can quit + // + if(Net_Common_Ptr->Status == NETNUB_OK) + { +// DEBUG_STREAM<<"No data on any stream\n"; + CLEAR_CHECK_BUFFERS(); + return(False); + } + // + // One or more streams had data or errors + // + for(i = 0; iStatus[i]; +// if(status != 0) +// DEBUG_STREAM<<"stream "<GetNetworkSocket()<<" status "<GetHostID(), + l4host->GetNetworkSocket()); + NetworkClient *client = GetNetworkClientPointer(NetworkManagerClientID); + Check(client); + client->ReceiveNetworkPacket(NULL, &myHostDisconnected); + } + else if(status < 0) + { + // error of some kind, handle it + DEBUG_STREAM<<"MUNGA reported network error "<pad_buffer[l4host->pad_tail], + current_receive_ptr, + status, + (short)(l4host->pad_size - l4host->pad_tail)); + l4host->pad_tail += (Word)status; + current_receive_ptr += status; + } + } +#endif + // + // Now loop through all the hosts again till we find one with a complete munga + // message to be returned for processing by the host. + // + get_buffer_status = GetNextMungaPacket(network_packet,&remote_hosts); + CLEAR_CHECK_BUFFERS(); + return(get_buffer_status); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// GetNextMungaPacket Checks the internal MUNGA packet assembly buffers to +// see if there are packets available on any open stream +// +Logical + L4NetworkManager::GetNextMungaPacket( + NetworkPacket *network_packet, + HostManager::RemoteHostIterator *remote_hosts) +{ + short + i, + host_count, + move_size, + receive_packet_size; + Host + *host; + L4Host + *remote_host; + NetworkPacket + *incoming_packet; + + // + // Loop through all the hosts and check their buffers + // + host_count = (short)remote_hosts->GetSize(); + for( + i = 0; + i < host_count; + i++) + { + // + // This causes us to start checking hosts where we left off the last time + // it prevents any one host from always getting serviced first. + // + lastHostIteratorPosition++; + if(lastHostIteratorPosition >= remote_hosts->GetSize()) + { + lastHostIteratorPosition = 0; + } + if((host = remote_hosts->GetNth(lastHostIteratorPosition)) == NULL) + { + break; + } + // + // get the host pointer and cast it over to an l4 host so we can look at it's buffers + // + remote_host = Cast_Object(L4Host*, host); + Check(remote_host); + // + // If we're in ConsoleOnly state, don't return messages for non-console streams + // + if((currentNetworkState == ConsoleOnly) && + (remote_host->GetHostType() != ConsoleHostType)) + continue; + // + // does this host data buffer contain a complete munga message header + // + if(remote_host->pad_tail >= sizeof(NetworkPacket)) + { + // + // enough bytes for a complete message header, read the message length and + // figure how many bytes the complete packet should be + // + incoming_packet = (NetworkPacket*)remote_host->pad_buffer; + receive_packet_size = (short)(incoming_packet->messageData.messageLength + sizeof(NetworkPacketHeader)); + Verify(receive_packet_size > 0); + // Are there enough bytes in the buffer to make up this packet? + if(remote_host->pad_tail >= receive_packet_size) + { + // we have a complete packet, copy it into the output buffer and rejustify the host's + // buffer (inefficient as hell but easy to write for now) + Mem_Copy( + network_packet, + remote_host->pad_buffer, + receive_packet_size, + NETWORKMANAGER_BUFFER_SIZE); + move_size = (short)(remote_host->pad_tail - receive_packet_size); + // don't do the next step if the buffer is empty + // we need to use memmove because the source and destination addresses overlap + // and memcopy doesn't know how to deal with that. + Verify(move_size < L4HOST_PAD_BUFFER_SIZE); + if(move_size != 0) + { + memmove( + remote_host->pad_buffer, + &remote_host->pad_buffer[receive_packet_size], + move_size); + } + remote_host->pad_tail -= receive_packet_size; + // Return true (packet received) + return True; + } + else + { +// cout<<"++++++++Waiting for "<pad_tail<<"\n"; + } + } + } + // + // If we get here, all the streams were empty + // + return False; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::RemovePacket If the network implimentation requires us to +// free up a packet buffer, this routine would do it. +// +void + L4NetworkManager::RemovePacket(NetworkPacket*) +{ + // + // This function is not required for now + // +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::NetShare This is Gene's implementation of the protected +// to real mode interface. +// +//WinSock support :ADB 01/06/07 +//void NetNub::SendCommand() +//{ +// struct RMREG +// rmreg; +// union REGS +// regs; +// struct SREGS +// sregs; +// +// SET_CALL_NETNUB(); +// // +// // Check a few things before making the DPMI call to the interrupt +// // +// Verify(Net_Common_Ptr->Buffer_Length <= SHARED_MEMORY_SIZE); +// // +// // This assembly routine copies the contents of the NetCommon down into real mode +// // +// setRMBuff(); +// // +// // Setup for the call to the DPMI to simulate real mode interrupt +// // +// regs.x.eax = 0x0300; // function of INT31 +// regs.h.bl = intno; // +// regs.h.bh = 0; //flags +// regs.x.ecx = 0; //number of words to copy from protected mode to real mode stack +// regs.x.edi =(unsigned int)&rmreg; //es:edi is an address of RMREG structure +// segread(&sregs); +// rmreg.reserved = 0; //default settings: +// rmreg.fs = 0; +// rmreg.gs = 0; +// rmreg.flags = 0; +// rmreg.ss = 0; //real mode stack is provided by DPMI unless ss:sp != 0 +// rmreg.sp = 0; +// // +// // Call the DPMI +// // +// int386x(0x31,®s,®s,&sregs); +// // +// // Check for an error +// // +// if (regs.x.cflag) +// { +// DEBUG_STREAM<<"int386x():ERROR="<Version_Number == NETCOM_VERSION); +// CLEAR_CALL_NETNUB(); +//} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~Encapsulations of netnub calls~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::GetMyAddress This routine calls the netnub and returns +// our network address if everything is ok or zero if it's not. It can also be +// used to tickle the netnub or to check status of the netnub. +// +//WinSock support :ADB 01/06/07 +NetworkAddress* L4NetworkManager::GetMyAddress() +{ + char name[255]; + PHOSTENT hostinfo; + + if (gethostname(name, sizeof(name)) != 0) + { + DEBUG_STREAM << "ERROR: gethostname() failed!" << std::endl << std::flush; + return NULL; + } + + if ((hostinfo = gethostbyname(name)) == NULL) + { + DEBUG_STREAM << "ERROR: gethostbyname() failed!" << std::endl << std::flush; + return NULL; + } + + // count how many addresses we have + for (num_addresses = 0; hostinfo->h_addr_list[num_addresses]; num_addresses++); + + NetworkAddress* myAddresses = new NetworkAddress[num_addresses + 1]; + for (int i=0; ih_addr_list[i]); + + // add 127.0.0.1 to list + myAddresses[num_addresses++] = (NetworkAddress)0x0100007F; + + return myAddresses; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::ResolveAddress This routine takes a CString containing +// a host name and makes the appropriate network calls to resolve it to a +// binary internet address. +// +//WinSock support :ADB 01/06/07 +bool L4NetworkManager::ResolveAddress(CString host_name, SOCKADDR_IN *address) +{ + //if (strstr(host_name, ":")) + { + // this address contains a colon so we'll do things a little differently + int bufferSize = sizeof(SOCKADDR_IN); + WSAStringToAddressA((LPSTR)host_name, AF_INET, NULL, (LPSOCKADDR)address, &bufferSize); + if (address->sin_port == 0) + address->sin_port = htons(GAME_NET_PORT); + return true; + } + + addrinfo* hostAddrinfo = NULL; + addrinfo aiHints; + memset(&aiHints, 0, sizeof(aiHints)); + aiHints.ai_family = AF_INET; + aiHints.ai_socktype = SOCK_STREAM; + aiHints.ai_protocol = IPPROTO_TCP; + + int iResult = getaddrinfo((char*)host_name, NULL, &aiHints , &hostAddrinfo); + if(iResult != 0) + { + DEBUG_STREAM<<"ERROR: getaddrinfo() failed with " << WSAGetLastError() << "!\n"; + return NULL; + } + + addrinfo* addr = hostAddrinfo; + while(addr != NULL) + { + if(addr->ai_addr->sa_family == AF_INET) + break; + addr = addr->ai_next; + } + + memset(address, 0, sizeof(SOCKADDR_IN)); + *address = *((sockaddr_in*)&addr->ai_addr->sa_data); + if (address->sin_port == 32778) + address->sin_port = htons(CONSOLE_NET_PORT); + + freeaddrinfo(hostAddrinfo); + + // + // Check the status returns and return the address if we got one ok + // + if(!address || address->sin_addr.S_un.S_addr == 0 || address->sin_port == 0) + { + DEBUG_STREAM << "Couldn't resolve " << host_name << " to a net address\n"; + Fail("unresolvable network address\n"); + } + + return true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::CheckSocket This routine does checks a socket and returns +// the state of that socket (connected or not) +// +//WinSock support :ADB 01/06/07 +bool L4NetworkManager::CheckSocket(SOCKET socket, SOCKADDR_IN *remoteEndpoint) +{ + if (remoteEndpoint) + { + int size = sizeof(SOCKADDR_IN); + memset(remoteEndpoint, 0, size); + if(!getpeername(socket, (sockaddr*)remoteEndpoint, &size)) + return true; + } + return false; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::OpenConnection This routine does the appropriate calls to +// start the open process for another host. You can do an active or passive open +// with this routine by passing the appropriate parameters in. The arguments +// are geared to the typical TCP/IP connection parameters. After calling this +// routine you must create the host yourself. +// +//WinSock support :ADB 01/06/07 +//unsigned long OpenConnection( +SOCKET L4NetworkManager::OpenConnection( + int connection_type, // NETNUB_TCP_LISTEN or NETNUB_TCP_OPEN + int local_port, + int remote_port, + int internet_address) +{ + //TCPOpenRequestPtr + // tcp_open_request; + //TCPOpenReturnPtr + // tcp_open_return; + // + // Checkup everything + // + //Check_Pointer(Net_Common_Ptr); + // + // Make sure we are using a legal open mode + // + Verify( (connection_type == NETNUB_TCP_LISTEN) || + (connection_type == NETNUB_TCP_OPEN)); + // + // Format the open/listen request + // + //tcp_open_request = (TCPOpenRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //tcp_open_return = (TCPOpenReturnPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //Net_Common_Ptr->Function = (short)connection_type; + //Net_Common_Ptr->Buffer_Length = sizeof(TCPOpenRequest); + //tcp_open_request->Local_Port = (short)local_port; + //tcp_open_request->Remote_Port = (short)remote_port; + //tcp_open_request->Internet_Address = internet_address; + //tcp_open_request->Socket_Ptr = 0; // !!! 0 causes netnub to allocate socket + //NetNub::SendCommand(); + //if(Net_Common_Ptr->Status == NETNUB_ERROR) + //{ + // DEBUG_STREAM<<"NetNub TCP Open/Listen error #"<Socket_Ptr<<" listening for "; + // DEBUG_STREAM<<((internet_address>>24) & 0xff)<<"."<<((internet_address>>16) & 0xff)<<"."; + // DEBUG_STREAM<<((internet_address>>8) & 0xff)<<"."<<(internet_address & 0xff)<<"\n"; + // Fail("Netnub error during open/listen\n"); + //} + //return(tcp_open_return->Socket_Ptr); + + if(connection_type == NETNUB_TCP_OPEN) + { + DEBUG_STREAM << "Opening connection to " << inet_ntoa(*(in_addr*)&internet_address) << ":" << remote_port << "...\n" << std::flush; + + SOCKET sock = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(sock == INVALID_SOCKET) + { + DEBUG_STREAM << "ERROR: socket() failed with " << WSAGetLastError() << "!\n"; + return INVALID_SOCKET; + } + + bool reuseAddr = true; + if (setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseAddr, sizeof(bool))) + { + DEBUG_STREAM << "ERROR: Could not set SO_REUSEADDR on socket; setsockopt() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return INVALID_SOCKET; + } + + sockaddr_in localEndpoint; + memset(&localEndpoint, 0, sizeof(localEndpoint)); + localEndpoint.sin_family = AF_INET; + localEndpoint.sin_port = htons(local_port); + localEndpoint.sin_addr.S_un.S_addr = INADDR_ANY; + if(bind(sock, (sockaddr*)&localEndpoint, sizeof(localEndpoint))) + { + DEBUG_STREAM << "ERROR: Could not bind local socket; bind() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return INVALID_SOCKET; + } + + sockaddr_in remoteEndpoint; + memset(&remoteEndpoint, 0, sizeof(remoteEndpoint)); + remoteEndpoint.sin_family = AF_INET; + //VERIFY: Network vs Host byte order? + remoteEndpoint.sin_addr.S_un.S_addr = internet_address; + remoteEndpoint.sin_port = htons(remote_port); + int wsaError, iResult; + + do + { + iResult = connect(sock, (sockaddr*)&remoteEndpoint, sizeof(remoteEndpoint)); + + if (iResult != 0) + { + wsaError = WSAGetLastError(); + } + } while (iResult != 0 && wsaError == 10061); + + if(iResult != 0) + { + DEBUG_STREAM << "ERROR: connect() failed with " << wsaError << "!\n" << std::flush; + return INVALID_SOCKET; + } + + //set to non blocking + unsigned long enable = 1; + if(ioctlsocket(sock, FIONBIO, &enable)) + { + DEBUG_STREAM << "ERROR: Could not set actively opened socket to nonblocking; ioctlsocket() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + } + return sock; + } + else if(connection_type == NETNUB_TCP_LISTEN) + { + if(gameListenerSocket == NULL) + { + DEBUG_STREAM << "Starting to listen on port " << local_port << "...\n" << std::flush; + + gameListenerSocket = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP); + if(gameListenerSocket == INVALID_SOCKET) + { + DEBUG_STREAM << "ERROR: Could not create game listener socket; socket() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + } + + bool reuseAddr = true; + if (setsockopt(gameListenerSocket, SOL_SOCKET, SO_REUSEADDR, (char*)&reuseAddr, sizeof(bool))) + { + DEBUG_STREAM << "ERROR: Could not set SO_REUSEADDR on game listener socket; setsockopt() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return INVALID_SOCKET; + } + + sockaddr_in localEndpoint; + memset(&localEndpoint, 0, sizeof(localEndpoint)); + localEndpoint.sin_family = AF_INET; + localEndpoint.sin_port = htons(local_port); + localEndpoint.sin_addr.S_un.S_addr = INADDR_ANY; + if(bind(gameListenerSocket, (sockaddr*)&localEndpoint, sizeof(localEndpoint))) + { + DEBUG_STREAM << "ERROR: Could not bind game listener socket; bind() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return INVALID_SOCKET; + } + if(listen(gameListenerSocket, 25)) + { + DEBUG_STREAM << "ERROR: Could not listen on game listener socket; listen() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return INVALID_SOCKET; + } + //set to non blocking + unsigned long enable = 1; + if(ioctlsocket(gameListenerSocket, FIONBIO, &enable)) + { + DEBUG_STREAM << "ERROR: Could not set game listener socket to nonblocking; ioctlsocket() failed with " << WSAGetLastError() << "!\n" << std::flush; + WSACleanup(); + PostQuitMessage(AbortExitCodeID); + return INVALID_SOCKET; + } + } + else + DEBUG_STREAM << "Listen requested on port " << local_port << " but gameListenerSocket already existed!\n" << std::flush; + + return INVALID_SOCKET; + } + else + return INVALID_SOCKET; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::CloseConnection This routine does the appropriate calls to +// close a connection to another host, it really should wait for an error return +// but doesn't right now. +// +//WinSock support :ADB 01/06/07 +void L4NetworkManager::CloseConnection(SOCKET socket_ptr) // socket address from netnub (to close) +{ + //TCPCloseRequestPtrclose_request; + // + // Checkup everything + // + Check_Pointer(Net_Common_Ptr); + // + // Do the actual close + // + //Net_Common_Ptr->Function = NETNUB_TCP_CLOSE; + //Net_Common_Ptr->Buffer_Length = sizeof(TCPCloseRequest); + //close_request = (TCPCloseRequestPtr)Net_Common_Ptr->Shared_Memory_Buffer; + //close_request->Socket_Ptr = socket_ptr; + //NetNub::SendCommand(); + shutdown(socket_ptr, SD_BOTH); + closesocket(socket_ptr); + // Check for errors + //if(Net_Common_Ptr->Status != NETNUB_OK) + //{ + // DEBUG_STREAM<<"NetNub close error "<Status<<" on stream "<Shared_Memory_Buffer; + //switch(myMode) + //{ + // case ReliableMode: + // set_switches_request->blocking_switch = True; + // break; + // case UnreliableMode: + // set_switches_request->blocking_switch = False; + // break; + //} + //Net_Common_Ptr->Function = NETNUB_SET_SWITCHES; + //Net_Common_Ptr->Buffer_Length = sizeof(SetSwitchesRequest); + //NetNub::SendCommand(); + //// Check for errors + //if(Net_Common_Ptr->Status != NETNUB_OK) + //{ + // DEBUG_STREAM<<"NetNub mode call failed\n"; + // return; + //} +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager::Marker This routine does the appropriate calls to send +// a text marker down to netnub +// +//WinSock support :ADB 01/06/07 +void L4NetworkManager::Marker(char *marker_text) // text message to send down +{ + //int + // marker_text_size; + //// + //// No netnub present? Just return + // // + //if(Net_Common_Ptr == NULL) + //{ + // return; + //} + //// + //// Checkup everything + //// + //Check_Pointer(Net_Common_Ptr); + //// + //// Copy the text over (including the 0 terminator) + //// + //marker_text_size = strlen(marker_text)+1; + //Mem_Copy( + // (char*)Net_Common_Ptr->Shared_Memory_Buffer, + // marker_text, + // marker_text_size, + // SHARED_MEMORY_SIZE); + //Net_Common_Ptr->Function = NETNUB_MARKER_TEXT; + //Net_Common_Ptr->Buffer_Length = (short)marker_text_size; + //NetNub::SendCommand(); + //// Check for errors + //if(Net_Common_Ptr->Status != NETNUB_OK) + //{ + // DEBUG_STREAM<<"NetNub marker text call failed\n"; + // return; + //} +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4NetworkManager::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +#ifdef TEST_CLASS +#include "l4net.tcp" +#endif + + +#if 0 + else if(networkStartupMode == MasterMode && remoteHostCount > 0) + { + enum ConsoleState + { + GetNextHostConsoleState, + OpenNextHostConsoleState, + WaitForConnectConsoleState, + SendEggConsoleState, + WaitForEggAckConsoleState, + WaitForGameConnectConsoleState, + CloseStreamConsoleState, + WaitForAllHostsConsoleState, + DoneConsoleState + }; + long + size_of_notation_text; + int + game_machine_up_count; + ConsoleState + consoleState; + NetworkAddress + temp_net_address; + char + *temp_notation_text; + Host + *host; + NotationFile + *temp_notation_file; + // + // Master must send the egg to the other hosts and wait for each to acknowledge + // it's processing before going on to the next host. First we turn the notation + // file into text so we can send it. + // + temp_notation_file = new NotationFile(GlobalEggFileName); + Register_Object(temp_notation_file); + if(temp_notation_file->PageCount() == 0) + { + Fail("Tried to startup with an empty notation file\n"); + } + size_of_notation_text = temp_notation_file->SizeOfText(); + temp_notation_text = new char[size_of_notation_text]; + Register_Pointer(temp_notation_text); + temp_notation_file->WriteText( + temp_notation_text, + size_of_notation_text); + // + // Now setup and run the state machine till everyone has been connected. + // + HostManager::RemoteHostIterator remote_hosts(application->GetHostManager()); + currentNetworkState = ConsoleOnly; + eggAcknowledged = False; + consoleState = GetNextHostConsoleState; + while ( consoleState != DoneConsoleState && remoteHostCount > 0) + { + // + // Poll the network (the arrival times of these measages are complicated + // so I don't advise messing with the order of this loop casually) + // + RoutePacket(); + // + // Do what we're supposed to based on our current state + // + switch(consoleState) + { + case GetNextHostConsoleState: + // + // Get the next game machine host + // + Tell("GetNextHostConsoleState--Getting next host\n"); + game_machine_up_count = numberOfMungaHostsConnected; + remote_hosts.First(); + while((host = remote_hosts.ReadAndNext()) != NULL) + { + L4Host* an_l4host = Cast_Object(L4Host*, host); + if(an_l4host->GetHostType() == ConsoleHostType || + an_l4host->GetConnectStatus() == L4Host::NoNetworkConnectionStatus || + an_l4host->GetConnectStatus() == L4Host::OnLineConnectionStatus) + continue; + if(an_l4host->GetHostType() == GameMachineHostType) + break; + } + if(host == NULL) + { + consoleState = WaitForAllHostsConsoleState; + } + else + { + consoleState = OpenNextHostConsoleState; + } + break; + case OpenNextHostConsoleState: + // Get the network address of this game machine host and open it + temp_net_address = host->GetNetworkAddress(); + Tell("OpenNextHostConsoleState--Opening console to "); + Tell(((temp_net_address>>24) & 0xff)<<"."<<((temp_net_address>>16) & 0xff)<<"."); + Tell(((temp_net_address>>8) & 0xff)<<"."<<(temp_net_address & 0xff)<<"\n"); + socket_ptr = OpenConnection( + NETNUB_TCP_OPEN, + 0, + CONSOLE_NET_PORT, + temp_net_address); + // Create a console host for this guy + myConsoleHost = new L4Host( + FirstLegalHostID, + ConsoleHostType, + temp_net_address, + socket_ptr, + "Console"); + Register_Object(myConsoleHost); + // Register the console host with the host manager + Check(application); + Check(application->GetHostManager()); + application->GetHostManager()->AdoptRemoteHost(myConsoleHost); + myConsoleHost->SetConnectStatus(L4Host::OpeningConnectionStatus); + numberOfConsoleHostsConnected = 0; + consoleState = WaitForConnectConsoleState; + break; + case WaitForConnectConsoleState: + Tell("C"< 1000) + bytes_left = 1000; + ReceiveEggFileMessage myEggMessage( + sequence, + size_of_notation_text, + temp_notation_text + next_send, + bytes_left); + Send( + &myEggMessage, + NetworkClient::NetworkManagerClientID, + myConsoleHost->GetHostID()); + next_send += bytes_left; + sequence++; + } + eggAcknowledged = False; + consoleState = WaitForEggAckConsoleState; + break; + } + case WaitForEggAckConsoleState: + Tell("E"<>24) & 0xff)<<"."<<((temp_net_address>>16) & 0xff)<<"."; + DEBUG_STREAM<<((temp_net_address>>8) & 0xff)<<"."<<(temp_net_address & 0xff)<<"\n"; + } + break; + case WaitForGameConnectConsoleState: + Tell("G"<GetHostID()); +#endif + Check(myConsoleHost); + CloseConnection(myConsoleHost->GetNetworkSocket()); + // deregister this host with the host manager + application->GetHostManager()->OrphanRemoteHost(myConsoleHost); + Unregister_Object(myConsoleHost); + delete myConsoleHost; + myConsoleHost = NULL; + consoleState = GetNextHostConsoleState; + break; + } + case WaitForAllHostsConsoleState: + Tell("W"<= remoteHostCount) + { + consoleState = DoneConsoleState; + Tell("\WaitForAllHostsConsoleState--done connecting\n"); + } + break; + } + } + Unregister_Pointer(temp_notation_text); + delete temp_notation_text; + Unregister_Object(temp_notation_file); + delete temp_notation_file; + currentNetworkState = NormalState; + } +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~ MessageQueue__SendRequest ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MessageQueue__SendRequest::MessageQueue__SendRequest( + NetworkClient::ClientID client_ID, + Receiver::Message *message +) +{ + // + // Set client ID + // + clientID = client_ID; + + // + // Store the message + // + Check(message); + messageToSend = (Receiver::Message*)new char[message->messageLength]; + Register_Pointer(messageToSend); + Mem_Copy( + messageToSend, + message, + message->messageLength, + message->messageLength + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MessageQueue__SendRequest::~MessageQueue__SendRequest() +{ + Unregister_Pointer(messageToSend); + delete messageToSend; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + MessageQueue__SendRequest::TestInstance() const +{ + Check_Pointer(messageToSend); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~ HostMessageBuffer__MessageQueue ~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +HostMessageBuffer__MessageQueue::HostMessageBuffer__MessageQueue( + HostID host_ID +): + sendRequestSocket(NULL) +{ + hostID = host_ID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +HostMessageBuffer__MessageQueue::~HostMessageBuffer__MessageQueue() +{ + ChainIteratorOf + iterator(&sendRequestSocket); + iterator.DeletePlugs(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + HostMessageBuffer__MessageQueue::TestInstance() const +{ + Check(&sendRequestSocket); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + HostMessageBuffer__MessageQueue::AddSendRequest( + NetworkClient::ClientID client_ID, + Receiver::Message *message + ) +{ + Check(this); + Check(message); + + // + // Create new send request and add it to the socket + // + SendRequest + *send_request; + + send_request = new SendRequest(client_ID, message); + Register_Object(send_request); + sendRequestSocket.Add(send_request); +} + +//~~~~~~~~~~~~~~~~~~~~ L4NetworkManager__MessageBuffer ~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4NetworkManager__MessageBuffer::L4NetworkManager__MessageBuffer( + L4NetworkManager *network_manager +): + messageQueueSocket(NULL, True) +{ + networkManager = network_manager; + currentQueueIndex = 0; + bufferSize = 0; + #ifdef LAB_ONLY + messageCount = 0; + maxBufferSize = 0; + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4NetworkManager__MessageBuffer::~L4NetworkManager__MessageBuffer() +{ + TableIteratorOf + iterator(&messageQueueSocket); + iterator.DeletePlugs(); + + #ifdef LAB_ONLY + cout << "L4NetworkManager__MessageBuffer::" << + "~L4NetworkManager__MessageBuffer" << + " messageCount=" << messageCount << "\n";; + cout << "L4NetworkManager__MessageBuffer::" << + "~L4NetworkManager__MessageBuffer" << + " maxBufferSize=" << maxBufferSize << "\n";; + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4NetworkManager__MessageBuffer::TestInstance() const +{ + Check(&messageQueueSocket); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4NetworkManager__MessageBuffer::AddSendRequest( + HostID host_ID, + NetworkClient::ClientID client_ID, + Receiver::Message *message + ) +{ + Check(this); + Check(message); + + // + // Get this hosts message queue + // + MessageQueue + *message_queue; + + if ((message_queue = messageQueueSocket.Find(host_ID)) == NULL) + { + message_queue = new MessageQueue(host_ID); + Register_Object(message_queue); + messageQueueSocket.AddValue(message_queue, host_ID); + } + Check(message_queue); + + // + // Add the send request + // + message_queue->AddSendRequest(client_ID, message); + bufferSize++; + #ifdef LAB_ONLY + messageCount++; + maxBufferSize = Max(maxBufferSize, bufferSize); + #endif +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4NetworkManager__MessageBuffer::AttemptToSend() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Verify that there exist non-empty queues and that the buffer size is + // correct + //-------------------------------------------------------------------------- + // + #if DEBUG_LEVEL>0 + { + TableIteratorOf + iterator(&messageQueueSocket); + MessageQueue + *message_queue; + CollectionSize + counter = 0; + + while ((message_queue = iterator.ReadAndNext()) != NULL) + { + Check(message_queue); + ChainIteratorOf + message_iterator(&message_queue->sendRequestSocket); + counter += message_iterator.GetSize(); + } + Verify(counter > 0); + Verify(counter == bufferSize); + } + #endif + + // + //-------------------------------------------------------------------------- + // Increment the index to the next non-empty queue + //-------------------------------------------------------------------------- + // + TableIteratorOf + queue_iterator(&messageQueueSocket); + MessageQueue + *message_queue; + MessageQueue::SendRequest + *send_request; + + do + { + // + // Increment the counter + // + if (++currentQueueIndex >= queue_iterator.GetSize()) + currentQueueIndex = 0; + + // + // Get the message queue + // + message_queue = queue_iterator.GetNth(currentQueueIndex); + Check(message_queue); + + // + // Get the message + // + ChainIteratorOf + message_iterator(&message_queue->sendRequestSocket); + send_request = message_iterator.GetCurrent(); + } + while (send_request == NULL); + Check(send_request); + + // + //-------------------------------------------------------------------------- + // Attempt to send + //-------------------------------------------------------------------------- + // + Check(networkManager); + if ( + networkManager->SendMessageToNetnub( + send_request->messageToSend, + send_request->clientID, + message_queue->hostID + ) + ) + { + Unregister_Object(send_request); + delete send_request; + bufferSize--; + } +} diff --git a/MUNGA_L4/L4NET.H b/MUNGA_L4/L4NET.H new file mode 100644 index 0000000..607f778 --- /dev/null +++ b/MUNGA_L4/L4NET.H @@ -0,0 +1,424 @@ +//===========================================================================// +// File: l4net.hh // +// Project: MUNGA Brick: Network Manager // +// Contents: Interface specification for network brick // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- ---------------------------------------------------------- // +// 03/02/95 GAC Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994-1995, Virtual World Entertainment, Inc. // +// PROPRIETARY AND CONFIDENTIAL // +//===========================================================================// + +#pragma once + +#include "l4host.h" + +#include "..\munga\network.h" +#include "..\munga\hostmgr.h" + +//WinSock support :ADB 01/06/07 +//#include "..\munga\netnub.h" +#define NETNUB_TCP_OPEN 3 // Opens a TCP stream to another computer +#define NETNUB_TCP_LISTEN 4 // Queue's a TCP listen that we can accept a connection on +#define MULTIPLE_SEND_PACKET_MAX 10 +#define MAX_RECEIVE_DATA_SIZE 1600 +#include +#include + +class NotationFile; +class L4NetworkManager__ReceiveEggFileMessage; +class L4NetworkManager__AcknowledgeEggFileMessage; +class L4NetworkManager__HostConnectedMessage; +class L4NetworkManager__HostDisconnectedMessage; + +class NetNub +{ + friend int + Netnub_Open_File( + const char* filename, + int access, + unsigned int model + ); + friend int + Netnub_Write_File( + int handle, + void *buffer, + size_t length + ); + friend int + Netnub_Close_File(int handle); + +public: + //WinSock support :ADB 01/06/07 + //static void SendCommand(); +}; + +//extern Netcom_Ptr +// Net_Common_Ptr; + +//~~~~~~~~~~~~~~~~~~~~~ MessageQueue__SendRequest ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class MessageQueue__SendRequest: + public Plug +{ + friend class HostMessageBuffer__MessageQueue; + friend class L4NetworkManager__MessageBuffer; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + MessageQueue__SendRequest( + NetworkClient::ClientID client_ID, + Receiver::Message *message + ); + ~MessageQueue__SendRequest(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + NetworkClient::ClientID + clientID; + Receiver::Message + *messageToSend; +}; + +//~~~~~~~~~~~~~~~~~~~ HostMessageBuffer__MessageQueue ~~~~~~~~~~~~~~~~~~~~~~ + +class HostMessageBuffer__MessageQueue: + public Node +{ + friend class L4NetworkManager__MessageBuffer; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + HostMessageBuffer__MessageQueue(HostID host_ID); + ~HostMessageBuffer__MessageQueue(); + + Logical + TestInstance() const; + + void + AddSendRequest( + NetworkClient::ClientID client_ID, + Receiver::Message *message + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + HostID + hostID; + + typedef MessageQueue__SendRequest + SendRequest; + ChainOf + sendRequestSocket; +}; + +//~~~~~~~~~~~~~~~~~~ L4NetworkManager__MessageBuffer ~~~~~~~~~~~~~~~~~~~~~~~ + +class L4NetworkManager__MessageBuffer: + public Node +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Public methods +// +public: + L4NetworkManager__MessageBuffer(L4NetworkManager *network_manager); + ~L4NetworkManager__MessageBuffer(); + + Logical + TestInstance() const; + + Logical + IsEmpty(); + void + AddSendRequest( + HostID host_ID, + NetworkClient::ClientID client_ID, + Receiver::Message *message + ); + void + AttemptToSend(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + L4NetworkManager + *networkManager; + typedef HostMessageBuffer__MessageQueue + MessageQueue; + TableOf + messageQueueSocket; + IteratorPosition + currentQueueIndex; + CollectionSize + bufferSize; + #ifdef LAB_ONLY + CollectionSize + messageCount, + maxBufferSize; + #endif +}; + +inline Logical + L4NetworkManager__MessageBuffer::IsEmpty() +{ + Check(this); + return (bufferSize == 0); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ l4Network manager~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class L4NetworkManager: public NetworkManager +{ + friend class L4NetworkManager__MessageBuffer; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Constructor, Destructor, Testing + // +public: + L4NetworkManager(); + ~L4NetworkManager(); + + static Logical TestClass(); + Logical TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Network message methods +// +public: + void Send( + Message *what, + ClientID to, + HostID host_ID); + void ExclusiveBroadcast( + Message *what, + ClientID to); + + void StartConnecting(Mission *mission); + + Logical Shutdown(); + + Logical CheckBuffers(NetworkPacket *packet); + + void RemovePacket(NetworkPacket *packet); + + Logical ExecuteBackground(); + + void Marker(char *marker_text); + + void Mode(NetworkMode myMode); + + void CreateConsoleHost(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Network maintenance support +// +public: + int netPlayerCount; + + enum NetworkState + { + NormalState, + ConsoleOnly + }; + + enum NetworkStartupMode + { + SlaveMode, + MasterMode + }; + + bool CheckSocket(SOCKET socket, SOCKADDR_IN *remoteEndpoint); + bool ResolveAddress(CString host_name, SOCKADDR_IN *address); + //WinSock support :ADB 01/06/07 + NetworkAddress* GetMyAddress(); + + //WinSock support :ADB 01/06/07 + SOCKET OpenConnection( + int connection_type, // NETNUB_TCP_LISTEN or NETNUB_TCP_OPEN + int local_port, + int remote_port, + int internet_address); + void CloseConnection(SOCKET socket_ptr); // socket address from netnub (to close) + Logical GetNextMungaPacket( + NetworkPacket *network_packet, + HostManager::RemoteHostIterator* all_iterator); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + // + // Message IDs + // + enum + { + AcknowledgeEggFileMessageID = NetworkManager::NextMessageID, + HostConnectedMessageID, + HostDisconnectedMessageID, + NextMessageID + }; + + // + // Message types + // + typedef L4NetworkManager__AcknowledgeEggFileMessage + AcknowledgeEggFileMessage; + typedef L4NetworkManager__HostConnectedMessage + HostConnectedMessage; + typedef L4NetworkManager__HostDisconnectedMessage + HostDisconnectedMessage; + // + // Message table + // + static const HandlerEntry MessageHandlerEntries[]; + + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void ReceiveEggFileMessageHandler( + ReceiveEggFileMessage *EggMessage); + void AcknowledgeEggFileMessageHandler( + AcknowledgeEggFileMessage *AcknowledgeEgg); + void HostConnectedMessageHandler( + HostConnectedMessage *HostConnected); + void HostDisconnectedMessageHandler( + HostDisconnectedMessage *ConsoleDisconnect); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private methods +// +private: + typedef ChainOf + DroppedMessageHostSocket; + typedef ChainIteratorOf + DroppedMessageHostIterator; + + Logical + SendMessageToNetnub( + Message *message, + ClientID client_ID, + HostID host_ID + ); + void + SendBatchedMessageToNetnub( + Message *message, + ClientID client, + DroppedMessageHostSocket *dropped_message_host_socket + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private Data +// +private: + int + numberOfMungaHostsConnected, + numberOfConsoleHostsConnected, + remoteHostCount; + NetworkStartupMode networkStartupMode; + Logical eggAcknowledged; + NetworkState currentNetworkState; + L4Host *myConsoleHost; + HostID nextOpenHostID; + IteratorPosition lastHostIteratorPosition; + + typedef L4NetworkManager__MessageBuffer + MessageBuffer; + MessageBuffer + messageBuffer; + + //WinSock Support + WSADATA* wsaData; + //hostent* thisHost; + addrinfo* thisHost; + SOCKET gameListenerSocket; + SOCKET consoleListenerSocket; +}; + +//~~~~~~~~~~~~~~~~~~~~~~ L4NetworkManager inlines ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager__AcknowledgeEggFileMessage +// This message is sent back to the console to acknowledge receipt of the +// egg, it indicates this computer has established all it's connections and +// the console can procede with the next host +// +class L4NetworkManager__AcknowledgeEggFileMessage: + public NetworkManager::Message +{ +public: + L4NetworkManager__AcknowledgeEggFileMessage(): + NetworkManager::Message( + L4NetworkManager::AcknowledgeEggFileMessageID, + sizeof(L4NetworkManager__AcknowledgeEggFileMessage) + ){} +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager__HostConnectedMessage +// This message is generated internally by CheckBuffers and indicates that +// a host has connected up to us. This is an INTERNAL message only and is +// not ment to be sent on the network. +class L4NetworkManager__HostConnectedMessage : + public NetworkManager::Message +{ +public: + L4NetworkManager__HostConnectedMessage(HostID host_id, const SOCKADDR_IN &network_address, unsigned long stream_pointer) : + NetworkManager::Message(L4NetworkManager::HostConnectedMessageID, sizeof(L4NetworkManager__HostConnectedMessage)), + hostID(host_id), + networkAddress(network_address), + streamPointer(stream_pointer) + { + } + + HostID hostID; + SOCKADDR_IN networkAddress; + unsigned long streamPointer; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// L4NetworkManager__HostDisconnectedMessage +// The console is expected to send us this message if it disconnects from us +// for any reason. This allows the local host to setup the internal state +// so the game will auto start even if the console can't stay connected to us +// for some reason (for example, the console simulator in the game code can't +// connect to more than one host at once). +// !!! CheckBuffers should poll the connection state of all the streams and +// generate this message automatically whenever a host drops off the net. +// !!! HACK At the moment this message is always treated as if it came from +// the console host, so it should only be sent down the console stream. +// +class L4NetworkManager__HostDisconnectedMessage : + public NetworkManager::Message +{ +public: + L4NetworkManager__HostDisconnectedMessage(HostID host_id, unsigned long stream_pointer) : + NetworkManager::Message(L4NetworkManager::HostDisconnectedMessageID, sizeof(L4NetworkManager__HostDisconnectedMessage)), + hostID(host_id), + streamPointer(stream_pointer) + { + } + + HostID hostID; + unsigned long streamPointer; +}; \ No newline at end of file diff --git a/MUNGA_L4/L4PARTICLES.cpp b/MUNGA_L4/L4PARTICLES.cpp new file mode 100644 index 0000000..599cdc4 --- /dev/null +++ b/MUNGA_L4/L4PARTICLES.cpp @@ -0,0 +1,528 @@ +#include "l4particles.h" +#include "../munga/time.h" + +LPDIRECT3DDEVICE9 ParticleEngine::mDevice = NULL; +PARTICLE_EFFECT ParticleEngine::mInstalledEffects[MAX_PARTICLE_EFFECTS]; +LPDIRECT3DTEXTURE9 ParticleEngine::mParticleTexture = NULL; + +bool ParticleEngine::mActiveParticles = false; +LPDIRECT3DVERTEXBUFFER9 ParticleEngine::mVertBuffer = NULL; + +Particle *ParticleEngine::mParticlesHead = NULL; +Particle *ParticleEngine::mParticlesTail = NULL; +long ParticleEngine::mTotalParticleCount = 0; +long ParticleEngine::mMaxParticleCount = 8192; + +int compare(const Particle *a, const Particle *b, const D3DXMATRIX *view_matrix) +{ + D3DXVECTOR3 aVec(a->mX, a->mY, a->mZ); + D3DXVECTOR3 bVec(b->mX, b->mY, b->mZ); + + D3DXVec3TransformCoord(&aVec, &aVec, view_matrix); + D3DXVec3TransformCoord(&bVec, &bVec, view_matrix); + + float aDist = aVec.x * aVec.x + aVec.y * aVec.y + aVec.z * aVec.z; + float bDist = bVec.x * bVec.x + bVec.y * bVec.y + bVec.z * bVec.z; + + // if both particles are within a certain distance from + // each other then we'll sort them by effect instead of + // distance so that they will be grouped together when + // rendering + //if (abs(bDist - aDist) < EFFECT_GROUPING_EPSILON) + // return b->mEffect->id - a->mEffect->id; + //else + return (int)(bDist - aDist); +} + +void mergesort(Particle **headPtr, Particle **tailPtr, const D3DXMATRIX *view_matrix) +{ + Particle *list = *headPtr; + + if (!list) + { + (*tailPtr) = NULL; + return; + } + + Particle *p, *q, *e, *tail, *oldhead; + int insize, nmerges, psize, qsize, i; + + insize = 1; + + while (1) + { + p = list; + oldhead = list; + list = NULL; + tail = NULL; + + nmerges = 0; // count number of merges we do in this pass + + while (p) + { + nmerges++; // there exists a merge to be done + // step 'insize' places along from p + q = p; + psize = 0; + for (i=0; iNext(); + if (!q) + break; + } + + // if q hasn't fallen off end, we have two lists to merge + qsize = insize; + + // now we have two lists; merge them + while (psize > 0 || (qsize > 0 && q)) + { + // decide whether next element of merge comes from p or q + if (psize == 0) + { + // p is empty; e must come from q + e = q; + q = q->Next(); + qsize--; + } + else if (qsize == 0 || !q) + { + // q is empty; e must come from p + e = p; + p = p->Next(); + psize--; + } + else if (compare(p, q, view_matrix) <= 0) + { + // first elements of p is lower (or same); + // e must come from p + e = p; + p = p->Next(); + psize--; + } + else + { + // first element of q is lower; e must come from q + e = q; + q = q->Next(); + qsize--; + } + + // add the next element to the merged list + if (tail) + tail->mNextParticle = e; + else + list = e; + e->mPrevParticle = tail; + tail = e; + } + + // now p has stepped 'insize' places along, and q has too + p = q; + } + + tail->mNextParticle = NULL; + + // if we have done only one merge, we're finished + if (nmerges <= 1) // allow for nmerges == 0, the empty list case + { + (*headPtr) = list; + (*tailPtr) = tail; + return; + } + + // otherwise repeat, merging lists twice the size + insize *= 2; + } +} + +Particle::Particle(PARTICLE_EFFECT *effect) +{ + mEffect = effect; + mAge = 0.0f; + mX = 0.0f; + mY = 0.0f; + mZ = 0.0f; + mColor.argb = D3DCOLOR_ARGB(0xFF, 0xFF, 0x00, 0x00); + memset(&mVelocity, 0, sizeof(mVelocity)); + memset(&mAcceleration, 0, sizeof(mAcceleration)); +} + +void Particle::Execute(Scalar dT) +{ + if (!mEffect) + return; + + if (IsAlive()) + { + mX += mVelocity.x * dT; + mY += mVelocity.y * dT; + mZ += mVelocity.z * dT; + + mVelocity.x += mAcceleration.x * dT; + mVelocity.y += mAcceleration.y * dT; + mVelocity.z += mAcceleration.z * dT; + + mAge += dT; + Scalar percentComplete = mAge / mEffect->fragLifetime; + COLOR_POINT *cp0 = NULL; + COLOR_POINT *cp1 = NULL; + for (COLOR_POINT *cp = mEffect->colors + COLOR_POINT_COUNT - 2; cp >= mEffect->colors; cp--) + { + if (cp->active && percentComplete >= cp->time) + { + cp0 = cp; + cp1 = cp + 1; + break; + } + } + + if (!cp0 || !cp1) + { + cp0 = mEffect->colors; + + if (COLOR_POINT_COUNT > 1) + { + cp1 = mEffect->colors + 1; + } else + { + cp1 = cp0; + } + } + + percentComplete = (percentComplete - cp0->time) / (cp1->time - cp0->time); + mColor.a = (unsigned char)(cp0->color.a + (cp1->color.a - cp0->color.a) * percentComplete); + mColor.r = (unsigned char)(cp0->color.r + (cp1->color.r - cp0->color.r) * percentComplete); + mColor.g = (unsigned char)(cp0->color.g + (cp1->color.g - cp0->color.g) * percentComplete); + mColor.b = (unsigned char)(cp0->color.b + (cp1->color.b - cp0->color.b) * percentComplete); + } +} + +ParticleEmitter::ParticleEmitter() +: mEffect(NULL), + mActive(false), + mPosition(0.0f, 0.0f, 0.0f) +{ +} + +void ParticleEmitter::SetEffect(int effect) +{ + mEffect = &ParticleEngine::mInstalledEffects[effect]; +} + +void ParticleEmitter::Execute() +{ + if (mEffect == NULL) + return; + + // calculate the number of particles we're going to need + if (mActive) + { + bool fire = false; + if (mEffect->id >= 1000) + { + // this is an independant effect + static Scalar lastEmitted = (Scalar)Now(); + Scalar now = (Scalar)Now(); + + INDIE_EFFECT *indieEffect = (INDIE_EFFECT*)mEffect; + if ((now - lastEmitted) >= indieEffect->releasePeriod) + { + lastEmitted = now; + fire = true; + } + if ((now - mActivated) >= indieEffect->duration) + mActive = false; + } + else + { + fire = true; + mActive = false; + } + + if (fire) + { + for (int i = 0; i < mEffect->fragCount; ++i) + ParticleEngine::CreateParticle(mPosition, mEffect); + } + } +} + +void ParticleEngine::Destroy() +{ + mVertBuffer->Release(); + mParticleTexture->Release(); +} + +void ParticleEngine::Initialize(LPDIRECT3DDEVICE9 device) +{ + mDevice = device; + memset(mInstalledEffects, 0, sizeof(mInstalledEffects)); + + ParticleEngine::mMaxParticleCount = atoi(getenv("MAXPARTICLES")); + + // create the vertex buffer that will store the four vertices we need for the billboards + mDevice->CreateVertexBuffer(ParticleEngine::mMaxParticleCount * 6 * sizeof(L4BASICVERTEX), + D3DUSAGE_DYNAMIC, + L4BASICVERTEX_FVF, + D3DPOOL_DEFAULT, + &mVertBuffer, + NULL); + + D3DXCreateTextureFromFile(mDevice, L"VIDEO\\particles.png", &mParticleTexture); +} + +void ParticleEngine::InstallEffect(int effectNumber, PARTICLE_EFFECT effect) +{ + mInstalledEffects[effectNumber] = effect; + mInstalledEffects[effectNumber].id = effectNumber; +} + +void ParticleEngine::CreateParticle(D3DXVECTOR3 position, PARTICLE_EFFECT *effect) +{ + if (effect == NULL || effect->fragCount <= 0) + return; + + Particle *p = new Particle(effect); + + // check to make sure we have room for this new particle + if (mTotalParticleCount + 1 >= ParticleEngine::mMaxParticleCount) + { + mTotalParticleCount--; + + // there isn't room for this particle so we'll delete the oldest particle + if (mParticlesHead == mParticlesTail) + { + delete mParticlesHead; + mParticlesHead = NULL; + mParticlesTail = NULL; + } + else + { + Particle *temp = mParticlesTail; + mParticlesTail = mParticlesTail->mPrevParticle; + mParticlesTail->mNextParticle = NULL; + delete temp; + } + } + + // insert the new particle into the linked list + if (mParticlesHead) + mParticlesHead->mPrevParticle = p; + p->mPrevParticle = NULL; + p->mNextParticle = mParticlesHead; + mParticlesHead = p; + if (!mParticlesTail) + mParticlesTail = p; + + mTotalParticleCount++; + + // now initialize all the particle data based on the effect + p->mX = position.x + ((float)rand() * 2.0f / RAND_MAX - 1.0f) * effect->varianceX; + p->mY = position.y + ((float)rand() * 2.0f / RAND_MAX - 1.0f) * effect->varianceY; + p->mZ = position.z + ((float)rand() * 2.0f / RAND_MAX - 1.0f) * effect->varianceZ; + + D3DXVECTOR3 vec( + (float)rand() * 2.0f / RAND_MAX - 1.0f, + (float)rand() * 2.0f / RAND_MAX - 1.0f, + (float)rand() * 2.0f / RAND_MAX - 1.0f); + + D3DXVec3Normalize(&vec, &vec); + + p->mVelocity.x = vec.x * effect->velocity; + p->mVelocity.y = vec.y * effect->velocity; + p->mVelocity.z = vec.z * effect->velocity; + + p->mAcceleration.x = 0.0f; + p->mAcceleration.y = effect->gravity; + p->mAcceleration.z = 0.0f; + + // generate a random rotation amount in radians + float centerX = effect->textureBounds.left + (effect->textureBounds.right - effect->textureBounds.left) / 2.0f; + float centerY = effect->textureBounds.top + (effect->textureBounds.bottom - effect->textureBounds.top) / 2.0f; + D3DXVECTOR2 rotCenter(centerX, centerY); + D3DXMatrixTransformation2D(&p->mTextureTransform, NULL, 1, NULL, &rotCenter, ((float)rand() / RAND_MAX) * 2.0f * D3DX_PI, NULL); + + p->mColor.argb = (effect->colors[0].active ? effect->colors[0].color.argb : 0); +} + +int ParticleEngine::BuildParticleVertices(const Particle *p, L4BASICVERTEX *verts, D3DXMATRIX *inverse_view_matrix) +{ + D3DXMATRIX rotation; + PARTICLE_EFFECT *effect = p->mEffect; + + inverse_view_matrix->_41 = p->mX; + inverse_view_matrix->_42 = p->mY; + inverse_view_matrix->_43 = p->mZ; + + float fragSize = effect->fragSize; + D3DXVECTOR3 vector3s[] = + { + D3DXVECTOR3(-fragSize, fragSize, 0.0f), // upper left + D3DXVECTOR3( fragSize, -fragSize, 0.0f), // lower right + D3DXVECTOR3(-fragSize, -fragSize, 0.0f), // lower left + + D3DXVECTOR3(-fragSize, fragSize, 0.0f), // upper left + D3DXVECTOR3( fragSize, fragSize, 0.0f), // upper right + D3DXVECTOR3( fragSize, -fragSize, 0.0f) // lower right + }; + + D3DXVECTOR2 vector2s[] = + { + D3DXVECTOR2(effect->textureBounds.left, effect->textureBounds.top), // upper left + D3DXVECTOR2(effect->textureBounds.right, effect->textureBounds.bottom), // lower right + D3DXVECTOR2(effect->textureBounds.left, effect->textureBounds.bottom), // lower left + + D3DXVECTOR2(effect->textureBounds.left, effect->textureBounds.top), // upper left + D3DXVECTOR2(effect->textureBounds.right, effect->textureBounds.top), // upper right + D3DXVECTOR2(effect->textureBounds.right, effect->textureBounds.bottom) // lower right + }; + + D3DXVECTOR3 normal, inNormal(0.0f, 0.0f, 1.0f); + D3DXVec3TransformCoord(&normal, &inNormal, inverse_view_matrix); + + int count = (sizeof(vector3s) / sizeof(D3DXVECTOR3)); + for (int i=0; irotate) + D3DXVec2TransformCoord(&outVec2, &vector2s[i], &p->mTextureTransform); + else + outVec2 = vector2s[i]; + + verts[i].u = outVec2.x; + verts[i].v = outVec2.y; + + verts[i].color = p->mColor.argb; + } + + return count; +} + +void ParticleEngine::ExecuteParticles(const D3DXMATRIX *view_matrix, Scalar timeSlice) +{ + // if we don't have a device or we have no particles, early exit + if (!mDevice || mTotalParticleCount <= 0) + return; // we can't run without having been initialized with a device + + // first we need to execute all the particles to update their positions, color, etc. + for (Particle *p = mParticlesHead; p;) + { + if (p->IsAlive()) + { + p->Execute(timeSlice); + + p = p->mNextParticle; + } + else + { + // remove from the list + if (p->mPrevParticle) + p->mPrevParticle->mNextParticle = p->mNextParticle; + if (p->mNextParticle) + p->mNextParticle->mPrevParticle = p->mPrevParticle; + + // time to kill the particle + if (p == mParticlesHead) + { + mParticlesHead = p->mNextParticle; + } + if (p == mParticlesTail) + { + mParticlesTail = p->mPrevParticle; + } + + Particle *temp = p; + p = p->mNextParticle; + + mTotalParticleCount--; + delete temp; + } + } + + // now we're going to sort the particle list based on distance to the camera + mergesort(&mParticlesHead, &mParticlesTail, view_matrix); + + //Scalar beforeBuild = (Scalar)Now(); + D3DXMATRIX inverse_view_matrix; + D3DXMatrixInverse(&inverse_view_matrix, NULL, view_matrix); + + // and finally, we'll build the vertex list to send to Direct3D + L4BASICVERTEX *vertBuffer = NULL; + mVertBuffer->Lock(0, mTotalParticleCount * sizeof(L4BASICVERTEX), (void**)&vertBuffer, D3DLOCK_DISCARD); + + int actualParticles = 0; + for (Particle *p = mParticlesHead; p; p = p->mNextParticle) + { + vertBuffer += BuildParticleVertices(p, vertBuffer, &inverse_view_matrix); + actualParticles++; + } + + mVertBuffer->Unlock(); + + //Scalar afterBuild = (Scalar)Now(); + + //afterBuild = afterBuild; +} + +void ParticleEngine::RenderParticles(const D3DXMATRIX *view_matrix, Scalar timeSlice) +{ + // we always have to execute otherwise our timing + // variables get all screwed up when we don't run for a while + ExecuteParticles(view_matrix, timeSlice); + + if (!mDevice || mTotalParticleCount <= 0) + return; + + // setup stages for particle's texture + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_DIFFUSE); + + mDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); + mDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_COLOR1); + + mDevice->SetTexture(0, mParticleTexture); + + mDevice->SetTextureStageState(0, D3DTSS_TEXTURETRANSFORMFLAGS, D3DTTFF_DISABLE); + + mDevice->SetFVF(L4BASICVERTEX_FVF); + mDevice->SetStreamSource(0, mVertBuffer, 0, sizeof(L4BASICVERTEX)); + + //DWORD wrap_u, wrap_v; + //mDevice->GetSamplerState(0, D3DSAMP_ADDRESSU, &wrap_u); + //mDevice->GetSamplerState(0, D3DSAMP_ADDRESSV, &wrap_v); + + //mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, D3DTADDRESS_WRAP); + //mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, D3DTADDRESS_WRAP); + + D3DXMATRIX world_matrix; + D3DXMatrixIdentity(&world_matrix); + mDevice->SetTransform(D3DTS_WORLD, &world_matrix); + + mDevice->DrawPrimitive(D3DPT_TRIANGLELIST, 0, mTotalParticleCount * 2); + + mDevice->SetRenderState(D3DRS_EMISSIVEMATERIALSOURCE, D3DMCS_MATERIAL); + + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR); + + //mDevice->SetSamplerState(0, D3DSAMP_ADDRESSU, wrap_u); + //mDevice->SetSamplerState(0, D3DSAMP_ADDRESSV, wrap_v); +} \ No newline at end of file diff --git a/MUNGA_L4/L4PARTICLES.h b/MUNGA_L4/L4PARTICLES.h new file mode 100644 index 0000000..49fe90c --- /dev/null +++ b/MUNGA_L4/L4PARTICLES.h @@ -0,0 +1,159 @@ +#pragma once + +#include +#include +#include +#include "../munga/time.h" +#include "l4d3d.h" + +#define COLOR_POINT_COUNT 10 +#define MAX_PARTICLE_EFFECTS 32 +#define EFFECT_GROUPING_EPSILON 1.0f + +#define L4BASICVERTEX_FVF (D3DFVF_XYZ | D3DFVF_TEX1 | D3DFVF_DIFFUSE | D3DFVF_NORMAL) + +struct L4BASICVERTEX +{ + float x, y, z; + float nx, ny, nz; + DWORD color; + float u, v; +}; + +union L4COLOR +{ + DWORD argb; + struct + { + unsigned char b; + unsigned char g; + unsigned char r; + unsigned char a; + }; +}; + +struct COLOR_POINT +{ + bool active; + Scalar time; + L4COLOR color; +}; + +struct PARTICLE_EFFECT +{ + int id; + struct + { + float left, top, right, bottom; + } textureBounds; + bool rotate; + float fragSize; + float velocity; + COLOR_POINT colors[COLOR_POINT_COUNT]; + float gravity; + float varianceX; + float varianceY; + float varianceZ; + int fragCount; + float fragLifetime; + float maxRepeat; +}; + +struct INDIE_EFFECT : public PARTICLE_EFFECT +{ + int maxIssue; + float releasePeriod; + float duration; +}; + +class ParticleEngine; +class ParticleEmitter; + +class Particle +{ + friend class ParticleEngine; + +public: + Particle(PARTICLE_EFFECT *effect); + + void Execute(Scalar dT); + inline bool IsAlive() { return (mEffect && ( mAge < mEffect->fragLifetime)); } + inline Particle *Next() { return mNextParticle; } + inline Particle *Prev() { return mPrevParticle; } + +private: + float mX, mY, mZ; + L4COLOR mColor; + D3DXVECTOR3 mVelocity; + D3DXVECTOR3 mAcceleration; + D3DXMATRIX mTextureTransform; + + PARTICLE_EFFECT *mEffect; + Scalar mAge; + + Particle *mNextParticle; + Particle *mPrevParticle; + + friend int compare(const Particle *, const Particle *, const D3DXMATRIX *); + friend void mergesort(Particle **, Particle **, const D3DXMATRIX *); +}; + +class ParticleEmitter +{ +public: + ParticleEmitter(); + + bool IsActive() { return mActive; } + + void SetEffect(int effect); + void SetEffect(INDIE_EFFECT *effect) { mEffect = effect; } + float GetMaxRepeat() { return mEffect->maxRepeat; } + void Execute(); + void Fire() { mActive = true; } + void Start() + { + mActive = true; + mActivated = (Scalar)Now(); + } + void SetPosition(float x, float y, float z) + { + mPosition.x = x; + mPosition.y = y; + mPosition.z = z; + } + +private: + PARTICLE_EFFECT *mEffect; + bool mActive; + Scalar mActivated; + D3DXVECTOR3 mPosition; +}; + +class ParticleEngine +{ + friend class ParticleEmitter; + +public: + static void Destroy(); + static void Initialize(LPDIRECT3DDEVICE9 device); + static void InstallEffect(int effectNumber, PARTICLE_EFFECT effect); + static void RenderParticles(const D3DXMATRIX *view_matrix, Scalar timeSlice); + +private: + static void CreateParticle(D3DXVECTOR3 position, PARTICLE_EFFECT *effect); + static int BuildParticleVertices(const Particle *p, L4BASICVERTEX *verts, D3DXMATRIX *view_matrix); + static void ExecuteParticles(const D3DXMATRIX *view_matrix, Scalar timeSlice); + + static LPDIRECT3DDEVICE9 mDevice; + + static PARTICLE_EFFECT mInstalledEffects[]; + static LPDIRECT3DTEXTURE9 mParticleTexture; + + static bool mActiveParticles; + static LPDIRECT3DVERTEXBUFFER9 mVertBuffer; + + static Particle *mParticlesHead; + static Particle *mParticlesTail; + static long mTotalParticleCount; + static long mMaxParticleCount; +}; \ No newline at end of file diff --git a/MUNGA_L4/L4PCSPAK.cpp b/MUNGA_L4/L4PCSPAK.cpp new file mode 100644 index 0000000..144e85d --- /dev/null +++ b/MUNGA_L4/L4PCSPAK.cpp @@ -0,0 +1,950 @@ +#include "mungal4.h" +#include +#include "L4SERIAL.h" +#include "L4PCSPAK.h" +#include + +//Win32 Serial support: ADB 02/10/07 +//------------------------------------------------ +// COM_INIT macro +// Initializes COMBUF structure +//------------------------------------------------ +void PCSerialPacket::COM_INIT(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + buffer->head = 0; + buffer->tempHead = 0; + buffer->tempTail = 0; + buffer->tail = 0; + + buffer->count = 0; + buffer->tempIn = 0; + buffer->tempOut = 0; + ReleaseMutex(hMutex); +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_PUT_AL macro +// 'Temporarily' puts character in AL into COMBUF +//------------------------------------------------ +void PCSerialPacket::COM_PUT_AL(PCSerPackBuf* buffer, BYTE al) +{ + WaitForSingleObject(hMutex, INFINITE); + if(buffer->tempIn > COMBUFSIZE) + { +#if DIE_ON_OVERFLOW + DISABLE_AND_DIE("Serial Packet Buffer Overflow!"); +#else + ReleaseMutex(hMutex); + return; +#endif + } + + buffer->tempIn++; //increment 'tempIn' count + + buffer->data[buffer->tempHead] = al; //write the data + + buffer->tempHead++; //bump 'tempHead' + buffer->tempHead &= (COMBUFSIZE-1); //limit it + ReleaseMutex(hMutex); +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_RESTORE_IN macro +// Discards characters 'temporarily' placed in COMBUF +//------------------------------------------------ +void PCSerialPacket::COM_RESTORE_IN(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + buffer->tempIn = 0; //clear the 'tempIn' count + buffer->tempHead = buffer->head; //restore 'tempHead' index + ReleaseMutex(hMutex); +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_ACCEPT_IN macro +// Accepts characters 'temporarily' placed in COMBUF +//------------------------------------------------ +void PCSerialPacket::COM_ACCEPT_IN(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + buffer->count += buffer->tempIn; //add to current count + buffer->tempIn = 0; + + buffer->head = buffer->tempHead; //set the new head offset + ReleaseMutex(hMutex); +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_GET_AL macro +// 'Temporarily' gets character into AL from COMBUF +//------------------------------------------------ +int PCSerialPacket::COM_GET_AL(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + buffer->tempOut++; //inc 'tempOut' count + + int al = buffer->data[buffer->tempTail]; //read the data + + buffer->tempTail ++; //bump 'tempTail' + buffer->tempTail &= (COMBUFSIZE-1); //limit it + + ReleaseMutex(hMutex); + return al; +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_RESTORE_OUT macro +// Restores characters 'temporarily' removed from COMBUF +//------------------------------------------------ +void PCSerialPacket::COM_RESTORE_OUT(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + buffer->tempOut = 0; //clear the 'tempOut' count + + buffer->tempTail = buffer->tail; //restore 'tempTail' index + ReleaseMutex(hMutex); +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_ACCEPT_OUT macro +// Discards characters 'temporarily' removed from COMBUF +//------------------------------------------------ +void PCSerialPacket::COM_ACCEPT_OUT(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + buffer->count -= buffer->tempOut; //subtract from current count + buffer->tempOut = 0; //clear 'tempOut' count + + buffer->tail = buffer->tempTail; //set the new tail offset + ReleaseMutex(hMutex); +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_EAT_PACKET macro +// Discards entire buffer item from COMBUF +//------------------------------------------------ +void PCSerialPacket::COM_EAT_PACKET(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + BYTE command = buffer->data[buffer->tail]; //read the packet command byte + + command &= 0x07; //remove the MSB + int length = this->rxLengthPtr[command]; //convert packet command to length + length++; //include the command byte + buffer->count -= length; //subtract from count + + buffer->tail += length; //move the tail + buffer->tail &= (COMBUFSIZE-1); //limit it + buffer->tempTail = buffer->tail; //set the new tempTail index + + buffer->tempOut = 0; + ReleaseMutex(hMutex); +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_SPACE_IN macro +// Returns input bytes available in COMBUF +//------------------------------------------------ +int PCSerialPacket::COM_SPACE_IN(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + int available = COMBUFSIZE; + available -= buffer->count; + available -= buffer->tempIn; + ReleaseMutex(hMutex); + return available; +} + +//Win32 Serial support: ADB 02/13/07 +//------------------------------------------------ +// COM_SPACE_OUT macro +// Returns output bytes available in COMBUF +//------------------------------------------------ +int PCSerialPacket::COM_SPACE_OUT(PCSerPackBuf* buffer) +{ + WaitForSingleObject(hMutex, INFINITE); + int output = buffer->count; + output -= buffer->tempOut; + ReleaseMutex(hMutex); + return output; +} + +//Win32 Serial support: ADB 06/23/07 +PCSerialPacket::PCSerialPacket() +{ +} + +void PCSerialPacket::ShutdownRxThread() +{ + //Win32 Serial support: ADB 06/23/07 + enabled = false; + bThreadAbort = TRUE; + if (overlapSend.hEvent != INVALID_HANDLE_VALUE) + { + CloseHandle(overlapSend.hEvent); + overlapSend.hEvent = INVALID_HANDLE_VALUE; + } + if(hRxAbortEvent != INVALID_HANDLE_VALUE) + { + SetEvent(hRxAbortEvent); + CloseHandle(hRxAbortEvent); + hRxAbortEvent = INVALID_HANDLE_VALUE; + } + if(hRxThread != INVALID_HANDLE_VALUE) + { + WaitForSingleObject(hRxThread, INFINITE); + CloseHandle(hRxThread); + hRxThread = INVALID_HANDLE_VALUE; + } + if(hMutex != INVALID_HANDLE_VALUE) + { + CloseHandle(hMutex); + hMutex = INVALID_HANDLE_VALUE; + } + if(hComm != INVALID_HANDLE_VALUE) + { + CloseHandle(hComm); + hComm = INVALID_HANDLE_VALUE; + } +} + +PCSerialPacket::~PCSerialPacket() +{ + if (this == NULL) + { + std::cout << "~PCSerialPacket() has been passed a NULL pointer\n" << std::flush; + } + else + { + ShutdownRxThread(); + } +} + +//Win32 Serial support: ADB 01/15/07 +// Only call Initialize(...) ONCE during the lifetime of the object! +int PCSerialPacket::Initialize(WORD rate, WORD format, const char* port, BYTE* rxLengths, BYTE rxCount, BYTE* txLengths, BYTE txCount) +{ + //;------------------------------------------------------------------------- + //; PCSPAKInit() + //; Constructor for serial packet driver interface + //;------------------------------------------------------------------------- + //; Enter: + //; init_this = pointer to object + //; init_port = address of serial port + //; init_irq_num = interrupt number + //; init_rx_len = pointer to (byte) receive length table + //; init_tx_len = pointer to (byte) transmit length table + //;------------------------------------------------------------------------- + //; Returns: + //; 1 if ok, + //; -1 if IRQ's all used, + //; -2 if DPMI error, + //; -3 if really weird bogus error, + //; else IIR value + //;------------------------------------------------------------------------- + + //DWORD return_status = 0; + + //;-------------------------------------------------------------- + //; Clear the data buffers + //;-------------------------------------------------------------- + COM_INIT(&rxBuf); //assumes esi points to object + COM_INIT(&txBuf); //assumes esi points to object + //;-------------------------------------------------------------- + //; Initialize values + //;-------------------------------------------------------------- + enabled = 0; + txHoldOff = 0; + txReply = 0; + rxFlags = 0; + Error = 0; + intDataPtr = 0; + + historyIndex = 0; + + txState = TX_IDLE_STATE; //initialize to idle state + rxState = RX_IDLE_STATE; //initialize to idle state + + + txLengthPtr = txLengths; //set dialect transmit table pointer + txMaximum = txCount; //set maximum dialect transmit index + + rxLengthPtr = rxLengths; //set dialect receive table pointer + rxMaximum = rxCount; //set maximum dialect receive index + + hComm = INVALID_HANDLE_VALUE; + hRxAbortEvent = INVALID_HANDLE_VALUE; + hRxThread = INVALID_HANDLE_VALUE; + hMutex = INVALID_HANDLE_VALUE; + bThreadAbort = FALSE; + overlapSend.hEvent = INVALID_HANDLE_VALUE; + + hComm = InitSerialPort(rate, format, port, true); + if(hComm == INVALID_HANDLE_VALUE) + { + enabled = 0; + DWORD err = GetLastError(); + DEBUG_STREAM << "ERROR: InitSerialPort() failed [GetLastError() = " << GetLastError() << "]!\n" << std::flush; + return PCSPAKWin32Err; + } + enabled = 1; + + //Setup multi-threading for rx thread + hMutex = CreateMutex(NULL, false, NULL); + if(hMutex == NULL) + { + DEBUG_STREAM << "ERROR: CreateMutex() failed [GetLastError() = " << GetLastError() << "]!\n" << std::flush; + enabled = 0; + return PCSPAKWin32Err; + } + + if(!SetCommMask(hComm, EV_RXCHAR)) + { + DEBUG_STREAM << "ERROR: SetCommMask() failed [GetLastError() = " << GetLastError() << "]!\n" << std::flush; + enabled = 0; + return PCSPAKWin32Err; + } + hRxAbortEvent = CreateEvent(NULL, FALSE, FALSE, NULL); + + hRxThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)(&RxThreadProc), this, NULL, NULL); + if(hRxThread == NULL) + { + DEBUG_STREAM << "ERROR: CreateThread() failed [GetLastError() = " << GetLastError() << "]!\n" << std::flush; + enabled = 0; + return PCSPAKWin32Err; + } + SetThreadPriority(hRxThread, THREAD_PRIORITY_TIME_CRITICAL); + + overlapSend.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + overlapSend.Internal = 0; + overlapSend.InternalHigh = 0; + overlapSend.Offset = 0; + overlapSend.OffsetHigh = 0; + + return PCSPAKInitOk; + } + +//Win32 Serial support: ADB 01/15/07 +Logical PCSerialPacket::TestInstance() +{ + //return PCSPAKTestInstance(this); + return 1; +} + +//Win32 Serial support: ADB 02/10/07 +//------------------------------------------------------------------------- +// PCSPAKReceive() +// Returns packet if available +//------------------------------------------------------------------------- +// Enter: +// BYTE *destPtr = pointer to 128-byte destination buffer +//------------------------------------------------------------------------- +// Returns: +// int packetSize (or zero if no packet available) +//------------------------------------------------------------------------- +int PCSerialPacket::ReceivePacket(BYTE *destPtr) // returns len (zero if none) +{ + if(!enabled) + return 0; + + //-------------------------------------------------------------- + // Check character count: non-zero indicates entire packet + //-------------------------------------------------------------- + if(rxBuf.count == 0) + return 0; + + //-------------------------------------------------------------- + // Get buffer length + //-------------------------------------------------------------- + BYTE c = COM_GET_AL(&rxBuf); //get character into al + //-------------------------------------------------------------- + // Verify first char is a valid command character + //-------------------------------------------------------------- + if((c & 0x80) == 0) + { + DISABLE_AND_DIE("Character was not a command character!"); + return 0; + } + + BYTE *overflow = destPtr + COMBUFSIZE - 1; + + *destPtr = c; //save it + destPtr++; + BYTE length = rxLengthPtr[c & 0x7F]; //translate into length + int count = length; //save in edx + count++; //return at least one character + assert(length < 256); + //-------------------------------------------------------------- + // Transfer data from buffer + //-------------------------------------------------------------- + do + { + c = COM_GET_AL(&rxBuf); //get character into al + *destPtr = c; //save it + destPtr++; + assert(destPtr < overflow); + }while(--length > 0); + + COM_ACCEPT_OUT(&rxBuf); //accept all 'taken' characters + + return count; +} + +//Win32 Serial Support +//------------------------------------------------------------------------- +// PCSPAKSend() +// Transmits packet +//------------------------------------------------------------------------- +// Enter: +// BYTE *sp_src = pointer to (up to) 128-byte source buffer +//------------------------------------------------------------------------- +// Returns: +// void +//------------------------------------------------------------------------- +void PCSerialPacket::SendPacket(BYTE *srcPtr) //sends packet +{ + //-------------------------------------------------------------- + // Wait for sufficient room + //-------------------------------------------------------------- + if(!enabled) //if disabled, don't even try + return; + + BYTE cmd = *srcPtr; //get the command byte + cmd &= 0x7F; //remove MSB + int length = txLengthPtr[cmd]; //get the length in al + length++; //add one for command byte + + //This code has been replaced for your sanity: + //while(COM_SPACE_IN(&txBuf) < length) //enough room? + // DISABLE_AND_DIE("Not enough space in serial packet buffer"); + + ////-------------------------------------------------------------- + //// Copy data into tx buffer + ////-------------------------------------------------------------- + //do + //{ + // COM_PUT_AL(&txBuf, *srcPtr); //place it in the buffer + // srcPtr++; //increment the source pointer + //} + //while(--length > 0); + + //COM_ACCEPT_IN(&txBuf); //accept all 'placed' characters + // + ////call StartSending ;attempt to start tx interrupt + + //Sane code: + BYTE *buffer = new BYTE[length + 1];//add one for the checksum + memcpy(&buffer[0], srcPtr, length);//copy packet + buffer[length] = 0;//initialize checksum + for(int b=0; brxMaximum<<"\n"; + //initialize com port event + OVERLAPPED o; + o.hEvent = CreateEvent(NULL, TRUE, FALSE, NULL); + o.Internal = 0; + o.InternalHigh = 0; + o.Offset = 0; + o.OffsetHigh = 0; + + HANDLE events[] = {pcPack->hRxAbortEvent, o.hEvent}; + + while(true) + { + DWORD dwEvent; + //DEBUG_STREAM<<"Waiting for Data...\n"<hComm, &dwEvent, &o); + if(WaitForMultipleObjects(2, &events[0], FALSE, INFINITE) == WAIT_OBJECT_0)//indicates that the abort event was triggered + if(pcPack->bThreadAbort)//if we really are supposed to abort + break;//then abort + + //perform read + BYTE buffer[COMBUFSIZE]; + memset(&buffer, 0, COMBUFSIZE); + DWORD bytesRead = 0; + //DEBUG_STREAM << "Reading Data\n" << std::flush; + ReadFile(pcPack->hComm, &buffer[0], COMBUFSIZE, NULL, &o); + GetOverlappedResult(pcPack->hComm, &o, &bytesRead, TRUE); + + //process data + //DEBUG_STREAM<<"Received "<rxFlags |= RX_ACK_BIT;//yes, flag for transmitter + goto recvDone; +rcNotAck: + //------------------------------ + // NAK + //------------------------------ + if((unsigned int)buffer[b] != NAK_CHAR)//NAK character? + goto rcNotNak;//no + pcPack->rxFlags |= RX_NAK_BIT;//yes, flag for transmitter + goto recvDone; +rcNotNak: +rcNotSpecial: + //-------------------------------------------------------------- + // Process state-dependent characters + //-------------------------------------------------------------- + if(pcPack->rxState != 0)//test the state + goto rxActive;//non-zero, so active + //-------------------------------------------------------------- + // Receiver "idle" state + // Wait for command character + //-------------------------------------------------------------- + if(((unsigned int)buffer[b] & 0x0080) != 0)//is it a control character? + goto rxIdleSpecial;//yes, process it + + pcPack->Error |= RX_SEQ_ERR;//Not expecting data, so error. + goto recvDone; +rxIdleSpecial: + if((unsigned int)buffer[b] == RESTART_CHAR)//restart? + goto recvDone;//yes, discard it + + unsigned int bx = pcPack->COM_SPACE_IN(&pcPack->rxBuf);//get remaining space + if(bx != 0)//zero? + goto rxIdleSpace;//no, continue + DEBUG_STREAM<<"RX Buffer Full!"<Error |= RX_COM_ERR;//error. Set flag. + goto recvDone; +rxIdleSpace: + unsigned int ah = (unsigned int)buffer[b];//move to ah for testing + ah &= 0x007F;//remove MSB + if(ah < pcPack->rxMaximum)//legitimate command? + goto rxIdleOk;//yes, continue + + DEBUG_STREAM<<"RX Unknown Command!"<Error |= RX_COM_ERR;//no. + goto recvDone; +rxIdleOk: + pcPack->COM_PUT_AL(&pcPack->rxBuf, buffer[b]);//save command character in buffer + pcPack->rxChecksum = buffer[b];//start a new receive checksum + + pcPack->rxCount = pcPack->rxLengthPtr[ah] + 1;//save the length + + pcPack->rxState = RX_ACTIVE_STATE;//change to "active" state + goto recvDone; + + //-------------------------------------------------------------- + // Receiver "active" state + // Place N characters into buffer, test checksum, and reply + //-------------------------------------------------------------- +rxActive: + if(((unsigned int)buffer[b] & 0x0080) == 0)//control character? + goto rxActiveData;//no, therefore data + + pcPack->Error |= RX_SEQ_ERR;//yes, error. Set error flag + pcPack->COM_RESTORE_IN(&pcPack->rxBuf);//Discard received data + //------------------------------ + // Process control char + //------------------------------ + if((unsigned int)buffer[b] == RESTART_CHAR)//restart character? + goto rxActiveAbandon;//yes, abandon received data + + pcPack->txReply = NAK_CHAR;//error, tell transmitter to send NAK + goto rxActiveReply; + //------------------------------ + // Process data + //------------------------------ +rxActiveData: + pcPack->rxCount--;//check the receive count + if(pcPack->rxCount <= 0) + goto rxActiveCheck;//if end of message, process checksum + //------------------------------ + // Enough space in buffer? + //------------------------------ + bx = pcPack->COM_SPACE_IN(&pcPack->rxBuf);//get remaining space + + if(bx != 0)//zero? + goto rxActiveSpace;//no, continue + + DEBUG_STREAM<<"RX Buffer Full @ 2!"<Error |= RX_COM_ERR;//error. Set flag. + pcPack->COM_RESTORE_IN(&pcPack->rxBuf);//Discard received data + goto rxActiveAbandon;//give up on packet + +rxActiveSpace: + //------------------------------ + // Save data in buffer + //------------------------------ + pcPack->rxChecksum += buffer[b];//update the checksum + pcPack->COM_PUT_AL(&pcPack->rxBuf, buffer[b]);//save the character + goto recvDone; + //------------------------------ + // Test checksum + //------------------------------ +rxActiveCheck: + unsigned int bl = pcPack->rxChecksum;//get the checksum + bl &= 0x007F;//remove MSB + if(bl == buffer[b])//checksum OK? + goto rxActiveOk;//yes! + //------------------------------ + // Buffer error + //------------------------------ + pcPack->Error |= RX_BAD_CHECKSUM;//error. Set flag. + pcPack->COM_RESTORE_IN(&pcPack->rxBuf);//Discard received data + pcPack->txReply = NAK_CHAR;//tell transmitter to send NAK + TransmitCommChar(pcPack->hComm, (char)NAK_CHAR); + goto rxActiveReply; + //------------------------------ + // Buffer OK + //------------------------------ +rxActiveOk: + pcPack->COM_ACCEPT_IN(&pcPack->rxBuf);//accept the received data + pcPack->txReply = ACK_CHAR;//tell transmitter to send ACK + TransmitCommChar(pcPack->hComm, (char)ACK_CHAR); +rxActiveReply: + //call StartSending ;restart transmitter if needed + //------------------------------ + // Return to inactive state + //------------------------------ +rxActiveAbandon: + pcPack->rxState = RX_IDLE_STATE; +recvDone: + ; + } + //DEBUG_STREAM<<"}\n"< +#include + +#include "..\munga\style.h" +#include "L4SERIAL.H" + +class PCSerialPacket; +class PCSerialPacketScanner; + +//Win32 Serial support: ADB 02/13/07 +#define DIE_ON_ERROR 1 +#define DIE_ON_OVERFLOW 1 +#define WATCH_IRQ 1 +#define THE_WAY_IT_WAS 0 +//=========================================================================== +// Equates +//=========================================================================== +#ifdef DIE_ON_ERROR + #define DISABLE_AND_DIE(errorString) throw errorString +#else + #define DISABLE_AND_DIE +#endif + +//Win32 Serial support: ADB 02/10/07 +//TX +#define TX_IDLE_STATE 0 +#define TX_RESTART_STATE 1 +#define TX_BODY_STATE 2 +#define TX_WAIT_STATE 3 +//RX +#define RX_IDLE_STATE 0 +#define RX_ACTIVE_STATE 1 + +// +// Lower eight bits reserved for UART status +// +#define ERR_INIT 0x0100 +#define TX_EARLY_ERR 0x0200 +#define TX_ABANDON 0x0400 +#define TX_RESTART 0x0800 +#define TX_NAK 0x1000 +#define RX_SEQ_ERR 0x2000 +#define RX_BAD_CHECKSUM 0x4000 +#define RX_COM_ERR 0x8000 + +#define TXMAXRESET 3 +#define TXMAXERROR 3 +#define TXMAXIDLE 4 + +#define MAX_COMMAND_CHAR 0xFB //largest command code allowed +#define ACK_CHAR 0xFC +#define NAK_CHAR 0xFD +#define RESTART_CHAR 0xFE +#define IDLE_CHAR 0xFF + +#define RX_ACK_BIT 0x0001 +#define RX_NAK_BIT 0x0002 + +enum +{ + //Win32 Serial support: ADB 02/10/07 + //PCSPAKInitErrDPMI = -2, + //PCSPAKInitErrAlloc = -1, + PCSPAKWin32Err = -1, + PCSPAKInitOk = 0 +}; + +//Win32 Serial support: ADB 01/15/07 +DWORD WINAPI RxThreadProc(LPVOID lpParameter); + +//Win32 Serial support: ADB 02/13/07 +#define COMBUFSIZE 2048 + +// This is for INTERNAL USE only (reflects structure in .ASM file) +struct PCSerPackBuf +{ + Word head, tail, tempHead, tempTail, count, tempIn, tempOut; + //Win32 Serial support: ADB 02/13/07 + BYTE data[COMBUFSIZE]; // was 256 before 7-13-95 cpb + // WARNING: make ABSOLUTELY SURE this matches pcspak.asm +}; + +class PCSerialPacket +{ + friend class PCSerialPacketScanner; + friend DWORD WINAPI RxThreadProc(LPVOID lpParameter); + +private: + + //Win32 Serial support: ADB 02/10/07 + //------------------------------------------------ + // COM_INIT macro + // Initializes COMBUF structure + //------------------------------------------------ + void COM_INIT(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_PUT_AL macro + // 'Temporarily' puts character in AL into COMBUF + //------------------------------------------------ + void COM_PUT_AL(PCSerPackBuf* buffer, BYTE al); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_RESTORE_IN macro + // Discards characters 'temporarily' placed in COMBUF + //------------------------------------------------ + void COM_RESTORE_IN(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_ACCEPT_IN macro + // Accepts characters 'temporarily' placed in COMBUF + //------------------------------------------------ + void COM_ACCEPT_IN(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_GET_AL macro + // 'Temporarily' gets character into AL from COMBUF + //------------------------------------------------ + int COM_GET_AL(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_RESTORE_OUT macro + // Restores characters 'temporarily' removed from COMBUF + //------------------------------------------------ + void COM_RESTORE_OUT(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_ACCEPT_OUT macro + // Discards characters 'temporarily' removed from COMBUF + //------------------------------------------------ + void COM_ACCEPT_OUT(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_EAT_PACKET macro + // Discards entire buffer item from COMBUF + //------------------------------------------------ + void COM_EAT_PACKET(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_SPACE_IN macro + // Returns input bytes available in COMBUF + //------------------------------------------------ + int COM_SPACE_IN(PCSerPackBuf* buffer); + + //Win32 Serial support: ADB 02/13/07 + //------------------------------------------------ + // COM_SPACE_OUT macro + // Returns output bytes available in COMBUF + //------------------------------------------------ + int COM_SPACE_OUT(PCSerPackBuf* buffer); + +public: + //Win32 Serial support: ADB 06/23/07 + PCSerialPacket(); + + void ShutdownRxThread(); + + ~PCSerialPacket(); + + //Win32 Serial support: ADB 01/15/07 + // Only call Initialize(...) ONCE during the lifetime of the object! + int Initialize(WORD rate, WORD format, const char* port, BYTE* rxLengths, BYTE rxCount, BYTE* txLengths, BYTE txCount); + + //Win32 Serial support: ADB 01/15/07 + Logical TestInstance(); + + //Win32 Serial support: ADB 02/10/07 + //------------------------------------------------------------------------- + // PCSPAKReceive() + // Returns packet if available + //------------------------------------------------------------------------- + // Enter: + // BYTE *destPtr = pointer to 128-byte destination buffer + //------------------------------------------------------------------------- + // Returns: + // int packetSize (or zero if no packet available) + //------------------------------------------------------------------------- + int ReceivePacket(BYTE *destPtr); + + //Win32 Serial Support + //------------------------------------------------------------------------- + // PCSPAKSend() + // Transmits packet + //------------------------------------------------------------------------- + // Enter: + // BYTE *sp_src = pointer to (up to) 128-byte source buffer + //------------------------------------------------------------------------- + // Returns: + // void + //------------------------------------------------------------------------- + void SendPacket(BYTE *srcPtr); + + // error bits returned by PCSerialPacket::Errors() + enum ErrorBits { + overrunError=0x0002, + parityError=0x0004, + framingError=0x0008, + breakDetect=0x0010, + initError=0x0100, + txEarlyReply=0x0200, + txAbandonPacket=0x0400, + txRestart=0x0800, + txNakReply=0x1000, + rxSequenceError=0x2000, + rxChecksumError=0x4000, + rxCommandError=0x8000 + }; + + //Win32 Serial support: ADB 01/15/07 + int ReceiveQueueCount(); + + //Win32 Serial support: ADB 01/15/07 + int TransmitQueueCount(); + + //Win32 Serial Support: ADB 02/25/2007 + void SetDTR(Logical on); + + //Win32 Serial support: ADB 01/15/2007 + //------------------------------------------------------------------------- + // PCSPAKActive() + // Returns transmitter 'active' state (=0 when all transmission is done). + //------------------------------------------------------------------------- + // This function is now deprecated. + int IsActive(); + + //Win32 Serial support: ADB 01/15/07 + Word Errors();// returns error value, clears it + +protected: + //Win32 Serial support: ADB 01/15/07 + //Word portBase; + HANDLE hComm; + WORD Error; //error word + + //Win32 Serial support: ADB 02/10/07 + WORD historyIndex; + + BYTE enabled; + BYTE txHoldOff; + BYTE txReply; //reply char + BYTE txState; //status + BYTE txCount; //maximum dialect transmit index + BYTE txResetCount; //counts down each time a NAK is recieved until 0 + BYTE txErrorCount; //counts down each time the RIO errors out + BYTE txIdleCount; + BYTE txChecksum; + BYTE txMaximum; + + BYTE rxFlags; //receive flags (ack/nak) + BYTE rxState; + BYTE rxCount; //maximum dialect receive index + BYTE rxChecksum; + BYTE rxMaximum; + + BYTE* txLengthPtr; //dialect transmit table pointer + BYTE* rxLengthPtr; //dialect receive table pointer + + LWord intDataPtr; //pointer to current working packet +// LWord hackCount; //WGR previously missing: seen in pcspak.asm + + PCSerPackBuf txBuf; + PCSerPackBuf rxBuf; + + //Win32 Serial support: ADB 06/23/07 + HANDLE hMutex; + HANDLE hRxThread; + HANDLE hRxAbortEvent; + BOOL bThreadAbort; + OVERLAPPED overlapSend; +}; \ No newline at end of file diff --git a/MUNGA_L4/L4PLASMA.cpp b/MUNGA_L4/L4PLASMA.cpp new file mode 100644 index 0000000..0a58dae --- /dev/null +++ b/MUNGA_L4/L4PLASMA.cpp @@ -0,0 +1,363 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4plasma.h" +#include "..\munga\time.h" + +//######################################################################## +//############################# PlasmaDisplay ############################ +//######################################################################## +PlasmaDisplay::PlasmaDisplay( + //Win32 Serial Support: ADB 02/24/2007 + //Word port, + const char* port + //Word int_num +): + Video8BitBuffered(plasmaWidth, plasmaHeight), + forceAll(False) +{ + //------------------------------------ + // Create serial interface + //------------------------------------ + //Win32 Serial Support: ADB 02/24/2007 + //pc_serial = new PCSerial(PCS_9600, PCS_N81, port, int_num); + pc_serial = new PCSerial(PCS_9600, PCS_N81, port); + if (pc_serial != NULL) + { + Register_Object(pc_serial); + pc_serial->FlowControlEnable(False); + //------------------------------------ + // Turn off the cursor + //------------------------------------ + static char + cursorOffString[] = { 27 /*ESC*/, 'G', (char) 0x00 }; + + pc_serial->SendString(cursorOffString, 3); + } + //------------------------------------ + // Clear update flag array + //------------------------------------ + currentTransferLine = 0; + updateInProgress = False; + + for(int i=0; iDrawFilledRectangle(0, 0xFF, GraphicsDisplay::Replace, 0, 0, this->width - 1, this->height - 1); + this->Update(True); + + Check_Fpu(); +} + +PlasmaDisplay::~PlasmaDisplay() +{ + if (pc_serial != NULL) + { + //--------------------------------------------------------------------- + // Flush data to plasma display + //--------------------------------------------------------------------- + this->DrawFilledRectangle(0, 0xFF, GraphicsDisplay::Replace, 0, 0, this->width - 1, this->height - 1); + this->Update(True); + + WaitForUpdate(); + + // This odd sequence of allocation, setting, and adding is necessary: + // if you try to combine them, the compiler gets confused as to which + // method to invoke for 'Now()'. + Time + then; + then = Now(); + then += 5.0f; + while (Now() < then) + { + //--------------------------------------------------- + // Drop out of loop when ALL data has been sent + //--------------------------------------------------- + if (pc_serial->CanDraw() <= 0) + { + if (!pc_serial->IsActive()) + { + break; + } + } + } + //--------------------------------------------------------------------- + // Delete the serial interface + //--------------------------------------------------------------------- + Unregister_Object(pc_serial); + delete pc_serial; + } + Check_Fpu(); +} + +Logical + PlasmaDisplay::TestInstance() const +{ + return Video8BitBuffered::TestInstance(); +} + +void + PlasmaDisplay::ShowInstance(char *indent) +{ + std::cout << indent << "Plasma:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + Video8BitBuffered::ShowInstance(temp); + Check_Fpu(); +} + + +int + sendLine( + char *transfer_pointer, + int line_number, + Byte *source_pointer, + int source_width + ) +{ + int + x, + index; + Byte + byte, + byte_bit; + //-------------------------------------------- + // Send header + //-------------------------------------------- + transfer_pointer[0] = (char) 27; // ascii ESC + transfer_pointer[1] = 'P'; // graphics command + transfer_pointer[2] = (char) 0; // screen number + transfer_pointer[3] = (char) line_number; // Y position + transfer_pointer[4] = (char) 0; // X BYTE position + transfer_pointer[5] = (char) ((source_width+7)>>3); // width in bytes + transfer_pointer[6] = (char) 1; + + transfer_pointer += 7; + + //pc_serial->SendString(graphics, 7); + //-------------------------------------------- + // Send data + //-------------------------------------------- + byte = 0; + byte_bit = 0x80; + index = 0; + for(x=0; x>= 1; + // + // If entire byte collected, send it + // + if (byte_bit == 0) + { + Verify(index < sizeof(graphics)); + *transfer_pointer = byte; + transfer_pointer++; + index++; + byte = 0; + byte_bit = 0x80; + } + } + // + // End of source line: send remaining bits + // + if (byte_bit != 0x80) + { + transfer_pointer[index++] = byte; + } + // + // Send graphics data + // + //pc_serial->SendString(graphics, index); + Check_Fpu(); + + return index + 7; +} + +void + PlasmaDisplay::Scan(Logical forceAll) +{ + Word + changed_line = (Word) forceAll, + *changed_line_pointer = changedLine; + char + *update_pointer=updateFlag; + int + y; + + for(y=0; yCanDraw()) + { + //----------------------------------------- + // Accumulate changed lines + //----------------------------------------- + forceAll |= force_all; + + if (currentTransferLine == 0) + { + Scan(forceAll); + forceAll = False; + } + //----------------------------------------- + // Send only if the buffer is empty + //----------------------------------------- + total_count = plasmaHeight; + transfer_count = 7; + int transfer_length = 32 * transfer_count; + char *transfer_data = new char[transfer_length]; + char *transfer_pointer = transfer_data; + int total_transfer_count = transfer_count; + int total_transfer_length = 0; + + startWhile = Now(); + + int i = 0; + + while(transfer_count>0) + { + //----------------------------------------- + // Transfer a line if it's ready + //----------------------------------------- + allStarts[i] = Now(); + if (updateFlag[currentTransferLine]) + { + //----------------------------------------- + // Decrement the 'transfer count' + //----------------------------------------- + --transfer_count; + //----------------------------------------- + // Clear the 'update' flag + //----------------------------------------- + updateFlag[currentTransferLine] = 0; + //----------------------------------------- + // Send the line data to the display + //----------------------------------------- + startSendLine = Now(); + int length = sendLine(transfer_pointer, currentTransferLine, + pixelBuffer->Data.MapPointer + + (pixelBuffer->Data.Size.x * currentTransferLine), + pixelBuffer->Data.Size.x + ); + endSendLine = Now(); + + transfer_pointer += length; + total_transfer_length += length; + } + + + allEnds[i] = Now(); + //----------------------------------------- + // Increment currentTransferLine + //----------------------------------------- + if (++currentTransferLine >= plasmaHeight) + { + currentTransferLine = 0; + } + //----------------------------------------- + // Reset to top if all lines scanned + //----------------------------------------- + if (--total_count < 0) + { + currentTransferLine = 0; // reset to top line + updateInProgress = False; + result = False; // False == 'all data sent' + break; + } + + i++; + } + + endWhile = Now(); + + dataSendStart = Now(); + if (total_transfer_length > 0) + { + this->pc_serial->SendString(transfer_data, total_transfer_length); + } + dataSendEnd = Now(); + + __totalTransferLength = total_transfer_length; + + delete [] transfer_data; + } + Check_Fpu(); + + Time end = Now(); + + if (end.ticks - start.ticks > 100) + { + start = end; + } + + return result; +} + +void + PlasmaDisplay::WaitForUpdate() +{ + Time + end_time; + + end_time = Now(); + end_time += 5.0f; // We'll wait this many seconds to update the display- + + while (updateInProgress) + { + Update(False); + + if (Now() >= end_time) + { + break; + } + } + Check_Fpu(); +} diff --git a/MUNGA_L4/L4PLASMA.h b/MUNGA_L4/L4PLASMA.h new file mode 100644 index 0000000..d434922 --- /dev/null +++ b/MUNGA_L4/L4PLASMA.h @@ -0,0 +1,51 @@ +#pragma once + +#include "l4vb8.h" +#include "l4serial.h" + +//######################################################################## +//################################ Plasma ################################ +//######################################################################## +class PlasmaDisplay : + public Video8BitBuffered +{ +public: + enum + { + plasmaWidth=128, + plasmaHeight=32 + }; + + //Win32 Serial Support: ADB 02/24/2007 + //PlasmaDisplay(Word port, Word int_num); + PlasmaDisplay::PlasmaDisplay(const char* port); + + ~PlasmaDisplay(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + Logical + Update(Logical forceall); + + void + WaitForUpdate(); + +protected: + void + Scan(Logical forceall); + + Logical + forceAll, + updateInProgress; + + PCSerial + *pc_serial; + int + currentTransferLine; + char + updateFlag[32]; +}; diff --git a/MUNGA_L4/L4RIO.cpp b/MUNGA_L4/L4RIO.cpp new file mode 100644 index 0000000..2f2bc4a --- /dev/null +++ b/MUNGA_L4/L4RIO.cpp @@ -0,0 +1,1674 @@ +#include "mungal4.h" +#include "..\munga\controls.h" +#pragma hdrstop + +#include "l4rio.h" +#include "l4ctrl.h" + +#if defined(TRACE_RIO_RECEIVE_PACKET) + BitTrace RIO_Receive_Packet("RIO Receive Packet"); +#endif + +#if defined(TRACE_RIO_SEND_PACKET) + BitTrace RIO_Send_Packet("RIO Send Packet); +#endif + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +#define default_deadband_value 0.03 + +static Byte RIOLengths[] = { + 0, // CheckRequest + 0, // VersionRequest + 0, // AnalogRequest + 1, // ResetRequest + 2, // LampRequest + 2, // CheckReply + 2, // VersionReply + 10, // AnalogReply + 1, // ButtonPressed + 1, // ButtonReleased + 2, // KeyPressed + 2, // KeyReleased + 1 // TestModeChange +}; + +Byte RIO::reply_check_string[] = {RIO::CheckReply, 3, 2 }; +Byte RIO::reply_version_string[] = {RIO::VersionReply, 1, 23}; +Byte RIO::reply_button_press_string[] = {RIO::ButtonPressed, 22}; +Byte RIO::reply_button_release_string[]= {RIO::ButtonReleased, 22}; +Byte RIO::reply_key_press_string[] = {RIO::KeyPressed, 0, 4}; +Byte RIO::reply_key_release_string[] = {RIO::KeyReleased, 0, 4}; +Byte RIO::reply_test_enter_string[] = {RIO::TestModeChange, 1}; +Byte RIO::reply_test_exit_string[] = {RIO::TestModeChange, 0}; +Byte RIO::reply_analog_string[] = +{ + RIO::AnalogReply, 1, 0, 2, 0, 3, 0, 4, 0, 5, 0 +}; + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Utilities ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +int + CombinePair(Byte low_value, Byte high_value) +{ + int result; + + result = ((int) (low_value & 0x7F)) | (((int) high_value) << 7); + if (result & 0x2000) + { + result |= ~0x3FFF; + } + Check_Fpu(); + return result; +} + + +void + BoardError(NotationFile *notation_file, char *type, int position) +{ + Check(notation_file); + Check_Pointer(type); + + char + where[40]; + + sprintf(where, "%s@Slot=%d:Address=%d", type, position >> 3, position & 7); + notation_file->AppendEntry("RIOBoardErrors", "error", where); + Check_Fpu(); +} + +//########################################################################### +//############################ Joystick classes ############################# +//########################################################################### +const char *FilterChannel::highName = "high"; +const char *FilterChannel::centerName = "center"; +const char *FilterChannel::lowName = "low"; +const char *FilterChannel::joystickXName = "JoystickX"; +const char *FilterChannel::joystickYName = "JoystickY"; +const char *FilterChannel::throttleName = "Throttle"; +const char *FilterChannel::leftPedalName = "LeftPedal"; +const char *FilterChannel::rightPedalName = "RightPedal"; + +FilterChannel::FilterChannel(): + average(5,0) +{ + valuesFromFile = False; + previousValue = 0; + polarity = unipolar; + mode = unaligned; + deadbandScalar = default_deadband_value; + + lowerDeadband = 0; + upperDeadband = 0; + + Check_Fpu(); +} + +FilterChannel::FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_max +): + average(5,0) +{ + valuesFromFile = True; + previousValue = 0; + polarity = unipolar; + mode = normal; + deadbandScalar = default_deadband_value; + + pageName = page_name; + min = default_min; + max = default_max; + //------------------------------------------- + // Attempt to read calibration values from + // the notation file. If the values don't + // exist, then create them from the defaults. + //------------------------------------------- + if (init_file->GetEntry(pageName, highName, &max) == 0) + { + init_file->SetEntry(pageName, highName, default_max); + } + + if (init_file->GetEntry(pageName, lowName, &min) == 0) + { + init_file->SetEntry(pageName, lowName, default_min); + } + + center = (max-min)/2; + + Check_Fpu(); +} + +FilterChannel::FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_center, int default_max +): + average(5,0) +{ + valuesFromFile = True; + previousValue = 0; + polarity = bipolar; + mode = normal; + deadbandScalar = default_deadband_value; + + pageName = page_name; + min = default_min; + center = default_center; + max = default_max; + + //------------------------------------------- + // Attempt to read calibration values from + // the notation file. If the values don't + // exist, then create them from the defaults. + //------------------------------------------- + + if (init_file->GetEntry(pageName, highName, &max) == 0) + { + init_file->SetEntry(pageName, highName, default_max); + } + + if (init_file->GetEntry(pageName, centerName, ¢er) == 0) + { + init_file->SetEntry(pageName, centerName, default_center); + } + + if (init_file->GetEntry(pageName, lowName, &min) == 0) + { + init_file->SetEntry(pageName, lowName, default_min); + } + + CalculateDeadBands(); + + Check_Fpu(); +} + +FilterChannel::~FilterChannel() +{ + Check(this); + Check_Fpu(); +} + +void + FilterChannel::SetPolarity(PolarMode newPolarity) +{ + Check(this); + polarity = newPolarity; + + // HACK - filterchannel must be realigned when changing to bipolar! + + Check_Fpu(); +} + +void + FilterChannel::SetDeadBand(Scalar dead_band) +{ + Check(this); + + deadbandScalar = fabs(dead_band); + //--------------------------------------------------------- + // Recalculate deadbands and ranges if needed + //--------------------------------------------------------- + if (mode == normal) + { + CalculateDeadBands(); + } + Check_Fpu(); +} + +void + FilterChannel::BeginAlignment() +{ + Check(this); + //--------------------------------------------------------- + // Set bogus min/max, force update + //--------------------------------------------------------- + mode = unaligned; + min = 10000; + max = -10000; + Check_Fpu(); +} + +void + FilterChannel::EndAlignment(NotationFile *init_file) +{ + Check(this); + //--------------------------------------------------------- + // Save the most recent value as the center + //--------------------------------------------------------- + center = previousValue; + //------------------------------------------------------------ + // If channel was never adjusted, synthesize reasonable values + //------------------------------------------------------------ + // I don't trust abs(): saw weirdness. + int + delta = max-min; + if (delta < 0) + { + delta = -delta; + } + + if (delta < 10) + { + if (polarity == bipolar) + { + min = center-100; + max = center+100; + } + else + { + min = 0; + max = 100; + } + } + else + { + int + setback = delta/33; // move the edges in by 3% + + max -= setback; + min += setback; + } + //--------------------------------------------------------- + // Save the new values + //--------------------------------------------------------- + if (valuesFromFile) + { + if (init_file != NULL) + { + init_file->SetEntry(pageName, highName, max); + init_file->SetEntry(pageName, lowName, min); + + if (polarity == bipolar) + { + init_file->SetEntry(pageName, centerName, center); + } + } + } + //--------------------------------------------------------- + // Calculate real deadband values + //--------------------------------------------------------- + CalculateDeadBands(); + //--------------------------------------------------------- + // Go to normal mode + //--------------------------------------------------------- + mode = normal; + + Check_Fpu(); +} + +Scalar + FilterChannel::Update(int value) +{ + Check(this); + + Scalar + result = 0.0; + + previousValue = value; + + //--------------------------------------------------------- + // Generate average, use for min/max determination + //--------------------------------------------------------- + average.Add(value); + { + int + the_average = average.CalculateOlympicAverage(); + + if (the_average < min) { min = the_average; } + if (the_average > max) { max = the_average; } + } + //--------------------------------------------------------- + // Perform position calculations + //--------------------------------------------------------- + switch (polarity) + { + case unipolar: + { + //--------------------------------------------------------- + // Subtract 'min' from current value + //--------------------------------------------------------- + value -= min; + //--------------------------------------------------------- + // Subtract deadband value + //--------------------------------------------------------- + int + deadband_adjustment = (int) ((max-min)*deadbandScalar); + + value -= deadband_adjustment; + if (value > 0) + { + int + adjusted_maximum = max-deadband_adjustment; + + if (adjusted_maximum > 0) + { + result = ((Scalar)value)/adjusted_maximum; + } + } + } + break; + + case bipolar: + if (mode == unaligned) + { + //--------------------------------------------------------- + // Use 1/2 (max-min) as temporary center + //--------------------------------------------------------- + center = (max-min) >> 1; + //--------------------------------------------------------- + // Set temporary deadband values + //--------------------------------------------------------- + upperDeadband = (int) ((max-min)*deadbandScalar); + lowerDeadband= upperDeadband; + } + //--------------------------------------------------------- + // Adjust for center + //--------------------------------------------------------- + value -= center; + //--------------------------------------------------------- + // Generate scaled results + //--------------------------------------------------------- + if (value < 0) + { + value += lowerDeadband; + if (value < 0) + { + if (lowerRange > 0) + { + if (value <= -lowerRange) + { + result = -1.0; + } + else + { + result = ((Scalar) value)/lowerRange; + } + } + } + } + else + { + value -= upperDeadband; + if (value > 0) + { + if (upperRange > 0) + { + if (value >= upperRange) + { + result = 1.0; + } + else + { + result = ((Scalar) value)/upperRange; + } + } + } + } + break; + } + //--------------------------------------------------------- + // Return result + //--------------------------------------------------------- + Check_Fpu(); + +# if defined(DEBUG) + DEBUG_STREAM << pageName << ":" << value << "=" << result << "\n"; +# endif + + return result; +} + +Logical + FilterChannel::TestInstance() const +{ + return True; +} + +void + FilterChannel::CalculateDeadBands() +{ + Check(this); + + lowerDeadband = (int) ((center-min)*deadbandScalar + .5); + lowerRange = center - (min+lowerDeadband); + + upperDeadband = (int) ((max-center)*deadbandScalar + .5); + upperRange = (max-upperDeadband) - center; + +# if defined(DEBUG) + DEBUG_STREAM << "pageName =" << pageName <<"\n"; + DEBUG_STREAM << "min =" << min <<"\n"; + DEBUG_STREAM << "center=" << center <<"\n"; + DEBUG_STREAM << "max= " << max <<"\n"; + DEBUG_STREAM << "lowerDeadband= " << lowerDeadband <<"\n"; + DEBUG_STREAM << "lowerRange = " << lowerRange <<"\n"; + DEBUG_STREAM << "upperDeadband= " << upperDeadband <<"\n"; + DEBUG_STREAM << "upperRange = " << upperRange <<"\n"; +# endif + + Check_Fpu(); +} + + +// ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Ranger ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +Ranger::Ranger( + const char *page_name, + int hardware_min, + int hardware_max, + Scalar deadband +){ + Check_Pointer(this); + + pageName = page_name; + hardwareMinimum = hardware_min; + hardwareMaximum = hardware_max; + + SetDeadBand(deadband); + //------------------------------------------------------------ + // We ASSUME that the control is at rest (center for joystick) + //------------------------------------------------------------ + ForceToZero(); + + Check_Fpu(); +} + +Ranger::~Ranger() +{ + Check(this); + Check_Fpu(); +} + +Logical + Ranger::TestInstance() const +{ + Check_Fpu(); + return True; +} + +void + Ranger::SetDeadBand(Scalar dead_band) +{ + Check(this); + + deadbandInteger = + (int)((hardwareMaximum - hardwareMinimum) * fabs(dead_band)); + + Check_Fpu(); +} + +void + Ranger::ForceToZero() +{ + Check(this); + sampledInputFlag = False; + Check_Fpu(); +} + +Scalar + Ranger::Update(int input) +{ + Check(this); + int + range; + Scalar + result = ((Scalar) 0); + + Verify(hardwareMaximum > hardwareMinimum); + //------------------------------------------------------------ + // Uncentered processing: slide offset to keep value + // within the proscribed range + //------------------------------------------------------------ + if (hardwareMinimum >= 0) // this designates an uncentered Ranger + { + //--------------------------------------------------------- + // Sample current input for offset value + //--------------------------------------------------------- + if (!sampledInputFlag) + { + sampledInputFlag = True; + + offset = -input; + //------------------------------------------ + // Initialize to reasonable values + //------------------------------------------ + highestInput = (hardwareMaximum*3)/4; + lowestInput = hardwareMinimum; + } + //------------------------------------------------------------ + // Add offset + //------------------------------------------------------------ + input += offset; + //------------------------------------------------------------ + // Slide offset if needed + //------------------------------------------------------------ + if (input > hardwareMaximum) + { + offset -= input-hardwareMaximum; + input = hardwareMaximum; + } + else if (input < hardwareMinimum) + { + offset -= input-hardwareMinimum; + input = hardwareMinimum; + } + //----------------------------------------------------------------- + // Keep track of limit (lowestValue will always be hardwareMinimum) + //----------------------------------------------------------------- + if (input > highestInput) + { + highestInput = input; + } + //------------------------------------------------------------ + // Generate scaled result + //------------------------------------------------------------ + input -= hardwareMinimum; // normalize to zero + + if (input > deadbandInteger) + { + range = highestInput - lowestInput - deadbandInteger; + + if (range > 0) + { + result = ((Scalar)(input-deadbandInteger))/(Scalar)range; + } + } + } + //------------------------------------------------------------ + // Centered processing: keep max, min of input to + // determine total range + //------------------------------------------------------------ + else + { + //--------------------------------------------------------- + // Sample current input for offset value + //--------------------------------------------------------- + if (!sampledInputFlag) + { + sampledInputFlag = True; + //------------------------------------------ + // Set offset such that this is the new zero + //------------------------------------------ + offset = -input; + //------------------------------------------ + // Initialize to reasonable values... + // ...add offset to reflect true limits + // that are available with this offset + //------------------------------------------ + // HardwareMinimum is known to be negative because of 'if' statement + Verify(hardwareMaximum > 0); + + highestInput = (hardwareMaximum*3)/4 + offset; + lowestInput = (hardwareMinimum*3)/4 + offset; + } + //------------------------------------------------------------ + // Adjust for offset + //------------------------------------------------------------ + input += offset; + + if (input > highestInput) + { + highestInput = input; + } + if (input < lowestInput) + { + lowestInput = input; + } + //--------------------------------------- + // Let's make sure before we continue... + //--------------------------------------- + Verify(highestInput >= lowestInput); + Verify(input <= highestInput); + Verify(input >= lowestInput); + //------------------------------------------------------------ + // Generate scaled result + //------------------------------------------------------------ + if (input < -deadbandInteger) + { + //--------------------------------------- + // Generate range + //--------------------------------------- + range = abs(lowestInput) - deadbandInteger; + //--------------------------------------- + // Generate scaled result + //--------------------------------------- + if (range > 0) + { + result = ((Scalar)(input+deadbandInteger))/(Scalar)range; + } + } + else if (input > deadbandInteger) + { + //--------------------------------------- + // Generate range + //--------------------------------------- + range = abs(highestInput) - deadbandInteger; + //--------------------------------------- + // Generate scaled result + //--------------------------------------- + if (range > 0) + { + result = ((Scalar)(input-deadbandInteger))/(Scalar)range; + } + } + } + + if (result > ((Scalar) 1.0)) + { + DEBUG_STREAM << + "Too high!" << + " input=" << input << " result=" << result << "\n" << + + pageName << + " offset=" << offset << + " lowestInput=" << lowestInput << + " highestInput=" << highestInput << + " deadbandInteger=" << deadbandInteger << + " range=" << range << + "\n"; + + result = ((Scalar) 1.0); +//Fail("Ranger::Update above 1.0"); + } + else if (result < ((Scalar)-1.0)) + { + DEBUG_STREAM << + "Too low!" << + " input=" << input << " result=" << result << "\n" << + + pageName << + " lowestInput=" << lowestInput << + " highestInput=" << highestInput << + " deadbandInteger=" << deadbandInteger << + " range=" << range << + "\n"; + + result = ((Scalar)-1.0); +//Fail("Ranger::Update below -1.0"); + } + + Verify(result <= ((Scalar) 1.0)); + Verify(result >= ((Scalar) -1.0)); + + Check_Fpu(); + return result; +} + +void + Ranger::Statistics(NotationFile *failure_file) +{ + Check(this); + Check(failure_file); + + int + range = highestInput - lowestInput, + hardware_range = hardwareMaximum - hardwareMinimum; + + Verify(hardware_range > 0); + + Scalar + range_percentage = ((Scalar) range)/hardware_range; + //--------------------------------- + // Report slippage + //--------------------------------- + if (range_percentage > (Scalar) 1.1) // allow 10% overrange + { + failure_file->SetEntry(pageName, "Overrange", range_percentage); + } + //--------------------------------- + // Report low range + //--------------------------------- + if (range_percentage < (Scalar) .50) + { + failure_file->SetEntry(pageName, "UnderRange", range_percentage); + } + Check_Fpu(); +} + +//######################################################################## +//############################### RIO #################################### +//######################################################################## + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//Win32 Serial support: ADB 02/13/07 +//RIO::RIO(Word port, Word intNum, Logical perform_tests): +RIO::RIO(const char* port, Logical perform_tests): + PCSerialPacket() +{ + Tell("RIO initialization: variables\n"); + Check_Pointer(this); + + // + //--------------------------------------------------------------------- + // Initialize values + //--------------------------------------------------------------------- + // + TestModeActive = 0; + + Throttle = (Scalar) 0; + LeftPedal = (Scalar) 0; + RightPedal = (Scalar) 0; + JoystickX = (Scalar) 0; + JoystickY = (Scalar) 0; + + remoteRetryCount = 0; + remoteAbandonCount = 0; + remoteFullBufferCount = 0; + lineErrorCount = 0; + overrunCount = 0; + abandonCount = 0; + operational = True; +// discardCount = 0; + + failureFile = NULL; + failureFileOpenCount = 0; + // + //--------------------------------------------------------------------- + // Clear error log + //--------------------------------------------------------------------- + // + OpenFailureFile(); + Check(failureFile); + failureFile->DeletePage("RIOBoardErrors"); + failureFile->DeletePage("RIODeadLamps"); + failureFile->DeletePage("RIOErrors"); + CloseFailureFile(); + // + //--------------------------------------------------------------------- + // Read value ranges from notation file, initialize rangers + // + // Order of integers is: minimum, maximum, end-zone-range, deadband + //--------------------------------------------------------------------- + // + { +// NotationFile +// stat_file((const char *) "RIO.INI"); + + leftPedalRanger = new Ranger("LeftPedal", 0, 470, .0); + Register_Object(leftPedalRanger); + + rightPedalRanger = new Ranger("RightPedal", 0, 470, .0); + Register_Object(rightPedalRanger); + + throttleRanger = new Ranger("Throttle", 0, 800, .05); + Register_Object(throttleRanger); + + joystickXRanger = new Ranger("JoystickX", -96, 96, .05); + Register_Object(joystickXRanger); + + joystickYRanger = new Ranger("JoystickY", -97, 108, .05); + Register_Object(joystickYRanger); + } + // + //--------------------------------------------------------------------- + // Start the PCSerialPacket + //--------------------------------------------------------------------- + // + //Win32 Serial support: ADB 02/13/07 + //int status = PCSerialPacket::Initialize( + // PCSP_9600, + // port, + // intNum, + // (Byte *) RIOLengths, + // 13, + // (Byte *) RIOLengths, + // 13 + // ); + int status = PCSerialPacket::Initialize(PCS_9600, PCS_N81, port, (BYTE*)RIOLengths, 13, (BYTE*)RIOLengths, 13); + + switch(status) + { + case PCSPAKInitOk: + // silent if OK + DEBUG_STREAM << "RIO successfully initialized!\n"; + break; + //Win32 Serial Support: ADB 02/24/2007 + //case PCSPAKInitErrDPMI: + // DEBUG_STREAM << "RIO::RIO DPMI error!\n"; + // break; + //case PCSPAKInitErrAlloc: + // DEBUG_STREAM << "RIO::RIO buffer allocation error!\n"; + // break; + case PCSPAKWin32Err: + DEBUG_STREAM << "RIO::RIO Win32 Serial Initalization error!\n"; + break; + default: + DEBUG_STREAM << "RIO::RIO unexpected init result=" << status << "!\n"; + break; + } + +#if 0 + extern Byte previousIMR, previousISR, previousIRR; + extern Byte middleIMR, middleISR, middleIRR; + extern Byte postIMR, postISR, postIRR; + extern Byte pcspakLSR, pcspakIER, pcspakIIR; + + DEBUG_STREAM << + hex << + "previousIMR=" << (int) (previousIMR & 0xFF) << + ", mid=" << (int) (middleIMR & 0xFF) << + ", post=" << (int) (postIMR & 0xFF) << "\n" << + + "previousISR=" << (int) (previousISR & 0xFF) << + ", mid=" << (int) (middleISR & 0xFF) << + ", post=" << (int) (postISR & 0xFF) << "\n" << + + "previousIRR=" << (int) (previousIRR & 0xFF) << + ", mid=" << (int) (middleIRR & 0xFF) << + ", post=" << (int) (postIRR & 0xFF) << "\n" << + + "pcspakLSR=" << (int) (pcspakLSR & 0xFF) << + ", pcspakIER=" << (int) (pcspakIER & 0xFF) << + ", pcspakIIR was=" << (int) (pcspakIIR & 0xFF) << "\n" << + dec; +#endif + + MajorRevision = 0xFF; + MinorRevision = 0xFF; + + if (perform_tests) + { + // + //--------------------------------------------------------------------- + // Reset remote I/O board + //--------------------------------------------------------------------- + // + Time + when; + int + bomb = 0; + + RIOEvent + dummy_event; + + Tell("RIO initialization: reset board\n"); + + // Reset RIO board + SetDTR(True); // Assert reset + when = Now(); + for(when += .1f; Now() < when; ); + + SetDTR(False); // Retract reset + when = Now(); + for(when += 1.0f; Now() < when; ); + + // + //--------------------------------------------------------------------- + // Wait for test mode to start (or bomb out) + //--------------------------------------------------------------------- + // + Tell("RIO initialization: check board\n"); + RequestCheck(); + + when = Now(); + when += 5.0f; + while (!TestModeActive) + { + if (Now() > when) + { + bomb = 1; + DEBUG_STREAM << "RIO never came back from check request!\n"; + break; + } + GetNextEvent(&dummy_event); + } + // + //--------------------------------------------------------------------- + // Wait for test mode to finish (or bomb out) + //--------------------------------------------------------------------- + // + if (!bomb) + { + when = Now(); + when += 5.0f; + while (TestModeActive) + { + if (Now() > when) + { + bomb = 1; + DEBUG_STREAM << "RIO never came back from test mode!\n"; + break; + } + GetNextEvent(&dummy_event); + } + } + // + //--------------------------------------------------------------------- + // Get version (or bomb out) + //--------------------------------------------------------------------- + // + + if (!bomb) + { + RequestVersion(); + when = Now(); + when += 5.0f; + while (MajorRevision == 0xFF) + { + if (Now() > when) + { + DEBUG_STREAM << "RIO never came back from version request!\n"; + break; + } + GetNextEvent(&dummy_event); + } + } + + if(!bomb) + { + DEBUG_STREAM<<"RIO initialization finished\n"; + } + else + { + DEBUG_STREAM<<"RIO initialization failed! Shutting Down Serial Port!\n"; + ShutdownRxThread(); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +extern int historyIndex; +extern Byte history[]; + +enum +{ + txFlag=1, + rxFlag=2, + eventFlag=3 +}; + +enum +{ + IRQ_EVENT=0, + IRQ_EVENT_RX=1, + IRQ_EVENT_TX=2, + IRQ_EVENT_MSR=3, + IRQ_EVENT_LSR=4, + IRQ_EVENT_BOGUS=5, + + TX_EVENT_RESTART=10, + TX_EVENT_ABANDON=11, + TX_EVENT_DONE=12, + TX_EVENT_ACK=13, + TX_EVENT_NAK=14, + TX_EVENT_EARLY=15, + TX_EVENT_EMPTY=16, + TX_EVENT_KICK=17, + + RX_EVENT_FULL=20, + RX_EVENT_NOT_CMD=21, + RX_EVENT_FULLBODY=22, + RX_EVENT_NAK=23, + RX_EVENT_CKSMERR=24, + RX_EVENT_OK=25 +}; + +RIO::~RIO() +{ + Check(this); + +#if 0 + //--------------------------------------------------------------------- + // Save serial history for debugging + //--------------------------------------------------------------------- + // If you enable this, set KEEP_HISTORY in PCSPAK.ASM to '1' as well. + // Otherwise you will be viewing nonexistent history data. + const char + *commandName[13] = + { + "CheckReq", //=0x80 + "VersionReq", + "AnalogReq", + "ResetReq", + "LampReq", + "CheckReply", + "VersionReply", + "AnalogReply", + "ButtonPressed", + "ButtonReleased", + "KeyPressed", + "KeyReleased", + "TestModeChange" + }; + + + int i, type, j; + + cout << flush; + printf("tx\t\trx\t\tevent\n"); + printf("-----\t-----\t\t---------------------\n"); + for(i=0; i= 0x80) && (j <= 0x8C)) + { + printf("%s", commandName[j-0x80]); + } + else + { + printf("%02X", j); + } + printf("\n"); + break; + } + break; + case rxFlag: + printf("\t\t"); + switch(j) + { + case 0xFC: printf("ACK\n"); break; + case 0xFD: printf("NAK\n"); break; + case 0xFE: printf("RST\n"); break; + case 0xFF: printf("IDL\n"); break; + default: + if ((j >= 0x80) && (j <= 0x8C)) + { + printf("%s", commandName[j-0x80]); + } + else + { + printf("%02X", j); + } + printf("\n"); + break; + } + break; + case eventFlag: + printf("\t\t\t\t"); + switch(j) + { + case IRQ_EVENT: printf("IRQ entry\n"); break; + case IRQ_EVENT_RX: printf("IRQ_EVENT_RX\n"); break; + case IRQ_EVENT_TX: printf("IRQ_EVENT_TX\n"); break; + case IRQ_EVENT_MSR: printf("IRQ_EVENT_MSR\n"); break; + case IRQ_EVENT_LSR: printf("IRQ_EVENT_LSR\n"); break; + case IRQ_EVENT_BOGUS: printf("IRQ_EVENT_BOGUS\n"); break; + + case TX_EVENT_RESTART: printf("TX_EVENT_RESTART\n"); break; + case TX_EVENT_ABANDON: printf("TX_EVENT_ABANDON\n"); break; + case TX_EVENT_DONE: printf("TX_EVENT_DONE\n"); break; + case TX_EVENT_ACK: printf("TX_EVENT_ACK\n"); break; + case TX_EVENT_NAK: printf("TX_EVENT_NAK\n"); break; + case TX_EVENT_EARLY: printf("TX_EVENT_EARLY\n"); break; + case TX_EVENT_EMPTY: printf("TX_EVENT_EMPTY\n"); break; + case TX_EVENT_KICK: printf("TX_EVENT_KICK\n"); break; + + case RX_EVENT_FULL: printf("RX_EVENT_FULL\n"); break; + case RX_EVENT_NOT_CMD: printf("RX_EVENT_NOT_CMD\n"); break; + case RX_EVENT_FULLBODY: printf("RX_EVENT_FULLBODY\n"); break; + case RX_EVENT_NAK: printf("RX_EVENT_NAK\n"); break; + case RX_EVENT_CKSMERR: printf("RX_EVENT_CKSMERR\n"); break; + case RX_EVENT_OK: printf("RX_EVENT_OK\n"); break; + default: printf("unknown event %02X\n", j); break; + } + break; + } + } + fflush(stdout); +#endif + + //--------------------------------------------------------------------- + // Flush data to RIO + //--------------------------------------------------------------------- + RIOEvent + dummy_event; + + // This odd sequence of allocation, setting, and adding is necessary: + // if you try to combine them, the compiler gets confused as to which + // method to invoke for 'Now()'. + Time + then; + then = Now(); + then += 5.0f; + while (Now() < then) + { + //------------------------------------------------- + // Drop out of loop when all packets have been + // transmitted and the last character has been sent + //------------------------------------------------- + if (TransmitQueueCount() <= 0) + { + if (!IsActive()) + { + break; + } + } + GetNextEvent(&dummy_event); + } + + //--------------------------------------------------------------------- + // Update failure log + //--------------------------------------------------------------------- +#if LOG_RIO_DATA + OpenFailureFile(); + Check(failureFile); + + failureFile->SetEntry("RIO","lineErrors",lineErrorCount); + failureFile->SetEntry("RIO","abandonedPackets",abandonCount); + failureFile->SetEntry("RIO","overruns",overrunCount); + failureFile->SetEntry("RIO","remoteRetry",remoteRetryCount); + failureFile->SetEntry("RIO","remoteAbandon",remoteAbandonCount); + failureFile->SetEntry("RIO","remoteFullBuffer",remoteFullBufferCount); + + CloseFailureFile(); +#endif + + //------------------------------------------- + // Update ranger statistics, delete rangers + //------------------------------------------- + { +// NotationFile +// stat_file((const char *) "RIO.INI"); + + Check(leftPedalRanger); +// leftPedalRanger->Statistics(&stat_file); + Unregister_Object(leftPedalRanger); + delete leftPedalRanger; + leftPedalRanger = NULL; + + Check(rightPedalRanger); +// rightPedalRanger->Statistics(&stat_file); + Unregister_Object(rightPedalRanger); + delete rightPedalRanger; + rightPedalRanger = NULL; + + Check(throttleRanger); +// throttleRanger->Statistics(&stat_file); + Unregister_Object(throttleRanger); + delete throttleRanger; + throttleRanger = NULL; + + Check(joystickXRanger); +// joystickXRanger->Statistics(&stat_file); + Unregister_Object(joystickXRanger); + delete joystickXRanger; + joystickXRanger = NULL; + + Check(joystickYRanger); +// joystickYRanger->Statistics(&stat_file); + Unregister_Object(joystickYRanger); + delete joystickYRanger; + joystickYRanger = NULL; + } + Check_Fpu(); +} + +Logical + RIO::TestInstance() const +{ + return True; +} + +extern Byte pic_isr, pic_imr, pic_irr; +extern Byte uart_iir; +extern Byte pcspak_active,pcspak_rxState,pcspak_txState; +extern Word pcspak_head,pcspak_tail; +extern Word pcspak_tempHead,pcspak_tempTail,pcspak_count; + +extern "C" void + PCSPAKState(PCSerialPacket *ptr); + +Logical + RIO::GetNextEvent(RIOEvent *destination) +{ + Check(this); + + Byte receive_buffer[256]; + Logical reply, looping; + Word errors; + +//PCSPAKState(this); +// +//cout << flush; +//printf( +// "RIO isr=%02X imr=%02X irr=%02X, iir=%02X, a=%1d c=%04X ts=%1d rs=%1d e=%X\n", +// pic_isr, pic_imr, pic_irr, +// uart_iir, +// pcspak_active, +// pcspak_count, +// pcspak_txState, pcspak_rxState, +// pcspak_tempHead,pcspak_tempTail, +// Errors() +//); +//fflush(stdout); + + if (! operational) + { + return False; + } + + errors = Errors(); + if (errors) + { + if (errors & PCSerialPacket::initError) + { + NotationFile + failure((const char *) "FAILURE.LOG"); + + failure.SetEntry("RIOErrors","error","initialization"); + operational = False; + } + else + { + if (errors & PCSerialPacket::txAbandonPacket) + { +//cout << "RIO:: packet abandoned\n"; + ++abandonCount; + } + if (errors & PCSerialPacket::overrunError) + { +//cout << "RIO:: overrun\n"; + ++overrunCount; + } + if (errors & + ( + PCSerialPacket::parityError | + PCSerialPacket::framingError | + PCSerialPacket::overrunError + ) + ) + { + ++lineErrorCount; + } + } + } + + do + { + looping = False; + + reply = ReceivePacket(receive_buffer); + if (reply) + { + switch(receive_buffer[0]) + { + case CheckReply: + switch(receive_buffer[1]) + { + case BoardMissing: + OpenFailureFile(); + BoardError(failureFile,"missing_board",(int) receive_buffer[2]); + CloseFailureFile(); + break; + + case BoardBad: + OpenFailureFile(); + BoardError(failureFile,"dead_board",(int) receive_buffer[2]); + CloseFailureFile(); + break; + + case LampBad: + OpenFailureFile(); + Check(failureFile); + failureFile->AppendEntry( + "RIODeadLamps", + "lamp", + LBE4ControlsManager::GetLampName((int) receive_buffer[2]) + ); + CloseFailureFile(); + break; + + case RestartCount: + remoteRetryCount += receive_buffer[2]; + break; + + case AbandonCount: + remoteAbandonCount += receive_buffer[2]; + break; + + case FullBufferCount: + remoteFullBufferCount += receive_buffer[2]; + break; + } + looping = True; // status events not sent to host + break; + + case VersionReply: + destination->Type = RIO::VersionEvent; + MajorRevision = receive_buffer[1]; + MinorRevision = receive_buffer[2]; + break; + + case AnalogReply: + destination->Type = RIO::AnalogEvent; + // + // NOTE: no data is sent in this packet. + // The application is expected to directly read + // the values in the object. + // + + //---------------------------------------- + // Discard the next N analog packets + // (set by ForceCenterJoystick) + //---------------------------------------- +// if (discardCount) +// { +// --discardCount; +// } +// else + { + Check(throttleRanger); + Throttle = throttleRanger->Update( + // Note (-): Throttle counts BACKWARDS + -CombinePair(receive_buffer[1], receive_buffer[2]) + ); + + Check(leftPedalRanger); + LeftPedal = leftPedalRanger->Update( + CombinePair(receive_buffer[3], receive_buffer[4]) + ); + + Check(rightPedalRanger); + RightPedal = rightPedalRanger->Update( + CombinePair(receive_buffer[5], receive_buffer[6]) + ); + + Check(joystickYRanger); + JoystickY = joystickYRanger->Update( + CombinePair(receive_buffer[7], receive_buffer[8]) + ); + + Check(joystickXRanger); + JoystickX = joystickXRanger->Update( + CombinePair(receive_buffer[9], receive_buffer[10]) + ); + } + break; + + case ButtonPressed: + destination->Type = RIO::ButtonPressedEvent; + destination->Data.Unit = receive_buffer[1]; + break; + + case ButtonReleased: + destination->Type = RIO::ButtonReleasedEvent; + destination->Data.Unit = receive_buffer[1]; + break; + + case KeyPressed: + destination->Type = RIO::KeyEvent; + destination->Data.Keyboard.Unit = receive_buffer[1]; + destination->Data.Keyboard.Key = receive_buffer[2]; + break; + + case TestModeChange: + if (receive_buffer[1] != 0) + { + Tell("RIO entered test mode\n"); + TestModeActive = 1; + + OpenFailureFile(); + Check(failureFile); + failureFile->DeletePage("RIOBoardErrors"); + failureFile->DeletePage("RIODeadLamps"); + } + else + { + Tell("RIO exited test mode\n"); + TestModeActive = 0; + CloseFailureFile(); + } + looping = True; // this event not sent to host + break; + + default: // discard unused or bogus packets + looping = True; + break; + } + } + } + while (looping); + + Check_Fpu(); + return reply; +} + +void + RIO::ForceCenterJoystick() +{ + Check(this); + +// ResetVerticalJoystick(); +// ResetHorizontalJoystick(); + //------------------------------------------- + // Make sure we don't use 'old' data + // (skip the next two packets) + // ...why 2? Just to make sure... + //------------------------------------------- +// discardCount = 2; + + Check(joystickXRanger); + joystickXRanger->ForceToZero(); + + Check(joystickYRanger); + joystickYRanger->ForceToZero(); + + Check_Fpu(); +} + +void + RIO::SetJoystickDeadBand(Scalar dead_band) +{ + Check(this); + + Check(joystickXRanger); + joystickXRanger->SetDeadBand(dead_band); + + Check(joystickYRanger); + joystickYRanger->SetDeadBand(dead_band); + + Check_Fpu(); +} + +void + RIO::SetThrottleDeadBand(Scalar dead_band) +{ + Check(this); + + Check(throttleRanger); + throttleRanger->SetDeadBand(dead_band); + + Check_Fpu(); +} + +void + RIO::SetPedalsDeadBand(Scalar dead_band) +{ + Check(this); + + Check(leftPedalRanger); + leftPedalRanger->SetDeadBand(dead_band); + + Check(rightPedalRanger); + rightPedalRanger->SetDeadBand(dead_band); + + Check_Fpu(); +} + +void + RIO::RequestCheck() +{ + Check(this); + static Byte request_check_string[] = { RIO::CheckRequest }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_check_string); + } + Check_Fpu(); +} + +void + RIO::RequestVersion() +{ + Check(this); + static Byte request_version_string[] = { RIO::VersionRequest }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_version_string); + } + Check_Fpu(); +} + +void + RIO::RequestAnalogUpdate() +{ + //DEBUG_STREAM << "Analog Update Requested: " << GetTickCount() << std::endl << std::flush; + Check(this); + static Byte request_analog_string[] = { RIO::AnalogRequest }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_analog_string); + } + Check_Fpu(); +} + +void + RIO::GeneralReset() +{ + Check(this); + static Byte request_reset_string[] = { RIO::ResetRequest, 0 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_reset_string); + } + Check_Fpu(); +} + +void + RIO::ResetThrottle() +{ + Check(this); + static Byte request_throttle_string[] = { RIO::ResetRequest, 1 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_throttle_string); + } + Check_Fpu(); +} + +void + RIO::ResetLeftPedal() +{ + Check(this); + static Byte request_lpedal_string[] = { RIO::ResetRequest, 2 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_lpedal_string); + } + Check_Fpu(); +} + +void + RIO::ResetRightPedal() +{ + Check(this); + static Byte request_rpedal_string[] = { RIO::ResetRequest, 3 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_rpedal_string); + } + Check_Fpu(); +} + +void + RIO::ResetVerticalJoystick() +{ + Check(this); + static Byte request_vstick_string[] = { RIO::ResetRequest, 4 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_vstick_string); + } + Check_Fpu(); +} + +void + RIO::ResetHorizontalJoystick() +{ + Check(this); + static Byte request_hstick_string[] = { RIO::ResetRequest, 5 }; + + if (operational && !TestModeActive) + { + SendPacket((Byte *) request_hstick_string); + } + Check_Fpu(); +} + +void + RIO::SetLamp(int lampNumber, int state) +{ + Check(this); + static Byte request_lamp_string[] = { RIO::LampRequest, 0, 0 }; + + if (operational) + { + request_lamp_string[1] = (Byte) (lampNumber & 0x7F); + request_lamp_string[2] = (Byte) (state & 0x7F); + SendPacket((Byte *) request_lamp_string); + } + Check_Fpu(); +} + +void + RIO::OpenFailureFile() +{ + Check(this); + + if (failureFileOpenCount == 0) + { + failureFile = new NotationFile("FAILURE.LOG"); + Check(failureFile); + Register_Object(failureFile); + } + ++failureFileOpenCount; + Check_Fpu(); +} + +void + RIO::CloseFailureFile() +{ + Check(this); + + --failureFileOpenCount; + if (failureFileOpenCount <= 0) + { + failureFileOpenCount = 0; + + Check(failureFile); + Unregister_Object(failureFile); + delete failureFile; + } + Check_Fpu(); +} diff --git a/MUNGA_L4/L4RIO.h b/MUNGA_L4/L4RIO.h new file mode 100644 index 0000000..0007210 --- /dev/null +++ b/MUNGA_L4/L4RIO.h @@ -0,0 +1,320 @@ +#pragma once + +#include "l4pcspak.h" +#include "..\munga\notation.h" +#include "..\munga\average.h" + +// These are purposely grouped as two parameters in one equate +// (See PCSPAK.HH). +// The standard PC COM ports ALWAYS use these combinations. +//#define RIO_COM1 PCSP_COM1 +//#define RIO_COM2 PCSP_COM2 +//#define RIO_COM3 PCSP_COM3 +//#define RIO_COM4 PCSP_COM4 + + +class FilterChannel SIGNATURED +{ +public: + static const char *highName; + static const char *centerName; + static const char *lowName; + static const char *joystickXName; + static const char *joystickYName; + static const char *throttleName; + static const char *leftPedalName; + static const char *rightPedalName; + + enum AlignMode { unaligned, normal }; + enum PolarMode { unipolar, bipolar }; + + FilterChannel(); + FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_max + ); + FilterChannel( + NotationFile *init_file, + const char *page_name, + int default_min, int default_center, int default_max + ); + ~FilterChannel(); + void + SetPolarity(PolarMode newPolarity); + void + SetDeadBand(Scalar amount_of_deadband); + virtual void + BeginAlignment(); + virtual void + EndAlignment(NotationFile *init_file=NULL); + virtual Scalar + Update(int value); + Logical + TestInstance() const; + +protected: + void + CalculateDeadBands(); + + const char *pageName; + PolarMode polarity; + AlignMode mode; + int previousValue, min, max, center; + int lowerRange, lowerDeadband; + int upperRange, upperDeadband; + Scalar deadbandScalar; + Logical valuesFromFile; + AverageOf average; +}; + + +class RIO; + +class Ranger SIGNATURED +{ + friend class RIO; +protected: + Ranger( + const char *page_name, + int default_min, + int default_max, + Scalar deadband_scalar + ); + + ~Ranger(); + + void + ForceToZero(); + void + SetDeadBand(Scalar amount_of_deadband); + Scalar + Update(int input); + Logical + TestInstance() const; + void + Statistics(NotationFile *stat_file); + + const char + *pageName; + Logical + sampledInputFlag; + int + offset, + hardwareMinimum, + hardwareMaximum, + hardwareRange, + deadbandInteger, + highestInput, + lowestInput; +}; + +class RIO : + public PCSerialPacket +{ +protected: + enum RIOCommand{ + CheckRequest=0x80, + VersionRequest, + AnalogRequest, + ResetRequest, + LampRequest, + CheckReply, + VersionReply, + AnalogReply, + ButtonPressed, + ButtonReleased, + KeyPressed, + KeyReleased, + TestModeChange + }; + +public: + enum RIOStatusType { + BoardOk=0, BoardMissing=1, BoardBad=2, + LampBad=3, + RestartCount=4, AbandonCount=5, FullBufferCount=6 + }; + + enum LampState{ + solid=0, flashSlow=1, flashMed=2, flashFast=3, + state1Off=0x00, state1Dim=0x04, state1Bright=0x0C, + state2Off=0x00, state2Dim=0x10, state2Bright=0x30, + }; + + enum RIOEventType { + ButtonPressedEvent, + ButtonReleasedEvent, + KeyEvent, + AnalogEvent, + VersionEvent + }; + + struct RIOKeyPair + { + int Unit; + int Key; + }; + + struct RIOEvent + { + RIOEventType Type; + union + { + int Unit; + RIOKeyPair Keyboard; + }Data; + }; + + //Win32 Serial support: ADB 02/13/07 + //RIO(Word port, Word intNum, Logical perform_tests = True); + RIO(const char* port, Logical perform_tests = True); + ~RIO(); + + Logical + TestInstance() const; + + Logical + GetNextEvent(RIOEvent *destinationPointer); + + void + ForceCenterJoystick(), + SetJoystickDeadBand(Scalar dead_band), + SetThrottleDeadBand(Scalar dead_band), + SetPedalsDeadBand(Scalar dead_band); + + void + RequestCheck(), + RequestVersion(), + RequestAnalogUpdate(); + + void + GeneralReset(), + ResetThrottle(), + ResetLeftPedal(), + ResetRightPedal(), + ResetVerticalJoystick(), + ResetHorizontalJoystick(); + + void + SetLamp(int lampNumber, int state); + + void + TestCheckReply(int type, int location) + { + RIO::reply_check_string[1] = (Byte) (type & 0x7F); + RIO::reply_check_string[2] = (Byte) (location & 0x7F); + SendPacket((Byte *)reply_check_string); + } + + void + TestVersionReply(int major, int minor) + { + RIO::reply_version_string[1] = (Byte) (major & 0x7F); + RIO::reply_version_string[2] = (Byte) (minor & 0x7F); + SendPacket((Byte *)reply_version_string); + } + + void + TestAnalogReply() + { + SendPacket((Byte *)reply_analog_string); + } + + void + TestButtonPressed(int button) + { + RIO::reply_button_press_string[1] = (Byte) (button & 0x7F); + SendPacket((Byte *)reply_button_press_string); + } + + void + TestButtonReleased(int button) + { + RIO::reply_button_release_string[1] = (Byte) (button & 0x7F); + SendPacket((Byte *)reply_button_release_string); + } + + void + TestKeyPressed(int board, int key) + { + RIO::reply_key_press_string[1] = (Byte) (board & 0x7F); + RIO::reply_key_press_string[2] = (Byte) (key & 0x7F); + SendPacket((Byte *)reply_key_press_string); + } + + void + TestKeyReleased(int board, int key) + { + RIO::reply_key_release_string[1] = (Byte) (board & 0x7F); + RIO::reply_key_release_string[2] = (Byte) (key & 0x7F); + SendPacket((Byte *)reply_key_release_string); + } + + void + TestEnterTestMode() + {SendPacket((Byte *)reply_test_enter_string);} + + void + TestExitTestMode() + {SendPacket((Byte *)reply_test_exit_string);} + + int + ReceiveQueueCount() + { return PCSerialPacket::ReceiveQueueCount(); } + + int + TransmitQueueCount() + { return PCSerialPacket::TransmitQueueCount(); } + + int + TestModeActive; + + Scalar + Throttle, LeftPedal, RightPedal, JoystickX, JoystickY; + + int + MajorRevision, MinorRevision; + + int remoteRetryCount; + int remoteAbandonCount; + int remoteFullBufferCount; + int lineErrorCount; + int abandonCount; + int overrunCount; + + int discardCount; // used by BeginAnalogCalibration() + +protected: + void + OpenFailureFile(); + + void + CloseFailureFile(); + + void + CheckErrors(); + + Logical + operational; + Ranger + *leftPedalRanger, *rightPedalRanger; + Ranger + *throttleRanger; + Ranger + *joystickXRanger, *joystickYRanger; + NotationFile + *failureFile; + int + failureFileOpenCount; + + static Byte reply_check_string[]; + static Byte reply_version_string[]; + static Byte reply_analog_string[]; + static Byte reply_button_press_string[]; + static Byte reply_button_release_string[]; + static Byte reply_key_press_string[]; + static Byte reply_key_release_string[]; + static Byte reply_test_enter_string[]; + static Byte reply_test_exit_string[]; +}; diff --git a/MUNGA_L4/L4SERIAL.H b/MUNGA_L4/L4SERIAL.H new file mode 100644 index 0000000..7488dd1 --- /dev/null +++ b/MUNGA_L4/L4SERIAL.H @@ -0,0 +1,164 @@ +//===========================================================================// +// File: L4Serial.hh // +// Project: MUNGA Brick: Platform-specific IO // +// Contents: PC serial interface class // +//---------------------------------------------------------------------------// +// Date Who Modification // +// -------- --- -----------------------------------------------------------// +// 01/04/95 CPB Initial coding. // +//---------------------------------------------------------------------------// +// Copyright (C) 1994, Virtual World Entertainment, Inc. // +// All Rights reserved worldwide // +// This unpublished sourcecode is PROPRIETARY and CONFIDENTIAL // +//===========================================================================// + +#pragma once + +#include "../MUNGA/STYLE.H" +//Win32 Serial support: ADB 06/30/07 +#include +#include + +// WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING +// Do NOT change ANY of the following lines without making +// corresponding changes in PCSerial.asm! PCSerial.hh exists +// ONLY to inform C++ compilers of the data and structures +// used by PCSerial.asm! +// WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING**WARNING + + +//Win32 Serial support: ADB 06/30/07 +// These are purposely grouped as two parameters in one equate. +// The standard PC COM ports ALWAYS use these combinations. +//#define PCS_COM1 0x3F8,0x0C // portAddress,interruptNumber +//#define PCS_COM2 0x2F8,0x0B +//#define PCS_COM3 0x3E8,0X0C +//#define PCS_COM4 0x2E8,0x0B + +// Data rates +#define PCS_300 0x0180 // 300 Baud +#define PCS_1200 0x0060 // 1200 Baud +#define PCS_2400 0x0030 // 2400 Baud +#define PCS_9600 0x000C // 9600 Baud +#define PCS_19P2 0x0006 // 19200 Baud +#define PCS_38P4 0x0003 // 38400 Baud +#define PCS_115K 0x0001 // 115,200 Baud (not supported on all PC's) + +// Data formats +//Win32 Serial support: ADB 06/23/07 +//Added masks as follows +//00PP PTSS where SS = Speed, T = Stop Bits, & PPP = Parity +#define PCS5D 0x0000 // 5 data bits +#define PCS6D 0x0001 // 6 data bits +#define PCS7D 0x0002 // 7 data bits +#define PCS8D 0x0003 // 8 data bits +#define PCSMD 0x0003 // data size mask + +#define PCS1S 0x0000 // one stop bit +#define PCS2S 0x0004 // two stop bits +#define PCSMS 0x0004 // stop bit mask + +#define PCSNP 0x0000 // no parity +#define PCSOP 0x0008 // odd parity +#define PCSEP 0x0018 // even parity +#define PCSMP 0x0028 // mark parity (untested) +#define PCSSP 0x0038 // space parity (untested) +#define PCSMAP 0x0038 // parity mask + + // some popular combinations- +#define PCS_N81 (PCS8D|PCS1S|PCSNP) // no parity, 8 data, 1 stop +#define PCS_E81 (PCS8D|PCS1S|PCSEP) // even parity, 8 data, 1 stop +#define PCS_O81 (PCS8D|PCS1S|PCSOP) // odd parity, 8 data, 1 stop + +// Flow control +// #define PCS_NOFLOWCTRL 0x0000 // no flow control + +// error bits returned by PC_Serial::Errors() +#define PCS_ERR_OVERRUN 0x0002 +#define PCS_ERR_PARITY 0x0004 +#define PCS_ERR_FRAMING 0x0008 +#define PCS_ERR_BREAK 0x0010 +#define PCS_ERR_ALLOC 0x0100 // failed at slot allocation +#define PCS_ERR_INIT 0x0200 // failed DPMI initialization +#define PCS_ERR_TXOVER 0x0400 // overran transmit buffer +#define PCS_ERR_RXOVER 0x0500 // overran receive buffer +//Win32 Serial support: ADB 01/15/07 +#define PCS_ERR_OTHER 0x8000 //Other Error not listed above + +// bits returned by PC_Serial::ModemStatus() + +// (1st four bits not defined yet, but non-zero) +#define PCS_MS_CTS 0x0010 +#define PCS_MS_DSR 0x0020 +#define PCS_MS_RI 0x0040 +#define PCS_MS_DCD 0x0080 + + +class PCSerial; + +HANDLE InitSerialPort(WORD rate, WORD format, const char* port, bool overlapped); + +class PCSerial +{ +public: + //Win32 Serial support: ADB 01/11/07 + PCSerial(WORD rate, WORD format, const char* port); + + ~PCSerial(); + + //Win32 Serial support: ADB 01/15/07 + Logical TestInstance(); + + Logical CanDraw(); + + //Win32 Serial support: ADB 01/15/07 + int ReceiveString(char *destPtr, int maxLen);// returns length + + //Win32 Serial support: ADB 01/15/07 + void FlowControlEnable(Logical onOff); + + //Win32 Serial support: ADB 01/15/07 + void SendString(char *srcPtr, int length); + + //Win32 Serial support: ADB 01/15/07 + int ReceiveCharCount(); + + //Win32 Serial support: ADB 01/15/07 + int TransmitCharCount(); + + //Win32 Serial support: ADB 01/15/07 + int Errors();// returns error value, clears it + + //Win32 Serial support: ADB 01/15/07 + int IsActive(); + + //Win32 Serial support: ADB 01/15/07 + int ModemStatus(); + +# if defined(USE_SIGNATURE) + friend int + Is_Signature_Bad(const volatile PCSerial *ptr) + { return PCSerialIsSignatureBad(ptr); } +# endif + +// protected: + + //Word portBase; + HANDLE hComm; + OVERLAPPED mOverlappedOb; + //Word errorValue; + Byte enabled; + //Byte txFlow; + //Byte flowOverride; + //LWord intDataPtr; + //LWord hackCount; + + // This is for INTERNAL USE only (reflects structure in .ASM file) + //Win32 Serial support: ADB 01/15/07 + //struct PCSerBuf + //{ + // Word head, tail, count; + // Byte data[1024]; + //} + //txBuf, rxBuf; +}; \ No newline at end of file diff --git a/MUNGA_L4/L4SERIAL.cpp b/MUNGA_L4/L4SERIAL.cpp new file mode 100644 index 0000000..ef55f43 --- /dev/null +++ b/MUNGA_L4/L4SERIAL.cpp @@ -0,0 +1,287 @@ +#include +#include +#include "L4SERIAL.h" + +HANDLE InitSerialPort(WORD rate, WORD format, const char* port, bool overlapped) +{ + HANDLE hComm = INVALID_HANDLE_VALUE; + + hComm = CreateFileA(port, GENERIC_READ | GENERIC_WRITE, 0, NULL, OPEN_EXISTING, overlapped ? FILE_FLAG_OVERLAPPED : NULL, NULL); + if(hComm == INVALID_HANDLE_VALUE) + { + DWORD err = GetLastError(); + DEBUG_STREAM << "ERROR: CreateFileA() failed [GetLastError() = " << GetLastError() << "]!\n" << std::flush; + return INVALID_HANDLE_VALUE; + } + + DCB control; + memset(&control, 0, sizeof(control)); + control.DCBlength = sizeof(control); + control.EvtChar = (char)0xFF; + + if(rate == PCS_300) + control.BaudRate = 300; + else if(rate == PCS_1200) + control.BaudRate = 1200; + else if(rate == PCS_2400) + control.BaudRate = 2400; + else if(rate == PCS_9600) + control.BaudRate = 9600; + else if(rate == PCS_19P2) + control.BaudRate = 19200; + else if(rate == PCS_38P4) + control.BaudRate = 38400; + else if(rate == PCS_115K) + control.BaudRate = 115200; + else + { + DEBUG_STREAM << "ERROR: Invalid Baud Rate!\n" << std::flush; + CloseHandle(hComm); + return INVALID_HANDLE_VALUE; + } + + if((format & PCSMAP) == PCSNP) + control.Parity = NOPARITY; + else if((format & PCSMAP) == PCSOP) + control.Parity = ODDPARITY; + else if((format & PCSMAP) == PCSEP) + control.Parity = EVENPARITY; + else if((format & PCSMAP) == PCSMP) + control.Parity = MARKPARITY; + else if((format & PCSMAP) == PCSSP) + control.Parity = SPACEPARITY; + else + { + DEBUG_STREAM << "ERROR: Invalid Parity!\n" << std::flush; + CloseHandle(hComm); + return INVALID_HANDLE_VALUE; + } + + if((format & PCSMD) == PCS8D) + control.ByteSize = 8; + else if((format & PCSMD) == PCS6D) + control.ByteSize = 6; + else if((format & PCSMD) == PCS7D) + control.ByteSize = 7; + else if((format & PCSMD) == PCS8D) + control.ByteSize = 8; + else + { + DEBUG_STREAM << "ERROR: Invalid Byte Size!\n" << std::flush; + CloseHandle(hComm); + return INVALID_HANDLE_VALUE; + } + + if((format & PCSMS) == PCS1S) + control.StopBits = ONESTOPBIT; + else if((format & PCSMS) == PCS2S) + control.StopBits = TWOSTOPBITS; + else + { + DEBUG_STREAM << "ERROR: Invalid Stop Bits!\n" << std::flush; + CloseHandle(hComm); + return INVALID_HANDLE_VALUE; + } + + if(!SetCommState(hComm, &control)) + { + DEBUG_STREAM << "ERROR: SetCommState() failed [rate = " << control.BaudRate; + DEBUG_STREAM << ", dataBits = " << control.ByteSize; + DEBUG_STREAM << ", stopBits = " << control.StopBits; + DEBUG_STREAM << ", parity = " << control.Parity << "!\n"; + CloseHandle(hComm); + return INVALID_HANDLE_VALUE; + } + + //Non-blocking + COMMTIMEOUTS timeout; + timeout.ReadIntervalTimeout = MAXDWORD; + timeout.ReadTotalTimeoutConstant = 0; + timeout.ReadTotalTimeoutMultiplier = 0; + timeout.WriteTotalTimeoutConstant = 0; + timeout.WriteTotalTimeoutMultiplier = 0; + if(!SetCommTimeouts(hComm, &timeout)) + { + DEBUG_STREAM << "ERROR: SetCommTimeouts() failed!\n"; + CloseHandle(hComm); + return INVALID_HANDLE_VALUE; + } + + PurgeComm(hComm, PURGE_TXABORT | PURGE_RXABORT | PURGE_TXCLEAR | PURGE_RXCLEAR); + + return hComm; +} + +//Win32 Serial support: ADB 01/11/07 +PCSerial::PCSerial(WORD rate, WORD format, const char* port) +//PCSerial(DWORD rate, BYTE dataBits, BYTE stopBits, BYTE parity, const WCHAR* port) +{ + enabled = 0; + + mOverlappedOb.hEvent = CreateEvent(NULL, TRUE, TRUE, NULL); + mOverlappedOb.Internal = 0; + mOverlappedOb.InternalHigh = 0; + mOverlappedOb.Offset = 0; + mOverlappedOb.OffsetHigh = 0; + + //PCSerialInit(this, rate, format, port, int_num); + hComm = InitSerialPort(rate, format, port, true); + + if(hComm != INVALID_HANDLE_VALUE) + enabled = 1; +} + +PCSerial::~PCSerial() +{ + if (this == NULL) + { + std::cout << "~PCSerial has been passed a NULL pointer\n" << std::flush; + } + else + { + WaitForSingleObject(mOverlappedOb.hEvent,INFINITE); + CloseHandle(mOverlappedOb.hEvent); + CloseHandle(hComm); + hComm = INVALID_HANDLE_VALUE; + enabled = 0; + } +} + +//Win32 Serial support: ADB 01/15/07 +Logical PCSerial::TestInstance() +{ + //return PCSerialTestInstance(this); + return 1; +} + +//Win32 Serial support: ADB 01/15/07 +int PCSerial::ReceiveString(char *destPtr, int maxLen) // returns length +{ + //TODO: Do overlapped reads if we ever need this function again + assert(FALSE); + //return PCSerialReceive(this, destPtr, maxLen) + DWORD bytesRead; + ReadFile(hComm, (void *)destPtr, maxLen, &bytesRead, NULL); + return (int)bytesRead; +} + +//Win32 Serial support: ADB 01/15/07 +void PCSerial::FlowControlEnable(Logical onOff) +{ + //STUBBED: Serial ADB 01/15/07 + //VERIFY: Probably not used + //PCSerialFlowControl(this, (int) onOff);DCB control; +} + +Logical PCSerial::CanDraw() +{ + return (WaitForSingleObject(mOverlappedOb.hEvent, 0) == WAIT_OBJECT_0); +} + +//Win32 Serial support: ADB 01/15/07 +void PCSerial::SendString(char *srcPtr, int length) +{ + //PCSerialSend(this, srcPtr, length); + WaitForSingleObject(mOverlappedOb.hEvent, INFINITE); + DWORD bytesWritten; + WriteFile(hComm, (void*)srcPtr, length, &bytesWritten, &mOverlappedOb); +} + +//Win32 Serial support: ADB 01/15/07 +int PCSerial::ReceiveCharCount() +{ + //return PCSerialReceiveCount(this); + COMMPROP props; + if(!GetCommProperties(hComm, &props)) + { + DEBUG_STREAM << "ERROR: GetCommProperties() failed in TransmitCharCount()! GetLastError() = " << GetLastError() << std::endl; + return 0; + } + + return props.dwCurrentRxQueue; +} + +//Win32 Serial support: ADB 01/15/07 +int PCSerial::TransmitCharCount() +{ + //return PCSerialTransmitCount(this); + COMMPROP props; + if(!GetCommProperties(hComm, &props)) + { + DEBUG_STREAM << "ERROR: GetCommProperties() failed in TransmitCharCount()! GetLastError() = " << GetLastError() << std::endl; + return 0; + } + + return props.dwCurrentTxQueue; +} + +//Win32 Serial support: ADB 01/15/07 +int PCSerial::Errors() // returns error value, clears it +{ + //return PCSerialErrors(this); + DWORD errors; + if(!ClearCommError(hComm, &errors, NULL)) + { + DEBUG_STREAM << "ERROR: GetCommError() failed!\n"; + return PCS_ERR_OTHER; + } + + int outError = 0; + if(errors & CE_OVERRUN) + { + outError |= PCS_ERR_OVERRUN; + errors ^= CE_OVERRUN; + } + if(errors & CE_RXPARITY) + { + outError |= PCS_ERR_PARITY; + errors ^= CE_RXPARITY; + } + if(errors & CE_FRAME) + { + outError |= PCS_ERR_FRAMING; + errors ^= CE_FRAME; + } + if(errors & CE_BREAK) + { + outError |= PCS_ERR_BREAK; + errors ^= CE_BREAK; + } + if(errors & CE_RXOVER) + { + outError |= PCS_ERR_RXOVER; + errors ^= CE_RXOVER; + } + if(errors & CE_TXFULL) + { + outError |= PCS_ERR_TXOVER; + errors ^= CE_TXFULL; + } + //other error + if(errors) + outError |= PCS_ERR_OTHER; + + return outError; +} + +//Win32 Serial support: ADB 01/15/07 +int PCSerial::IsActive() +{ + //return PCSerialActive(this); + return enabled; +} + + +//Win32 Serial support: ADB 01/15/07 +int PCSerial::ModemStatus() +{ + //return PCSerialModemStatus(this); + DWORD modem; + if(!GetCommModemStatus(hComm, &modem)) + { + DEBUG_STREAM << "ERROR: GetCommModemStatus() failed!\n"; + return 0; + } + + return modem; +} diff --git a/MUNGA_L4/L4SPLR.cpp b/MUNGA_L4/L4SPLR.cpp new file mode 100644 index 0000000..dd48d3f --- /dev/null +++ b/MUNGA_L4/L4SPLR.cpp @@ -0,0 +1,741 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4splr.h" +#include "..\munga\mission.h" +#include "..\munga\controls.h" +#include "..\munga\appmsg.h" + +//############################################################################# +//####################### SpoolingInterestManager ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolingInterestManager::SpoolingInterestManager() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolingInterestManager::~SpoolingInterestManager() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolingInterestManager::LoadInterestArenas(Mission *) +{ + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolingInterestManager::LoadMission(Mission *) +{ + Check(this); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolingInterestManager::ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message * + ) +{ + // + //-------------------------------------------------------------------- + // All network messages coming to the interest manager will be spooled + //-------------------------------------------------------------------- + // + packet->timeStamp = Now(); // HACK - spoof the clock stuff + Check(l4_spooling_application); + SpoolFile *spool = l4_spooling_application->GetSpoolFile(); + Check(spool); + spool->SpoolPacket(packet); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolingInterestManager::Shutdown() +{ + Check(this); +} + +//############################################################################# +//###################### L4SpoolingNetworkManager ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4SpoolingNetworkManager::L4SpoolingNetworkManager() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingNetworkManager::StartConnecting(Mission *mission) +{ + // + //-------------------------------------------------------- + // Let the L4 network manager start the connection process + //-------------------------------------------------------- + // + L4NetworkManager::StartConnecting(mission); + + // + //--------------------------------- + // Local the spool file to write to + //--------------------------------- + // + Check(l4_spooling_application); + SpoolFile *spool = l4_spooling_application->GetSpoolFile(); + Check(spool); + + *(ApplicationID*)spool->GetPointer() = application->GetApplicationID(); + spool->AdvancePointer(sizeof(ApplicationID)); + + ResourceFile *res_file = application->GetResourceFile(); + Check(res_file); + int major_version = res_file->versionArray[1]; + *(int*)spool->GetPointer() = major_version; + spool->AdvancePointer(sizeof(major_version)); + + // + //----------------------------------------------------------------- + // Now, write out the host IDs. Follow each host ID with a logical + // indicating whether it is local or remote + //----------------------------------------------------------------- + // + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + Mission::HostIterator mission_host_iterator(mission); + MissionHostData *mission_host_data; + + while ((mission_host_data = mission_host_iterator.ReadAndNext()) != NULL) + { + CString host_name(mission_host_data->GetAddressString()); + SOCKADDR_IN net_address; + + ResolveAddress(host_name, &net_address); + Host *host = host_mgr->FindHost(net_address); + + *(Logical*)spool->GetPointer() = (host != host_mgr->GetLocalHost()); + spool->AdvancePointer(sizeof(Logical)); + + *(HostID*)spool->GetPointer() = host->GetHostID(); + spool->AdvancePointer(sizeof(HostID)); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4SpoolingNetworkManager::~L4SpoolingNetworkManager() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingNetworkManager::ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *message + ) +{ + // + //------------------------------------------------------ + // Any egg messages will be spooled before being sent on + //------------------------------------------------------ + // + if (message->messageID == ReceiveEggFileMessageID) + { + packet->timeStamp = Now(); // HACK - spoof the clock stuff + Check(l4_spooling_application); + SpoolFile *spool = l4_spooling_application->GetSpoolFile(); + Check(spool); + spool->SpoolPacket(packet); + } + L4NetworkManager::ReceiveNetworkPacket(packet, message); +} + +//############################################################################# +//###################### L4PlaybackNetworkManager ######################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4PlaybackNetworkManager::L4PlaybackNetworkManager(): + NetworkManager(L4PlaybackNetworkManager::DefaultData) +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4PlaybackNetworkManager::StartConnecting(Mission *mission) +{ + // + // Create the host iterator for the mission egg + // + Mission::HostIterator mission_host_iterator(mission); + MissionHostData *mission_host_data; + Check(application); + SpoolFile *spool = application->GetSpoolFile(); + Check(spool); + + ApplicationID id = *(ApplicationID*)spool->GetPointer(); + spool->AdvancePointer(sizeof(id)); + int major_rev = *(int*)spool->GetPointer(); + spool->AdvancePointer(sizeof(major_rev)); + + if (id != application->GetApplicationID()) + { + DEBUG_STREAM << "\n\nError - Not a spool file for this application!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + ResourceFile *resource_file = application->GetResourceFile(); + Check(resource_file); + + if (major_rev != resource_file->versionArray[1]) + { + DEBUG_STREAM << "\n\nError - Spool file major data version should be " + << (int)resource_file->versionArray[1] << ", not " << major_rev + << "!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + + // + // Iterate through all the host addresses in the egg and create all the host + // structures, note that there MUST be an entry in the egg for us. + // + while ((mission_host_data = mission_host_iterator.ReadAndNext()) != NULL) + { + Check(mission_host_data); + CString host_name(mission_host_data->GetAddressString()); + + Logical remote = *(Logical*)spool->GetPointer(); + spool->AdvancePointer(sizeof(Logical)); + HostID host_id = *(HostID*)spool->GetPointer(); + spool->AdvancePointer(sizeof(HostID)); + + Host *my_host = + new L4Host( + host_id, + mission_host_data->GetHostType(), + NULL, + INVALID_SOCKET, + host_name + ); + Register_Object(my_host); + if (remote) + { + host_mgr->AdoptRemoteHost(my_host); + } + else + { + host_mgr->AdoptLocalHost(my_host); + } + } + + // + // Now, just send the load message + // + Check(application); + Application::Message + load_message( + Application::LoadMissionMessageID, + sizeof(Application::Message) + ); + application->Post(DefaultEventPriority, application, &load_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4PlaybackNetworkManager::Shutdown() +{ + Check(this); + NetworkManager::Shutdown(); + + Check(application); + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + HostManager::RemoteHostIterator remote_hosts(host_mgr); + Host *my_host; + while ((my_host = remote_hosts.ReadAndNext()) != NULL) + { + Check(my_host); + host_mgr->OrphanRemoteHost(my_host); + Unregister_Object(my_host); + delete my_host; + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4PlaybackNetworkManager::CheckBuffers(NetworkPacket*) +{ + // + // The buffers are always empty + // + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4PlaybackNetworkManager::~L4PlaybackNetworkManager() +{ +} + +//############################################################################# +//###################### L4SpoolingApplication ########################## +//############################################################################# + +L4SpoolingApplication*& + l4_spooling_application = (L4SpoolingApplication*&)application; + +const Receiver::HandlerEntry + L4SpoolingApplication::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(L4SpoolingApplication, RunMission), + MESSAGE_ENTRY(L4SpoolingApplication, StopMission), + MESSAGE_ENTRY(L4SpoolingApplication, AbortMission), + MESSAGE_ENTRY(L4SpoolingApplication, LoadMission) +}; + +Receiver::MessageHandlerSet& L4SpoolingApplication::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(L4SpoolingApplication::MessageHandlerEntries), L4SpoolingApplication::MessageHandlerEntries, L4Application::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Virtual Data support +// +Derivation* L4SpoolingApplication::GetClassDerivations() +{ + static Derivation classDerivations(L4Application::GetClassDerivations(), "L4SpoolingApplication"); + return &classDerivations; +} + +L4SpoolingApplication::SharedData + L4SpoolingApplication::DefaultData( + L4SpoolingApplication::GetClassDerivations(), + L4SpoolingApplication::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingApplication::LoadMissionMessageHandler(Message *) +{ + applicationState.SetState(WaitingForLaunch); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingApplication::RunMissionMessageHandler(RunMissionMessage *) +{ + Check(this); + + applicationState.SetState(RunningMission); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void L4SpoolingApplication::StopMissionMessageHandler(StopMissionMessage *message) +{ + if (!missionSpooled) + { + missionSpooled = True; + // + //----------------------------------------------------------------------- + // Post this message again until the application is running + //----------------------------------------------------------------------- + // + Time post_time = Now(); + post_time += 3.0f; + + Post(DefaultEventPriority, this, message, post_time); + } + else + { + MissionReviewApplicationManager *app_mgr = GetApplicationManager(); + Check(app_mgr); + SpoolFile *spool = GetSpoolFile(); + Check(spool); + app_mgr->StoreSpoolFile(spool); + spoolFile = NULL; + + L4Application::StopMissionMessageHandler(message); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingApplication::AbortMissionMessageHandler( + AbortMissionMessage *message + ) +{ + Check(this); + Check(spoolFile); + spoolFile->Rewind(); + + L4Application::AbortMissionMessageHandler(message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingApplication::ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *message + ) +{ + Check(this); + + // + //------------------------------------------------------ + // Any egg messages will be spooled before being sent on + //------------------------------------------------------ + // + switch (message->messageID) + { + case StopMissionMessageID: + if (missionSpooled) + { + packet->timeStamp = Now(); // HACK - spoof the clock stuff + SpoolFile *spool = GetSpoolFile(); + Check(spool); + spool->SpoolPacket(packet); + break; + } + + case RunMissionMessageID: + packet->timeStamp = Now(); // HACK - spoof the clock stuff + SpoolFile *spool = GetSpoolFile(); + Check(spool); + spool->SpoolPacket(packet); + break; + } + L4Application::ReceiveNetworkPacket(packet, message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4SpoolingApplication::L4SpoolingApplication( + HINSTANCE hInstance, + HWND hWnd, + ResourceFile *resource_file, + ApplicationID application_ID +): + L4Application( + hInstance, + hWnd, + resource_file, + application_ID, + L4ApplicationClassID, + DefaultData + ) +{ + missionSpooled = False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Registry* + L4SpoolingApplication::MakeRegistry() +{ + return NULL; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +InterestManager* + L4SpoolingApplication::MakeInterestManager() +{ + return new SpoolingInterestManager; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkManager* + L4SpoolingApplication::MakeNetworkManager() +{ + return new L4SpoolingNetworkManager; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingApplication::Initialize() +{ + Check(this); + Application::Initialize(); + + // + // Create the console host and socket + // + L4NetworkManager *net_mgr = GetNetworkManager(); + Check(net_mgr); + net_mgr->CreateConsoleHost(); + + // + // Allocate the spool file + // + MissionReviewApplicationManager *app_mgr = GetApplicationManager(); + Check(app_mgr); + spoolFile = app_mgr->GetEmptySpoolFile(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4SpoolingApplication::LoadBackgroundTasks() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VideoRenderer* + L4SpoolingApplication::MakeVideoRenderer() +{ + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +AudioRenderer* + L4SpoolingApplication::MakeAudioRenderer() +{ + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GaugeRenderer* + L4SpoolingApplication::MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index) +{ + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Mission* + L4SpoolingApplication::MakeMission( + NotationFile *notation_file, + ResourceFile *resources + ) +{ + Check(this); + Check(notation_file); + Check(resources); + +//////////// return new L4Mission(notation_file, resources); + return new Mission(notation_file, resources); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity* + L4SpoolingApplication::MakeViewpointEntity(Entity__MakeMessage *) +{ + return NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical L4SpoolingApplication::ExecuteForeground(Time, Scalar) +{ + SET_FOREGROUND_PROCESSING(); + Check(this); + + // + //-------------------------------------------------------------------------- + // Controls Manager + // + // Poll all devices, update all control variables. + // + // This is executed before the update manager so that the + // models have valid control values. It is not necessary for + // the controls to operate at the frame rate of this loop. If + // the controls manager can run run at a lower rate it can + // throttle itself internally. + //-------------------------------------------------------------------------- + // + Check(controlsManager); + controlsManager->Execute(); + + CLEAR_FOREGROUND_PROCESSING(); + return executeFrames && !Exit_Code; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void L4SpoolingApplication::ExecuteBackgroundTask() +{ + Check(this); + + Check(networkManager); + if (!networkManager->RoutePacket()) + { + ProcessOneEvent(DefaultEventPriority); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4SpoolingApplication::Shutdown(int remainingApps) +{ + Check(this); + + L4Application::Shutdown(remainingApps); + return !Exit_Code && !missionSpooled; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4SpoolingApplication::~L4SpoolingApplication() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4SpoolingApplication::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +//########################### SpoolerTask ############################### +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolerTask::SpoolerTask() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolerTask::DispatchPacket(NetworkPacket *) +{ + Fail("SpoolerTask::DispatchPacket - shouldn't be here!"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + SpoolerTask::GetTimeBias() +{ + Fail("SpoolerTask::GetTimeBias - shouldn't be here!"); + return 0; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + SpoolerTask::Execute() +{ + Check(this); + Check(application); + + SpoolFile* spool = application->GetSpoolFile(); + if (!spool) + { + return; + } + + // + //----------------------------------------------------------------------- + // We have a spool file, so interpret it based upon the application state + //----------------------------------------------------------------------- + // + Check(spool); + NetworkPacket *packet; + switch (application->GetApplicationState()) + { + // + //----------------------------------------------------------------------- + // If we are waiting for an egg, post the egg messages to the application + // from the spool + //----------------------------------------------------------------------- + // + case Application::WaitingForEgg: + packet = (NetworkPacket*)spool->GetPointer(); + while (packet->clientID == NetworkClient::NetworkManagerClientID) + { + spool->NextPacket(); + DispatchPacket(packet); + packet = (NetworkPacket*)spool->GetPointer(); + } + break; + + // + //------------------------------------------------------------------- + // If the application is loading, then move off the block of interest + // messages into the interest manager + //------------------------------------------------------------------- + // + case Application::CreatingMission: + case Application::LoadingMission: + packet = (NetworkPacket*)spool->GetPointer(); + while ( + packet->clientID != NetworkClient::ApplicationClientID + && spool->GetBytesRemaining() > 0 + ) + { + spool->NextPacket(); + DispatchPacket(packet); + packet = (NetworkPacket*)spool->GetPointer(); + } + break; + + // + //------------------------------------------------------------------- + // These messages need to be doled out based upon the system time, as + // modified by when the run message was received + //------------------------------------------------------------------- + // + + case Application::LaunchingMission: + case Application::RunningMission: + while (spool && spool->GetBytesRemaining() > 0) + { + packet = (NetworkPacket*)spool->GetPointer(); + Time when = packet->timeStamp; + when.ticks += GetTimeBias(); + if (when > Now()) + { + break; + } + spool->NextPacket(); + DispatchPacket(packet); + spool = application->GetSpoolFile(); + } + break; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SpoolerTask::~SpoolerTask() +{ +} diff --git a/MUNGA_L4/L4SPLR.h b/MUNGA_L4/L4SPLR.h new file mode 100644 index 0000000..c9a5f05 --- /dev/null +++ b/MUNGA_L4/L4SPLR.h @@ -0,0 +1,204 @@ +#pragma once + +#include "l4net.h" +#include "l4app.h" +#include "..\munga\spooler.h" +#include "..\munga\interest.h" +#include "..\munga\apptask.h" + +//########################################################################## +//#################### SpoolingInterestManager ######################### +//########################################################################## + +class SpoolingInterestManager: + public InterestManager +{ +public: + SpoolingInterestManager(); + ~SpoolingInterestManager(); + + void + LoadInterestArenas(Mission *mission); + void + LoadMission(Mission *mission); + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + void + Shutdown(); +}; + +//########################################################################## +//################### L4SpoolingNetworkManager ######################### +//########################################################################## + +class L4SpoolingNetworkManager: + public L4NetworkManager +{ +public: + L4SpoolingNetworkManager(); + ~L4SpoolingNetworkManager(); + + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + void + StartConnecting(Mission *mission); +}; + +//########################################################################## +//################### L4PlaybackNetworkManager ######################### +//########################################################################## + +class L4PlaybackNetworkManager: + public NetworkManager +{ +public: + L4PlaybackNetworkManager(); + ~L4PlaybackNetworkManager(); + + void + StartConnecting(Mission *mission); + + Logical + Shutdown(); + + Logical + CheckBuffers(NetworkPacket*); +}; + +//########################################################################## +//################### L4SpoolingApplication ########################## +//########################################################################## + +class L4SpoolingApplication: + public L4Application +{ +public: + L4SpoolingApplication( + HINSTANCE hInstance, + HWND hWnd, + ResourceFile *resource, + ApplicationID application_ID + ); + ~L4SpoolingApplication(); + + SpoolingInterestManager* + GetInterestManager() + { + return + (SpoolingInterestManager*)Application::GetInterestManager(); + } + + L4SpoolingNetworkManager* + GetNetworkManager() + { + return + (L4SpoolingNetworkManager*)Application::GetNetworkManager(); + } + + MissionReviewApplicationManager* + GetApplicationManager() + { + return + (MissionReviewApplicationManager*) + Application::GetApplicationManager(); + } + +protected: + Registry* + MakeRegistry(); + InterestManager* + MakeInterestManager(); + NetworkManager* + MakeNetworkManager(); + + Mission* + MakeMission( + NotationFile *notation_file, + ResourceFile *resources + ); + + VideoRenderer* + MakeVideoRenderer(); + AudioRenderer* + MakeAudioRenderer(); + GaugeRenderer* + MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index); + + Entity* + MakeViewpointEntity(Entity__MakeMessage *); + + void + Initialize(); + void + LoadBackgroundTasks(); + Logical + Shutdown(int remainingApps); + + + void + ReceiveNetworkPacket( + NetworkPacket *packet, + Receiver::Message *packet_message + ); + + Logical + ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ); + void + ExecuteBackgroundTask(); + +protected: + Logical + missionSpooled; + +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + + void + LoadMissionMessageHandler(Message *message); + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); + void + AbortMissionMessageHandler(AbortMissionMessage *message); + + Logical + TestInstance() const; +}; + +extern L4SpoolingApplication * &l4_spooling_application; + +//########################################################################## +//######################## SpoolerTask ############################### +//########################################################################## + +class SpoolerTask: + public ApplicationTask +{ +public: + SpoolerTask(); + ~SpoolerTask(); + + void + Execute(); + + virtual void + DispatchPacket(NetworkPacket *packet); + virtual long + GetTimeBias(); +}; diff --git a/MUNGA_L4/L4TIME.cpp b/MUNGA_L4/L4TIME.cpp new file mode 100644 index 0000000..75a2d0d --- /dev/null +++ b/MUNGA_L4/L4TIME.cpp @@ -0,0 +1,162 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4time.h" +//#include +//#include +#include +#include + +//############################################################################# +//########################### System Clock ############################## +//############################################################################# + +SystemClock SystemClock::timer; +long SystemClock::ticksPerSecond; +__int64 SystemClock::perfCounterFreq; + +//RB 1/20/07 +//volatile long fast_time = 0L; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//void outportb(short portid, unsigned char value) +//{ +// __asm +// { +// MOV DX, portid +// MOV AL, value +// OUT DX, AL +// } +// __outbyte(portid, value); +//} +////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//// +//unsigned char inportb(short portid) +//{ +// unsigned char retVal; +// __asm +// { +// MOV DX, portid +// IN AL, DX +// MOV retVal, AL +// } +// return retVal; +//} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +/*TIME RB 1/20/07 +void Timer_Handler() +{ + ++fast_time; +}*/ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long SystemClock::GetRTC() +{ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return (long)((count.QuadPart * (__int64)1000) / SystemClock::perfCounterFreq); +} + +double SystemClock::GetHiRes() +{ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return (count.QuadPart / (double)SystemClock::perfCounterFreq); +} + +__int64 SystemClock::GetHiResTicks() +{ + LARGE_INTEGER count; + QueryPerformanceCounter(&count); + return count.QuadPart; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +SystemClock::SystemClock() +{ + // + //------------------------------- + // Initialize the timer variables + //------------------------------- + // + pauseStart = 0; + pauseTime = 0; + + // + //------------------------------ + // Initialize the platform timer + //------------------------------ + // + // query the performance counter for its frequency + LARGE_INTEGER freq; + QueryPerformanceFrequency(&freq); + //SystemClock::ticksPerSecond = freq.QuadPart; + SystemClock::perfCounterFreq = freq.QuadPart; + SystemClock::ticksPerSecond = 1000L; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void SystemClock::Shutdown() +{ + /*STUBBED: TIME RB 1/20/07 + if (timer_handler_handle != 0xFFFF) + { + #if DEBUG_LEVEL>0 + WORD err = sosTIMERRemoveEvent(timer_handler_handle); + Verify(err == _ERR_NO_ERROR); + err = sosTIMERUnInitSystem(0); + Verify(err == _ERR_NO_ERROR); + #else + sosTIMERRemoveEvent(timer_handler_handle); + sosTIMERUnInitSystem(0); + #endif + } + */ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +#define TIMER_CONTROL 0x43 +#define GET_TIMER0 0xC2 +#define TIMER0_PORT 0x40 +#define OUTPUT_BIT 0x80 + +#undef inportb +#undef outportb + +float Get_Frame_Percent_Used() +{ + //STUBBED: SOS RB 1/14/07 + + ///* RB 1/11/07 + //outportb(TIMER_CONTROL, GET_TIMER0); + //int half = inportb(TIMER0_PORT) & OUTPUT_BIT; + //int subtick = ((int)inportb(TIMER0_PORT)) >> 1; + //subtick += (((int)inportb(TIMER0_PORT)) << 7); + //*/ + + //__outbyte(TIMER_CONTROL, GET_TIMER0); + //int half = __inbyte(TIMER0_PORT) & OUTPUT_BIT; + //int subtick = ((int)__inbyte(TIMER0_PORT)) >> 1; + //subtick += (((int)__inbyte(TIMER0_PORT)) << 7); + + //if (timer_handler_handle == 0xFFFF) + //{ + // subtick += half << 8; + // return (65535 - subtick) / 65536.0f; + //} + //else + //{ + // if (half) + // { + // subtick += _wTIMERValue >> 1; + // } + // return (_wTIMERValue - 1 - subtick) / (float)_wTIMERValue; + //} + return 0.0f; +} diff --git a/MUNGA_L4/L4TIME.h b/MUNGA_L4/L4TIME.h new file mode 100644 index 0000000..6b77f9f --- /dev/null +++ b/MUNGA_L4/L4TIME.h @@ -0,0 +1,6 @@ +#pragma once + +#include "..\munga\time.h" + +#define TIMER_ENV "L4TIMER" +#define USE_SOS_TIMER "FAST" \ No newline at end of file diff --git a/MUNGA_L4/L4TOOL.h b/MUNGA_L4/L4TOOL.h new file mode 100644 index 0000000..5fd385a --- /dev/null +++ b/MUNGA_L4/L4TOOL.h @@ -0,0 +1,68 @@ +#pragma once + +#include "..\munga\tool.h" +#include "..\munga\audtools.h" + +class L4Tool: + public PlatformTool +{ +public: + ResourceDescription::ResourceID + CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelAudioStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelGaugeStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelGaugeImageStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateModelGaugeMissionReviewStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + + ResourceDescription::ResourceID + CreateStaticAudioStreamResource( + ResourceFile *resource_file + ); + + FindNameFunction + GetControlMappingFunction(); +}; + +//########################################################################## +//##################### AudioCreateSymbols ########################### +//########################################################################## + +class L4AudioCreateSymbols: + public AudioCreateSymbols +{ +protected: + void WriteEntryStream(std::ofstream &symbol_file); +}; diff --git a/MUNGA_L4/L4TRACE.cpp b/MUNGA_L4/L4TRACE.cpp new file mode 100644 index 0000000..f23ad48 --- /dev/null +++ b/MUNGA_L4/L4TRACE.cpp @@ -0,0 +1,127 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "..\munga\style.h" + +void* Get_Caller(int level) +{ + char *address; + __asm MOV address, EBP; + while (level--) + { + Check_Pointer(address); + address = *(char**)address; + } + Check_Pointer(address); + return *(char**)(address+4); +} + +#if defined(USE_ACTIVE_PROFILE) + #undef inportb + #undef outportb + + // + // table of data representing bits on the parallel port at 0x378 (usually LPT1) + // DO NOT ALTER THIS DATA - IT REQUIRES LOTS OF SCHEMATIC TRACING TO DUPLICATE + // + struct ParallelBit + { + unsigned int port; + Byte mask; + int sense; + }; + + ParallelBit Bit_Table[12] = + { + {0x378, 0x80, 0x00}, + {0x378, 0x40, 0x00}, + {0x378, 0x20, 0x00}, + {0x378, 0x10, 0x00}, + {0x37a, 0x08, 0x01}, + {0x37a, 0x04, 0x00}, + {0x37a, 0x02, 0x01}, + {0x37a, 0x01, 0x01}, + {0x378, 0x08, 0x00}, + {0x378, 0x04, 0x00}, + {0x378, 0x02, 0x00}, + {0x378, 0x01, 0x00} + }; + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void BitTrace::SetLineImplementation(Byte line) + { + Verify(line < ELEMENTS(Bit_Table)); + + // + //------------------------------------------------------------------ + // read the current value of the appropriate port + //------------------------------------------------------------------ + // + Byte port_value = inportb(Bit_Table[line].port); + + // + //------------------------------------------------------------------ + // set the appropriate bit, taking into account the hardware sense + //------------------------------------------------------------------ + // + if (!Bit_Table[line].sense) + { + port_value |= Bit_Table[line].mask; + } + else + { + port_value &= (Byte)(~Bit_Table[line].mask); + } + + // + //------------------------------------------------------------------ + // put the modified value into the appropriate port + //------------------------------------------------------------------ + // + outportb(Bit_Table[line].port, port_value); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + void BitTrace::ClearLineImplementation(Byte line) + { + Verify(line < ELEMENTS(Bit_Table)); + + // + //------------------------------------------------------------------ + // read the current value of the appropriate port + //------------------------------------------------------------------ + // + Byte port_value = inportb(Bit_Table[line].port); + + // + //------------------------------------------------------------------ + // clear the appropriate bit, taking into account the hardware sense + //------------------------------------------------------------------ + // + if (!Bit_Table[line].sense) + { + port_value &= (Byte)(~Bit_Table[line].mask); + } + else + { + port_value |= Bit_Table[line].mask; + } + + // + //------------------------------------------------------------------ + // put the modified value into the appropriate port + //------------------------------------------------------------------ + // + outportb(Bit_Table[line].port, port_value); + } + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Logical + BitTrace::IsLineValidImplementation(Byte line) + { + return line= 1.0f) + { + value = 1.0f; + direction = - direction; + } + else if (value <= -1.0f) + { + value = -1.0f; + direction = - direction; + } + bar->UpdateParameters(); + bar->Execute(); + display->Update(0); + } + getch(); + + Check(bar); + Unregister_Object(bar); + delete bar; + + Check(port); + Unregister_Object(port); + delete port; + + Check(display); + Unregister_Object(display); + delete display; + } + #endif + + // + //------------------------------------------------- + // Test Audio Hardware + //------------------------------------------------- + // + #if 0 + { + char *blaster1, *blaster2; + + blaster1 = getenv(FRONT_CARD_ENV_VAR); + blaster2 = getenv(REAR_CARD_ENV_VAR); + + //cout << "Audio test...\n" << flush; + + Check_Pointer(blaster1); + Check_Pointer(blaster2); + + AudioHardware::TestClass(); + // AudioHardware::ProfileClass(); + } + #endif + + // + //-------------------------------------------- + // Stop registering, and tell us about its use + //-------------------------------------------- + // + Stop_Registering(); + Tell("Exiting\n"); + #endif + + return 0; +} diff --git a/MUNGA_L4/L4VB16.cpp b/MUNGA_L4/L4VB16.cpp new file mode 100644 index 0000000..942fad7 --- /dev/null +++ b/MUNGA_L4/L4VB16.cpp @@ -0,0 +1,5935 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4vb16.h" +#include "../munga/gaugrend.h" +#include "L4VIDEO.h" +#include "DXUtils.h" + +#if defined(TRACE_SCREEN_COPY) + static BitTrace Screen_Copy("Screen Copy"); + #define SET_SCREEN_COPY() Screen_Copy.Set() + #define CLEAR_SCREEN_COPY() Screen_Copy.Clear() +#else + #define SET_SCREEN_COPY() + #define CLEAR_SCREEN_COPY() +#endif + +#define BLIT_STATISTICS + +#if defined(BLIT_STATISTICS) + static int + dirtyPixelCount, + transferPixelCount, + overflowPixelCount; +#endif + +//#define DEBUG + +#if defined(DEBUG) + static Logical + printFlag=True; +# define Diag_on printFlag=True +# define Diag_off printFlag=False +# define Diag_Tell(stuff) if(printFlag){std::cout << stuff;} +#else +# define Diag_on +# define Diag_off +# define Diag_Tell(n) +#endif + +//STUBBED: VIDEO RB 1/15/07 +//extern "C" void +// SVGASetMode( +// int mode, +// LWord pageFlipFcnpointer +// ); +// +//extern "C" void +// SVGASetPage( +// int page +// ); +// +//extern "C" int +// SVGATransfer32( +// int dest_offset, +// Word *source_pointer, +// LWord changed_bits +// ); +// +//extern "C" int +// SVGATransfer32x( +// int dest_offset, +// Word *source_pointer, +// LWord changed_bits +// ); +// +//extern "C" void +// SVGASetSplitterClock( +// Logical state +// ); +// +//extern "C" void +// SVGAZeroPalette( +// Word DAC_port +// ); +// +//extern "C" void +// SVGAWriteFullPalette( +// Byte *firstColorByte, +// Word DAC_port +// ); +// +//extern "C" void +// SVGAReadFullPalette( +// Byte *firstColorByte, +// Word DAC_port +// ); +// +//extern "C" void +// SVGAWritePaletteMask( +// Word DAC_port, +// Byte new_mask +// ); +// +//extern "C" void +// SVGAFunkyVideo( +// Logical on_off +// ); + + +void SVGA16::BuildWindows(unsigned int width, unsigned int height, bool windowed, int *secondaryIndex, int *aux1Index, int *aux2Index) +{ + NUMGAUGEWINDOWS = 0; + + if (secondaryIndex != NULL) + { + NUMGAUGEWINDOWS++; + } + + if (aux1Index != NULL) + { + NUMGAUGEWINDOWS++; + } + + if (aux2Index != NULL) + { + NUMGAUGEWINDOWS++; + } + + if (NUMGAUGEWINDOWS == 0) + { + return; + } + + gaugeWindows = new HWND[NUMGAUGEWINDOWS]; + mDevice = new LPDIRECT3DDEVICE9[NUMGAUGEWINDOWS]; + mVertBuffers = new LPDIRECT3DVERTEXBUFFER9[NUMGAUGEWINDOWS]; + mSurfaces = new LPDIRECT3DTEXTURE9[NUMGAUGEWINDOWS * 2]; + mLockFlags = new DWORD[NUMGAUGEWINDOWS]; + mPresentParams = new D3DPRESENT_PARAMETERS[NUMGAUGEWINDOWS]; + mSurfaceRects = new RECT[NUMGAUGEWINDOWS]; + for (int j=0; j < NUMGAUGEWINDOWS; j++) + { + int desiredAdapter = -1; + + int adapterIndex = j; + + if (secondaryIndex != NULL && adapterIndex >= 0) + { + desiredAdapter = *secondaryIndex; + adapterIndex--; + } + + if (aux1Index != NULL && adapterIndex >= 0) + { + desiredAdapter = *aux1Index; + adapterIndex--; + } + + if (aux2Index != NULL && adapterIndex >= 0) + { + desiredAdapter = *aux2Index; + adapterIndex--; + } + + if (adapterIndex >= 0 || desiredAdapter < 0) + { + break; + } + + RECT r; + + MONITORINFO info; + info.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(gD3D->GetAdapterMonitor(desiredAdapter),&info); + r = info.rcMonitor; + + mSurfaceRects[j].left = r.left; + mSurfaceRects[j].top = r.top; + mSurfaceRects[j].right = r.left + ((j==0 || aux2Index != NULL)?width:width*2); + mSurfaceRects[j].bottom = r.top + height; + + RECT surfaceWindowRect = mSurfaceRects[j]; + AdjustWindowRectEx(&surfaceWindowRect, WS_BORDER, false, 0); + + gaugeWindows[j] = CreateWindowEx(0, L"MainWndClass", L"RPL4", WS_BORDER, surfaceWindowRect.left, surfaceWindowRect.top, surfaceWindowRect.right-surfaceWindowRect.left, surfaceWindowRect.bottom-surfaceWindowRect.top, (HWND)NULL, (HMENU)NULL, L4Application::GetAppInstance(), (LPVOID)NULL); + if (gaugeWindows[j]) + { + ShowWindow(gaugeWindows[j], SW_SHOW); + + memset(&mPresentParams[j], 0, sizeof(D3DPRESENT_PARAMETERS)); + + mPresentParams[j].BackBufferCount = 1; + mPresentParams[j].SwapEffect = D3DSWAPEFFECT_DISCARD; + mPresentParams[j].hDeviceWindow = gaugeWindows[j]; + mPresentParams[j].Flags = 0; + mPresentParams[j].FullScreen_RefreshRateInHz = (windowed)?D3DPRESENT_RATE_DEFAULT:60; + mPresentParams[j].PresentationInterval = D3DPRESENT_RATE_DEFAULT; + mPresentParams[j].BackBufferFormat = D3DFMT_R5G6B5; + //pp.EnableAutoDepthStencil = TRUE; + //pp.AutoDepthStencilFormat = D3DFMT_D24X8; + mPresentParams[j].Windowed = windowed; + if (!windowed) + { + mPresentParams[j].BackBufferWidth = mSurfaceRects[j].right - mSurfaceRects[j].left; + mPresentParams[j].BackBufferHeight = mSurfaceRects[j].bottom - mSurfaceRects[j].top; + } + + + HRESULT hr = gD3D->CreateDevice(desiredAdapter, D3DDEVTYPE_HAL, ghWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &mPresentParams[j], &mDevice[j]); + if (FAILED(hr)) + { + DEBUG_STREAM<<"Couldn't create Direct3D device!"<GetDeviceCaps(&caps); + mLockFlags[j] = 0; + + hr = mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_SYSTEMMEM, &mSurfaces[j * 2], NULL); + if (FAILED(hr)) + { + DEBUG_STREAM << "Couldn't create dynamic texture for display " << j << "!" << std::endl << std::flush; + PostQuitMessage(1); + } + + hr = mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[j * 2 + 1], NULL); + if (FAILED(hr)) + { + DEBUG_STREAM << "Couldn't create dynamic texture for display " << j << "!" << std::endl << std::flush; + PostQuitMessage(1); + } + + hr = mDevice[j]->CreateVertexBuffer(sizeof(float) * 6 * 4, NULL, D3DFVF_XYZRHW | D3DFVF_TEX1, D3DPOOL_MANAGED, &mVertBuffers[j], NULL); + if (FAILED(hr)) + { + DEBUG_STREAM << "Couldn't create vertex buffer for display " << j << "!" << std::endl << std::flush; + PostQuitMessage(1); + } + + float *buffer; + hr = mVertBuffers[j]->Lock(0, 0, (void**)&buffer, 0); + + buffer[0] = 0.0f; // top left, x + buffer[1] = 0.0f; // y + buffer[2] = 0.0f; // z + buffer[3] = 1.0f; // rhw + buffer[4] = 0.0f; // u + buffer[5] = 0.0f; // v + + buffer[6] = mSurfaceRects[j].right - mSurfaceRects[j].left; // top right, x + buffer[7] = 0.0f; // y + buffer[8] = 0.0f; // z + buffer[9] = 1.0f; // rhw + buffer[10] = 1.0f; // u + buffer[11] = 0.0f; // v + + buffer[12] = mSurfaceRects[j].right - mSurfaceRects[j].left; // bottom right, x + buffer[13] = height; // y + buffer[14] = 0.0f; // z + buffer[15] = 1.0f; // rhw + buffer[16] = 1.0f; // u + buffer[17] = 1.0f, // v + + buffer[18] = 0.0f; // bottom left, x + buffer[19] = height; // y + buffer[20] = 0.0f; // z + buffer[21] = 1.0f; // rhw + buffer[22] = 0.0f; // u + buffer[23] = 1.0f; // v + + hr = mVertBuffers[j]->Unlock(); + + mDevice[j]->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1); + mDevice[j]->SetStreamSource(0, mVertBuffers[j], 0, sizeof(float) * 6); + mDevice[j]->SetTexture(0, mSurfaces[j * 2 + 1]); + + mDevice[j]->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 0.0f, 0); + V( mDevice[j]->Present(NULL, NULL, NULL, NULL) ); + if (hr == D3DERR_DEVICELOST) + { + int bbCount = mPresentParams[j].BackBufferCount; + int bbWidth = mPresentParams[j].BackBufferWidth; + int bbHeight = mPresentParams[j].BackBufferHeight; + + mSurfaces[j * 2 + 1]->Release(); + V(mDevice[j]->Reset(&mPresentParams[j])); + V(mDevice[j]->CreateTexture(mSurfaceRects[j].right - mSurfaceRects[j].left, height, 1, usage, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[j * 2 + 1], NULL)); + + mPresentParams[j].BackBufferCount = bbCount; + mPresentParams[j].BackBufferWidth = bbWidth; + mPresentParams[j].BackBufferHeight = bbHeight; + } + } + } +} + + +//######################################################################## +//############################# BitWrangler ############################## +//######################################################################## +// +// A "bitwrangler" manages a group of bits by segregating them into two groups: +// "active", and "inactive". Active bits are those specified within a given +// bit mask as "ones", and inactive bits are those specified as "zeros". +// +// Once initialized, the bitwrangler may be requested to increment either +// the active bit field or the inactive bit field: the "carry" is propagated +// from the least significant bit through the most significant bit, and if +// an overflow is generated it is returned as "False". +// +// Why in the world would anyone want such a bizarre object? +// It's used here to generate palettes and translation tables according +// to bit allocations for a GraphicsPort. "Unused" colors are easily +// found and set to proper values. +// +class BitWrangler +{ +public: + BitWrangler(int bit_mask, int total_length); + ~BitWrangler() + {} + void ResetActive(); + void ResetInactive(); + Logical IncrementActive(); + Logical IncrementInactive(); + int NumberOfActiveBits(); + int NumberOfInactiveBits(); + + int Value; +protected: + int length; + int bitMask; +}; + +// +// Bitwrangler initialization +// +BitWrangler::BitWrangler(int bit_mask, int total_length) +{ + Verify(bit_mask != 0); + + bitMask = bit_mask; + length = total_length; + Value = 0; + Check_Fpu(); +} + +// +// Reset all "active" bits to zero +// +void + BitWrangler::ResetActive() +{ + Value &= ~ bitMask; + Check_Fpu(); +} + +// +// Reset all "inactive" bits to zero +// +void + BitWrangler::ResetInactive() +{ + Value &= bitMask; + Check_Fpu(); +} + +// +// Increment the "active" bit field, and return "false" if overflow +// +Logical + BitWrangler::IncrementActive() +{ + int single_bit; + int count(length); + + for(single_bit=1; count>0; --count, single_bit <<= 1) + { + // + // If it's an active bit, process it + // + if (bitMask & single_bit) + { + // + // Invert the bit + // + Value ^= single_bit; + // + // If the bit is now set, it was zero, so exit + // + if (Value & single_bit) + { + Check_Fpu(); + return True; + } + } + } + // + // All the active bits are set, so return false + // + Check_Fpu(); + return False; +} + +// +// Increment the "inactive" bit field, and return "false" if overflow +// +Logical + BitWrangler::IncrementInactive() +{ + int single_bit; + int count(length); + int inverse_mask(~bitMask); + + for(single_bit=1; count>0; --count, single_bit <<= 1) + { + // + // If it's an inactive bit, process it + // + if (inverse_mask & single_bit) + { + // + // Invert the bit + // + Value ^= single_bit; + // + // If the bit is now set, it was zero, so exit + // + if (Value & single_bit) + { + Check_Fpu(); + return True; + } + } + } + // + // All the inactive bits are set, so return false + // + Check_Fpu(); + return False; +} + +// +// Return the number of "active" bits +// +int + BitWrangler::NumberOfActiveBits() +{ + int count(0), temp(bitMask); + + while(temp != 0) + { + ++count; + + temp = temp & (temp-1); + } + + Check_Fpu(); + return count; +} + +// +// Return the number of "inactive" bits +// +int + BitWrangler::NumberOfInactiveBits() +{ + Check_Fpu(); + return length-NumberOfActiveBits(); +} + +//######################################################################## +//######################### Video16BitBuffered ########################### +//######################################################################## +// +//NOTE: the application assumes that the origin is in the lower left +// corner of the display, and all parameters passed to these routines +// use the application's coordinate system. +// +// All of the methods here convert these values to the SCREEN +// coordinate system, with the origin in the UPPER LEFT corner of +// the display. +// + +//=================================================================== +// Creator +//=================================================================== +Video16BitBuffered::Video16BitBuffered(int x, int y): + GraphicsDisplay(x, y), + pixelBuffer(x, y) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::Video16BitBuffered()\n" + ); +# endif + int + i, + changed_size; + + Verify(pixelBuffer.Data.MapPointer != NULL); + + height = y; + width = x; + changedBitWidth = (width >> 5); + changed_size = height * changedBitWidth; + + maximumY = height-1; + maximumX = width-1; + //--------------------------------------------------------- + // Create 'changedLine' and 'changedBit' arrays + //--------------------------------------------------------- + changedLine = new Byte[height]; + changedBit = new LWord[changed_size]; + + if (changedLine == NULL || changedBit == NULL) + { +# if defined(DEBUG) + Tell("INVALID!\n"); +# endif + valid = False; + return; + } + else + { + Register_Pointer(changedLine); + Register_Pointer(changedBit); + valid = True; + } + +# if defined(DEBUG) + Tell("changedLine=" << changedLine << "\n"); + Tell("changedBit=" << changedBit << "\n"); +# endif + + //--------------------------------------------------------- + // Clear the 'changedBit' array + //--------------------------------------------------------- + memset(changedLine, 0, height); + //--------------------------------------------------------- + // Clear the 'changedBit' array + //--------------------------------------------------------- + LWord + *bit_dest; + + for (i=changed_size,bit_dest=changedBit; i>0; --i,++bit_dest) + { + *bit_dest = (LWord) 0; + } + Check_Fpu(); +} + +//=================================================================== +// Destructor +//=================================================================== +Video16BitBuffered::~Video16BitBuffered() +{ + Check(this); + + if (changedLine != NULL) + { + Unregister_Pointer(changedLine); + delete changedLine; + changedLine = NULL; + } + + if (changedBit != NULL) + { + Unregister_Pointer(changedBit); + delete changedBit; + changedBit = NULL; + } + Check_Fpu(); +} + + +//=================================================================== +// TestInstance +//=================================================================== +Logical + Video16BitBuffered::TestInstance() const +{ + return True; +} + +//=================================================================== +// ShowInstance +//=================================================================== +void + Video16BitBuffered::ShowInstance( + char *indent + ) +{ + std::cout << indent << "Video16BitBuffered:\n"; + + Check(this); + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "width =" << width << "\n"; + std::cout << temp << "height =" << height << "\n"; + std::cout << temp << "maximumX =" << maximumX << "\n"; + std::cout << temp << "maximumY =" << maximumY << "\n"; + std::cout << temp << "changedLine=" << changedLine << "\n"; + std::cout << temp << "changedBit =" << changedBit << "\n"; + + pixelBuffer.ShowInstance(temp); + GraphicsDisplay::ShowInstance(temp); + Check_Fpu(); +} + + +//=================================================================== +// buildDestPointer +//=================================================================== +void + Video16BitBuffered::buildDestPointer( + int screenX, + int screenY, + Word **pixel_pointer, + LWord **changed_bit_pointer, + LWord *changed_bit + ) +{ + Verify(valid); + + Verify(pixel_pointer != NULL); + Verify(changed_bit_pointer != NULL); + Verify(changed_bit != NULL); + + Verify(screenX >= 0); + Verify(screenX < width); + Verify(screenY >= 0); + Verify(screenY < height); + + *pixel_pointer = pixelBuffer.Data.MapPointer + + screenX + + (screenY * width); + Verify(*pixel_pointer >= pixelBuffer.Data.MapPointer); + Verify(*pixel_pointer < &pixelBuffer.Data.MapPointer[height*width]); + + *changed_bit_pointer = changedBit + + (screenX >> 5) + + (screenY * changedBitWidth); + Verify(*changed_bit_pointer >= changedBit); + Verify(*changed_bit_pointer < &changedBit[height*changedBitWidth]); + + *changed_bit = 1L << (0x1F - (screenX & 0x1F)); + Verify(*changed_bit != 0L); + + Diag_Tell( + "Video16BitBuffered::buildDestPointer(" << screenX << + ", " << screenY << std::hex << + ") = pix " << *pixel_pointer << + ", cbp " << *changed_bit_pointer << + ", cb " << *changed_bit << std::dec << + "\n" + ); + Diag_Tell("changedBitWidth=" << changedBitWidth << "\n"); + + Check_Fpu(); +} + +//=================================================================== +// MarkChangedLines +//=================================================================== +#if defined(BLIT_STATISTICS) +# define SET_CHANGED(pointer, bits) *pointer |= bits; ++dirtyPixelCount +#else +# define SET_CHANGED(pointer, bits) *pointer |= bits +#endif + +#define LEFT_CHANGED(pointer, bits) \ + bits <<= 1; \ + if (bits == 0) { --pointer; bits=0x00000001L; } + +#define RIGHT_CHANGED(pointer, bits) \ + bits >>= 1; \ + if (bits == 0) { ++pointer; bits=0x80000000L; } + +#define UP_CHANGED(pointer, bits) pointer -= changedBitWidth +#define DOWN_CHANGED(pointer, bits) pointer += changedBitWidth + + +#define LEFT_DEST(pointer) --pointer +#define RIGHT_DEST(pointer) ++pointer +#define UP_DEST(pointer) pointer -= width +#define DOWN_DEST(pointer) pointer += width + +#define LEFT_SOURCE(pointer,map) --pointer +#define RIGHT_SOURCE(pointer,map) ++pointer +#define UP_SOURCE(pointer,map) pointer -= map->Data.Size.x +#define DOWN_SOURCE(pointer,map) pointer += map->Data.Size.x + + + +#define LEFT_BITMAP(pointer,bits) \ + bits <<= 1; \ + if (bits == 0) { --pointer; bits=0x0001; } + +#define RIGHT_BITMAP(pointer, bits) \ + bits >>= 1; \ + if (bits == 0) { ++pointer; bits=0x8000; } + +#define UP_BITMAP(pointer,map) pointer -= map->Data.WidthInWords +#define DOWN_BITMAP(pointer,map) pointer += map->Data.WidthInWords + + +// +// Inputs are in DISPLAY COORDINATES, i.e., (0,0) in top left corner! +// +void + Video16BitBuffered::MarkChangedLines( + int start, + int stop + ) +{ + Check(this); + Diag_Tell( + "Video16BitBuffered::MarkChangedLines(" << start << + ", " << stop << + ")\n" + ); + + if (start > stop) + { +# if defined(DEBUG) + Tell("MarkChangedLines FLIPPING\n"); +# endif + int temp; + + temp = start; + start = stop; + stop = temp; + } + + Verify(start >= 0); + Verify(start <= maximumY); + Verify(stop >= 0); + Verify(stop <= maximumY); + + //------------------------------------------------ + // Set the flag for each changed line + //------------------------------------------------ + Verify(stop >= start); + memset(&changedLine[start], 1, stop-start+1); + + Check_Fpu(); +} + +//=================================================================== +// DrawPoint +//=================================================================== +void + Video16BitBuffered::DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ) +{ + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + Word + *dest_pointer; + LWord + *changed_pointer; + LWord + changed_bit; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); +# endif + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y, y); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Create pointers + //--------------------------------------------------------- + buildDestPointer( + x, y, + &dest_pointer, + &changed_pointer, + &changed_bit + ); + //--------------------------------------------------------- + // Write the point + //--------------------------------------------------------- + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + Check_Fpu(); +} + +//=================================================================== +// DrawLine +//=================================================================== +void + Video16BitBuffered::DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawLine(" << color << + ", " << bitmask << + ", " << operation << + ", " << x1 << "," << y1 << "," << x2 << "," << y2 << + ", " << include_last_pixel << + "\n" + ); +# endif + + Check(this); + + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + enum + { + negative_delta_x = 1, + negative_delta_y = 2, + delta_y_greater = 0, + delta_x_greater = 4 + }; + + long + length, + rate, + accumulator; + + int + octant, + delta_x, + delta_y; + + Word + *dest_pointer; + LWord + *changed_pointer; + LWord + changed_bit; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Route to DrawPoint if single pixel + //--------------------------------------------------------- + if (x1 == x2 && y1 == y2) + { + if (include_last_pixel) + { + DrawPoint(color, bitmask, operation, x1, y1); + } + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that endpoints are legitimate + //--------------------------------------------------------- + Verify(x1 >= 0); + Verify(x1 < width); + Verify(x2 >= 0); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 < height); + Verify(y2 >= 0); + Verify(y2 < height); + +# if defined(DEBUG) + Tell( + "Transformed coordinates=" << x1 << "," << y1 << + "," << x2 << "," << y2 << + "\n" + ); +# endif + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Determine which octant to use + //--------------------------------------------------------- + octant = 0; + + delta_x = x2 - x1; + if (delta_x < 0) + { +# if defined(DEBUG) + Tell("negative dx\n"); +# endif + octant |= negative_delta_x; + delta_x = - delta_x; + } + + delta_y = y2 - y1; + if (delta_y < 0) + { +# if defined(DEBUG) + Tell("negative dy\n"); +# endif + octant |= negative_delta_y; + delta_y = - delta_y; + } + + if (delta_x > delta_y) + { +# if defined(DEBUG) + Tell("dx > dy\n"); +# endif + octant |= delta_x_greater; + } +# if defined(DEBUG) + Tell( + "dx=" << delta_x << + ", dy=" << delta_y << + ", octant=" << octant << + ", color=" << color << + "\n" + ); +# endif + //--------------------------------------------------------- + // Prepare to draw line + //--------------------------------------------------------- + buildDestPointer( + x1, y1, + &dest_pointer, + &changed_pointer, + &changed_bit + ); + + accumulator = 1024L; // preset accumulator to 1/2 full + //--------------------------------------------------------- + // Draw the line! + //--------------------------------------------------------- + switch (octant) + { + case delta_y_greater: + //------------------------------------- + // delta y greater + // positive delta x + // positive delta y + // + // + + // \ & + // \ & + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + + Verify(delta_y > 0); + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_y_greater+negative_delta_x: + //------------------------------------- + // delta y greater + // negative delta x + // positive delta y + // + // + + // / + // / + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_y_greater+negative_delta_y: + //------------------------------------- + // delta y greater + // positive delta x + // negative delta y + // + // / + // / + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_y_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta y greater + // negative delta x + // negative delta y + // + // \ & + // \ & + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater: + //------------------------------------- + // delta x greater + // positive delta x + // positive delta y + // + // +---___ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater+negative_delta_x: + //------------------------------------- + // delta x greater + // negative delta x + // positive delta y + // + // ___---+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + DOWN_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater+negative_delta_y: + //------------------------------------- + // delta x greater + // positive delta x + // negative delta y + // + // +___--- + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + RIGHT_DEST(dest_pointer); + RIGHT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + } + } + break; + + case delta_x_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta x greater + // negative delta x + // negative delta y + // + // ---___+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + SET_CHANGED(changed_pointer, changed_bit); + + LEFT_DEST(dest_pointer); + LEFT_CHANGED(changed_pointer, changed_bit); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + UP_CHANGED(changed_pointer, changed_bit); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawFilledRectangle +//=================================================================== +void + Video16BitBuffered::DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ +# if defined(DEBUG) + Tell("Video16BitBuffered::DrawFilledRectangle(" << + color << ", " << + std::hex << bitmask << ", " << std::dec << + operation << ", " << + x1 << ", " << + y1 << ", " << + x2 << ", " << + y2 << ", " << + ")\n"); +# endif + Check(this); + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + Word + *dest_pointer; + LWord + *init_changed_pointer, + *changed_pointer; + LWord + init_changed_bit, + changed_bit; + int + x, + dest_fixup, + rect_width, + rect_height; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that rectangle is properly specified + //--------------------------------------------------------- + if (x2 < x1) + { + int temp; + + temp = x1; + x1 = x2; + x2 = temp; + } + + if (y2 < y1) + { + int temp; + + temp = y1; + y1 = y2; + y2 = temp; + } + //--------------------------------------------------------- + // Verify that values are legitimate + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + Verify(x1 >= 0); + Verify(x1 <= x2); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 <= y2); + Verify(y2 < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to fill + //--------------------------------------------------------- +# if defined(DEBUG) + Tell( + "x1=" << x1 << ", " << "y1=" << y1 << "\n" << + "x2=" << x2 << ", " << "y2=" << y2 << "\n" << + std::flush + ); +# endif + buildDestPointer( + x1, y1, + &dest_pointer, + &init_changed_pointer, + &init_changed_bit + ); + + rect_height = y2 - y1 + 1; + rect_width = x2 - x1 + 1; + dest_fixup = width - rect_width; + +# if defined(DEBUG) + Tell( + "rect_height=" << rect_height << "\n" << + "rect_width=" << rect_width << "\n" << + "dest_fixup=" << dest_fixup << "\n" << + std::flush + ); +# endif + //--------------------------------------------------------- + // Fill the rectangle + //--------------------------------------------------------- + switch(operation) + { + case GraphicsDisplay::Replace: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + dest_pointer++; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::And: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer++ &= (Word) color; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Or: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer++ |= (Word) color; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Xor: + for( ; rect_height>0; --rect_height) + { + changed_bit = init_changed_bit; + changed_pointer = init_changed_pointer; + DOWN_CHANGED(init_changed_pointer, init_changed_bit); + for(x=rect_width; x>0; --x) + { + *dest_pointer++ ^= (Word) color; + SET_CHANGED(changed_pointer, changed_bit); + RIGHT_CHANGED(changed_pointer, changed_bit); + } + dest_pointer += dest_fixup; + } + break; + } + Check_Fpu(); +} + + +void + Video16BitBuffered::DrawText( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +# if defined(DEBUG) + Tell("Video16BitBuffered::DrawText()\n"); +# endif + Check(this); + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + Check_Fpu(); + if (!valid) + { + return; + } +} + +//=================================================================== +// DrawBitMap +//=================================================================== +void + Video16BitBuffered::DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawBitMap(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + switch (rotation) + { + default: + //-------------------------------------------- + // transparent bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "zero: xp=" << (x+map_width-1) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width-1 >= 0); + Verify(x+map_width-1 < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent bitmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n"); +# endif + + if (x-map_height < 0) + { + Tell("x-map_height = " << (x - map_height) << "\n"); + return; + } + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawBitMapOpaque +//=================================================================== +void + Video16BitBuffered::DrawBitMapOpaque( + int foreground, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + +Diag_on; + Diag_Tell( + "Video16BitBuffered::DrawBitMapOpaque(<" << x << + ", " << y << + ">,<" << sLeft << + ", " << sBottom << + ", " << sRight << + ", " << sTop << + ">)\n" + ); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + Word + color; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +Diag_off; + Diag_Tell("x=" << x << ", y=" << y << "\n"); + Diag_Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Diag_Tell( + "map_width=" << map_width << + ", map_height=" << map_height << + "\n" + ); +Diag_on; + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + //--------------------------------------------------------- + // The bitmap is always read left-to-right, bottom-to-top. + // We write it to the screen in different directions + // based on the rotation. + //--------------------------------------------------------- + switch (rotation) + { + default: + //-------------------------------------------- + // opaque bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width <= width); // HACK? <, or <=? + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // opaque bitmap, 90 degrees + // #--Y--. + // | | + // X | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // opaque bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // opaque bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "xp=" << (x-map_height+1) << + ", yp=" << (y-(map_width-1)) << + "\n" + ); +# endif + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + Diag_Tell( + "(y-(map_width-1))=" << (y-(map_width-1)) << + ", y=" << y << + "," + ); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Word) foreground; + } + else + { + color = (Word) background; + } + { + switch (operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + Diag_Tell( + "changed_pointer=" << changed_pointer << std::dec << + "\n" + ); + + break; + } + Check_Fpu(); +Diag_off; +} + +//=================================================================== +// DrawPixelMap8 +//=================================================================== +void + Video16BitBuffered::DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawPixelMap8(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + source_data, + *source_pointer_begin, + *source_pointer; + + Word + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + Word + color; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + if (opaque) + { + switch (rotation) + { + default: + //-------------------------------------------- + // Opaque pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Opaque pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << + "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Opaque pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << + "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Opaque pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Opaque 270: x=" << x << ", y=" << y << "\n"); + Tell( + "xp=" << (x-map_height) << + ", yp=" << (y-(map_width-1)) << + "\n" + ); +# endif + Verify(x-map_height-1 >= 0); + Verify(x-map_height-1 < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + } + else + { + switch (rotation) + { + default: + //-------------------------------------------- + // Transparent pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << + "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << + "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("transparent 270: x=" << x << ", y=" << y << "\n"); + Tell( + "xp=" << (x-map_height) << + ", yp=" << (y-(map_width-1)) << + "\n" + ); +# endif + Verify(x-(map_height-1) >= 0); + Verify(x-(map_height-1) < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + color = (Word) translation_table[source_data]; + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//=================================================================== +// DrawPixelMap8SingleColor +//=================================================================== +void + Video16BitBuffered::DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video16BitBuffered::DrawPixelMap8SingleColor(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + source_data, + *source_pointer_begin, + *source_pointer; + + Word + *dest_pointer_begin, + *dest_pointer; + + LWord + changed_bit_begin, + changed_bit, + *changed_pointer_begin, + *changed_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- + bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer.Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin, + &changed_pointer_begin, + &changed_bit_begin + ); + + { + switch (rotation) + { + default: + //-------------------------------------------- + // Single-color pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << + "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_CHANGED(changed_pointer_begin, changed_bit_begin); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + RIGHT_CHANGED(changed_pointer, changed_bit); + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Single-color pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << + "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_CHANGED(changed_pointer_begin, changed_bit_begin); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word) ((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + DOWN_CHANGED(changed_pointer, changed_bit); + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Single-color pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << + "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_CHANGED(changed_pointer_begin, changed_bit_begin); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + LEFT_CHANGED(changed_pointer, changed_bit); + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Single-color pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Single-color 270: x=" << x << ", y=" << y << "\n"); + Tell( + "xp=" << (x-map_height) << + ", yp=" << (y-map_width) << + "\n" + ); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-map_width >= 0); + Verify(y-map_width < height); + + MarkChangedLines(y-map_width, y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + changed_pointer = changed_pointer_begin; + changed_bit = changed_bit_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_CHANGED(changed_pointer_begin, changed_bit_begin); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer.Data.MapPointer); + Verify(dest_pointer < pixelBuffer.Data.MapPointer+ + (width*height)); + + Verify(changed_pointer >= changedBit); + Verify(changed_pointer < changedBit+(changedBitWidth*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + switch(operation) + { + case GraphicsDisplay::Replace: + *dest_pointer = (Word)((*dest_pointer & bitmask) | color); + break; + + case GraphicsDisplay::And: + *dest_pointer &= (Word) color; + break; + + case GraphicsDisplay::Or: + *dest_pointer |= (Word) color; + break; + + case GraphicsDisplay::Xor: + *dest_pointer ^= (Word) color; + break; + } + SET_CHANGED(changed_pointer, changed_bit); + } + UP_CHANGED(changed_pointer, changed_bit_begin); + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//######################################################################## +//############################ SVGA640x480x16 ############################ +//######################################################################## +SVGA16::SVGA16( + int mode, + int init_width, + int init_height, + int mem_page_size, + int mem_granularity, + int bytes_per_line, + int page_function_pointer, + int special_interface, + bool windowed, + int *secondaryIndex, + int *aux1Index, + int *aux2Index +):Video16BitBuffered(init_width, init_height) +{ + BuildWindows(init_width,init_height,windowed, secondaryIndex, aux1Index, aux2Index); +//STUBBED: VIDEO RB 1/15/07 +# if defined(DEBUG) + Tell("SVGA16::SVGA16()\n"); +# endif + + pageSize = mem_page_size * 1024; + Verify(mem_granularity > 0); + pageDelta = mem_page_size/mem_granularity; + widthInBytes = bytes_per_line; + pageFcnPtr = page_function_pointer; + specialInterface = special_interface; // currently unused + + currentPageNumber = -1; + + // + // Set video mode + // + //SVGASetMode(mode, pageFcnPtr); + // + // Set VWE video splitter clock divider + // + //SVGASetSplitterClock(True); + + //------------------------------------------------------------------------ + // Initialize palettes + //------------------------------------------------------------------------ + FadeToWhite(0.0); + //------------------------------------------------------------------------ + // Initialize palette data + //------------------------------------------------------------------------ + // The +2 causes Adam's std::decoded Palette addresses to "match up" + // with the address definitions used by the standard VGA palette port. + // Adam's port std::decoder design uses: + // xx00 = write address port + // xx01 = data port + // xx10 = pixel mask port + // xx11 = read address port + // The standard VGA/SVGA ports are: + // 03C6 = ......0110 = xx10 = pixel mask port + // 03C7 = ......0111 = xx11 = read address port + // 03C8 = ......1000 = xx00 = write address port + // 03C9 = ......1001 = xx01 = data port + // Adam's ports are: + // 0300 = secondary palette + // 0308 = auxiliary palette 1 + // 0310 = auxiliary palette 2 + // By adding 2 to "Adam's" port assignments, they match with a VGA: + // 0302/030A/0312 = xx10 = pixel mask port + // 0303/030B/0313 = xx11 = read address port + // 0304/030C/0314 = xx00 = write address port + // 0305/030D/0315 = xx01 = data port + + // See L4VB16.hpp, class SVGA16 for an enumeration of palettes + // matching this table. + + static Word port_addr[PaletteCount] = { + 0x3C6, // NativePalette + 0x300+2, // SecondaryPalette + 0x308+2, // AuxiliaryPalette1 + 0x310+2 // AuxiliaryPalette2 + }; + + SVGA16Palette + *palette_pointer = &palette[0]; + for(int i=0; ihardwarePort = port_addr[i]; + palette_pointer->modified = False; + palette_pointer->flashAccumulator = 0.0; + palette_pointer->flashRate = 0.0; + palette_pointer->previousMaskState = -1; + + for(j=0; jmask[j] = 0xFF; + } + + /*if (port_addr[i] != 0x3C6) + { + SVGAZeroPalette(port_addr[i]); + }*/ + } + //--------------------------------------------------------- + // Prepare update values + //--------------------------------------------------------- + currentPageNumber = -1; + + ResetUpdatePosition(); + +# if defined(BLIT_STATISTICS) + dirtyPixelCount = 0; + transferPixelCount = 0; + overflowPixelCount = 0; +# endif + //--------------------------------------------------------- + // Clear the display + //--------------------------------------------------------- +# if defined(DEBUG) + Tell("Valid, drawing rectangle-\n" << std::flush); +# endif + DrawFilledRectangle( + 0, + 0xFFFF, + GraphicsDisplay::Replace, + 0, 0, + maximumX, maximumY + ); +# if defined(DEBUG) + Tell("About to update-\n" << std::flush); +# endif + Update(False); + Check_Fpu(); + + mDisplayToUpdate = 0; +} + +SVGA16::~SVGA16() +{ + for (int i=0; i < NUMGAUGEWINDOWS; i++) + { + if (mSurfaces[i * 2] != NULL) + { + mSurfaces[i * 2]->Release(); + mSurfaces[i * 2] = NULL; + } + if (mSurfaces[i * 2 + 1] != NULL) + { + mSurfaces[i * 2 + 1]->Release(); + mSurfaces[i * 2 + 1] = NULL; + } + + if (mDevice[i] != NULL) + { + mDevice[i]->Release(); + mSurfaces[i] = NULL; + } + + DestroyWindow(gaugeWindows[i]); + } + +//STUBBED: VIDEO RB 1/15/07 +# if defined(DEBUG) + Tell("SVGA16::~SVGA16()\n"); +# endif + Check(this); + //--------------------------------------------------------- + // Eventually wait for fade (if any) to complete?? + //--------------------------------------------------------- + + //--------------------------------------------------------- + // Set video mode + //--------------------------------------------------------- + //SVGASetMode(3, 0); +# if defined(BLIT_STATISTICS) + double + ratio; + + if (transferPixelCount == 0) + { + ratio = (double) 0; + } + else + { + ratio = ((double) dirtyPixelCount) / transferPixelCount; + } + + //------------------------------------------------------ + // Print statistics + //------------------------------------------------------ + DEBUG_STREAM << + "SVGA16::~SVGA16: pixel management statistics ------------" << + "\nNumber of dirty pixels =" << dirtyPixelCount << + "\nNumber of transferred pixels=" << transferPixelCount << + "\nTimes overflowed =" << overflowPixelCount << + "\nRatio =" << ratio << + "\n-------------------------------------------------------\n"; +# endif + //--------------------------------------------------------- + // Set VWE video splitter clock divider + //--------------------------------------------------------- + //SVGASetSplitterClock(False); + Check_Fpu(); +} + +Logical + SVGA16::TestInstance() const +{ + return Video16BitBuffered::TestInstance(); +} + +void + SVGA16::ShowInstance(char *indent) +{ + std::cout << indent << "SVGA16:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "SVGA16:\n"; + Video16BitBuffered::ShowInstance(temp); + Check_Fpu(); +} + +int GetShiftAmount(DWORD mask) +{ + int amount = -1; + while (mask) + { + mask >>= 1; + amount++; + } + return amount; +} + +Logical SVGA16::Update(Logical forceAll) +{ + HRESULT hr; + + GaugeRenderer *renderer = application->GetGaugeRenderer(); + if (!valid || renderer == NULL) + { + CLEAR_SCREEN_COPY(); + return False; // Do no more! + } + + if (++mDisplayToUpdate >= NUMGAUGEWINDOWS) + mDisplayToUpdate = 0; + + //Top MFD's + L4GraphicsPort *UL = static_cast(renderer->GetGraphicsPort("auxUL2")); + L4GraphicsPort *Cent = static_cast(renderer->GetGraphicsPort("auxC")); + L4GraphicsPort *UR = static_cast(renderer->GetGraphicsPort("auxUR2")); + //Bottom MFD's + L4GraphicsPort *LL = static_cast(renderer->GetGraphicsPort("auxLL")); + L4GraphicsPort *LR = static_cast(renderer->GetGraphicsPort("auxLR")); + //Secondary + L4GraphicsPort *secPort = static_cast(renderer->GetGraphicsPort("sec")); + + DWORD ulMask = 0, ucMask = 0, urMask = 0, llMask = 0, lrMask = 0; + int ulMask_sh = 0, ucMask_sh = 0, urMask_sh = 0, llMask_sh = 0, lrMask_sh = 0; + int secMask = 0; + SVGA16Palette *secPalette = NULL; + + if (this->mDisplayToUpdate == 1 || this->mDisplayToUpdate == 2) + { + //Drawing MFD's... make sure we have MFDs to draw + if (UL != NULL && Cent != NULL && UR != NULL && LL != NULL && LR != NULL) + { + ulMask = UL->GetBitMask(); + ulMask_sh = GetShiftAmount(ulMask); + ulMask |= (ulMask << 16); + + ucMask = Cent->GetBitMask(); + ucMask_sh = GetShiftAmount(ucMask); + ucMask |= (ucMask << 16); + + urMask = UR->GetBitMask(); + urMask_sh = GetShiftAmount(urMask); + urMask |= (urMask << 16); + + llMask = LL->GetBitMask(); + llMask_sh = GetShiftAmount(llMask); + llMask |= (llMask << 16); + + lrMask = LR->GetBitMask(); + lrMask_sh = GetShiftAmount(lrMask); + lrMask |= (lrMask << 16); + } else + { + //No MFDs to draw, break out early + return False; + } + } else + { + //Drawing secondary, make sure we got secondary + if (secPort != NULL) + { + secMask = secPort->GetBitMask(); + secPalette = &((SVGA16 *) secPort->graphicsDisplay)->palette[secPort->paletteID]; + } else + { + //No secondary, skip + return False; + } + } + + Word *data = pixelBuffer.Data.MapPointer; + + D3DLOCKED_RECT rect; + if (FAILED(mSurfaces[mDisplayToUpdate * 2]->LockRect(0, &rect, NULL, mLockFlags[mDisplayToUpdate]))) + { + DEBUG_STREAM << "Failed to lock texture for display " << mDisplayToUpdate << "!" << std::endl << std::flush; + } + else + { + switch(mDisplayToUpdate) + { + case 0: + { + //Secondary + Word *source = data; + Word *dest = (Word*)rect.pBits; + + int postRowIncrement = (rect.Pitch / 2) - pixelBuffer.Data.Size.x; + for (int y = 0; y < pixelBuffer.Data.Size.y; y++) + { + for (int x = 0; x < pixelBuffer.Data.Size.x; x++) + { + PaletteTriplet *paletteEntry = &(secPalette->paletteData.Color[*source & secMask]); + + *dest = ((paletteEntry->Red >> 3) << 11) | + ((paletteEntry->Green >> 2) << 5) | + ((paletteEntry->Blue >> 3)); + + dest++; + source++; + } + + dest += postRowIncrement; + } + } + break; + case 2: + { + //HACK - set the upper mask to be the lower mask (so that we draw the lower MFDs to the window) + //and then drop through and draw like the upper stuff + ulMask = llMask; + ucMask = lrMask; + urMask = 0; + ulMask_sh = llMask_sh; + ucMask_sh = lrMask_sh; + urMask_sh = 0; + } + case 1: + { + DWORD *sourceData = (DWORD*)data; + DWORD *destData = (DWORD*)rect.pBits; + + int leftWidth = pixelBuffer.Data.Size.x/2; + + int postRowIncrement = (rect.Pitch / sizeof(DWORD)) - leftWidth; + for (int y = 0; y < pixelBuffer.Data.Size.y; y++) + { + for (int x=0; x < leftWidth; x++) + { + *destData = (((*sourceData & ulMask) >> ulMask_sh) * 0xF800) | + (((*sourceData & ucMask) >> ucMask_sh) * 0x07E0) | + (((*sourceData & urMask) >> urMask_sh) * 0x001F); + + if (NUMGAUGEWINDOWS < 3) + { + //Only draw if we are in spanning mode + *(destData + leftWidth) = (((*sourceData & llMask) >> llMask_sh) * 0xF800) | + (((*sourceData & lrMask) >> lrMask_sh) * 0x07E0); + } + sourceData++; + destData++; + } + + destData += postRowIncrement; + } + + break; + } + } + + V( mSurfaces[mDisplayToUpdate * 2]->UnlockRect(0) ); + + V( mDevice[mDisplayToUpdate]->UpdateTexture(mSurfaces[mDisplayToUpdate * 2], mSurfaces[mDisplayToUpdate * 2 + 1]) ); + } + + V( mDevice[mDisplayToUpdate]->BeginScene() ); + V( mDevice[mDisplayToUpdate]->SetFVF(D3DFVF_XYZRHW | D3DFVF_TEX1) ); + V( mDevice[mDisplayToUpdate]->SetStreamSource(0, mVertBuffers[mDisplayToUpdate], 0, sizeof(float) * 6) ); + V( mDevice[mDisplayToUpdate]->SetTexture(0, mSurfaces[mDisplayToUpdate * 2 + 1]) ); + V( mDevice[mDisplayToUpdate]->DrawPrimitive(D3DPT_TRIANGLEFAN, 0, 2) ); + V( mDevice[mDisplayToUpdate]->EndScene() ); + + V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL) ); + if (hr == D3DERR_DEVICELOST) + { + int bbCount = mPresentParams[mDisplayToUpdate].BackBufferCount; + int bbWidth = mPresentParams[mDisplayToUpdate].BackBufferWidth; + int bbHeight = mPresentParams[mDisplayToUpdate].BackBufferHeight; + + mSurfaces[mDisplayToUpdate * 2 + 1]->Release(); + V(mDevice[mDisplayToUpdate]->Reset(&mPresentParams[mDisplayToUpdate])); + hr = mDevice[mDisplayToUpdate]->CreateTexture(mSurfaceRects[mDisplayToUpdate].right - mSurfaceRects[mDisplayToUpdate].left, height, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[mDisplayToUpdate * 2 + 1], NULL); + + + mPresentParams[mDisplayToUpdate].BackBufferCount = bbCount; + mPresentParams[mDisplayToUpdate].BackBufferWidth = bbWidth; + mPresentParams[mDisplayToUpdate].BackBufferHeight = bbHeight; + } + +// Time end = Now(); + +// if (end.ticks - start.ticks > 100) +// end = start; + + return False; // True == 'more to do' +} + + +void SVGA16::Refresh() +{ + HRESULT hr; + V( mDevice[mDisplayToUpdate]->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0) ); + + V( mDevice[mDisplayToUpdate]->BeginScene() ); + + V( mDevice[mDisplayToUpdate]->EndScene() ); + + V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL) ); + if (hr == D3DERR_DEVICELOST) + { + int bbCount = mPresentParams[mDisplayToUpdate].BackBufferCount; + int bbWidth = mPresentParams[mDisplayToUpdate].BackBufferWidth; + int bbHeight = mPresentParams[mDisplayToUpdate].BackBufferHeight; + + mSurfaces[mDisplayToUpdate * 2 + 1]->Release(); + V(mDevice[mDisplayToUpdate]->Reset(&mPresentParams[mDisplayToUpdate])); + hr = mDevice[mDisplayToUpdate]->CreateTexture(mSurfaceRects[mDisplayToUpdate].right - mSurfaceRects[mDisplayToUpdate].left, height, 1, 0, D3DFMT_R5G6B5, D3DPOOL_DEFAULT, &mSurfaces[mDisplayToUpdate * 2 + 1], NULL); + + V( mDevice[mDisplayToUpdate]->Present(NULL, NULL, NULL, NULL)); + + mPresentParams[mDisplayToUpdate].BackBufferCount = bbCount; + mPresentParams[mDisplayToUpdate].BackBufferWidth = bbWidth; + mPresentParams[mDisplayToUpdate].BackBufferHeight = bbHeight; + } + + mDisplayToUpdate++; + + if (mDisplayToUpdate >= NUMGAUGEWINDOWS) + { + mDisplayToUpdate = 0; + } +} +//STUBBED: VIDEO RB 1/15/07 +// SET_SCREEN_COPY(); +// Diag_Tell("SVGA16::Update(" << forceAll << ")\n"); +// Check(this); +// +// //--------------------------------------------------------- +// // If pixelbuffer is invalid, do nothing +// //--------------------------------------------------------- +// if (!valid) +// { +// CLEAR_SCREEN_COPY(); +// return False; // Do no more! +// } +// //--------------------------------------------------------- +// // Mark all lines as changed if commanded +// //--------------------------------------------------------- +// if (forceAll) +// { +// memset(changedLine, 1, height); +// } +// +// int +// previous_line_number = lineNumber; +// +// long +// dest_size, +// dest_line_size; +// +// //--------------------------------------------------------- +// // Calculate sizes based on specialInterface +// //--------------------------------------------------------- +// if (specialInterface) +// { +// dest_size = 32L; // BYTE offset! +// dest_line_size = width; +// } +// else +// { +// dest_size = 32L << 1; // WORD offset! +// dest_line_size = width << 1; +// } +// //--------------------------------------------------------- +// // Process lines for as long as we can +// //--------------------------------------------------------- +//#if 0 // Let's process just a few lines for background loop processing... +// while (Get_Frame_Percent_Used() < .65f) +//#endif +// { +// //--------------------------------------------------------- +// // Do a couple of lines before checking time again +// //--------------------------------------------------------- +// for(int line_limit=15; line_limit > 0; ) +// { +// //--------------------------------------------------------- +// // Check for changed line, clear the flag +// //--------------------------------------------------------- +// Verify(changedLinePointer < &changedLine[height]); +// +// int +// changed_line = *changedLinePointer; +// *changedLinePointer++ = 0; +// +// if (changed_line) +// { +// Diag_Tell(height << ":"); +// //--------------------------------------------------------- +// // Pixels on this line have been changed +// //--------------------------------------------------------- +// --line_limit; +// //--------------------------------------------------------- +// // Check 'dirty' LWords: if set, scan for changed pixels +// //--------------------------------------------------------- +// for(int x=0; x= pageSize) +// { +// destOffset -= pageSize; +// nextPageNumber += pageDelta; +// } +// } +// Diag_Tell("\n"); +// } +// else +// { +// //--------------------------------------------------------- +// // Line has not changed, skip over it +// //--------------------------------------------------------- +//#if defined(CHECK_FOR_DIRT) +// Logical +// dirty_flag = False; +// +// for(int x=0; x= pageSize) +// { +// destOffset -= pageSize; +// nextPageNumber += pageDelta; +// } +// } +// if (dirty_flag) +// { +// Tell( +// "SVGA16::Update: Unexpected dirty bits in line " << +// lineNumber << +// "\n!" +// ); +// } +//#else +// changedBitPointer += changedBitWidth; +// sourcePointer += width; +// destOffset += dest_line_size; +// +// if (destOffset >= pageSize) +// { +// destOffset -= pageSize; +// nextPageNumber += pageDelta; +// } +//#endif +// } +// +//# if defined(BLIT_STATISTICS) +// //--------------------------------- +// // Keep values within a sane range +// //--------------------------------- +// if ( +// (transferPixelCount > 0x10000000) +// || +// (dirtyPixelCount > 0x10000000) +// ) +// { +// transferPixelCount >>= 1; +// dirtyPixelCount >>= 1; +// ++overflowPixelCount; +// } +//# endif +// //--------------------------------------------------------- +// // Check for wrap +// //--------------------------------------------------------- +// if (++lineNumber >= height) +// { +// ResetUpdatePosition(); +// } +// //--------------------------------------------------------- +// // If back to beginning, exit loop +// //--------------------------------------------------------- +// if (lineNumber == previous_line_number) +// { +// Check_Fpu(); +// CLEAR_SCREEN_COPY(); +// return False; // All done +// } +// } +// } +// Check_Fpu(); +// CLEAR_SCREEN_COPY(); + + +void + SVGA16::ResetUpdatePosition() +{ + lineNumber = 0; + + sourcePointer = pixelBuffer.Data.MapPointer; + + changedLinePointer = changedLine; + changedBitPointer = changedBit; + + nextPageNumber = 0; + destOffset = 0L; +} + +void + SVGA16::FadeToPalettes(Scalar fade_time) +{ + Check(this); + + previousFadeTime = Now(); + paletteFadeState = fadeToColor; + + if(Small_Enough(fade_time)) + { + fadeUnitsPerSecond = 0.0; + fadeAlpha = 1.0; + } + else + { + fadeUnitsPerSecond = (1.0/fade_time); + } + Check_Fpu(); +} + +void + SVGA16::FadeToWhite(Scalar fade_time) +{ + Check(this); + + previousFadeTime = Now(); + paletteFadeState = fadeToWhite; + + if(Small_Enough(fade_time)) + { + fadeUnitsPerSecond = 0.0; + fadeAlpha = 0.0; + } + else + { + fadeUnitsPerSecond = (1.0/fade_time); + } + Check_Fpu(); +} + +void + generateFade( + SVGA16Palette *source, + Scalar alpha + ) +{ +//STUBBED: VIDEO RB 1/15/07 + Check_Pointer(source); + + if (alpha < 0.0) + { + alpha = 0.0; + } + else if (alpha > 1.0) + { + alpha = 1.0; + } + + Palette8 + temp; +// Scalar +// inverse_alpha = (1.0 - alpha) * 255.0; + int + i; + + for(i=0; i<256; ++i) + { + temp.Color[i].Red = (Byte) +// (inverse_alpha + (source->paletteData.Color[i].Red * alpha)); + ((source->paletteData.Color[i].Red * alpha)); + temp.Color[i].Green = (Byte) +// (inverse_alpha + (source->paletteData.Color[i].Green * alpha)); + ((source->paletteData.Color[i].Green * alpha)); + temp.Color[i].Blue = (Byte) +// (inverse_alpha + (source->paletteData.Color[i].Blue * alpha)); + ((source->paletteData.Color[i].Blue * alpha)); + } + +// SVGAWriteFullPalette( // in L4SVGA16.ASM +// &temp.Color[0].Red, +// source->hardwarePort +// ); + Check_Fpu(); +} + +void + SVGA16::FlashPalette( + int palette_number, + Scalar rate, + unsigned char *stateList + ) +{ + Check(this); + Verify(palette_number >= 0); + Verify(palette_number < PaletteCount); + + SVGA16Palette + *palette_pointer = &palette[palette_number]; + + //------------------------------------------------- + // Adjust rate so value becomes "cycles per second" + //------------------------------------------------- + palette_pointer->flashRate = rate * (Scalar) SVGA16Palette::maskStates; + //------------------------------------------------- + // Copy the mask values + //------------------------------------------------- + for (int i=0; imask[i] = *stateList++; + } + Check_Fpu(); +} + +void + SVGA16::UnflashPalette( + int palette_number + ) +{ + //STUBBED: VIDEO RB 1/15/07 + //Check(this); + //Verify(palette_number >= 0); + //Verify(palette_number < PaletteCount); + + //SVGA16Palette + // *palette_pointer = &palette[palette_number]; + + //palette_pointer->flashRate = 0.0; + //palette_pointer->flashAccumulator = 0.0; + //palette_pointer->previousMaskState = -1; + //SVGAWritePaletteMask(palette_pointer->hardwarePort, 0xFF); + + //Check_Fpu(); +} + +void + SVGA16::UpdatePalette() +{ + //STUBBED: VIDEO RB 1/15/07 + Check(this); + + int + i, + mask_state; + SVGA16Palette + *palette_pointer; + + //-------------------------------------------------------- + // Update time values + //-------------------------------------------------------- + Time + right_now = Now(); + Scalar + delta_t = (Scalar) (right_now - previousFadeTime); + + previousFadeTime = right_now; + if (delta_t <= 0.0) + { + return; + } + //-------------------------------------------------------- + // Set palette masks + //-------------------------------------------------------- + palette_pointer = &palette[0]; + for(i=0; iflashRate != 0.0) + { + palette_pointer->flashAccumulator += + palette_pointer->flashRate * delta_t; + + while (palette_pointer->flashAccumulator >= + (Scalar) SVGA16Palette::maskStates) + { + palette_pointer->flashAccumulator -= + (Scalar) SVGA16Palette::maskStates; + } + + mask_state = (int) palette_pointer->flashAccumulator; + + if (mask_state != palette_pointer->previousMaskState) + { + palette_pointer->previousMaskState = mask_state; + + // SVGAWritePaletteMask( + // palette_pointer->hardwarePort, + // palette_pointer->mask[mask_state] + // ); + } + } + } + //-------------------------------------------------------- + // Fade palettes + //-------------------------------------------------------- + palette_pointer = &palette[0]; + for(i=0; imodified) + { + palette_pointer->modified = False; + + // SVGAWriteFullPalette( + // &palette_pointer->paletteData.Color[0].Red, + // palette_pointer->hardwarePort + // ); + } + } + else + { + //-------------------------------------------------------- + // Discard 'modified' flag (we use the local values for + // fade in/out, and in the 'white' state we don't care, + // because we'll have to fade back in anyway) + //-------------------------------------------------------- + palette_pointer->modified = False; + //-------------------------------------------------------- + // Perform fade (or stay white) + //-------------------------------------------------------- + switch(paletteFadeState) + { + case fadeToWhite: + fadeAlpha -= (delta_t * fadeUnitsPerSecond); + generateFade(palette_pointer, fadeAlpha); + + if (fadeAlpha <= 0.0) + { + fadeAlpha = 0.0; + paletteFadeState = whitePalette; + } + break; + + case whitePalette: + break; + + case fadeToColor: + fadeAlpha += (delta_t * fadeUnitsPerSecond); + generateFade(palette_pointer, fadeAlpha); + + if (fadeAlpha >= 1.0) + { + fadeAlpha = 1.0; + paletteFadeState = staticPalette; + } + break; + } + } + } + Check_Fpu(); +} + +void + SVGA16::FunkyVideo(Logical on_off) +{ + //STUBBED: VIDEO RB 1/15/07 + //Check(this); + //SVGAFunkyVideo(on_off); + //Check_Fpu(); +} + +//######################################################################## +//########################### L4GraphicsPort ############################# +//######################################################################## + +L4GraphicsPort::L4GraphicsPort( + Video16BitBuffered *graphics_display, + const char *name, + int rotation, + int bit_mask, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID channel_enable +):GraphicsPort(graphics_display, name) +{ + int + bit_test; + // + // Save the base rotation value + // + baseRotation = rotation; + // + // Save the paletteID and channel enable + // + paletteID = palette_ID; + channelEnable = channel_enable; + // + // Save the bitMask + // + bitMask = bit_mask; + Verify (bitMask != 0); + // + // Count the number of active bits in the bitMask + // + for(bit_test=0x8000,numberOfBits=0; bit_test!=0; bit_test>>=1) + { + if (bit_test & bitMask) + { + ++numberOfBits; + } + } + // + // Initialize conversion constants + // + maximumX = bounds.topRight.x - bounds.bottomLeft.x; + maximumY = bounds.topRight.y - bounds.bottomLeft.y; + // + // Overwrite the GraphicsPort::bounds data with rotated values + // for GraphView's benefit + // + switch(baseRotation) + { + default: + // do nothing + break; + + case 90: + case 270: + if (graphics_display != NULL) + { + Check(graphics_display); + bounds.bottomLeft.x = graphics_display->bounds.bottomLeft.y; + bounds.bottomLeft.y = graphics_display->bounds.bottomLeft.x; + bounds.topRight.x = graphics_display->bounds.topRight.y; + bounds.topRight.y = graphics_display->bounds.topRight.x; + } + break; + } + + for(int j=0; j<256; ++j) + { + myColor[j] = NULL; + } + + Check_Fpu(); +} + +L4GraphicsPort::~L4GraphicsPort() +{ + Check(this); + Check_Fpu(); +} + +Logical + L4GraphicsPort::TestInstance() const +{ + return True; +} + +void + L4GraphicsPort::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "L4GraphicsPort:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "bitMask =" << bitMask << "\n"; + std::cout << temp << "baseRotation =" << baseRotation << "\n"; + std::cout << temp << "maximumX =" << maximumX << "\n"; + std::cout << temp << "maximumY =" << maximumY << "\n"; + std::cout << temp << "bounds =" << bounds << "\n"; + std::cout << std::flush; + GraphicsPort::ShowInstance(temp); + Check_Fpu(); +} + +void + L4GraphicsPort::SetColor( + PaletteTriplet *source_triplet, + int color_index + ) +{ + Check(this); + Check_Pointer(source_triplet); + Verify(color_index >= 0); + Verify(color_index < 256); + + switch(channelEnable) + { + case L4GraphicsPort::DirectColor: + case L4GraphicsPort::BlankColor: + break; + default: + BuildSecondaryColor(source_triplet, color_index); + break; + } + Check_Fpu(); +} + +void + L4GraphicsPort::SetSecondaryPalette( + Palette8 *source_palette + ) +{ + Check(this); + Check(source_palette); + + if (graphicsDisplay == NULL) + { + return; + } + + switch(channelEnable) + { + case L4GraphicsPort::DirectColor: + BuildDirectTranslation(source_palette); + break; + case L4GraphicsPort::BlankColor: + BlankPalette(); + BuildSecondaryTranslation(); + break; + default: + BuildSecondaryPalette(source_palette); + BuildSecondaryTranslation(); + break; + } + Check_Fpu(); +} + + +void + L4GraphicsPort::SetAuxiliaryPalette() +{ + Check(this); + + if (graphicsDisplay == NULL) + { + return; + } + + switch(channelEnable) + { + case L4GraphicsPort::DirectColor: + //--------------------------------------------------------------- + // Set translation table for direct color mode + //--------------------------------------------------------------- + { + Palette8 + monochrome_palette; + + PaletteTriplet + black, + white; + + black.Red = 0; + black.Green = 0; + black.Blue = 0; + + white.Red = 255; + white.Green = 255; + white.Blue = 255; + + monochrome_palette.BuildColorRange(0,255,black, white); + + BuildDirectTranslation(&monochrome_palette); + } + break; + + case L4GraphicsPort::BlankColor: + BlankPalette(); + BuildAuxiliaryTranslation(); + break; + + default: + BuildAuxiliaryPalette(); + BuildAuxiliaryTranslation(); + break; + } + Check_Fpu(); +} + + +void + L4GraphicsPort::DrawPoint( + int color, + Enumeration operation, + int x, int y + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + graphicsDisplay-> + DrawPoint( + translationTable[color], + bitMask, + operation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawLine( + translationTable[color], + bitMask, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y, + include_last_pixel + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawFilledRectangle( + translationTable[color], + bitMask, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawText( + int /*color*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +} + +void + L4GraphicsPort::DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMap( + translationTable[color], + bitMask, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMapOpaque( + translationTable[color], + translationTable[background], + bitMask, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); +} + +void + L4GraphicsPort::DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8( + translationTable, + bitMask, + operation, + opaque, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4GraphicsPort::DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8SingleColor( + translationTable[color], + bitMask, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4GraphicsPort::convertPortPair( + int *xp, + int *yp, + int x, + int y + ) +{ + switch(baseRotation) + { + default: + *xp = x; + *yp = y; + break; + + case 90: + *xp = y; + *yp = maximumY - x; + break; + + case 180: + *xp = maximumX - x; + *yp = maximumY - y; + break; + + case 270: + *xp = maximumX - y; + *yp = x; + break; + } + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method generates a translation table specifically for writing +// to a "direct" color mode display, in which colors are represented +// as 5 red bits, 6 green bits, and 5 blue bits in a display word. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildDirectTranslation( + Palette8 *source_palette + ) +{ + PaletteTriplet + *source_data(source_palette->Color); + + int + *dest(translationTable); + + int + red_bits, + green_bits, + blue_bits, + i; + + // + // Force to all bits (just to be sure) + // + bitMask = 0xFFFF; + + for(i=256; i>0; --i,++source_data) + { + red_bits = source_data->Red >> 3; + green_bits = source_data->Green >> 2; + blue_bits = source_data->Blue >> 3; + + *dest++ = (red_bits << 11)|(green_bits << 5) | blue_bits; + } + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method combines palettes from multiple L4GraphicsPorts. +// If several ports have palettes mapped onto the same RGB display, then +// the most recently built palette has precedence over the previous one(s). +// +// Palettes are assumed to always have 256 colors. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildSecondaryPalette( + Palette8 *source_palette + ) +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + Check(source_palette); + + + int + byte_mask(bitMask & 0xFF); + Verify (byte_mask != 0); + + BitWrangler + wrangler(byte_mask, 8); + + PaletteTriplet + *source_triplet, + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + source_triplet = &source_palette->Color[0]; + + //------------------------------------------- + // Clear the 'owned color' flags + //------------------------------------------- + for(int j=0; j<256; ++j) + { + myColor[wrangler.Value] = 0; + } + + // + // If any of the ...TransparentZero modes are used, + // leave color zero undefined for this bit group by + // skipping over it + // + if (channelEnable & 0x80) + { + ++source_triplet; + wrangler.IncrementActive(); + } + + // + // Fill in the color table for this palette set + // + do + { + //------------------------------------------- + // Write all destination colors + //------------------------------------------- + do + { + //------------------------------------------- + // Set the 'owned color' flag + //------------------------------------------- + myColor[wrangler.Value] = 1; + //------------------------------------------- + // Get destination pointer + //------------------------------------------- + destination_triplet = + &svga_palette->paletteData.Color[wrangler.Value]; + //------------------------------------------- + // Copy color data + //------------------------------------------- + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = source_triplet->Red; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = source_triplet->Green; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = source_triplet->Blue; + break; + + case AllChannels: + case AllChannelsTransparentZero: + *destination_triplet = *source_triplet; + break; + } + } + while (wrangler.IncrementInactive()); + //------------------------------------------- + // Bump the source pointer + //------------------------------------------- + ++source_triplet; + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method combines palettes from multiple L4GraphicsPorts. +// If several ports have palettes mapped onto the same RGB display, then +// the most recently built palette has precedence over the previous one(s). +// +// Palettes are assumed to always have 256 colors. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildSecondaryColor( + PaletteTriplet *source_triplet, + int dest_color_number + ) +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + Check_Pointer(source_triplet); + + int + byte_mask(bitMask & 0xFF); + Verify (byte_mask != 0); + + BitWrangler + wrangler(byte_mask, 8); + + int + destination_color = 0; + + PaletteTriplet + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + //------------------------------------------- + // If any of the ...TransparentZero modes are used, + // leave color zero undefined for this bit group by + // skipping over it + //------------------------------------------- + if (channelEnable & 0x80) + { + ++destination_color; + wrangler.IncrementActive(); + } + + //------------------------------------------- + // Set the color value + //------------------------------------------- + do + { + //------------------------------------------- + // Write all destination colors + //------------------------------------------- + if (destination_color == dest_color_number) + { + //------------------------------------------- + // Write all destination colors + //------------------------------------------- + do + { + //------------------------------------------- + // Do we own this color? Skip if unowned + //------------------------------------------- + if (myColor[wrangler.Value]) + { + //------------------------------------------- + // Copy color data + //------------------------------------------- + destination_triplet = + &svga_palette->paletteData.Color[wrangler.Value]; + + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = source_triplet->Red; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = source_triplet->Green; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = source_triplet->Blue; + break; + + case AllChannels: + case AllChannelsTransparentZero: + *destination_triplet = *source_triplet; + break; + } + } + } + while (wrangler.IncrementInactive()); + //------------------------------------------- + // Only doing one color, so exit the loop + //------------------------------------------- + break; + } + //------------------------------------------- + // Bump the color counter + //------------------------------------------- + ++destination_color; + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method combines palettes from multiple L4GraphicsPorts. +// If several ports have palettes mapped on top of another, then +// the most recently built palette has precedence over the previous one(s). +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildAuxiliaryPalette() +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + + + int + byte_mask((bitMask >> 8) & 0xFF); + + Verify (byte_mask != 0); + BitWrangler + wrangler(byte_mask, 8); + + int + rate, + accumulator; + + Byte + color_value; + + PaletteTriplet + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + Verify(((1< 0); + rate = (255<<5)/((1<> 5); + accumulator += rate; + + do + { + destination_triplet = &svga_palette->paletteData. + Color[wrangler.Value]; + + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = color_value; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = color_value; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = color_value; + break; + + case AllChannels: + case AllChannelsTransparentZero: + destination_triplet->Red = color_value; + destination_triplet->Green = color_value; + destination_triplet->Blue = color_value; + break; + } + } + while (wrangler.IncrementInactive()); + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + +# if defined(TESTPALETTE) + std::cout << "L4GraphicsPort::BuildAuxiliaryPalette for port " << + std::hex << svga_palette->hardwarePort << "\n"; + for(int i=0; i<256; ++i) + { + if ((i & 0x03) == 0) + { + std::cout << std::dec << "\n" << i << ":" << std::hex; + } + std::cout << svga_palette->paletteData.Color[i] << " "; + } + std::cout << "\n"; + { + Palette8 + temp; + + SVGAReadFullPalette( + &temp.Color[0].Red, + svga_palette->hardwarePort + ); + + std::cout << "L4GraphicsPort::BuildAuxiliaryPalette, read back\n"; + for(int i=0; i<256; ++i) + { + if ((i & 0x03) == 0) + { + std::cout << std::dec << "\n" << i << ":" << std::hex; + } + std::cout << temp.Color[i] << " "; + } + std::cout << "\n"; + } +# endif + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This sets 'owned' color values in a palette to zero. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BlankPalette() +{ + Verify (bitMask != 0); + + if (graphicsDisplay == NULL) + { + return; + } + Check(graphicsDisplay); + + int + byte_mask((bitMask >> 8) & 0xFF); + + Verify (byte_mask != 0); + BitWrangler + wrangler(byte_mask, 8); + + Byte + color_value; + + PaletteTriplet + *destination_triplet; + + SVGA16Palette + *svga_palette(&((SVGA16 *) graphicsDisplay)->palette[paletteID]); + + Verify(((1< 0); + + color_value = 0; + do + { + do + { + destination_triplet = &svga_palette->paletteData. + Color[wrangler.Value]; + + switch(channelEnable) + { + case RedChannel: + case RedChannelTransparentZero: + destination_triplet->Red = color_value; + break; + + case GreenChannel: + case GreenChannelTransparentZero: + destination_triplet->Green = color_value; + break; + + case BlueChannel: + case BlueChannelTransparentZero: + destination_triplet->Blue = color_value; + break; + + case AllChannels: + case AllChannelsTransparentZero: + destination_triplet->Red = color_value; + destination_triplet->Green = color_value; + destination_triplet->Blue = color_value; + break; + } + } + while (wrangler.IncrementInactive()); + } + while (wrangler.IncrementActive()); + + svga_palette->paletteData.Valid = True; + svga_palette->modified = True; + + Check_Fpu(); +} + +// +//--------------------------------------------------------------------------- +// This method generates a translation table for the secondary display, +// using a previously set palette and channel. +// +// Palettes are assumed to always have 256 colors. +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildSecondaryTranslation() +{ + Verify((bitMask & 0xFF) != 0); + + BitWrangler + wrangler(bitMask & 0xFF, 8); + + int + *destination(translationTable); + + do + { + *destination++ = wrangler.Value; + } + while (wrangler.IncrementActive()); + Check_Fpu(); +} + + +// +//--------------------------------------------------------------------------- +// This method generates a translation table for the auxiliary displays. +// +// Palettes are assumed to always have 256 colors (0=black, 255=white). +//--------------------------------------------------------------------------- +// +void + L4GraphicsPort::BuildAuxiliaryTranslation() +{ + Verify(numberOfBits != 0); + Verify(numberOfBits <= 8); + + int + byte_mask((bitMask >> 8) & 0xFF); + Verify(byte_mask != 0); + + BitWrangler + wrangler(byte_mask, 8); + int + *destination(translationTable); + int + currentValue; + + // + // Generate lookup table + // + do + { + currentValue = wrangler.Value << 8; + + do + { + *destination++ = currentValue; + } + while (wrangler.IncrementInactive()); + } + while (wrangler.IncrementActive()); + +# if defined(TESTPALETTE) + std::cout << "L4GraphicsPort::BuildAuxiliaryTranslation\n"; + for(int i=0; i<256; ++i) + { + if ((i & 0x07) == 0) + { + std::cout << "\n" << std::dec << i << ":" << std::hex; + } + std::cout << translationTable[i] << " "; + } + std::cout << "\n"; +# endif + Check_Fpu(); +} diff --git a/MUNGA_L4/L4VB16.h b/MUNGA_L4/L4VB16.h new file mode 100644 index 0000000..bc1b987 --- /dev/null +++ b/MUNGA_L4/L4VB16.h @@ -0,0 +1,508 @@ +#pragma once + +#include "..\munga\graph2d.h" +#include "..\munga\time.h" +#include +#include + + +class L4graphicsPort; + +//######################################################################## +//######################### Video16BitBuffered ########################### +//######################################################################## +// +// X/Y values passed to these routines are assumed to be in +// the VIDEO DISPLAY COORDINATE SYSTEM, with (0,0) at the top left. +// +class Video16BitBuffered : + public GraphicsDisplay +{ +public: + Video16BitBuffered(int x, int y); + + ~Video16BitBuffered(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + +protected: + void + MarkChangedLines(int screenTop, int screenBottom); + + void + buildDestPointer( + int x, int y, + Word **pixelPointer, + LWord **changed_bit_pointer, + LWord *changed_bit + ); + + Logical + valid; + int + width, + changedBitWidth, + height, + maximumX, + maximumY; + + PixelMap16 + pixelBuffer; + Byte + *changedLine; + LWord + *changedBit; +}; + + +//######################################################################## +//################################ SVGA16 ################################ +//######################################################################## +struct SVGA16Palette +{ + Word + hardwarePort; + Logical + modified; + Palette8 + paletteData; + Scalar + flashAccumulator, + flashRate; + + enum PaletteID + { + maskStates=4 + }; + unsigned char + mask[maskStates]; + int + previousMaskState; +}; + + +class SVGA16 : + public Video16BitBuffered +{ +friend class L4GraphicsPort; // for palette access + +public: + enum PaletteID { + NativePalette=0, + SecondaryPalette, + AuxiliaryPalette1, + AuxiliaryPalette2, + PaletteCount + }; + + SVGA16( + int mode, + int width, + int height, + int page_size, + int mem_granularity, + int bytes_per_line, + int page_function_pointer, + int special_interface, + bool windowed, + int *secondaryIndex, + int *aux1Index, + int *aux2Index + ); + + ~SVGA16(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + Logical + Update(Logical forceall); + void + Refresh(); + void + UpdatePalette(); + + void + FadeToPalettes(Scalar fade_time); + void + FadeToWhite(Scalar fade_time); + void + FlashPalette( + int palette_number, + Scalar rate, + unsigned char *stateList + ); + void + UnflashPalette(int palette_number); + + void + FunkyVideo(Logical on_off); + +protected: + + void BuildWindows(unsigned int width, unsigned int height, bool windowed, int *secondaryIndex, int *aux1Gauge, int *aux2Gauge); + + + void + ResetUpdatePosition(); + + int + pageSize, + pageDelta, + widthInBytes, + pageFcnPtr, + specialInterface; + + int + currentPageNumber, + nextPageNumber, + lineNumber; + long + destOffset; + Byte + *changedLinePointer; + Word + *sourcePointer; + LWord + *changedBitPointer; + + enum PaletteFadeState + { + staticPalette, + fadeToWhite, + whitePalette, + fadeToColor + }; + + PaletteFadeState + paletteFadeState; + Scalar + fadeAlpha, + fadeUnitsPerSecond; + Time + previousFadeTime; + + // This array is closely linked to the PaletteID enumeration, above + SVGA16Palette + palette[PaletteCount]; + +private: + int NUMGAUGEWINDOWS; + HWND *gaugeWindows; + LPDIRECT3DDEVICE9 *mDevice; + D3DPRESENT_PARAMETERS *mPresentParams; + LPDIRECT3DVERTEXBUFFER9 *mVertBuffers; + LPDIRECT3DTEXTURE9 *mSurfaces; + DWORD *mLockFlags; + RECT *mSurfaceRects; + + int mDisplayToUpdate; +}; + +//######################################################################## +//########################## L4GraphicsPort ############################## +//######################################################################## +// +// X/Y values passed to these routines are assumed to be in +// the GRAPHICS COORDINATE SYSTEM, with (0,0) at the bottom left. +// +class L4GraphicsPort : + public GraphicsPort +{ +public: + enum ChannelEnableID { + RedChannel, + GreenChannel, + BlueChannel, + AllChannels, + + DirectColor, + BlankColor, + + RedChannelTransparentZero=0x80, + GreenChannelTransparentZero, + BlueChannelTransparentZero, + AllChannelsTransparentZero + }; + + L4GraphicsPort( + Video16BitBuffered *graphics_display, + const char *name, + int rotation, + int bit_mask, + SVGA16::PaletteID palette_ID, + L4GraphicsPort::ChannelEnableID channel_enable + ); + + ~L4GraphicsPort(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + SetSecondaryPalette( + Palette8 *source_palette + ); + + void + SetAuxiliaryPalette(); + + void + SetColor( + PaletteTriplet *source_color, + int color_index + ); + + void + DrawPoint( + int color, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + SetPaletteID(SVGA16::PaletteID palette_ID) + { + Check(this); + paletteID = palette_ID; + } + + void + SetEnableID(L4GraphicsPort::ChannelEnableID channel_enable) + { + Check(this); + channelEnable = channel_enable; + } + + int + GetBitMask() + { + Check(this); + return bitMask; + } + SVGA16::PaletteID + paletteID; + +protected: + void + convertPortPair( + int *xp, + int *yp, + int x, + int y + ); + + void + BuildDirectTranslation( + Palette8 *source_palette + ); + + void + BuildSecondaryPalette( + Palette8 *source_palette + ); + + void + BuildAuxiliaryPalette(); + + void + BuildSecondaryTranslation(); + + void + BuildAuxiliaryTranslation(); + + void + BlankPalette(); + + void + BuildSecondaryColor( + PaletteTriplet *source_triplet, + int color_number + ); + //------------------------------------------------------------ + // Protected data + //------------------------------------------------------------ + int + translationTable[256]; + unsigned char + myColor[256]; + + int + baseRotation, + bitMask, + numberOfBits, + maximumX, + maximumY; + + + L4GraphicsPort::ChannelEnableID + channelEnable; +}; diff --git a/MUNGA_L4/L4VB8.cpp b/MUNGA_L4/L4VB8.cpp new file mode 100644 index 0000000..a1b2472 --- /dev/null +++ b/MUNGA_L4/L4VB8.cpp @@ -0,0 +1,3010 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4vb8.h" + +//######################################################################## +//######################### Video8BitBuffered ########################### +//######################################################################## +// +//NOTE: the application assumes that the origin is in the lower left +// corner of the display, and all parameters passed to these routines +// use the application's coordinate system. +// +// All of the methods here convert these values to the SCREEN +// coordinate system, with the origin in the UPPER LEFT corner of +// the display. +// + +//=================================================================== +// Creator +//=================================================================== +Video8BitBuffered::Video8BitBuffered(int x, int y): + GraphicsDisplay(x, y) + { +# if defined(DEBUG) + Tell( + "Video8BitBuffered::Video8BitBuffered()\n" + ); +# endif + int + i; + Word + *line_dest; + + pixelBuffer = new PixelMap8(x, y); + Check(pixelBuffer); + Verify(pixelBuffer->Data.MapPointer != NULL); + Register_Object(pixelBuffer); + createdPixelmap = True; + + height = y; + width = x; + + maximumY = height-1; + maximumX = width-1; + //--------------------------------------------------------- + // Create 'changedLine' array + //--------------------------------------------------------- + changedLine = new Word[height]; + Register_Pointer(changedLine); + valid = True; + + //--------------------------------------------------------- + // Clear the 'changedLine' array + //--------------------------------------------------------- + for (i=height,line_dest=changedLine; i>0; --i,++line_dest) + { + *line_dest = 0; + } + Check_Fpu(); +} + +Video8BitBuffered::Video8BitBuffered(PixelMap8 *pixel_buffer): + GraphicsDisplay(pixel_buffer->Data.Size.x, pixel_buffer->Data.Size.y) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::Video8BitBuffered()\n" + ); +# endif + int + i; + Word + *line_dest; + + pixelBuffer = pixel_buffer; + Verify(pixelBuffer->Data.MapPointer != NULL); + createdPixelmap = False; + + height = pixelBuffer->Data.Size.y; + width = pixelBuffer->Data.Size.x; + + maximumY = height-1; + maximumX = width-1; + //--------------------------------------------------------- + // Create 'changedLine' array + //--------------------------------------------------------- + changedLine = new Word[height]; + Register_Pointer(changedLine); + +# if defined(DEBUG) + Tell("changedLine=" << changedLine << "\n"); +# endif + + if (changedLine == NULL) + { +# if defined(DEBUG) + Tell("INVALID!\n"); +# endif + valid = False; + return; + } + else + { + Register_Pointer(changedLine); + valid = True; + } + //--------------------------------------------------------- + // Clear the 'changedLine' array + //--------------------------------------------------------- + for (i=height,line_dest=changedLine; i>0; --i,++line_dest) + { + *line_dest = 0; + } + Check_Fpu(); +} + +//=================================================================== +// Destructor +//=================================================================== +Video8BitBuffered::~Video8BitBuffered() +{ + Check(this); + + if (changedLine != NULL) + { + Unregister_Pointer(changedLine); + delete changedLine; + changedLine = NULL; + } + + if (createdPixelmap) + { + if (pixelBuffer != NULL) + { + Check(pixelBuffer); + Unregister_Object(pixelBuffer); + delete pixelBuffer; + pixelBuffer = NULL; + } + createdPixelmap = False; + } + + Check_Fpu(); +} + + +//=================================================================== +// TestInstance +//=================================================================== +Logical + Video8BitBuffered::TestInstance() const +{ + return True; +} + +//=================================================================== +// ShowInstance +//=================================================================== +void + Video8BitBuffered::ShowInstance( + char *indent + ) +{ + std::cout << indent << "Video8BitBuffered:\n"; + + Check(this); + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "width =" << width << "\n"; + std::cout << temp << "height =" << height << "\n"; + std::cout << temp << "maximumX =" << maximumX << "\n"; + std::cout << temp << "maximumY =" << maximumY << "\n"; + std::cout << temp << "changedLine=" << changedLine << "\n"; + + pixelBuffer->ShowInstance(temp); + GraphicsDisplay::ShowInstance(temp); + Check_Fpu(); +} + + +//=================================================================== +// buildDestPointer +//=================================================================== +void + Video8BitBuffered::buildDestPointer( + int screenX, + int screenY, + Byte **pixel_pointer + ) +{ + Verify(valid); + + Verify(pixel_pointer != NULL); + + Verify(screenX >= 0); + Verify(screenX < width); + Verify(screenY >= 0); + Verify(screenY < height); + + *pixel_pointer = pixelBuffer->Data.MapPointer + + screenX + + (screenY * width); + Verify(*pixel_pointer >= pixelBuffer->Data.MapPointer); + Verify(*pixel_pointer < &pixelBuffer->Data.MapPointer[height*width]); + + Check_Fpu(); +} +#define LEFT_DEST(pointer) --pointer +#define RIGHT_DEST(pointer) ++pointer +#define UP_DEST(pointer) pointer -= width +#define DOWN_DEST(pointer) pointer += width + +#define LEFT_SOURCE(pointer,map) --pointer +#define RIGHT_SOURCE(pointer,map) ++pointer +#define UP_SOURCE(pointer,map) pointer -= map->Data.Size.x +#define DOWN_SOURCE(pointer,map) pointer += map->Data.Size.x + +#define LEFT_BITMAP(pointer,bits) \ + bits <<= 1; \ + if (bits == 0) { --pointer; bits=0x0001; } + +#define RIGHT_BITMAP(pointer, bits) \ + bits >>= 1; \ + if (bits == 0) { ++pointer; bits=0x8000; } + +#define UP_BITMAP(pointer,map) pointer -= map->Data.WidthInWords +#define DOWN_BITMAP(pointer,map) pointer += map->Data.WidthInWords + +#define WRITEPIXEL(dest_pointer, operation, color) \ + switch (operation) \ + {\ + case GraphicsDisplay::Replace:\ + *dest_pointer = (Byte)color;\ + break;\ + case GraphicsDisplay::And:\ + *dest_pointer &= (Byte) color;\ + break;\ + case GraphicsDisplay::Or:\ + *dest_pointer |= (Byte) color;\ + break;\ + case GraphicsDisplay::Xor:\ + *dest_pointer ^= (Byte) color;\ + break;\ + } + +//=================================================================== +// MarkChangedLines +//=================================================================== +// +// Inputs are in DISPLAY COORDINATES, i.e., (0,0) in top left corner! +// +void + Video8BitBuffered::MarkChangedLines( + int start, + int stop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::MarkChangedLines(" << start << ", " << stop << + ")\n" + ); +# endif + Check(this); + + if (start > stop) + { +# if defined(DEBUG) + Tell("MarkChangedLines FLIPPING\n"); +# endif + int temp; + + temp = start; + start = stop; + stop = temp; + } + + Verify(start >= 0); + Verify(start <= maximumY); + Verify(stop >= 0); + Verify(stop <= maximumY); + + ++changedLine[start]; + + // + // Always include at least one line + // + if (stop < maximumY) + { + --changedLine[stop+1]; + } + + Check_Fpu(); +} + +//=================================================================== +// DrawPoint +//=================================================================== +void + Video8BitBuffered::DrawPoint( + int color, + int /*bitmask*/, + Enumeration operation, + int x, int y + ) +{ + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + Byte + *dest_pointer; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); +# endif + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y, y); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Create pointers + //--------------------------------------------------------- + buildDestPointer( + x, y, + &dest_pointer + ); + //--------------------------------------------------------- + // Write the point + //--------------------------------------------------------- + WRITEPIXEL(dest_pointer, operation, color) + Check_Fpu(); +} + +//=================================================================== +// DrawLine +//=================================================================== +void + Video8BitBuffered::DrawLine( + int color, + int /*bitmask*/, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawLine(" << color << + ", " << bitmask << + ", " << operation << + ", " << x1 << "," << y1 << "," << x2 << "," << y2 << + ", " << include_last_pixel << + "\n" + ); +# endif + + Check(this); + + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + enum + { + negative_delta_x = 1, + negative_delta_y = 2, + delta_y_greater = 0, + delta_x_greater = 4 + }; + + long + length, + rate, + accumulator; + + int + octant, + delta_x, + delta_y; + + Byte + *dest_pointer; + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Route to DrawPoint if single pixel + //--------------------------------------------------------- + if (x1 == x2 && y1 == y2) + { + if (include_last_pixel) + { + DrawPoint(color, 0 /*bitmask*/, operation, x1, y1); + } + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that endpoints are legitimate + //--------------------------------------------------------- + Verify(x1 >= 0); + Verify(x1 < width); + Verify(x2 >= 0); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 < height); + Verify(y2 >= 0); + Verify(y2 < height); + +# if defined(DEBUG) + Tell( + "Transformed coordinates=" << x1 << "," << y1 << + "," << x2 << "," << y2 << + "\n" + ); +# endif + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Determine which octant to use + //--------------------------------------------------------- + octant = 0; + + delta_x = x2 - x1; + if (delta_x < 0) + { +# if defined(DEBUG) + Tell("negative dx\n"); +# endif + octant |= negative_delta_x; + delta_x = - delta_x; + } + + delta_y = y2 - y1; + if (delta_y < 0) + { +# if defined(DEBUG) + Tell("negative dy\n"); +# endif + octant |= negative_delta_y; + delta_y = - delta_y; + } + + if (delta_x > delta_y) + { +# if defined(DEBUG) + Tell("dx > dy\n"); +# endif + octant |= delta_x_greater; + } +# if defined(DEBUG) + Tell( + "dx=" << delta_x << + ", dy=" << delta_y << + ", octant=" << octant << + ", color=" << color << + "\n" + ); +# endif + //--------------------------------------------------------- + // Prepare to draw line + //--------------------------------------------------------- + buildDestPointer( + x1, y1, + &dest_pointer + ); + + accumulator = 1024L; // preset accumulator to 1/2 full + //--------------------------------------------------------- + // Draw the line! + //--------------------------------------------------------- + switch (octant) + { + case delta_y_greater: + //------------------------------------- + // delta y greater + // positive delta x + // positive delta y + // + // + + // \ & + // \ & + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + + Verify(delta_y > 0); + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + DOWN_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + } + } + break; + + case delta_y_greater+negative_delta_x: + //------------------------------------- + // delta y greater + // negative delta x + // positive delta y + // + // + + // / + // / + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + DOWN_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + } + } + break; + + case delta_y_greater+negative_delta_y: + //------------------------------------- + // delta y greater + // positive delta x + // negative delta y + // + // / + // / + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + UP_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + RIGHT_DEST(dest_pointer); + } + } + break; + + case delta_y_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta y greater + // negative delta x + // negative delta y + // + // \ & + // \ & + // + + //------------------------------------- + length = delta_y; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_x*2048L)/delta_y; + +# if defined(DEBUG) + Tell( + "delta_y_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + UP_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + LEFT_DEST(dest_pointer); + } + } + break; + + case delta_x_greater: + //------------------------------------- + // delta x greater + // positive delta x + // positive delta y + // + // +---___ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + RIGHT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + } + } + break; + + case delta_x_greater+negative_delta_x: + //------------------------------------- + // delta x greater + // negative delta x + // positive delta y + // + // ___---+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + LEFT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + DOWN_DEST(dest_pointer); + } + } + break; + + case delta_x_greater+negative_delta_y: + //------------------------------------- + // delta x greater + // positive delta x + // negative delta y + // + // +___--- + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_y, length=" << length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + RIGHT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + } + } + break; + + case delta_x_greater+negative_delta_x+negative_delta_y: + //------------------------------------- + // delta x greater + // negative delta x + // negative delta y + // + // ---___+ + // + // + //------------------------------------- + length = delta_x; + if (!include_last_pixel) + { + -- length; + } + rate = (delta_y*2048L)/delta_x; + +# if defined(DEBUG) + Tell( + "delta_x_greater+negative_delta_x+negative_delta_y, length=" << + length << + ", rate=" << rate << + "\n" + ); +# endif + Verify(rate >= 0L); + Verify(rate <= 2048L); + Verify(length >= 0); + for ( ; length>0; --length) + { + WRITEPIXEL(dest_pointer, operation, color) +# if defined(DEBUG) + Tell( + length << + ", accum=" << accumulator << + ", dest_pointer=" << dest_pointer << + "\n" + ); +# endif + LEFT_DEST(dest_pointer); + + accumulator += rate; + if (accumulator > 2048L) + { +# if defined(DEBUG) + Tell("OVERFLOW\n"); +# endif + accumulator -= 2048L; + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawFilledRectangle +//=================================================================== +void + Video8BitBuffered::DrawFilledRectangle( + int color, + int /*bitmask*/, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ +# if defined(DEBUG) + Tell("Video8BitBuffered::DrawFilledRectangle(" << + color << ", " << + std::hex << bitmask << ", " << std::dec << + operation << ", " << + x1 << ", " << + y1 << ", " << + x2 << ", " << + y2 << ", " << + ")\n"); +# endif + Check(this); + Verify(x1 >= bounds.bottomLeft.x); + Verify(x1 <= bounds.topRight.x); + Verify(y1 >= bounds.bottomLeft.y); + Verify(y1 <= bounds.topRight.y); + + Verify(x2 >= bounds.bottomLeft.x); + Verify(x2 <= bounds.topRight.x); + Verify(y2 >= bounds.bottomLeft.y); + Verify(y2 <= bounds.topRight.y); + + Byte + *dest_pointer; + int + x, + dest_fixup, + rect_width, + rect_height; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y1 = maximumY - y1; + y2 = maximumY - y2; + //--------------------------------------------------------- + // Ensure that rectangle is properly specified + //--------------------------------------------------------- + if (x2 < x1) + { + int temp; + + temp = x1; + x1 = x2; + x2 = temp; + } + + if (y2 < y1) + { + int temp; + + temp = y1; + y1 = y2; + y2 = temp; + } + //--------------------------------------------------------- + // Verify that values are legitimate + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + Verify(x1 >= 0); + Verify(x1 <= x2); + Verify(x2 < width); + + Verify(y1 >= 0); + Verify(y1 <= y2); + Verify(y2 < height); + //--------------------------------------------------------- + // Update changedLine array + //--------------------------------------------------------- + MarkChangedLines(y1, y2); + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to fill + //--------------------------------------------------------- +# if defined(DEBUG) + Tell( + "x1=" << x1 << ", " << "y1=" << y1 << "\n" << + "x2=" << x2 << ", " << "y2=" << y2 << "\n" << + std::flush + ); +# endif + buildDestPointer(x1, y1, &dest_pointer); + + rect_height = y2 - y1 + 1; + rect_width = x2 - x1 + 1; + dest_fixup = width - rect_width; + +# if defined(DEBUG) + Tell( + "rect_height=" << rect_height << "\n" << + "rect_width=" << rect_width << "\n" << + "dest_fixup=" << dest_fixup << "\n" << + std::flush + ); +# endif + //--------------------------------------------------------- + // Fill the rectangle + //--------------------------------------------------------- + switch(operation) + { + case GraphicsDisplay::Replace: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer = (Byte) color; + dest_pointer++; + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::And: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer++ &= (Byte) color; + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Or: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer++ |= (Byte) color; + } + dest_pointer += dest_fixup; + } + break; + + case GraphicsDisplay::Xor: + for( ; rect_height>0; --rect_height) + { + for(x=rect_width; x>0; --x) + { + *dest_pointer++ ^= (Byte) color; + } + dest_pointer += dest_fixup; + } + break; + } + Check_Fpu(); +} + + +void + Video8BitBuffered::DrawText( + int /*color*/, + int /*bitmask*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +# if defined(DEBUG) + Tell("Video8BitBuffered::DrawText()\n"); +# endif + Check(this); + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + Check_Fpu(); + if (!valid) + { + return; + } +} + +//=================================================================== +// DrawBitMap +//=================================================================== +void + Video8BitBuffered::DrawBitMap( + int color, + int /*bitmask*/, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawBitMap(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer; + Byte + *dest_pointer_begin, + *dest_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + switch (rotation) + { + default: + //-------------------------------------------- + // transparent bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("zero: xp=" << (x+map_width-1) << ", yp=" << (y-map_height+1) << "\n"); +# endif + Verify(x+map_width-1 >= 0); + Verify(x+map_width-1 < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent bitmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_height) << ", yp=" << (y-(map_width-1)) << "\n"); +# endif + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + WRITEPIXEL(dest_pointer, operation, color) + } + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawBitMapOpaque +//=================================================================== +void + Video8BitBuffered::DrawBitMapOpaque( + int foreground, + int background, + int /*bitmask*/, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawBitMapOpaque(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y, + bits, + bit_test, + first_bit_test; + + Word + *source_pointer_begin, + *source_pointer; + Byte + *dest_pointer_begin, + *dest_pointer; + Byte + color; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(bitmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < bitmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < bitmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = bitmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= bitmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= bitmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + bitmap->Data.MapPointer + + (sLeft >> 4) + + (sBottom * bitmap->Data.WidthInWords); + + first_bit_test = 1 << (15-(sLeft & 15)); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + switch (rotation) + { + default: + //-------------------------------------------- + // opaque bitmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("zero: xp=" << (x+map_width) << ", yp=" << (y-map_height+1) << "\n"); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width <= width); // HACK? <, or <=? + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + UP_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // opaque bitmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("90 xp=" << (x+map_height) << ", yp=" << (y+map_width) << "\n"); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + RIGHT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // opaque bitmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_width+1) << ", yp=" << (y+map_height) << "\n"); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + DOWN_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // opaque bitmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("xp=" << (x-map_height+1) << ", yp=" << (y-(map_width-1)) << "\n"); +# endif + + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_BITMAP(source_pointer_begin, bitmap); + LEFT_DEST(dest_pointer_begin); + + bit_test = first_bit_test; + bits = *source_pointer++; + + for(x=map_width; x>0; --x,bit_test>>=1) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + if (bit_test == 0) + { + bit_test = 0x8000; + bits = *source_pointer++; + } + + if (bits & bit_test) + { + color = (Byte) foreground; + } + else + { + color = (Byte) background; + } + WRITEPIXEL(dest_pointer, operation, color) + UP_DEST(dest_pointer); + } + } + break; + } + Check_Fpu(); +} + +//=================================================================== +// DrawPixelMap8 +//=================================================================== +void + Video8BitBuffered::DrawPixelMap8( + int */*translation_table*/, + int /*bitmask*/, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawPixelMap8(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + color, + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + if (opaque) + { + switch (rotation) + { + default: + //-------------------------------------------- + // Opaque pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Opaque pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Opaque pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Opaque 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Opaque pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Opaque 270: x=" << x << ", y=" << y << "\n"); + Tell("xp=" << x-map_height << ", yp=" << y-(map_width-1) << "\n"); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + color = *source_pointer++; //SOURCE_RIGHT + WRITEPIXEL(dest_pointer, operation, color) + UP_DEST(dest_pointer); + } + } + break; + } + } + else + { + switch (rotation) + { + default: + //-------------------------------------------- + // Transparent pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Transparent pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Transparent pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "transparent 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Transparent pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("transparent 270: x=" << x << ", y=" << y << "\n"); + Tell("xp=" << x-map_height << ", yp=" << y-(map_width-1) << "\n"); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-(map_width-1) >= 0); + Verify(y-(map_width-1) < height); + + MarkChangedLines(y-(map_width-1), y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + color = *source_pointer++; //SOURCE_RIGHT + if (color) + { + WRITEPIXEL(dest_pointer, operation, color) + } + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//=================================================================== +// DrawPixelMap8SingleColor +//=================================================================== +void + Video8BitBuffered::DrawPixelMap8SingleColor( + int color, + int /*bitmask*/, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ +# if defined(DEBUG) + Tell( + "Video8BitBuffered::DrawPixelMap8SingleColor(<" << + x << ", " << + y << ">,<" << + sLeft << ", " << + sBottom << ", " << + sRight << ", " << + sTop << ">" << + ")\n" + ); +# endif + Check(this); + Verify(x >= bounds.bottomLeft.x); + Verify(x <= bounds.topRight.x); + Verify(y >= bounds.bottomLeft.y); + Verify(y <= bounds.topRight.y); + + int + map_width, + map_height, + map_max_y; + + Byte + source_data, + *source_pointer_begin, + *source_pointer, + *dest_pointer_begin, + *dest_pointer; + + //--------------------------------------------------------- + // If pixelbuffer is invalid, do nothing + //--------------------------------------------------------- + if (!valid) + { + Check_Fpu(); + return; + } + //--------------------------------------------------------- + // Ensure that source rectangle is properly specified + //--------------------------------------------------------- + Verify(pixelmap != NULL); + + Verify(sLeft >= 0); + Verify(sLeft <= sRight); + Verify(sRight < pixelmap->Data.Size.x); + + Verify(sBottom >= 0); + Verify(sBottom <= sTop); + Verify(sTop < pixelmap->Data.Size.y); + //--------------------------------------------------------- + // Convert to screen co-ordinates + //--------------------------------------------------------- + y = maximumY - y; + + map_max_y = pixelmap->Data.Size.y-1; + sTop = map_max_y - sTop; + sBottom = map_max_y - sBottom; + + map_width = sRight - sLeft + 1; + map_height = sBottom - sTop + 1; + +# if defined(DEBUG) + Tell("x=" << x << ", y=" << y << "\n"); + Tell("sTop=" << sTop << ", sBottom=" << sBottom << "\n"); + Tell("map_width=" << map_width << ", map_height=" << map_height << "\n"); +# endif + + Verify(map_width > 0); + Verify(map_width <= pixelmap->Data.Size.x); + Verify(map_height > 0); + Verify(map_height <= pixelmap->Data.Size.y); + + Verify(x >= 0); + Verify(x < width); + Verify(y >= 0); + Verify(y < height); + + //--------------------------------------------------------- + // We really need inverse bitmap here + //--------------------------------------------------------- +// bitmask = ~bitmask; + //--------------------------------------------------------- + // Prepare to draw bitmap + //--------------------------------------------------------- + Verify(pixelBuffer->Data.MapPointer != NULL); + + source_pointer_begin = + pixelmap->Data.MapPointer + + sLeft + + (sBottom * pixelmap->Data.Size.x); + + buildDestPointer( + x, y, + &dest_pointer_begin + ); + + { + switch (rotation) + { + default: + //-------------------------------------------- + // Single-color pixelmap, zero degrees + // .-----. + // | | + // | | + // Y | + // #X----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color zero: xp=" << (x+map_width) << + ", yp=" << (y-map_height+1) << "\n" + ); +# endif + Verify(x+map_width >= 0); + Verify(x+map_width < width); + Verify(y-map_height+1 >= 0); + Verify(y-map_height+1 < height); + + MarkChangedLines(y-map_height+1, y); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + UP_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + RIGHT_DEST(dest_pointer); + } + } + break; + + case 90: + //-------------------------------------------- + // Single-color pixelmap, 90 degrees + // #Y----. + // X | + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 90: xp=" << (x+map_height) << + ", yp=" << (y+map_width) << "\n" + ); +# endif + Verify(x+map_height >= 0); + Verify(x+map_height < width); + Verify(y+map_width >= 0); + Verify(y+map_width < height); + + MarkChangedLines(y, y+map_width); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + RIGHT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + DOWN_DEST(dest_pointer); + } + } + break; + + case 180: + //-------------------------------------------- + // Single-color pixelmap, 180 degrees + // .----X# + // | Y + // | | + // | | + // .-----. + //-------------------------------------------- +# if defined(DEBUG) + Tell( + "Single-color 180: xp=" << (x-map_width+1) << + ", yp=" << (y+map_height) << "\n" + ); +# endif + Verify(x-map_width+1 >= 0); + Verify(x-map_width+1 < width); + Verify(y+map_height >= 0); + Verify(y+map_height < height); + + MarkChangedLines(y, y+map_height); + + for(y=map_height; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + DOWN_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + LEFT_DEST(dest_pointer); + } + } + break; + + case 270: + //-------------------------------------------- + // Single-color pixelmap, 270 degrees + // .-----. + // | | + // | X + // | | + // .--Y--# + //-------------------------------------------- +# if defined(DEBUG) + Tell("Single-color 270: x=" << x << ", y=" << y << "\n"); + Tell("xp=" << x-map_height << ", yp=" << y-map_width << "\n"); +# endif + Verify(x-map_height >= 0); + Verify(x-map_height < width); + Verify(y-map_width >= 0); + Verify(y-map_width < height); + + MarkChangedLines(y-map_width, y); + + for(y=map_height ; y>0; --y) + { + source_pointer = source_pointer_begin; + dest_pointer = dest_pointer_begin; + + UP_SOURCE(source_pointer_begin, pixelmap); + LEFT_DEST(dest_pointer_begin); + + for(x=map_width; x>0; --x) + { + Verify(dest_pointer >= pixelBuffer->Data.MapPointer); + Verify(dest_pointer < pixelBuffer->Data.MapPointer+ + (width*height)); + + source_data = *source_pointer++; //SOURCE_RIGHT + if (source_data) + { + WRITEPIXEL(dest_pointer, operation, color) + } + UP_DEST(dest_pointer); + } + } + break; + } + } + Check_Fpu(); +} + +//######################################################################## +//########################### L4BytePort ############################# +//######################################################################## + +L4BytePort::L4BytePort( + Video8BitBuffered *graphics_display, + const char *name, + int rotation +):GraphicsPort(graphics_display, name) +{ + // + // Save the base rotation value + // + baseRotation = rotation; + // + // Initialize conversion constants + // + maximumX = bounds.topRight.x - bounds.bottomLeft.x; + maximumY = bounds.topRight.y - bounds.bottomLeft.y; + // + // Overwrite the GraphicsPort::bounds data with rotated values + // for GraphView's benefit + // + switch(baseRotation) + { + default: + // do nothing + break; + + case 90: + case 270: + if (graphics_display != NULL) + { + Check(graphics_display); + bounds.bottomLeft.x = graphics_display->bounds.bottomLeft.y; + bounds.bottomLeft.y = graphics_display->bounds.bottomLeft.x; + bounds.topRight.x = graphics_display->bounds.topRight.y; + bounds.topRight.y = graphics_display->bounds.topRight.x; + } + break; + } + Check_Fpu(); +} + +L4BytePort::~L4BytePort() +{ + Check(this); + Check_Fpu(); +} + +Logical + L4BytePort::TestInstance() const +{ + return True; +} + +void + L4BytePort::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "L4BytePort:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "baseRotation =" << baseRotation << "\n"; + std::cout << temp << "maximumX =" << maximumX << "\n"; + std::cout << temp << "maximumY =" << maximumY << "\n"; + std::cout << temp << "bounds =" << bounds << "\n"; + std::cout << std::flush; + GraphicsPort::ShowInstance(temp); + Check_Fpu(); +} + +void + L4BytePort::DrawPoint( + int color, + Enumeration operation, + int x, int y + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + graphicsDisplay-> + DrawPoint( + color, + 0, + operation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4BytePort::DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawLine( + color, + 0, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y, + include_last_pixel + ); + Check_Fpu(); +} + +void + L4BytePort::DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + int + x1p, y1p, + x2p, y2p; + + convertPortPair(&x1p, &y1p, x1, y1); + convertPortPair(&x2p, &y2p, x2, y2); + + graphicsDisplay-> + DrawFilledRectangle( + color, + 0, + operation, + x1p+bounds.bottomLeft.x, y1p+bounds.bottomLeft.y, + x2p+bounds.bottomLeft.x, y2p+bounds.bottomLeft.y + ); + Check_Fpu(); +} + +void + L4BytePort::DrawText( + int /*color*/, + Enumeration /*operation*/, + Logical /*opaque*/, + int /*rotation*/, + Enumeration /*fontNumber*/, + Logical /*vertical*/, + GraphicsDisplay::Justification /*justification*/, + Rectangle2D */*clippingRectanglepointer*/, + char */*stringPointer*/ + ) +{ +} + +void + L4BytePort::DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMap( + color, + 0, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4BytePort::DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (bitmap == NULL) + { + Check_Fpu(); + return; + } + + if (bitmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(bitmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawBitMapOpaque( + color, + background, + 0, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + bitmap, + sLeft, sBottom, sRight, sTop + ); +} + +void + L4BytePort::DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8( + NULL, + 0, + operation, + opaque, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4BytePort::DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sLeft, int sBottom, int sRight, int sTop + ) +{ + Check(this); + + if (graphicsDisplay == NULL) + { + Check_Fpu(); + return; + } + + Check(graphicsDisplay); + + if (pixelmap == NULL) + { + Check_Fpu(); + return; + } + + if (pixelmap->Data.MapPointer == NULL) + { + Check_Fpu(); + return; + } + + Check(pixelmap); + + int + xp, yp; + + convertPortPair(&xp, &yp, x, y); + + rotation += baseRotation; + while (rotation < 0) { rotation += 360; } + while (rotation >= 360) { rotation -= 360; } + + graphicsDisplay-> + DrawPixelMap8SingleColor( + color, + 0, + operation, + rotation, + xp+bounds.bottomLeft.x, yp+bounds.bottomLeft.y, + pixelmap, + sLeft, sBottom, sRight, sTop + ); + Check_Fpu(); +} + +void + L4BytePort::convertPortPair( + int *xp, + int *yp, + int x, + int y + ) +{ + switch(baseRotation) + { + default: + *xp = x; + *yp = y; + break; + + case 90: + *xp = y; + *yp = maximumY - x; + break; + + case 180: + *xp = maximumX - x; + *yp = maximumY - y; + break; + + case 270: + *xp = maximumX - y; + *yp = x; + break; + } + Check_Fpu(); +} diff --git a/MUNGA_L4/L4VB8.h b/MUNGA_L4/L4VB8.h new file mode 100644 index 0000000..99f16fa --- /dev/null +++ b/MUNGA_L4/L4VB8.h @@ -0,0 +1,260 @@ +#pragma once + +#include "..\munga\graph2d.h" + +//######################################################################## +//######################### Video8BitBuffered ########################### +//######################################################################## +// +// X/Y values passed to these routines are assumed to be in +// the VIDEO DISPLAY COORDINATE SYSTEM, with (0,0) at the top left. +// +class Video8BitBuffered : + public GraphicsDisplay +{ +public: + Video8BitBuffered(int x, int y); + Video8BitBuffered(PixelMap8 *pixel_map); + + ~Video8BitBuffered(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + DrawPoint( + int color, + int bitmask, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + int bitmask, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + int *translation_table, + int bitmask, + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + int bitmask, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + +protected: + void + MarkChangedLines(int screenTop, int screenBottom); + + void + buildDestPointer( + int x, int y, + Byte **pixelPointer + ); + + Logical + valid, + createdPixelmap; + int + width, + height, + maximumX, + maximumY; + +public: + PixelMap8 + *pixelBuffer; +protected: + Word + *changedLine; +}; + + +//######################################################################## +//########################## L4BytePort ############################## +//######################################################################## +// +// X/Y values passed to these routines are assumed to be in +// the GRAPHICS COORDINATE SYSTEM, with (0,0) at the bottom left. +// +class L4BytePort : + public GraphicsPort +{ +public: + L4BytePort( + Video8BitBuffered *graphics_display, + const char *name, + int rotation + ); + + ~L4BytePort(); + + Logical + TestInstance() const; + + void + ShowInstance(char *indent); + + void + DrawPoint( + int color, + Enumeration operation, + int x, int y + ); + + void + DrawLine( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2, + Logical include_last_pixel + ); + + void + DrawFilledRectangle( + int color, + Enumeration operation, + int x1, int y1, + int x2, int y2 + ); + + void + DrawText( + int color, + Enumeration operation, + Logical opaque, + int rotation, + Enumeration fontNumber, + Logical vertical, + GraphicsDisplay::Justification justification, + Rectangle2D *clippingRectanglePtr, + char *stringPointer + ); + + void + DrawBitMap( + int color, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawBitMapOpaque( + int color, + int background, + Enumeration operation, + int rotation, + int x, int y, + BitMap *bitmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8( + Enumeration operation, + Logical opaque, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); + + void + DrawPixelMap8SingleColor( + int color, + Enumeration operation, + int rotation, + int x, int y, + PixelMap8 *pixelmap, + int sx1, int sy1, int sx2, int sy2 // these are SOURCE coordinates + ); +protected: + void + convertPortPair( + int *xp, + int *yp, + int x, + int y + ); + + //------------------------------------------------------------ + // Protected data + //------------------------------------------------------------ + int + baseRotation, + maximumX, + maximumY; +}; diff --git a/MUNGA_L4/L4VIDEO.cpp b/MUNGA_L4/L4VIDEO.cpp new file mode 100644 index 0000000..1762479 --- /dev/null +++ b/MUNGA_L4/L4VIDEO.cpp @@ -0,0 +1,7419 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "..\munga\door.h" +#include "..\munga\doorfram.h" +#include "..\munga\eyecandy.h" +#include "l4vidrnd.h" +#include "l4video.h" +#include "..\munga\matrix.h" +#include "..\munga\mover.h" +#include "..\munga\jmover.h" +#include "..\munga\player.h" +#include "..\munga\camship.h" +#include "..\munga\director.h" +#include "..\munga\mission.h" +#include "..\munga\cultural.h" +#include "..\munga\nttmgr.h" +#include "..\munga\app.h" +#include "l4particles.h" +#include "DXUtils.h" + +using namespace std; +#include +#include +#include +#include + +LPDIRECT3D9 gD3D = NULL; + +//STUBBED: DPL RB 1/14/07 +// when this is resolved it can be removed +#include "..\DPLSTUB.h" + +#include +#define char8 unsigned char +#define uint32 unsigned __int32 + +// basic macro to help with releasing things +#define SAFE_RELEASE(handle) if (handle) { handle->Release(); handle = NULL; } + +#define PILL_COUNT 20 +#define PILL_SIZE (y_size*0.03125) // 32 @ 1280x1024 +#define PILL_SPACING (PILL_SIZE*0.625) // 20 @ 1280x1024 +#define LOAD_COLOR 0xFF6565FF +#define FADE_IN 0.05f +#define PILL_ON 0.05f +#define FADE_OUT 0.5f +#define LOAD_TEXT_HEIGHT PILL_SIZE // 32 @ 1280x1024 +#define LOAD_TEXT_WIDTH (LOAD_TEXT_HEIGHT*12.125) // 388 @ 1280x1024 +#define PS_OFF 0 +#define PS_FADINGIN 1 +#define PS_ON 2 +#define PS_FADINGOUT 3 +#define LOAD_TEXT_VERT (PILL_SIZE/2.0) + +#ifdef LOGFRAMERATE +FILE *FRAMERATE_LOG; +#endif + +// +// Includes for the DPL libraries +// +// RB 1/15/07 +//#include +//#include +//#include +//#include +//#include +// +// You can enable or disable these traces here for quicker rebuilding during +// profile testing, but for production they should be all turned off! +// +//#define TRACE_VIDEO_CULL_SETUP +//#define TRACE_VIDEO_VEHICLE_RENDERABLES +// #define TRACE_VIDEO_ALL_RENDERABLES +// +// These are other traces you can use to extract data +// +#if defined(TRACE_VIDEO_LOAD_OBJECT) + static BitTrace Video_Load_Object("Video Load Object"); + #define SET_VIDEO_LOAD_OBJECT() Video_Load_Object.Set() + #define CLEAR_VIDEO_LOAD_OBJECT() Video_Load_Object.Clear() +#else + #define SET_VIDEO_LOAD_OBJECT() + #define CLEAR_VIDEO_LOAD_OBJECT() +#endif + +#if defined(TRACE_VIDEO_CONSTRUCT_ROOT) + static BitTrace Video_Construct_Root("Video Construct Root"); + #define SET_VIDEO_CONSTRUCT_ROOT() Video_Construct_Root.Set() + #define CLEAR_VIDEO_CONSTRUCT_ROOT() Video_Construct_Root.Clear() +#else + #define SET_VIDEO_CONSTRUCT_ROOT() + #define CLEAR_VIDEO_CONSTRUCT_ROOT() +#endif +// +// This is the time spent fetching and processing the pickpoint information +// from the DPL renderer. +// +#if defined(TRACE_VIDEO_PICKPOINT) + static BitTrace Video_Pickpoint("Video Pickpoint"); + #define SET_VIDEO_PICKPOINT() Video_Pickpoint.Set() + #define CLEAR_VIDEO_PICKPOINT() Video_Pickpoint.Clear() +#else + #define SET_VIDEO_PICKPOINT() + #define CLEAR_VIDEO_PICKPOINT() +#endif +// +// Traces the time spent setting up the video culling parameters +// +#if defined(TRACE_VIDEO_CULL_SETUP) + static BitTrace Video_Cull_Setup("Video Cull Setup"); +# define SET_VIDEO_CULL_SETUP() Video_Cull_Setup.Set() +# define CLEAR_VIDEO_CULL_SETUP() Video_Cull_Setup.Clear() +#else +# define SET_VIDEO_CULL_SETUP() +# define CLEAR_VIDEO_CULL_SETUP() +#endif +// +// This trace covers the entire time spent executing renderables as one +// transition. It goes up when the execute implimentation starts running +// over the all iterator and goes down when it's done. +// +#if defined(TRACE_VIDEO_RENDERABLES) + static BitTrace Video_Renderables("Video Renderables"); + #define SET_VIDEO_RENDERABLES() Video_Renderables.Set() + #define CLEAR_VIDEO_RENDERABLES() Video_Renderables.Clear() +#else + #define SET_VIDEO_RENDERABLES() + #define CLEAR_VIDEO_RENDERABLES() +#endif +// +// Traces time spent executing renderables that belong to a vehicle entity +// (currently Mech, VTV or BTPlayer) +// +#if defined(TRACE_VIDEO_VEHICLE_RENDERABLES) + static BitTrace Video_Vehicle_Renderables("Video Vehicle Renderables"); +# define SET_VIDEO_VEHICLE_RENDERABLES() Video_Vehicle_Renderables.Set() +# define CLEAR_VIDEO_VEHICLE_RENDERABLES() Video_Vehicle_Renderables.Clear() +#else +# define SET_VIDEO_VEHICLE_RENDERABLES() +# define CLEAR_VIDEO_VEHICLE_RENDERABLES() +#endif +// +// This trace will transition as each individual renderable is executed. +// It will buzz and cause serious impact to the accuracy of the trace but is +// good for identifying time-eating individual renderables +// +#if defined(TRACE_VIDEO_ALL_RENDERABLES) + static BitTrace Video_All_Renderables("Video All Renderables"); +# define SET_VIDEO_ALL_RENDERABLES() Video_All_Renderables.Set() +# define CLEAR_VIDEO_ALL_RENDERABLES() Video_All_Renderables.Clear() +#else +# define SET_VIDEO_ALL_RENDERABLES() +# define CLEAR_VIDEO_ALL_RENDERABLES() +#endif +// +// This is the routine that does a DPL_FlushArticulations on the batch of +// DCS's that we've been holding during rendering, std::flushing them all to +// the card in a big batch +// +#if defined(TRACE_VIDEO_BATCH_FLUSH) + static BitTrace Video_Batch_Flush("Video Batch Flush"); +# define SET_VIDEO_BATCH_FLUSH() Video_Batch_Flush.Set() +# define CLEAR_VIDEO_BATCH_FLUSH() Video_Batch_Flush.Clear() +#else +# define SET_VIDEO_BATCH_FLUSH() +# define CLEAR_VIDEO_BATCH_FLUSH() +#endif +// +// This trace shows the time spent doing the "frame done" processing where the +// renderer waits for the DPL card to become ready and then issues a command +// to start the scene drawing. An additional batch std::flush can happen here. +// If USE_ONE_VIDEO_TRACE is turned on, data from this trace will show up as +// part of the Video_Renderer trace. +// +#if defined(TRACE_VIDEO_RENDERER_FRAME_DONE) +# if defined(USE_ONE_VIDEO_TRACE) +# define SET_VIDEO_RENDERER_FRAME_DONE() Video_Renderer.Set() +# define CLEAR_VIDEO_RENDERER_FRAME_DONE() Video_Renderer.Clear() +# else + static BitTrace Video_Renderer_Frame_Done("Video Renderer Frame Done"); +# define SET_VIDEO_RENDERER_FRAME_DONE() Video_Renderer_Frame_Done.Set() +# define CLEAR_VIDEO_RENDERER_FRAME_DONE() Video_Renderer_Frame_Done.Clear() +# endif +#else +# define SET_VIDEO_RENDERER_FRAME_DONE() +# define CLEAR_VIDEO_RENDERER_FRAME_DONE() +#endif +// +// The following traces are specifically designed for profileing the low level +// DPL routines in Division's libraries. You need to link to a special "profile" +// version of the division libraries for these to work. If you enable them +// with a production libdpl you will get NO traces. If you disable them and +// try to link to a profile version of libdpl you will get link errors. Sorry +// but this is the most efficient way of connecting the c++ trace routines to +// the C code of division's libraries. +// +// There are switches in the DPL libraries that handle turning these functions +// on and off in the profile version. +// +//#define TRACE_DPL_LOAD_OBJECT +//#define TRACE_DPL_TRANSPUTER_LINK // will buzz +//#define TRACE_DPL_DO_OUTSW // will buzz +//#define TRACE_DPL_OUTINT32 // will buzz + +#if defined(TRACE_DPL_LOAD_OBJECT) + static BitTrace DPL_Load_Object("DPL Load Object"); + + extern "C" + { + void Set_DPL_Load_Object(); + void Clear_DPL_Load_Object(); + } + + void + Set_DPL_Load_Object() + { + DPL_Load_Object.Set(); + } + + void + Clear_DPL_Load_Object() + { + DPL_Load_Object.Clear(); + } +#endif + +#if defined(TRACE_DPL_TRANSPUTER_LINK) + static BitTrace DPL_Transputer_Link("DPL Transputer Link"); + + extern "C" + { + void Set_DPL_Transputer_Link(); + void Clear_DPL_Transputer_Link(); + } + + void + Set_DPL_Transputer_Link() + { + DPL_Transputer_Link.Set(); + } + + void + Clear_DPL_Transputer_Link() + { + DPL_Transputer_Link.Clear(); + } +#endif + +#if defined(TRACE_DPL_DO_OUTSW) + static BitTrace DPL_do_outsw("DPL do_outsw"); + + extern "C" + { + void Set_DPL_do_outsw(); + void Clear_DPL_do_outsw(); + } + + void + Set_DPL_do_outsw() + { + DPL_do_outsw.Set(); + } + + void + Clear_DPL_do_outsw() + { + DPL_do_outsw.Clear(); + } +#endif + +#if defined(TRACE_DPL_OUTINT32) + static BitTrace DPL_outint32("DPL outint32"); + + extern "C" + { + void Set_DPL_outint32(); + void Clear_DPL_outint32(); + } + + void + Set_DPL_outint32() + { + DPL_outint32.Set(); + } + + void + Clear_DPL_outint32() + { + DPL_outint32.Clear(); + } +#endif + +// +// The following trace will probably be obsolete soon +// + +#if 0 +#if defined(TRACE_VIDEO_FIRST_FRAME_DONE) + static BitTrace Video_First_Frame_Done("Video First Frame Done"); +# define SET_VIDEO_FIRST_FRAME_DONE() Video_First_Frame_Done.Set() +# define CLEAR_VIDEO_FIRST_FRAME_DONE() Video_First_Frame_Done.Clear() +#else +# define SET_VIDEO_FIRST_FRAME_DONE() +# define CLEAR_VIDEO_FIRST_FRAME_DONE() +#endif +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Definitions of various debugging switches +// +#define DEBUG_SPECIAL_CALLBACK 0 // 0 = none, 1 = print special, 2 = real noisy +#define DEBUG_CREATE_CALLBACK 0 // 0 = none, +#define PRINT_THE_PFX False // Set to true and the pfx definition will print when it is read in. +#define RAPID_SECT_PIXEL True // True if you want to use the rapidsectpixel call for intersections +#define PARTICLE_TEST False // True to issue a stream of particles at the detected intersect point +#define PRINT_PICKPOINT_TEST False // True to print data whenever the intersect changes +#define NOISY_RENDERER False // True enables a lot of printouts as the renderer makes/kills object +#define USE_TRACKER_STRUCTURE False // True to enable the full tracker structure that holds damage zone names & such +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Definitions of system constants used only in this file +// +#define MAX_SPECIAL_ARGUMENTS 25 // Maximum number of arguments a "special" callback can handle +#define MAX_SPECIAL_SIZE 512 // Maximum size (characters) of a "special" +#define dpl_arg_sep '~' // seperator used when parsing dpl argument string +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Entity + *Entity_Being_Created = 0; // !!! temp, till callback handlers become a class +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// These extern "c" routines and constants are from startdpl or from dpl +// itself and need to be here. +// +extern "C" { + //STUBBED: DPL RB 1/15/07 + //extern const int + // x_size, // x size of the screen (from startdpl) + // y_size; // y size of the screen (startdpl) + void + dpl_TexmapTexels2D ( // A routine from DPL we normally couldn't access + dpl_TEXMAP *tm, + uint32 *texels, + int32 u_size, + int32 v_size, + int32 bytes_per_texel); + int + screen_resolution( // Sets up the screen resolution (startdpl) + char *dpl_argv ), + explode_args( // Parses DPLARG system environmental (startdpl) + char **argv, + char *dpl_args, + char sep ); + char + *dpl_TypeToString( // Converts a DPL type code into a string (libdpl) + dpl_TYPE t); + int32 + dpl_DrawSceneComplete(void); // missing definition (libdpl) +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// see DPLReportPerfStats() +//STUBBED: VIDEO RB 1/15/07 +//extern "C" const int32 __sect_time; +//extern "C" const int32 __last_cull_time; +//extern "C" const int32 __last_draw_time; +//extern "C" const int32 __last_frame_time; +//extern "C" const int32 __last_pxpl_time; +//extern "C" const int32 __last_frame_prims; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// dump_frame_buffer() std::declaration +void dump_frame_buffer( + dpl_VIEW *eye, + int32 x_size, + int32 y_size, + Logical antialias); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The following are definitions of DPL callback functions. These are called +// by the dpl file loader as it is loading graphics files so we can do material +// substitution and set special attributes on geometry & such. +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The "special" callback is called whenever a "special" field is processed in +// incomming geometry. +// dPL special callback function type. +// typedef void (dpl_SPECIAL_CALLBACK)(dpl_TYPE type, void *handle, +// char8 *special, uint32 special_len); + +static void + TestSpecialCallBack( + dpl_TYPE type, + void *handle, + char8 *special, + uint32 special_len) +{ +//STUBBED: DPL RB 1/14/07 +// char +// *args[MAX_SPECIAL_ARGUMENTS], +// **argptr, +// *argstring; +// int +// argcount; +// float +// u0, +// v0, +// du, +// dv; +// int32 +// immunity; +// char +//// NameBuff[80], +// TempBuff[MAX_SPECIAL_SIZE + 1]; +// #if USE_TRACKER_STRUCTURE +// dpl_tracker +// *this_tracker; +// #endif +// +// if(special_len > MAX_SPECIAL_SIZE) +// { +// DEBUG_STREAM<<"SPECIAL was bigger than "< MAX_SPECIAL_SIZE); +// } +// strncpy(TempBuff, (const char*)special, special_len); +// TempBuff[special_len] = 0; +// if(TempBuff[special_len-1] != 0) +// { +// DEBUG_STREAM<<"Caution, the following SPECIAL was not null terminated\n" << std::flush; +// printf("SPECIAL->%08x: %s, %s\n", handle, dpl_TypeToString(type), TempBuff); +// } +// #if DEBUG_SPECIAL_CALLBACK >= 1 +// printf("SPECIAL->%08x: %s, %s\n", handle, dpl_TypeToString(type), TempBuff); +// #endif +//// +//// Scan all the argument start points into an array for easier processing. +//// also avoids non-reentrand problem with strtok +//// +// argstring = TempBuff; +// for(argcount = 0; argcount= 2 +// Tell("Calling SetObjectAdditiveLODs on an object\n"); +// #endif +// // REMOVE dpl_SetObjectAdditiveLODs to run with older renderers +// dpl_SetObjectAdditiveLODs ( (dpl_OBJECT *)handle); +// } +// } +// break; +// case dpl_type_lod: +// break; +// case dpl_type_geogroup: +// #if USE_TRACKER_STRUCTURE +// this_tracker = (dpl_tracker *)dpl_GetAppSpecific(handle); +// #endif +// for(argptr = args; +// *argptr; +// argptr++) +// { +// if (strncmp(*argptr, "dz_", 3) == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL GEOGROUP Damage zone "); +// #endif +// +// #if USE_TRACKER_STRUCTURE +// if (this_tracker) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("marked\n"); +// #endif +// strncpy(this_tracker->dz_name, *argptr, MAX_DZ_NAME_LENGTH); +// this_tracker->dz_name[MAX_DZ_NAME_LENGTH - 1] = 0; +// #endif +// //--------------------------------------------- +// // lookup damage zone index in global namelist +// //--------------------------------------------- +// if (Entity_Being_Created->damageZones) +// { +// Check_Pointer(Entity_Being_Created->damageZones); +// +// int +// damage_zone_index; +// +// damage_zone_index = +// Entity_Being_Created->GetDamageZoneIndex(*argptr); +// +// if (damage_zone_index != -1) +// { +// #if USE_TRACKER_STRUCTURE +// this_tracker->Damage_Zone_Number = damage_zone_index; +// #else +// if(dpl_GetAppSpecific(handle)) +// Fail("AppSpecific already set\n"); +// dpl_PutAppSpecific(handle, (void *)(damage_zone_index+1)); +// #endif +// } +// else +// { +// DEBUG_STREAM << std::endl << "Damage zone '" << +// *argptr << "' not in table." << std::endl; +// } +// } +// #if USE_TRACKER_STRUCTURE +// } +// else +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("NOT marked\n"); +// #endif +// } +// #endif +// } +// else if(strcmp(*argptr,"PUNCH") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL GEOGROUP Punchize\n"); +// #endif +// dpl_Punchize((dpl_GEOGROUP *)handle); +// } +// else if(strcmp(*argptr,"DAMAGE") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL GEOGROUP damagize\n"); +// #endif +// if(*(++argptr)) +// { +// int +// status; +// dpl_MATERIAL *damagize_material = dpl_LookupMaterial ( *argptr, dpl_lookup_normal, &status ); +// if(damagize_material) +// { +// dpl_Damagize((dpl_GEOGROUP *)handle, damagize_material); +// } +// else +// { +// DEBUG_STREAM<<"SPECIAL GEOGROUP DAMAGE couldn't find material "<<*argptr<<"\n" << std::flush; +// Verify(damagize_material); +// } +// } +// else +// { +// DEBUG_STREAM<<"SPECIAL GEOGROUP DAMAGE no material name \n" << std::flush; +// Verify(*argptr); +// } +// } +// else if(strcmp(*argptr,"WIREFRAME") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL GEOGROUP WIREFRAME\n"); +// #endif +// dpl_SetGeogroupWireframe((dpl_GEOGROUP *)handle, True); +// } +// else if(strcmp(*argptr,"GEOMETRIZE") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL GEOGROUP geometrize\n"); +// #endif +// if(*(++argptr)) +// { +// dpl_GEOMETRY +// *geometry_ptr; +// long +// geometrize_code; +// int +// geometry_id = 0; +// sscanf( +// *argptr, +// "%lx", +// &geometrize_code); +// do +// { +// geometry_ptr = dpl_GetGeogroupGeometry((dpl_GEOGROUP *)handle,geometry_id); +// if(geometry_ptr) +// { +// dpl_Geometrize(geometry_ptr,geometrize_code); +// } +// geometry_id++; +// } while(geometry_ptr); +// } +// else +// { +// DEBUG_STREAM<<"SPECIAL GEOGROUP GEOMETRIZE has no geometrize code\n" << std::flush; +// Verify(*argptr); +// } +// } +// else if(strcmp(*argptr,"DRAWLAST") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL GEOGROUP DRAWLAST\n"); +// #endif +// dpl_SetGeogroupDrawLast((dpl_GEOGROUP *)handle, True); +// dpl_FlushGeogroup((dpl_GEOGROUP *)handle); +// } +// else if(strcmp(*argptr,"BLINK") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("SPECIAL GEOGROUP BLINK is not supported\n"); +// #endif +// } +// else +// { +// DEBUG_STREAM<<"SPECIAL GEOGROUP "<<*argptr<<" is not a geogroup modifier\n" << std::flush; +// } +// } +// break; +// case dpl_type_geometry: +// break; +// case dpl_type_material: +// for(argptr = args; +// *argptr; +// argptr++) +// { +// if(strcmp(*argptr,"IMMUNE") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL MATERIAL IMMUNE\n"); +// #endif +// if(*(++argptr)) +// { +// immunity = atol(*argptr); +// dpl_SetMaterialFogImmunity ( (dpl_MATERIAL *)handle, immunity ); +// dpl_FlushMaterial((dpl_MATERIAL *)handle); +// } +// else +// { +// DEBUG_STREAM<<"SPECIAL MATERIAL IMMUNE has no immune code\n" << std::flush; +// Verify(*argptr); +// } +// } +// else +// { +// DEBUG_STREAM<<"SPECIAL MATERIAL "<<*argptr<<" is not a material modifier\n" << std::flush; +// } +// } +// break; +// case dpl_type_texture: +// for(argptr = args; +// *argptr; +// argptr++) +// { +// if(strcmp(*argptr,"SCROLL") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SCROLL\n"); +// #endif +// u0 = v0 = du = dv = 0.0; +// if(*(++argptr)) +// u0 = atof(*argptr); +// else +// { +// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing u0\n" << std::flush; +// Verify(*argptr); +// } +// if(*(++argptr)) +// v0 = atof(*argptr); +// else +// { +// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing v0\n" << std::flush; +// Verify(*argptr); +// } +// if(*(++argptr)) +// du = atof(*argptr); +// else +// { +// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing du\n" << std::flush; +// Verify(*argptr); +// } +// if(*(++argptr)) +// dv = atof(*argptr); +// else +// { +// DEBUG_STREAM<<"SPECIAL TECTURE SCROLL missing dv\n" << std::flush; +// Verify(*argptr); +// } +// dpl_SetTextureScroll ( +// (dpl_TEXTURE *)handle, +// u0, +// v0, +// du, +// dv); +// dpl_FlushTexture((dpl_TEXTURE *)handle); +// } +// else if(strcmp(*argptr,"FAKESIZE") == 0) +// { +// #if DEBUG_SPECIAL_CALLBACK >= 2 +// Tell("Doing SPECIAL TEXURE FAKESIZE\n"); +// #endif +// int +// size, offset; +// if(*(++argptr)) +// size = atoi(*argptr); +// else +// { +// DEBUG_STREAM<<"SPECIAL TEXTURE FAKESIZE missing size\n" << std::flush; +// Verify(*argptr); +// } +// if(*(++argptr)) +// offset = atoi(*argptr); +// else +// { +// DEBUG_STREAM<<"SPECIAL TEXTURE FAKESIZE missing offset\n" << std::flush; +// Verify(*argptr); +// } +// dpl_FakeTextureSize((dpl_TEXTURE *)handle,size,offset); +// dpl_FlushTexture((dpl_TEXTURE *)handle); +// } +// else +// { +// DEBUG_STREAM<<"SPECIAL TEXTURE "<<*argptr<<" is not a texture modifier\n" << std::flush; +// } +// } +// break; +// case dpl_type_texmap: +// break; +// case dpl_type_ramp: +// break; +// } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// The TestCreateCallBack callback is called whenever a dpl node of the indicated +// type is created while loading a DPL graphics file. +/* dPL create/delete callback function type. */ +//typedef void (dpl_CREATE_DELETE_CALLBACK)(dpl_TYPE type, void *handle); + +static void + TestCreateCallBack( + dpl_TYPE type, + #if DEBUG_CREATE_CALLBACK>=1 + void *handle + #else + void * + #endif + ) +{ + // + // get a pointer to the node structure (first part of most dpl types) + // + #if DEBUG_CREATE_CALLBACK >=1 + printf("CREATE->%08x: %s\n", handle, dpl_TypeToString(type)); + #endif + switch(type) + { + case dpl_type_error: + break; + case dpl_type_scene: + break; + case dpl_type_zones: + break; + case dpl_type_view: + break; + case dpl_type_instance: + break; + case dpl_type_dcs: + break; + case dpl_type_light: + break; + case dpl_type_object: + break; + case dpl_type_lod: + break; + case dpl_type_geogroup: + #if USE_TRACKER_STRUCTURE + { + dpl_tracker *this_tracker = new dpl_tracker; + this_tracker->This_Entity = Entity_Being_Created; + this_tracker->dz_name[0] = 0; + this_tracker->Damage_Zone_Number = -1; // no damage zone (default) + if(dpl_GetAppSpecific(handle)) + DEBUG_STREAM<<"app_specific hook already set!\n" << std::flush; + dpl_PutAppSpecific(handle, this_tracker); + + break; + } + #endif + case dpl_type_geometry: + break; + case dpl_type_material: + break; + case dpl_type_texture: + break; + case dpl_type_texmap: + break; + case dpl_type_ramp: + break; + } +} + +//############################################################################# +// Code to setup and handle material substitutions. +//############################################################################# +// +NameList + *materialSubstitutionList = NULL; + +const char *opMaterialName(const char *fileName, int opId) +{ + hash_map>::const_iterator fileIter = gOpNames->find(string(fileName)); + + if (fileIter != gOpNames->end()) + { + hash_map::const_iterator matIter = (*fileIter).second.find(opId); + + if (matIter != (*fileIter).second.end()) + { + return (*matIter).second.c_str(); + } + } + + return NULL; +} + +void loadTables() +{ + gOpNames = new hash_map>(); + gReplacementData = new hash_map(); + + FILE * opNames = fopen("VIDEO\\REPLACEMATS.tbl", "rb"); + + size_t numMats; + + fread(&numMats, sizeof(size_t), 1, opNames); + + for (int i = 0; i < (int)numMats; i++) + { + int opNum, fileNameLen, matNameLen; + + fread(&opNum, sizeof(int), 1, opNames); + fread(&fileNameLen, sizeof(int), 1, opNames); + + char *fileName = new char[fileNameLen]; + + fread(fileName, sizeof(char), fileNameLen, opNames); + + fread(&matNameLen, sizeof(int), 1, opNames); + + char *matName = new char[matNameLen]; + + fread(matName, sizeof(char), matNameLen, opNames); + + hash_map>::const_iterator fileIter = gOpNames->find(string(fileName)); + + if (fileIter != gOpNames->end()) + { + hash_map::const_iterator matIter = (*fileIter).second.find(opNum); + + if (matIter != (*fileIter).second.end()) + { + (*gOpNames)[string(fileName)][opNum] = string(matName); + } else + { + (*gOpNames)[string(fileName)].insert(pair(opNum, string(matName))); + } + } else + { + hash_map fileMap; + fileMap.insert(pair(opNum, string(matName))); + + gOpNames->insert(pair>(string(fileName), fileMap)); + } + + delete [] fileName; + delete [] matName; + } + + fclose(opNames); + + FILE *replacementData = fopen("VIDEO\\MATREPLACETABLE.tbl", "rb"); + + fread(&numMats, sizeof(size_t), 1, replacementData); + + for (int i = 0; i < (int)numMats; i++) + { + int matNameLen, texNameLen; + + fread(&matNameLen, sizeof(int), 1, replacementData); + + char *matName = new char[matNameLen]; + fread(matName, sizeof(char), matNameLen, replacementData); + + fread(&texNameLen, sizeof(int), 1, replacementData); + + char *texName = new char[texNameLen]; + fread(texName, sizeof(char), texNameLen, replacementData); + + ReplacementMaterialData data; + data.texName = string(texName); + + fread(&data, sizeof(float), 3, replacementData); + + gReplacementData->insert(pair(string(matName), data)); + + delete [] matName; + delete [] texName; + } + + fclose(replacementData); +} + +/* dPL material name callback function type. */ +//typedef char8 *(dpl_MATERIAL_NAME_CALLBACK)(char8 *mat_name); +char* + substituteMaterial( + char *source + ) +{ + static char + buffer[MATERIAL_NAME_BUFFER_LENGTH]; + NameList::Entry + *entry; + const char + *search, + *replace, + *pc; + int + len; + //---------------------------------------------- + // perform text substitution + // first match in the sub list gets substituted + // materialSubstitutionList is a pre-prepared global namelist. + //---------------------------------------------- + if (materialSubstitutionList == NULL) + { + return source; + } + + entry = materialSubstitutionList->GetFirstEntry(); + while (entry) + { + search = entry->GetName(); + if (search && *search && (pc = strstr((char*)source, search)) != NULL) + { + replace = entry->GetChar(); + *buffer = '\0'; + + len = (char*)pc - source; + while (*replace == '<') + { + ++replace; + --len; + } + if (len > 0) + { + strncat(buffer, (const char*)source, len); + } + + pc += strlen(search); + len = strlen(replace); + while (len && *(replace+len-1) == '>') + { + --len; + if (*pc) { ++pc; } + } + if (len > 0) + { + strncat(buffer, replace, len); + } + + Str_Cat(buffer, pc, MATERIAL_NAME_BUFFER_LENGTH); + + delete [] source; + source = new char[strlen(buffer) + 1]; + + Str_Copy((char*)source, buffer, MATERIAL_NAME_BUFFER_LENGTH); + break; + } + entry = entry->GetNextEntry(); + } + return source; +} + +vector DPLRenderer::MonitorsCreateAll(int &monitorCount) +{ + monitorCount = gD3D->GetAdapterCount(); + + vector allMonitors(monitorCount); + + for(UINT i = 0; i < monitorCount; i++) + { + HMONITOR monitorHandle = gD3D->GetAdapterMonitor(i); + MONITORINFO info; + info.cbSize = sizeof(MONITORINFO); + GetMonitorInfo(monitorHandle, &info); + allMonitors[i] = info; + } + + return allMonitors; +} + +void DPLRenderer::SetCoreRenderStates() +{ + + mDevice->SetRenderState(D3DRS_ZENABLE, D3DZB_USEW); + + float size = 1.0f; + mDevice->SetRenderState(D3DRS_POINTSIZE, *(DWORD*)(&size)); + + mDevice->SetRenderState(D3DRS_CULLMODE, D3DCULL_CW); + + D3DXMATRIX view_matrix, proj_matrix; + D3DXMatrixIdentity(&view_matrix); + D3DXMatrixOrthoLH(&proj_matrix, x_size, y_size, 1.0f, 1000.0f); + mDevice->SetTransform(D3DTS_VIEW, &view_matrix); + mDevice->SetTransform(D3DTS_PROJECTION, &proj_matrix); + + mDevice->SetRenderState(D3DRS_LIGHTING, false); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, true); + + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_TEXTURE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_DIFFUSE); + + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_TEXTURE); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TFACTOR); + + mDevice->SetRenderState(D3DRS_SRCBLEND, D3DBLEND_SRCALPHA); + mDevice->SetRenderState(D3DRS_DESTBLEND, D3DBLEND_INVSRCALPHA); + mDevice->SetRenderState(D3DRS_BLENDOP, D3DBLENDOP_ADD); + + mDevice->SetSamplerState(0, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + mDevice->SetSamplerState(1, D3DSAMP_MIPFILTER, D3DTEXF_LINEAR); + mDevice->SetSamplerState(0, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + mDevice->SetSamplerState(0, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); + mDevice->SetSamplerState(1, D3DSAMP_MINFILTER, D3DTEXF_LINEAR); + mDevice->SetSamplerState(1, D3DSAMP_MAGFILTER, D3DTEXF_LINEAR); +} +//----------------------------------------------------------------------------- +//--------------------------DPL video resource object-------------------------- +//----------------------------------------------------------------------------- +//############################################################################# +//############################ L4VideoObject ############################ +//############################################################################# + +L4VideoObject::L4VideoObject( + const char *filename, + ResourceType resource_type, + Enumeration renderer_modes, // RendererModes + float blink_period, + float percent_time_on +) +{ + Check_Pointer(filename); + + Str_Copy(objectFilename, filename, sizeof(objectFilename)); + //--------------------------------------------------------------- + // pad objectFilename with nulls so all .res files are identical + //--------------------------------------------------------------- + char + *p = objectFilename + strlen(filename) + 1, + *c = objectFilename + sizeof(objectFilename); + + for (; p < c; ++p) + { *p = '\0'; } + + resourceType = resource_type; + rendererModes = renderer_modes; + blinkPeriod = blink_period; + percentTimeOn = percent_time_on; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4VideoObject::~L4VideoObject() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4VideoObject::TestInstance() const +{ + Verify( strlen(objectFilename) < sizeof(objectFilename) ); + return True; +} + +//############################################################################# +//######################## L4VideoObjectWrapper ######################### +//############################################################################# + +L4VideoObjectWrapper::L4VideoObjectWrapper( + L4VideoObject *video_object, + Logical delete_object +) +{ + Check_Pointer(video_object); // do not use Check() + + videoObject = video_object; + deleteObject = delete_object; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4VideoObjectWrapper::~L4VideoObjectWrapper() +{ + if (deleteObject) + { + Unregister_Pointer(videoObject); + delete videoObject; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4VideoObjectWrapper::TestInstance() const +{ + if (videoObject) + { + Check_Pointer(videoObject); // do not use Check() + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// static +int L4VideoObjectWrapper::BuildVideoObjectChainFromResource(ChainOf *video_chain, ResourceDescription *video_resource) +{ + //do not Check(this) - static + Check(video_chain); + Check(video_resource); + + const char *video_pointer; + int object_count, index; + long object_size; + L4VideoObject *video_object; + L4VideoObjectWrapper *video_wrapper; + + //---------------------------------------------------- + // convert video resource into chain of video objects + //---------------------------------------------------- + video_pointer = (char *)video_resource->resourceAddress; + Check_Pointer(video_pointer); + + object_count = *((int *)video_pointer); + video_pointer += sizeof(int); + + object_size = sizeof(L4VideoObject); + Verify(video_resource->resourceSize == sizeof(int) + object_count * object_size); + + //Tell("video chain: ("<GetObjectFilename()<<"' 0x"<GetRendererModes()); + + video_wrapper = new L4VideoObjectWrapper(video_object, False); + Register_Object(video_wrapper); + + video_chain->Add(video_wrapper); + } + + //Tell(std::dec<<"\n"); + + return object_count; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// static +void + L4VideoObjectWrapper::DeleteVideoObjectChain( + ChainOf *video_chain + ) +{ + //do not Check(this) - static + Check(video_chain); + + ChainIteratorOf + video_iterator(video_chain); + L4VideoObjectWrapper + *video_wrapper; + + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + Check(video_wrapper); + + Unregister_Object(video_wrapper); + delete video_wrapper; + } + return; +} + +void DPLRenderer::FindBestAdapterIndices(bool isWindowed) +{ + bool spanDisable = false; + bool *spanDisablePtr = NULL; + + //Get all available monitor indices & stats + int monitorCount = 0; + std::vector monitors = this->MonitorsCreateAll(monitorCount); + int monitorReserved = 0x10000000; + + //Test for primary gauge override + char* gaugeAdapterString = getenv("PRIMGAUGE"); + if (gaugeAdapterString != NULL) + { + mPrimaryIndex = new int; + *mPrimaryIndex = atoi(gaugeAdapterString); + DEBUG_STREAM << "Primary gauge override- adapter " << *mPrimaryIndex << std::endl; + } + + //Test for secondary gauge override + gaugeAdapterString = getenv("SECGAUGE"); + if (gaugeAdapterString != NULL) + { + mSecondaryIndex = new int; + *mSecondaryIndex = atoi(gaugeAdapterString); + DEBUG_STREAM << "Secondary gauge override- adapter " << *mSecondaryIndex << std::endl; + } + + //Only do gauge overrides if we're using gauges during this execution + if (!Application::DoSuppressGauges()) + { + //Test for gauge1 override + gaugeAdapterString = getenv("MFDGAUGE"); + if (gaugeAdapterString != NULL) + { + mAux1Index = new int; + *mAux1Index = atoi(gaugeAdapterString); + DEBUG_STREAM << "MFD Gauge Override- adapter " << *mAux1Index << std::endl; + } + + //Test for span disable override + spanDisablePtr = NULL; + gaugeAdapterString = getenv("SPANDISABLE"); + if (gaugeAdapterString != NULL) + { + spanDisable = atoi(gaugeAdapterString); + spanDisablePtr = &spanDisable; + DEBUG_STREAM << "Spanning Override: Span "; + + if (*spanDisablePtr) + { + DEBUG_STREAM << "Disabled"; + } else + { + DEBUG_STREAM << "Enabled"; + } + + DEBUG_STREAM << std::endl; + } + + if (spanDisablePtr == NULL || *spanDisablePtr) + { + //Test for gauge2 override + gaugeAdapterString = getenv("MFDGAUGE2"); + if (gaugeAdapterString != NULL) + { + mAux2Index = new int; + *mAux2Index = atoi(gaugeAdapterString); + DEBUG_STREAM << "MFD Gauge #2 Override- adapter " << *mAux2Index << std::endl; + } + } + + //Disable spanning if they overrode the 2nd gauge + if (spanDisablePtr == NULL && mAux2Index != NULL) + { + DEBUG_STREAM << "MFD Gauge #2 was overridden... forcing spanning disabled." << std::endl; + spanDisable = true; + spanDisablePtr = &spanDisable; + } + } + + //Remove all monitors explicitly assigned somewhere from the list of available monitors + if (mPrimaryIndex != NULL && (*mPrimaryIndex) >= 0 && (*mPrimaryIndex) < monitorCount) + { + monitors[*mPrimaryIndex].dwFlags |= monitorReserved; + } + + if (mSecondaryIndex != NULL && (*mSecondaryIndex) >= 0 && (*mSecondaryIndex) < monitorCount) + { + monitors[*mSecondaryIndex].dwFlags |= monitorReserved; + } + + if (mAux1Index != NULL && (*mAux1Index) >= 0 && (*mAux1Index) < monitorCount) + { + monitors[*mAux1Index].dwFlags |= monitorReserved; + } + + if (mAux2Index != NULL && (*mAux2Index) >= 0 && (*mAux2Index) < monitorCount) + { + monitors[*mAux2Index].dwFlags |= monitorReserved; + } + + if (mPrimaryIndex == NULL) + { + DEBUG_STREAM << "Trying to find the monitor marked as active in Windows..." << std::endl; + //Set up the monitor so marked as the primary (unless none are marked) + for (int i = 0; i < monitorCount; i++) + { + int flags = monitors[i].dwFlags; + + if ((flags & (MONITORINFOF_PRIMARY | monitorReserved)) == MONITORINFOF_PRIMARY) + { + DEBUG_STREAM << "Monitor " << i << " was set as active in Windows... setting it as the primary monitor." << endl; + mPrimaryIndex = new int; + *mPrimaryIndex = i; + monitors[i].dwFlags |= monitorReserved; + break; + } + } + } + + //Do gauges next, since they're the easiest to pick out + if (!Application::DoSuppressGauges() && !isWindowed && monitorCount > 2) + { + DEBUG_STREAM << "Gauges are on, we are not in windowed mode, and we have " << monitorCount << " available monitors, so will try to find MFDs..." << std::endl; + + if (mAux1Index == NULL && (spanDisablePtr == NULL || !(*spanDisablePtr))) + { + DEBUG_STREAM << "Don't have a MFD #1 monitor yet, and spanning is not explicitly disabled, so will try to find a really wide monitor for both MFDs..." << std::endl; + + //try to find a really wide monitor to use as gauge1 + for (int i = 0; i < monitorCount; i++) + { + if ((monitors[i].dwFlags & monitorReserved) == 0) + { + RECT size = monitors[i].rcMonitor; + + float aspect = ( (double)(size.right - size.left) / (double)(size.bottom - size.top)); + + if (aspect > 2.5f) + { + //Really wide! Probably a spanning monitor + DEBUG_STREAM << "Monitor " << i << " is really wide, so will try to use it as the MFDs." << std::endl; + + mAux1Index = new int; + *mAux1Index = i; + monitors[i].dwFlags |= monitorReserved; + + if (spanDisablePtr == NULL) + { + DEBUG_STREAM << "Explicitly setting spanning to enabled..." << std::endl; + spanDisable = FALSE; + spanDisablePtr = &(spanDisable); + } + break; + } + } + } + } + + int possibleAux2Index = -1; + if (mAux1Index == NULL && (spanDisablePtr == NULL || *spanDisablePtr)) + { + DEBUG_STREAM << "MFDs not found yet, and spanning isn't explicitly enabled. Will try to find two same-size monitors to use as MFDs..." << std::endl; + map,vector> sameSizeMonitors; + + //Group the unclaimed monitors by resolution + for (int i = 0; i < monitorCount; i++) + { + if ((monitors[i].dwFlags & monitorReserved) == 0) + { + int width = monitors[i].rcMonitor.right - monitors[i].rcMonitor.left; + int height = monitors[i].rcMonitor.bottom - monitors[i].rcMonitor.top; + + pair resolution(width, height); + if (sameSizeMonitors.find(resolution) == sameSizeMonitors.end()) + { + sameSizeMonitors[resolution] = vector(); + } + + sameSizeMonitors[resolution].insert(sameSizeMonitors[resolution].begin(), i); + } + } + + //Retrieve the bucket of monitors with at least two monitors and the smallest resolution (y res counts more than x res) + vector bestMonitors; + int smallestYRes = -1; + int bestXRes = -1; + for (map,vector>::iterator it = sameSizeMonitors.begin(); it != sameSizeMonitors.end(); it++) + { + if ((*it).second.size() >= 2) + { + int yRes = (*it).first.second; + int xRes = (*it).first.first; + + if (smallestYRes >= 0) + { + DEBUG_STREAM << "Multiple sets of identically-sized monitors are available. Will use smallest set..." << std::endl; + } + + if (smallestYRes < 0 || yRes < smallestYRes || (yRes == smallestYRes && xRes < bestXRes)) + { + smallestYRes = yRes; + bestXRes = xRes; + bestMonitors = (*it).second; + } + } + } + + int aux1Candidate = -1; + int aux2Candidate = -1; + + int aux1Right = 0; + int aux2Right = 0; + + if (bestMonitors.size() > 2) + { + DEBUG_STREAM << "More than 2 monitors in the set of smallest, identically-sized monitors... Will use the furthest right as right MFD, one just to the left of that as left MFD..." << std::endl; + } + + //The second aux screen is the one furthest to the right + //the first aux screen is the one just to the left of that one + for (vector::iterator it = bestMonitors.begin(); it != bestMonitors.end(); it++) + { + int i = (*it); + + if ((monitors[i].dwFlags & monitorReserved) == 0) + { + int right = monitors[i].rcMonitor.right; + if (aux2Candidate < 0 || aux2Right < right) + { + aux1Candidate = aux2Candidate; + aux1Right = aux2Right; + aux2Candidate = i; + aux2Right = right; + } else if (aux1Candidate < 0 || aux1Right < right) + { + aux1Candidate = i; + aux1Right = right; + } + } + } + + if (aux1Candidate >= 0 && aux2Candidate >= 0) + { + DEBUG_STREAM << "Got two decent same-size monitors, will use as MFDs... Left is " << aux1Candidate << " and right is " << aux2Candidate << "." << std::endl; + mAux1Index = new int; + *mAux1Index = aux1Candidate; + monitors[aux1Candidate].dwFlags |= monitorReserved; + + mAux2Index = new int; + *mAux2Index = aux2Candidate; + monitors[aux2Candidate].dwFlags |= monitorReserved; + + spanDisable = true; + spanDisablePtr = &spanDisable; + } else + { + DEBUG_STREAM << "Could not find two identical monitors to use for MFDs." << std::endl; + } + } + + if (mAux2Index == NULL && mAux1Index != NULL && (spanDisablePtr == NULL || *spanDisablePtr)) + { + DEBUG_STREAM << "We have a left MFD and no right MFD, and spanning is not explicitly enabled. Will try to find identically-sized right MFD." << std::endl; + //find a monitor that is identical to the first gauge monitor + //if multiple, use the furthest to the right + int bestMonitorIndex = -1; + int bestMonitorRight = 0; + int aux1Width = (monitors[*mAux1Index].rcMonitor.right - monitors[*mAux1Index].rcMonitor.left); + int aux1Height = (monitors[*mAux1Index].rcMonitor.bottom - monitors[*mAux1Index].rcMonitor.top); + + for (int i = 0; i < monitorCount; i++) + { + if ((monitors[i].dwFlags & monitorReserved) == 0) + { + int monitorWidth = (monitors[i].rcMonitor.right - monitors[i].rcMonitor.left); + int monitorHeight = (monitors[i].rcMonitor.bottom - monitors[i].rcMonitor.top); + + if (monitorWidth == aux1Width && monitorHeight == aux1Height) + { + if (bestMonitorIndex >= 0) + { + DEBUG_STREAM << "Found more than one monitor identically sized to the left MFD. Will use furthest-right monitor." << std::endl; + } + + if (bestMonitorIndex < 0 || bestMonitorRight < monitors[i].rcMonitor.right) + { + bestMonitorIndex = i; + bestMonitorRight = monitors[i].rcMonitor.right; + } + } + } + } + + if (bestMonitorIndex >= 0) + { + DEBUG_STREAM << "Using monitor " << bestMonitorIndex << "as right MFD monitor." << std::endl; + mAux2Index = new int; + *mAux2Index = bestMonitorIndex; + monitors[bestMonitorIndex].dwFlags |= monitorReserved; + } else + { + DEBUG_STREAM << "Could not find decent monitor for right MFD." << std::endl; + } + } + } else + { + DEBUG_STREAM << "Either MFDs are explicitly disabled, we're running in windowed mode, or we don't have enough monitors attached to this machine. MFD monitors will not be detected." << std::endl; + } + + if (mPrimaryIndex == NULL) + { + DEBUG_STREAM << "Still no appropriate primary monitor- will find tallest monitor to use." << std::endl; + //Pick the monitor with the highest y resolution (leftmost if there's a tie) + int bestMonitorIndex = -1; + int bestMonitorHeight = 0; + int bestMonitorX = 0; + + for (int i = 0; i < monitorCount; i++) + { + if ((monitors[i].dwFlags & monitorReserved) == 0) + { + int height = (monitors[i].rcMonitor.bottom - monitors[i].rcMonitor.top); + if (bestMonitorIndex < 0 || height > bestMonitorHeight || (height == bestMonitorHeight && monitors[i].rcMonitor.left < bestMonitorX)) + { + bestMonitorIndex = i; + bestMonitorHeight = height; + bestMonitorX = monitors[i].rcMonitor.left; + } + } + } + + if (bestMonitorIndex >= 0) + { + DEBUG_STREAM << "Using monitor " << bestMonitorIndex << " as primary monitor." << std::endl; + mPrimaryIndex = new int; + *mPrimaryIndex = bestMonitorIndex; + monitors[bestMonitorIndex].dwFlags |= monitorReserved; + } else + { + DEBUG_STREAM << "Could not find decent primary monitor. Likely no unclaimed monitors." << std::endl; + } + } + + if (mPrimaryIndex != NULL && isWindowed) + { + DEBUG_STREAM << "Game is currently running windowed mode- will set all remaining undefined monitors to be the same as the primary monitor." << std::endl; + if (mSecondaryIndex == NULL) + { + mSecondaryIndex = new int; + *mSecondaryIndex = *mPrimaryIndex; + } + + if (mAux1Index == NULL && mAux2Index == NULL) + { + mAux1Index = new int; + *mAux1Index = *mPrimaryIndex; + + mAux2Index = new int; + *mAux2Index = *mPrimaryIndex; + } + } else if (!isWindowed && mSecondaryIndex == NULL) + { + DEBUG_STREAM << "Detecting secondary monitor- will attempt to use furthest-left remaining monitor." << std::endl; + //Pick the leftmost remaining monitor + int leftmostIndex = -1; + int leftmostX = 0; + + for (int i = 0; i < monitorCount; i++) + { + if ((monitors[i].dwFlags & monitorReserved) == 0) + { + if (leftmostIndex < 0 || monitors[i].rcMonitor.left < leftmostX) + { + leftmostIndex = i; + leftmostX = monitors[i].rcMonitor.left; + } + } + } + + if (leftmostIndex >= 0) + { + DEBUG_STREAM << "Using monitor " << leftmostIndex << " as secondary monitor." << std::endl; + mSecondaryIndex = new int; + *mSecondaryIndex = leftmostIndex; + } else + { + DEBUG_STREAM << "Could not find appropriate secondary monitor. Likely no unclaimed monitors remain." << std::endl; + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLRenderer +// +DPLRenderer::DPLRenderer( + HWND hWnd, + unsigned int screenWidth, + unsigned int screenHeight, + bool fullscreen, + InterestType interest_type, + InterestDepth depth_calibration +): + VideoRenderer( + 1.0f, + 1.0f, + RendererPriority::DefaultRendererPriority, + interest_type, + depth_calibration + ), + projectile_list(NULL), + dplObjectCacheSocket(NULL, False), + dplJointToDCSTranslatorSocket(NULL,False), + dplRenderableSocket(NULL), + mRenderables(NULL), + x_size(screenWidth), + y_size(screenHeight), + mReticle(NULL), + mCamShipHUD(NULL), + mStaticObjectsHead(NULL), + mStaticObjectsCount(0), + mPrimaryIndex(NULL), + mSecondaryIndex(NULL), + mAux1Index(NULL), + mAux2Index(NULL) +{ + __int64 frequency = HiResCounterFreq(); +#ifdef LOGFRAMERATE + FRAMERATE_LOG = fopen("framerate.log", "wb"); + fwrite(&frequency, sizeof(__int64), 1, FRAMERATE_LOG); +#endif + + mCamera = NULL; + + loadTables(); + + // clear out our render lists + memset(mRenderLists, 0, sizeof(mRenderLists)); + memset(mNameTextures, 0, sizeof(mNameTextures)); + memset(mOrdinalTextures, 0, sizeof(mOrdinalTextures)); + + D3DXCreateMatrixStack(0, &m_MatrixStack); + m_MatrixStack->LoadIdentity(); + + gD3D = Direct3DCreate9(D3D_SDK_VERSION); + if (!gD3D) + { + DEBUG_STREAM<<"Couldn't create Direct3D interface!"<FindBestAdapterIndices(!fullscreen); + + memset(&mPresentParams, 0, sizeof(D3DPRESENT_PARAMETERS)); + + mPresentParams.BackBufferCount = 1; + mPresentParams.MultiSampleType = (D3DMULTISAMPLE_TYPE)atol(getenv("MULTISAMPLE")); + if (mPresentParams.MultiSampleType > 0) + { + gD3D->CheckDeviceMultiSampleType(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, D3DFMT_X8R8G8B8, !fullscreen, mPresentParams.MultiSampleType, &mPresentParams.MultiSampleQuality); + mPresentParams.MultiSampleQuality--; + } + mPresentParams.SwapEffect = D3DSWAPEFFECT_DISCARD; + mPresentParams.hDeviceWindow = hWnd; + mPresentParams.Flags = 0; + mPresentParams.FullScreen_RefreshRateInHz = (fullscreen)?60:D3DPRESENT_RATE_DEFAULT; + mPresentParams.PresentationInterval = D3DPRESENT_RATE_DEFAULT; + mPresentParams.BackBufferFormat = D3DFMT_X8R8G8B8; + mPresentParams.EnableAutoDepthStencil = TRUE; + mPresentParams.AutoDepthStencilFormat = D3DFMT_D24X8; + mPresentParams.Windowed = !fullscreen; + if (fullscreen) + { + mPresentParams.BackBufferWidth = screenWidth; + mPresentParams.BackBufferHeight = screenHeight; + } + + HRESULT hr; + + //DEBUG_STREAM<<"**************************"<GetAdapterModeCount(adapter, format); + // DEBUG_STREAM<EnumAdapterModes(adapter, format, mode, &displayMode); + // if (FAILED(hr)) + // { + // DEBUG_STREAM<<"\t\tFailed to retrieve display mode "<CreateDevice(*mPrimaryIndex, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &mPresentParams, &mDevice)); + if (FAILED(hr)) + { + DEBUG_STREAM<<"Couldn't create HARDWARE_VERTEXPROCESSING device."<CreateDevice(D3DADAPTER_DEFAULT, D3DDEVTYPE_HAL, hWnd, D3DCREATE_SOFTWARE_VERTEXPROCESSING, &mPresentParams, &mDevice)); + if (FAILED(hr)) + { + PostQuitMessage(1); + } + } + + mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 0.0f, 0); + mDevice->Present(NULL, NULL, NULL, NULL); + + ParticleEngine::Initialize(mDevice); + + SetCoreRenderStates(); + +//STUBBED: DPL RB 1/14/07 + char + Eye_Type[50], + *Eye_Arg, // Controls generation of the eye point + *DPL_Arg; // Points to DPLARG environment pointer once we get it + int + psfx_number; +// int +// i; // Temporary loop counter + float + eye_x, + eye_y, + eye_z, + eye_x_rot, + eye_y_rot, + eye_z_rot; +// +// Initialize a bunch of the variables to their starting values +// + eyeRelative = False; + completeCycleNeeded = False; + lastAppState = 0; + fogUpdating = True; + fogRed = 0.0f; + fogBlue = 0.0f; + fogGreen = 0.0f; + fogNear = 0.0f; + fogFar = 0.0f; + currentFogFar = 0.0f; + currentFogNear = 0.0f; + searchLightFogRed = 0.0f; + searchLightFogGreen = 0.0f; + searchLightFogBlue = 0.0f; + searchLightFogNear = 0.0f; + searchLightFogFar = 0.0f; + noSearchLightFogRed = 0.0f; + noSearchLightFogGreen = 0.0f; + noSearchLightFogBlue = 0.0f; + noSearchLightFogNear = 0.0f; + noSearchLightFogFar = 0.0f; + clipNear = 0.0f; + clipFar = 0.0f; + backgroundRed = 0.0f; + backgroundGreen = 0.0f; + backgroundBlue = 0.0f; + viewAngle = 30.0f; + dplMainView = NULL; + dplDeathZone = NULL; + dplMainZone = NULL; + vehicleReticle = NULL; + dplHitInstance = NULL; + dplHitDCS = NULL; + dplHitGeoGroup = NULL; + dplHitGeometry = NULL; + delayedDCSCount = 0; + myUniqueID = 0; + sceneLightDCS = NULL; + sceneLight = NULL; + sceneLightCount = 0; + + worldToEyeMatrix = LinearMatrix::Identity; // the current world to eye transform for our linked entity + currentFrameTime = Now(); // the time at the start of renderable execution + + Verify(!DPLHeap); +// DPLHeap = new UserHeap("DPL Heap", 2000000); + Register_Object(DPLHeap); + + // + // Clear the myPSFXDescriptons array to all zeros so we can detect attempts + // to use uninitialized items. + // + memset(myPSFXDescriptons, 0, sizeof(myPSFXDescriptons)); + + // + // These guys will come out of a world environment variable eventually + // + eye_x = 0.0f; + eye_y = 10.0f; + eye_z = 0.0f; + eye_x_rot = 0.0f; + eye_y_rot = 0.0f; + eye_z_rot = 0.0f; +// +// Get pointers to environmentals containing DPL startup arguments and +// eye positioning information. If L4EYES is present set the renderer +// variable that controls the hooking up of the eye position. +// + Eye_Type[0] = 0; + DPL_Arg = getenv("DPLARG"); + Eye_Arg = getenv("L4EYES"); + if(Eye_Arg) + { + sscanf( + Eye_Arg, + "%f %f %f %f %f %f %s", + &eye_x, + &eye_y, + &eye_z, + &eye_x_rot, + &eye_y_rot, + &eye_z_rot, + Eye_Type); + + printf("%f, %f, %f %f, %f, %f\n", + eye_x, + eye_y, + eye_z, + eye_x_rot, + eye_y_rot, + eye_z_rot); + + Disconnected_Eye = True; // tells vidrend:: to request outside view of linked entity + if(*Eye_Type == 'r') + { + DEBUG_STREAM<<"DPLRenderer::DPLRenderer Eye will be offset relative to vehicle\n" << std::flush; + eyeRelative = True; + } + } +// +// If the argument was empty, we can't render !!! should exit sensiblly +// + if(!DPL_Arg) + { + DEBUG_STREAM << "DPLARG must be set for the Division card to come up\n" << std::flush; + Verify(DPL_Arg); + } +// +// If we're still here, try to interpret and setup the screen resolution +// requested by DPLARG. The screen_resolution function is Phil's routine +// in startdpl. +// +// if (screen_resolution ( DPL_Arg ) == 0) +// { +// DEBUG_STREAM << "DPLARG is bad, I couldn't understand video format\n" << std::flush; +// Verify(DPL_Arg); +// } +// +// Breakdown the DPLARGS string using expload_args from startdpl, then feed +// the results to the dpl_Init routine to get DPL up and running. +// + char *argv[32]; +// int argc = explode_args ( argv, DPL_Arg, dpl_arg_sep ); +// dpl_Init ( argc, argv ); + // + // Setup the file paths for geometry and texture loading + // +// dpl_SetObjectFilePath ( ".\\video", "\\video", "..\\video" ); +// dpl_SetTexmapFilePath ( ".\\video", "\\video", "..\\video" ); +// dpl_SetMaterialFilePath ( ".\\video", "\\video", "..\\video" ); +// dpl_SetObjectFilePath ( ".\\video", "", "" ); +// std::cout<= PASS_TOTAL_COUNT) + return; + + for (d3d_OBJECT *iter = mRenderLists[pass]; iter; iter = iter->GetNext(pass)) + if ((void*)iter == (void*)object) + return; + + object->SetPrevious(NULL, pass); + object->SetNext(mRenderLists[pass], pass); + + if (mRenderLists[pass] != NULL) + mRenderLists[pass]->SetPrevious(object, pass); + + mRenderLists[pass] = object; +} + +hyper DPLRenderer::HashAdd(hyper input, char data) +{ + const hyper multiplier = 37; + return (input * multiplier) + data; +} + +hyper DPLRenderer::HashDrawOp(L4DRAWOP *op) +{ + char diffR = (char)(op->material.Diffuse.r * 255); + char diffG = (char)(op->material.Diffuse.g * 255); + char diffB = (char)(op->material.Diffuse.b * 255); + char diffA = (char)(op->material.Diffuse.a * 255); + + char ambA = (char)(op->material.Ambient.a * 255); + char ambR = (char)(op->material.Ambient.r * 255); + char ambG = (char)(op->material.Ambient.g * 255); + char ambB = (char)(op->material.Ambient.b * 255); + + char spcA = (char)(op->material.Specular.a * 255); + char spcR = (char)(op->material.Specular.r * 255); + char spcG = (char)(op->material.Specular.g * 255); + char spcB = (char)(op->material.Specular.b * 255); + char spcP = (char)(op->material.Power * 255); + + char emiA = (char)(op->material.Emissive.a * 255); + char emiR = (char)(op->material.Emissive.r * 255); + char emiG = (char)(op->material.Emissive.g * 255); + char emiB = (char)(op->material.Emissive.b * 255); + + const hyper startValue = 37; + hyper hash = startValue; + + hash = HashAdd(hash, diffA); + hash = HashAdd(hash, diffR); + hash = HashAdd(hash, diffG); + hash = HashAdd(hash, diffB); + hash = HashAdd(hash, ambA); + hash = HashAdd(hash, ambR); + hash = HashAdd(hash, ambG); + hash = HashAdd(hash, ambB); + hash = HashAdd(hash, spcA); + hash = HashAdd(hash, spcR); + hash = HashAdd(hash, spcG); + hash = HashAdd(hash, spcB); + hash = HashAdd(hash, spcP); + hash = HashAdd(hash, emiA); + hash = HashAdd(hash, emiR); + hash = HashAdd(hash, emiG); + hash = HashAdd(hash, emiB); + hash = HashAdd(hash, (char)op->drawAsDecal); + hash = HashAdd(hash, (char)op->alphaTest); + hash = HashAdd(hash, (char)op->drawAsSky); + + char *pointerPointer = (char*)(&(op->texture.texture)); + + for (int i = 0; i < 4; i++) + { + hash = HashAdd(hash, pointerPointer[i]); + } + + return hash; +} + +void DPLRenderer::AddStaticObject(d3d_OBJECT *object) +{ + object->SetPrevious(NULL, -1); + object->SetNext(mStaticObjectsHead, -1); + + if (mStaticObjectsHead != NULL) + mStaticObjectsHead->SetPrevious(object, -1); + + mStaticObjectsHead = object; + mStaticObjectsCount++; +} + +void DPLRenderer::RecurseStaticObject(HierarchicalDrawComponent *obj) +{ + if (obj->IsStatic()) + { + if (obj->GetDrawObj() != NULL && obj->GetDrawObj()->GetMesh() != NULL) + { + //Only load it for a static object if it has a valid mesh- + //we'll handle valid sphere lists later + this->AddStaticObject(obj->GetDrawObj()); + obj->ResetDrawObj(); + } + + std::vector::const_iterator child_it = obj->Enumerate(); + + while (child_it != obj->End()) + { + RecurseStaticObject(*child_it); + ++child_it; + } + } +} + +d3d_OBJECT * DPLRenderer::ConsolidateSingleObject(LPD3DXMESH *meshes, D3DXMATRIX *transforms, UINT startingMesh, UINT meshCount, hash_map subsetHash, hash_map hashToOp, vector finalOps) +{ + HRESULT hr; + LPD3DXMESH outMesh; + + V( D3DXConcatenateMeshes(meshes + startingMesh, meshCount, D3DXMESH_MANAGED, transforms + startingMesh, NULL, NULL, mDevice, &outMesh) ); + + DWORD *adjacency = new DWORD[outMesh->GetNumFaces() * 3]; + V( outMesh->GenerateAdjacency(0.05f, adjacency) ); + + DWORD *attributes; + int numFaces = outMesh->GetNumFaces(); + V( outMesh->LockAttributeBuffer(0, &attributes) ); + for (int i = 0; i < numFaces; i++) + { + stdext::hash_map::const_iterator face_it = subsetHash.find(attributes[i]); + + if (face_it == subsetHash.end()) + { + //Freak out + + } + + stdext::hash_map::const_iterator subset_it = hashToOp.find((*face_it).second); + + if (subset_it == hashToOp.end()) + { + //Freak out + } + + attributes[i] = (*subset_it).second; + } + V( outMesh->UnlockAttributeBuffer() ); + + V( outMesh->OptimizeInplace(D3DXMESHOPT_COMPACT | D3DXMESHOPT_ATTRSORT, adjacency, adjacency, NULL, NULL) ); + + d3d_OBJECT *consolObj = new d3d_OBJECT(mDevice, outMesh, adjacency, finalOps.size()); + + for (int drawOpInd = 0; drawOpInd < consolObj->GetDrawOpCount(); drawOpInd++) + { + L4DRAWOP *op = consolObj->GetDrawOp(drawOpInd); + L4DRAWOP *source = finalOps[drawOpInd]; + + op->material = source->material; + op->texture = source->texture; + op->drawAsDecal = source->drawAsDecal; + op->alphaTest = source->alphaTest; + op->drawAsSky = source->drawAsSky; + + if (op->texture.texture != NULL) + { + op->texture.texture->AddRef(); + } + } + + delete [] adjacency; + + return consolObj; +} + +void DPLRenderer::ConsolidateStaticObjects() +{ + HRESULT hr; + + HierarchicalDrawComponent *drawComp; + SChainIteratorOf iterator(&mRenderables); + while ((drawComp = iterator.ReadAndNext()) != NULL) + { + if (drawComp->IsStatic()) + { + drawComp->Execute(); + this->RecurseStaticObject(drawComp); + } + } + + LPD3DXMESH *meshes = new LPD3DXMESH[mStaticObjectsCount]; + D3DXMATRIX *transforms = new D3DXMATRIX[mStaticObjectsCount]; + + int i = 0; + int opCount = 0; + + std::vector finalOps; + stdext::hash_map hashToOp; + stdext::hash_map subsetHash; + + int vertCount = 0; + int startMesh = 0; + int meshCount = 0; + + for (d3d_OBJECT *obj = mStaticObjectsHead; obj; obj = obj->GetNext(-1), i++) + { + if (vertCount + obj->GetMesh()->GetNumVertices() > 65535) + { + this->mConsolidatedStaticObjects.push_back(this->ConsolidateSingleObject(meshes, transforms, startMesh, meshCount, subsetHash, hashToOp, finalOps)); + vertCount = 0; + startMesh = meshCount; + meshCount = 0; + opCount = 0; + + //Clear the draw ops lists + finalOps.clear(); + hashToOp.clear(); + subsetHash.clear(); + } + + meshes[i] = obj->GetMesh(); + transforms[i] = obj->GetLocalToWorld(); + + vertCount += meshes[i]->GetNumVertices(); + meshCount++; + + for (int opNum = 0; opNum < obj->GetDrawOpCount(); opNum++) + { + hyper hash = this->HashDrawOp(obj->GetDrawOp(opNum)); + stdext::hash_map::const_iterator hash_it = hashToOp.find(hash); + + if (hash_it == hashToOp.end()) + { + finalOps.insert(finalOps.end(), obj->GetDrawOp(opNum)); + hashToOp.insert(std::pair(hash, (DWORD)(finalOps.size() - 1))); + hash_it = hashToOp.find(hash); + } + + subsetHash.insert(std::pair((DWORD)opCount, hash)); + opCount++; + } + } + + if (meshCount > 0) + { + this->mConsolidatedStaticObjects.push_back(this->ConsolidateSingleObject(meshes, transforms, startMesh, meshCount, subsetHash, hashToOp, finalOps)); + } + + d3d_OBJECT *obj = mStaticObjectsHead; + while (obj != NULL) + { + d3d_OBJECT *next = obj->GetNext(-1); + + delete obj; + obj = next; + } + + mStaticObjectsHead = NULL; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RemoveDynamicRenderable removes a renderable from the dynamic execution +// socket. +// +void + DPLRenderer::RemoveDynamicRenderable(Component *my_renderable) +{ + Check(my_renderable); + Check(&dplRenderableSocket); + PlugIterator remover(my_renderable); + remover.RemoveSocket(&dplRenderableSocket); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void + DPLRenderer::SetFogStyle(FogStyle my_fog) +{ + //STUBBED: DPL RB 1/14/07 + switch(my_fog) + { + case updateFogSetting: + fogUpdating = True; + break; + case noUpdateFogSetting: + fogUpdating = False; + break; + case searchLightOnFogStyle: + fogRed = searchLightFogRed; + fogGreen = searchLightFogGreen; + fogBlue = searchLightFogBlue; + fogNear = searchLightFogNear; + fogFar = searchLightFogFar; + if(fogUpdating) + { + mDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen), (int)(255 * fogBlue))); + // dpl_SetViewFog( + // dplMainView, + // dpl_fog_type_pixel_lin, + // fogRed, + // fogGreen, + // fogBlue, + // fogNear, + // fogFar ); + // dpl_FlushView(dplMainView); + } + break; + case searchLightOffFogStyle: + fogRed = noSearchLightFogRed; + fogGreen = noSearchLightFogGreen; + fogBlue = noSearchLightFogBlue; + fogNear = noSearchLightFogNear; + fogFar = noSearchLightFogFar; + if(fogUpdating) + { + mDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen), (int)(255 * fogBlue))); + // dpl_SetViewFog( + // dplMainView, + // dpl_fog_type_pixel_lin, + // fogRed, + // fogGreen, + // fogBlue, + // fogNear, + // fogFar ); + // dpl_FlushView(dplMainView); + } + break; + case winnersCircleFogStyle: + // + // HACK!! This really shouldn't reset the clip planes, but since + // it only happens at the end of the review, it should be safe for now. + // + // dpl_SetViewClipPlanes ( dplMainView, 0.25f, 1100.0f ); + // dpl_SetViewFog( + // dplMainView, + // dpl_fog_type_pixel_lin, + // 0.32, + // 0.3, + // 0.65, + // 100.0f, + // 1050.0f ); + // dpl_FlushView(dplMainView); + break; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void + DPLRenderer::GetCurrentFogSettings( + float *fog_Red, + float *fog_Green, + float *fog_Blue, + float *fog_Near, + float *fog_Far) +{ + *fog_Red = fogRed; + *fog_Green = fogGreen; + *fog_Blue = fogBlue; + *fog_Near = fogNear; + *fog_Far = fogFar; +} + +void DPLRenderer::SetCurrentFogLimits( + float fog_Near, + float fog_Far) +{ + currentFogNear = fog_Near; + currentFogFar = fog_Far; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// MarkDCSHiearchy This will std::decend a DCS tree and set the appSpecific hook +// in every DCS equal to the entity pointer "entity", it calls itself recursively +// to do this. +// +void + DPLRenderer::MarkDCSHiearchy( + dpl_DCS *root_DCS, // Root of the hiearchy to mark + Entity *entity) // Entity pointer to mark it with +{ + //STUBBED: DPL RB 1/14/07 + //int + // dcs_counter; + //dpl_DCS + // *child_DCS; + //// + //// First, mark this DCS + //// + //if(dpl_GetAppSpecific(root_DCS)) + // Fail("DPLRenderer::MarkDCSHiearchy tried to mark a DCS that was already marked!\n"); + //dpl_PutAppSpecific(root_DCS,entity); + //// + //// Now call this routine on all this dcs's children + //// + //dcs_counter = 0; + //while((child_DCS=dpl_GetDCSChildDCS(root_DCS,dcs_counter)) != NULL) + //{ + // MarkDCSHiearchy(child_DCS, entity); + // dcs_counter++; + //} +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ReadPSFX +// reads a pfx file into a supplied array +// Most of this routine was a direct copy of phil's code and as such is a bit +// on the messy side. +// +dpl_PARTICLESTART_EFFECT_INFO* + DPLRenderer::ReadPSFX( + const char *file_name) // Name of the file containing the PSFX description +{ +//STUBBED: DPL RB 1/14/07 +// FILE +// *fp; +// int +// i, +// status; +// char +// line[256], +// *cp; +// // +// // Open the file containing the psfx, fail if it doesn't exist +// // +// strcpy(line,"video\\"); +// strcat(line,file_name); +// fp = fopen ( line, "rt" ); +// if(!fp) +// { +// DEBUG_STREAM<<"Could not open pfx file "<tex = dpl_LookupTexture ( cp, dpl_lookup_normal, &status ); +// #if PRINT_THE_PFX +// printf ( "texture => %s\n", cp ); +// #endif +// // +// // The remander of these statements get the rest of the PFX data +// // +// cp = fgets ( line, 255, fp ); +// status = sscanf ( cp, +// "%x %d %f %f\n", +// &psfx_info->identifier, &psfx_info->maximum_issue, &psfx_info->release_period, &psfx_info->rate ); +// if(status < 4) +// { +// std::cout<<"pfx file "<px, &psfx_info->py, &psfx_info->pz, &psfx_info->pv ); +// if(status < 4) +// { +// std::cout<<"pfx file "<velx, &psfx_info->vely, &psfx_info->velz, +// &psfx_info->velxv, &psfx_info->velyv, &psfx_info->velzv ); +// if(status < 6) +// { +// std::cout<<"pfx file "<rad, &psfx_info->radv, &psfx_info->exp, &psfx_info->expv, &psfx_info->dexp, &psfx_info->dexpv ); +// if(status < 6) +// { +// std::cout<<"pfx file "<accelx, &psfx_info->accely, &psfx_info->accelz, +// &psfx_info->accelxv, &psfx_info->accelyv, &psfx_info->accelzv ); +// if(status < 6) +// { +// std::cout<<"pfx file "<atten, &psfx_info->attenv ); +// if(status < 2) +// { +// std::cout<<"pfx file "<sRi,&psfx_info->sGi,&psfx_info->sBi,&psfx_info->sAi,&psfx_info->sRiv,&psfx_info->sGiv,&psfx_info->sBiv,&psfx_info->sAiv ); +// if(status < 8) +// { +// std::cout<<"pfx file "<sRo,&psfx_info->sGo,&psfx_info->sBo,&psfx_info->sAo,&psfx_info->sRov,&psfx_info->sGov,&psfx_info->sBov,&psfx_info->sAov ); +// if(status < 8) +// { +// std::cout<<"pfx file "<eRi,&psfx_info->eGi,&psfx_info->eBi,&psfx_info->eAi,&psfx_info->eRiv,&psfx_info->eGiv,&psfx_info->eBiv,&psfx_info->eAiv ); +// if(status < 8) +// { +// std::cout<<"pfx file "<eRo,&psfx_info->eGo,&psfx_info->eBo,&psfx_info->eAo,&psfx_info->eRov,&psfx_info->eGov,&psfx_info->eBov,&psfx_info->eAov ); +// if(status < 8) +// { +// std::cout<<"pfx file "<colour_warp, &psfx_info->alpha_warp ); +// if(status < 2) +// { +// std::cout<<"pfx file "<dur, &psfx_info->durv ); +// if(status < 2) +// { +// std::cout<<"pfx file "<\n" ); +// /*{{{ trace the psfx*/ +// printf ( "psfx_info->tex = 0x%x\n", +// psfx_info->tex ); +// printf ( "identifier = 0x%x ", +// psfx_info->identifier ); +// printf ( "maximum_issue = %d ", +// psfx_info->maximum_issue ); +// printf ( "release_period = %f\n", +// psfx_info->release_period ); +// printf ( "rate = %f ", +// psfx_info->rate ); +// printf ( "px = %f ", +// psfx_info->px ); +// printf ( "py = %f ", +// psfx_info->py ); +// printf ( "pz = %f ", +// psfx_info->pz ); +// printf ( "pv = %f\n", +// psfx_info->pv ); +// printf ( "velx = %f ", +// psfx_info->velx ); +// printf ( "vely = %f ", +// psfx_info->vely ); +// printf ( "velz = %f\n", +// psfx_info->velz ); +// printf ( "velxv = %f ", +// psfx_info->velxv ); +// printf ( "velyv = %f ", +// psfx_info->velyv ); +// printf ( "velzv = %f\n", +// psfx_info->velzv ); +// printf ( "rad = %f ", +// psfx_info->rad ); +// printf ( "radv = %f\n", +// psfx_info->radv ); +// printf ( "exp = %f ", +// psfx_info->exp ); +// printf ( "expv = %f ", +// psfx_info->expv ); +// printf ( "dexp = %f ", +// psfx_info->dexp ); +// printf ( "dexpv = %f\n", +// psfx_info->dexpv ); +// printf ( "accelx = %f ", +// psfx_info->accelx ); +// printf ( "accely = %f ", +// psfx_info->accely ); +// printf ( "accelz = %f ", +// psfx_info->accelz ); +// printf ( "accelxv = %f ", +// psfx_info->accelxv ); +// printf ( "accelyv = %f ", +// psfx_info->accelyv ); +// printf ( "accelzv = %f\n", +// psfx_info->accelzv ); +// printf ( "atten = %f ", +// psfx_info->atten ); +// printf ( "attenv = %f\n", +// psfx_info->attenv ); +// printf ( "sRi = %f ", +// psfx_info->sRi ); +// printf ( "sGi = %f ", +// psfx_info->sGi ); +// printf ( "sBi = %f ", +// psfx_info->sBi ); +// printf ( "sAi = %f\n", +// psfx_info->sAi ); +// printf ( "sRiv = %f ", +// psfx_info->sRiv ); +// printf ( "sGiv = %f ", +// psfx_info->sGiv ); +// printf ( "sBiv = %f ", +// psfx_info->sBiv ); +// printf ( "sAiv = %f\n", +// psfx_info->sAiv ); +// printf ( "sRo = %f ", +// psfx_info->sRo ); +// printf ( "sGo = %f ", +// psfx_info->sGo ); +// printf ( "sBo = %f ", +// psfx_info->sBo ); +// printf ( "sAo = %f\n", +// psfx_info->sAo ); +// printf ( "sRov = %f ", +// psfx_info->sRov ); +// printf ( "sGov = %f ", +// psfx_info->sGov ); +// printf ( "sBov = %f ", +// psfx_info->sBov ); +// printf ( "sAov = %f\n", +// psfx_info->sAov ); +// printf ( "eRi = %f ", +// psfx_info->eRi ); +// printf ( "eGi = %f ", +// psfx_info->eGi ); +// printf ( "eBi = %f ", +// psfx_info->eBi ); +// printf ( "eAi = %f\n", +// psfx_info->eAi ); +// printf ( "eRiv = %f ", +// psfx_info->eRiv ); +// printf ( "eGiv = %f ", +// psfx_info->eGiv ); +// printf ( "eBiv = %f ", +// psfx_info->eBiv ); +// printf ( "eAiv = %f\n", +// psfx_info->eAiv ); +// printf ( "eRo = %f ", +// psfx_info->eRo ); +// printf ( "eGo = %f ", +// psfx_info->eGo ); +// printf ( "eBo = %f ", +// psfx_info->eBo ); +// printf ( "eAo = %f\n", +// psfx_info->eAo ); +// printf ( "eRov = %f ", +// psfx_info->eRov ); +// printf ( "eGov = %f ", +// psfx_info->eGov ); +// printf ( "eBov = %f ", +// psfx_info->eBov ); +// printf ( "eAov = %f\n", +// psfx_info->eAov ); +// printf ( "colour_warp = %f ", +// psfx_info->colour_warp ); +// printf ( "alpha_warp = %f ", +// psfx_info->alpha_warp ); +// printf ( "dur = %f ", +// psfx_info->dur ); +// printf ( "durv = %f\n", +// psfx_info->durv ); +// #endif + return(psfx_info); +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// New INI file handler +// routine to read in an environment from a notation file and setup lights, +// spfx and such... +// +void + DPLRenderer::DPLReadINIPage( + NotationFile *master_notation_file, + const char *starting_page_name, + Mission *mission, + Logical debug_printing) +{ +//STUBBED: DPL RB 1/14/07 + float + red, + green, + blue, + x_rotate, + y_rotate, + z_rotate; + NameList + *cache_namelist, + *light_namelist, + *psfx_namelist, + *specialfx_namelist, + *include_pages, + *path_pages; + NameList::Entry + *entry; + const char + *next_include_page_name, + *TempStringPtr, + *compare_source; + + if (debug_printing) + std::cout<<"DPLReadINIPage processing "<MakeEntryList(starting_page_name, "objectpath")) != NULL) + { + Register_Object(path_pages); + // + // Recursively process all the include pages + // + for( entry = path_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { +// dpl_AddToObjectFilePath((char *)entry->dataReference, dpl_path_user); + if (debug_printing) + { +// DEBUG_STREAM << "objectpath '" << dpl_GetObjectFilePath() << "'" << std::endl << std::flush; + } + } + Unregister_Object(path_pages); + delete path_pages; + } + if ((path_pages = master_notation_file->MakeEntryList(starting_page_name, "texmappath")) != NULL) + { + Register_Object(path_pages); + // + // Recursively process all the include pages + // + for( entry = path_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { +// dpl_AddToTexmapFilePath((char *)entry->dataReference, dpl_path_user); + if (debug_printing) + { +// DEBUG_STREAM << "texmappath '" << dpl_GetTexmapFilePath() << "'" << std::endl << std::flush; + } + } + Unregister_Object(path_pages); + delete path_pages; + } + if ((path_pages = master_notation_file->MakeEntryList(starting_page_name, "materialpath")) != NULL) + { + Register_Object(path_pages); + // + // Recursively process all the include pages + // + for( entry = path_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { +// dpl_AddToMaterialFilePath((char *)entry->dataReference, dpl_path_user); + if (debug_printing) + { +// DEBUG_STREAM << "materialpath '" << dpl_GetMaterialFilePath() << "'" << std::endl << std::flush; + } + } + Unregister_Object(path_pages); + delete path_pages; + } + + if (master_notation_file->GetEntry(starting_page_name, "priorityobjectpath", &TempStringPtr)) + { +// dpl_AddToObjectFilePath((char *)TempStringPtr, dpl_path_system); + if (debug_printing) + { DEBUG_STREAM << "priorityobjectpath '" << TempStringPtr << "'" << std::endl << std::flush; } + } + if (master_notation_file->GetEntry(starting_page_name, "prioritytexmappath", &TempStringPtr)) + { +// dpl_AddToTexmapFilePath((char *)TempStringPtr, dpl_path_system); + if (debug_printing) + { DEBUG_STREAM << "prioritytexmappath '" << TempStringPtr << "'" << std::endl << std::flush; } + } + if (master_notation_file->GetEntry(starting_page_name, "prioritymaterialpath", &TempStringPtr)) + { +// dpl_AddToMaterialFilePath((char *)TempStringPtr, dpl_path_system); + if (debug_printing) + { DEBUG_STREAM << "prioritymaterialpath '" << TempStringPtr << "'" << std::endl << std::flush; } + } + // + // Get a the list of dpl objects that should be loaded into cache and load them + // + if ((cache_namelist = master_notation_file->MakeEntryList(starting_page_name, "cache")) != NULL) + { + d3d_OBJECT *d3d_a_object; + Register_Object(cache_namelist); + for(entry = cache_namelist->GetFirstEntry(); entry; entry = entry->GetNextEntry()) + { + d3d_a_object = d3d_OBJECT::LoadObject(mDevice, (char *)entry->dataReference); + if(!d3d_a_object) + DEBUG_STREAM<<"Unable to cache "<<(char *)entry->dataReference<<"\n" << std::flush; + else + { + if(debug_printing) + std::cout<<"Caching "<<(char *)entry->dataReference<<"\n"; + } + } + Unregister_Object(cache_namelist); + delete cache_namelist; + } + // + // Get the clip range + // + if(master_notation_file->GetEntry(starting_page_name, "clip" ,&TempStringPtr)) + { + sscanf(TempStringPtr, "%f %f", &clipNear, &clipFar); + if(debug_printing) + std::cout<<"Clip Range "<GetEntry(starting_page_name, "backgnd" ,&TempStringPtr)) + { + sscanf(TempStringPtr, "%f %f %f", &backgroundRed, &backgroundGreen, &backgroundBlue); + if(debug_printing) + std::cout<<"Background Color "<GetEntry(starting_page_name, "viewangle" ,&TempStringPtr)) + { + sscanf(TempStringPtr, "%f", &viewAngle); + if(debug_printing) + std::cout<<"View Angle "<GetEntry(starting_page_name, "fog" ,&TempStringPtr)) + { + sscanf(TempStringPtr, "%f %f %f %f %f", &fogNear, &fogFar, &fogRed, &fogGreen, &fogBlue); + searchLightFogRed = fogRed; + searchLightFogGreen = fogGreen; + searchLightFogBlue = fogBlue; + searchLightFogNear = fogNear; + searchLightFogFar = fogFar; + noSearchLightFogRed = fogRed; + noSearchLightFogGreen = fogGreen; + noSearchLightFogBlue = fogBlue; + noSearchLightFogNear = fogNear; + noSearchLightFogFar = fogFar; + currentFogNear = fogNear; + currentFogFar = fogFar; + // Force a 0-0 black fog on startup +// dpl_SetViewFog(dplMainView, dpl_fog_type_pixel_lin, 0.0, 0.0, 0.0, 0.01, 0.05); + //TODO: for fog testing, just set the values here + mDevice->SetRenderState(D3DRS_FOGENABLE, TRUE); + mDevice->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen), (int)(255 * fogBlue))); + mDevice->SetRenderState(D3DRS_FOGTABLEMODE, D3DFOG_LINEAR); + + if(debug_printing) + std::cout<<"Fog "<GetEntry(starting_page_name, "nosearchlightfog" ,&TempStringPtr)) + { + sscanf(TempStringPtr, "%f %f %f %f %f", &noSearchLightFogNear, &noSearchLightFogFar, &noSearchLightFogRed, &noSearchLightFogGreen, &noSearchLightFogBlue); + if(debug_printing) + std::cout<<"nosearchlightfog "<GetEntry(starting_page_name, "ambient" ,&TempStringPtr)) + { + sscanf(TempStringPtr, "%f %f %f ", &red, &green, &blue); + mDevice->SetRenderState(D3DRS_AMBIENT, D3DCOLOR_XRGB((int)(255 * red), (int)(255 * green), (int)(255 * blue))); + if(debug_printing) + std::cout<<"Ambient Light "<GetEntry(starting_page_name, "clouds", &TempStringPtr)) + { + sscanf(TempStringPtr, "%f %f %f ", &this->mCloudRed, &this->mCloudGreen, &this->mCloudBlue); + } + + if (master_notation_file->GetEntry(starting_page_name, "cloudemit", &TempStringPtr)) + { + sscanf(TempStringPtr, "%f %f %f ", &this->mCloudEmitRed, &this->mCloudEmitGreen, &this->mCloudEmitBlue); + } + + // + // Get a the list of lights from this page + // + if ((light_namelist = master_notation_file->MakeEntryList(starting_page_name, "light")) != NULL) + { + Register_Object(light_namelist); + // + // HACK !!! All the lights must (temporarily) be defined on a single page. + // The lights and their DCS's should really be stored in a light object on + // a chain, or as an actual entity in the simulation. This line will throw + // an exception if this rule is violated + // + if(light_namelist->EntryCount() != 0) + { + if(sceneLightCount != 0) + { + Fail("All lights must be defined on a single INI file page!\n"); + } + // + // Create storage space for the dpl_LIGHT and dpl_DCS structures + // + sceneLightCount = light_namelist->EntryCount(); + if (sceneLightCount) + { + sceneLight = new D3DLIGHT9[sceneLightCount]; + memset(sceneLight, 0, sizeof(D3DLIGHT9) * sceneLightCount); + } + + int current_entry = 0; + for(entry = light_namelist->GetFirstEntry(); entry; entry = entry->GetNextEntry(), ++current_entry) + { + // + // Read the parameters for the light + // + sscanf( + (char *)entry->dataReference, + "%f %f %f %f %f %f", + &red, + &green, + &blue, + &x_rotate, + &y_rotate, + &z_rotate); + if(debug_printing) + std::cout<<"Light "<<(char *)entry->dataReference<<"\n"; + // + // Create and rotate a dcs to hold the light, and the light itself + // + sceneLight[current_entry].Type = D3DLIGHT_DIRECTIONAL; + sceneLight[current_entry].Diffuse.r = red; + sceneLight[current_entry].Diffuse.g = green; + sceneLight[current_entry].Diffuse.b = blue; + sceneLight[current_entry].Diffuse.a = 1.0f; + + D3DXMATRIX rot, rotX, rotY, rotZ; + D3DXMatrixRotationX(&rotX, x_rotate * (PI/180.0f)); + D3DXMatrixRotationY(&rotY, y_rotate * (PI/180.0f)); + D3DXMatrixRotationZ(&rotZ, z_rotate * (PI/180.0f)); + rot = rotZ * rotX * rotY; + + D3DXVECTOR3 dir(0, 0, -1); + D3DXVECTOR4 vec; + D3DXVec3Transform(&vec, &dir, &rot); + dir = D3DXVECTOR3(vec.x, vec.y, vec.z); + D3DXVec3Normalize(&dir, &dir); + sceneLight[current_entry].Direction.x = dir.x; + sceneLight[current_entry].Direction.y = dir.y; + sceneLight[current_entry].Direction.z = dir.z; + + mDevice->SetLight(current_entry, &sceneLight[current_entry]); + mDevice->LightEnable(current_entry, TRUE); + +// sceneLight[current_entry] = dpl_NewLight(); +// sceneLightDCS[current_entry] = dpl_NewDCS(); + +// dpl_AddDCSToScene ( sceneLightDCS[current_entry] ); +// dpl_SetLightType ( sceneLight[current_entry], dpl_light_type_directional ); +// dpl_SetLightColor ( sceneLight[current_entry], red, green, blue); +// dpl_SetLightDCS ( sceneLight[current_entry], sceneLightDCS[current_entry] ); +// dpl_RotateDCS ( sceneLightDCS[current_entry], z_rotate, dpl_Z ); +// dpl_RotateDCS ( sceneLightDCS[current_entry], x_rotate, dpl_X ); +// dpl_RotateDCS ( sceneLightDCS[current_entry], y_rotate, dpl_Y ); +// dpl_FlushLight ( sceneLight[current_entry] ); +// dpl_FlushDCS ( sceneLightDCS[current_entry] ); + } + } + // + // Get rid of the light entry list + // + Unregister_Object(light_namelist); + delete light_namelist; + } + //// + //// Get a the list of PSFX effects we should load into RAM + //// + //if ((psfx_namelist = master_notation_file->MakeEntryList(starting_page_name, "psfx")) != NULL) + //{ + // const char *psfx_file_name; + // int psfx_number; + // // + // // create all the PSFX on the current page + // // + // for( entry = psfx_namelist->GetFirstEntry(); + // entry; + // entry = entry->GetNextEntry()) + // { + // psfx_number = atoi(entry->GetName()+4); + // psfx_file_name = entry->GetChar(); + // if(debug_printing) + // std::cout<<"psfx"< MAX_PSFX_COUNT-1) + // { + // Fail("PSFX id number was not in the allowed range"); + // } + // // + // // See if we are overwriting an existing psfx + // // + // if(myPSFXDescriptons[psfx_number]) + // { + // std::cout<<"psfx#"<MakeEntryList(starting_page_name, "effect")) != NULL) + { + const char *effect_page_name; + int status, spfx_number, version; + INDIE_EFFECT spfx; + memset(&spfx, 0, sizeof(PARTICLE_EFFECT)); + + Register_Object(specialfx_namelist); + // + // create all the effects on the current page + // + for( entry = specialfx_namelist->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + // + // Get the page with this effect on it + // + effect_page_name = entry->GetChar(); + if(debug_printing) + std::cout<<"specialfx"<GetEntry(effect_page_name, "id", &spfx_number); + + version = 1; + master_notation_file->GetEntry(effect_page_name, "version", &version); + if (version < 2) + continue; + + master_notation_file->GetEntry(effect_page_name, "texbounds", &TempStringPtr); + sscanf(TempStringPtr, "%f %f %f %f", &spfx.textureBounds.left, &spfx.textureBounds.top, &spfx.textureBounds.right, &spfx.textureBounds.bottom); + + master_notation_file->GetEntry(effect_page_name, "rotate", (int*)&spfx.rotate); + master_notation_file->GetEntry(effect_page_name, "size", &spfx.fragSize); + master_notation_file->GetEntry(effect_page_name, "velocity", &spfx.velocity); + master_notation_file->GetEntry(effect_page_name, "varianceX", &spfx.varianceX); + master_notation_file->GetEntry(effect_page_name, "varianceY", &spfx.varianceY); + master_notation_file->GetEntry(effect_page_name, "varianceZ", &spfx.varianceZ); + master_notation_file->GetEntry(effect_page_name, "gravity", &spfx.gravity); + master_notation_file->GetEntry(effect_page_name, "count", &spfx.fragCount); + master_notation_file->GetEntry(effect_page_name, "life", &spfx.fragLifetime); + if (!master_notation_file->GetEntry(effect_page_name, "max_repeat", &spfx.maxRepeat)) + spfx.maxRepeat = 30.0; + NameList *color_list = master_notation_file->MakeEntryList(effect_page_name, "color"); + int i = 0; + for (NameList::Entry *color_entry = color_list->GetFirstEntry(); color_entry; color_entry = color_entry->GetNextEntry()) + { + memset(&spfx.colors[i], 0, sizeof(COLOR_POINT)); + spfx.colors[i].active = true; + + int a, r, g, b; + sscanf(color_entry->GetChar(), "%f %d %d %d %d", &spfx.colors[i].time, &a, &r, &g, &b); + + spfx.colors[i].color.argb = D3DCOLOR_ARGB(a, r, g, b); + i++; + } + + for (;i < COLOR_POINT_COUNT; i++) + { + memset(&spfx.colors[i], 0, sizeof(COLOR_POINT)); + } + + // + // install the effect + // + int isIndie = 0; + master_notation_file->GetEntry(effect_page_name, "independent", &isIndie); + if (isIndie) + { + master_notation_file->GetEntry(effect_page_name, "maxIssue", &spfx.maxIssue); + master_notation_file->GetEntry(effect_page_name, "releasePeriod", &spfx.releasePeriod); + master_notation_file->GetEntry(effect_page_name, "duration", &spfx.duration); + + spfx.id = 1000 + spfx_number; + myPSFXDescriptons[spfx_number] = spfx; + } + else + ParticleEngine::InstallEffect(spfx_number, *((PARTICLE_EFFECT*)&spfx)); + } + // + // Get rid of the effect entry list + // + Unregister_Object(specialfx_namelist); + delete specialfx_namelist; + } + //-------------------------------------------------- + // Make a list of all the include pages on this page + //-------------------------------------------------- + if ((include_pages = master_notation_file->MakeEntryList(starting_page_name, "include")) != NULL) + { + Register_Object(include_pages); + // + // Recursively process all the include pages + // + for( entry = include_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + // Get the name of the next include page + next_include_page_name = (char *)entry->dataReference; + // Process the next page recursively through this routine + DPLReadINIPage( + master_notation_file, + next_include_page_name, + mission, + debug_printing); + if(debug_printing) + std::cout<<"DPLReadINIPage returned to "<GetEntry(starting_page_name, "compare" ,&compare_source)) + { + Logical + match; + NameList + *branch_pages; + CString + compare_strings[10], + wild_card("*"), + token_string, + target_string, + master_compare_string(compare_source); + int + token_count; + ResourceFile + *this_resource_file; + // + // Get a pointer to our resource file so we can find the name of the map + // resource later in this process. + // + Check(application); + this_resource_file = application->GetResourceFile(); + Check(this_resource_file); + // + // Print the compare string + // + if(debug_printing) + std::cout<<"compare = "<FindResourceDescription(mission->GetMapID()))->resourceName; +// std::cout<GetMissionTime(); +// std::cout<GetMissionWeather(); +// std::cout<GetScenarioName(); +// std::cout<MakeEntryList(starting_page_name,"branch"); + Register_Object(branch_pages); + for( entry = branch_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + CString + branch_command, + match_string; + int + compare_token; + // + // Get the text of the branch command and print it + // + branch_command = (char *)entry->dataReference; + if(debug_printing) + std::cout<<"branch = "<GetFileName() << + "' NO MATCH FOUND!!" << std::endl; + } + } +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Read environment +// routine to read in an environment from a notation file and setup lights, +// spfx and such... +// +void + DPLRenderer::DPLReadEnvironment(Mission *mission) +{ +//STUBBED: DPL RB 1/14/07 + char *L4DPLcfg; +// const char +// *cc; + + NotationFile *renderer_environment; + + Logical debug_printing; + // + // Get the name of the notation file from an environmental + // + L4DPLcfg = getenv("L4DPLCFG"); + if (!L4DPLcfg) + { + DEBUG_STREAM<<"L4DPLCFG not defined, using dpldflt.ini!\n" << std::flush; + L4DPLcfg = "dpldflt.ini"; + } + // + // Read the environment out of a notation file + // + renderer_environment = new NotationFile(L4DPLcfg); + Register_Object(renderer_environment); + if (renderer_environment->PageCount() == 0) + { + DEBUG_STREAM<<"Renderer config notation file "<PageCount() == 0); + } + // + // Register the notation file and check it + // + Check(renderer_environment); + if (renderer_environment->PageExists("main")) + { + if (!(renderer_environment->GetLogicalEntry("main", "debug", &debug_printing))) + { + debug_printing=False; + } + DPLReadINIPage(renderer_environment, "main", mission, debug_printing); +#if 0 + if ((cc = dpl_GetObjectFilePath()) == NULL || *cc == NULL) + { + dpl_SetObjectFilePath ( ".\\video", NULL, NULL ); + } + if ((cc = dpl_GetTexmapFilePath()) == NULL || *cc == NULL) + { + dpl_SetTexmapFilePath ( ".\\video", NULL, NULL ); + } + if ((cc = dpl_GetMaterialFilePath()) == NULL || *cc == NULL) + { + dpl_SetMaterialFilePath ( ".\\video", NULL, NULL ); + } +#endif + } + else + { + if (!(renderer_environment->GetLogicalEntry("dpl_config", "debug", &debug_printing))) + { + debug_printing=False; + } + std::cout<<"READING OLD FORMAT INI FILE '"<GetFileName()<<"'---hope this works\n"; +// dpl_SetObjectFilePath ( ".\\video", NULL, NULL ); +// dpl_SetTexmapFilePath ( ".\\video", NULL, NULL ); +// dpl_SetMaterialFilePath ( ".\\video", NULL, NULL ); + DPLReadINIPage(renderer_environment, "dpl_config", mission, debug_printing); + } + if (debug_printing) + { +// DEBUG_STREAM << "ObjectFilePath '" << dpl_GetObjectFilePath() << "'" << std::endl << std::flush; +// DEBUG_STREAM << "TexmapFilePath '" << dpl_GetTexmapFilePath() << "'" << std::endl << std::flush; +// DEBUG_STREAM << "MaterialFilePath '" << dpl_GetMaterialFilePath() << "'" << std::endl << std::flush; + } + // + // Close the notation file + // + Verify( !renderer_environment->IsDirty() ); + Unregister_Object(renderer_environment); + delete renderer_environment; + // + // Flush all the things we've set/changed here + // +// dpl_FlushView(dplMainView); + return; +} +// +//############################################################################# +// Destructor for the video renderer +//############################################################################# +// +DPLRenderer::~DPLRenderer() +{ + delete gOpNames; + delete gReplacementData; + + if (mPrimaryIndex != NULL) + { + delete mPrimaryIndex; + } + + if (mSecondaryIndex != NULL) + { + delete mSecondaryIndex; + } + + if (mAux1Index != NULL) + { + delete mAux1Index; + } + + if (mAux2Index != NULL) + { + delete mAux2Index; + } + + SAFE_RELEASE(mDevice); + SAFE_RELEASE(gD3D); + //STUBBED: DPL RB 1/14/07 + //int + // psfx_number; + ////------------------------------------------------------ + //// release allocated memory used by dump_frame_buffer() + ////------------------------------------------------------ + //dump_frame_buffer(NULL, NULL, NULL, NULL); + //// + //// Delete any memory allocated to hold psfx effect descriptions + //// + //for( psfx_number = 0; psfx_number < MAX_PSFX_COUNT; psfx_number++) + //{ + // if(myPSFXDescriptons[psfx_number]) + // { + // delete myPSFXDescriptons[psfx_number]; + // Unregister_Pointer(myPSFXDescriptons[psfx_number]); + // myPSFXDescriptons[psfx_number] = NULL; + // } + //} + //// + ////~~~~~~~~~~~~~~~~~~ + //// Delete all Lights + ////~~~~~~~~~~~~~~~~~~ + //// + //if (ambientLight) + //{ + // Check_Pointer(ambientLight); + // Unregister_Pointer(ambientLight); + // dpl_DeleteLight(ambientLight); + //} + //if (sceneLightDCS && sceneLight) + //{ + // Check_Pointer(sceneLightDCS); + // for(int ii=0;iiLockRect(0, &lockedRect, NULL, D3DLOCK_DISCARD); + + // + // Figure out the position to start copying the data at + // + Word *word_pointer = bitmap_to_load->Data.MapPointer; + __int16 *pixel_pointer = (__int16*)lockedRect.pBits; + + // + // Actually process the texels + // + int bit_mask = 0x8000; + for(int y = 0; y < 32; y++) + { + for(int x = 0; x < 128; x++) + { + if (*word_pointer & bit_mask) + *(pixel_pointer++) = 0xFFFF; + else + *(pixel_pointer++) = 0x0000; + bit_mask >>= 1; + if (bit_mask == 0) + { + bit_mask = 0x8000; + word_pointer++; + } + } + } + + // unlock the texture now that we're done updating it + local_storage->UnlockRect(0); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CacheExplosionScripts +// Handles code to preload the morph and other caches with things needed by +// explosion scripts. Should be called at startup, once for each. +// +void + DPLRenderer::CacheExplosionScripts( + int script_select) // The script to be cached +{ +//STUBBED: DPL RB 1/14/07 +// dpl_OBJECT +// *object; +// // +// // Load the morph targets into the MUNGA object cache +// // +// switch(script_select) +// { +// case 104: // Thor death explosion +// case 106: // Thor death explosion +// { +// dpl_LoadObject("flamebig.bgf", dpl_load_normal); +// dpl_LoadObject("thrdbr.bgf" , dpl_load_normal); +// dpl_LoadObject("ldbr.bgf" , dpl_load_normal); +// dpl_LoadObject("flamesml.bgf", dpl_load_normal); +//// DEBUG_STREAM << "explosion "<< script_select<<" cached\n" << std::flush; +// break; +// } +// } +} +// +//############################################################################# +// ExplosionScripts +// Contains several scripts for running various types of explosion effects. +//############################################################################# +// +void + DPLRenderer::ExplosionScripts( + Entity *entity, // The entity we are dealing with + ResourceDescription* ,//model_resource, // Pointer to the video resource + ViewFrom ,//view_type, // Type of reference (inside/outside...etc.) + int script_select) +{ +//STUBBED: DPL RB 1/14/07 +// dpl_OBJECT +// *object_1; +// // +// // Construct a root renderable to hang the explosion effects on +// // +// RootRenderable *this_root = +// new RootRenderable( +// entity, // Entity to attach the renderable to +// RootRenderable::Dynamic, // How/when to execute the renderable +// NULL, // object to hang on the DCS, may be a list later +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL); // intersection mask for the object +// Register_Object(this_root); +// // +// // Select which script to construct +// // +// switch(script_select) +// { +// case 0: // Shock wave +// { +// // +// // Load object(s) we will be using for the explosions +// // +// object_1 = dpl_LoadObject("shock.bgf", dpl_load_normal); +// // +// // Setup control variables and transforms we need +// // +// Vector3D scaling_velocity_1(3.5, 3.5, 3.5); +// Vector3D velocity_accel_1(0.0, 0.0, 0.0); +// LinearMatrix explosion_1_offset(True); +// // +// // Create the scaling explosion renderables +// // +// ScalingExplosionRenderable *explosion_1 = +// new ScalingExplosionRenderable( +// entity, // Entity to attach the renderable to +// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable +// object_1, // This will be the scaling explosion object +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS(), // the parent DCS we will be offsetting from +// &explosion_1_offset, // offset matrix to be applied prior to joint DCS +// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity +// &velocity_accel_1, +// 0.0f, +// NULL); // -.25 gravity is normal +// Register_Object(explosion_1); +// // +// // Create a sweep renderable to drive the material morph +// // +// SweepRenderable *sweep_1 = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 0.5f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// NULL); +// Register_Object(sweep_1); +// // +// // Lookup a texture that we can use for the morphing materials +// // +// int +// status; +// dpl_TEXTURE *effect_texture = +// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); +// if (effect_texture == NULL) +// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush; +// // +// // Setup a morph material renderable for each explosion shape +// // +// MorphMaterialRenderable *morph_material_1 = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 1.0f,1.0f,1.0f, // Material's ambient component +// 1.0f,1.0f,1.0f, // Material's emissive component +// 1.0f,1.0f,1.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 4.0f,0.2f,-0.05f, // Material's opacity +// effect_texture, // Material's texture pointer +// 0.0f, // Material's Z dither value +// 0, // Material's Fog Imunity value +// 0.5f,0.5f,0.5f, // Material's ambient component +// 0.5f,0.5f,0.5f, // Material's emissive component +// 0.5f,0.5f,0.5f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +//// 0.25f,0.25f,-0.05f, // Material's opacity +// 0.1f,0.1f,-0.05f, // Material's opacity +// 0.0f, // Material's Z dither value +// sweep_1->GetSweepAttribute()); +// Register_Object(morph_material_1); +// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); +// if(!explosion_1_instance) +// Fail("explosion_1_instance came back null\n"); +// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); +// dpl_FlushInstance(explosion_1_instance); +// break; +// } +// case 1: // Big explosion +// { +// // +// // Load object(s) we will be using for the explosions +// // +// object_1 = dpl_LoadObject("exp.bgf", dpl_load_normal); +// // +// // Setup control variables and transforms we need +// // +// Vector3D scaling_velocity_1(0.15, 0.15, 0.15); +// Vector3D scaling_velocity_2(0.18, 0.22, 0.18); +// Vector3D velocity_accel_1(0.0, 0.0, 0.0); +// Vector3D velocity_accel_2(0.0, 0.0, 0.0); +// LinearMatrix explosion_1_offset(True); +// LinearMatrix explosion_2_offset(True); +// Point3D explosion_2_translate(0.0f, 0.0f, 0.0f); +// EulerAngles explosion_2_rotate(0.0f, 1.0f, 0.0f); +// explosion_2_offset = explosion_2_rotate; +// explosion_2_offset = explosion_2_translate; +// // +// // Create the scaling explosion renderables +// // +// ScalingExplosionRenderable *explosion_1 = +// new ScalingExplosionRenderable( +// entity, // Entity to attach the renderable to +// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable +// object_1, // This will be the scaling explosion object +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS(), // the parent DCS we will be offsetting from +// &explosion_1_offset, // offset matrix to be applied prior to joint DCS +// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity +// &velocity_accel_1, +// 0.0f, +// NULL); // -.25 gravity is normal +// Register_Object(explosion_1); +// ScalingExplosionRenderable *explosion_2 = +// new ScalingExplosionRenderable( +// entity, // Entity to attach the renderable to +// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable +// object_1, // This will be the scaling explosion object +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS(), // the parent DCS we will be offsetting from +// &explosion_2_offset, // offset matrix to be applied prior to joint DCS +// &scaling_velocity_2, // Effect control vector, Y is acceleration, X, Z are velocity +// &velocity_accel_2, +// 0.0f, +// NULL); +// Register_Object(explosion_2); +// // +// // Create a sweep renderable to drive the material morph +// // +// SweepRenderable *sweep_1 = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 3.0f, +// 1, // number of times to cycle before stopping +// NULL); // How long to take to sweep from 0 to 1 +// Register_Object(sweep_1); +// SweepRenderable *sweep_2 = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 2.0f, +// 1, // number of times to cycle before stopping +// NULL); // How long to take to sweep from 0 to 1 +// Register_Object(sweep_2); +// // +// // Lookup a texture that we can use for the morphing materials +// // +// int +// status; +// dpl_TEXTURE *effect_texture = +// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); +// if (effect_texture == NULL) +// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush; +// // +// // Setup a morph material renderable for each explosion shape +// // +// #if 0 +// 0.9f,0.0f,0.0f, // Material's ambient component +// 1.0f,1.0f,0.0f, // Material's emissive component +// 1.0f,0.7f,0.2f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 8.0f,0.2f,-0.05f, // Material's opacity +// #endif +// MorphMaterialRenderable *morph_material_1 = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 0.9f,0.0f,0.0f, // Material's ambient component +// 1.0f,0.2f,0.0f, // Material's emissive component +// 1.0f,0.2f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 10.0f,0.6f,-0.05f, // Material's opacity +// effect_texture, // Material's texture pointer +// 0.0f, // Material's Z dither value +// 0, // Material's Fog Imunity value +// 0.3f,0.0f,0.0f, // Material's ambient component +// 0.5f,0.0f,0.0f, // Material's emissive component +// 0.2f,0.0f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 0.25f,0.25f,-0.05f, // Material's opacity +// 15.0f, // Material's Z dither value +// sweep_1->GetSweepAttribute()); +// Register_Object(morph_material_1); +// MorphMaterialRenderable *morph_material_2 = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 0.9f,0.0f,0.0f, // Material's ambient component +// 1.0f,0.6f,0.3f, // Material's emissive component +// 1.0f,0.4f,0.2f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 8.0f,0.2f,-0.05f, // Material's opacity +// effect_texture, // Material's texture pointer +// 0.0f, // Material's Z dither value +// 0, // Material's Fog Imunity value +// 0.1f,0.0f,0.0f, // Material's ambient component +// 0.0f,0.0f,0.0f, // Material's emissive component +// 0.1f,0.0f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 0.25f,0.25f,-0.05f, // Material's opacity +// 15.0f, // Material's Z dither value +// sweep_2->GetSweepAttribute()); +// Register_Object(morph_material_2); +// // +// // Override the materials in the two explosion shapes using these morph materials +// // +// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); +// dpl_INSTANCE *explosion_2_instance = dpl_GetDCSInstance(explosion_2->GetDCS(), 1); +// +// if(!explosion_1_instance) +// Fail("explosion_1_instance came back null\n"); +// if(!explosion_2_instance) +// Fail("explosion_2_instance came back null\n"); +// +// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); +// dpl_SetInstanceFrontMaterial(explosion_2_instance, morph_material_2->GetMaterial()); +// +// dpl_FlushInstance(explosion_1_instance); +// dpl_FlushInstance(explosion_2_instance); +// break; +// } +// case 2: // Big explosion +// { +// // +// // Load object(s) we will be using for the explosions +// // +// object_1 = dpl_LoadObject("exp.bgf", dpl_load_normal); +// // +// // Setup control variables and transforms we need +// // +// Vector3D scaling_velocity_1(1.0, 0.2, 1.0); +// Vector3D scaling_velocity_2(0.75, 0.75, 0.75); +// Vector3D velocity_accel_1(-0.00725, -0.004, -0.00725); +//// Vector3D velocity_accel_1(-0.00925, -0.00925, -0.00925); +// Vector3D velocity_accel_2(-0.01388, -0.01388, -0.01388); +// LinearMatrix explosion_1_offset(True); +// LinearMatrix explosion_2_offset(True); +// Point3D explosion_2_translate(0.0f, 0.0f, 0.0f); +// EulerAngles explosion_2_rotate(0.0f, 1.0f, 0.0f); +// explosion_2_offset = explosion_2_rotate; +// explosion_2_offset = explosion_2_translate; +// // +// // Create the scaling explosion renderables +// // +// ScalingExplosionRenderable *explosion_1 = +// new ScalingExplosionRenderable( +// entity, // Entity to attach the renderable to +// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable +// object_1, // This will be the scaling explosion object +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS(), // the parent DCS we will be offsetting from +// &explosion_1_offset, // offset matrix to be applied prior to joint DCS +// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity +// &velocity_accel_1, +// 0.0f, +// NULL); // -.25 gravity is normal +// Register_Object(explosion_1); +// ScalingExplosionRenderable *explosion_2 = +// new ScalingExplosionRenderable( +// entity, // Entity to attach the renderable to +// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable +// object_1, // This will be the scaling explosion object +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS(), // the parent DCS we will be offsetting from +// &explosion_2_offset, // offset matrix to be applied prior to joint DCS +// &scaling_velocity_2, // Effect control vector, Y is acceleration, X, Z are velocity +// &velocity_accel_2, +// 0.0f, +// NULL); +// Register_Object(explosion_2); +// // +// // Create a sweep renderable to drive the material morph +// // +// SweepRenderable *sweep_1 = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 3.0f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// NULL); +// Register_Object(sweep_1); +// SweepRenderable *sweep_2 = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 2.0f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// NULL); +// Register_Object(sweep_2); +// // +// // Lookup a texture that we can use for the morphing materials +// // +// int +// status; +// dpl_TEXTURE *effect_texture = +// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); +// if (effect_texture == NULL) +// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush; +// // +// // Setup a morph material renderable for each explosion shape +// // +// #if 0 +// 0.9f,0.0f,0.0f, // Material's ambient component +// 1.0f,1.0f,0.0f, // Material's emissive component +// 1.0f,0.7f,0.2f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 8.0f,0.2f,-0.05f, // Material's opacity +// #endif +// MorphMaterialRenderable *morph_material_1 = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 0.9f,0.0f,0.0f, // Material's ambient component +// 1.0f,0.2f,0.0f, // Material's emissive component +// 1.0f,0.2f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 8.0f,0.2f,-0.05f, // Material's opacity +// effect_texture, // Material's texture pointer +// 0.0f, // Material's Z dither value +// 0, // Material's Fog Imunity value +// 0.3f,0.0f,0.0f, // Material's ambient component +// 0.5f,0.0f,0.0f, // Material's emissive component +// 0.2f,0.0f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 0.25f,0.25f,-0.05f, // Material's opacity +// 15.0f, // Material's Z dither value +// sweep_1->GetSweepAttribute()); +// Register_Object(morph_material_1); +// MorphMaterialRenderable *morph_material_2 = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 0.9f,0.0f,0.0f, // Material's ambient component +// 1.0f,0.6f,0.4f, // Material's emissive component +// 1.0f,0.3f,0.2f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 8.0f,0.2f,-0.05f, // Material's opacity +// effect_texture, // Material's texture pointer +// 0.0f, // Material's Z dither value +// 0, // Material's Fog Imunity value +// 0.1f,0.0f,0.0f, // Material's ambient component +// 0.0f,0.0f,0.0f, // Material's emissive component +// 0.0f,0.0f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 0.25f,0.25f,-0.05f, // Material's opacity +// 15.0f, // Material's Z dither value +// sweep_2->GetSweepAttribute()); +// Register_Object(morph_material_2); +// // +// // Override the materials in the two explosion shapes using these morph materials +// // +// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); +// dpl_INSTANCE *explosion_2_instance = dpl_GetDCSInstance(explosion_2->GetDCS(), 1); +// +// if(!explosion_1_instance) +// Fail("explosion_1_instance came back null\n"); +// if(!explosion_2_instance) +// Fail("explosion_2_instance came back null\n"); +// +// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); +// dpl_SetInstanceFrontMaterial(explosion_2_instance, morph_material_2->GetMaterial()); +// +// dpl_FlushInstance(explosion_1_instance); +// dpl_FlushInstance(explosion_2_instance); +// break; +// } +// case 3: // Sparks +// { +// // +// // Load object(s) we will be using for the explosions +// // +// object_1 = dpl_LoadObject("spk1.bgf", dpl_load_normal); +// // +// // Setup control variables and transforms we need +// // +// Vector3D scaling_velocity_1(0.1, 0.1, 0.1); +// Vector3D velocity_accel_1(0.0, 0.0, 0.0); +// LinearMatrix explosion_1_offset(True); +// // +// // Create the scaling explosion renderables +// // +// ScalingExplosionRenderable *explosion_1 = +// new ScalingExplosionRenderable( +// entity, // Entity to attach the renderable to +// ScalingExplosionRenderable::Dynamic, // How/when to execute the renderable +// object_1, // This will be the scaling explosion object +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS(), // the parent DCS we will be offsetting from +// &explosion_1_offset, // offset matrix to be applied prior to joint DCS +// &scaling_velocity_1, // Effect control vector, Y is acceleration, X, Z are velocity +// &velocity_accel_1, +// -0.15f, +// NULL); // -.25 gravity is normal +// Register_Object(explosion_1); +// // +// // Create a sweep renderable to drive the material morph +// // +// SweepRenderable *sweep_1 = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 0.5f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// NULL); +// Register_Object(sweep_1); +// // +// // Lookup a texture that we can use for the morphing materials +// // +// int +// status; +// dpl_TEXTURE *effect_texture = +// dpl_LookupTexture ( "btfx:firesmoke1_scr_tex", dpl_lookup_normal, &status ); +// if (effect_texture == NULL) +// DEBUG_STREAM<<"couldn't find texture btfx:firesmoke1_scr_tex for an effect\n" << std::flush; +// // +// // Setup a morph material renderable for each explosion shape +// // +// MorphMaterialRenderable *morph_material_1 = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 1.0f,1.0f,0.0f, // Material's ambient component +// 1.0f,1.0f,0.0f, // Material's emissive component +// 1.0f,1.0f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 1.0f,1.0f,1.0f, // Material's opacity +// effect_texture, // Material's texture pointer +// 0.0f, // Material's Z dither value +// 2, // Material's Fog Imunity value +// 0.9f,0.0f,0.0f, // Material's ambient component +// 0.9f,0.0f,0.0f, // Material's emissive component +// 0.9f,0.0f,0.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0, // Material's specular component +// 1.0f,1.0f,1.0f, // Material's opacity +// 0.0f, // Material's Z dither value +// sweep_1->GetSweepAttribute()); +// Register_Object(morph_material_1); +// dpl_INSTANCE *explosion_1_instance = dpl_GetDCSInstance(explosion_1->GetDCS(), 1); +// if(!explosion_1_instance) +// Fail("explosion_1_instance came back null\n"); +// dpl_SetInstanceFrontMaterial(explosion_1_instance, morph_material_1->GetMaterial()); +// dpl_FlushInstance(explosion_1_instance); +// break; +// } +// case 4: // A huge mech explodes (yawn) +// { +// Point3D null_offset(0.0f, 0.0f, 0.0f); +// LinearMatrix null_offset_matrix(True); +// Point3D local_height(0.0f, 6.2f, 0.0f); // height of Thor +// LinearMatrix local_offset(True); +// local_offset = local_height; +// DPLStaticChildRenderable *local_root = +// new DPLStaticChildRenderable( +// entity, +// false, +// NULL, +// dpl_isect_mode_obj, +// NULL, +// local_offset, +// this_root->GetDCS()); +// Register_Object(local_root); +// // +// // Load morph sources we need for the effect +// // +// dpl_OBJECT *thor_debris_object = dpl_LoadObject("thrdbr.bgf", dpl_load_normal); +// dpl_OBJECT *large_debris_object = dpl_LoadObject("ldbr.bgf", dpl_load_normal); +// dpl_OBJECT *small_flames_object = dpl_LoadObject("flamesml.bgf", dpl_load_normal); +// // +// // Load morph targets we need for the effect +// // +// //------------------------------------------------ +// // Renderables to handle the chunks and fireballs +// //------------------------------------------------ +//#if 0 +// OneShotDelayRenderable *fireball_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.25f); // How long to wait before raising the trigger +// Register_Object(fireball_delay); +// Point3D my_offset(0.0, 4.0, 0.0); +// #if DEBUG_LEVEL > 0 +// DPLPSFXRenderable* initial_boom = +// #endif +// new DPLPSFXRenderable( +// entity, // Entity to attach the renderable to +// DPLPSFXRenderable::Dynamic, // How/when to execute the renderable +// fireball_delay->GetTriggerAttribute(), // address containing the trigger +// myPSFXDescriptons[7], // pointer to the PFX description +// this_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &my_offset); // Offset (or world coordinants if DCS is NULL) +// Register_Object(initial_boom); +// #if DEBUG_LEVEL > 0 +// DPLEffectRenderable *chunks_effect = +// #endif +// new DPLEffectRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// fireball_delay->GetTriggerAttribute(), // address containing the trigger +// 3, // Chunks // DPL effect number to trigger +// local_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &null_offset); // Offset (or world coordinants if DCS is NULL) +// Register_Object(chunks_effect); +// Point3D fireball_offset(1.0f, 5.0f, 1.0f); +// #if DEBUG_LEVEL > 0 +// DPLEffectRenderable *fireball_effect = +// #endif +// new DPLEffectRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// fireball_delay->GetTriggerAttribute(), // address containing the trigger +// 15, // Fireball // DPL effect number to trigger +// local_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &fireball_offset); // Offset (or world coordinants if DCS is NULL) +// Register_Object(fireball_effect); +//#endif +// OneShotDelayRenderable *fireball_delay_2 = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.55f); // How long to wait before raising the trigger +// Register_Object(fireball_delay_2); +// Point3D fireball_offset_2(-1.0f, 5.0f, -1.0f); +// #if DEBUG_LEVEL > 0 +// DPLEffectRenderable *fireball_effect_2 = +// #endif +// new DPLEffectRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// fireball_delay_2->GetTriggerAttribute(), // address containing the trigger +// 15, // Fireball // DPL effect number to trigger +// local_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &fireball_offset_2); // Offset (or world coordinants if DCS is NULL) +// Register_Object(fireball_effect_2); +// //----------------------------------------------- +// // Renderables to handle static debris +// //----------------------------------------------- +// OneShotDelayRenderable *static_debris_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.25f); // How long to wait before raising the trigger +// Register_Object(static_debris_delay); +// DPLStaticChildRenderable *mech_debris = +// new DPLStaticChildRenderable( +// entity, +// false, +// thor_debris_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// this_root->GetDCS()); +// Register_Object(mech_debris); +// #if DEBUG_LEVEL > 0 +// MakeDCSFall *mech_debris_fall = +// #endif +// new MakeDCSFall( +// entity, // Entity to attach the renderable to +// MakeDCSFall::Dynamic, // How/when to execute the renderable +// mech_debris->GetDCS(), // the DCS to control +// -0.025f, // Gravity in meters/sec squared +// static_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off +// Register_Object(mech_debris_fall); +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *mech_debris_instance = dpl_GetDCSInstance(mech_debris->GetDCS(), 1); +// #if DEBUG_LEVEL > 0 +// InstanceSwitchRenderable *mech_debris_instance_switch = +// #endif +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// mech_debris_instance, // the instance to control +// True, // Instance is on when trigger is... +// static_debris_delay->GetTriggerAttribute()); +// Register_Object(mech_debris_instance_switch); +// +// DPLStaticChildRenderable *large_debris = +// new DPLStaticChildRenderable( +// entity, +// false, +// large_debris_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// mech_debris->GetDCS()); +// Register_Object(large_debris); +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *large_debris_instance = dpl_GetDCSInstance(large_debris->GetDCS(), 1); +// #if DEBUG_LEVEL > 0 +// InstanceSwitchRenderable *large_debris_instance_switch = +// #endif +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// large_debris_instance, // the instance to control +// True, // Instance is on when trigger is... +// static_debris_delay->GetTriggerAttribute()); +// Register_Object(large_debris_instance_switch); +// //----------------------------------------------- +// // Renderables to handle fires +// //----------------------------------------------- +// OneShotDelayRenderable *fires_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.25f); // How long to wait before raising the trigger +// Register_Object(fires_delay); +// DPLStaticChildRenderable *fires = +// new DPLStaticChildRenderable( +// entity, +// false, +// NULL, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// this_root->GetDCS()); +// Register_Object(fires); +// #if DEBUG_LEVEL > 0 +// MakeDCSFall *fires_fall = +// #endif +// new MakeDCSFall( +// entity, // Entity to attach the renderable to +// MakeDCSFall::Dynamic, // How/when to execute the renderable +// fires->GetDCS(), // the DCS to control +// -0.01f, // Gravity in meters/sec squared +// fires_delay->GetTriggerAttribute()); // true if the instance is on, false if off +// Register_Object(fires_fall); +// DPLStaticChildRenderable *small_flames = +// new DPLStaticChildRenderable( +// entity, +// false, +// small_flames_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// fires->GetDCS()); +// Register_Object(small_flames); +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *small_flames_instance = dpl_GetDCSInstance(small_flames->GetDCS(), 1); +// #if DEBUG_LEVEL > 0 +// InstanceSwitchRenderable *small_flames_instance_switch = +// #endif +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// small_flames_instance, // the instance to control +// True, // Instance is on when trigger is... +// fires_delay->GetTriggerAttribute()); +// Register_Object(small_flames_instance_switch); +// +// dpl_OBJECT *big_flames_object = dpl_LoadObject("flamebig.bgf", dpl_load_normal); +// DPLStaticChildRenderable *big_flames = +// new DPLStaticChildRenderable( +// entity, +// false, +// big_flames_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// fires->GetDCS()); +// Register_Object(big_flames); +// // Make big flames object billboard along y-axis +// dpl_SetDCSReorientAxes(big_flames->GetDCS(), dpl_reorient_axes_y); +// dpl_FlushDCS(big_flames->GetDCS()); +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *big_flames_instance = dpl_GetDCSInstance(big_flames->GetDCS(), 1); +// #if DEBUG_LEVEL > 0 +// InstanceSwitchRenderable *big_flames_instance_switch = +// #endif +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// big_flames_instance, // the instance to control +// True, // Instance is on when trigger is... +// fires_delay->GetTriggerAttribute()); +// Register_Object(big_flames_instance_switch); +// // +// // These renderables create the rising smoke column using a pfx effect. +// // +//#if 0 +// Point3D my_offset2(0.0, 5.0, 0.0); +// #if DEBUG_LEVEL > 0 +// OnePSFXRenderable *this_effect= +// #endif +// new OnePSFXRenderable( +// entity, // Entity to attach the renderable to +// OnePSFXRenderable::Static, // How/when to execute the renderable +// myPSFXDescriptons[1], // name of file with the PFX description in it +// this_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &my_offset2); // Offset (or world coordinants if DCS is NULL) +// Register_Object(this_effect); +//#endif +// break; +// } +// //---------------------------------------- +// case 5: // Sfx #105 - Delayed ground hit +// //---------------------------------------- +// { +// // +// // Create the delayed ground hit renderables +// // +// Point3D null_offset(0.0f, 0.0f, 0.0f); +// OneShotDelayRenderable *ground_hit_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.15f); // How long to wait before raising the trigger +// Register_Object(ground_hit_delay); +// #if DEBUG_LEVEL > 0 +// DPLEffectRenderable *ground_hit_effect = +// #endif +// new DPLEffectRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// ground_hit_delay->GetTriggerAttribute(), // address containing the trigger +// 12, // GroundHit // DPL effect number to trigger +// this_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &null_offset); // Offset (or world coordinants if DCS is NULL) +// Register_Object(ground_hit_effect); +// break; +// } +// //------------------------------------------ +// case 6: // Sfx #106 - Thor death explosion +// //------------------------------------------ +// { +// #if 0 +// int status; // used with dpl calls +// Point3D null_offset(0.0f, 0.0f, 0.0f); +// LinearMatrix null_offset_matrix(True); +// Point3D local_height(0.0f, 6.2f, 0.0f); // height of Thor +// LinearMatrix local_offset(True); +// local_offset = local_height; +// DPLStaticChildRenderable *local_root = +// new DPLStaticChildRenderable( +// entity, +// false, +// NULL, +// dpl_isect_mode_obj, +// NULL, +// local_offset, +// this_root->GetDCS()); +// Register_Object(local_root); +//#if 0 +// //vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// // +// // Show static thor (TEMPORARY for testing) +// // +// dpl_OBJECT *static_thr_object = dpl_LoadObject("thr.bgf", dpl_load_normal); +// DPLStaticChildRenderable *static_thr = +// new DPLStaticChildRenderable( +// entity, +// false, +// static_thr_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// local_root->GetDCS()); +// Register_Object(static_thr); +// // This defines how long the static_thr stays visible +// OneShotDelayRenderable *static_thr_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.5f); // How long to wait before raising the trigger +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *static_thr_instance = dpl_GetDCSInstance(static_thr->GetDCS(), 1); +// InstanceSwitchRenderable *static_thr_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// static_thr_instance, // the instance to control +// False, // Instance is on when trigger is... +// static_thr_delay->GetTriggerAttribute()); +// // +// //^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//#endif +// // +// // Load objects we will be using for the explosion effect +// // +// DPLObjectWrapper *flash_object_wrapper = +// new DPLObjectWrapper( +// entity, // Entity to attach the renderable to +// "exdisk_A.bgf", // Name of the DPL object to load into the wrapper +// dpl_load_nocache); // Type of loading to perform on this object +// Register_Object(flash_object_wrapper); +// dpl_OBJECT *flash_object_a = flash_object_wrapper->GetDPLObject(); +// dpl_OBJECT *flash_object_b = dpl_LoadObject("exdisk_B.bgf", dpl_load_normal); +// dpl_OBJECT *flash_object_c = dpl_LoadObject("exdisk_C.bgf", dpl_load_normal); +// DPLObjectWrapper *debris_object_wrapper = +// new DPLObjectWrapper( +// entity, // Entity to attach the renderable to +// "thrtor_A.bgf", // Name of the DPL object to load into the wrapper +// dpl_load_nocache); // Type of loading to perform on this object +// Register_Object(debris_object_wrapper); +// dpl_OBJECT *morph_debris_a = debris_object_wrapper->GetDPLObject(); +// dpl_OBJECT *morph_debris_b = dpl_LoadObject("thrtor_B.bgf", dpl_load_normal); +// dpl_OBJECT *morph_debris_c = dpl_LoadObject("thrtor_C.bgf", dpl_load_normal); +// DPLObjectWrapper *hips_object_wrapper = +// new DPLObjectWrapper( +// entity, // Entity to attach the renderable to +// "thrhip_A.bgf", // Name of the DPL object to load into the wrapper +// dpl_load_nocache); // Type of loading to perform on this object +// Register_Object(hips_object_wrapper); +// dpl_OBJECT *morph_hips_a = hips_object_wrapper->GetDPLObject(); +// dpl_OBJECT *morph_hips_b = dpl_LoadObject("thrhip_B.bgf", dpl_load_normal); +// dpl_OBJECT *morph_hips_c = dpl_LoadObject("thrhip_C.bgf", dpl_load_normal); +// dpl_OBJECT *thor_debris_object = dpl_LoadObject("thrdbr.bgf", dpl_load_normal); +// dpl_OBJECT *large_debris_object = dpl_LoadObject("ldbr.bgf", dpl_load_normal); +// dpl_OBJECT *small_flames_object = dpl_LoadObject("flamesml.bgf", dpl_load_normal); +// dpl_OBJECT *big_flames_object = dpl_LoadObject("flamebig.bgf", dpl_load_normal); +// //---------------------------------------------- +// // Renderables to perform morphing flash object +// //---------------------------------------------- +// SweepRenderable *flash_morph_sweep = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 1.0f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// NULL, // trigger +// -0.5f, // Initial value +// 2.0f); // Final value +// ChildMorphRenderable *flash_morph = +// new ChildMorphRenderable( +// entity, // Entity to attach the renderable to +// ChildMorphRenderable::Dynamic, // How/when to execute the renderable +// flash_object_a, // destination +// flash_object_b, // start object +// flash_object_c, // end object +// flash_morph_sweep->GetSweepAttribute(), // pointer to control variable +// dpl_morph_vertices | dpl_morph_colors, // Defines type of morph to do +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS()); // the parent DCS we will be offsetting from +// // Make flash object billboard along y-axis +// dpl_SetDCSReorientAxes(flash_morph->GetDCS(), dpl_reorient_axes_y); +// dpl_FlushDCS(flash_morph->GetDCS()); +// // This defines how long the flash stays up +// OneShotDelayRenderable *flash_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 1.0f); // How long to wait before raising the trigger +// Register_Object(flash_delay); +// // Find the instance with the flash in it and hook up the instance switch +// dpl_INSTANCE *flash_morph_instance = dpl_GetDCSInstance(flash_morph->GetDCS(), 1); +// InstanceSwitchRenderable *flash_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// flash_morph_instance, // the instance to control +// False, // Instance is on when trigger is... +// flash_delay->GetTriggerAttribute()); +// //--------------------------------------------------- +// // Create a material morph to fade flash object away +// //--------------------------------------------------- +// OneShotDelayRenderable *flash_fade_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.5f); // How long to wait before raising the trigger +// SweepRenderable *flash_fade_sweep = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 0.4f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// flash_fade_delay->GetTriggerAttribute()); // trigger variable +// Register_Object(flash_fade_sweep); +// // Lookup texture for smoke column +// dpl_TEXTURE *flash_texture = +// dpl_LookupTexture("btfx:bexp9_tex", dpl_lookup_normal, &status); +// if (flash_texture == NULL) +// DEBUG_STREAM<<"couldn't find texture btfx:bexp9_tex for an effect\n" << std::flush; +// // +// MorphMaterialRenderable *flash_fade_material = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 1.0f,1.0f,1.0f, // Material's ambient component +// 1.0f,1.0f,1.0f, // Material's emissive component +// 1.0f,1.0f,1.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0f, // Material's specular component +// 1.0f,1.0f,1.0f, // Material's opacity +// flash_texture, // Material's texture pointer +// 0.0f, // Material's Z dither value +// 1, // Material's Fog Imunity value +// 1.0f,1.0f,1.0f, // Material's ambient component +// 1.0f,1.0f,1.0f, // Material's emissive component +// 1.0f,1.0f,1.0f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0f, // Material's specular component +// 0.0f,0.0f,0.0f, // Material's opacity +// 0.0f, // Material's Z dither value +// flash_fade_sweep->GetSweepAttribute()); +// Register_Object(flash_fade_material); +//// dpl_INSTANCE *flash_morph_instance = dpl_GetDCSInstance(flash_morph->GetDCS(), 1); +// if (!flash_morph_instance) +// Fail("flash_morph_instance came back null\n"); +// dpl_SetInstanceFrontMaterial(flash_morph_instance, flash_fade_material->GetMaterial()); +// dpl_FlushInstance(flash_morph_instance); +// //------------------------------------------------ +// // Renderables to handle the chunks and fireballs +// //------------------------------------------------ +// OneShotDelayRenderable *fireball_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.25f); // How long to wait before raising the trigger +// Register_Object(fireball_delay); +// DPLEffectRenderable *chunks_effect = +// new DPLEffectRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// fireball_delay->GetTriggerAttribute(), // address containing the trigger +// 3, // Chunks // DPL effect number to trigger +// local_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &null_offset); // Offset (or world coordinants if DCS is NULL) +// Register_Object(chunks_effect); +// Point3D fireball_offset(1.0f, 5.0f, 1.0f); +// DPLEffectRenderable *fireball_effect = +// new DPLEffectRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// fireball_delay->GetTriggerAttribute(), // address containing the trigger +// 15, // Fireball // DPL effect number to trigger +// local_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &fireball_offset); // Offset (or world coordinants if DCS is NULL) +// Register_Object(fireball_effect); +// OneShotDelayRenderable *fireball_delay_2 = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.55f); // How long to wait before raising the trigger +// Register_Object(fireball_delay_2); +// Point3D fireball_offset_2(-1.0f, 5.0f, -1.0f); +// DPLEffectRenderable *fireball_effect_2 = +// new DPLEffectRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// fireball_delay_2->GetTriggerAttribute(), // address containing the trigger +// 15, // Fireball // DPL effect number to trigger +// local_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &fireball_offset_2); // Offset (or world coordinants if DCS is NULL) +// Register_Object(fireball_effect_2); +// //------------------------------------------------------ +// // Renderables to handle the torso debris explode morph +// //------------------------------------------------------ +// OneShotDelayRenderable *morph_debris_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.25f, // How long to wait before raising the trigger +// 4.25f); // Duration of trigger +// SweepRenderable *debris_morph_sweep = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 4.0f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// morph_debris_delay->GetTriggerAttribute(), // trigger variable +// 0.0f, // initial value of sweep +// 9.0f, // final value of sweep +// SweepRenderable::Y_SQR_X); // function to apply +// ChildMorphRenderable *debris_morph = +// new ChildMorphRenderable( +// entity, // Entity to attach the renderable to +// ChildMorphRenderable::Dynamic, // How/when to execute the renderable +// morph_debris_a, // destination +// morph_debris_b, // start object +// morph_debris_c, // end object +// debris_morph_sweep->GetSweepAttribute(), // pointer to control variable +// dpl_morph_vertices, // Defines type of morph to do +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// local_root->GetDCS()); // the parent DCS we will be offsetting from +// MakeDCSFall *debris_make_fall = +// new MakeDCSFall( +// entity, // Entity to attach the renderable to +// MakeDCSFall::Dynamic, // How/when to execute the renderable +// debris_morph->GetDCS(), // the DCS to control +// -9.81f, // Gravity in meters/sec squared +// morph_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off +// // Find the instance with the debris in it and hook up the instance switch +// dpl_INSTANCE *debris_morph_instance = dpl_GetDCSInstance(debris_morph->GetDCS(), 1); +// InstanceSwitchRenderable *debris_morph_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// debris_morph_instance, // the instance to control +// True, // Instance is on when trigger is... +// morph_debris_delay->GetTriggerAttribute()); +// //----------------------------------------------------- +// // Renderables to handle the hips debris explode morph +// //----------------------------------------------------- +// ChildMorphRenderable *hips_morph = +// new ChildMorphRenderable( +// entity, // Entity to attach the renderable to +// ChildMorphRenderable::Dynamic, // How/when to execute the renderable +// morph_hips_a, // destination +// morph_hips_b, // start object +// morph_hips_c, // end object +// debris_morph_sweep->GetSweepAttribute(), // pointer to control variable +// dpl_morph_vertices, // Defines type of morph to do +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// local_root->GetDCS()); // the parent DCS we will be offsetting from +// MakeDCSFall *hips_make_fall = +// new MakeDCSFall( +// entity, // Entity to attach the renderable to +// MakeDCSFall::Dynamic, // How/when to execute the renderable +// hips_morph->GetDCS(), // the DCS to control +// -9.81f, // Gravity in meters/sec squared +// morph_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off +// // Find the instance with the debris in it and hook up the instance switch +// dpl_INSTANCE *hips_morph_instance = dpl_GetDCSInstance(hips_morph->GetDCS(), 1); +// InstanceSwitchRenderable *hips_morph_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// hips_morph_instance, // the instance to control +// True, // Instance is on when trigger is... +// morph_debris_delay->GetTriggerAttribute()); +// //----------------------------------------------- +// // Renderables to handle static debris and fires +// //----------------------------------------------- +// OneShotDelayRenderable *static_debris_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.25f); // How long to wait before raising the trigger +// DPLStaticChildRenderable *mech_debris = +// new DPLStaticChildRenderable( +// entity, +// false, +// thor_debris_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// this_root->GetDCS()); +// Register_Object(mech_debris); +// MakeDCSFall *mech_debris_fall = +// new MakeDCSFall( +// entity, // Entity to attach the renderable to +// MakeDCSFall::Dynamic, // How/when to execute the renderable +// mech_debris->GetDCS(), // the DCS to control +// -0.01f, // Gravity in meters/sec squared +// static_debris_delay->GetTriggerAttribute()); // true if the instance is on, false if off +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *mech_debris_instance = dpl_GetDCSInstance(mech_debris->GetDCS(), 1); +// InstanceSwitchRenderable *mech_debris_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// mech_debris_instance, // the instance to control +// True, // Instance is on when trigger is... +// static_debris_delay->GetTriggerAttribute()); +// +// DPLStaticChildRenderable *large_debris = +// new DPLStaticChildRenderable( +// entity, +// false, +// large_debris_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// mech_debris->GetDCS()); +// Register_Object(large_debris); +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *large_debris_instance = dpl_GetDCSInstance(large_debris->GetDCS(), 1); +// InstanceSwitchRenderable *large_debris_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// large_debris_instance, // the instance to control +// True, // Instance is on when trigger is... +// static_debris_delay->GetTriggerAttribute()); +// +// DPLStaticChildRenderable *small_flames = +// new DPLStaticChildRenderable( +// entity, +// false, +// small_flames_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// mech_debris->GetDCS()); +// Register_Object(small_flames); +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *small_flames_instance = dpl_GetDCSInstance(small_flames->GetDCS(), 1); +// InstanceSwitchRenderable *small_flames_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// small_flames_instance, // the instance to control +// True, // Instance is on when trigger is... +// static_debris_delay->GetTriggerAttribute()); +// +// DPLStaticChildRenderable *big_flames = +// new DPLStaticChildRenderable( +// entity, +// false, +// big_flames_object, +// dpl_isect_mode_obj, +// NULL, +// null_offset_matrix, +// mech_debris->GetDCS()); +// Register_Object(big_flames); +// // Make big flames object billboard along y-axis +// dpl_SetDCSReorientAxes(big_flames->GetDCS(), dpl_reorient_axes_y); +// dpl_FlushDCS(big_flames->GetDCS()); +// // Find the instance with the static_thr in it and hook up the instance switch +// dpl_INSTANCE *big_flames_instance = dpl_GetDCSInstance(big_flames->GetDCS(), 1); +// InstanceSwitchRenderable *big_flames_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// big_flames_instance, // the instance to control +// True, // Instance is on when trigger is... +// static_debris_delay->GetTriggerAttribute()); +// //------------------------------------------------------------- +// // Renderables to handle the rising smoke column (first shape) +// //------------------------------------------------------------- +//#if 1 +// OneShotDelayRenderable *first_one_shot = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 0.0f); // How long to wait before raising the trigger +// Register_Object(first_one_shot); +// Point3D my_offset(0.0, 6.0, 0.0); +// #if DEBUG_LEVEL > 0 +// DPLPSFXRenderable* this_effect = +// #endif +// new DPLPSFXRenderable( +// entity, // Entity to attach the renderable to +// DPLPSFXRenderable::Dynamic, // How/when to execute the renderable +// first_one_shot->GetTriggerAttribute(), // address containing the trigger +// myPSFXDescriptons[1], // pointer to the PFX description +// this_root->GetDCS(), // DCS the effect is relative to (may be NULL) +// &my_offset); // Offset (or world coordinants if DCS is NULL) +// Register_Object(this_effect); +// +//// the below code will be removed in favor of PFX effects once they are tested +//#else +//// OneShotDelayRenderable *smoke_1_morph_delay = +//// new OneShotDelayRenderable( +//// entity, // Entity to attach the renderable to +//// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +//// 0.25f); // How long to wait before raising the trigger +// SweepRenderable *smoke_1_sweep = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 40.0f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// static_debris_delay->GetTriggerAttribute(), +// 0.2f, +// 2.5f); +// ChildMorphRenderable *smoke_1_morph = +// new ChildMorphRenderable( +// entity, // Entity to attach the renderable to +// ChildMorphRenderable::Dynamic, // How/when to execute the renderable +// smoke_1_a, // destination +// smoke_b, // start object +// smoke_c, // end object +// smoke_1_sweep->GetSweepAttribute(), // pointer to control variable +// dpl_morph_vertices, // Defines type of morph to do +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS()); // the parent DCS we will be offsetting from +// // Find the instance with the flash in it and hook up the instance switch +// dpl_INSTANCE *smoke_1_instance = dpl_GetDCSInstance(smoke_1_morph->GetDCS(), 1); +// InstanceSwitchRenderable *smoke_1_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// smoke_1_instance, // the instance to control +// True, // Instance is on when trigger is... +// static_debris_delay->GetTriggerAttribute()); +// //-------------------------------------------------------------- +// // Renderables to handle the rising smoke column (second shape) +// //-------------------------------------------------------------- +//#if 0 +// OneShotDelayRenderable *smoke_2_morph_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 6.0f); // How long to wait before raising the trigger +// SweepRenderable *smoke_2_sweep = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 30.0f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// smoke_2_morph_delay->GetTriggerAttribute(), +// 0.1f, +// 1.0f); +// ChildMorphRenderable *smoke_2_morph = +// new ChildMorphRenderable( +// entity, // Entity to attach the renderable to +// ChildMorphRenderable::Dynamic, // How/when to execute the renderable +// smoke_2_a, // destination +// smoke_b, // start object +// smoke_c, // end object +// smoke_2_sweep->GetSweepAttribute(), // pointer to control variable +// dpl_morph_vertices, // Defines type of morph to do +// false, // DPL Zone this stuff will live in (for culling) +// dpl_isect_mode_obj, // type of intersections to do on this object +// NULL, // intersection mask for the object +// this_root->GetDCS()); // the parent DCS we will be offsetting from +// // Find the instance with the flash in it and hook up the instance switch +// dpl_INSTANCE *smoke_2_instance = dpl_GetDCSInstance(smoke_2_morph->GetDCS(), 1); +// InstanceSwitchRenderable *smoke_2_morph_instance_switch = +// new InstanceSwitchRenderable( +// entity, // Entity to attach the renderable to +// InstanceSwitchRenderable::Dynamic, // How/when to execute the renderable +// smoke_2_instance, // the instance to control +// True, // Instance is on when trigger is... +// smoke_2_morph_delay->GetTriggerAttribute()); +//#endif +// //------------------------------------------- +// // Set dither Z on material for smoke column +// //------------------------------------------- +// dpl_MATERIAL *damage_material = +// dpl_LookupMaterial ("btfx:smoke1_mtl", +// dpl_lookup_normal, +// &status); +// if (damage_material == 0) +// { +// std::cout << "couldn't find material\n"; +// } +// else +// { +// dpl_SetMaterialDitherZ(damage_material, 10.0f); +// dpl_FlushMaterial(damage_material); +// } +// //--------------------------------------------------- +// // Create a material morph to fade smoke column away +// //--------------------------------------------------- +// OneShotDelayRenderable *smoke_fade_delay = +// new OneShotDelayRenderable( +// entity, // Entity to attach the renderable to +// OneShotDelayRenderable::Dynamic, // How/when to execute the renderable +// 25.0f); // How long to wait before raising the trigger +// SweepRenderable *smoke_fade_sweep = +// new SweepRenderable( +// entity, // Entity to attach the renderable to +// SweepRenderable::Dynamic, // How/when to execute the renderable +// 18.5f, // How long to take to sweep from 0 to 1 +// 1, // number of times to cycle before stopping +// smoke_fade_delay->GetTriggerAttribute()); // trigger variable +// Register_Object(smoke_fade_sweep); +// // Lookup texture for smoke column +// dpl_TEXTURE *smoke_texture = +// dpl_LookupTexture("btfx:smoke1_scr_tex", dpl_lookup_normal, &status); +// if (smoke_texture == NULL) +// DEBUG_STREAM<<"couldn't find texture btfx:smoke1_scr_tex for an effect\n" << std::flush; +// // +// MorphMaterialRenderable *smoke_fade_material = +// new MorphMaterialRenderable( +// entity, // Entity to attach the renderable to +// MorphMaterialRenderable::Dynamic, // How/when to execute the renderable +// 1.0f,1.0f,1.0f, // Material's ambient component +// 0.7f,0.4f,0.4f, // Material's emissive component +// 0.3714f,0.2899f,0.3714f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0f, // Material's specular component +// 0.7f,0.99f,0.0f, // Material's opacity +// smoke_texture, // Material's texture pointer +// 10.0f, // Material's Z dither value +// 3, // Material's Fog Imunity value +// 1.0f,1.0f,1.0f, // Material's ambient component +// 0.7f,0.4f,0.4f, // Material's emissive component +// 0.3714f,0.2899f,0.3714f, // Material's diffuse component +// 0.0f,0.0f,0.0f,0.0f, // Material's specular component +// 0.0f,0.99f,0.0f, // Material's opacity +// 10.0f, // Material's Z dither value +// smoke_fade_sweep->GetSweepAttribute()); +// Register_Object(smoke_fade_material); +//// dpl_INSTANCE *smoke_1_instance = dpl_GetDCSInstance(smoke_1_morph->GetDCS(), 1); +// if (!smoke_1_instance) +// Fail("smoke_1_instance came back null\n"); +// dpl_SetInstanceFrontMaterial(smoke_1_instance, smoke_fade_material->GetMaterial()); +// dpl_FlushInstance(smoke_1_instance); +//#endif +// #else +// DEBUG_STREAM <<"Explosion effect 104 called, this is disabled and shouldn't be used!\n" << std::flush; +// #endif +// break; +// } +// default: +// { +// break; +// } +// } +} +// +//############################################################################# +// MakeEntityRenderables handles creating all the renderables necessary to +// display an object. This routine contains default behaviors for creating +// some types of simple objects. The idea is that if a higher level routine +// can't figure out how to make renderables for something this routine will be +// called and the default behavior will be used. +//############################################################################# +// +void + DPLRenderer::MakeEntityRenderables( + Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom view_type) // Type of reference (inside/outside...etc.) +{ +//STUBBED: DPL RB 1/14/07 + char *object_filename; + #if DEBUG_LEVEL > 0 + int object_count; + #endif + L4VideoObject *video_object; + L4VideoObjectWrapper *video_wrapper; + ChainOf video_chain(NULL); + L4VideoObject::ResourceType resource_type; +// dpl_DCS *my_root_dcs; + Enumeration renderer_modes; + // + // Set the Entity_Being_Created global so the C language callback will + // be able to mark the geometry with damage zone values if necessary. + // + Entity_Being_Created = entity; +// my_root_dcs = NULL; + // + // convert video resource into chain of video objects and make an iterator + // for that chain + // + if (model_resource) + { + #if DEBUG_LEVEL > 0 + object_count = + #endif + L4VideoObjectWrapper::BuildVideoObjectChainFromResource(&video_chain, model_resource); + } + ChainIteratorOf video_iterator(video_chain); + // + // Switch to allow us to have scripts at this level for constructing certain + // types of video objects (whether or not they have a video resource) + // + switch (entity->GetClassID()) + { + // + // Dropzones have no graphical appearance so we do nothing + // + case DropZoneClassID: + break; + // + // Player objects have no graphical appearance unless one is created + // at a higher (game specific) level, so we do nothing here. + // + case PlayerClassID: + break; + // this entity has no visual appearance + case AudioEntityClassID: + break; + // + // Cultural and landmark are the only ones with "destroyed" processing + // This is similar to the default case but does not allow us to be + // inside the entity, does not allow us to be a mover, + // + case CulturalIconClassID: + case LandmarkClassID: + { + dpl_INSTANCE *this_instance; + d3d_OBJECT *this_object; + dpl_ISECT_MODE intersect_mode; + HierarchicalDrawComponent *component = NULL; + uint32 intersect_mask; + LinearMatrix offset_matrix = LinearMatrix::Identity; + //dpl_DCS *root_DCS, *this_DCS; + // + // Make sure the object has a video resource + // + if (!model_resource) + { + VideoRenderer::MakeEntityRenderables(entity, model_resource, view_type); + Entity_Being_Created = NULL; + return; + } +// intersect_mode = dpl_isect_mode_geometry; + intersect_mask = INTERSECT_ALL; + Logical first_object = True; + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + object_filename = video_object->GetObjectFilename(); + resource_type = video_object->GetResourceType(); + renderer_modes = video_object->GetRendererModes(); + + #if NOISY_RENDERER + Tell("L4VIDEO.cpp loading object " << object_filename); + Tell(" type " << resource_type); + Tell(" mode 0x" < + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + //root_DCS = this_static_root->GetDCS(); + //------------------------------------------------------ + // if root object billboards (all others billboard too) + //------------------------------------------------------ + //this_DCS = root_DCS; +// this_instance = this_static_root->GetInstance(); + // + // Set my_root_dcs because we want this guy's hiearchy to be marked + // with his entity pointer + // +// my_root_dcs = root_DCS; + } + else + { + if (renderer_modes | L4VideoObject::BillboardObject) + { + //------------------------------------------ + // attach additional object to separate DCS + // because it is billboarded + //------------------------------------------ + component = new DPLStaticChildRenderable( + entity, + false, + this_object, + intersect_mode, + intersect_mask, + offset_matrix, + NULL); +// this_DCS = this_child->GetDCS(); +// this_instance = this_child->GetInstance(); + } + else + { + //---------------------------------------- + // attach additional objects to root_DCS + // (HACK) temporary implementation (HACK) + //---------------------------------------- + component = new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + this_object, // object to connect to the instance + NULL, // the DCS to add the instance to + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + True); // initial visibility setting + //this_DCS = NULL; +// this_instance = another_instance->GetInstance(); + } + } + // add the new object to our renderables list + if (component) + mRenderables.Add(component); + component = NULL; + // + // Hook up the object to an instance switch renderable responsive to state + // + StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState"); + switch(resource_type) + { + case L4VideoObject::Object: + { + component = new StateInstanceSwitchRenderable( + entity, // Entity to attach the renderable to + StateInstanceSwitchRenderable::Watcher, // How/when to execute the renderable + this_instance, // the instance to control + False, // true to turn on in this state, false for off + simulation_state, // State dial we use to control the on/off + CulturalIcon::BurningState); // State that we look for + break; + } + case L4VideoObject::Rubble: + { + component = new StateInstanceSwitchRenderable( + entity, // Entity to attach the renderable to + StateInstanceSwitchRenderable::Watcher, // How/when to execute the renderable + this_instance, // the instance to control + True, // true to turn on in this state, false for off + simulation_state, // State dial we use to control the on/off + CulturalIcon::BurningState); // State that we look for + break; + } + } + if (component) + mRenderables.Add(component); + //---------------------------------- + // billboard object if so indicated + //---------------------------------- +// if (this_DCS && (renderer_modes & L4VideoObject::BillboardObject)) +// { +// int axes = dpl_reorient_axes_none; + +// if (renderer_modes & L4VideoObject::BillboardXAxis) +// { +// axes |= dpl_reorient_axes_x; +// } +// if (renderer_modes & L4VideoObject::BillboardYAxis) +// { +// axes |= dpl_reorient_axes_y; +// } +// if (renderer_modes & L4VideoObject::BillboardZAxis) +// { +// axes |= dpl_reorient_axes_z; +// } +// dpl_SetDCSReorientAxes(this_DCS, (dpl_REORIENT_AXES)axes); +// dpl_FlushDCS(this_DCS); +// } + } + break; + } + // + // Case to handle rivets using the fast projectile code + // + case RivetClassID: + { + d3d_OBJECT + *this_object; + video_iterator.First(); + video_wrapper = video_iterator.ReadAndNext(); + Check(video_wrapper); + video_object = video_wrapper->GetVideoObject(); + Check_Pointer(video_object); + object_filename = video_object->GetObjectFilename(); + this_object = d3d_OBJECT::LoadObject(GetDevice(), object_filename); + #if DEBUG_LEVEL > 0 + ProjectileRootRenderable *projectile = + #endif + new ProjectileRootRenderable( + entity, // Entity to attach the renderable to + ProjectileRootRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false); // DPL Zone this stuff will live in (for culling) + Register_Object(projectile); + break; + } + // + // Script for generating renderables for eyecandy + // + case EyeCandyClassID: + { + int effect_number; + + dpl_ISECT_MODE dpl_isect_mode_obj; + RootRenderable *this_root = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Dynamic, // How/when to execute the renderable + NULL, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL); // intersection mask for the object + Register_Object(this_root); + StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState"); + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + effect_number = atoi(video_object->GetObjectFilename()); + #if DEBUG_LEVEL > 0 + DPLSFXRenderable *this_effect = + #endif + new DPLSFXRenderable( + entity, // Entity to attach the effect to + false, // DPL zone everything will be in + Point3D::Identity, // Point offset from the parent DCS + this_root, // Parent DCS (can be NULL for world) + simulation_state, // Trigger effect when this state changes + EyeCandy::effectOn, // Trigger effect when in this state + effect_number, // Type of effect to trigger + .01); // Effect repeat speed. + Register_Object(this_effect); + } + break; + } + // + // Script for generating an explosion of type specified in the resource file + // + case ExplosionClassID: + { + DEBUG_STREAM << "Explosion Created in MakeEntityRenderables:" << std::endl << std::flush; + int effect_number; + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + effect_number = atoi(video_object->GetObjectFilename()); + DEBUG_STREAM << " ** effect_number = " << effect_number << std::endl << std::flush; + if(effect_number < 100 || effect_number >= 1000) + { + DEBUG_STREAM << " ** DPLIndependantEffect([" + << entity->localOrigin.linearPosition.x + << ", " << entity->localOrigin.linearPosition.y + << ", " << entity->localOrigin.linearPosition.z << "], " << effect_number << ");" << std::endl << std::flush; + DPLIndependantEffect( + entity->localOrigin.linearPosition, + effect_number); + } + else + { + DEBUG_STREAM << " ** ExplosionScripts(*entity*, RES[" + << model_resource->resourceID << " - " << model_resource->resourceName << "], " + << "ViewFrom::" << (view_type == ViewFrom::insideEntity ? "insideEntity" : (view_type == ViewFrom::outsideEntity ? "outsideEntity" : "collisionEntity")) + << ", " << (effect_number - 100) << ");" << std::endl << std::flush; + ExplosionScripts( + entity, // The entity we are dealing with + model_resource, // Pointer to the video resource + view_type, // Type of reference (inside/outside...etc.) + effect_number - 100); + } + } + break; + } + case CameraDirectorClassID: + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the CameraDirector HUD Renderable if not a Replicant + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (entity->GetInstance() == CameraDirector::MasterInstance) + { + CameraDirector *camera_director = (CameraDirector*) entity; + Check_Pointer(camera_director); + + int *player_index = &camera_director->goalPlayerIndex; + Check_Pointer(player_index); + + Logical *display_rank_window = &camera_director->displayRankingWindow; + Check_Pointer(display_rank_window); + + mCamShipHUD = new CameraShipHUDRenderable(entity, CameraShipHUDRenderable::Dynamic, player_index, display_rank_window); + } + break; + } + // + // Script for a drivable camera, the camera is invisible to other players + // + case CameraShipClassID: + { + if(view_type == insideEntity) + { + // + // Build an empty root renderable and an eye renderable + // + dpl_ISECT_MODE dpl_isect_mode_obj; + RootRenderable *this_root = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Dynamic, // How/when to execute the renderable + NULL, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL); // intersection mask for the object + Register_Object(this_root); + + #if 0 //DEBUG_LEVEL > 0 + DPLEyeRenderable* this_eye = + #endif + mCamera = + new DPLEyeRenderable( + entity, + LinearMatrix::Identity, + this_root, + NULL + ); + Register_Object(this_eye); + } + break; + } + // + // Script for doorframe, so it can be used in any game + // + case DoorFrameClassID: + { + Verify( object_count == 6 ); + //------------------------------------------------ + // First video object is root shape for the door + // followed by left door shape, right door shape, + // door lights, left door lights, and right door + // lights. + //------------------------------------------------ + d3d_OBJECT + *object, + *left, + *right, + *object_lights, + *left_lights, + *right_lights; + int object_number = 0; + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + object_filename = video_object->GetObjectFilename(); + + #if NOISY_RENDERER + Tell("L4VIDEO.cpp loading door object "<GetSubsystem(0); + Point3D* left_door_position = &left_door_sub->currentPosition; + Door *right_door_sub = (Door*) entity->GetSubsystem(1); + Point3D* right_door_position = &right_door_sub->currentPosition; + dpl_ISECT_MODE dpl_isect_mode_obj; + RootRenderable *door_sill = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Static, // How/when to execute the renderable + object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + dpl_isect_mode_obj, // type of intersections to do on this object + NULL); // intersection mask for the object + Register_Object(door_sill); + // + // Set my_root_dcs because we want this guy's hiearchy to be marked + // with his entity pointer + // +// my_root_dcs = door_sill->GetDCS(); + LinearMatrix my_ident(True); + DPLChildPointRenderable* left_door = + new DPLChildPointRenderable( + entity, + false, + left, + dpl_isect_mode_obj, + NULL, + my_ident, + door_sill, + left_door_position); + Register_Object(left_door); + DPLChildPointRenderable* right_door = + new DPLChildPointRenderable( + entity, + false, + right, + dpl_isect_mode_obj, + NULL, + my_ident, + door_sill, + right_door_position); + Register_Object(right_door); + #if DEBUG_LEVEL > 0 + DCSInstanceRenderable *door_sill_lights_instance = + #endif + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + object_lights, // object to connect to the instance + door_sill, // the DCS to add the instance to + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + True); // initial visibility setting + Register_Object(door_sill_lights_instance); + #if DEBUG_LEVEL > 0 + DCSInstanceRenderable *left_door_lights_instance = + #endif + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + left_lights, // object to connect to the instance + left_door, // the DCS to add the instance to + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + True); // initial visibility setting + Register_Object(left_door_lights_instance); + #if DEBUG_LEVEL > 0 + DCSInstanceRenderable *right_door_lights_instance = + #endif + new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + right_lights, // object to connect to the instance + right_door, // the DCS to add the instance to + dpl_isect_mode_obj, // type of intersections to do on this object + NULL, // intersection mask for the object + True); // initial visibility setting + Register_Object(right_door_lights_instance); + break; + } + // + // This is the script run on anything that isn't already listed above + // + default: + { + d3d_OBJECT *this_object; + dpl_ISECT_MODE intersect_mode; + uint32 intersect_mask; + LinearMatrix offset_matrix = LinearMatrix::Identity; + Component *component = NULL; + HierarchicalDrawComponent *rootCom = NULL; + HierarchicalDrawComponent *thisCom = NULL; + // + // First, establish that this level doesn't know what to do + // if the object has no video resource. + // + if (!model_resource) + { + VideoRenderer::MakeEntityRenderables(entity, model_resource, view_type); + Entity_Being_Created = NULL; + return; + } + // + // If we're inside the entity, set up the intersect mode and mask so we + // won't intersect ourselves with the pickpoint. Other items get full + // geometry intersection. + // + if (view_type == insideEntity) + { +// intersect_mode = dpl_isect_mode_obj; + intersect_mask = NULL; + } + else + { +// intersect_mode = dpl_isect_mode_geometry; + intersect_mask = INTERSECT_ALL; + } + + Logical first_object = True; + + video_iterator.First(); + while ((video_wrapper = video_iterator.ReadAndNext()) != NULL) + { + video_object = video_wrapper->GetVideoObject(); + object_filename = video_object->GetObjectFilename(); + resource_type = video_object->GetResourceType(); + renderer_modes = video_object->GetRendererModes(); + + #if NOISY_RENDERER + Tell("L4VIDEO.cpp loading object " << object_filename); + Tell(" type " << resource_type); + Tell(" mode 0x" <IsDerivedFrom(*Mover::GetClassDerivations())) + { + // + // It's a mover, construct it with a dynamic root renderable so it can move + // also remember it's DCS so we can hook other shapes to it later. + // + SET_VIDEO_CONSTRUCT_ROOT(); + rootCom = new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + Register_Object(this_root); + CLEAR_VIDEO_CONSTRUCT_ROOT(); + } + else + { + // + // It's a static, construct it with a static RootRenderable and + // remember it's DCS so we can hook other shapes to it later. + // + rootCom = new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Static, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + } + // + // Set my_root_dcs because we want this guy's hiearchy to be marked + // with his entity pointer + // +// my_root_dcs = root_DCS; + // + // If we are inside the entity, then we must build an eyepoint for it too. + // since there is no special construction, we build the eyepoint with a + // zero offset. + // + if (view_type == insideEntity) + { + EulerAngles *eyepoint_rotation = (EulerAngles *)entity->GetAttributePointer("EyepointRotation"); + #if 0 //DEBUG_LEVEL > 0 + DPLEyeRenderable *this_eye = + #endif + mCamera = + new DPLEyeRenderable( + entity, + LinearMatrix::Identity, + rootCom, + eyepoint_rotation); + Register_Object(this_eye); + } + //------------------------------------------------------ + // if root object billboards (all others billboard too) + //------------------------------------------------------ +// this_DCS = root_DCS; + } + else + { + if (renderer_modes & L4VideoObject::BillboardObject) + { + //------------------------------------------ + // attach additional object to separate DCS + // because it is billboarded + //------------------------------------------ + thisCom = new DPLStaticChildRenderable( + entity, + false, + this_object, + intersect_mode, + intersect_mask, + offset_matrix, + rootCom); + Register_Object(this_child); +// this_DCS = this_child->GetDCS(); + } + else + { + //---------------------------------------- + // attach additional objects to root_DCS + // (HACK) temporary implementation (HACK) + //---------------------------------------- + thisCom = new DCSInstanceRenderable( + entity, // Entity to attach the renderable to + DCSInstanceRenderable::Static, // How/when to execute the renderable + this_object, // object to connect to the instance + rootCom, // the DCS to add the instance to + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + True); // initial visibility setting + Register_Object(another_instance); +// this_DCS = NULL; + } + } + //---------------------------------- + // billboard object if so indicated + //---------------------------------- + if (thisCom && (renderer_modes & L4VideoObject::BillboardObject)) + { +// int axes = dpl_reorient_axes_none; + + if (renderer_modes & L4VideoObject::BillboardXAxis) + { +// axes |= dpl_reorient_axes_x; + } + if (renderer_modes & L4VideoObject::BillboardYAxis) + { +// axes |= dpl_reorient_axes_y; + } + if (renderer_modes & L4VideoObject::BillboardZAxis) + { +// axes |= dpl_reorient_axes_z; + } +// dpl_SetDCSReorientAxes(this_DCS, (dpl_REORIENT_AXES)axes); +// dpl_FlushDCS(this_DCS); + } + + //MOVED THIS TO ROOTRENDERABLE - Was this a hack? + //mRenderables.Add(component); + } + break; + } + } + // + // release the video chain memory + // + L4VideoObjectWrapper::DeleteVideoObjectChain(&video_chain); + // + // Clear the entity pointer passed to the callback system + // + Entity_Being_Created = NULL; + // + // If my_root_dcs is non-null, mark the entity's DCS hiearchy with it's + // entity pointer. + // +// if(my_root_dcs) +// { +// MarkDCSHiearchy(my_root_dcs,entity); +//#if 0 +// if(entity->GetClassID() == DemolitionPackClassID) +// { +// Point3D temp_point(0.0,0.0,0.0); +// #if DEBUG_LEVEL > 0 +// OnePSFXRenderable *this_effect= +// #endif +// new OnePSFXRenderable( +// entity, // Entity to attach the renderable to +// OnePSFXRenderable::Static, // How/when to execute the renderable +// myPSFXDescriptons[3], // name of file with the PFX description in it +// my_root_dcs, // DCS the effect is relative to (may be NULL) +// &temp_point); // Offset (or world coordinants if DCS is NULL) +// Register_Object(this_effect); +// } +//#endif +// } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This should be called prior to the rendering of a frame to setup the culling +// data the renderer keeps (mostly the world to eye transform) +// +void + DPLRenderer::SetupCull() +{ + Entity + *linked_entity; + LinearMatrix + site_to_world, + world_to_site, + eye_rotation, + eye_inverted; + EntitySegment + *eyepoint_segment; + EulerAngles + *eyepoint_rotation; + // + // To test the functionality, this is not as efficient as it could be. + // when it gets fully patched into the renderer it will be improved. + // + // Figure out what type of entity this is. + // + linked_entity = GetLinkedEntity(); + eyepoint_rotation = (EulerAngles*)linked_entity->GetAttributePointer("EyepointRotation"); + if(linked_entity->IsDerivedFrom(*JointedMover::GetClassDerivations())) + { + JointedMover + *linked_jointed_mover; + + linked_jointed_mover = Cast_Object(JointedMover*, linked_entity); + eyepoint_segment = linked_jointed_mover->GetSegment("siteeyepoint"); + if(!eyepoint_segment) + { + Fail("DPLRenderer::SetupCull jointed mover had no siteeyepoint\n"); + } + if(!eyepoint_rotation) + { + Fail("DPLRenderer::SetupCull jointed mover had no EyepointRotation attribute\n"); + } + linked_jointed_mover->GetSegmentToWorld(*eyepoint_segment, &site_to_world); + if(eyepoint_rotation) + { + world_to_site.Invert(site_to_world); + eye_rotation = *eyepoint_rotation; + eye_inverted.Invert(eye_rotation); + worldToEyeMatrix.Multiply(world_to_site, eye_inverted); + } + else + { + worldToEyeMatrix.Invert(site_to_world); + } + } + else + { + site_to_world = linked_entity->localOrigin; + if(eyepoint_rotation) + { + world_to_site.Invert(site_to_world); + eye_rotation = *eyepoint_rotation; + eye_inverted.Invert(eye_rotation); + worldToEyeMatrix.Multiply(world_to_site, eye_inverted); + } + else + { + worldToEyeMatrix.Invert(site_to_world); + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +void + DPLRenderer::ResetStatistics() +{ + total_cull = 0; + total_draw = 0; + total_pixelplanes = 0; + total_frame_time = 0; + frame_count = 0; + target_frame_time = 56000; + target_frame_count= 0; + report_time = currentFrameTime + 60.0f; +} +void + DPLRenderer::ReportStatistics() +{ + if(frame_count != 0) + { + std::cout<<"Frames "<GetApplicationState(); + switch (currentAppState) + { + case Application::CreatingMission: + case Application::LoadingMission: + case Application::WaitingForLaunch: + //if (mLoadingScreenThread == NULL) + //{ + // mLoadingScreenRunning = true; + // mLoadingScreenThread = CreateThread(NULL, 0, (LPTHREAD_START_ROUTINE)ExecuteLoadScreenThread, this, 0, NULL); + //} + + //hr = mDevice->TestCooperativeLevel(); + //if (hr == D3DERR_DEVICELOST || hr == D3DERR_DEVICENOTRESET) + //{ + // mPrimaryDeviceReseting = true; + // DEBUG_STREAM << this << " RESETTING DEVICE - WAITING FOR FRAME TO FINISH" << std::endl << std::flush; + // while (mRenderingLoadingFrame) + // { + // Sleep(100); + // } + + // DEBUG_STREAM << this << " RESETTING DEVICE - DONE WAITING FOR FRAME TO FINISH" << std::endl << std::flush; + + // int bbCount = mPresentParams.BackBufferCount; + // int bbWidth = mPresentParams.BackBufferWidth; + // int bbHeight = mPresentParams.BackBufferHeight; + + // ParticleEngine::Destroy(); + // V(mDevice->Reset(&mPresentParams)); + // ParticleEngine::Initialize(mDevice); + // this->SetCoreRenderStates(); + + // mPresentParams.BackBufferCount = bbCount; + // mPresentParams.BackBufferWidth = bbWidth; + // mPresentParams.BackBufferHeight = bbHeight; + + // mPrimaryDeviceReseting = false; + //} + + ticks = HiResNowTicks(); +#ifdef LOGFRAMERATE + fputc(1, FRAMERATE_LOG); + fwrite(&ticks, sizeof(__int64), 1, FRAMERATE_LOG); +#endif + return; + + case Application::LaunchingMission: + case Application::RunningMission: + break; + } + if (lastAppState != currentAppState && currentAppState == Application::LaunchingMission) + { + this->mDevice->SetRenderState(D3DRS_LIGHTING, true); + this->mDevice->SetTransform(D3DTS_PROJECTION, &this->mProjectionMatrix); + this->mDevice->SetRenderState(D3DRS_TEXTUREFACTOR, D3DCOLOR_ARGB(128, 255, 255, 255)); + this->mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + } + lastAppState = currentAppState; + + // before we execute everything we need to clear + // the render lists + memset(mRenderLists, 0, sizeof(mRenderLists)); + + HierarchicalDrawComponent *drawComp; + SChainIteratorOf iterator(&mRenderables); + while ((drawComp = iterator.ReadAndNext()) != NULL) + drawComp->Execute(); + + if (mReticle) + mReticle->Execute(); + + if (mCamShipHUD) + mCamShipHUD->Execute(); + + gNumBatches = 0; + static Time lastFrameTime = mTargetRenderTime; + Scalar dT = mTargetRenderTime - lastFrameTime; + lastFrameTime = mTargetRenderTime; + currentFrameTime = Now(); + + DWORD currentFog; + mDevice->GetRenderState(D3DRS_FOGCOLOR, ¤tFog); + hr = mDevice->Clear(0, NULL, D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, currentFog, 1.0f, 0); + + hr = mDevice->BeginScene(); + + mDevice->SetFVF(L4VERTEX_FVF); + + D3DXMATRIX viewTransform; + mDevice->GetTransform(D3DTS_VIEW, &viewTransform); + + // + // Start with the opaque pass + // + mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(¤tFogNear))); + mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(¤tFogFar))); + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, true); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE, false); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG1); + mDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_MATERIAL); + mDevice->SetTextureStageState(2, D3DTSS_COLOROP, D3DTOP_DISABLE); + + d3d_OBJECT::ResetState(mDevice); + + if (!l4_application->IsDead()) + { + std::list::const_iterator iter; + + for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter) + { + (*iter)->Draw(PASS_OPAQUE, &viewTransform, mTargetRenderTime); + } + } + + for (d3d_OBJECT *obj = mRenderLists[PASS_OPAQUE]; obj != NULL; obj = obj->GetNext(PASS_OPAQUE)) + obj->Draw(PASS_OPAQUE, &viewTransform, mTargetRenderTime); + + // + // Next up is the decal pass + // + + mDevice->SetTransform(D3DTS_PROJECTION, &mDecalProjectionMatrix); + + if (!l4_application->IsDead()) + { + std::list::const_iterator iter; + + for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter) + { + (*iter)->Draw(PASS_DECAL, &viewTransform, mTargetRenderTime); + } + } + + for (d3d_OBJECT *obj = mRenderLists[PASS_DECAL]; obj != NULL; obj = obj->GetNext(PASS_DECAL)) + obj->Draw(PASS_DECAL, &viewTransform, mTargetRenderTime); + + // + // The sphere pass + // + + //Set it up so the fog won't affect spheres' colors so much- extend the near fog plane out + float fogModNear = currentFogFar; + float fogModFar = fogModNear + (currentFogFar - currentFogNear); + mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(&fogModNear))); + mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(&fogModFar))); + + for (d3d_OBJECT *obj = mRenderLists[PASS_SPHERE]; obj != NULL; obj = obj->GetNext(PASS_SPHERE)) + obj->Draw(PASS_SPHERE, &viewTransform, mTargetRenderTime); + + // + // The sky pass + // + + //Further extend the fog distance + fogModNear = currentFogNear * 3; + fogModFar = currentFogFar * 6; + + mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(&fogModNear))); + mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(&fogModFar))); + + mDevice->SetTransform(D3DTS_PROJECTION, &mProjectionMatrix); + + + if (!l4_application->IsDead()) + { + std::list::const_iterator iter; + + for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter) + { + (*iter)->Draw(PASS_SKY, &viewTransform, mTargetRenderTime); + } + } + + for (d3d_OBJECT *obj = mRenderLists[PASS_SKY]; obj != NULL; obj = obj->GetNext(PASS_SKY)) + obj->Draw(PASS_SKY, &viewTransform, mTargetRenderTime); + + //Reactivate fog + mDevice->SetRenderState(D3DRS_FOGSTART, *((DWORD*)(¤tFogNear))); + mDevice->SetRenderState(D3DRS_FOGEND, *((DWORD*)(¤tFogFar))); + + // + // Finally we do the alpha blend pass + // + mDevice->SetRenderState(D3DRS_ZWRITEENABLE,false); + mDevice->SetRenderState(D3DRS_ALPHABLENDENABLE,true); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_SELECTARG2); + + if (!l4_application->IsDead()) + { + std::list::const_iterator iter; + + for (iter = this->mConsolidatedStaticObjects.begin(); iter != this->mConsolidatedStaticObjects.end(); ++iter) + { + (*iter)->Draw(PASS_ALPHABLEND, &viewTransform, mTargetRenderTime); + } + } + + for (d3d_OBJECT *obj = mRenderLists[PASS_ALPHABLEND]; obj != NULL; obj = obj->GetNext(PASS_ALPHABLEND)) + obj->Draw(PASS_ALPHABLEND, &viewTransform, mTargetRenderTime); + + // + // And don't forget particles too + // + D3DXMATRIX ident; + mDevice->SetTransform(D3DTS_WORLD, D3DXMatrixIdentity(&ident)); + + + if (!l4_application->IsDead()) + { + ParticleEngine::RenderParticles(&viewTransform, dT); + + for (int i=0; iSetFVF(L4VERTEX_2D_FVF); + mDevice->SetRenderState(D3DRS_ZWRITEENABLE, true); + mDevice->SetTextureStageState(0, D3DTSS_COLOROP, D3DTOP_MODULATE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG1, D3DTA_DIFFUSE); + mDevice->SetTextureStageState(0, D3DTSS_COLORARG2, D3DTA_TEXTURE); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAOP, D3DTOP_MODULATE); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG1, D3DTA_DIFFUSE); + mDevice->SetTextureStageState(0, D3DTSS_ALPHAARG2, D3DTA_TEXTURE); + mDevice->SetRenderState(D3DRS_DIFFUSEMATERIALSOURCE, D3DMCS_COLOR1); + mDevice->SetTextureStageState(1, D3DTSS_COLOROP, D3DTOP_DISABLE); + + if (mReticle && !l4_application->IsDead()) + mReticle->Render(0, &viewTransform); + + if (mCamShipHUD) + mCamShipHUD->Render(0, &viewTransform); + + hr = mDevice->EndScene(); + + hr = mDevice->Present(NULL, NULL, NULL, NULL); + if (hr == D3DERR_DEVICELOST) + { + int bbCount = mPresentParams.BackBufferCount; + int bbWidth = mPresentParams.BackBufferWidth; + int bbHeight = mPresentParams.BackBufferHeight; + + ParticleEngine::Destroy(); + V(mDevice->Reset(&mPresentParams)); + ParticleEngine::Initialize(mDevice); + this->SetCoreRenderStates(); + + mPresentParams.BackBufferCount = bbCount; + mPresentParams.BackBufferWidth = bbWidth; + mPresentParams.BackBufferHeight = bbHeight; + } + + ticks = HiResNowTicks(); + +#ifdef LOGFRAMERATE + fputc(1, FRAMERATE_LOG); + fwrite(&ticks, sizeof(__int64), 1, FRAMERATE_LOG); +#endif +} + +void DPLRenderer::ExecuteIdle() +{ + HRESULT hr; + + hr = mDevice->Clear(0, NULL, D3DCLEAR_TARGET, 0xFF000000, 1.0f, 0); + + hr = mDevice->BeginScene(); + + hr = mDevice->EndScene(); + + if (mDevice->Present(NULL, NULL, NULL, NULL) == D3DERR_DEVICELOST) + { + int bbCount = mPresentParams.BackBufferCount; + int bbWidth = mPresentParams.BackBufferWidth; + int bbHeight = mPresentParams.BackBufferHeight; + + ParticleEngine::Destroy(); + V(mDevice->Reset(&mPresentParams)); + ParticleEngine::Initialize(mDevice); + this->SetCoreRenderStates(); + + mPresentParams.BackBufferCount = bbCount; + mPresentParams.BackBufferWidth = bbWidth; + mPresentParams.BackBufferHeight = bbHeight; + } +} +// +//############################################################################# +// DPLDelayDCSFlush and DPLDoDCSBatchFlush queue up a list of DCS pointers +// for later std::flushing in one big batch. +//############################################################################# +// +void + DPLRenderer::DPLDelayDCSFlush( + dpl_DCS *my_dcs) // The DCS we want to remember for later +{ + // + // Make sure the array hasn't become overfilled somehow and make + // sure the DCS is valid. + // + Verify(delayedDCSCount <= DELAY_DCS_FLUSH_ARRAY_SIZE); + Check_Pointer(my_dcs); + // + // If the array is full, std::flush it out to make space for this DCS + // + if(delayedDCSCount == DELAY_DCS_FLUSH_ARRAY_SIZE) + { + DPLDoDCSBatchFlush(); + } + // + // Add the New DCS to the list + // + delayDCSFlushArray[delayedDCSCount++] = my_dcs; +} +void + DPLRenderer::DPLDoDCSBatchFlush() // Flush the dcs's remembered by DPLDelayDCSFlush +{ + //STUBBED: DPL RB 1/14/07 + //SET_VIDEO_BATCH_FLUSH(); + //// + //// Make sure the array hasn't become overfilled somehow + //// + //Verify(delayedDCSCount <= DELAY_DCS_FLUSH_ARRAY_SIZE); + //// + //// Flush the array and reset the counters that go with it + //// + //if(delayedDCSCount != 0) + //{ + // delayDCSFlushArray[delayedDCSCount] = NULL; + // dpl_FlushDCSArticulations(delayDCSFlushArray); + // delayedDCSCount = 0; + //} + //CLEAR_VIDEO_BATCH_FLUSH(); +} +// +//############################################################################# +// DPLReportFreeMemory writes current free memory in graphics card to any +// output stream. +//############################################################################# +// +void + DPLRenderer::DPLReportFreeMemory(std::ostream &output) +{ +//STUBBED: DPL RB 1/14/07 +// output << "Free memory in card: " << dpl_FreeMemory() << " bytes." << std::endl; + return; +} +// +//############################################################################# +// DPLReportPerfStats writes performance statistics to std::cout (stdout). +//############################################################################# +// +void + DPLRenderer::DPLReportPerfStats(std::ostream &output) +{ + //STUBBED: DPL RB 1/15/07 + ////----------------------------------------------------- + //// HACK - copied from camera.c must re-copy if changed + //// + //// case '?': + //// printf ("sect time %d dcs 0x%x inst 0x%x\n", + //// __sect_time, sect_dcs, sect_inst ); + ////----------------------------------------------------- + //output << "sect time " << __sect_time << + // " dcs and inst not available" << std::endl; + + ////------------------------------------------------------------ + //// HACK - copied from dpl_vpx.c must re-copy if changed + //// + //// void dpl_PerfStats(void) + //// printf ( "cull %d draw %d frame %d pxpl %d prims %d\n", + //// __last_cull_time, + //// __last_draw_time, + //// __last_frame_time, + //// __last_pxpl_time, + //// __last_frame_prims ); + ////------------------------------------------------------------ + //output << + // "cull " << __last_cull_time << + // " draw " << __last_draw_time << + // " frame " << __last_frame_time << + // " pxpl " << __last_pxpl_time << + // " prims " << __last_frame_prims << + // std::endl; + //if(statistics_started) + //{ + // ReportStatistics(); + //} + //else + //{ + // ResetStatistics(); + // statistics_started = True; + //} + //return; +} +// +//############################################################################# +// DPLToggleWireframe toggles the state of dpl global wireframe. +//############################################################################# +// +void + DPLRenderer::DPLToggleWireframe() +{ + //STUBBBED: DPL RB 1/14/07 + //static Logical wireframe_on = 0; + + //if ((wireframe_on ^= 1) != 0) + //{ + // DEBUG_STREAM << "wireframe ON" << std::endl << std::flush; + // dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_on, NULL ); + //} + //else + //{ + // DEBUG_STREAM << "wireframe OFF" << std::endl << std::flush; + // dpl_SetRenderProperty(dpl_render_prop_wireframe, dpl_render_value_off, NULL ); + //} +} +// +//############################################################################# +// DPLTogglePVision toggles the state of dpl "predator" vision. +//############################################################################# +// +void + DPLRenderer::DPLTogglePVision() +{ + //STUBBED: DPL RB 1/14/07 + //static Logical pvision_on = 0; + //dpl_EXPLOSION_EFFECT_INFO sfx_info; + + //sfx_info.x = sfx_info.y = sfx_info.z = 0; + //if ((pvision_on ^= 1) != 0) + //{ + // DEBUG_STREAM << "pvision ON" << std::endl << std::flush; + // sfx_info.type = -1; + //} + //else + //{ + // DEBUG_STREAM << "pvision OFF" << std::endl << std::flush; + // sfx_info.type = -2; + //} + //dpl_Effect(dpl_effect_type_explosion, NULL, &sfx_info); + //return; +} +// +//############################################################################# +// DPLFrameDump writes screen image to targa file. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// oneD_filter() antialiased framegrab support +void + oneD_filter( + uint32 *linebuffer, + unsigned short *rframe, + unsigned short *gframe, + unsigned short *bframe, + int32 y, + int32 x_size + ) +{ + int32 + pos, + i, + r, g, b; + unsigned char + *clinebuf = (unsigned char *)linebuffer; + + pos = y * x_size; + + for (i=0; i> 8) & 0xff); + *clinebuf++ = (unsigned char)((g >> 8) & 0xff); + *clinebuf++ = (unsigned char)((b >> 8) & 0xff); + } + return; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// dump_frame_buffer() +void + dump_frame_buffer( + dpl_VIEW *eye, + int32 x_size, + int32 y_size, + Logical antialias + ) +{ + //STUBBED: DPL RB 1/14/07 + ////do not check eye here + + ////---------------------------------------- + //// control variable and operating buffers + ////---------------------------------------- + //static uint32 + // dumped_frames = 0, + // *line_buffer = NULL; + //static unsigned short + // *rframebuffer = NULL, + // *gframebuffer = NULL, + // *bframebuffer = NULL; + + //if (eye == NULL) + //{ + // //-------------------------- + // // release allocated memory + // //-------------------------- + // if (line_buffer) + // { + // Unregister_Pointer(line_buffer); + // delete line_buffer; + // } + // if (rframebuffer) + // { + // Unregister_Pointer(rframebuffer); + // delete rframebuffer; + // } + // if (gframebuffer) + // { + // Unregister_Pointer(gframebuffer); + // delete gframebuffer; + // } + // if (bframebuffer) + // { + // Unregister_Pointer(bframebuffer); + // delete bframebuffer; + // } + // return; + //} + //Check_Pointer(eye); + + ////----------------------------------------------------------------- + //// AA kernel definition: + //// + //// normalized screen coordinates are -1.0 .. +1.0 + //// these map (in NTSC) to 705 and 512. + //// So a pixel in x is + //// 2.0 / 704 = 2.841e-3 + //// in y = 3.906e-3 + //// for the re-use 5-sample kernel we displace by 0.5 pixels ... + ////----------------------------------------------------------------- + //static const int32 kernel_size = 4; + + //static const float xk = 2.0f / x_size; + //static const float yk = 2.0f / y_size; + //static const float ox = xk / 4.0f; + //static const float oy = yk / 4.0f; + //static const float jx = 0.0f; // ox / 4.0f + //static const float jy = 0.0f; // oy / 4.0f + + //static const float x_kernel[4] = { -(ox+jx), ox-jx, jx-ox, jx+ox }; + //static const float y_kernel[4] = { oy-jy, oy+jy, -(jy+oy), jy-oy }; + //static const int kernel_weights[4] = { 64, 64, 64, 64 }; + + ////--------------------- + //// operating variables + ////--------------------- + //int32 passes = (antialias)?kernel_size:1; + //int32 size = x_size * y_size; + //int32 frameptr; + //int32 i, x, y; + + //DEBUG_STREAM << "Dump frame buffer (antialias=" << + // ((antialias)?"True":"False") << ") - press Esc to cancel." << std::endl; + + ////---------------------------- + //// allocate operating buffers + ////---------------------------- + //if (line_buffer == NULL) + //{ + // //----------------------------------------------------------------------- + // // NOTE - must call dump_frame_buffer(NULL, NULL, NULL, NULL) to release + // //----------------------------------------------------------------------- + // line_buffer = new uint32[1024]; + // Register_Pointer(line_buffer); + // rframebuffer = new unsigned short[size]; + // Register_Pointer(rframebuffer); + // gframebuffer = new unsigned short[size]; + // Register_Pointer(gframebuffer); + // bframebuffer = new unsigned short[size]; + // Register_Pointer(bframebuffer); + //} + + ////------------------------------ + //// clear out r g b framebuffers + ////------------------------------ + //frameptr = 0; + //for (i=0; i> 8) & 0xff); + //tga_hdr[14] = (unsigned char)(y_size & 0xff); + //tga_hdr[15] = (unsigned char)((y_size >> 8) & 0xff); + + //tga_hdr[16] = 0x18; + //tga_hdr[17] = 0x00; + + //DEBUG_STREAM << "Writing image to file '" << fname << "' . . . " << std::flush; + //fp = fopen(fname, "wb"); + //fwrite(tga_hdr, 18, 1, fp); + + //for (y=0; yidentifier & 0xffff0000) | GetUniqueID() | ((subid << 16) & 0x00ff0000); + //tempParticle.px = location.x; + //tempParticle.py = location.y; + //tempParticle.pz = location.z; + //dpl_Effect(dpl_effect_type_particlestart, my_DCS, &tempParticle); + + +// std::cout<<"psfx identifier used was "<= 1000) + { + effect_number -= 1000; + if(effect_number < 0 || effect_number > MAX_PSFX_COUNT-1) + { + Fail("PSFX id number was not in the allowed range"); + } +// DPLIndependantPFX(location,myPSFXDescriptons[effect_number],my_DCS,subid); + + // find a free emitter + ParticleEmitter *emitter = NULL; + for (int i=0; iSetEffect(&myPSFXDescriptons[effect_number]); + emitter->SetPosition(location.x, location.y, location.z); + emitter->Start(); + } + + return; + } + + //dpl_EXPLOSION_EFFECT_INFO my_explosion; + //my_explosion.type = effect_number; + //my_explosion.x = location.x; + //my_explosion.y = location.y; + //my_explosion.z = location.z; + //dpl_Effect ( dpl_effect_type_explosion, my_DCS, &my_explosion ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void DPLRenderer::SetViewAngle(Degree new_angle) +{ + //STUBBED: DPL RB 1/14/07 + //Check(this); + //// + ////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //// Convert From Degree To Radian + ////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //// + //Radian view_angle; + //view_angle = new_angle; + //viewAngle = view_angle; + //viewRatio = tan(viewAngle/2.0f); + //// + ////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //// Calc Aspect Ratio and Set View Projection + ////~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + //// + //aspectRatio = (float) y_size / (float) x_size; + //dpl_SetViewProjection ( dplMainView, -1.0f, -aspectRatio, 1.0f, aspectRatio, 1.0f/viewRatio); + //dpl_FlushView(dplMainView); +} +// +//############################################################################# +// Startup the implementation of the Division video renderer +//############################################################################# +// +void + DPLRenderer::LoadMissionImplementation(Mission *mission) +{ + Check(this); + Tell("DPLVideoRenderer::StartImplementation has been called\n"); + DPLReadEnvironment(mission); + + LoadNameBitmaps(); +} +//############################################################################## +// Name Bitmap Support +// + +void DPLRenderer::SortAndReloadNameBitmaps() +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Entity Group of Players + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + EntityGroup *player_group = application->GetEntityManager()->FindGroup("Players"); + ChainIteratorOf player_iterator(player_group->groupMembers); + Player *current_player; + while ((current_player = (Player*)player_iterator.ReadAndNext()) != NULL) + { + BitMap *name_bitmap = application->GetCurrentMission()->GetLargeNameBitmap(current_player->playerBitmapIndex); + if (name_bitmap && current_player->IsScoringPlayer()) + { + int index = current_player->playerRanking + 1; + if (mNameTextures[index]) + mNameTextures[index]->Release(); + + mDevice->CreateTexture(128, 32, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &mNameTextures[index], NULL); + + LoadBitSliceTexture(name_bitmap, mNameTextures[index]); + } + } + + LoadOrdinalBitmaps(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void DPLRenderer::LoadOrdinalBitmaps() +{ + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Check if we have a Director on this machine, + // if so, create load the ordinal Bitmaps only + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + // + if (application->GetMissionPlayer()->GetInstance() == CameraDirector::MasterInstance && + application->GetMissionPlayer()->IsDerivedFrom(*CameraDirector::GetClassDerivations())) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make Sure index is in the right place + // in case < 8 players!!!! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int index = 0; + for(int ii=1; ii<5; ++ii) + { + // + //~~~~~~~~~~~~~~~~~~ + // Index Starts at 1 + //~~~~~~~~~~~~~~~~~~ + // + BitMap *ordinal_bitmap = application->GetCurrentMission()->GetOrdinalBitmap(ii); + + if (mOrdinalTextures[index]) + mOrdinalTextures[index]->Release(); + + mDevice->CreateTexture(128, 32, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &mOrdinalTextures[index], NULL); + + LoadBitSliceTexture(ordinal_bitmap, mOrdinalTextures[index]); + + ++index; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +unsigned int* + DPLRenderer::MakeBitSliceStorage() +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Allocate some temporary memory + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + uint32 *worst_case_texels = new uint32[128*64]; + if(!worst_case_texels) + { + Fail("Could not allocate RAM for worst case texels\n"); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Zero Out Memory so Empty Texture space is Black + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;ii<8192;++ii) + { + worst_case_texels[ii] = 0; + } + + return worst_case_texels; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void DPLRenderer::LoadNameBitmaps() +{ + int player_count = application->GetCurrentMission()->GetPlayerCount(); + for (int ii=0; iiGetCurrentMission()->GetLargeNameBitmap(ii + 1); + if (name_bitmap) + { + if (mNameTextures[ii]) + mNameTextures[ii]->Release(); + + HRESULT hr; + + V(mDevice->CreateTexture(128, 32, 1, 0, D3DFMT_A4R4G4B4, D3DPOOL_MANAGED, &mNameTextures[ii], NULL)); + + LoadBitSliceTexture(name_bitmap, mNameTextures[ii]); + } + } + + LoadOrdinalBitmaps(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DPLRenderer::ShutdownImplementation() +{ +//STUBBED: DPL RB 1/14/07 +// Tell("DPLVideoRenderer::StopImplementation has been called\n"); +// dpl_EnableSyncOnCreate(); +// SChainIteratorOf projectile_iterator(&projectile_list); +// TreeIteratorOf cache_iterator(&dplObjectCacheSocket); +//#if defined(LAB_ONLY) +// std::cout<<"max projectiles "<objectPointer; + delete my_cache_line; + + // + // Return the object pointer + // + return(object_pointer); +} + +void + DPLRenderer::PutCachedObject( + const CString &object_name, // Name of the object we will cache + dpl_OBJECT *object_pointer) // pointer to the object being cached +{ + // + // Create the cache line data structure + // + #if 0 + typedef PlugOf DPLObjectCacheLine; + + DPLObjectCacheLine *my_cache_line = new DPLObjectCacheLine(object_pointer); + #endif + + DPLObjectCacheLine *my_cache_line = + new DPLObjectCacheLine( + object_name, + object_pointer); + Register_Object(my_cache_line); + + // + // Store this cache line in the cache + // + dplObjectCacheSocket.AddValue(my_cache_line, object_name); + +} +//----------------------------------------------------------------------------- +//--------------------------Projectile Speedup--------------------------------- +//----------------------------------------------------------------------------- +InnerProjectileRenderable* + DPLRenderer::GetProjectile( + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone) // DPL Zone this stuff will live in (for culling) +{ + //STUBBED: DPL RB 1/14/07 + //InnerProjectileRenderable + // *return_projectile; + //dpl_INSTANCE + // *temp_instance; + //// + //// Are there projectiles in the list? + //// + //SChainIteratorOf iterator(&projectile_list); + //if ((return_projectile = iterator.GetCurrent()) != NULL) + //{ + // // Yes, remove it from the list set it's instance and return it + // iterator.Remove(); + // temp_instance = return_projectile->GetInstance(); + // if(graphical_object != dpl_GetInstanceObject(temp_instance)) + // { + // dpl_SetInstanceObject (temp_instance, graphical_object); + // dpl_FlushInstance (temp_instance); + // } + // return(return_projectile); + //} + //else + //{ + // // no, make a new one and return that + InnerProjectileRenderable *projectile = + new InnerProjectileRenderable( + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone); // DPL Zone this stuff will live in (for culling) + return(projectile); + //} +} +void + DPLRenderer::ReleaseProjectile( + InnerProjectileRenderable* inner_projectile) +{ + // add the projectile back to the list + //projectile_list.Add(inner_projectile); +} +//----------------------------------------------------------------------------- +//--------------------------Joint to DCS translator---------------------------- +//----------------------------------------------------------------------------- +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLJointToDCSTranslator is a class that contains a joint number to dcs +// pointer translation table. This lets a renderer find the dcs that goes +// with a particular segment. +// + DPLJointToDCSTranslator::DPLJointToDCSTranslator( + Entity *entity, // The entity to translate + dpl_DCS *dcs_array[]) // Array of DCS's to translate +{ + JointedMover + *my_jointed_mover; + // + // Make sure this is a jointed mover, then cast the entity pointer over + // + if (entity->IsDerivedFrom(*JointedMover::GetClassDerivations())) + { + my_jointed_mover = (JointedMover*)entity; + } + else + { + Fail("DPLJointToDCSTranslator was called on an entity NOT a JointedMover\n"); + } + // + // Find out how many joints the entity has, then allocate enough RAM for a + // DCS pointer to every joint. + // + JointSubsystem* joint_subsystem = my_jointed_mover->GetJointSubsystem(); + Check(joint_subsystem); + translation_array = new (dpl_DCS(*[joint_subsystem->GetJointCount()])); + Register_Pointer(translation_array); + // + // Setup to iterate the entity segment table + // + EntitySegment::SegmentTableIterator segment_iterator(my_jointed_mover->segmentTable); + EntitySegment *current_segment; + while ((current_segment = segment_iterator.ReadAndNext()) != NULL) + { + // + // For each segment, see if it has a joint index, if it does, put the + // DCS for that joint into the translation array + // + Check(current_segment); + int joint_index = current_segment->GetJointIndex(); + if(joint_index != -1) + { + translation_array[joint_index] = dcs_array[current_segment->GetIndex()]; + } + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +DPLJointToDCSTranslator::~DPLJointToDCSTranslator() +{ + Unregister_Pointer(translation_array); + delete[] translation_array; + translation_array = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +Logical + DPLJointToDCSTranslator::TestInstance() const +{ + return True; +} +//----------------------------------------------------------------------------- +//--------------------------Resource creation support-------------------------- +//----------------------------------------------------------------------------- +//############################################################################# +//############# DPLRenderer::CreateModelVideoStreamResource ############# +//############################################################################# + +ResourceDescription::ResourceID + DPLRenderer::CreateModelVideoStreamResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories * /*directories*/ + ) +{ + ResourceDescription *res_description = + resource_file->FindResourceDescription( + model_name, + ResourceDescription::VideoModelResourceType + ); + + if (res_description == NULL) + { + NameList *video_entries = model_file->MakeEntryList("video"); + + if (video_entries != NULL) + { + Register_Object(video_entries); + + //---------------------------------------------- + // parse video model data and store in resource + //---------------------------------------------- + Tell("Building video resource for model '" << model_name << "'.\n"); + + NameList::Entry + *entry, + *next_entry; + const char + *entry_name, + *entry_pointer, + *argument_start; + int + length; + char + argument[40], + *argument_pointer; + L4VideoObject::ResourceType + resource_type; + Enumeration //(see L4VideoObject::RendererModes) + renderer_modes; + enum + { + parsing_filename, + seeking_switch, + parsing_switch, + parsing_billboard + } state; + L4VideoObject + *video_object; + L4VideoObjectWrapper + *video_wrapper; + ChainOf + video_chain(NULL); + char + *video_stream, + *video_pointer; + int + object_count; + long + object_size, + stream_length; + + //------------------------------------------------ + // parse each entry in [video] page of model file + //------------------------------------------------ + next_entry = video_entries->GetFirstEntry(); + while (next_entry) + { + entry = next_entry; + Check(entry); + next_entry = entry->GetNextEntry(); // so 'continue' works + entry_name = entry->GetName(); + if (entry_name && *entry_name) + { + //-------------------------------------------- + // could be "skeleton" or "object" or comment + //-------------------------------------------- + if (strcmp(entry_name, "object") == 0) + { + resource_type = L4VideoObject::Object; + } + else if (strcmp(entry_name, "rubble") == 0) + { + resource_type = L4VideoObject::Rubble; + } + else if (strcmp(entry_name, "skeleton") == 0) + { + resource_type = L4VideoObject::Skeleton; + } + else if (Comment_Line(entry_name)) + { + // do nothing - skip comments + continue; + } + else if (strncmp(entry_name, "skeleton", 8) == 0) + { + // do nothing - skip temporary skeleton entries + continue; + } + else if (strncmp(entry_name, "destroyed", 9) == 0) + { + // do nothing - skip destroyed skeleton entries + continue; + } + else if (strncmp(entry_name, "dzm", 3) == 0) + { + // do nothing - skip damage zone material entries + continue; + } + else + { +// resource_type = L4VideoObject::Unknown; + DEBUG_STREAM << "Unknown entry '" << entry_name << + "' in model '" << model_name << "' ignored." << std::endl; + continue; + } + //--------------------------------- + // parse and process each argument + //--------------------------------- + entry_pointer = entry->GetChar(); + while (entry_pointer && *entry_pointer) + { + //------------------------- + // skip leading whitespace + //------------------------- + while (*entry_pointer != '\0' && isspace(*entry_pointer)) + { + ++entry_pointer; + } + //--------------------------- + // exit loop if nothing left + //--------------------------- + if (*entry_pointer == '\0') + { + break; + } + //------------------------------------------- + // parse the next argument into local buffer + //------------------------------------------- + argument_start = entry_pointer; + while (*entry_pointer != '\0' && !isspace(*entry_pointer)) + { + ++entry_pointer; + } + length = entry_pointer - argument_start; + Verify( length < sizeof(argument) ); + strncpy(argument, argument_start, length); + argument[length] = '\0'; + //---------------------- + // parse local argument + //---------------------- + argument_pointer = argument; + renderer_modes = L4VideoObject::Normal; + state = parsing_filename; + while (*argument_pointer != '\0') + { + switch (state) + { + case parsing_filename: + switch (*argument_pointer) + { + #if 0 + case '.': + if ((resource_type == L4VideoObject::Object) || + (resource_type == L4VideoObject::Rubble)) + { + *argument_pointer = '\0'; // terminate filename + state = seeking_switch; + } + break; + #endif + case '/': + *argument_pointer = '\0'; // terminate filename + state = parsing_switch; + break; + default: + // later check for valid filename character... + break; + } + break; + case seeking_switch: + if (*argument_pointer == '/') + { state = parsing_switch; } + break; + case parsing_switch: + switch (*argument_pointer) + { + case 'b': + case 'B': + state = parsing_billboard; + break; + case 'i': + case 'I': + renderer_modes |= L4VideoObject::IntersectImmune; + state = seeking_switch; + break; + default: + state = seeking_switch; + break; + } + break; + case parsing_billboard: + switch (*argument_pointer) + { + case 'x': + case 'X': + renderer_modes |= L4VideoObject::BillboardXAxis; + break; + case 'y': + case 'Y': + renderer_modes |= L4VideoObject::BillboardYAxis; + break; + case 'z': + case 'Z': + renderer_modes |= L4VideoObject::BillboardZAxis; + break; + case '/': + state = parsing_switch; + break; + default: + state = seeking_switch; + break; + } + break; + // no default: + } + ++argument_pointer; + } + //----------------------------------------------- + // create video resource object and add to chain + //----------------------------------------------- + video_object = + new L4VideoObject( + argument, + resource_type, + renderer_modes + ); + Register_Pointer(video_object); // not _Object! + + video_wrapper = + new L4VideoObjectWrapper( + video_object, + True // delete object when done + ); + Register_Object(video_wrapper); + + //Tell(" adding video object '"< + video_iterator(video_chain); + + object_count = video_iterator.GetSize(); + + object_size = sizeof(L4VideoObject); + stream_length = sizeof(int) + object_count * object_size; + + video_stream = new char[stream_length]; + Register_Pointer(video_stream); + + video_pointer = video_stream; + *((int *)video_pointer) = object_count; + video_pointer += sizeof(int); + + Tell(" count " <GetVideoObject(); + if (!stricmp(video_object->GetObjectFilename(), "bp1.bgf")) + video_pointer += 1 - 1; + *((L4VideoObject *)video_pointer) = *video_object; + video_pointer += object_size; + } + //-------------------------------------------------- + // store stream of video resources in resource file + //-------------------------------------------------- + res_description = + resource_file->AddResource( + model_name, + ResourceDescription::VideoModelResourceType, + 1, + ResourceDescription::Preload, + video_stream, + stream_length + ); + //-------------------------- + // release allocated memory + //-------------------------- + // video_chain + L4VideoObjectWrapper::DeleteVideoObjectChain(&video_chain); + // video_stream + Unregister_Pointer(video_stream); + delete video_stream; + // video_entries + Unregister_Object(video_entries); + delete video_entries; + } + else + { + //------------------------------- + // no [video] page in model file + //------------------------------- + return (ResourceDescription::NullResourceID); + } + } + return (res_description->resourceID); +} +//===========================================================================// diff --git a/MUNGA_L4/L4VIDEO.h b/MUNGA_L4/L4VIDEO.h new file mode 100644 index 0000000..8a182cf --- /dev/null +++ b/MUNGA_L4/L4VIDEO.h @@ -0,0 +1,577 @@ +#pragma once + +#include "..\munga\vidrend.h" +#include "..\munga\rotation.h" +#include "..\munga\reticle.h" +#include "..\munga\graph2d.h" +#include "..\munga\simulate.h" +#include "l4vidrnd.h" +#include "..\munga\tree.h" +#include "..\munga\table.h" +#include "l4d3d.h" +#include +#include +#include + +using namespace std; +using namespace stdext; + +//STUBBED: DPL RB 1/14/07 +//once the stubs are removed, the following can be removed +#define char8 unsigned char + +// RB 1/14/07 +//#include +//#include +#include +#include + +class NotationFile; + +#define INTERSECT_ALL (0xFFFFFFFF) + +//########################################################################## +// Declaration of dpl callback function that performs in-place text +// substitution on all material names before they are looked up. +// There must be at least MATERIAL_NAME_LENGTH bytes available at source! +// +#define MATERIAL_NAME_BUFFER_LENGTH 256 + +char* + substituteMaterial(char *source); + +void loadTables(); +const char* opMaterialName(const char *fileName, int opId); + +struct ReplacementMaterialData +{ + float r, g, b; + string texName; +}; + +hash_map> *gOpNames; +hash_map *gReplacementData; + +//########################################################################## +// This structure is attached to DPL nodes so we can put information in them +// on what entity the node is part of and what damage zone it belongs to. +// +#define MAX_DZ_NAME_LENGTH 25 + +struct dpl_tracker +{ + Entity + *This_Entity; // The entity this is part of + char + dz_name[MAX_DZ_NAME_LENGTH]; // this is temporary, to make testing easier + int + Damage_Zone_Number; // number of this damage zone +}; + +//----------------------------------------------------------------------------- +//--------------------------DPL video resource object-------------------------- +//----------------------------------------------------------------------------- +//########################################################################## +//########################## L4VideoObject ########################### +//########################################################################## + +#define MAX_OBJECT_FILENAME_LENGTH 15 + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This class gets stored in a resource so it is derived from nothing. +// +class L4VideoObject +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction and testing +// +public: + enum ResourceType + { + Unknown, + Skeleton, + Object, + Rubble, + VidFile + }; + enum RendererModes // bit flags + { + Normal = 0x000, + BillboardXAxis = 0x001, + BillboardYAxis = 0x002, + BillboardZAxis = 0x004, + BillboardObject = (BillboardXAxis | BillboardYAxis | BillboardZAxis), + BlinkObject = 0x008, + IntersectImmune = 0x010 + }; + +// L4VideoObject(); + L4VideoObject( + const char *filename, + ResourceType resource_type, + Enumeration renderer_modes, // RendererModes + float blink_period = 0.0f, + float percent_time_on = 0.0f + ); + ~L4VideoObject(); + + const char* + GetObjectFilename() const + { return objectFilename; } + char* + GetObjectFilename() + { return objectFilename; } + ResourceType + GetResourceType() const + { return resourceType; } + Enumeration // RendererModes + GetRendererModes() const + { return rendererModes; } + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +// private: + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + char + objectFilename[MAX_OBJECT_FILENAME_LENGTH]; + ResourceType + resourceType; + Enumeration // RendererModes + rendererModes; // bit flags (see RendererModes) + float + blinkPeriod, // cycle length in seconds + percentTimeOn; // percent of cycle on +}; + +//########################################################################## +//####################### L4VideoObjectWrapper ####################### +//########################################################################## + +class L4VideoObjectWrapper: + public Plug +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction, Destruction and testing +// +public: +// L4VideoObjectWrapper(); + L4VideoObjectWrapper( + L4VideoObject *video_object, + Logical delete_object = False + ); + ~L4VideoObjectWrapper(); + + L4VideoObject* + GetVideoObject() const + { Check(this); return videoObject; } + + Logical + TestInstance() const; + + static int + BuildVideoObjectChainFromResource( + ChainOf *video_chain, + ResourceDescription *video_resource + ); + static void + DeleteVideoObjectChain( + ChainOf *video_chain + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Implementations +// +// public: + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Private data +// +private: + L4VideoObject + *videoObject; + Logical + deleteObject; +}; + +// +//----------------------------------------------------------------------------- +//--------------Actual DPL video renderer class starts below------------------- +//----------------------------------------------------------------------------- +// +class DPLObjectCacheLine: + public Plug +{ + public: + DPLObjectCacheLine( + const CString &object_name, + dpl_OBJECT *object_ptr) + { + objectName = object_name; + objectPointer = object_ptr; + }; + + ~DPLObjectCacheLine(){}; + + Logical + TestInstance() const + { + Check(&objectName); + Check_Pointer(objectPointer); + + return True; + }; + + CString + objectName; + dpl_OBJECT + *objectPointer; +}; + +class DPLJointToDCSTranslator: + public Plug +{ + public: + DPLJointToDCSTranslator( + Entity *entity, // The entity to translate + dpl_DCS *dcs_array[]); // Array of DCS's to translate + + ~DPLJointToDCSTranslator(); + + Logical + TestInstance() const; + + int + DCSCount; + dpl_DCS + **translation_array; // array to translate from joint # to DCS* +}; + +//########################################################################## +//########################### DPLRenderer ############################ +//########################################################################## +#define DELAY_DCS_FLUSH_ARRAY_SIZE 100 +#define MAX_PSFX_COUNT 40 +#define MAX_INDIE_EMITTERS 32 +class DPLRenderer : + public VideoRenderer +{ +public: + // + // Construction, Destruction and test instance declarations + // + DPLRenderer(HWND hWnd, unsigned int screenWidth, unsigned int screenHeight, bool fullscreen, InterestType interest_type, InterestDepth depth_calibration); + ~DPLRenderer(); + + virtual vector MonitorsCreateAll(int &monitorCount); + + Logical TestInstance() const; + // + // These routines are the renderer side of the culling system, they are + // used to setup the stored data on the eyepoint's transformation matrices + // + inline Scalar GetCurrentFrameTime() { return(currentFrameTime); } // Returns the time at the start of the frame + + inline LinearMatrix* GetWorldToEyeMatrix() { return(&worldToEyeMatrix); } // Returns the world to eye matrix (for culling) + inline Scalar GetViewRatio() { return(viewRatio); } // Returns tan(viewAngle/2.0) + void SetupCull(); // Sets up the WorldToEyeMatrix each frame + // + // These routines manage the renderer's list of renderables that need to be + // executed each frame. For the moment these routines just blindly add and + // remove the items from the dplRenderableSocket + // + void AddDynamicRenderable(Component *my_renderable); + void RemoveDynamicRenderable(Component *my_renderable); + // + // These routines are used for tracking target frame time + // + void ResetStatistics(); + void ReportStatistics(); + // + // Other renderer stuff + // + dpl_ZONE* MakeNewZone(); + + void MarkDCSHiearchy(dpl_DCS *root_DCS, Entity *entity); + void FlushBitSliceTexture(unsigned int *local_storage); + void LoadBitSliceTexture(BitMap *bitmap_to_load, LPDIRECT3DTEXTURE9 local_storage); + + void SetViewAngle(Degree new_angle); + + unsigned int* MakeBitSliceStorage(); + + void SortAndReloadNameBitmaps(); + + void LoadNameBitmaps(); + + void LoadOrdinalBitmaps(); + + void DPLIndependantEffect(Point3D location, // Location of the effect in world space + int effect_number, // DPL effect number to trigger at this location + dpl_DCS *my_dcs = NULL, + int subid = 0); // inserted into third byte of effect id. + + void DPLIndependantPFX(Point3D location, // Location in space to trigger the effect + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // Description of the pfx + dpl_DCS *my_dcs = NULL, // optional DCS to issue from + int subid = 0); // inserted into third byte of effect id. + + void DPLDelayDCSFlush(dpl_DCS *my_dcs); // The DCS we want to remember for later + + void DPLDoDCSBatchFlush(); // Flush the dcs's remembered by DPLDelayDCSFlush + + void DPLReportFreeMemory(std::ostream &output); // Report current free memory in card + + void DPLReportPerfStats(std::ostream &output); // Report performance statistics + + void DPLToggleWireframe(); // Toggle state of dpl wireframe + + void DPLTogglePVision(); // Toggle state of dpl pvision + + void DPLFrameDump(Logical antialias); // Write framedump to targa file + + InnerProjectileRenderable* GetProjectile( + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone); // DPL Zone this stuff will live in (for culling) + + void ReleaseProjectile(InnerProjectileRenderable *inner_projectile); + + int GetUniqueID(); + + dpl_PARTICLESTART_EFFECT_INFO* ReadPSFX(const char *file_name); // Name of the file containing the PSFX description + + dpl_OBJECT* GetCachedObject(const CString &object_name); // Name of the object we want to get + + void PutCachedObject( + const CString &object_name, // Name of the object we will cache + dpl_OBJECT *object_pointer); // pointer to the object being cached + + static ResourceDescription::ResourceID CreateModelVideoStreamResource(ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories *directories); + + void CacheExplosionScripts(int script_select); // The script to be cached + + enum FogStyle + { + updateFogSetting, + noUpdateFogSetting, + searchLightOnFogStyle, + searchLightOffFogStyle, + winnersCircleFogStyle + }; + + void SetFogStyle(FogStyle my_fog); + + void GetCurrentFogSettings(float *fogRed, float *fogGreen, float *fogBlue, float *fogNear, float *fogFar); + void SetCurrentFogLimits(float fogNear, float fogFar); + + LPDIRECT3DTEXTURE9 GetNameTexture(int playerIndex) { return mNameTextures[playerIndex]; } + + inline LPDIRECT3DDEVICE9 GetDevice() { return mDevice; } + inline LPD3DXMATRIXSTACK GetMatrixStack() { return m_MatrixStack; } + inline void AddRenderable(HierarchicalDrawComponent *component) { mRenderables.Add(component); } + void AddToPassList(d3d_OBJECT *object, int pass); + void AddStaticObject(d3d_OBJECT *object); + void RecurseStaticObject(HierarchicalDrawComponent *obj); + virtual void ConsolidateStaticObjects(); + + inline unsigned int GetWidth() { return x_size; } + inline unsigned int GetHeight() { return y_size; } + + inline int *GetSecondaryIndex() { return mSecondaryIndex; } + inline int *GetAux1Index() { return mAux1Index; } + inline int *GetAux2Index() { return mAux2Index; } + +private: + d3d_OBJECT *ConsolidateSingleObject(LPD3DXMESH *meshes, D3DXMATRIX *transforms, UINT startMesh, UINT meshCount, hash_map subsetHash, hash_map hashToOp, vector finalOps); + void ExplosionScripts(Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom view_type, // Type of reference (inside/outside...etc.) + int script_select); + void DPLRenderer::DPLReadINIPage(NotationFile *master_notation_file, const char *starting_page_name, Mission *mission, Logical debug_print); + + void DPLRenderer::DPLReadEnvironment(Mission *mission); + void ShutdownImplementation(); + void SuspendImplementation(); + void ResumeImplementation(); + void ExecuteImplementation(RendererComplexity complexity_update, RendererOrigin::InterestingEntityIterator *iterator); + void ExecuteIdle(); + + hyper HashAdd(hyper input, char data); + hyper HashDrawOp(L4DRAWOP *op); + + //Damn eye renderable is our camera and I hate it +public: + DPLEyeRenderable *mCamera; + float GetCloudRed() { return mCloudRed;} + float GetCloudGreen() { return mCloudGreen;} + float GetCloudBlue() { return mCloudBlue;} + float GetCloudEmitRed() { return mCloudEmitRed; } + float GetCloudEmitGreen() { return mCloudEmitGreen; } + float GetCloudEmitBlue() { return mCloudEmitBlue; } + + void SetCoreRenderStates(); + +private: + // + // Direct3D Required Variables + // + LPDIRECT3DDEVICE9 mDevice; + D3DPRESENT_PARAMETERS mPresentParams; + unsigned int x_size; + unsigned int y_size; + SChainOf mRenderables; + d3d_OBJECT *mRenderLists[PASS_TOTAL_COUNT]; + LPD3DXMATRIXSTACK m_MatrixStack; + D3DXMATRIX mProjectionMatrix; + D3DXMATRIX mDecalProjectionMatrix; + float mDecalEpsilon; + + void FindBestAdapterIndices(bool isWindowed); + + float mCloudRed, mCloudGreen, mCloudBlue; + float mCloudEmitRed, mCloudEmitGreen, mCloudEmitBlue; + + int *mPrimaryIndex, *mSecondaryIndex, *mAux1Index, *mAux2Index; + + // these are used for the map rendering + d3d_OBJECT *mStaticObjectsHead; + int mStaticObjectsCount; + std::list mConsolidatedStaticObjects; + + // name and ordinal texture maps + LPDIRECT3DTEXTURE9 mNameTextures[MAX_PLAYER_NAMES]; + LPDIRECT3DTEXTURE9 mOrdinalTextures[MAX_PLAYER_NAMES]; + +protected: + ReticleRenderable *mReticle; + CameraShipHUDRenderable *mCamShipHUD; + + void LoadMissionImplementation(Mission *mission); + + // + // These variables hold some culling related information + // + + LinearMatrix worldToEyeMatrix; // the current world to eye transform for our linked entity + Scalar currentFrameTime; // the time at the start of renderable execution + + // + // These variables are used for tracking target frame time + // + unsigned long total_cull, + total_draw, + total_pixelplanes, + total_frame_time, + target_frame_time, + frame_count, + target_frame_count; + Logical statistics_started; + Scalar report_time; + // + // The rest of the renderer's variables. + // + + Time StartSample; // For generating a framerate printout + + Logical fogUpdating, + eyeRelative, // True if the eye will be relative to the linked entity origin + completeCycleNeeded; // True when we are waiting for DPL to be ready for the next frame + + int myUniqueID, // Generates a unique 16 bit id value for PSFX use + lastAppState; // For keeping track of what the application is doing + + float aspectRatio, // aspect ratio of the screen + FrameCount, // For keeping track of framerate + // Fog is setup as standard fog used for vehicles without simulated lights + // and used when a vehicle with lights has them switched on. This setting + // is replicated into the "noSearchLight" setting so vehicles with lights + // will always get this setting if the environment doesn't specifically say + // that headlight simulation will work. + fogRed, // Fog setting to use when vehicle lights are on + fogBlue, // This is the default for vehicles with no lights + fogGreen, + fogNear, + fogFar, + currentFogNear, + currentFogFar, + searchLightFogRed, // Fog setting to use when vehicle lights are on + searchLightFogBlue, + searchLightFogGreen, + searchLightFogNear, + searchLightFogFar, + noSearchLightFogRed, // Fog setting to use when vehicle lights are off + noSearchLightFogBlue, + noSearchLightFogGreen, + noSearchLightFogNear, + noSearchLightFogFar, + clipNear, // Near clipping plane (from INI file) + clipFar, // Far clipping plane (from INI file) + backgroundRed, // Background color (from INI file) + backgroundGreen, + backgroundBlue, + viewAngle, // Viewing angle (from INI file) + viewRatio; // This is tan(viewAngle/2.0f) (handy for culling) + + dpl_DCS *dplTestEyeDCS; // A DCS we temporarily hook our eye on (for testing) + + void MakeEntityRenderables(Entity *this_entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom type); // Type of reference (inside/outside...etc.) + + dpl_VIEW *dplMainView; // The DPL view we create at the beginning and use for our eye + + dpl_ZONE *dplDeathZone, // The DPL zone that holds our vehicle (for death effect) + *dplMainZone; // The DPL zone that holds the rest of the world + + Reticle *vehicleReticle; // Pointer to our vehicle's reticle if one exists. + + dpl_DCS *delayDCSFlushArray[DELAY_DCS_FLUSH_ARRAY_SIZE+1]; + int delayedDCSCount; + INDIE_EFFECT myPSFXDescriptons[MAX_PSFX_COUNT]; + ParticleEmitter myPSFXEmitters[MAX_INDIE_EMITTERS]; + // + // This information is captured from the pickpoint when it is enabled + // + dpl_INSTANCE *dplHitInstance; + dpl_DCS *dplHitDCS; + dpl_GEOGROUP *dplHitGeoGroup; + dpl_GEOMETRY *dplHitGeometry; + // + // This information holds the list of projectile renderables + // + SChainOf projectile_list; + // + // This holds the list of cached objects + // + TreeOf dplObjectCacheSocket; + // + // This holds the list of jointed mover DCS tables + // + TableOf dplJointToDCSTranslatorSocket; + // + // This chain contains the list of active renderables + // + SChainOf dplRenderableSocket; + +public: + // + // Store Lights for Later Revision + // +// dpl_LIGHT *ambientLight; + D3DLIGHT9 *sceneLight; // Array of all the lights + + dpl_DCS **sceneLightDCS; // Array of DCS's for Lights + + int sceneLightCount; + + //static UserHeap *DPLHeap; +}; + +extern LPDIRECT3D9 gD3D; diff --git a/MUNGA_L4/L4VIDPER.cpp b/MUNGA_L4/L4VIDPER.cpp new file mode 100644 index 0000000..68e0c97 --- /dev/null +++ b/MUNGA_L4/L4VIDPER.cpp @@ -0,0 +1,477 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4vidper.h" + +//STUBBED: VIDEO RB 1/15/07 +//extern "C" const int32 __sect_time; +//extern "C" const int32 __last_cull_time; +//extern "C" const int32 __last_draw_time; +//extern "C" const int32 __last_frame_time; +//extern "C" const int32 __last_pxpl_time; +//extern "C" const int32 __last_frame_prims; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the StripChartRenderable +// Used to performance monitor a variable that can change every frame +// +StripChartRenderable::StripChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int *value_to_chart, // the value we will be graphing + int update_interval // How frequently (in frames) to update the graphics +): + VideoRenderable(entity, execution_type) +{ + //STUBBED: DPL RB 1/14/07 + //int + // i; + //// + //// Save the incoming data inside this class + //// + //myView = this_view; + //myLeft = left; + //myRight = right; + //myTop = top; + //myBottom = bottom; + //myMaxSamples = max_samples; + //myMaxValue = max_value; + //myMinValue = min_value; + //myValue = value_to_chart; + //myUpdateInterval = update_interval; + //myFrameCount = 0; + //myCurrentSample = 0; + //// + //// Allocate the RAM to store the values we are charting and clear them out + //// + //myValueStorage = new int[max_samples]; + //if(!myValueStorage) + // Fail("stripchart couldn't allocate value storage\n"); + + //Check_Pointer(myValueStorage); + //for(i = 0; i= myUpdateInterval) + //{ + // myFrameCount = 0; + // // + // // Figure the scale factor for the graph + // // + // float + // current_x, + // current_y, + // x_increment, + // y_increment; + // x_increment = (myRight - myLeft)/ (float)(myMaxSamples); + // y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue); + // dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear); + // dpl2d_AddFullScreenClipRegion (myDisplayList); + // dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f); + // dpl2d_AddOpenPolyline (myDisplayList); + // dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + // dpl2d_AddPoint (myDisplayList, myRight, myBottom); + // dpl2d_AddPoint (myDisplayList, myRight, myTop); + // dpl2d_AddPoint (myDisplayList, myLeft, myTop); + // dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + // dpl2d_AddClosePolyline (myDisplayList); + // dpl2d_AddOpenPolyline (myDisplayList); + // current_x = myLeft; + // for(i = 0; i < myMaxSamples; i++) + // { + // current_y = myBottom-((float)myValueStorage[i] * y_increment); + // dpl2d_AddPoint(myDisplayList,current_x,current_y); + // current_x += x_increment; + // } + // dpl2d_AddClosePolyline (myDisplayList); + // dpl2d_AddOpenLines (myDisplayList); + // dpl2d_AddPoint (myDisplayList, + // myLeft + (x_increment*myCurrentSample), + // myBottom); + // dpl2d_AddPoint (myDisplayList, + // myLeft + (x_increment*myCurrentSample), + // myTop); + // dpl2d_AddCloseLines (myDisplayList); + // dpl2d_CloseDisplayList (myDisplayList); + // dpl2d_FlushDisplayList (myDisplayList); + //} + //// + //// Update the current sample pointer + //// + //myCurrentSample ++; + //if(myCurrentSample >= myMaxSamples) + // myCurrentSample = 0; + + //// + //// Call the execute method in our parent + //// + //VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the RendererChartRenderable +// Used to performance monitor a variable that can change every frame +// +RendererChartRenderable::RendererChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int update_interval // How frequently (in frames) to update the graphics +): + VideoRenderable(entity, execution_type) +{ + //STUBBED: DPL RB 1/14/07 + //int + // i; + //// + //// Save the incoming data inside this class + //// + //myView = this_view; + //myLeft = left; + //myRight = right; + //myTop = top; + //myBottom = bottom; + //myMaxSamples = max_samples; + //myMaxValue = max_value; + //myMinValue = min_value; + //myUpdateInterval = update_interval; + //myFrameCount = 0; + //myCurrentSample = 0; + //// + //// Allocate the RAM to store the values we are charting and clear them out + //// + //myCullStorage = new int[max_samples]; + //myDrawStorage = new int[max_samples]; + //myFrameStorage = new int[max_samples]; + //myPixelPlanesStorage = new int[max_samples]; + //myPrimativeStorage = new int[max_samples]; + //if(!myCullStorage || !myDrawStorage || !myFrameStorage || !myPixelPlanesStorage || !myPrimativeStorage) + // Fail("RendererChartRenderable couldn't allocate storage\n"); + + //Check_Pointer(myValueStorage); + //for(i = 0; i= myUpdateInterval) + //{ + // myFrameCount = 0; + // // + // // Figure the scale factor for the graph + // // + // float + // current_x, + // current_y, + // x_increment, + // y_increment; + // x_increment = (myRight - myLeft)/ (float)(myMaxSamples); + // y_increment = (myBottom - myTop)/((float)myMaxValue - (float)myMinValue); + // dpl2d_OpenDisplayList (myDisplayList, dpl2d_open_mode_clear); + // dpl2d_AddFullScreenClipRegion (myDisplayList); + // dpl2d_AddSetLineWidth (myDisplayList,1.0); + // dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f); + // dpl2d_AddOpenPolyline (myDisplayList); + // dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + // dpl2d_AddPoint (myDisplayList, myRight, myBottom); + // dpl2d_AddPoint (myDisplayList, myRight, myTop); + // dpl2d_AddPoint (myDisplayList, myLeft, myTop); + // dpl2d_AddPoint (myDisplayList, myLeft, myBottom); + // dpl2d_AddClosePolyline (myDisplayList); + // // + // // Draw the primative count trace + // // + // dpl2d_AddOpenLines (myDisplayList); + // dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (500.0f * y_increment * 50.0f)); + // dpl2d_AddPoint(myDisplayList,myRight, myBottom + (500.0f * y_increment * 50.0f)); + // dpl2d_AddPoint(myDisplayList,myLeft, myBottom + (1000.0f * y_increment * 50.0f)); + // dpl2d_AddPoint(myDisplayList,myRight, myBottom + (1000.0f * y_increment * 50.0f)); + // dpl2d_AddCloseLines (myDisplayList); + // dpl2d_AddOpenPolyline (myDisplayList); + // current_x = myLeft; + // for(i = 0; i < myMaxSamples; i++) + // { + // current_y = myBottom+((float)myPrimativeStorage[i] * y_increment * 50.0f); + // dpl2d_AddPoint(myDisplayList,current_x,current_y); + // current_x += x_increment; + // } + // dpl2d_AddClosePolyline (myDisplayList); + // // + // // Draw the frame time trace + // // + // dpl2d_AddSetColor (myDisplayList, 0.75f, 0.75f, 0.75f); + // dpl2d_AddOpenPolyline (myDisplayList); + // current_x = myLeft; + // for(i = 0; i < myMaxSamples; i++) + // { + // current_y = myBottom-((float)myFrameStorage[i] * y_increment); + // dpl2d_AddPoint(myDisplayList,current_x,current_y); + // current_x += x_increment; + // } + // dpl2d_AddClosePolyline (myDisplayList); + // // + // // Draw the draw time trace + // // + // dpl2d_AddSetColor (myDisplayList, 0.75f, 0.0f, 0.0f); + // dpl2d_AddOpenPolyline (myDisplayList); + // current_x = myLeft; + // for(i = 0; i < myMaxSamples; i++) + // { + // current_y = myBottom-((float)myDrawStorage[i] * y_increment); + // dpl2d_AddPoint(myDisplayList,current_x,current_y); + // current_x += x_increment; + // } + // dpl2d_AddClosePolyline (myDisplayList); + // // + // // Draw the pixel planes time trace + // // + // dpl2d_AddSetColor (myDisplayList, 0.0f, 0.0f, 0.75f); + // dpl2d_AddOpenPolyline (myDisplayList); + // current_x = myLeft; + // for(i = 0; i < myMaxSamples; i++) + // { + // current_y = myBottom-((float)myPixelPlanesStorage[i] * y_increment); + // dpl2d_AddPoint(myDisplayList,current_x,current_y); + // current_x += x_increment; + // } + // dpl2d_AddClosePolyline (myDisplayList); + // // + // // Stack the cull time on top of the draw + // // + // dpl2d_AddSetColor (myDisplayList, 0.0f, 0.75f, 0.0f); + // dpl2d_AddOpenPolyline (myDisplayList); + // current_x = myLeft; + // for(i = 0; i < myMaxSamples; i++) + // { + // current_y = myBottom-(((float)myCullStorage[i] + (float)myDrawStorage[i]) * y_increment); + // dpl2d_AddPoint(myDisplayList,current_x,current_y); + // current_x += x_increment; + // } + // dpl2d_AddClosePolyline (myDisplayList); + // // + // // Draw a line indicating the current time + // // + // dpl2d_AddOpenLines (myDisplayList); + // dpl2d_AddPoint (myDisplayList, + // myLeft + (x_increment*myCurrentSample), + // myBottom); + // dpl2d_AddPoint (myDisplayList, + // myLeft + (x_increment*myCurrentSample), + // myTop); + // dpl2d_AddCloseLines (myDisplayList); + // // + // // If there is a pre existing dlist, insert a call to it here + // // + // if(mySystemDisplayList) + // { + // dpl2d_AddCallDisplayList (myDisplayList, mySystemDisplayList ); + // } + // // + // // Close up the display list and flush it + // // + // dpl2d_CloseDisplayList (myDisplayList); + // dpl2d_FlushDisplayList (myDisplayList); + //} + //// + //// Update the current sample pointer + //// + //myCurrentSample ++; + //if(myCurrentSample >= myMaxSamples) + // myCurrentSample = 0; + + //// + //// Call the execute method in our parent + //// + //VideoRenderable::Execute(); +} diff --git a/MUNGA_L4/L4VIDPER.h b/MUNGA_L4/L4VIDPER.h new file mode 100644 index 0000000..79954a4 --- /dev/null +++ b/MUNGA_L4/L4VIDPER.h @@ -0,0 +1,117 @@ +#pragma once + +#include "l4vidrnd.h" +#include "..\munga\rotation.h" +#include "..\munga\reticle.h" +#include "..\munga\simulate.h" +#include "..\munga\linmtrx.h" + +// RB 1/14/07 +//#include +//#include +//#include + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// StripChartRenderable +// +class StripChartRenderable: + public VideoRenderable +{ + public: + StripChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int *value_to_chart, // the value we will be graphing + int update_interval); // How frequently (in frames) to update the graphics + + ~StripChartRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_VIEW + *myView; + dpl2d_DISPLAY + *mySystemDisplayList, + *myDisplayList; + int + myMaxSamples, + myMaxValue, + myMinValue, + *myValue, + *myValueStorage, + myUpdateInterval, + myFrameCount, + myCurrentSample; + float + myLeft, + myRight, + myTop, + myBottom; + +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RendererChartRenderable +// +class RendererChartRenderable: + public VideoRenderable +{ + public: + RendererChartRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_VIEW *this_view, // the view associated with our eye + float left, + float right, + float top, + float bottom, + int max_samples, // The number of samples to hold + int max_value, // The maximum value allowed + int min_value, // the minimum value allowed + int update_interval); // How frequently (in frames) to update the graphics + + ~RendererChartRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_VIEW + *myView; + dpl2d_DISPLAY + *mySystemDisplayList, + *myDisplayList; + int + *myCullStorage, + *myDrawStorage, + *myFrameStorage, + *myPixelPlanesStorage, + *myPrimativeStorage, + myMaxSamples, + myMaxValue, + myMinValue, + myUpdateInterval, + myFrameCount, + myCurrentSample; + float + myLeft, + myRight, + myTop, + myBottom; + +}; \ No newline at end of file diff --git a/MUNGA_L4/L4VIDRND.cpp b/MUNGA_L4/L4VIDRND.cpp new file mode 100644 index 0000000..0a47997 --- /dev/null +++ b/MUNGA_L4/L4VIDRND.cpp @@ -0,0 +1,7317 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4vidrnd.h" +#include "..\munga\vector2d.h" +#include "..\munga\matrix.h" +#include "..\munga\mover.h" +#include "..\munga\player.h" +#include "l4video.h" +#include "..\munga\nttmgr.h" +#include "l4app.h" +#include "..\RP\VTV.h" + +// RB 1/14/07 +//#include +//#include +//#include +//#include +//#include + +#if defined(TRACE_VIDEO_MECH_CULL_RENDERABLE) + static BitTrace Video_Mech_Cull_Renderable("Video Mech Cull Renderable"); + #define SET_VIDEO_MECH_CULL_RENDERABLE() Video_Mech_Cull_Renderable.Set() + #define CLEAR_VIDEO_MECH_CULL_RENDERABLE() Video_Mech_Cull_Renderable.Clear() +#else + #define SET_VIDEO_MECH_CULL_RENDERABLE() + #define CLEAR_VIDEO_MECH_CULL_RENDERABLE() +#endif + +// +// Below allows the use of DPLDelayDCSFlush to be on or off +// +#if 1 +# define HACK_DPL_FLUSH_DCS(a)\ + {L4Application *l4_application = Cast_Object(L4Application*, application);\ + Check(l4_application);\ + l4_application->GetVideoRenderer()->DPLDelayDCSFlush(a);} +# define DPL_FLUSH_DCS(a)\ + {myRenderer->DPLDelayDCSFlush(a);} +#else +# define DPL_FLUSH_DCS(a)\ + dpl_FlushDCS(a) +# define HACK_DPL_FLUSH_DCS(a)\ + dpl_FlushDCS(a) +#endif + +// +// All renderables that need to use "Now()" should use renderer frame time +// as it should be much quicker (it returns the time at the start of the +// frame execution. All the renderables should know which renderer they belong +// to, but since many don't, this macro will supply the time from the default one +// +#define GET_CURRENT_FRAME_TIME() \ +{L4Application *l4_application = Cast_Object(L4Application*, application);\ +Check(l4_application);\ +l4_application->GetVideoRenderer()->GetCurrentFrameTime();} + +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +// All the stuff between these big ugly bars is the new video component stuff// +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +HierarchicalDrawComponent::HierarchicalDrawComponent(RegisteredClass::ClassID classId) +:Component(classId), isDeathDraw(false) +{ + L4Application *l4_application = Cast_Object(L4Application*, application); + myRenderer = l4_application->GetVideoRenderer(); + m_parent = NULL; +} + +HierarchicalDrawComponent::HierarchicalDrawComponent(RegisteredClass::ClassID classId, HierarchicalDrawComponent *parent) +:Component(classId), isDeathDraw(false), graphicalObject(NULL) +{ + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + myRenderer = l4_application->GetVideoRenderer(); + + m_parent = parent; + + if (m_parent != NULL) + { + m_parent->addChild(this); + } +} + +HierarchicalDrawComponent::~HierarchicalDrawComponent() +{ + if (m_parent != NULL) + { + m_parent->removeChild(this); + } + + for (int i=0; i < m_children.size(); i++) + { + m_children[i]->clearParent(); + } + + m_children.clear(); +} + +void HierarchicalDrawComponent::ExecuteChildren() +{ + std::vector::iterator iter = m_children.begin(); + + while(iter != m_children.end()) + { + (*iter)->Execute(); + iter++; + } +} + +std::vector::const_iterator HierarchicalDrawComponent::Enumerate() +{ + return this->m_children.begin(); +} + +std::vector::const_iterator HierarchicalDrawComponent::End() +{ + return this->m_children.end(); +} + +void HierarchicalDrawComponent::ResetDrawObj() +{ + this->graphicalObject = NULL; +} + +void HierarchicalDrawComponent::Execute() +{ + ExecuteChildren(); + + if (graphicalObject != NULL) + { + if (isDeathDraw || !l4_application->IsDead()) + { + bool addedToOpaqueList = false, addedToAlphaList = false, addedToDecalList = false, addedToSphereList = false, addedToSkyList = false; + for (int i=0; iGetDrawOpCount(); i++) + { + if (graphicalObject->GetDrawOp(i)->alphaTest) + { + if (!addedToAlphaList) + { + myRenderer->AddToPassList(graphicalObject, PASS_ALPHABLEND); + addedToAlphaList = true; + } + } + else if (graphicalObject->GetDrawOp(i)->drawAsDecal) + { + if (!addedToDecalList) + { + myRenderer->AddToPassList(graphicalObject, PASS_DECAL); + addedToDecalList = true; + } + } + else if (graphicalObject->GetDrawOp(i)->drawAsSky) + { + if (!addedToSkyList) + { + myRenderer->AddToPassList(graphicalObject, PASS_SKY); + addedToSkyList = true; + } + } + else if (graphicalObject->GetMesh() == NULL) + { + if (!addedToSphereList) + { + myRenderer->AddToPassList(graphicalObject, PASS_SPHERE); + addedToSphereList = true; + } + } + else + { + if (!addedToOpaqueList) + { + myRenderer->AddToPassList(graphicalObject, PASS_OPAQUE); + addedToOpaqueList = true; + } + } + } + } + } +} + +void HierarchicalDrawComponent::Render(int pass, const D3DXMATRIX *viewTransform) +{ + //if (graphicalObject != NULL && (isDeathDraw || l4_application->GetMissionPlayer()->GetPlayerVehicle()->GetSimulationState() != VTV::BurningState)) + //{ + // myRenderer->GetDevice()->SetTransform(D3DTS_WORLD, &myLocalToWorld); + // graphicalObject->Draw(pass, &myLocalToWorld, viewTransform); + //} + + //std::vector::iterator iter = m_children.begin(); + + //while (iter != m_children.end()) + //{ + // (*iter)->Render(pass, viewTransform); + // iter++; + //} +} + +void HierarchicalDrawComponent::addChild(HierarchicalDrawComponent *child) +{ + m_children.insert(m_children.end(), child); +} + +void HierarchicalDrawComponent::removeChild(HierarchicalDrawComponent *child) +{ + //Seek and remove + std::vector::iterator iter = m_children.begin(); + + while(iter != m_children.end()) + { + if (child == (*iter)) + { + m_children.erase(iter); + child->clearParent(); + break; + } + iter++; + } +} + +void HierarchicalDrawComponent::clearParent() +{ + m_parent = NULL; +} + +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~This is a special class to speed up projectiles~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for InnerProjectileRenderable +// +InnerProjectileRenderable::InnerProjectileRenderable( + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone // DPL Zone this stuff will live in (for culling) +): + HierarchicalDrawComponent(TrivialNodeClassID) // Inherited constructor +{ + isDeathDraw = isDeathZone; + graphicalObject = graphical_object; + //STUBBED: DPL RB 1/14/07 + //// + //// Check incoming data + //// + //Check_Pointer(this_zone); + //Check_Pointer(graphical_object); + //// + //// Construct the hiearchy the projectile needs to be renderable + //// + //myDCS = dpl_NewDCS (); + //myInstance = dpl_NewInstance(); + //Check_Pointer (myDCS); + //Check_Pointer (myInstance); + //dpl_SetDCSZone (myDCS, this_zone); + //dpl_SetInstanceObject (myInstance, graphical_object); + //dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj ); + //dpl_SetInstanceSectMask (myInstance, NULL ); + //dpl_SetInstanceVisibility (myInstance, 1 ); + //dpl_AddInstanceToDCS (myDCS, myInstance ); + //dpl_AddDCSToScene (myDCS ); + //dpl_FlushInstance (myInstance); + //dpl_FlushDCS (myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for InnerProjectileRenderable +// +InnerProjectileRenderable::~InnerProjectileRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Delete the instance(s) hanging on the DCS (if any) + //// NOTE: we may want to iterate through all the instances here using DPL routines + //// + //dpl_RemoveInstanceFromDCS(myDCS, myInstance); + //dpl_RemoveDCSFromScene(myDCS); + //dpl_DeleteInstance(myInstance); + //// + //// Delete the DCS + //// + //dpl_DeleteDCS(myDCS); + //myDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the InnerProjectileRenderable +// +Logical + InnerProjectileRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + Component::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myInstance); + Check_Pointer(myDCS); + return True; +} + +void InnerProjectileRenderable::Execute() +{ + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + HierarchicalDrawComponent::Execute(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ProjectileRootRenderable +// +ProjectileRootRenderable::ProjectileRootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone // DPL Zone this stuff will live in (for culling) +): +VideoRenderable(entity, execution_type) +{ + isDeathDraw = isDeathZone; + // + // Check the incoming pointers + // + Check_Pointer(graphical_object); + //Check_Pointer(this_zone); + // + // Get a projectile renderable we can use + // + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + myInnerProjectile = l4_application->GetVideoRenderer()->GetProjectile( + graphical_object, + isDeathZone); + Check(myInnerProjectile); + addChild(myInnerProjectile); + oldLocalToWorld = myEntity->localToWorld; + transMatrix = myEntity->localToWorld; + + ////This is necessary? + //myRenderer->mRenderables.Add(this); + l4_application->GetVideoRenderer()->AddRenderable(this); + + // + // Set the DCS matrix and std::flush it + // + + //float32* tempMatrix = dpl_GetDCSMatrix( myInnerProjectile->GetDCS()); + //Check_Pointer ( tempMatrix ); + //*(Matrix4x4*)tempMatrix = myEntity->localToWorld; + //DPL_FLUSH_DCS ( myInnerProjectile->GetDCS()); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ProjectileRootRenderable +// +ProjectileRootRenderable::~ProjectileRootRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // return our inner renderable to the pool + // + Point3D infinity(0.0f, 10000.0f, 0.0f); + transMatrix = infinity; + //float32* tempMatrix = dpl_GetDCSMatrix(myInnerProjectile->GetDCS()); + //Check_Pointer (tempMatrix); + //*(Matrix4x4*)tempMatrix = infinity; + //DPL_FLUSH_DCS ( myInnerProjectile->GetDCS() ); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->ReleaseProjectile(myInnerProjectile); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ProjectileRootRenderable +// +Logical + ProjectileRootRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check(&oldLocalToWorld); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ProjectileRootRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ProjectileRootRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // If our entity has changed it's localToWorld matrix, update DPL + // + if(oldLocalToWorld != myEntity->localToWorld) + { + oldLocalToWorld = myEntity->localToWorld; + transMatrix = oldLocalToWorld; + } + //// + //// Call the next lower execute method + //// + //#if DEBUG_LEVEL > 0 + //VideoRenderable::Execute(); + //#endif + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrix(&transMatrix.ToD3DMatrix()); + VideoRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLObjectWrapper +// +DPLObjectWrapper::DPLObjectWrapper( + Entity *entity, // Entity to attach the renderable to + const CString &name, // Name of the DPL object to load into the wrapper + dpl_LOAD_MODE cache_mode // DPL Zone this stuff will live in (for culling) +): +VideoRenderable(entity, DPLObjectWrapper::Static) +{ + //STUBBED: DPL RB 1/14/07 + // + // Check the incoming pointers + // + Check(&name); + + myDPLObject = d3d_OBJECT::LoadObject(myRenderer->GetDevice(),(char*)name); + myDPLObjectName = name; + //// + //// Load the DPL object into the wrapper, try to get the object pointer from + //// the cache, if it isn't there, do a regular load. + //// + //if(cache_mode == dpl_load_nocache) + //{ + // L4Application *l4_application = Cast_Object(L4Application*, application); + // Check(l4_application); + // myDPLObject = l4_application->GetVideoRenderer()->GetCachedObject(name); + // if(!myDPLObject) + // { + // myDPLObject = dpl_LoadObject(name, cache_mode); + // } + //} + //else + //{ + // myDPLObject = dpl_LoadObject(name, cache_mode); + //} + //myCacheMode = cache_mode; + //myDPLObjectName = name; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLObjectWrapper +// +DPLObjectWrapper::~DPLObjectWrapper() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Handle the unloading of DPL objects + //// + //if(myCacheMode == dpl_load_nocache) + //{ + // // + // // If this object was not cached, we will eventually return it to the video + // // renderer's list of unused uncached objects for later use by someone else + // // + // L4Application *l4_application = Cast_Object(L4Application*, application); + // Check(l4_application); + // l4_application->GetVideoRenderer()->PutCachedObject(myDPLObjectName, myDPLObject); + //} + //else + //{ + // // + // // Do nothing (should unload the object) + // // + // //dpl_UnloadObject(myDPLObject); + //} + myDPLObject = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLObjectWrapper +// +Logical + DPLObjectWrapper::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myDPLObject); + Check(&myDPLObjectName); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLObjectWrapper +// Nothing to execute here so we just pass it down to the next lower level. +// +void + DPLObjectWrapper::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Call the next lower execute method + // + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~New Class Hiearchy for Renderables~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for VideoRenderable +// +VideoRenderable::VideoRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + HierarchicalDrawComponent *parent +): + HierarchicalDrawComponent(TrivialNodeClassID, parent) // Inherited constructor +{ + // + // Check incoming data + // + Check(entity); + // + // Remember the entity and execution type + // + myEntity = entity; + myExecutionType = execution_type; + // + // HACK HACK HACK + // This initializes the video renderable's pointer back to the renderer that + // owns it so it can get information from that renderer. The renderer pointer + // really should be passed in as an argument, this is a concession to avoid + // spending the time to edit all references to the renderer so they support + // a new argument. This will be fixed later, for now we know there is only + // on renderer so we grab the application pointer and get the video renderer + // from it. + // + // SB - moved to HierarchicalDrawComponent + // + // Register us as static or dynamic + // + switch(myExecutionType) + { + case Static: + myEntity->AddStaticVideoComponent(this); + break; + case Dynamic: +// myEntity->AddDynamicVideoComponent(this); + myEntity->AddStaticVideoComponent(this); + myRenderer->AddDynamicRenderable(this); + break; + case Watcher: + myEntity->AddStaticVideoComponent(this); + break; + case Dependant: + myEntity->AddStaticVideoComponent(this); + break; + default: + Fail("VideoRenderable--Illegal execution type\n"); + break; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for VideoRenderable +// +VideoRenderable::~VideoRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); + // + // Nothing else to do here + // +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the VideoRenderable +// +Logical + VideoRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + Component::TestInstance(); + // + // Test our own variables + // + Check(myEntity); + Check(myRenderer); + Verify(myExecutionType >= Static && myExecutionType <= Dependant); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the VideoRenderable +// This method just checks to be sure we are not trying to execute a static +// renderable, then returns. +// +void VideoRenderable::Execute() +{ + // if we're a static renderable then only execute the + // children and don't add ourselves to any render lists + //if (myExecutionType == Static) + // HierarchicalDrawComponent::ExecuteChildren(); + //else + HierarchicalDrawComponent::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the ChildLightRenderable +// +// This renderable is used to connect a light as a child of an existing DCS +// the light isn't setup to move on it's own and creates a DCS only for the +// purpose of offsetting it from it's parent. +// +ChildLightRenderable::ChildLightRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Scalar red, // light color + Scalar green, + Scalar blue, + Scalar inner_radius, + Scalar outer_radius, + dpl_LIGHT_TYPE light_type, + int light_mask +): + VideoRenderable(entity, execution_type, parent) +{ + isDeathDraw = isDeathZone; +//STUBBED: DPL RB 1/14/07 +// // +// // Check the inbound data +// // +// Check_Pointer(this_zone); +// Check_Pointer(parent_DCS); +// Check(offset_matrix); +// // +// // Remember the interesting parameters +// // +// myZone = this_zone; +// myParentDCS = parent_DCS; + myOffsetMatrix = *offset_matrix; +// // +// // Create the dpl DCS and the light that we will be using +// // +// myDCS = dpl_NewDCS (); +// myLight = dpl_NewLight(); +// Check_Pointer(myDCS); +// Check_Pointer(myLight); +// // +// // Setup light type and color +// // +// dpl_SetLightType (myLight, light_type ); +// dpl_SetLightColor (myLight, red, green, blue ); +// dpl_SetLightDCS (myLight, myDCS ); +// dpl_SetLightRadii (myLight, inner_radius, outer_radius ); +// dpl_SetLightLightingMask (myLight, light_mask); +// // +// // Connect the DCS just created to a parent +// // +// dpl_AddDCSToDCS ( myParentDCS, myDCS ); +// // +// // Set the DCS into the requested zone for culling +// // +// dpl_SetDCSZone ( myDCS, this_zone ); +// // +// // Load up the DCS matrix with the supplied matrix +// // +// float32* tempMatrix = dpl_GetDCSMatrix(myDCS); +// Check_Pointer(tempMatrix); +// *(Matrix4x4*)tempMatrix = myOffsetMatrix; +// // +// // Flip the light around to point the correct direction +// // +//// dpl_RotateDCS ( myDCS, 180.0f, dpl_Y ); +// // +// // Flush out the instance and DCS +// // +// dpl_FlushLight ( myLight); +// dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ChildLightRenderable +// +ChildLightRenderable::~ChildLightRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //Check(this); + //dpl_DeleteDCS(myDCS); + //dpl_DeleteLight(myLight); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ChildLightRenderable +// +Logical + ChildLightRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer(myDCS); + Check_Pointer(myParentDCS); + Check_Pointer(myLight); + Check(&myOffsetMatrix); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for ChildLightRenderable +// +void ChildLightRenderable::Execute() +{ + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&myOffsetMatrix.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + //Do something with light? + VideoRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DCSObjectRenderable +// +DCSObjectRenderable::DCSObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent +): + VideoRenderable(entity, execution_type, parent) +{ + isDeathDraw = isDeathZone; + // + // Check incoming data + // + #if DEBUG_LEVEL > 0 + if(graphical_object) + Check_Pointer(graphical_object); // allowed to be null + #endif + Check_Pointer(this_zone); + // + // Remember my d3d object, intersect and offset data + // + graphicalObject = graphical_object; + //myDPLZone = this_zone; + myIntersectMode = intersect_mode; + myIntersectMask = intersect_mask; + myDCS = NULL; + myInstance = NULL; + // + // We need to construct a DCS node here and remember it. The next class up is + // expected to handle the std::flushing and connecting of structure so we just setup + // the DCS and zone information here, leaving std::flushing to someone else. + // +// myDCS = dpl_NewDCS (); + + Check_Pointer ( myDCS ); +// dpl_SetDCSZone ( myDCS, myDPLZone ); + // + // Construct the instance(s) and hang them on the DCS. Since we may be building + // more than one instance, we have to take care of std::flushing them here. + // + if(myD3DObject) + { +// myInstance = dpl_NewInstance(); + + Check_Pointer ( myInstance); +// dpl_SetInstanceObject ( myInstance, myDPLObject); +// dpl_SetInstanceIntersect ( myInstance, myIntersectMode ); +// dpl_SetInstanceSectMask ( myInstance, myIntersectMask ); +// dpl_SetInstanceVisibility ( myInstance, 1 ); +// dpl_AddInstanceToDCS ( myDCS, myInstance ); + +// dpl_FlushInstance ( myInstance ); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DCSObjectRenderable +// +DCSObjectRenderable::~DCSObjectRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Delete the instance(s) hanging on the DCS (if any) + //// NOTE: we may want to iterate through all the instances here using DPL routines + //// + //if(myInstance) + //{ + // dpl_RemoveInstanceFromDCS(myDCS, myInstance); + // dpl_DeleteInstance(myInstance); + //} + //// + //// Delete the DCS + //// + //dpl_DeleteDCS(myDCS); + //myDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DCSObjectRenderable +// +Logical + DCSObjectRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + #if DEBUG_LEVEL > 0 + if(myDPLObject) + Check_Pointer(myDPLObject); + if(myInstance) + Check_Pointer(myInstance); + #endif + Check_Pointer(myDPLZone); + Check_Pointer(myDCS); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DCSObjectRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void DCSObjectRenderable::Execute() +{ + //// + //// Check our variables + //// + //Check(this); + //// + //// Call the next lower execute method + //// + //#if DEBUG_LEVEL > 0 + //VideoRenderable::Execute(); + // #endif + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + + //HierarchicalDrawComponent::Execute(); + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DCSInstanceRenderable +// +DCSInstanceRenderable::DCSInstanceRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to connect to the instance + HierarchicalDrawComponent *parent, // the DCS to add the instance to + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + Logical visible // initial visibility setting +): + VideoRenderable(entity, execution_type, parent) +{ + // + // Check incoming data + // + Check_Pointer(graphical_object); + Check_Pointer(parent_DCS); + // + // Remember my dpl object, intersect and offset data + // + graphicalObject = graphical_object; + myIntersectMode = intersect_mode; + myIntersectMask = intersect_mask; +// myDCS = parent_DCS; + //myInstance = dpl_NewInstance(); + Check_Pointer(myInstance); + // + // Construct the instance(s) and hang them on the parent DCS + // + //dpl_SetInstanceObject ( myInstance, myDPLObject); + //dpl_SetInstanceIntersect ( myInstance, myIntersectMode ); + //dpl_SetInstanceSectMask ( myInstance, myIntersectMask ); + //dpl_SetInstanceVisibility ( myInstance, visible ); + //dpl_AddInstanceToDCS ( myDCS, myInstance ); + //dpl_FlushInstance ( myInstance ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DCSInstanceRenderable +// +DCSInstanceRenderable::~DCSInstanceRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Disconnect the instance from the DCS and delete the instance + //// + //dpl_RemoveInstanceFromDCS(myDCS, myInstance); + //dpl_DeleteInstance(myInstance); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DCSInstanceRenderable +// +Logical + DCSInstanceRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myDPLObject); + Check_Pointer(myInstance); + Check_Pointer(myDCS); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DCSInstanceRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + DCSInstanceRenderable::Execute() +{ + //// + //// Check our variables + //// + //Check(this); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + //HierarchicalDrawComponent::Execute(); + //// + //// Call the next lower execute method + //// + //#if DEBUG_LEVEL > 0 + //VideoRenderable::Execute(); + //#endif + + myRenderer->GetMatrixStack()->Push(); + //myRenderer->GetMatrixStack()->MultMatrixLocal(&OrientationMatrix.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + VideoRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for RootRenderable +// +RootRenderable::RootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask // intersection mask for the object +): +DCSObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask) // intersection mask for the object +{ + // + // All the incoming data will have been checked by DCSObjectRenderable + // already, so we don't have to check anything locally. + // + // + // Initialize our variables + // + oldLocalToWorld = myEntity->localToWorld; + // + // Now we finish the work of hooking up and initializing the root renderable + // Add the DCS to the scene and initialize it's matrix with the localToWorld + // transformation from our entity + // + + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddRenderable(this); + + // dpl_AddDCSToScene ( myDCS ); + +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// *(Matrix4x4*)tempMatrix = myEntity->localToWorld; + +// dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for RootRenderable +// +RootRenderable::~RootRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Remove the DCS from the scene, deletion of the DCS and it's instances is + //// handled by our parent class. + //// + //dpl_RemoveDCSFromScene(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the RootRenderable +// +Logical + RootRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check(&oldLocalToWorld); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the RootRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + RootRenderable::Execute() +{ + // + // Check our variables + // + Check(this); +// We don't need to do this because we're going to use the matrix directly +// // +// // If our entity has changed it's localToWorld matrix, update DPL +// // +// if(oldLocalToWorld != myEntity->localToWorld) +// { +// oldLocalToWorld = myEntity->localToWorld; +// float32* tempMatrix = dpl_GetDCSMatrix(myDCS); +// Check_Pointer (tempMatrix); +// *(Matrix4x4*)tempMatrix = oldLocalToWorld; +// DPL_FLUSH_DCS ( myDCS ); +// } + myRenderer->GetMatrixStack()->Push(); + Matrix4x4 tempMatrix; + tempMatrix = myEntity->localToWorld; + + myRenderer->GetMatrixStack()->MultMatrix(&tempMatrix.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + + DCSObjectRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ChildOffsetRenderable +// +ChildOffsetRenderable::ChildOffsetRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix // offset matrix to be applied prior to joint DCS +): +DCSObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent) +{ + // + // Check incoming data not handled by lower levels + // + Check(offset_matrix); + // + // Remember my offset matrix + // + myOffsetMatrix = *offset_matrix; + myOffsetDCS = NULL; + //myParentDCS = parent_DCS; + // + // We construct the offset DCS node and link the DCS carrying our our + // graphical instances to it. + // +// myOffsetDCS = dpl_NewDCS (); + Check_Pointer ( myOffsetDCS ); +// dpl_SetDCSZone ( myDCS, myDPLZone ); +// dpl_AddDCSToDCS ( myOffsetDCS, myDCS ); + // + // Now we connect that DCS to our parent + // +// dpl_AddDCSToDCS ( myParentDCS, myOffsetDCS); + // + // Then fill in the offset DCS and std::flush it + // +// float32* tempMatrix = dpl_GetDCSMatrix( myOffsetDCS ); +// Check_Pointer ( tempMatrix ); +// *(Matrix4x4*)tempMatrix = myOffsetMatrix; +// dpl_FlushDCS ( myOffsetDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ChildOffsetRenderable +// +ChildOffsetRenderable::~ChildOffsetRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Delete the connection to our parent DCS + //// + //dpl_RemoveDCSFromDCS(myParentDCS, myOffsetDCS); + //// + //// Delete the static DCS and it's connections to the dynamic one + //// + //dpl_RemoveDCSFromDCS(myOffsetDCS, myDCS); + //dpl_DeleteDCS(myOffsetDCS); + //myOffsetDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ChildOffsetRenderable +// +Logical + ChildOffsetRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myParentDCS); + Check_Pointer(myOffsetDCS); + Check(&myOffsetMatrix); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ChildOffsetRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ChildOffsetRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Call the next lower execute method + // + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&myOffsetMatrix.ToD3DMatrix()); + DCSObjectRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for HingeRenderable +// +#define SINGLE_AXIS_HINGE True + +HingeRenderable::HingeRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const Hinge *my_hinge // Hinge attribute we will use to control the joint +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + // + // Check the incomming data + // + Check(my_hinge); + // + // Initialize our variables + // + myHinge = my_hinge; + oldHinge = *my_hinge; + // + // Dump the initial value of the hing into the DCS our instances are attached + // to, then std::flush it out. We have to copy the hinge to a quaternion because + // the math library doesn't support direct assignment of hing to matrix yet. + // + hingeOffsetMatrix.BuildIdentity(); +/*#if SINGLE_AXIS_HINGE + SinCosPair + temp_sin_cos_pair; + temp_sin_cos_pair = myHinge->rotationAmount; + switch(myHinge->axisNumber) + { + case X_Axis: +// dpl_SetDCSXAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + hingeOffsetMatrix. + break; + case Y_Axis: +// dpl_SetDCSYAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + case Z_Axis: +// dpl_SetDCSZAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); + break; + } +#else*/ + Quaternion + temp_quaternion; +// float32 +// *temp_matrix; +// temp_matrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer( temp_matrix ); + temp_quaternion = oldHinge; + hingeOffsetMatrix.BuildRotation(temp_quaternion); +// *(Matrix4x4*)temp_matrix = temp_quaternion; +//#endif +// dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for HingeRenderable +// +HingeRenderable::~HingeRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the HingeRenderable +// +Logical + HingeRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + // + // Test our own variables + // + Check(myHinge); + Check(&oldHinge); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the HingeRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + HingeRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // If the hinge we're watching has changed, update our matrix + // + if(oldHinge != *myHinge) + { + oldHinge = *myHinge; + hingeOffsetMatrix.BuildIdentity(); +//#if SINGLE_AXIS_HINGE +// SinCosPair +// temp_sin_cos_pair; +// temp_sin_cos_pair = myHinge->rotationAmount; +// switch(myHinge->axisNumber) +// { +// case X_Axis: +// dpl_SetDCSXAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); +// break; +// case Y_Axis: +// dpl_SetDCSYAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); +// break; +// case Z_Axis: +// dpl_SetDCSZAxis(myDCS, temp_sin_cos_pair.sine, temp_sin_cos_pair.cosine); +// break; +// } +//#else + Quaternion + temp_quaternion; +// float32 +// *temp_matrix; +// temp_matrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer( temp_matrix ); + temp_quaternion = oldHinge; + hingeOffsetMatrix.BuildRotation(temp_quaternion); +// *(Matrix4x4*)temp_matrix = temp_quaternion; +//#endif +// DPL_FLUSH_DCS ( myDCS ); + } + + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&myOffsetMatrix.ToD3DMatrix()); + myRenderer->GetMatrixStack()->MultMatrixLocal(&hingeOffsetMatrix.ToD3DMatrix()); + // + // Call the execute method in our parent + // + DCSObjectRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for BallJointRenderable +// +BallJointRenderable::BallJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler // Euler angles to control rotation of the ball joint +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + //float32 + // *temp_matrix; + // + // Check the incomming data + // + Check(my_euler); + // + // Initialize our variables + // + myEuler = my_euler; + oldEuler = *my_euler; + // + // Dump the initial value of the euler angles into the DCS our instances are attached + // to, then std::flush it out. + // + eulerMatrix = *myEuler; + //temp_matrix = dpl_GetDCSMatrix( myDCS ); + //Check_Pointer( temp_matrix ); + //*(Matrix4x4*)temp_matrix = oldEuler; + //dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for BallJointRenderable +// +BallJointRenderable::~BallJointRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the BallJointRenderable +// +Logical + BallJointRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + // + // Test our own variables + // + Check(myEuler); + Check(&oldEuler); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the BallJointRenderable +// +void + BallJointRenderable::Execute() +{ + //float32 + // *temp_matrix; + // + // Check our variables + // + Check(this); + // + // If the hinge we're watching has changed, update our matrix + // + if(oldEuler != *myEuler) + { + oldEuler = *myEuler; + eulerMatrix = oldEuler; + // temp_matrix = dpl_GetDCSMatrix( myDCS ); + // Check_Pointer( temp_matrix ); + // *(Matrix4x4*)temp_matrix = oldEuler; + // DPL_FLUSH_DCS ( myDCS ); + } + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&myOffsetMatrix.ToD3DMatrix()); + myRenderer->GetMatrixStack()->MultMatrixLocal(&eulerMatrix.ToD3DMatrix()); + DCSObjectRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for BallTranslateJointRenderable +// +BallTranslateJointRenderable::BallTranslateJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler, // Euler angles to control rotation of the ball joint + const Point3D *my_translation // offset for the translation part of the joint +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + AffineMatrix + tempAffine(True); + + //float32 + // *temp_matrix; + // + // Check the incomming data + // + Check(my_euler); + Check(my_translation); + // + // Initialize our variables + // + myEuler = my_euler; + oldEuler = *my_euler; + myTranslation = my_translation; + oldTranslation = *my_translation; + // + // Dump the initial value of the euler angles into the DCS our instances are attached + // to, then std::flush it out. + // + //temp_matrix = dpl_GetDCSMatrix( myDCS ); + Check_Pointer( temp_matrix ); + tempAffine = oldTranslation; + tempAffine = oldEuler; + jointMatrix = tempAffine; + //*(Matrix4x4*)temp_matrix = tempAffine; + //dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for BallTranslateJointRenderable +// +BallTranslateJointRenderable::~BallTranslateJointRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the BallTranslateJointRenderable +// +Logical + BallTranslateJointRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + // + // Test our own variables + // + Check(myEuler); + Check(&oldEuler); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the BallTranslateJointRenderable +// +void + BallTranslateJointRenderable::Execute() +{ + //float32 + // *temp_matrix; + // + // Check our variables + // + Check(this); + // + // If the hinge we're watching has changed, update our matrix + // + if(oldEuler != *myEuler || oldTranslation != *myTranslation) + { + oldEuler = *myEuler; + oldTranslation = *myTranslation; + // temp_matrix = dpl_GetDCSMatrix( myDCS ); + // Check_Pointer( temp_matrix ); + AffineMatrix tempAffine(True); + tempAffine = oldTranslation; + tempAffine = oldEuler; + jointMatrix = tempAffine; + // *(Matrix4x4*)temp_matrix = tempAffine; + // DPL_FLUSH_DCS ( myDCS ); + } + + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&myOffsetMatrix.ToD3DMatrix()); + myRenderer->GetMatrixStack()->MultMatrixLocal(&jointMatrix.ToD3DMatrix()); + DCSObjectRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SpinScaleQuatRenderable +// +SpinScaleQuatRenderable::SpinScaleQuatRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Logical *visible, // turns the object on and off + Scalar z_spin_rate // spins the object about z (radians/frame) +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check the inbound data + //// + //Check(rotation_quaternion); + //Check(scale_vector); + //Check_Pointer(visible); + //// + //// Remember the entity that this renderable is attached to and the + //// orientation matrix that offsets it to the correct position. + //// + //myRotationQuaternion = rotation_quaternion; + //myScaleVector = scale_vector; + //myVisible = visible; + //myZSpinRate = z_spin_rate; + //OldVisible = *visible; + //OldZSpin = 0; + //// + //// Setup the dcs matrix to it's initial state + //// + //float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + //Check_Pointer ( tempMatrix ); + //AffineMatrix tempAffine(True); + //tempAffine *= (*myScaleVector); + //tempAffine *= (*myRotationQuaternion); + //*(Matrix4x4*)tempMatrix = tempAffine; + //dpl_FlushDCS ( myDCS ); + //// + //// Set the instance visibility correctly + //// + //dpl_SetInstanceVisibility ( myInstance, OldVisible ); + //dpl_FlushInstance ( myInstance ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SpinScaleQuatRenderable +// +SpinScaleQuatRenderable::~SpinScaleQuatRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SpinScaleQuatRenderable +// +Logical + SpinScaleQuatRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SpinScaleQuatRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + SpinScaleQuatRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our variables + //// + //Check(this); + //// + //// Load up the DCS matrix with the localToWorld matrix from the entity + //// then std::flush out the new DCS + //// + //if(OldVisible != *myVisible) + //{ + // OldVisible = *myVisible; + // dpl_SetInstanceVisibility ( myInstance, OldVisible ); + // dpl_FlushInstance ( myInstance ); + //} + //// + //// If the beam is visible, we have to update it + //// + //if(OldVisible) + //{ + // OldZSpin += myZSpinRate; + // if(OldZSpin > TWO_PI) + // OldZSpin -= TWO_PI; + // Hinge temp_hinge(Z_Axis, OldZSpin); + + // float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + // Check_Pointer ( tempMatrix ); + + // AffineMatrix tempAffine(True); + // Quaternion temp_quaternion; + // temp_quaternion = temp_hinge; + // tempAffine = temp_quaternion; + // tempAffine *= (*myScaleVector); + // temp_quaternion = *myRotationQuaternion; + // tempAffine *= temp_quaternion; + // *(Matrix4x4*)tempMatrix = tempAffine; + // DPL_FLUSH_DCS ( myDCS ); + //} + + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for POVTranslocateRenderable +// +POVTranslocateRenderable::POVTranslocateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + StateIndicator *effect_trigger, // State dial we use to control the translocation + unsigned effect_control_state // State that controls start/end of the effect +): + VideoRenderable(entity, execution_type, parent) +{ + isDeathDraw = isDeathZone; + +//STUBBED: DPL RB 1/14/07 +#define COLLAPSE_TIME 1.3f // Time in seconds for initial collapse +#define COLLAPSE_START_SCALE 100.0f // Scale factor of the sphere when we start collapse +#define EXPAND_TIME 1.0f // Time that expansion of the sphere should take +#define EXPAND_END_SCALE 150.0f // Scale factor of the sphere when expansion ends +#define ROTATE_RATE (0.5f * (0.01745329222222)) +#define ROTATE_LIMIT (20.0f * (0.01745329222222)) +#define TRANSLATE_RATE 0.2f +#define TRANSLATE_LIMIT 2.0f +// // HACK HACK HACK this should be removed once red planet is checked out + if(execution_type != Watcher) + std::cout<<"POVTranslocateRenderable wants to be a watcher and isn't!\n"; + // + // Check the inbound data, note that the parent DCS could be a null pointer + // +// Check_Pointer(this_zone); +// Check_Pointer(death_zone); +// Check_Pointer(parent_DCS); + Check(effect_trigger); + // + // Remember the entity and DCS this renderable is attached to + // +// myZone = this_zone; +// myDeathZone = death_zone; +// myParentDCS = parent_DCS; + myEffectTrigger = effect_trigger; + myEffectControlState = effect_control_state; + myState = IdleState; + myRotateY = 0.0f; + myRotateYSpeed = TRANSLATE_RATE; + // + // Load up the object we're going to use for the translocation + // + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); +// dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere.bgf", dpl_load_normal ); + myDevice = l4_application->GetVideoRenderer()->GetDevice(); + myTranslocateSphere = d3d_OBJECT::LoadObject(myDevice, "tsphere.bgf"); + graphicalObject = myTranslocateSphere; + + if (isDeathDraw) + { + //Draw this as sky + for (int i = 0; i < graphicalObject->GetDrawOpCount(); i++) + { + graphicalObject->GetDrawOp(i)->drawAsSky = true; + } + } +// Check_Pointer(myTranslocateSphere); + // + // Setup a DCS that we can put the sphere on so it can be rotated and scaled + // around the VTV. Attach the sphere to this DCS but make it invisible. + // +// myInstance = dpl_NewInstance(); +// myDCS = dpl_NewDCS(); + Check_Pointer (myInstance); + Check_Pointer (myDCS); +// dpl_AddDCSToDCS (myParentDCS, myDCS); +// dpl_SetDCSZone (myDCS, myDeathZone); +// dpl_SetInstanceObject (myInstance, myTranslocateSphere); +// dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj); +// dpl_SetInstanceSectMask (myInstance, NULL); +// dpl_SetInstanceVisibility (myInstance, False); + visible = false; +// dpl_AddInstanceToDCS (myDCS, myInstance); +// dpl_FlushInstance (myInstance); +// dpl_FlushDCS (myDCS); + // + // Connect us to the state dial's watcher hook + // + //l4_application->GetVideoRenderer()->mDeathRenderables.Add(this); + myEffectTrigger->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for POVTranslocationRenderable +// +POVTranslocateRenderable::~POVTranslocateRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //Check(this); + //// + //// Disconnect the structure we have setup + //// + //dpl_RemoveDCSFromDCS(myParentDCS, myDCS); + //dpl_RemoveInstanceFromDCS(myDCS,myInstance); + //// + //// Delete the DPL elements we created + //// + //dpl_DeleteInstance(myInstance); + //dpl_DeleteDCS(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the POVTranslocateRenderable +// +Logical + POVTranslocateRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + + Check_Pointer(myZone); + Check_Pointer(myDeathZone); + Check_Pointer(myParentDCS); + Check(myEffectTrigger); + Check_Pointer(myInstance); + Check_Pointer(myDCS); + Verify(myState >= IdleState && myState <= ExpandRevealState); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for POVTranslocateRenderable. +// +void + POVTranslocateRenderable::Execute() +{ + Scalar + elapsed_time, + current_time, + percent_time_left, + percent_time_used, + scale_factor; + unsigned + current_trigger_state; + // + // Get the current state and the current time for later use + // + Check(myEffectTrigger); + current_trigger_state = myEffectTrigger->GetState(); + current_time = myRenderer->GetCurrentFrameTime(); + // + // State engine (running off myState) to manage running of the death effect + // +// std::cout<<"POVTranslocateRenderable::Execute\n"; + switch(myState) + { + // + // IdleState waits for a transition in the effect control state and starts + // the effect state machine when it detects one. + // + case IdleState: + { + if(current_trigger_state == myEffectControlState) + { + myState = InitialCollapseState; + myCollapseEnd = current_time + COLLAPSE_TIME; + visible = true; +// dpl_SetInstanceVisibility (myInstance, True); +// dpl_FlushInstance (myInstance); + myRenderer->AddDynamicRenderable(this); + std::cout<<"POVTranslocateRenderable::Going Dynamic\n"; + } + break; + } + // + // This case handles ending the screen flash when we need to + // + case FlashScreenState: + { + myState = InitialCollapseState; + break; + } + // + // InitialCollapseState handles reducing the sphere from its max size down + // to one over a period of time. We figure the percentage of the time + // left then multiply it by the size the sphere started at to get the + // scale factor. + // + case InitialCollapseState: + { + percent_time_left = (myCollapseEnd - current_time)/COLLAPSE_TIME; + // + // See how much time is left in the effect. + // + + if(percent_time_left <= 0.0f) + { + // + // Time's up! Go to WaitForReincarnate state, force scale factor to + // 1.0, and turn off the outside world4 + // + scale_factor = 1.0f; +// dpl_SetZoneAllViewsOff (myZone); +// dpl_FlushZone (myZone); + + myCollapseEnd = current_time; + myState = WaitForReincarnateState; + l4_application->SetIsDead(true); + } + else + { + // + // Recalculate the scale factor based on time left + // + //visible = false; + scale_factor = (percent_time_left * COLLAPSE_START_SCALE) + 1.0f; + } + // + // Build a scaling identity matrix based on our scale factor + // + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + // + // Put the scale matrix into the DCS and std::flush it. + // + localToWorld = tempAffine; +// tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// *(Matrix4x4*)tempMatrix = tempAffine; +// DPL_FLUSH_DCS (myDCS); + break; + } + // + // WaitForReincarnateState waits till we the trigger state switches off + // then does what we want to get us back into the world. + // + case WaitForReincarnateState: + { + if(current_trigger_state != myEffectControlState) + { + // + // Switch the world back on, then change states + // +// dpl_SetZoneAllViewsOn (myZone); +// dpl_FlushZone (myZone); + myState = ExpandRevealState; + myCollapseEnd = current_time + EXPAND_TIME; + l4_application->SetIsDead(false); + } + else + { + // + // Mess with the DCS to make the tunnel effect more pronounced + // + elapsed_time = current_time - myCollapseEnd; + Point3D temp_point( + (cos(elapsed_time * 3.33) * TRANSLATE_LIMIT), + (sin(elapsed_time * 2.5) * TRANSLATE_LIMIT), + 0.0); +// tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer( tempMatrix ); + localToWorld = temp_point; +// *(Matrix4x4*)tempMatrix = temp_point; +// DPL_FLUSH_DCS(myDCS); + } + break; + } + // + // ExpandRevealState expands the sphere rapidly in size to reveal the world + // getting rid of the sphere when it hits a maximum size. + // + case ExpandRevealState: + { + // + // In case we get killed again while in this state, I watch for + // a change back into the trigger state and retrigger the + // effect if it shows up + // + if(current_trigger_state == myEffectControlState) + { + myState = InitialCollapseState; + myCollapseEnd = current_time + COLLAPSE_TIME; +//// dpl_SetInstanceVisibility (myInstance, True); +//// dpl_FlushInstance (myInstance); +//// myRenderer->AddDynamicRenderable(this); +//// std::cout<<"POVTranslocateRenderable::Going Dynamic\n"; + } + percent_time_used = 1.0f - ((myCollapseEnd - current_time)/EXPAND_TIME); + if(percent_time_used >= 1.0f) + { + visible = false; +// dpl_SetInstanceVisibility (myInstance, False); +// dpl_FlushInstance (myInstance); + myState = IdleState; + scale_factor = 1.0f; + myRenderer->RemoveDynamicRenderable(this); +//// std::cout<<"POVTranslocateRenderable::Going Static\n"; + } + else + { + scale_factor = (percent_time_used * EXPAND_END_SCALE) + 1.0f; + } + // + // Build a scaling identity matrix based on our scale factor + // + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + // + // Put the scale matrix into the DCS and std::flush it. + // + localToWorld = tempAffine; +// tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// *(Matrix4x4*)tempMatrix = tempAffine; +// DPL_FLUSH_DCS (myDCS); + break; + } + } + + if (!visible) + { + graphicalObject = NULL; + } else + { + graphicalObject = myTranslocateSphere; + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&localToWorld.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + VideoRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for POVStartEndRenderable This handles the effect we use when +// the mission begins and ends (different from death) +// +POVStartEndRenderable::POVStartEndRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + dpl_VIEW *this_view, // The view containing our eye + StateIndicator *effect_trigger, // State dial we use to control the translocation + float red_fog, // Fog color + float green_fog, + float blue_fog, + float near_fog, // The near fog plane + float far_fog, // The far fog plane + unsigned start_mission_state, // State that signals start of mission + unsigned end_mission_state // State that signals end of mission +): + VideoRenderable(entity, execution_type) +{ + isDeathDraw = isDeathZone; + +#define FLASH_TIME (0.1f) // Time the screen will stay stark white +#define FADE_IN_TIME (1.0f) // Time to fade from white to the world +#define FADE_OUT_TIME (0.5f) // Time to fade to black at the end of the game + // HACK HACK HACK this should be removed once red planet is checked out + if(execution_type != Watcher) + std::cout<<"POVStartEndRenderable wants to be a watcher and isn't!\n"; + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(this_zone); + Check_Pointer(death_zone); + Check_Pointer(this_view); + Check(effect_trigger); + // + // Remember the entity and DCS this renderable is attached to + // +// myZone = this_zone; + myDeathZone = death_zone; + myEffectTrigger = effect_trigger; + myView = this_view; + myState = WaitForStartState; + myFogRed = red_fog; + myFogGreen = green_fog; + myFogBlue = blue_fog; + myFogNear = near_fog; + myFogFar = far_fog; + myStartMissionState = start_mission_state; + myEndMissionState = end_mission_state; + myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting); + + l4_application->GetVideoRenderer()->AddRenderable(this); + // + // Connect us to the state dial's watcher hook + // + myEffectTrigger->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for POVStartEndRenderable +// +POVStartEndRenderable::~POVStartEndRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the POVStartEndRenderable +// +Logical + POVStartEndRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + + Check_Pointer(myZone); + Check_Pointer(myDeathZone); + Check(myEffectTrigger); + Verify(myState >= WaitForStartState && myState <= FadeOutState); + Verify(myFogRed >= 0.0f && myFogRed <= 1.0f); + Verify(myFogGreen >= 0.0f && myFogGreen <= 1.0f); + Verify(myFogBlue >= 0.0f && myFogBlue <= 1.0f); + + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for POVStartEndRenderable. +// +void + POVStartEndRenderable::Execute() +{ + Scalar + current_time, + percent_time_left, + percent_time_used; + unsigned + current_trigger_state; + // + // Get the current state and the current time for later use + // + Check(myEffectTrigger); + current_trigger_state = myEffectTrigger->GetState(); + current_time = myRenderer->GetCurrentFrameTime(); + // + // State engine (running off myState) to manage running of the death effect + // + //std::cout<<"POVStartEndRenderable::Executing\n"; + switch(myState) + { + // + // WaitForStartState waits for the state that signals the start of the mission + // then sends the screen to full white by manipulating the fog color and limits. + // + case WaitForStartState: + { + myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting); + if(current_trigger_state == myStartMissionState) + { + myState = FlashScreenState; + myStateTimer = current_time + FLASH_TIME; + float fogNear = 0.01f; + float fogFar = 0.05f; + float fogRed = 1.0f; + float fogGreen = 1.0f; + float fogBlue = 1.0f; + myRenderer->SetCurrentFogLimits(fogNear, fogFar); + myRenderer->GetDevice()->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * fogRed), (int)(255 * fogGreen), (int)(255 * fogBlue))); +// dpl_SetViewFog( +// myView, +// dpl_fog_type_pixel_lin, +// 1.0, +// 1.0, +// 1.0, +// 0.01, +// 0.05 ); +// dpl_FlushView(myView); + myRenderer->AddDynamicRenderable(this); +// std::cout<<"POVStartEndRenderable::Going Dynamic\n"; + } + break; + } + // + // FlashScreenState is a state we park in for a short time so the screen will + // stay white for more than one frame. + // + case FlashScreenState: + { + if(myStateTimer <= current_time) + { + myStateTimer = current_time + FADE_IN_TIME; + myState = FadeInState; + } + break; + } + // + // FadeInState fades the fog color down from white to what it's supposed to + // be, while sweeping the fog ranges out to their proper ranges. + // + case FadeInState: + { + percent_time_left = (myStateTimer - current_time)/FADE_IN_TIME; + if(percent_time_left <= 0.0f) + { + percent_time_left = 0.0f; + myState = MissionRunningState; + myRenderer->SetFogStyle(DPLRenderer::updateFogSetting); + myRenderer->RemoveDynamicRenderable(this); +// std::cout<<"POVStartEndRenderable::Going Static\n"; + } + percent_time_used = 1.0f - percent_time_left; + myRenderer->GetCurrentFogSettings( + &myFogRed, + &myFogGreen, + &myFogBlue, + &myFogNear, + &myFogFar); + + myFogRed += (1.0f - myFogRed) * percent_time_left; + myFogGreen += (1.0f - myFogGreen) * percent_time_left; + myFogBlue += (1.0f - myFogBlue) * percent_time_left; + myFogNear *= percent_time_used; + myFogFar *= percent_time_used; + + myFogNear += 0.01f; + myFogFar += 0.05f; + + myRenderer->SetCurrentFogLimits(myFogNear, myFogFar); + myRenderer->GetDevice()->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * myFogRed), (int)(255 * myFogGreen), (int)(255 * myFogBlue))); +// dpl_SetViewFog( +// myView, +// dpl_fog_type_pixel_lin, +// myFogRed + ((1.0f - myFogRed) * percent_time_left), +// myFogGreen + ((1.0f - myFogGreen) * percent_time_left), +// myFogBlue + ((1.0f - myFogBlue) * percent_time_left), +// (myFogNear * percent_time_used) + 0.01f, +// (myFogFar * percent_time_used) + 0.05f); +// dpl_FlushView(myView); + break; + } + // + // MissionRunningState is where we park while the mission is going on, waiting + // for the state that signals the end of the game + // + case MissionRunningState: + { + if(current_trigger_state == myEndMissionState) + { + myState = FadeOutState; + myStateTimer = current_time + FADE_OUT_TIME; + myRenderer->SetFogStyle(DPLRenderer::noUpdateFogSetting); + myRenderer->AddDynamicRenderable(this); +// std::cout<<"POVStartEndRenderable::Going Dynamic\n"; + } else + { + myRenderer->GetCurrentFogSettings( + &myFogRed, + &myFogGreen, + &myFogBlue, + &myFogNear, + &myFogFar); + myRenderer->SetCurrentFogLimits(myFogNear, myFogFar); + } + break; + } + // + // FadeOutState handles doing a fade-to-black at the end of the game + // + case FadeOutState: + { + percent_time_left = (myStateTimer - current_time)/FADE_OUT_TIME; + if(percent_time_left <= 0.0f) + { + myState = WaitForStartState; + percent_time_left = 0.0f; + myRenderer->RemoveDynamicRenderable(this); +// std::cout<<"POVStartEndRenderable::Going Static\n"; + } + myRenderer->GetCurrentFogSettings( + &myFogRed, + &myFogGreen, + &myFogBlue, + &myFogNear, + &myFogFar); + + myFogRed *= percent_time_left; + myFogGreen *= percent_time_left; + myFogBlue *= percent_time_left; + myFogNear *= percent_time_left; + myFogFar *= percent_time_left; + + myFogNear += 0.01f; + myFogFar += 0.05f; + + myRenderer->SetCurrentFogLimits(myFogNear, myFogFar); + myRenderer->GetDevice()->SetRenderState(D3DRS_FOGCOLOR, D3DCOLOR_XRGB((int)(255 * myFogRed), (int)(255 * myFogGreen), (int)(255 * myFogBlue))); + +// dpl_SetViewFog( +// myView, +// dpl_fog_type_pixel_lin, +// myFogRed * percent_time_left, +// myFogGreen * percent_time_left, +// myFogBlue * percent_time_left, +// (myFogNear * percent_time_left) + 0.01f, +// (myFogFar * percent_time_left) + 0.05f); +// dpl_FlushView(myView); + break; + } + } + +VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the ReticleRenderable +// This produces a movable crosshair reticle that can be either static or +// dynamic. If static, it will position the graphic at wherever the reticle +// points when we construct this. +// +ReticleRenderable::ReticleRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Reticle **my_reticle, // points to renderable reticle pointer that points to entity's reticle + dpl_VIEW *this_view // the view associated with our eye +): + VideoRenderable(entity, execution_type), + mVB(NULL) +{ + // + // Remember the entity that this renderable is attached to + // + rendererReticle = my_reticle; + myReticle = *my_reticle; + myOldReticlePosition = myReticle->reticlePosition; + + LPDIRECT3DDEVICE9 device = myRenderer->GetDevice(); + + device->CreateVertexBuffer(sizeof(L4VERTEX_2D) * 8, D3DUSAGE_WRITEONLY, L4VERTEX_2D_FVF, D3DPOOL_MANAGED, &mVB, NULL); + + L4VERTEX_2D *verts; + mVB->Lock(0, 0, (void**)&verts, 0); + + DWORD color = D3DCOLOR_XRGB(0, 128, 0); + float segmentLen = 5.0f / 192.0f; + float spread = 5.0f / 256.0f; + float width = myRenderer->GetWidth(); + float height = myRenderer->GetHeight(); + float centerX = width / 2.0f; + float centerY = height / 2.0f; + + // top segment + verts[0].x = centerX; + verts[0].y = centerY - (spread + segmentLen) * height; + verts[0].z = 0.0f; + verts[0].rhw = 1.0f; + verts[0].color = color; + + verts[1].x = centerX; + verts[1].y = centerY - spread * height; + verts[1].z = 0.0f; + verts[1].rhw = 1.0f; + verts[1].color = color; + + // right segment + verts[2].x = centerX + (spread + segmentLen) * height; + verts[2].y = centerY; + verts[2].z = 0.0f; + verts[2].rhw = 1.0f; + verts[2].color = color; + + verts[3].x = centerX + spread * height; + verts[3].y = centerY; + verts[3].z = 0.0f; + verts[3].rhw = 1.0f; + verts[3].color = color; + + // bottom segment + verts[4].x = centerX; + verts[4].y = centerY + (spread + segmentLen) * height; + verts[4].z = 0.0f; + verts[4].rhw = 1.0f; + verts[4].color = color; + + verts[5].x = centerX; + verts[5].y = centerY + spread * height; + verts[5].z = 0.0f; + verts[5].rhw = 1.0f; + verts[5].color = color; + + // left segment + verts[6].x = centerX - (spread + segmentLen) * height; + verts[6].y = centerY; + verts[6].z = 0.0f; + verts[6].rhw = 1.0f; + verts[6].color = color; + + verts[7].x = centerX - spread * height; + verts[7].y = centerY; + verts[7].z = 0.0f; + verts[7].rhw = 1.0f; + verts[7].color = color; + + mVB->Unlock(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the ReticleRenderable +// +ReticleRenderable::~ReticleRenderable() +{ + if (mVB) + { + mVB->Release(); + mVB = NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLDrawReticleRenderable +// Not much to check here, the entity and DCS pointers must be valid while +// the instance is allowed to be NULL +// +Logical ReticleRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myReticle); + Check_Pointer(rendererReticle); + Check_Pointer(myView); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ReticleRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void ReticleRenderable::Execute() +{ + // + // See if the reticle has moved + // + if(myOldReticlePosition != myReticle->reticlePosition) + { + myOldReticlePosition = myReticle->reticlePosition; + // + // Re-create the display list that positions the reticle + // + // dpl2d_OpenDisplayList( + // myPositionDisplayList, + // dpl2d_open_mode_clear); + // dpl2d_IdMatrix(my_2d_matrix); + // dpl2d_TranslateMatrix( + // my_2d_matrix, + // myOldReticlePosition.x, + // myOldReticlePosition.y ); + // dpl2d_AddSetMatrix( + // myPositionDisplayList, + // my_2d_matrix ); + // dpl2d_CloseDisplayList(myPositionDisplayList); + // dpl2d_FlushDisplayList(myPositionDisplayList); + } + + // we've done everything that needs to be done, no need to call parent +} + +void ReticleRenderable::Render(int pass, const D3DXMATRIX *viewTransform) +{ + if (myReticle->reticleState == Reticle::ReticleState::ReticleOn) + { + LPDIRECT3DDEVICE9 device = myRenderer->GetDevice(); + + device->SetTexture(0, NULL); + device->SetStreamSource(0, mVB, 0, sizeof(L4VERTEX_2D)); + device->DrawPrimitive(D3DPT_LINELIST, 0, 4); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the CameraShipHUDRenderable +// +CameraShipHUDRenderable::CameraShipHUDRenderable(Entity *entity, ExecutionType execution_type, int *player_index, Logical *display_ranking_window) + : VideoRenderable(entity, execution_type) +{ + //STUBBED: DPL RB 1/14/07 + + // + // Remember the entity that this renderable is attached to + // + LPDIRECT3DDEVICE9 device = myRenderer->GetDevice(); + + device->CreateVertexBuffer(sizeof(L4VERTEX_2D_TEX) * 4, D3DUSAGE_WRITEONLY, L4VERTEX_2D_TEX_FVF, D3DPOOL_MANAGED, &mVB, NULL); + + L4VERTEX_2D_TEX *verts; + mVB->Lock(0, 0, (void**)&verts, 0); + memset(verts, 0, sizeof(L4VERTEX_2D_TEX) * 4); + + DWORD color = D3DCOLOR_XRGB(0, 128, 0); + float width = myRenderer->GetWidth(); + float height = myRenderer->GetHeight(); + float centerX = width / 2.0f; + float centerY = height / 2.0f; + float nameWidth = (width * 0.32f) / 2.0f; + float nameHeight = height * 0.10f; + + // top right + verts[0].x = centerX + nameWidth; + verts[0].y = height - (nameHeight * 2.0f); + verts[0].u = 1.0f; + verts[0].v = 0.0f; + verts[0].rhw = 1.0f; + verts[0].color = color; + + // top left + verts[1].x = centerX - nameWidth; + verts[1].y = height - (nameHeight * 2.0f); + verts[1].u = 0.0f; + verts[1].v = 0.0f; + verts[1].rhw = 1.0f; + verts[1].color = color; + + // bottom right + verts[2].x = centerX + nameWidth; + verts[2].y = height - nameHeight; + verts[2].u = 1.0f; + verts[2].v = 1.0f; + verts[2].rhw = 1.0f; + verts[2].color = color; + + // bottom left + verts[3].x = centerX - nameWidth; + verts[3].y = height - nameHeight; + verts[3].u = 0.0f; + verts[3].v = 1.0f; + verts[3].rhw = 1.0f; + verts[3].color = color; + + mVB->Unlock(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in PlayerName Geometry + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + //playerNameObject[0] = dpl_LoadObject("PNAME1.bgf", dpl_load_normal); + //playerNameObject[1] = dpl_LoadObject("PNAME2.bgf", dpl_load_normal); + //playerNameObject[2] = dpl_LoadObject("PNAME3.bgf", dpl_load_normal); + //playerNameObject[3] = dpl_LoadObject("PNAME4.bgf", dpl_load_normal); + //playerNameObject[4] = dpl_LoadObject("PNAME5.bgf", dpl_load_normal); + //playerNameObject[5] = dpl_LoadObject("PNAME6.bgf", dpl_load_normal); + //playerNameObject[6] = dpl_LoadObject("PNAME7.bgf", dpl_load_normal); + //playerNameObject[7] = dpl_LoadObject("PNAME8.bgf", dpl_load_normal); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Read in Ordinal Rankings Geometry + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + //ordinalObject[0] = dpl_LoadObject("PLACE1.bgf", dpl_load_normal); + //ordinalObject[1] = dpl_LoadObject("PLACE2.bgf", dpl_load_normal); + //ordinalObject[2] = dpl_LoadObject("PLACE3.bgf", dpl_load_normal); + //ordinalObject[3] = dpl_LoadObject("PLACE4.bgf", dpl_load_normal); + //ordinalObject[4] = dpl_LoadObject("PLACE5.bgf", dpl_load_normal); + //ordinalObject[5] = dpl_LoadObject("PLACE6.bgf", dpl_load_normal); + //ordinalObject[6] = dpl_LoadObject("PLACE7.bgf", dpl_load_normal); + //ordinalObject[7] = dpl_LoadObject("PLACE8.bgf", dpl_load_normal); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize CameraFollowing + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + followedPlayerIndex = player_index; + oldFollowedPlayerIndex = -1; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create One DCS for a Camera Following Name Bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + //followedNameDCS = dpl_NewDCS(); + //followedNameInstance = dpl_NewInstance(); + //dpl_ScaleDCS ( followedNameDCS, 0.20f, 0.20f, 1.0f ); + //dpl_TranslateDCS ( followedNameDCS, 0.0f, -0.15f, -0.5f ); + //dpl_SetDCSIgnoreGeo ( followedNameDCS, 1 ); + //dpl_SetDCSTraversal ( followedNameDCS, 0x7 ); + //dpl_AddDCSToScene ( followedNameDCS ); + //dpl_SetInstanceObject ( followedNameInstance, playerNameObject[0] ); + //dpl_AddInstanceToDCS ( followedNameDCS, followedNameInstance ); + //dpl_SetInstanceVisibility ( followedNameInstance, 1 ); + //dpl_FlushInstance ( followedNameInstance ); + //dpl_FlushDCS ( followedNameDCS ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create One DCS for Camera Following Ordinal Ranking Bitmap + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + //followedOrdinalDCS = dpl_NewDCS(); + //followedOrdinalInstance = dpl_NewInstance(); + //dpl_AddDCSToDCS ( followedNameDCS, followedOrdinalDCS ); + //dpl_SetInstanceObject ( followedOrdinalInstance, ordinalObject[0] ); + //dpl_AddInstanceToDCS ( followedOrdinalDCS, followedOrdinalInstance ); + //dpl_SetDCSIgnoreGeo ( followedOrdinalDCS, 1 ); + //dpl_SetDCSTraversal ( followedOrdinalDCS, 0x7 ); + //dpl_TranslateDCS ( followedOrdinalDCS, -0.75f, 0.0f, 0.0f ); + //dpl_SetInstanceVisibility ( followedOrdinalInstance, 0 ); + //dpl_FlushInstance ( followedOrdinalInstance ); + //dpl_FlushDCS ( followedOrdinalDCS ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the Ranking Window + //~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + displayRankingWindow = display_ranking_window; + oldDisplayRankingWindow = False; + + Scalar rank_window_y; + rank_window_y = 0.16f; + + //rankingWindowDCS = dpl_NewDCS(); + //dpl_ScaleDCS ( rankingWindowDCS, 0.12f, 0.12f, 1.0f ); + //dpl_TranslateDCS ( rankingWindowDCS, 0.22f, rank_window_y, -0.5f ); + //dpl_SetDCSIgnoreGeo ( rankingWindowDCS, 1 ); + //dpl_SetDCSTraversal ( rankingWindowDCS, 0x7 ); + //dpl_AddDCSToScene ( rankingWindowDCS ); + //dpl_FlushDCS ( rankingWindowDCS ); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the pointer's to the player Ranks + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + playerRank = NULL; + oldPlayerRank = NULL; + nameDCS = NULL; + rankDCS = NULL; + nameInstance = NULL; + rankInstance = NULL; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See How Many Regular Players and CameraShip Players! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + playerCount = 0; + Check(application); + EntityManager *entity_mgr = application->GetEntityManager(); + Check(entity_mgr); + EntityGroup *player_group = entity_mgr->FindGroup("Players"); + if (player_group) + { + Check(player_group); + ChainIteratorOf player_iterator(player_group->groupMembers); + playerCount = player_iterator.GetSize(); + } + + EntityGroup *camera_player_group = entity_mgr->FindGroup("CameraPlayers"); + int camera_player_count=0; + if (camera_player_group) + { + Check(player_group); + ChainIteratorOf camera_iterator(camera_player_group->groupMembers); + camera_player_count = camera_iterator.GetSize(); + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make the Arrays for Ranking the size of regular and cameras players + // summed up. This is necessary since GameMachineHost type of Camera + // Ships also have a bitmapIndex! + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (playerCount) + { + camera_player_count += playerCount; + Verify(camera_player_count <= MAX_PLAYER_NAMES); + playerRank = new (int (*[camera_player_count])); + Register_Pointer(playerRank); + Player *active_player; + if(player_group) + { + Check(player_group); + ChainIteratorOf player_iterator(player_group->groupMembers); + while ((active_player = (Player*) player_iterator.ReadAndNext()) != NULL) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PlayerRank Array indexed by bitmapIndex + // holds that player's ranking + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(active_player); + Verify( + active_player->playerBitmapIndex > 0 + && active_player->playerBitmapIndex <= MAX_PLAYER_NAMES + ); + playerRank[active_player->playerBitmapIndex - 1] = + &active_player->playerRanking ; + } + } + if (camera_player_group) + { + ChainIteratorOf camera_iterator(camera_player_group->groupMembers); + while ((active_player = (Player*) camera_iterator.ReadAndNext()) != NULL) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // PlayerRank Array indexed by bitmapIndex + // holds that player's ranking + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Check(active_player); + Verify( + active_player->playerBitmapIndex > 0 + && active_player->playerBitmapIndex <= MAX_PLAYER_NAMES + ); + playerRank[active_player->playerBitmapIndex - 1] = + &active_player->playerRanking ; + } + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize OldPlayerRank + //~~~~~~~~~~~~~~~~~~~~~~~~~ + // + oldPlayerRank = new int[camera_player_count]; + Register_Pointer(oldPlayerRank); + + int ii; + for(ii=0; iiGetApplicationState() == Application::StoppingMission || + application->GetApplicationState() == Application::EndingMission) + { + //dpl_SetInstanceVisibility ( followedOrdinalInstance, 0 ); + //dpl_SetInstanceVisibility ( followedNameInstance, 0 ); + //dpl_FlushInstance ( followedOrdinalInstance ); + //dpl_FlushInstance ( followedNameInstance ); + } + + VideoRenderable::Execute(); +} + +void CameraShipHUDRenderable::Render(int pass, const D3DXMATRIX *viewTransform) +{ + if (application->GetApplicationState() == Application::RunningMission && oldFollowedPlayerIndex >= 0 && oldFollowedPlayerIndex < MAX_PLAYER_NAMES) + { + LPDIRECT3DDEVICE9 device = myRenderer->GetDevice(); + + device->SetFVF(L4VERTEX_2D_TEX_FVF); + device->SetStreamSource(0, mVB, 0, sizeof(L4VERTEX_2D_TEX)); + device->SetTexture(0, myRenderer->GetNameTexture(oldFollowedPlayerIndex)); + device->DrawPrimitive(D3DPT_TRIANGLESTRIP, 0, 2); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + CameraShipHUDRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DCSMorphObjectRenderable +// +DCSMorphObjectRenderable::DCSMorphObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask // intersection mask for the object +): + VideoRenderable(entity, execution_type) +{ + isDeathDraw = isDeathZone; + + //STUBBED: DPL RB 1/14/07 + //// + //// Check incoming data + //// + //Check_Pointer(destination_object); + //Check_Pointer(start_object); + //Check_Pointer(end_object); + //Check_Pointer(morph_control); + //Check_Pointer(this_zone); + //// + //// Remember my dpl object, intersect and offset data + //// + //myDPLObject = destination_object; + //myStartObject = start_object; + //myEndObject = end_object; + //myMorphControl = morph_control; + //oldMorphControl = *myMorphControl; + //myMorphMode = morph_mode; + //myDPLZone = this_zone; + //myIntersectMode = intersect_mode; + //myIntersectMask = intersect_mask; + //myDCS = NULL; + //myInstance = NULL; + //// + //// We need to construct a DCS node here and remember it. The next class up is + //// expected to handle the std::flushing and connecting of structure so we just setup + //// the DCS and zone information here, leaving std::flushing to someone else. + //// + //myDCS = dpl_NewDCS (); + //Check_Pointer ( myDCS ); + //dpl_SetDCSZone ( myDCS, myDPLZone ); + //// + //// Construct the instance(s) and hang them on the DCS. Since we may be building + //// more than one instance, we have to take care of std::flushing them here. + //// + //myInstance = dpl_NewInstance(); + //Check_Pointer ( myInstance); + //dpl_SetInstanceObject ( myInstance, myDPLObject); + //dpl_SetInstanceIntersect ( myInstance, myIntersectMode ); + //dpl_SetInstanceSectMask ( myInstance, myIntersectMask ); + //dpl_SetInstanceVisibility ( myInstance, 1 ); + //dpl_AddInstanceToDCS ( myDCS, myInstance ); + //dpl_FlushInstance ( myInstance ); + //// + //// Setup the morph and do the initial morph to get the destination object + ////-------------------------------------------------------------------------- + //// NOTE: dpl_MorphObject seems to have Start and End objects reversed + //// so they are reversed here as well...(two negatives make positive) + ////-------------------------------------------------------------------------- + //dpl_MorphObject(myDPLObject,myStartObject,myEndObject,oldMorphControl,myMorphMode); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DCSMorphObjectRenderable +// +DCSMorphObjectRenderable::~DCSMorphObjectRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Delete the instance(s) hanging on the DCS (if any) + //// NOTE: we may want to iterate through all the instances here using DPL routines + //// + //dpl_RemoveInstanceFromDCS(myDCS, myInstance); + //dpl_DeleteInstance(myInstance); + //// + //// Delete the DCS + //// + //dpl_DeleteDCS(myDCS); + //myDCS = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DCSMorphObjectRenderable +// +Logical + DCSMorphObjectRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + VideoRenderable::TestInstance(); + // + // Test our own variables + // + Check_Pointer(myDPLObject); + Check_Pointer(myStartObject); + Check_Pointer(myEndObject); + Check_Pointer(myMorphControl); + Check_Pointer(myDPLZone); + Check_Pointer(myDCS); + Check_Pointer(myInstance); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DCSMorphObjectRenderable +// If the morph control variable has changed, we re-do the morph +// +void + DCSMorphObjectRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our variables + //// + //Check(this); + //// + //// See if the morph control varaible has changed + //// + //if(oldMorphControl != *myMorphControl) + //{ + // oldMorphControl = *myMorphControl; + // //-------------------------------------------------------------------------- + // // NOTE: dpl_MorphObject seems to have Start and End objects reversed + // // so they are reversed here as well...(two negatives make positive) + // //-------------------------------------------------------------------------- + + // dpl_MorphObject(myDPLObject,myStartObject,myEndObject,oldMorphControl,myMorphMode); + //} + //// + //// Call the next lower execute method + //// + //#if DEBUG_LEVEL > 0 + //VideoRenderable::Execute(); + // #endif + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for RootMorphRenderable +// +RootMorphRenderable::RootMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask // intersection mask for the object +): +DCSMorphObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + destination_object, // destination + start_object, // start object + end_object, // end object + morph_control, // pointer to control variable + morph_mode, // Defines type of morph to do + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask) // intersection mask for the object +{ + //STUBBED: DPL RB 1/14/07 + //// + //// All the incoming data will have been checked by DCSObjectRenderable + //// already, so we don't have to check anything locally. + //// + //// + //// Initialize our variables + //// + //oldLocalToWorld = myEntity->localToWorld; + //// + //// Now we finish the work of hooking up and initializing the root renderable + //// Add the DCS to the scene and initialize it's matrix with the localToWorld + //// transformation from our entity + //// + //dpl_AddDCSToScene ( myDCS ); + //float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + //Check_Pointer ( tempMatrix ); + //*(Matrix4x4*)tempMatrix = myEntity->localToWorld; + //dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for RootMorphRenderable +// +RootMorphRenderable::~RootMorphRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our structure before we do anything + //// + //Check(this); + //// + //// Remove the DCS from the scene, deletion of the DCS and it's instances is + //// handled by our parent class. + //// + //dpl_RemoveDCSFromScene(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the RootMorphRenderable +// +Logical + RootMorphRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSMorphObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check(&oldLocalToWorld); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the RootMorphRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + RootMorphRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check our variables + //// + //Check(this); + //// + //// If our entity has changed it's localToWorld matrix, update DPL + //// + //if(oldLocalToWorld != myEntity->localToWorld) + //{ + // oldLocalToWorld = myEntity->localToWorld; + // float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + // Check_Pointer (tempMatrix); + // *(Matrix4x4*)tempMatrix = oldLocalToWorld; + // DPL_FLUSH_DCS ( myDCS ); + //} + //// + //// Call the execute method in our parent + //// + DCSMorphObjectRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ChildMorphRenderable +// +ChildMorphRenderable::ChildMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS // the parent DCS we will be offsetting from +): +DCSMorphObjectRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + destination_object, // destination + start_object, // start object + end_object, // end object + morph_control, // pointer to control variable + morph_mode, // Defines type of morph to do + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask) // intersection mask for the object +{ + //STUBBED: DPL RB 1/14/07 + //// + //// All the incoming data will have been checked by DCSObjectRenderable + //// already, so we don't have to check anything locally. + //// + //Check_Pointer(parent_DCS); + //// + //// Now we finish the work of hooking up and initializing the root renderable + //// Add the DCS to the scene and initialize it's matrix with the localToWorld + //// transformation from our entity + //// + //dpl_AddDCSToDCS ( parent_DCS, myDCS ); + //dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ChildMorphRenderable +// +ChildMorphRenderable::~ChildMorphRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ChildMorphRenderable +// +Logical + ChildMorphRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSMorphObjectRenderable::TestInstance(); + // + // Test our own variables + // + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ChildMorphRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ChildMorphRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + // + // Call the execute method in our parent + // + DCSMorphObjectRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ScalingExplosionRenderable +// +ScalingExplosionRenderable::ScalingExplosionRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // This will be the scaling explosion object + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Vector3D *control_vector, // Effect control velocity vector + Vector3D *accel_vector, // rate of change of control vector + Scalar gravity, + int *trigger // doesn't run till the trigger comes up +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ + // + // Check the incoming data + // + Check(control_vector); + #if DEBUG_LEVEL > 0 + if(trigger) + Check_Pointer(trigger); + #endif + // + // Initialize our variables + // + myScalingVector.x = 0.01; + myScalingVector.y = 0.01; + myScalingVector.z = 0.01; + myVelocityVector = *control_vector; + myVelocityChange = *accel_vector; + myGravity = gravity; + myVelocity = 0.0f; + myTranslation.x = 0.0; + myTranslation.y = 0.0; + myTranslation.z = 0.0; + myTrigger = trigger; + // + // Initialize the matrix in this dcs + // + //float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + //Check_Pointer ( tempMatrix ); + //AffineMatrix tempAffine(True); + //tempAffine *= myScalingVector; + //tempAffine *= myTranslation; + //*(Matrix4x4*)tempMatrix = tempAffine; + //dpl_FlushDCS ( myDCS ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ScalingExplosionRenderable +// +ScalingExplosionRenderable::~ScalingExplosionRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ScalingExplosionRenderable +// +Logical + ScalingExplosionRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + DCSObjectRenderable::TestInstance(); + // + // Test our own variables + // + Check(&myScalingVector); + Check(&myVelocityVector); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ScalingExplosionRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ScalingExplosionRenderable::Execute() +{ + // + // Check our variables + // + Check(this); + if(!myTrigger || *myTrigger != 0) + { + // + // Apply the scaling factor to the object + // + myVelocityVector += myVelocityChange; + myScalingVector += myVelocityVector; + myVelocity += myGravity; + myTranslation.y += myVelocity; + // + // Initialize the matrix in this dcs + // + //float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); + //Check_Pointer ( tempMatrix ); + //AffineMatrix tempAffine(True); + //tempAffine *= myScalingVector; + //tempAffine *= myTranslation; + //*(Matrix4x4*)tempMatrix = tempAffine; + //DPL_FLUSH_DCS ( myDCS ); + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); + } +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Micro Renderables +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// From here to the row of === is pretty kludgy stuff to allow dave to prototype +// some explosion stuff. +// I expect to replace most of it within a week with the all-new micro +// renderable system. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DependantRenderable +// This is a class of renderable that has other dependant renderables which it +// will execute on command. This is a base for this type of renderable and is +// not ment to be used by itself. +// +DependantRenderable::DependantRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type // How/when to execute the renderable +): + VideoRenderable(entity, execution_type), + dependantRenderableSocket(NULL) +{ + // Check incoming data + // Initialize variables +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DependantRenderable +DependantRenderable::~DependantRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DependantRenderable +Logical + DependantRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + // Now do our checking + Check(&dependantRenderableSocket); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AddDependantRenderable for the DependantRenderable +// This adds an existing renderable as a dependant on this renderable so it +// will be run when this renderable is executed. +void + DependantRenderable::AddDependantRenderable(Component *dependant) +{ + Check(dependant); + dependantRenderableSocket.Add(dependant); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DependantRenderable +void + DependantRenderable::Execute() +{ + Component + *dependant; + // + // Make an iterator for our components then execute them all + // +// std::cout<<"DependantRenderable::Execute()\n"; + SChainIteratorOf dependant_iterator(&dependantRenderableSocket); + while ((dependant = dependant_iterator.ReadAndNext()) != NULL) + { + dependant->Execute(); +// std::cout<<"dependant->Execute();\n"; + } + + // Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ScalarTriggerRenderable +// Whenever "watched_value" changes by "watched_precision" the dependants of this +// renderable will be called. +// +ScalarTriggerRenderable::ScalarTriggerRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar *watched_value, // we run dependants when this changes + Scalar watched_precision // watched_value must change by this much +): + DependantRenderable(entity, execution_type) +{ + // + // Check incoming data + // + Check_Pointer(watched_value); + // + // Initialize variables + // + myWatchedValue = watched_value; + myOldWatchedValue = *myWatchedValue; + myPrecision = watched_precision; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ScalarTriggerRenderable +ScalarTriggerRenderable::~ScalarTriggerRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ScalarTriggerRenderable +Logical + ScalarTriggerRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + DependantRenderable::TestInstance(); + // Now do our checking + Check_Pointer(myWatchedValue); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ScalarTriggerRenderable +void + ScalarTriggerRenderable::Execute() +{ + Check(this); + // + // If there hasn't been a significant enough change, return right now + // + if(Abs((*myWatchedValue - myOldWatchedValue)) < myPrecision) + return; + // + // Update my watcher data, then call my parent to execute the dependants + // + myOldWatchedValue = *myWatchedValue; + DependantRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for TimeCullRenderable +// This renderable will run all it's dependants at a set frequency based on +// a clock value supplied by the culling system. +// +TimeCullRenderable::TimeCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_between_runs // Time delay between executions of dependants +): + DependantRenderable(entity, execution_type) +{ + // + // Check incoming data + // + // + // Initialize the renderable, set clock so this will execute the first time + // it's called. + // + delayBetweenRuns = delay_between_runs; + nextRunTime = myRenderer->GetCurrentFrameTime(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for TimeCullRenderable +TimeCullRenderable::~TimeCullRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the TimeCullRenderable +Logical + TimeCullRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + DependantRenderable::TestInstance(); + // Now do our checking + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the TimeCullRenderable +void + TimeCullRenderable::Execute() +{ + Check(this); + // + // If it's time, call my parent to execute the dependants + // + if(nextRunTime <= myRenderer->GetCurrentFrameTime()) + { + nextRunTime = myRenderer->GetCurrentFrameTime() + delayBetweenRuns; + DependantRenderable::Execute(); +// std::cout<<"Time Cull ran dependants\n"; + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +MechCullRenderable::MechCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical always_run_all, // If true, disable culling and run everything + bool isDeathZone // Switch off this zone when the mech goes off screen +): + DependantRenderable(entity, execution_type), + legRenderableSocket(NULL) +{ + isDeathDraw = isDeathZone; + Check_Pointer(my_zone); + myAlwaysRunAll = always_run_all; + //myZone = my_zone; + myMechWasVisible = True; + myNextRootUpdate = myRenderer->GetCurrentFrameTime(); + myNextLegUpdate = myRenderer->GetCurrentFrameTime(); + myRootUpdateRate = 0.0; + myLegUpdateRate = 0.0; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for MechCullRenderable +MechCullRenderable::~MechCullRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// AddDependantLegRenderable for the MechCullRenderable +// This adds an existing renderable as a dependant of the leg chain. +void + MechCullRenderable::AddDependantLegRenderable(Component *dependant) +{ + Check(dependant); + legRenderableSocket.Add(dependant); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the MechCullRenderable +Logical + MechCullRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + DependantRenderable::TestInstance(); + // Now do our checking + Check_Pointer(myZone); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the MechCullRenderable +void + MechCullRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //#define CULL_VOLUME_SIZE 11.0 // Assume mech (or other object) fills 10 meter bubble + Scalar + current_time; + //Point3D + // target_point; + //Component + // *dependant; + + //Check(this); + //// + //// If we've been told to always run everything, do so. I don't flip the + //// profile bit here because I only want to time the actual cull algorithim. + //// + //if(myAlwaysRunAll) + //{ + // DependantRenderable::Execute(); + // SChainIteratorOf dependant_iterator(&legRenderableSocket); + // while ((dependant = dependant_iterator.ReadAndNext()) != NULL) + // { + // dependant->Execute(); + // } + // myMechWasVisible = True; + // return; + //} + //SET_VIDEO_MECH_CULL_RENDERABLE(); + //// + //// Continue on to do the full culling process + //// + current_time = myRenderer->GetCurrentFrameTime(); + //// + //// Transform this entities position into eye space + //// + //target_point = myEntity->localOrigin.linearPosition; + //target_point *= (*myRenderer->GetWorldToEyeMatrix()); + //Check(this); + //// + //// See if this is inside the viewing volume + //// HACK, viewing volume is hard coded here for now + //// negative z goes into the screen + //// + //// See if it's behind me + //// + //if((target_point.z - CULL_VOLUME_SIZE) >= 0.0f) + //{ + // if(myMechWasVisible) + // { + // myMechWasVisible = False; + // dpl_SetZoneAllViewsOff (myZone); + // dpl_FlushZone (myZone); + // // + // // Set the root rate to slow and the leg rate to stopped + // // + // myRootUpdateRate = 1.0f; + // myLegUpdateRate = 60.0f; + // myNextRootUpdate = current_time + myRootUpdateRate; + // myNextLegUpdate = current_time + myLegUpdateRate; + // } + //} + //else + //{ + // // + // // Fix up the Z so objects very close behind us (close enough they might + // // stick into our view) will be properly culled. + // // + // if(target_point.z >= 0) + // target_point.z = 0.1; + // else + // target_point.z = Abs(target_point.z); + // Check(this); + // // + // // See if the object's volume is to the left or right of the culling + // // volume. + // // + // if(((Abs(target_point.x)-CULL_VOLUME_SIZE)/target_point.z) > myRenderer->GetViewRatio()) + // { + // // + // // If we were visible before, we're not any more + // // + // Check(this); + // if(myMechWasVisible) + // { + // myMechWasVisible = False; + // dpl_SetZoneAllViewsOff (myZone); + // dpl_FlushZone (myZone); + // // + // // Set the root rate to slow and the leg rate to stopped + // // + // myRootUpdateRate = 1.0f; + // myLegUpdateRate = 60.0f; + // myNextRootUpdate = current_time + myRootUpdateRate; + // myNextLegUpdate = current_time + myLegUpdateRate; + // } + // } + // else + // { + // // + // // If we were invisible before, we're visible now + // // + // Check(this); + // if(!myMechWasVisible) + // { + // myMechWasVisible = True; + // dpl_SetZoneAllViewsOn (myZone); + // dpl_FlushZone (myZone); + // // + // // Set the various update rates appropriately and force an update + // // + // myRootUpdateRate = 0.0; + // myNextRootUpdate = current_time; + // myNextLegUpdate = current_time; + // } + // // + // // Set the leg update rate based on range (really should be a formulia) + // // + // if(target_point.z < 500.0f) + // myLegUpdateRate = 0.0; + // else + // myLegUpdateRate = 0.25; + // } + //} + //// + //// Flip the trace bit here because I don't want to include the cost of the + //// dependant renderables. + //// + //CLEAR_VIDEO_MECH_CULL_RENDERABLE(); + //// + //// Use the data already calculated to determine which of the dependant + //// renderable groups we should execute. + //// + //if(myNextLegUpdate <= current_time) + //{ + // myNextLegUpdate = current_time + myLegUpdateRate; + // // + // // Execute all the leg renderables + // // + // SChainIteratorOf dependant_iterator(&legRenderableSocket); + // while ((dependant = dependant_iterator.ReadAndNext()) != NULL) + // { + // dependant->Execute(); + // } + //} + if(myNextRootUpdate <= current_time) + { + myNextRootUpdate = current_time + myRootUpdateRate; + DependantRenderable::Execute(); + } + return; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for InstanceSwitchRenderable +InstanceSwitchRenderable::InstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // instance on when trigger is.... + int *trigger // true if the instance is on, false if off +): + VideoRenderable(entity, execution_type) +{ + //STUBBED: DPL RB 1/14/07 + //// Check incoming data + //Check_Pointer(this_instance); + //Check_Pointer(trigger); + //// Initialize variables + //mySense = sense; + //myInstance = this_instance; + //myTriggerAttribute = trigger; + //oldTriggerAttribute = *myTriggerAttribute; + //if(mySense == oldTriggerAttribute) + //{ + // dpl_SetInstanceVisibility ( myInstance, 1 ); + //} + //else + //{ + // dpl_SetInstanceVisibility ( myInstance, 0 ); + //} + // dpl_FlushInstance ( myInstance ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for InstanceSwitchRenderable +InstanceSwitchRenderable::~InstanceSwitchRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the InstanceSwitchRenderable +Logical + InstanceSwitchRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myInstance); + Check_Pointer(myTriggerAttribute); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the InstanceSwitchRenderable +void + InstanceSwitchRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //// Check our variables + //Check(this); + //if(*myTriggerAttribute != oldTriggerAttribute) + //{ + // oldTriggerAttribute = *myTriggerAttribute; + // if(mySense == oldTriggerAttribute) + // { + // dpl_SetInstanceVisibility ( myInstance, 1 ); + // } + // else + // { + // dpl_SetInstanceVisibility ( myInstance, 0 ); + // } + // dpl_FlushInstance ( myInstance ); + //} + //// Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// StateInstanceSwitchRenderable is designed to be a watcher that connects to +// a state dial. Whenever the state dial changes we are called and check to +// see if the trigger state has been entered. If we are in the trigger state +// we will change the instance visibility based on the sense variable passed +// into the constructor. This lets you have an instance on while in a +// certain state or off while in that state and on in others. +// Messages Sent: None +// Messages Received: None +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for StateInstanceSwitchRenderable +// +StateInstanceSwitchRenderable::StateInstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // true to turn on in this state, false for off + StateIndicator *state_dial, // State dial we use to control the on/off + unsigned trigger_state // State that we look for +): + VideoRenderable(entity, execution_type) +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Check incoming data for correctness + //// + //Check_Pointer(this_instance); + //Check(state_dial); + //// + //// Initialize variables + //// + //myInstance = this_instance; + //mySense = sense; + //myStateDial = state_dial; + //myTriggerState = trigger_state; + //// + //// Put the instance in the proper state and std::flush it + //// + //if(myStateDial->GetState() == myTriggerState) + //{ + // if(mySense == True) + // myLastInstanceState = True; + // else + // myLastInstanceState = False; + //} + //else + //{ + // if(mySense == True) + // myLastInstanceState = False; + // else + // myLastInstanceState = True; + //} + //dpl_SetInstanceVisibility ( myInstance, myLastInstanceState ); + //dpl_FlushInstance ( myInstance ); + //// + //// Connect us to the state dial's watcher hook + //// + //state_dial->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for StateInstanceSwitchRenderable +StateInstanceSwitchRenderable::~StateInstanceSwitchRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the StateInstanceSwitchRenderable +Logical + StateInstanceSwitchRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myInstance); + Check(myStateDial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the StateInstanceSwitchRenderable --- called by the state dial +// watcher hook when the state changes. The state dial won't call us if unless +// the state actually changes so there is no need to filter transitions between +// two identical states. +// +void + StateInstanceSwitchRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //unsigned + // new_state; + //// + //// Check our variables + //// + //Check(this); + //// + //// See what state we should go into + //// + //if(myStateDial->GetState() == myTriggerState) + //{ + // if(mySense == True) + // new_state = True; + // else + // new_state = False; + //} + //else + //{ + // if(mySense == True) + // new_state = False; + // else + // new_state = True; + //} + //if(new_state != myLastInstanceState) + //{ + // myLastInstanceState = new_state; + // dpl_SetInstanceVisibility ( myInstance, myLastInstanceState ); + // dpl_FlushInstance ( myInstance ); + //} + //// Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for MakeDCSFall +MakeDCSFall::MakeDCSFall( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_DCS *this_DCS, // the DCS to control + Scalar gravity, // Gravity in meters/sec squared + int *trigger // true if the instance is on, false if off +): + VideoRenderable(entity, execution_type) +{ + // Check incoming data + Check_Pointer(this_DCS); + Check_Pointer(trigger); + // + // Was an input trigger provided? + // + if(trigger) + { + // Yes, remember a pointer to it and it's state + myTrigger = trigger; + oldMyTrigger = *myTrigger; + } + else + { + // No, point it at a fake trigger that is turned on + fakeTrigger = 1; + myTrigger = &fakeTrigger; + oldMyTrigger = 0; + } + // + // Initialize other variables + // + myDCS = this_DCS; + myDisplacement = Point3D::Identity; + myHalfAcceleration = gravity/2.0f; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for MakeDCSFall +MakeDCSFall::~MakeDCSFall() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the MakeDCSFall +Logical + MakeDCSFall::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the MakeDCSFall +void + MakeDCSFall::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //// Check our variables + //Check(this); + //// + //// Look for an edge in the trigger input + //// + //if(*myTrigger != oldMyTrigger) + //{ + // // + // // A transition from zero to nonzero resets the DCS position and + // // starts us falling again. + // // + // if(oldMyTrigger == 0) + // { + // myFallStart = myRenderer->GetCurrentFrameTime(); + // myDisplacement = Point3D::Identity; + // } + // oldMyTrigger = *myTrigger; + //} + //// + //// If the trigger is nonzero and the sweep isn't at 1 yet, update + //// the sweep values. + //// + //if(oldMyTrigger != 0) + //{ + // Scalar + // elapsed_time, + // current_time; + // // Figure displacement do to gravity... 0.5 * a * t^2 + // // note that we've already taken a * 0.5 in the constructor + // current_time = myRenderer->GetCurrentFrameTime(); + // elapsed_time = current_time - myFallStart; + // myDisplacement.y = myHalfAcceleration * (elapsed_time * elapsed_time); + // float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + // Check_Pointer (tempMatrix); + // *(Matrix4x4*)tempMatrix = myDisplacement; + // DPL_FLUSH_DCS ( myDCS ); + //} + //// Call the next lower execute method + VideoRenderable::Execute(); +} +//============================================================================= +#if 0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SquareWaveRenderable +SquareWaveRenderable::SquareWaveRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar time_false, // time to spend in zero state + Scalar time_true, // time to spend in one state + int *trigger // starts square wave when it goes to 1 + int start_state // state we start in + int cycles // number of transitions before we stop +): + VideoRenderable(entity, execution_type) +{ + if(trigger) + { + // Yes, remember a pointer to it and it's state + myTriggerInput = trigger; + oldTriggerInput = *myTrigger; + } + else + { + // No, point it at a fake trigger that is turned on + fakeTrigger = 1; + myTriggerInput = &fakeTrigger; + oldTriggerInput = 0; + } + // Initialize variables + myTriggerInput = trigger; + oldTriggerInput = 0; + myNextStateChange = 0; + myTimeFalse = time_false; + myTimeTrue = time_true; + myTriggerAttribute = start_state; + myCyclesLeft = cycles; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SquareWaveRenderable +SquareWaveRenderable::~SquareWaveRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SquareWaveRenderable +Logical + SquareWaveRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Verify(myTriggerTime > 0.0f); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SquareWaveRenderable +void + SquareWaveRenderable::Execute() +{ + Scalar + current_time; + // Check our variables + Check(this); + + if(*myTriggerInput != oldTriggerInput && oldTriggerInput == 0) + { + if(myStartState) + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeTrue; + myTriggerAttribute = True; + } + else + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeFalse; + myTriggerAttribute = False; + } + myCyclesLeft = myCycles; + } + + if(*myTriggerInput == 1 && myCyclesLeft > 0) + { + current_time = myRenderer->GetCurrentFrameTime(); + if(current_time >= myNextStateChange) + { + myCyclesLeft--; + myTriggerAttribute = (!myTriggerAttribute); + if(myTriggerAttribute) + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeTrue; + } + else + { + myNextStateChange = myRenderer->GetCurrentFrameTime(); + myNextStateChange += myTimeFalse; + } + } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif +} +#endif +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for OneShotDelayRenderable +// This renderable delays for a fixed amount after it's creation, then turns on +// a trigger attribute. It is used for the triggering of other renderables a +// fixed time after an object is created. +OneShotDelayRenderable::OneShotDelayRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to wait before raising the trigger + Scalar duration_time // How long trigger is up (0.0 == stay up) +): + VideoRenderable(entity, execution_type) +{ + // Check incoming data + Verify(delay_time >= 0.0f); + Verify(duration_time >= 0.0f); + // Initialize variables + myState = WaitingForTriggerTime; + myEndTimeFlag = !Small_Enough(duration_time); + myTriggerTime = myRenderer->GetCurrentFrameTime(); + myTriggerTime += delay_time; + myTriggerEndTime = myTriggerTime + duration_time; + myTriggerAttribute = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for OneShotDelayRenderable +OneShotDelayRenderable::~OneShotDelayRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the OneShotDelayRenderable +Logical + OneShotDelayRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Verify(myTriggerTime > 0.0f); + Verify(myTriggerEndTime >= myTriggerTime); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the OneShotDelayRenderable +void + OneShotDelayRenderable::Execute() +{ + Scalar + current_time; + // Check our variables + Check(this); + if (myState != WaitingForEternity) + { + current_time = myRenderer->GetCurrentFrameTime(); + // putting this here insures that the one-time will always spend + // at least one frame at True before resetting. + if (myState == WaitingForTriggerTime) + { + if (current_time > myTriggerTime) + { + myTriggerAttribute = 1; + if (myEndTimeFlag) + { + myState = WaitingForTriggerEndTime; + } + else + { + myState = WaitingForEternity; + myRenderer->RemoveDynamicRenderable(this); + } + } + } + else if (myState == WaitingForTriggerEndTime) + { + if (current_time > myTriggerEndTime) + { + myTriggerAttribute = NULL; + myState = WaitingForEternity; + myRenderer->RemoveDynamicRenderable(this); + } + } + else + { + Dump(myState); + Fail("invalid myState"); + } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SweepRenderable +// When triggered this renderable sweeps it's output attribute from 0.0 to 1.0 +// over a preset time interval. Used for controling morphs. +SweepRenderable::SweepRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to take to sweep from 0 to 1 + int cycles, // number of times to cycle before stopping + int *trigger, // When it goes from 0 to 1 it resets the sweep generator + Scalar start_value, // Initial value of sweep (default = 0.0f) + Scalar end_value, // Final value of sweep (default = 1.0f) + SweepFunction sweep_function // Function applied to sweep +): + VideoRenderable(entity, execution_type) +{ + // + // Verify incoming data + // + Verify(delay_time >= 0.0f); + Verify(start_value <= end_value); + if (sweep_function == Y_SQR_X) + { Verify(start_value >= 0.0f); } + // + // Was an input trigger provided? + // + if(trigger) + { + // Yes, remember a pointer to it and it's state + myTrigger = trigger; + oldMyTrigger = *myTrigger; + } + else + { + // No, point it at a fake trigger that is turned on + fakeTrigger = 1; + myTrigger = &fakeTrigger; + oldMyTrigger = 0; + } + // + // Initialize other variables + // + mySweepFunction = sweep_function; + myStartValue = start_value; + myEndValue = end_value; + myCycleCount = cycles; + mySweepTime = delay_time; + mySweepAttribute = myStartValue; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SweepRenderable +SweepRenderable::~SweepRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SweepRenderable +Logical + SweepRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Verify(mySweepTime >= 0.0f) + Verify((mySweepAttribute >= myStartValue) && (mySweepAttribute <= myEndValue)); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SweepRenderable +void + SweepRenderable::Execute() +{ + // Check our variables + Check(this); + // + // Look for an edge in the trigger input + // + if(*myTrigger != oldMyTrigger) + { + // + // A transition from zero to nonzero resets all the sweep parameters + // and starts the process over again. + // + if(oldMyTrigger == 0) + { + // A transition from zero to nonzero causes a reset of sweep timers + // and starts the sweep running. + mySweepStart = myRenderer->GetCurrentFrameTime(); + mySweepAttribute = myStartValue; + myCyclesLeft = myCycleCount; + } + oldMyTrigger = *myTrigger; + } + // + // If the trigger is nonzero and the sweep isn't at 1 yet, update + // the sweep values. + // + if(oldMyTrigger != 0 && myCyclesLeft > 0) + { + Scalar + current_time; + // putting this here insures that the sweep will always spend one frame at + // {EndValue} before resetting. + current_time = myRenderer->GetCurrentFrameTime(); + if(mySweepAttribute >= myEndValue) + { + myCyclesLeft--; + if(myCyclesLeft > 0) + { mySweepStart = current_time; } + } + mySweepAttribute = myStartValue + (myEndValue - myStartValue) * + (current_time - mySweepStart) / mySweepTime; + if (mySweepFunction == Y_SQR_X) + { + mySweepAttribute = Sqrt(mySweepAttribute); + } +// else if (mySweepFunction == Y_ ) +// { +// } + if(mySweepAttribute > myEndValue) + { mySweepAttribute = myEndValue; } + } + // Call the next lower execute method + #if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + #endif + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for PullFogRenderable +// This routine handles swapping the fog settings in and out when you +// turn headlight systems on and off. +// +PullFogRenderable::PullFogRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical *light_1, + Logical *light_2 // address containing the trigger +): + VideoRenderable(entity, execution_type) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(light_1); + myLight1 = light_1; + myOldLight1 = !(*myLight1); + if(light_2 == NULL) + { + myLight2 = myLight1; + } + else + { + Check_Pointer(light_2); + myLight2 = light_2; + } + myOldLight2 = !(*myLight2); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for PullFogRenderable +// +PullFogRenderable::~PullFogRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the PullFogRenderable +// +Logical + PullFogRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myLight1); + Check_Pointer(myLight2); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for PullFogRenderable. +// +void + PullFogRenderable::Execute() +{ + Check(this); + if(*myLight1 != myOldLight1 || *myLight2 != myOldLight2) + { + myOldLight1 = *myLight1; + myOldLight2 = *myLight2; + if(myOldLight1 || myOldLight2) + { + myRenderer->SetFogStyle(DPLRenderer::searchLightOnFogStyle); + } + else + { + myRenderer->SetFogStyle(DPLRenderer::searchLightOffFogStyle); + } + } + // Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLEffectRenderable +// This routine handles the creation of a DPL special effect whenever the +// trigger attribute changes. This is an edge triggered renderable and will +// generate an effect on ANY form of state change. The only way to effect the +// size and speed of the effect is by way of the DPL effect tables. +// +DPLEffectRenderable::DPLEffectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + int effect_type, // DPL effect number to trigger + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) + +): + VideoRenderable(entity, execution_type, parent) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(trigger); + Verify(effect_type >= 0); + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + // + // Initialze the local variables + // + myTrigger = trigger; + oldMyTrigger = *myTrigger; + myEffectType = effect_type; +// myEffectDCS = effect_DCS; + myEffectOffset = *offset_point; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLEffectRenderable +// +DPLEffectRenderable::~DPLEffectRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLEffectRenderable +// +Logical + DPLEffectRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myTrigger); + Verify(myEffectType >= 0); + #if DEBUG_LEVEL > 0 + if(myEffectDCS != NULL) + Check_Pointer(myEffectDCS); + #endif + Check(&myEffectOffset); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLEffectRenderable. +// +void + DPLEffectRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //Check_Pointer(myTrigger); + //if(*myTrigger != oldMyTrigger) + //{ + // dpl_EXPLOSION_EFFECT_INFO my_explosion; + // oldMyTrigger = *myTrigger; + // my_explosion.type = myEffectType; + // my_explosion.x = myEffectOffset.x; + // my_explosion.y = myEffectOffset.y; + // my_explosion.z = myEffectOffset.z; + // dpl_Effect ( dpl_effect_type_explosion, myEffectDCS, &my_explosion ); + //} + //// Call the next lower execute method + //#if DEBUG_LEVEL > 0 + VideoRenderable::Execute(); + // #endif +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLPSFXRenderable +// This routine triggers a pfx whenever the trigger attribute goes true. +// since pfx effects have built-in durations we don't attempt to do any repeats +// or other controls here, we just start one and kill it if the entity dies. +// +DPLPSFXRenderable::DPLPSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) + +): + VideoRenderable(entity, execution_type, parent) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check_Pointer(trigger); + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + if(!psfx_definition) + { + Fail("A pfx was not defined in the .ini file\n"); + } + // + // Initialze the local variables + // + myTrigger = trigger; + myOldTrigger = *myTrigger; +// myEffectDCS = effect_DCS; + myEffectOffset = *offset_point; + myPSFXInfo = *psfx_definition; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLPSFXRenderable +// +DPLPSFXRenderable::~DPLPSFXRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// !!!!HACK Note that because the effect id changes every time we start one, + //// the destructor will only stop the last PFX played. We should probably + //// be keeping track of all the ID's we've sent down to make sure everything + //// attached to the DCS gets properly killed. + //Check(this); + //dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLPSFXRenderable +// +Logical + DPLPSFXRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + Check_Pointer(myTrigger); + #if DEBUG_LEVEL > 0 + if(myEffectDCS != NULL) + Check_Pointer(myEffectDCS); + #endif + Check(&myEffectOffset); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLPSFXRenderable. +// +void + DPLPSFXRenderable::Execute() +{ + Check_Pointer(myTrigger); + if(*myTrigger != myOldTrigger) + { + myOldTrigger = *myTrigger; + if(myOldTrigger == True) + { + // we put our id into the lower 16 bits because (at least) the upper 8 bits are flags + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + //myPSFXInfo.identifier = + // (myPSFXInfo.identifier & 0xffff0000) | + // l4_application->GetVideoRenderer()->GetUniqueID(); + //dpl_Effect ( dpl_effect_type_particlestart, myEffectDCS, &myPSFXInfo ); + } + } + // Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLPSFXStateRenderable +// This routine triggers a pfx whenever a state dial transitions to a designated +// state. +// NOTE this currently does NOT trigger if the state dial is in the trigger state +// when this renderable is created. +// +DPLPSFXStateRenderable::DPLPSFXStateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + StateIndicator *effect_trigger, // Trigger effect when this state changes + unsigned my_trigger, // The state to edge trigger on + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) +): + VideoRenderable(entity, execution_type, parent) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + Check(effect_trigger); + Check_Pointer(psfx_definition); + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + if(!psfx_definition) + { + Fail("A pfx was not defined in the .ini file\n"); + } + // + // Initialze the local variables + // + myTriggerState = my_trigger; + myStateDial = effect_trigger; +// myEffectDCS = effect_DCS; + myEffectOffset = *offset_point; + myPSFXInfo = *psfx_definition; + // + // Add us to the state's watcher socket + // + effect_trigger->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLPSFXStateRenderable +// +DPLPSFXStateRenderable::~DPLPSFXStateRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// !!!!HACK Note that because the effect id changes every time we start one, + //// the destructor will only stop the last PFX played. We should probably + //// be keeping track of all the ID's we've sent down to make sure everything + //// attached to the DCS gets properly killed. + //Check(this); + //dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLPSFXStateRenderable +// +Logical + DPLPSFXStateRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + #if DEBUG_LEVEL > 0 + if(myEffectDCS != NULL) + Check_Pointer(myEffectDCS); + #endif + Check(&myEffectOffset); + Check(myStateDial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLPSFXStateRenderable. +// Note that this will get called by the state dial, not by the renderer +// +void DPLPSFXStateRenderable::Execute() +{ + Check(myStateDial); + // + // If the state dial is in the right state, trigger + // + if(myStateDial->GetState() == myTriggerState) + { + // we put our id into the lower 16 bits because (at least) the upper 8 bits are flags + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + //myPSFXInfo.identifier = + // (myPSFXInfo.identifier & 0xffff0000) | + // l4_application->GetVideoRenderer()->GetUniqueID(); + //dpl_Effect ( dpl_effect_type_particlestart, myEffectDCS, &myPSFXInfo ); + } + // + // Call the next lower execute method + // + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLMaterialRenderable +// This renderable creates a DPL Material structure and encapsulates it so +// it will be properly deleted when the object it's part of gets deleted. +DPLMaterialRenderable::DPLMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red, // Material's ambient component + Scalar ambient_green, + Scalar ambient_blue, + Scalar emissive_red, // Material's emissive component + Scalar emissive_green, + Scalar emissive_blue, + Scalar diffuse_red, // Material's diffuse component + Scalar diffuse_green, + Scalar diffuse_blue, + Scalar specular_red, // Material's specular component + Scalar specular_green, + Scalar specular_blue, + Scalar specular_shininess, + Scalar opacity_red, // Material's opacity + Scalar opacity_green, + Scalar opacity_blue, + dpl_TEXTURE *texture, // Material's texture pointer + Scalar z_dither, // Material's Z dither value + int fog_immune // Material's Fog Imunity value +): + VideoRenderable(entity, execution_type) +{ + //STUBBED: DPL RB 1/14/07 + //// Check input pointers + //#if DEBUG_LEVEL > 0 + //if(texture) + // Check_Pointer(texture); + //#endif + //// Create and initialize the DPL material + //myMaterial = dpl_NewMaterial(); + //Check_Pointer(myMaterial); + //// + //// Materials should be static most of the time, if they are dynamic it means someone + //// inheriting from us is going to try and modify the material. So if we are dynamic + //// we leave the rest of this stuff for that routine to do + //// + //if(execution_type == DPLMaterialRenderable::Static) + //{ + // dpl_SetMaterialAmbient (myMaterial, ambient_red, ambient_green, ambient_blue); + // dpl_SetMaterialEmissive (myMaterial, emissive_red, emissive_green, emissive_blue); + // dpl_SetMaterialDiffuse (myMaterial, diffuse_red, diffuse_green, diffuse_blue); + // dpl_SetMaterialSpecular (myMaterial, specular_red, specular_green, specular_blue, specular_shininess); + // dpl_SetMaterialOpacity (myMaterial, opacity_red, opacity_green, opacity_blue); + // if(texture) + // dpl_SetMaterialTexture(myMaterial, texture); + // if(z_dither) + // dpl_SetMaterialDitherZ(myMaterial, z_dither); + // if(fog_immune) + // dpl_SetMaterialFogImmunity(myMaterial,fog_immune); + // dpl_FlushMaterial(myMaterial); + //} +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLMaterialRenderable +DPLMaterialRenderable::~DPLMaterialRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// Check our structure before we do anything + //Check(this); + //dpl_DeleteMaterial(myMaterial); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLMaterialRenderable +Logical + DPLMaterialRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myMaterial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLMaterialRenderable +void + DPLMaterialRenderable::Execute() +{ + Check(this); + // Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for MorphMaterialRenderable +// This renderable takes two material specifications and loads up a third +// material with a morph between the first two. +MorphMaterialRenderable::MorphMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red_1, // Material's ambient component + Scalar ambient_green_1, + Scalar ambient_blue_1, + Scalar emissive_red_1, // Material's emissive component + Scalar emissive_green_1, + Scalar emissive_blue_1, + Scalar diffuse_red_1, // Material's diffuse component + Scalar diffuse_green_1, + Scalar diffuse_blue_1, + Scalar specular_red_1, // Material's specular component + Scalar specular_green_1, + Scalar specular_blue_1, + Scalar specular_shininess_1, + Scalar opacity_red_1, // Material's opacity + Scalar opacity_green_1, + Scalar opacity_blue_1, + dpl_TEXTURE *texture_1, // Material's texture pointer + Scalar z_dither_1, // Material's Z dither value + int fog_immune_1, // Material's Fog Imunity value + Scalar ambient_red_2, // Material's ambient component + Scalar ambient_green_2, + Scalar ambient_blue_2, + Scalar emissive_red_2, // Material's emissive component + Scalar emissive_green_2, + Scalar emissive_blue_2, + Scalar diffuse_red_2, // Material's diffuse component + Scalar diffuse_green_2, + Scalar diffuse_blue_2, + Scalar specular_red_2, // Material's specular component + Scalar specular_green_2, + Scalar specular_blue_2, + Scalar specular_shininess_2, + Scalar opacity_red_2, // Material's opacity + Scalar opacity_green_2, + Scalar opacity_blue_2, + Scalar z_dither_2, // Material's Z dither value + Scalar *morph_control +): +DPLMaterialRenderable( + entity, // Entity to attach the renderable to + execution_type, + ambient_red_1, ambient_green_1, ambient_blue_1, // Material's ambient component + emissive_red_1, emissive_green_1, emissive_blue_1, // Material's emissive component + diffuse_red_1, diffuse_green_1, diffuse_blue_1, // Material's diffuse component + specular_red_1, specular_green_1, specular_blue_1, specular_shininess_1, // Material's specular component + opacity_red_1, opacity_green_1, opacity_blue_1, // Material's opacity + texture_1, // Material's texture pointer + z_dither_1, // Material's Z dither value + fog_immune_1) // Material's Fog Imunity value +{ + //STUBBED: DPL RB 1/14/07 + //Scalar + // Weight1, + // Weight2; + //// + //// Remember the parameters of the two materials we are morphing between + //// + //myAmbientRed1 = ambient_red_1; // Material's ambient component + //myAmbientGreen1 = ambient_green_1; + //myAmbientBlue1 = ambient_blue_1; + //myEmissiveRed1 = emissive_red_1; // Material's emissive component + //myEmissiveGreen1 = emissive_green_1; + //myEmissiveBlue1 = emissive_blue_1; + //myDiffuseRed1 = diffuse_red_1; // Material's diffuse component + //myDiffuseGreen1 = diffuse_green_1; + //myDiffuseBlue1 = diffuse_blue_1; + //mySpecularRed1 = specular_red_1; // Material's specular component + //mySpecularGreen1 = specular_green_1; + //mySpecularBlue1 = specular_blue_1; + //mySpecularShininess1 = specular_shininess_1; + //myOpacityRed1 = opacity_red_1; // Material's opacity + //myOpacityGreen1 = opacity_green_1; + //myOpacityBlue1 = opacity_blue_1; + //myTexture1 = texture_1; // Material's texture pointer + //myZDither1 = z_dither_1; // Material's Z dither value + //myFogImmune1 = fog_immune_1; // Material's Fog Imunity value + //myAmbientRed2 = ambient_red_2; // Material's ambient component + //myAmbientGreen2 = ambient_green_2; + //myAmbientBlue2 = ambient_blue_2; + //myEmissiveRed2 = emissive_red_2; // Material's emissive component + //myEmissiveGreen2 = emissive_green_2; + //myEmissiveBlue2 = emissive_blue_2; + //myDiffuseRed2 = diffuse_red_2; // Material's diffuse component + //myDiffuseGreen2 = diffuse_green_2; + //myDiffuseBlue2 = diffuse_blue_2; + //mySpecularRed2 = specular_red_2; // Material's specular component + //mySpecularGreen2 = specular_green_2; + //mySpecularBlue2 = specular_blue_2; + //mySpecularShininess2 = specular_shininess_2; + //myOpacityRed2 = opacity_red_2; // Material's opacity + //myOpacityGreen2 = opacity_green_2; + //myOpacityBlue2 = opacity_blue_2; + //myZDither2 = z_dither_2; // Material's Z dither value + //myMorphControl = morph_control; + //oldMorphControl = *morph_control; + //// + //// Calculate the target material + //// + //Weight1 = 1.0 - oldMorphControl; + //Weight2 = oldMorphControl; + //myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); + //myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); + //myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); + //myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); + //myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); + //myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); + //myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); + //myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); + //myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); + //mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); + //mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); + //mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); + //mySpecularShininess = (mySpecularShininess1*Weight1) + (mySpecularShininess2*Weight2); + //myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); + //myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); + //myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); + //myZDither = (myZDither1*Weight1) + (myZDither2*Weight2); + //// + //// Initialize the target material + //// + //dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); + //dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); + //dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); + //dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); + //dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); + //if(myTexture1) + // dpl_SetMaterialTexture(myMaterial, myTexture1); + //if(myZDither) + // dpl_SetMaterialDitherZ(myMaterial,myZDither); + //if(myFogImmune1) + // dpl_SetMaterialFogImmunity(myMaterial,myFogImmune1); + //dpl_FlushMaterial(myMaterial); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for MorphMaterialRenderable +MorphMaterialRenderable::~MorphMaterialRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the MorphMaterialRenderable +Logical + MorphMaterialRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the MorphMaterialRenderable +void + MorphMaterialRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + //Scalar + // Weight1, + // Weight2; + + //Check(this); + //// See if the morph control variable has changed + //if(oldMorphControl != *myMorphControl) + //{ + // // + // // Re-calculate the target material + // // + // oldMorphControl = *myMorphControl; + // Weight1 = 1.0 - oldMorphControl; + // Weight2 = oldMorphControl; + // myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); + // myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); + // myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); + // myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); + // myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); + // myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); + // myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); + // myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); + // myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); + // mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); + // mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); + // mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); + // mySpecularShininess = (mySpecularShininess1*Weight1) + (mySpecularShininess2*Weight2); + // myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); + // myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); + // myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); + // myZDither = (myZDither1*Weight1) + (myZDither2*Weight2); + // // + // // Reset the target material and std::flush it + // // Note we don't try to morph texture or fog immune + // // + // dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); + // dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); + // dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); + // dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); + // dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); + // if(myZDither) + // dpl_SetMaterialDitherZ(myMaterial,myZDither); + // dpl_FlushMaterial(myMaterial); + //} + //// Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLDamageMaterialRenderable +// This renderable handles modifying a material in response to damage. We +// get the pointer to an existing DPL material on startup and we get out +// color and texture settings from that +DPLDamageMaterialRenderable::DPLDamageMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_MATERIAL *damage_material, // The material we want to control + Scalar *damage_attribute, // The attribute containing the current damage level + Scalar damage_percent // Degradation factor to make damaged material +): + VideoRenderable(entity, execution_type) +{ +//STUBBED: DPL RB 1/14/07 +// Scalar +// Weight1, +// Weight2; +// +// Check_Pointer(damage_material); +// Check_Pointer(damage_attribute); +// Verify(damage_percent >= 0.0f && damage_percent <= 1.0f); +// // +// // Grab the material's components, remember them and figure the target colors +// // +// myMaterial = damage_material; +// myDamageAttribute = damage_attribute; +// oldDamageAttribute = *myDamageAttribute; +// dpl_GetMaterialAmbient (myMaterial, &myAmbientRed1, &myAmbientGreen1, &myAmbientBlue1); +// dpl_GetMaterialEmissive (myMaterial, &myEmissiveRed1, &myEmissiveGreen1, &myEmissiveBlue1); +// dpl_GetMaterialDiffuse (myMaterial, &myDiffuseRed1, &myDiffuseGreen1, &myDiffuseBlue1); +// dpl_GetMaterialSpecular (myMaterial, &mySpecularRed1, &mySpecularGreen1, &mySpecularBlue1, &mySpecularShininess1); +// dpl_GetMaterialOpacity (myMaterial, &myOpacityRed1, &myOpacityGreen1, &myOpacityBlue1); +// myAmbientRed2 = damage_percent * myAmbientRed1; // Material's ambient component +// myAmbientGreen2 = damage_percent * myAmbientGreen1; +// myAmbientBlue2 = damage_percent * myAmbientBlue1; +// myEmissiveRed2 = damage_percent * myEmissiveRed1; // Material's emissive component +// myEmissiveGreen2 = damage_percent * myEmissiveGreen1; +// myEmissiveBlue2 = damage_percent * myEmissiveBlue1; +// myDiffuseRed2 = damage_percent * myDiffuseRed1; // Material's diffuse component +// myDiffuseGreen2 = damage_percent * myDiffuseGreen1; +// myDiffuseBlue2 = damage_percent * myDiffuseBlue1; +// mySpecularRed2 = damage_percent * mySpecularRed1; // Material's specular component +// mySpecularGreen2 = damage_percent * mySpecularGreen1; +// mySpecularBlue2 = damage_percent * mySpecularBlue1; +// mySpecularShininess2 = damage_percent * mySpecularShininess1; +// myOpacityRed2 = damage_percent * myOpacityRed1; // Material's opacity +// myOpacityGreen2 = damage_percent * myOpacityGreen1; +// myOpacityBlue2 = damage_percent * myOpacityBlue1; +// // +// // Calculate the target material using the current level of damage +// // +// Weight1 = 1.0f - oldDamageAttribute; +// Weight2 = oldDamageAttribute; +// myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); +// myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); +// myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); +// myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); +// myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); +// myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); +// myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); +// myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); +// myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); +// mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); +// mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); +// mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); +// mySpecularShininess = (mySpecularShininess1*Weight1)+ (mySpecularShininess2*Weight2); +// myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); +// myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); +// myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); +// // +// // Set the target material +// // +// dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); +// dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); +// dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); +// dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); +//// dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); +// dpl_FlushMaterial(myMaterial); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLDamageMaterialRenderable +DPLDamageMaterialRenderable::~DPLDamageMaterialRenderable() +{ + // Check our structure before we do anything + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLDamageMaterialRenderable +Logical + DPLDamageMaterialRenderable::TestInstance() const +{ + // Call our parent's TestInstance first + VideoRenderable::TestInstance(); + Check_Pointer(myMaterial); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLDamageMaterialRenderable +void + DPLDamageMaterialRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 +// Scalar +// Weight1, +// Weight2; +// +// Check(this); +// if(oldDamageAttribute != *myDamageAttribute) +// { +// // +// // Re-calculate the target material +// // +// oldDamageAttribute = *myDamageAttribute; +// Weight1 = 1.0 - oldDamageAttribute; +// Weight2 = oldDamageAttribute; +// myAmbientRed = (myAmbientRed1*Weight1) + (myAmbientRed2*Weight2); +// myAmbientGreen = (myAmbientGreen1*Weight1) + (myAmbientGreen2*Weight2); +// myAmbientBlue = (myAmbientBlue1*Weight1) + (myAmbientBlue2*Weight2); +// myEmissiveRed = (myEmissiveRed1*Weight1) + (myEmissiveRed2*Weight2); +// myEmissiveGreen = (myEmissiveGreen1*Weight1) + (myEmissiveGreen2*Weight2); +// myEmissiveBlue = (myEmissiveBlue1*Weight1) + (myEmissiveBlue2*Weight2); +// myDiffuseRed = (myDiffuseRed1*Weight1) + (myDiffuseRed2*Weight2); +// myDiffuseGreen = (myDiffuseGreen1*Weight1) + (myDiffuseGreen2*Weight2); +// myDiffuseBlue = (myDiffuseBlue1*Weight1) + (myDiffuseBlue2*Weight2); +// mySpecularRed = (mySpecularRed1*Weight1) + (mySpecularRed2*Weight2); +// mySpecularGreen = (mySpecularGreen1*Weight1) + (mySpecularGreen2*Weight2); +// mySpecularBlue = (mySpecularBlue1*Weight1) + (mySpecularBlue2*Weight2); +// mySpecularShininess = (mySpecularShininess1*Weight1)+ (mySpecularShininess2*Weight2); +// myOpacityRed = (myOpacityRed1*Weight1) + (myOpacityRed2*Weight2); +// myOpacityGreen = (myOpacityGreen1*Weight1) + (myOpacityGreen2*Weight2); +// myOpacityBlue = (myOpacityBlue1*Weight1) + (myOpacityBlue2*Weight2); +// // +// // Reset the target material and std::flush it +// // +// dpl_SetMaterialAmbient (myMaterial, myAmbientRed, myAmbientGreen, myAmbientBlue); +// dpl_SetMaterialEmissive (myMaterial, myEmissiveRed, myEmissiveGreen, myEmissiveBlue); +// dpl_SetMaterialDiffuse (myMaterial, myDiffuseRed, myDiffuseGreen, myDiffuseBlue); +// dpl_SetMaterialSpecular (myMaterial, mySpecularRed, mySpecularGreen, mySpecularBlue, mySpecularShininess); +//// dpl_SetMaterialOpacity (myMaterial, myOpacityRed, myOpacityGreen, myOpacityBlue); +// dpl_FlushMaterial(myMaterial); +// } +// // Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~End of the new renderable class hiearchy~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~Dynamic Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~these renderables allow things to change after construction~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//############################################################################# +// This is the DPLEyeRenderable class. This is a DYNAMIC renderable that +// places the renderer's eyepoint relative to some other DCS/renderable. +// At the moment the eyepoint won't actually move in response to an argument +// but this will be changed after we have something to hook the eye to. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLEyeRenderable +// All the arguments are required. +// +DPLEyeRenderable::DPLEyeRenderable( + Entity* This_Entity, + const LinearMatrix& Offset_Matrix, + HierarchicalDrawComponent* parent, + EulerAngles* eyepoint_rotation // Pointer to attribute that contains eye rotations +): + HierarchicalDrawComponent(TrivialNodeClassID, parent) +{ +//STUBBED: DPL RB 1/14/07 +// // +// // Check the inbound data +// // + Check(This_Entity); + Check(&Offset_Matrix); + Check_Pointer(Parent_DCS); + #if DEBUG_LEVEL > 0 + if(eyepoint_rotation) + Check(eyepoint_rotation); + #endif + // + // Remember the entity that this renderable is attached to and the + // orientation matrix that sets the eye location + // + myEntity = This_Entity; +// myParentDCS = Parent_DCS; + myOrientationMatrix = Offset_Matrix; + myEyepointRotation = eyepoint_rotation; + if(myEyepointRotation) + { + oldEyepointRotation = *myEyepointRotation; + } + else + { + oldEyepointRotation = NULL; + } + // + // Create the dpl DCS for this renderable, connect it to it's parent + // and set it into the current zone. + // + // myDCS = dpl_NewDCS (); + // Check_Pointer(myDCS); + // dpl_AddDCSToDCS ( myParentDCS, myDCS ); + // dpl_SetDCSZone ( myDCS, This_Zone ); + // + // Load up the DCS matrix with the supplied matrix + // + // float32* dplMatrix = dpl_GetDCSMatrix(myDCS); + // Check_Pointer(dplMatrix); + // *((Matrix4x4*)dplMatrix) = rotation_matrix; + // + // float32* tempMatrix = dpl_GetDCSMatrix(myDCS); + // Check_Pointer(tempMatrix); + // *(Matrix4x4*)tempMatrix = OrientationMatrix; + // + // Flush out the instance and DCS + // + // dpl_SetViewDCS ( This_View, myDCS); + // dpl_FlushView ( This_View); + // dpl_FlushDCS ( myDCS ); + + // myEntity->AddDynamicVideoComponent(this); + // + // HACK HACK this needs to be folded back into the new videorenderable hiearchy + // +// myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); + //l4_application->GetVideoRenderer()->mDeathRenderables.Add(this); + myDevice = l4_application->GetVideoRenderer()->GetDevice(); + + camMatrix = myOrientationMatrix; + if (myEyepointRotation) + { + Matrix4x4 rotation; + rotation = *myEyepointRotation; + //camMatrix.entries[14] /= 1.1f; + camMatrix *= rotation; + } + + Matrix4x4 mat4; + mat4 = camMatrix; + Matrix4x4 prev; + prev = *myRenderer->GetMatrixStack()->GetTop(); + mat4 *= prev; + LinearMatrix mat(True); + mat = mat4; + + D3DXVECTOR3 pos(mat(3,0), mat(3, 1), mat(3,2)); + mat(3,0) = 0; + mat(3,1) = 0; + mat(3,2) = 0; + + Matrix4x4 temp; + temp = mat; + D3DXMATRIX drot = temp.ToD3DMatrix(); + D3DXVECTOR3 at(0,0,1); + D3DXVECTOR3 up(0,1,0); + + at.x = drot._31 + drot._41; + at.y = drot._32 + drot._42; + at.z = drot._33 + drot._43; + at += pos; + + up.x = drot._21 + drot._41; + up.y = drot._22 + drot._42; + up.z = drot._23 + drot._43; + + //D3DXVECTOR3 dir; + //D3DXVec3Subtract(&dir,&at, &pos); + //D3DXVec3Normalize(&dir, &dir); + //D3DXVec3Scale(&dir, &dir, 50); + //D3DXVec3Subtract(&pos, &pos, &dir); + + D3DXMATRIX view; + D3DXMatrixLookAtRH(&view,&pos,&at,&up); + + //myDevice->SetTransform(D3DTS_VIEW, &view); + + oldLocalToWorld = myEntity->localToWorld; + mForceUpdate = true; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLEyeRenderable +// After calling this the eyepoint must be relocated to another DCS before +// the execute method of the renderer is called. +// +DPLEyeRenderable::~DPLEyeRenderable() +{ +//STUBBED: DPL RB 1/14/07 +// Check(this); +//// Below is probably unnecessary as the parent should be destroyed too +//// but Phil is making a patch to allow us to check that. +//// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); +// dpl_DeleteDCS(myDCS); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLEyeRenderable +// +Logical + DPLEyeRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer(myDCS); + Check_Pointer(myParentDCS); + Check(&myOrientationMatrix); + Check(myEntity); + if(myEyepointRotation) + { + Check(myEyepointRotation); + } + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLEyeRenderable. +// +void + DPLEyeRenderable::Execute() +{ + //STUBBED: DPL RB 1/14/07 + // + //---------------------------------------------------------------------- + // If we have an eyepoint rotation specified, generate a new matrix each + // time based upon the setting of the eyepoint rotation + //---------------------------------------------------------------------- + // + if((myEyepointRotation && *myEyepointRotation != oldEyepointRotation) || oldLocalToWorld != myEntity->localToWorld || mForceUpdate) + { + mForceUpdate = false; + oldLocalToWorld = myEntity->localToWorld; + + if (myEyepointRotation) + { + oldEyepointRotation = *myEyepointRotation; + camMatrix = *myEyepointRotation; + } + else + camMatrix = Matrix4x4::Identity; + camMatrix *= myOrientationMatrix; + + myRenderer->GetMatrixStack()->Push(); + Matrix4x4 mat4; + mat4 = camMatrix; + Matrix4x4 prev; + prev = *myRenderer->GetMatrixStack()->GetTop(); + mat4 *= prev; + LinearMatrix mat(True); + mat = mat4; + + D3DXVECTOR3 pos(mat(3,0), mat(3, 1), mat(3,2)); + mat(3,0) = 0; + mat(3,1) = 0; + mat(3,2) = 0; + + Matrix4x4 temp; + temp = mat; + D3DXMATRIX drot = temp.ToD3DMatrix(); + D3DXVECTOR3 at(0,0,1); + D3DXVECTOR3 up(0,1,0); + + at.x = drot._31 + drot._41; + at.y = drot._32 + drot._42; + at.z = drot._33 + drot._43; + at += pos; + + up.x = drot._21 + drot._41; + up.y = drot._22 + drot._42; + up.z = drot._23 + drot._43; + + //D3DXVECTOR3 dir; + //D3DXVec3Subtract(&dir,&at, &pos); + //D3DXVec3Normalize(&dir, &dir); + //D3DXVec3Scale(&dir, &dir, 10.0f); + //D3DXVec3Add(&pos, &pos, &dir); + //D3DXVec3Add(&pos, &pos, &(D3DXVECTOR3(0, 0.15f, 0))); + //D3DXVec3Add(&at, &pos,&( D3DXVECTOR3(0, 0, 1))); + + D3DXMATRIX view; + D3DXMatrixLookAtRH(&view,&pos,&at,&up); + + myDevice->SetTransform(D3DTS_VIEW, &view); + myRenderer->GetMatrixStack()->Pop(); + } + + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&camMatrix.ToD3DMatrix()); + HierarchicalDrawComponent::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} + +// +//############################################################################# +// This is the DPLChildPointRenderable class. This is a dynamic renderable that +// lets you build a translating joint between two objects. If you supply a +// NULL Graphic_Object pointer when constructing the renderable it will be +// built without hooking up an instance of a graphical object. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLChildPointRenderable +// +DPLChildPointRenderable::DPLChildPointRenderable( + Entity* This_Entity, + bool isDeathZone, + d3d_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + HierarchicalDrawComponent *Parent, + Point3D *my_point +): + HierarchicalDrawComponent(TrivialNodeClassID, Parent) +{ + isDeathDraw = isDeathZone; + +//STUBBED: DPL RB 1/14/07 +// +// Check the inbound data +// + Check(This_Entity); + Check_Pointer(This_Zone); + #if DEBUG_LEVEL > 0 + if(Graphic_Object != NULL) + Check_Pointer(Graphic_Object); + #endif + Check(&Offset_Matrix); + //Check_Pointer(Parent_DCS); + Check(my_point); +// +// Remember the entity that this renderable is attached to and the +// orientation matrix that sets the eye location +// + myEntity = This_Entity; +// myParentDCS = Parent_DCS; + myPoint = my_point; + OrientationMatrix = Offset_Matrix; + OldPoint = *my_point; +// +// Create the dpl DCS, add it to the parent DCS, set it into the current zone, +// and stuff the orientation matrix into it +// +// myOffsetDCS = dpl_NewDCS(); + //Check_Pointer ( myOffsetDCS ); +// dpl_AddDCSToDCS ( myParentDCS, myOffsetDCS ); +// dpl_SetDCSZone ( myOffsetDCS, This_Zone ); + +// myDCS = dpl_NewDCS(); + Check_Pointer ( myDCS ); +// dpl_AddDCSToDCS ( myOffsetDCS, myDCS ); +// dpl_SetDCSZone ( myDCS, This_Zone ); +// +// Setup the offset matrix in the offset DCS +// +// float32* tempMatrix = dpl_GetDCSMatrix( myOffsetDCS ); + Check_Pointer ( tempMatrix ); +// *(Matrix4x4*)tempMatrix = OrientationMatrix; +// +// Setup the initial state of the hinge joint +// +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); +// *(Matrix4x4*)tempMatrix2 = *myPoint; +// +// If there was a graphic, create an instance with that graphic in it and link +// it to the DCS. +// + graphicalObject = Graphic_Object; + Matrix4x4 temp,temp2; + temp = OrientationMatrix; + temp2 = *myPoint; + temp *= temp2; + HierarchicalDrawComponent::SetLocalToWorld(&temp.ToD3DMatrix()); + //if(Graphic_Object == NULL) + //{ + // graphicalObject = myObject; + //} + //else + //{ +// myInstance = dpl_NewInstance(); + //Check_Pointer ( myInstance ); +// dpl_SetInstanceObject ( myInstance, Graphic_Object ); +// dpl_SetInstanceIntersect ( myInstance, Intersect_Mode ); +// dpl_SetInstanceSectMask ( myInstance, Intersect_Mask ); +// dpl_SetInstanceVisibility ( myInstance, 1 ); +// dpl_AddInstanceToDCS ( myDCS, myInstance ); +// dpl_FlushInstance ( myInstance ); + //} +// +// Flush out the DCS and add this to the static component list +// +// dpl_FlushDCS ( myOffsetDCS ); +// dpl_FlushDCS ( myDCS ); +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + //l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLChildPointRenderable +// + +DPLChildPointRenderable::~DPLChildPointRenderable() +{ +// Check(this); +//// Below is probably unnecessary as the parent should be destroyed too +//// but Phil is making a patch to allow us to check that. +//// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); +// +// dpl_DeleteDCS(myDCS); +// dpl_DeleteDCS(myOffsetDCS); +// if(myInstance != NULL) +// { +// dpl_DeleteInstance(myInstance); +// } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLChildPointRenderable +// This method should really use a watcher to make sure the position of the +// object has changed before updating the DCS matrix. +// +void + DPLChildPointRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 +// Check(this); +//// +//// Load up the DCS matrix with the localToWorld matrix from the entity +//// then std::flush out the new DCS +//// +// if(OldPoint != *myPoint) +// { +// OldPoint = *myPoint; +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); +// *(Matrix4x4*)tempMatrix2 = OldPoint; +// HACK_DPL_FLUSH_DCS ( myDCS ); +// } + + myRenderer->GetMatrixStack()->Push(); + Matrix4x4 temp,temp2; + temp = OrientationMatrix; + temp2 = *myPoint; + temp *= temp2; + myRenderer->GetMatrixStack()->MultMatrixLocal(&temp.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + HierarchicalDrawComponent::Execute(); + myRenderer->GetMatrixStack()->Pop(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLChildPointRenderable +// +Logical + DPLChildPointRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer ( myDCS ); + Check_Pointer ( myParentDCS ); + Check_Pointer ( myOffsetDCS ); + Check(myPoint); + if(myInstance != NULL) + { + Check_Pointer(myInstance); + } + Check(&OrientationMatrix); + Check(myEntity); + + return True; +} +// +//############################################################################# +// This is the DPLScaleRenderable class. This is a dynamic renderable that +// lets you scale everything downstream of it in the hiearchy. It is also +// setup to switch it's own instances on and off based on the value in visible. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLScaleRenderable +// +DPLScaleRenderable::DPLScaleRenderable( + Entity* This_Entity, + bool isDeathZone, + d3d_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + HierarchicalDrawComponent *Parent, + Vector3D *scale_vector, + Logical *visible +): + HierarchicalDrawComponent(TrivialNodeClassID, Parent) +{ + isDeathDraw = isDeathZone; + +//STUBBED: DPL RB 1/14/07 +//// +//// Check the inbound data +//// +// Check(This_Entity); +// Check_Pointer(This_Zone); +// Check_Pointer(Graphic_Object); +// Check(&Offset_Matrix); +// Check_Pointer(Parent_DCS); +// Check(scale_vector); +// Check_Pointer(visible); +//// +//// Remember the entity that this renderable is attached to and the +//// orientation matrix that offsets it to the correct position. +//// + myEntity = This_Entity; +// myParentDCS = Parent_DCS; + myScaleVector = scale_vector; + myVisible = visible; + OffsetMatrix = Offset_Matrix; + OldScaleVector = *scale_vector; + OldVisible = *visible; + myObject = Graphic_Object; +//// +//// Create the dpl DCS, add it to the parent DCS, set it into the current zone, +//// and stuff the orientation matrix into it +//// +// myDCS = dpl_NewDCS(); +// Check_Pointer ( myDCS ); +// dpl_AddDCSToDCS ( myParentDCS, myDCS ); +// dpl_SetDCSZone ( myDCS, This_Zone ); +// +// Setup the dcs matrix to it's initial state +// +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine *= OldScaleVector; + tempAffine *= OffsetMatrix; + transMatrix = tempAffine; +// *(Matrix4x4*)tempMatrix = tempAffine; +//// +//// If there was a graphic, create an instance with that graphic in it and link +//// it to the DCS. +//// +// myInstance = dpl_NewInstance(); +// Check_Pointer ( myInstance ); +// dpl_SetInstanceObject ( myInstance, Graphic_Object ); +// dpl_SetInstanceIntersect ( myInstance, Intersect_Mode ); +// dpl_SetInstanceSectMask ( myInstance, Intersect_Mask ); +// dpl_SetInstanceVisibility ( myInstance, OldVisible ); +// dpl_AddInstanceToDCS ( myDCS, myInstance ); +// dpl_FlushInstance ( myInstance ); +//// +//// Flush out the DCS and add this to the static component list +//// +// dpl_FlushDCS ( myDCS ); +//// myEntity->AddDynamicVideoComponent(this); +//// +//// HACK HACK this needs to be folded back into the new videorenderable hiearchy +// myEntity->AddStaticVideoComponent(this); +// L4Application *l4_application = Cast_Object(L4Application*, application); +// Check(l4_application); +// l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLScaleRenderable +// + +DPLScaleRenderable::~DPLScaleRenderable() +{ +//STUBBED: DPL RB 1/14/07 +// Check(this); +//// Below is probably unnecessary as the parent should be destroyed too +//// but Phil is making a patch to allow us to check that. +//// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); +// +// dpl_DeleteDCS(myDCS); +// dpl_DeleteInstance(myInstance); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLScaleRenderable +// This method should really use a watcher to make sure the position of the +// object has changed before updating the DCS matrix. +// +void + DPLScaleRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 +// Check(this); +// +// Load up the DCS matrix with the localToWorld matrix from the entity +// then std::flush out the new DCS +// + if(OldVisible != *myVisible) + { + OldVisible = *myVisible; +// dpl_SetInstanceVisibility ( myInstance, OldVisible ); +// dpl_FlushInstance ( myInstance ); + } + + if(OldScaleVector != *myScaleVector) + { + OldScaleVector = *myScaleVector; +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine *= OldScaleVector; + tempAffine *= OffsetMatrix; + transMatrix = tempAffine; +// *(Matrix4x4*)tempMatrix2 = tempAffine; +// HACK_DPL_FLUSH_DCS ( myDCS ); + } + + if (!(*myVisible)) + { + graphicalObject = NULL; + } else + { + graphicalObject = myObject; + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&transMatrix.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + HierarchicalDrawComponent::Execute(); + myRenderer->GetMatrixStack()->Pop(); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLChildRenderable +// +Logical + DPLScaleRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer ( myDCS ); + Check_Pointer ( myParentDCS ); + Check_Pointer(myInstance); + Check(&OffsetMatrix); + Check(myEntity); + Check(myScaleVector); + + return True; +} +// +//############################################################################# +// This is the DPLScaleQuatRenderable class. This is a dynamic renderable that +// lets you control joint position with a Quaternion, Scale with a vector and +// switch the instance on and off with a logical. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLScaleQuatRenderable +// +DPLScaleQuatRenderable::DPLScaleQuatRenderable( + Entity* This_Entity, + bool isDeathZone, + d3d_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + HierarchicalDrawComponent *Parent, + Quaternion *rotation_quaternion, + Vector3D *scale_vector, + Logical *visible +): + HierarchicalDrawComponent(TrivialNodeClassID, Parent) +{ + isDeathDraw = isDeathZone; + +//STUBBED: DPL RB 1/14/07 + Quaternion my_quat; +//// +//// Check the inbound data +//// +// Check(This_Entity); +// Check_Pointer(This_Zone); +// Check_Pointer(Graphic_Object); +// Check(&Offset_Matrix); +// Check_Pointer(Parent_DCS); +// Check(rotation_quaternion); +// Check(scale_vector); +// Check_Pointer(visible); +// +// Remember the entity that this renderable is attached to and the +// orientation matrix that offsets it to the correct position. +// + myEntity = This_Entity; +// myParentDCS = Parent_DCS; + myRotationQuaternion = rotation_quaternion; + myScaleVector = scale_vector; + myVisible = visible; + OffsetMatrix = Offset_Matrix; + OldRotationQuaternion = *rotation_quaternion; + OldScaleVector = *scale_vector; + OldVisible = *visible; + myObject = Graphic_Object; +//// +//// Create the dpl DCS, add it to the parent DCS, set it into the current zone, +//// and stuff the orientation matrix into it +//// +// myDCS = dpl_NewDCS(); +// Check_Pointer ( myDCS ); +// dpl_AddDCSToDCS ( myParentDCS, myDCS ); +// dpl_SetDCSZone ( myDCS, This_Zone ); +// +// Setup the dcs matrix to it's initial state +// +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); +// tempAffine.Multiply(OldRotationQuaternion,OffsetMatrix); + tempAffine *= OldScaleVector; + tempAffine *= OldRotationQuaternion; + tempAffine *= OffsetMatrix; + tempMatrix = tempAffine; +// *(Matrix4x4*)tempMatrix = tempAffine; +//// +//// If there was a graphic, create an instance with that graphic in it and link +//// it to the DCS. +//// +// myInstance = dpl_NewInstance(); +// Check_Pointer ( myInstance ); +// dpl_SetInstanceObject ( myInstance, Graphic_Object ); +// dpl_SetInstanceIntersect ( myInstance, Intersect_Mode ); +// dpl_SetInstanceSectMask ( myInstance, Intersect_Mask ); +// dpl_SetInstanceVisibility ( myInstance, OldVisible ); +// dpl_AddInstanceToDCS ( myDCS, myInstance ); +// dpl_FlushInstance ( myInstance ); +//// +//// Flush out the DCS and add this to the static component list +//// +// dpl_FlushDCS ( myDCS ); +//// myEntity->AddDynamicVideoComponent(this); +//// +//// HACK HACK this needs to be folded back into the new videorenderable hiearchy +// myEntity->AddStaticVideoComponent(this); +// L4Application *l4_application = Cast_Object(L4Application*, application); +// Check(l4_application); +// l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLScaleQuatRenderable +// + +DPLScaleQuatRenderable::~DPLScaleQuatRenderable() +{ +//STUBBED: DPL RB 1/14/07 +// Check(this); +//// Below is probably unnecessary as the parent should be destroyed too +//// but Phil is making a patch to allow us to check that. +//// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); +// +// dpl_DeleteDCS(myDCS); +// dpl_DeleteInstance(myInstance); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the DPLScaleQuatRenderable +// This method should really use a watcher to make sure the position of the +// object has changed before updating the DCS matrix. +// +void + DPLScaleQuatRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 + Check(this); +// +// Load up the DCS matrix with the localToWorld matrix from the entity +// then std::flush out the new DCS +// + if(OldVisible != *myVisible) + { + OldVisible = *myVisible; +// dpl_SetInstanceVisibility ( myInstance, OldVisible ); +// dpl_FlushInstance ( myInstance ); + } + + // + // The memcmp below is sort of a HACK but all I really care about is if the + // value in the quaternion has been changed since last time I saw it, this + // seems to be the easiest way to find out as JM hasn't written an == operator + // + if((OldScaleVector != *myScaleVector) || + (memcmp(&OldRotationQuaternion,myRotationQuaternion, sizeof(Quaternion)) != 0)) + { + OldScaleVector = *myScaleVector; + OldRotationQuaternion = *myRotationQuaternion; +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); +// tempAffine.Multiply(OldRotationQuaternion,OffsetMatrix); + tempAffine *= OldScaleVector; + tempAffine *= OldRotationQuaternion; + tempAffine *= OffsetMatrix; + tempMatrix = tempAffine; +// *(Matrix4x4*)tempMatrix2 = tempAffine; +// HACK_DPL_FLUSH_DCS ( myDCS ); + } + + if (!(*myVisible)) + { + graphicalObject = NULL; + } else + { + graphicalObject = myObject; + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&tempMatrix.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + HierarchicalDrawComponent::Execute(); + myRenderer->GetMatrixStack()->Pop(); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLScaleQuatRenderable +// +Logical + DPLScaleQuatRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer ( myDCS ); + Check_Pointer ( myParentDCS ); + Check_Pointer(myInstance); + Check(&OffsetMatrix); + Check(myEntity); + Check(myRotationQuaternion); + Check(myScaleVector); + Check_Pointer(myVisible); + + return True; +} +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~Static Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~these renderables remain constant after construction~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +// +//############################################################################# +// This is the DPLStaticChildRenderable class. This is a STATIC renderable that +// lets you build a DCS that is a child of a pre-existing DCS. If you supply a +// NULL Graphic_Object pointer when constructing the renderable it will be +// built without hooking up an instance of a graphical object. +//############################################################################# +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for the DPLStaticChildRenderable +// +DPLStaticChildRenderable::DPLStaticChildRenderable( + Entity* This_Entity, + bool isDeathZone, + d3d_OBJECT* Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix& Offset_Matrix, + HierarchicalDrawComponent* Parent +): + HierarchicalDrawComponent(TrivialNodeClassID, Parent) +{ + isDeathDraw = isDeathZone; + +//STUBBED: DPL RB 1/14/07 + // + // Check the inbound data + // + Check(This_Entity); + Check_Pointer(This_Zone); + Check(&Offset_Matrix); + //Check_Pointer(Parent_DCS); +// #if DEBUG_LEVEL > 0 + if(Graphic_Object != NULL) + Check_Pointer(Graphic_Object); +// #endif + // + // Remember the entity that this renderable is attached to and the + // orientation matrix that sets the eye location + // + myEntity = This_Entity; +// myParentDCS = Parent_DCS; + OrientationMatrix = Offset_Matrix; + graphicalObject = Graphic_Object; + // + // Create the dpl DCS, add it to the parent DCS, set it into the current zone, + // and stuff the orientation matrix into it + // +// myDCS = dpl_NewDCS(); +// Check_Pointer(myDCS); +// dpl_AddDCSToDCS( myParentDCS, myDCS); +// dpl_SetDCSZone(myDCS, This_Zone); +// float32* tempMatrix = dpl_GetDCSMatrix(myDCS); +// Check_Pointer(tempMatrix); +// *(Matrix4x4*)tempMatrix = OrientationMatrix; + // + // If there was a graphic, create an instance with that graphic in it and link + // it to the DCS. + // + if(Graphic_Object == NULL) + { + //myInstance = NULL; + } + else + { +// myInstance = dpl_NewInstance(); +// Check_Pointer(myInstance ); +// dpl_SetInstanceObject(myInstance, Graphic_Object); +// dpl_SetInstanceIntersect(myInstance, Intersect_Mode); +// dpl_SetInstanceSectMask(myInstance, Intersect_Mask); +// dpl_SetInstanceVisibility(myInstance, 1); +// dpl_AddInstanceToDCS(myDCS, myInstance); +// dpl_FlushInstance(myInstance); + } + // + // Flush out the DCS and add this to the static component list + // +// dpl_FlushDCS(myDCS); + //myEntity->AddStaticVideoComponent(this); + + //L4Application *l4_application = Cast_Object(L4Application*, application); + //Check(l4_application); + //l4_application->GetVideoRenderer()->mRenderables.Add(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for the DPLStaticChildRenderable +// + +DPLStaticChildRenderable::~DPLStaticChildRenderable() +{ +//STUBBED: DPL RB 1/14/07 +// Check(this); +//// Below is probably unnecessary as the parent should be destroyed too +//// but Phil is making a patch to allow us to check that. +//// dpl_RemoveDCSFromDCS(myParentDCS, myDCS); +// +// dpl_DeleteDCS(myDCS); +// if(myInstance != NULL) +// { +// dpl_DeleteInstance(myInstance); +// } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLStaticChildRenderable +// +Logical + DPLStaticChildRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check_Pointer(myDCS); + Check_Pointer(myParentDCS); + if(myInstance != NULL) + { + Check_Pointer(myInstance); + } + Check(&OrientationMatrix); + Check(myEntity); + + return True; +} + +void DPLStaticChildRenderable::Execute() +{ + myRenderer->GetMatrixStack()->Push(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&OrientationMatrix.ToD3DMatrix()); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + HierarchicalDrawComponent::Execute(); + + //std::vector::iterator iter = m_children.begin(); + + //while(iter != m_children.end()) + //{ + // (*iter)->Execute(); + // iter++; + //} + myRenderer->GetMatrixStack()->Pop(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~Special Effects Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//############################################################################# +// This is the DPLSFXRenderable class. This renderable is used to trigger a +// special effect in the world. The effect can be relative to a DCS or can be +// positioned in world coordinants by passing NULL as Parent_DCS. The trigger +// is a specific attribute entering a specific state. The effect will be +// generated repeatedly till the trigger changes state. +// +// This renderable is useful for triggering one-shot effects like puffs of smoke +// from guns or for triggering effects that the renderer will automatically +// repeat on it's own. +//############################################################################# +#define DPLSFXRenderable_MAX_RATE 28.0 // Repeat rate when speed = 1.0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLSFXRenderable +// +DPLSFXRenderable::DPLSFXRenderable( + Entity *This_Entity, // Entity to attach the effect to + bool isDeathZone , //*This_Zone, // DPL zone everything will be in + const Point3D &Offset_Point, // Point offset from the parent DCS + HierarchicalDrawComponent *Parent, // Parent DCS (can be NULL for world) + StateIndicator *Effect_Trigger, // Trigger effect when this state changes + int Trigger_State, // Trigger effect when in this state + int Effect_Type, // Type of effect to trigger + Scalar Repeat_Speed // Effect repeat speed. +): + HierarchicalDrawComponent(TrivialNodeClassID, Parent) +{ + isDeathDraw = isDeathZone; + +// +// Check the inbound data, note that the parent DCS could be a null pointer +// + Check(This_Entity); +// Check_Pointer(This_Zone); + Check(&Offset_Point); + #if DEBUG_LEVEL > 0 + if(Parent_DCS != NULL) + Check_Pointer(Parent_DCS); + #endif + Check(Effect_Trigger); +// +// Remember the entity and DCS this renderable is attached to +// + myEntity = This_Entity; + //myParentDCS = Parent_DCS; + myOffsetPoint = Offset_Point; + myEffectTrigger = Effect_Trigger; + myEffectTriggerOld = myEffectTrigger->GetState(); + myEffectTriggerState = Trigger_State; + myEffectType = Effect_Type; + mEmitter.SetEffect(myEffectType); + myRepeatSpeed = 1.0/(Repeat_Speed * DPLSFXRenderable_MAX_RATE); + myLastEffect = 0.0; +// +// Register this effect as a dynamic renderable of the entity +// + myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLSFXRenderable +// +DPLSFXRenderable::~DPLSFXRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLSFXRenderable +// +Logical + DPLSFXRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEntity); + #if DEBUG_LEVEL > 0 + if(myParentDCS != NULL) + Check_Pointer(myParentDCS); + #endif + Check(&myOffsetPoint) + Check_Pointer(myEffectTrigger); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLSFXRenderable. +// This watches the pre-assigned attribute pointer and triggers a special effect +// whenever that attribute changes. +// +void + DPLSFXRenderable::Execute() +{ + Scalar current_time; + + Matrix4x4 mat; + mat = myEntity->localToWorld; + D3DXMATRIX transform = mat.ToD3DMatrix(); + D3DXVECTOR4 v4; + D3DXVECTOR3 v3(myOffsetPoint.x, myOffsetPoint.y, myOffsetPoint.z); + D3DXVec3Transform(&v4, &v3, &transform); + + mEmitter.SetPosition(v4.x, v4.y, v4.z); + + mEmitter.Execute(); + + // + // Is the attribute in the trigger state? + // + if(myEffectTrigger->GetState() == myEffectTriggerState) + { + // + // The effect is on, see if this is an edge + // + if(myEffectTriggerOld != myEffectTrigger->GetState()) + { + // + // An edge, reset the repeat timers so we will get an effect right now. + // + myLastEffect = 0.0; + } + // + // Is it time for another effect yet? + // + current_time = Now(); + if((myLastEffect + myRepeatSpeed) < current_time) + { + // + // Trigger the effect + // + // dpl_EXPLOSION_EFFECT_INFO my_explosion; + // my_explosion.type = myEffectType; + // my_explosion.x = myOffsetPoint.x; + // my_explosion.y = myOffsetPoint.y; + // my_explosion.z = myOffsetPoint.z; + // dpl_Effect ( dpl_effect_type_explosion, myParentDCS, &my_explosion ); + mEmitter.Fire(); + myLastEffect = current_time; + } + } + myEffectTriggerOld = myEffectTrigger->GetState(); + //HierarchicalDrawComponent::Execute(); +} +//############################################################################# +// This is the DPLRepeatSFXRenderable class. This renderable is used to trigger +// a special effect that repeats periodically with the repeat rate under program +// control. The most common use will probably be generating smoke trails. If +// the density argument is set to zero, no smoke will be generated. +//############################################################################# +#define DPLRepeatSFXRenderable_MAX_RATE 30.0 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLRepeatSFXRenderable +// +DPLRepeatSFXRenderable::DPLRepeatSFXRenderable( + Entity *This_Entity, + bool isDeathZone , //*This_Zone, + const Point3D &Offset_Point, + HierarchicalDrawComponent *Parent, // offset is relative to this + int Effect_Type, // type code for the effect + Scalar *Speed +): + HierarchicalDrawComponent(TrivialNodeClassID, Parent) +{ + isDeathDraw = isDeathZone; + +// +// Check the inbound data +// + Check(This_Entity); +// Check_Pointer(This_Zone); + Check(&Offset_Point); + #if DEBUG_LEVEL > 0 + if(Parent_DCS != NULL) + Check_Pointer(Parent_DCS); // it is allowed to be null + #endif + Check_Pointer(Speed); +// +// Remember the entity and DCS this renderable is attached to +// + myEntity = This_Entity; +// myParentDCS = Parent_DCS; + myParent = Parent; + myOffsetPoint = Offset_Point; + myEffectType = Effect_Type; + mEmitter.SetEffect(myEffectType); + mySpeed = Speed; + myLastSmoke = 0.0; + mOldLocalToWorld = This_Entity->localToWorld; + mTransMatrix = This_Entity->localToWorld; +// +// Setup as a dynamic renderable +// +// myEntity->AddDynamicVideoComponent(this); +// +// HACK HACK this needs to be folded back into the new videorenderable hiearchy + myEntity->AddStaticVideoComponent(this); + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLRepeatSFXRenderable +// +DPLRepeatSFXRenderable::~DPLRepeatSFXRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLRepeatSFXRenderable +// +Logical + DPLRepeatSFXRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEntity); + #if DEBUG_LEVEL > 0 + if(myParentDCS != NULL) + Check_Pointer(myParentDCS); // it is allowed to be null + #endif + Check(&myOffsetPoint); + Check_Pointer(mySpeed); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLRepeatSFXRenderable. +// This watches the pre-assigned attribute pointer and triggers a special effect +// whenever that attribute changes. +// +void DPLRepeatSFXRenderable::Execute() +{ + Scalar current_time = Now(); + + if(mOldLocalToWorld != myEntity->localToWorld) + { + mOldLocalToWorld = myEntity->localToWorld; + mTransMatrix = mOldLocalToWorld; + } + + Matrix4x4 mat; + mat = myEntity->localToWorld; + D3DXMATRIX transform = mat.ToD3DMatrix(); + D3DXVECTOR4 v4; + D3DXVECTOR3 v3(myOffsetPoint.x, myOffsetPoint.y, myOffsetPoint.z); + D3DXVec3Transform(&v4, &v3, &transform); + + mEmitter.SetPosition(v4.x, v4.y, v4.z); + + mEmitter.Execute(); + + // If speed is zero, the effect is turned off so we do nothing + if(*mySpeed == 0.0) + { + myLastSmoke = 0.0; + return; + } + + // Figure how often we should generate smoke, speed ranges from 0 to 1, with + // 1 being the fastest + if((myLastSmoke + (1.0 / ((*mySpeed) * mEmitter.GetMaxRepeat()))) < current_time) + { + //dpl_EXPLOSION_EFFECT_INFO my_explosion; + myLastSmoke = current_time; + //my_explosion.type = myEffectType; + //my_explosion.x = myOffsetPoint.x; + //my_explosion.y = myOffsetPoint.y; + //my_explosion.z = myOffsetPoint.z; + //dpl_Effect(dpl_effect_type_explosion, myParentDCS, &my_explosion); + mEmitter.Fire(); + } + //HierarchicalDrawComponent::Execute(); +} + +//############################################################################# +// This is the DPLTranslocationRenderable class. This renderable handles the +// entire process of doing a UFT translocation effect from the perspective of +// people watching the player. This renderable is connected to the player object +// and manages positioning itself in the world based on information from that +// object. HACK HACK HACK (this will be obsolete when RP is fixed) +//############################################################################# +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLTranslocationRenderable +// +DPLTranslocationRenderable::DPLTranslocationRenderable( + Entity *This_Entity, // Entity to attach the effect to + bool isDeathZone, // DPL zone everything will be in + StateIndicator *Effect_Trigger, // Trigger effects off of this state dial + Point3D *Drop_Zone_Location, // Attribute that holds where the new drop will be + unsigned Drop_Zone_State +): + HierarchicalDrawComponent(TrivialNodeClassID) +{ + isDeathDraw = isDeathZone; + +//STUBBED: DPL RB 1/14/07 +//// +//// Check the inbound data, note that the parent DCS could be a null pointer +//// +// Check(This_Entity); +// Check_Pointer(This_Zone); +// Check(Effect_Trigger); +// Check(Drop_Zone_Location); +//// +//// Remember the entity and DCS this renderable is attached to +//// +// myEntity = This_Entity; +// myZone = This_Zone; +// myEffectTrigger = Effect_Trigger; +// myEffectTriggerOld = myEffectTrigger->GetState(); +// myDropZoneLocation = Drop_Zone_Location; +// myDropZoneState = Drop_Zone_State; +// myState = IdleState; +//// +//// Load up the object we're going to use for the translocation +//// +// dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere", dpl_load_normal ); +// Check_Pointer(myTranslocateSphere); +//// +//// Setup a DCS that we can put the effect on so it can be rotated, scaled and +//// placed anywhere we want in the world. +//// +// myInstance = dpl_NewInstance(); +// myDCS = dpl_NewDCS(); +// Check_Pointer (myInstance); +// Check_Pointer (myDCS); +// dpl_AddDCSToScene (myDCS); +// dpl_SetDCSZone (myDCS, myZone); +// dpl_SetInstanceObject (myInstance, myTranslocateSphere); +// dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj); +// dpl_SetInstanceSectMask (myInstance, NULL); +// dpl_SetInstanceVisibility (myInstance, False); +// dpl_AddInstanceToDCS (myDCS, myInstance); +// dpl_FlushInstance (myInstance); +// dpl_FlushDCS (myDCS); +//// +//// Register this effect as a dynamic renderable of the entity +//// +//// myEntity->AddDynamicVideoComponent(this); +//// +//// HACK HACK this needs to be folded back into the new videorenderable hiearchy +// myEntity->AddStaticVideoComponent(this); +// L4Application *l4_application = Cast_Object(L4Application*, application); +// Check(l4_application); +// l4_application->GetVideoRenderer()->AddDynamicRenderable(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for DPLTranslocationRenderable +// +DPLTranslocationRenderable::~DPLTranslocationRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the DPLTranslocationRenderable +// +Logical + DPLTranslocationRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEntity); + Check(myEffectTrigger); + Check_Pointer(myZone); + Check(myDropZoneLocation); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for DPLTranslocationRenderable. +// Note that the states listed here are temporary for testing and will be changed +// to player based effects as things are finalized. +// +void + DPLTranslocationRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 +// Scalar +// current_time, +// scale_factor; +// unsigned +// current_trigger_state; +// // +// // Check data we're going to use and get our current state to a local variable +// // +// Check_Pointer(myEffectTrigger); +// current_trigger_state = myEffectTrigger->GetState(); +// // HACK, because this renderable doesn't know what renderer it's on yet. +// {L4Application *l4_application = Cast_Object(L4Application*, application); +// Check(l4_application); +// current_time = l4_application->GetVideoRenderer()->GetCurrentFrameTime();} +//// current_time = myRenderer->GetCurrentFrameTime(); +// // +// // Simple state engine to manage the death/translocation effect +// // +// switch(myState) +// { +// case IdleState: +// { +// // +// // Watch for transition to the dropzone acquired state +// // +// if(current_trigger_state == myDropZoneState) +// { +// myState = InitialExpandState; +// myEffectTimer = current_time; +// scale_factor = current_time - myEffectTimer; +// if(scale_factor < 0.05f) +// scale_factor = 0.05f; +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// AffineMatrix tempAffine(True); +// tempAffine(0,0) = scale_factor; +// tempAffine(1,1) = scale_factor; +// tempAffine(2,2) = scale_factor; +// tempAffine = *myDropZoneLocation; +// *(Matrix4x4*)tempMatrix = tempAffine; +// dpl_SetInstanceVisibility (myInstance, True); +// dpl_FlushInstance (myInstance); +// HACK_DPL_FLUSH_DCS (myDCS); +// } +// break; +// } +// case InitialExpandState: +// { +// scale_factor = current_time - myEffectTimer; +// if(scale_factor < 0.05f) +// scale_factor = 0.05f; +// if(scale_factor >= 1.0) +// { +// scale_factor = 1.0; +// myState = HoldAtSizeState; +// } +// // Below is a hack to build a scaling identity matrix +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); +// AffineMatrix tempAffine(True); +// tempAffine(0,0) = scale_factor; +// tempAffine(1,1) = scale_factor; +// tempAffine(2,2) = scale_factor; +// tempAffine = *myDropZoneLocation; +// *(Matrix4x4*)tempMatrix2 = tempAffine; +// HACK_DPL_FLUSH_DCS (myDCS); +// break; +// } +// case HoldAtSizeState: +// { +// if((current_time - myEffectTimer) >= 3.0) +// { +// myState = ColapseState; +// myEffectTimer = current_time + 1.0; +// } +// break; +// } +// case ColapseState: +// { +// scale_factor = myEffectTimer - current_time; +// if(scale_factor < 0.05f) +// { +// scale_factor = 0.05f; +// dpl_SetInstanceVisibility (myInstance, False); +// dpl_FlushInstance (myInstance); +// myState = IdleState; +// } +// // Below is a hack to build a scaling identity matrix +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); +// AffineMatrix tempAffine(True); +// tempAffine(0,0) = scale_factor; +// tempAffine(1,1) = scale_factor; +// tempAffine(2,2) = scale_factor; +// tempAffine = *myDropZoneLocation; +// *(Matrix4x4*)tempMatrix2 = tempAffine; +// HACK_DPL_FLUSH_DCS (myDCS); +// break; +// } +// } +HierarchicalDrawComponent::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This is brand new stuff as of 5/12/96 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for OnePSFXRenderable +// This renderable triggers off a single PSFX effect and then hangs around and +// kills the effect when the renderable goes away. This is useful for things +// like missiles which you want to leave a smoke trail that stops if the object +// is destroyed. You REALLY want to do this whenever you attach an effect to +// a DCS since if the DCS goes away the DPL renderer will go wackey. +// +OnePSFXRenderable::OnePSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point // Offset (or world coordinants if DCS is NULL) +): + VideoRenderable(entity, execution_type, parent) +{ + // + // Check the inbound data, note that the parent DCS could be a null pointer + // + #if DEBUG_LEVEL > 0 + if(effect_DCS != NULL) + Check_Pointer(effect_DCS); + #endif + Check(offset_point); + if(!psfx_definition) + { + Fail("A pfx was not defined in the .ini file\n"); + } + // + // Initialze the local variables + // + myPSFXInfo = *psfx_definition; + // + // Start the PFX immediately + // +// myPSFXInfo.identifier = (myPSFXInfo.identifier & 0xffff0000) | myRenderer->GetUniqueID(); +// dpl_Effect ( dpl_effect_type_particlestart, effect_DCS, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for OnePSFXRenderable +// +OnePSFXRenderable::~OnePSFXRenderable() +{ + //STUBBED: DPL RB 1/14/07 + //// + //// Since this renderable only sends one PSFX ID down, we only have to kill + //// one PSFX, no need to track how many are spawned. + //// + //Check(this); + //dpl_Effect ( dpl_effect_type_particlestop, NULL, &myPSFXInfo ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the OnePSFXRenderable +// +Logical + OnePSFXRenderable::TestInstance() const +{ + VideoRenderable::TestInstance(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for OnePSFXRenderable. +// +void + OnePSFXRenderable::Execute() +{ + // Call the next lower execute method + VideoRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for TranslocationRenderable +// This renderable does the UFT translocation effect from the perspective of +// someone else watching the person translocating. We connect this to the +// player object and uses information from that object to position itself. +// +TranslocationRenderable::TranslocationRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL zone everything will be in + StateIndicator *effect_trigger, // Trigger effects off of this state dial + Point3D *drop_zone_location, // Attribute that holds where the new drop will be + unsigned drop_zone_state // State that indicates drop zone is valid (starts effect) +): + VideoRenderable(entity, execution_type) +{ + isDeathDraw = isDeathZone; + +//STUBBED: DPL RB 1/14/07 +//// +//// Check the inbound data, note that the parent DCS could be a null pointer +//// +// Check_Pointer(this_zone); + Check(effect_trigger); + Check(drop_zone_location); +//// +//// Remember the entity and DCS this renderable is attached to +//// +// myZone = this_zone; + myEffectTrigger = effect_trigger; + myDropZoneLocation = drop_zone_location; + myDropZoneState = drop_zone_state; + myState = IdleState; + + L4Application *l4_application = Cast_Object(L4Application*, application); + Check(l4_application); + +//// +//// Load up the object we're going to use for the translocation +//// +// dpl_OBJECT* myTranslocateSphere = dpl_LoadObject ( "tsphere", dpl_load_normal ); + myDevice = l4_application->GetVideoRenderer()->GetDevice(); + myTranslocateSphere = d3d_OBJECT::LoadObject(myDevice, "tsphere.bgf"); +// Check_Pointer(myTranslocateSphere); +//// +//// Setup a DCS that we can put the effect on so it can be rotated, scaled and +//// placed anywhere we want in the world. +//// +// myInstance = dpl_NewInstance(); +// myDCS = dpl_NewDCS(); +// Check_Pointer (myInstance); +// Check_Pointer (myDCS); +// dpl_AddDCSToScene (myDCS); + l4_application->GetVideoRenderer()->AddRenderable(this); +// dpl_SetDCSZone (myDCS, myZone); +// dpl_SetInstanceObject (myInstance, myTranslocateSphere); +// dpl_SetInstanceIntersect (myInstance, dpl_isect_mode_obj); +// dpl_SetInstanceSectMask (myInstance, NULL); +// dpl_SetInstanceVisibility (myInstance, False); + //TODO set visibility +// dpl_AddInstanceToDCS (myDCS, myInstance); +// dpl_FlushInstance (myInstance); +// dpl_FlushDCS (myDCS); +//// +//// Plug us into the watcher hook of the effect trigger state dial +//// + myEffectTrigger->AddVideoWatcher(this); + visible = false; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for TranslocationRenderable +// +TranslocationRenderable::~TranslocationRenderable() +{ + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the TranslocationRenderable +// +Logical + TranslocationRenderable::TestInstance() const +{ + Component::TestInstance(); + + Check(myEffectTrigger); + Check_Pointer(myZone); + Check(myDropZoneLocation); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute method for TranslocationRenderable. +// Note that the states listed here are temporary for testing and will be changed +// to player based effects as things are finalized. +// +void + TranslocationRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 + Scalar + current_time, + scale_factor; + unsigned + current_trigger_state; + // + // Check data we're going to use and get our current state to a local variable + // + Check(myEffectTrigger); + current_trigger_state = myEffectTrigger->GetState(); + current_time = myRenderer->GetCurrentFrameTime(); + // + // Simple state engine to manage the death/translocation effect + // +// std::cout<<"TranslocationRenderable::Execute\n"; + switch(myState) + { + case IdleState: + { + // + // Watch for transition to the dropzone acquired state + // + if(current_trigger_state == myDropZoneState) + { + myState = InitialExpandState; + myEffectTimer = current_time; + scale_factor = current_time - myEffectTimer; + if(scale_factor < 0.05f) + scale_factor = 0.05f; +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + localToWorld = tempAffine; +// *(Matrix4x4*)tempMatrix = tempAffine; +// dpl_SetInstanceVisibility (myInstance, True); + visible = true; +// dpl_FlushInstance (myInstance); +// DPL_FLUSH_DCS (myDCS); + myRenderer->AddDynamicRenderable(this); +// std::cout<<"TranslocationRenderable Going Dynamic\n"; + } + break; + } + case InitialExpandState: + { + scale_factor = current_time - myEffectTimer; + if(scale_factor < 0.05f) + scale_factor = 0.05f; + if(scale_factor >= 1.0) + { + scale_factor = 1.0; + myState = HoldAtSizeState; + } +// // Below is a hack to build a scaling identity matrix +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + localToWorld = tempAffine; +// *(Matrix4x4*)tempMatrix2 = tempAffine; +// DPL_FLUSH_DCS (myDCS); + break; + } + case HoldAtSizeState: + { + if((current_time - myEffectTimer) >= 3.0) + { + myState = ColapseState; + myEffectTimer = current_time + 1.0; + } + break; + } + case ColapseState: + { + scale_factor = myEffectTimer - current_time; + if(scale_factor < 0.05f) + { + scale_factor = 0.05f; + visible = false; +// dpl_SetInstanceVisibility (myInstance, False); +// dpl_FlushInstance (myInstance); + myState = IdleState; + myRenderer->RemoveDynamicRenderable(this); +//// std::cout<<"TranslocationRenderable Going Static\n"; + } + // Below is a hack to build a scaling identity matrix +// float32* tempMatrix2 = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix2 ); + AffineMatrix tempAffine(True); + tempAffine(0,0) = scale_factor; + tempAffine(1,1) = scale_factor; + tempAffine(2,2) = scale_factor; + tempAffine = *myDropZoneLocation; + localToWorld = tempAffine; +// *(Matrix4x4*)tempMatrix2 = tempAffine; +// DPL_FLUSH_DCS (myDCS); + break; + } + } + + if (!visible) + { + graphicalObject = NULL; + } else + { + graphicalObject = myTranslocateSphere; + myRenderer->GetMatrixStack()->Push(); + D3DXMATRIX transform = localToWorld.ToD3DMatrix(); + myRenderer->GetMatrixStack()->MultMatrixLocal(&transform); + //myLocalToWorld = *myRenderer->GetMatrixStack()->GetTop(); + HierarchicalDrawComponent::SetLocalToWorld(myRenderer->GetMatrixStack()->GetTop()); + VideoRenderable::Execute(); + myRenderer->GetMatrixStack()->Pop(); + } +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for SpinScaleQuatWatcherRenderable +// +SpinScaleQuatWatcherRenderable::SpinScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Scalar z_spin_rate // spins the object about z (radians/frame) + ): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ +//STUBBED: DPL RB 1/14/07 +// // +// // Check the inbound data +// // +// Check(control); +// Check(rotation_quaternion); +// Check(scale_vector); +// // +// // Remember the entity that this renderable is attached to and the +// // orientation matrix that offsets it to the correct position. +// // +// myControl = control; +// myTriggerState = effect_trigger_state; +// myVisible = False; +// myRotationQuaternion = rotation_quaternion; +// myScaleVector = scale_vector; +// myZSpinRate = z_spin_rate; +// OldZSpin = 0; +// // +// // Setup the dcs matrix to it's initial state +// // +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// AffineMatrix tempAffine(True); +// tempAffine *= (*myScaleVector); +// tempAffine *= (*myRotationQuaternion); +// *(Matrix4x4*)tempMatrix = tempAffine; +// dpl_FlushDCS ( myDCS ); +// // +// // Set the instance visibility correctly +// // +// dpl_SetInstanceVisibility ( myInstance, myVisible ); +// dpl_FlushInstance ( myInstance ); +//// +//// Plug us into the watcher hook of the effect trigger state dial +//// +// myControl->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for SpinScaleQuatWatcherRenderable +// +SpinScaleQuatWatcherRenderable::~SpinScaleQuatWatcherRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the SpinScaleQuatWatcherRenderable +// +Logical + SpinScaleQuatWatcherRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + Check(myControl); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the SpinScaleQuatWatcherRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + SpinScaleQuatWatcherRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 +// // +// // Check our variables +// // +// Check(this); +// // +// // Check data we're going to use and get our current state to a local variable +// // +//// std::cout<<"SpinScaleQuatWatcherRenderable::Execute "<GetState()<<"\n"; +// if(myControl->GetState() == myTriggerState) +// { +// // +// // We're in the trigger state, if we aren't already visible, make us +// // visible and dynamic now. +// // +// if(!myVisible) +// { +// myVisible = True; +// dpl_SetInstanceVisibility ( myInstance, True ); +// dpl_FlushInstance ( myInstance ); +// myRenderer->AddDynamicRenderable(this); +//// std::cout<<"SpinScaleQuatWatcherRenderable Going Dynamic\n"; +// } +// // +// // Now update the beam +// // +// OldZSpin += myZSpinRate; +// if(OldZSpin > TWO_PI) +// OldZSpin -= TWO_PI; +// Hinge temp_hinge(Z_Axis, OldZSpin); +// +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// +// AffineMatrix tempAffine(True); +// Quaternion temp_quaternion; +// temp_quaternion = temp_hinge; +// tempAffine = temp_quaternion; +// tempAffine *= (*myScaleVector); +// tempAffine *= (*myRotationQuaternion); +// *(Matrix4x4*)tempMatrix = tempAffine; +// DPL_FLUSH_DCS ( myDCS ); +// } +// else +// { +// // +// // We've left the trigger state, so if we're visible we make the beam +// // invisible and go static. +// // +// if(myVisible) +// { +// myVisible = False; +// dpl_SetInstanceVisibility ( myInstance, False ); +// dpl_FlushInstance ( myInstance ); +// myRenderer->RemoveDynamicRenderable(this); +//// std::cout<<"SpinScaleQuatWatcherRenderable Going Static\n"; +// } +// } + // + // Call the execute method in our parent + // + ChildOffsetRenderable::Execute(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for ScaleQuatWatcherRenderable +// +ScaleQuatWatcherRenderable::ScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector // Scales the object +): +ChildOffsetRenderable( + entity, // Entity to attach the renderable to + execution_type, // How/when to execute the renderable + graphical_object, // object to hang on the DCS, may be a list later + isDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + offset_matrix) // offset matrix to be applied prior to joint DCS +{ +//STUBBED: DPL RB 1/14/07 +// // +// // Check the inbound data +// // +// Check(control); +// Check(rotation_quaternion); +// Check(scale_vector); +// // +// // Remember the entity that this renderable is attached to and the +// // orientation matrix that offsets it to the correct position. +// // +// myControl = control; +// myTriggerState = effect_trigger_state; +// myVisible = False; +// myRotationQuaternion = rotation_quaternion; +// myScaleVector = scale_vector; +// // +// // Setup the dcs matrix to it's initial state +// // +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// AffineMatrix tempAffine(True); +// tempAffine *= (*myScaleVector); +// tempAffine *= (*myRotationQuaternion); +// *(Matrix4x4*)tempMatrix = tempAffine; +// dpl_FlushDCS ( myDCS ); +// // +// // Set the instance visibility correctly +// // +// dpl_SetInstanceVisibility ( myInstance, myVisible ); +// dpl_FlushInstance ( myInstance ); +//// +//// Plug us into the watcher hook of the effect trigger state dial +//// +// myControl->AddVideoWatcher(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Destructor for ScaleQuatWatcherRenderable +// +ScaleQuatWatcherRenderable::~ScaleQuatWatcherRenderable() +{ + // + // Check our structure before we do anything + // + Check(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TestInstance for the ScaleQuatWatcherRenderable +// +Logical + ScaleQuatWatcherRenderable::TestInstance() const +{ + // + // Call our parent's TestInstance first + // + ChildOffsetRenderable::TestInstance(); + Check(myControl); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Execute for the ScaleQuatWatcherRenderable +// Nothing to execute here so we just pass it down to the next lower level. +// +void + ScaleQuatWatcherRenderable::Execute() +{ +//STUBBED: DPL RB 1/14/07 +// // +// // Check our variables +// // +// Check(this); +// // +// // Check data we're going to use and get our current state to a local variable +// // +// //std::cout<<"ScaleQuatWatcherRenderable::Execute "<GetState()<<"\n"; +// if(myControl->GetState() == myTriggerState) +// { +// // +// // We're in the trigger state, if we aren't already visible, make us +// // visible and dynamic now. +// // +// if(!myVisible) +// { +// myVisible = True; +// dpl_SetInstanceVisibility ( myInstance, True ); +// dpl_FlushInstance ( myInstance ); +// myRenderer->AddDynamicRenderable(this); +//// std::cout<<"ScaleQuatWatcherRenderable Going Dynamic\n"; +// } +// // +// // Now update the beam +// // +// float32* tempMatrix = dpl_GetDCSMatrix( myDCS ); +// Check_Pointer ( tempMatrix ); +// AffineMatrix tempAffine(True); +// tempAffine *= (*myScaleVector); +// tempAffine *= (*myRotationQuaternion); +// *(Matrix4x4*)tempMatrix = tempAffine; +// DPL_FLUSH_DCS ( myDCS ); +// } +// else +// { +// // +// // We've left the trigger state, so if we're visible we make the beam +// // invisible and go static. +// // +// if(myVisible) +// { +// myVisible = False; +// dpl_SetInstanceVisibility ( myInstance, False ); +// dpl_FlushInstance ( myInstance ); +// myRenderer->RemoveDynamicRenderable(this); +//// std::cout<<"ScaleQuatWatcherRenderable Going Static\n"; +// } +// } +//// if(*myTest != myVisible) +//// { +//// std::cout<<"myTest="<<*myTest<<" myVisible="< + +//STUBBED: DPL RB 1/14/07 +//when stubs are done, this can be removed +#include "..\DPLSTUB.h" +#define int32 __int32 +#define uint32 unsigned __int32 + +// RB 1/14/07 +//#include +//#include +//#include + +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +// All the stuff between these big ugly bars is the new video component stuff// + +typedef enum +{ + NullVideoControlID = 0, + StartVideoControlID = 1, + StopVideoControlID = 2, +} VideoControlID; + +typedef enum +{ + StaticVideoExecutionType = 0, + DynamicVideoExecutionType = 1, + WatcherVideoExecutionType = 2, +} VideoExecutionType; + +typedef enum +{ + NotDPLComponentType = 0, +} DPLComponentType; + +class HierarchicalDrawComponent : public Component +{ +public: + HierarchicalDrawComponent(RegisteredClass::ClassID classId); + HierarchicalDrawComponent(RegisteredClass::ClassID classId, HierarchicalDrawComponent *parent); + ~HierarchicalDrawComponent(); + + void addChild(HierarchicalDrawComponent *child); + void removeChild(HierarchicalDrawComponent *child); + void clearParent(); + virtual void Execute(); + virtual void Render(int pass, const D3DXMATRIX *viewTransform); + void ResetDrawObj(); + +// D3DXMATRIX *GetLocalToWorld() { return &myLocalToWorld; } + inline void SetLocalToWorld(const D3DXMATRIX *localToWorld) { if (localToWorld != NULL && graphicalObject != NULL) graphicalObject->SetLocalToWorld(*localToWorld); } + + std::vector::const_iterator Enumerate(); + std::vector::const_iterator End(); + + virtual bool IsStatic() { return false; } + + d3d_OBJECT *GetDrawObj() { return this->graphicalObject; } +protected: + void ExecuteChildren(); + + DPLRenderer *myRenderer; // The renderer that owns this renderable + bool isDeathDraw; +// D3DXMATRIX myLocalToWorld; + d3d_OBJECT *graphicalObject; +private: + HierarchicalDrawComponent *m_parent; + std::vector m_children; +}; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Video component base class +// +class VideoComponent: + public HierarchicalDrawComponent +{ + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + VideoComponent( + Entity *entity, // Entity to attach the renderable to + VideoExecutionType execution_type); // How/when to execute the renderable + + ~VideoComponent(); + + Logical + TestInstance() const; + // + //-------------------------------------------------------------------- + // Add, handles establishing graphical hiearchal links between + // things like DCS's, Instances, geometry and so on. This does not + // establish a control path, only a graphical hiearchy. For each + // target type that something can be added to there is also an + // AddMeToTYPE(component) virtual (ie: AddMeToDCS) + //-------------------------------------------------------------------- + // + virtual void + Add( + VideoComponent *component_to_add); + virtual void + AddMeToDCS( + VideoComponent *component_to_add) + {Fail("Don't know how to add this component to a DCS\n");}; + virtual void + AddMeToInstance( + VideoComponent *component_to_add) + {Fail("Don't know how to add this component to an Instance\n");}; + virtual void + AddMeToScene( + VideoComponent *component_to_add) + {Fail("Don't know how to add this component to a Scene\n");}; + // + //-------------------------------------------------------------------- + // Connect, connects a control path between us and the component + // in the argument. The path goes from us to that element. + //-------------------------------------------------------------------- + // + virtual void + Connect( + VideoComponent *component_to_connect); + // + //-------------------------------------------------------------------- + // ReceiveControl, called by people connected to us to send control + // inputs to us. For the moment we will have several virtuals that + // accept different control types. + //-------------------------------------------------------------------- + // + virtual void + ReceiveControl( + VideoControlID control_ID, + Scalar control_value + ); + // + //-------------------------------------------------------------------- + // Execute + //-------------------------------------------------------------------- + // + void + Execute(); + + protected: + #if DEBUG_LEVEL > 0 + VideoExecutionType + myExecutionType; // We use this to test if the component is in the wrong list + #endif + + SlotOf + videoComponentSocket; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLDCSWrapper class +// +class DPLDCSWrapper : public VideoComponent +{ + public: + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + DPLDCSWrapper( + Entity *entity, // Entity to attach the renderable to + VideoExecutionType execution_type, // How/when to execute the renderable + LinearMatrix initial_matrix); // Initial value to put into the matrix + + ~DPLDCSWrapper(); + + Logical TestInstance() const; + + void Add(VideoComponent *component_to_add); + void Connect(VideoComponent *component_to_connect); + void ReceiveControl(VideoControlID control_ID, Scalar control_value); + void Execute(); + + protected: + dpl_DCS *my_DCS; +}; + +//===========================================================================// +//===========================================================================// +//===========================================================================// +//===========================================================================// +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~New Class Hiearchy for Renderables~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Video renderable base class +// +class VideoRenderable: + public HierarchicalDrawComponent +{ + public: + enum ExecutionType + { + Static = 0, + Dynamic, + Watcher, + Dependant, + NextExecutionType + }; + + VideoRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + HierarchicalDrawComponent *parent=NULL); + + ~VideoRenderable(); + + Logical TestInstance() const; + + void Execute(); + + virtual bool IsStatic() { return (this->myExecutionType == ExecutionType::Static); } + + protected: + Entity *myEntity; // The entity we are linked to + ExecutionType myExecutionType; // How/when to execute the renderable +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~This is a special class to speed up projectiles~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class InnerProjectileRenderable : public HierarchicalDrawComponent +{ + public: + InnerProjectileRenderable( + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone); // DPL Zone this stuff will live in (for culling) + + ~InnerProjectileRenderable(); + + virtual void Execute(); + + Logical TestInstance() const; + + dpl_DCS* GetDCS() { return myDCS; } + dpl_INSTANCE* GetInstance() { return myInstance; } + + protected: + dpl_DCS *myDCS; + dpl_INSTANCE *myInstance; + d3d_OBJECT *obj; +}; + +class ProjectileRootRenderable : public VideoRenderable +{ + public: + ProjectileRootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone); // DPL Zone this stuff will live in (for culling) + + ~ProjectileRootRenderable(); + + Logical TestInstance() const; + + virtual void Execute(); + protected: + InnerProjectileRenderable *myInnerProjectile; + LinearMatrix oldLocalToWorld; // The value of this matrix the last time through + Matrix4x4 transMatrix; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ChildLightRenderable +// This renderable is used to connect a light as a child of an existing DCS +// the light isn't setup to move on it's own and creates a DCS only for the +// purpose of offsetting it from it's parent. +// +class ChildLightRenderable : public VideoRenderable +{ + public: + + ChildLightRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Scalar red, // light color + Scalar green, + Scalar blue, + Scalar inner_radius, + Scalar outer_radius, + dpl_LIGHT_TYPE light_type, + int light_mask); + + ~ChildLightRenderable(); + + Logical TestInstance() const; + + virtual void Execute(); + + protected: + dpl_LIGHT *myLight; + dpl_DCS *myDCS, *myParentDCS; + Matrix4x4 myOffsetMatrix; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLObjectWrapper is a wrapper class that holds on to one of DPL's objects +// so it can be deleted properly at a later time. +// +class DPLObjectWrapper : public VideoRenderable +{ + public: + DPLObjectWrapper( + Entity *entity, // Entity to attach the renderable to + const CString &name, // Name of the DPL object to load into the wrapper + dpl_LOAD_MODE cache_mode); // DPL Zone this stuff will live in (for culling) + + ~DPLObjectWrapper(); + + Logical TestInstance() const; + + d3d_OBJECT* GetDPLObject() {return myDPLObject;} + CString* GetDPLObjectName() {return &myDPLObjectName;} + + void Execute(); + + protected: + CString myDPLObjectName; + dpl_LOAD_MODE myCacheMode; + d3d_OBJECT *myDPLObject; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DCSObjectRenderable a subclass not intended to be used on it's own, it +// encapsulates the information that follows a DCS node around. Parameters +// marked with are allowed to be passed in as NULL values. +// +class DCSObjectRenderable : public VideoRenderable +{ + public: + DCSObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // actual geometry data that will sent to card + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent=NULL); + + ~DCSObjectRenderable(); + + Logical TestInstance() const; + + dpl_DCS* GetDCS() {return myDCS;} + dpl_INSTANCE* GetInstance() {return myInstance;} + + virtual void Execute(); + + protected: + d3d_OBJECT *myD3DObject; + dpl_ISECT_MODE myIntersectMode; + dpl_DCS *myDCS; // The dpl DCS we create to hold the instance of this object + dpl_INSTANCE *myInstance; // Instance that we hang on the DCS + uint32 myIntersectMask; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DCSInstanceRenderable Creates a DPL instance and binds it to a DCS. This +// is mainly used to insure these instances will be deleted properly when the +// object goes away. +// +class DCSInstanceRenderable : public VideoRenderable +{ + public: + DCSInstanceRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to connect to the instance + HierarchicalDrawComponent *parent, // the DCS to add the instance to + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + Logical visible); // initial visibility setting + + ~DCSInstanceRenderable(); + + Logical TestInstance() const; + + dpl_INSTANCE* GetInstance() { return myInstance; } + + virtual void Execute(); + + protected: + d3d_OBJECT *myD3DObject; + dpl_ISECT_MODE myIntersectMode; + dpl_DCS *myDCS; // The dpl DCS we create to hold the instance of this object + dpl_INSTANCE *myInstance; // Instance that we hang on the DCS + uint32 myIntersectMask; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RootRenderable handles an entity that is assumed to be attached at the root +// of the DCS hiearchy. That is, it's connected to the scene rather than to +// another DCS. The root automatically connects up to entity->localToWorld +// +class RootRenderable : public DCSObjectRenderable +{ + public: + RootRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask); // intersection mask for the object + + ~RootRenderable(); + + Logical TestInstance() const; + + virtual void Execute(); + + protected: + LinearMatrix oldLocalToWorld; // The value of this matrix the last time through + +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ChildOffsetRenderable is an intermediate layer that establishes a DCS to handle +// a static offset matrix to be applied prior to the DCS that actually carries +// joint and geometry information. This is not intended to ever be used +// directly. +// +class ChildOffsetRenderable : public DCSObjectRenderable +{ + public: + ChildOffsetRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix); // offset matrix to be applied prior to joint DCS + + ~ChildOffsetRenderable(); + + Logical + TestInstance() const; + + virtual void + Execute(); + + protected: + Matrix4x4 + myOffsetMatrix; // The offset to apply prior to the joint DCS + dpl_DCS + *myParentDCS, // Pointer to our parent DCS + *myOffsetDCS; // The dpl DCS we create to hold the offset from our parent. +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HingeRenderable Handles controlling a joint by way of a munga HINGE class +// attribute. +// +class HingeRenderable: + public ChildOffsetRenderable +{ + public: + HingeRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const Hinge *my_hinge); // Hinge attribute we will use to control the joint + + ~HingeRenderable(); + + Logical + TestInstance() const; + + virtual void + Execute(); + + protected: + const Hinge + *myHinge; // Pointer to the hinge attribute we use to modify the DCS + Hinge + oldHinge; // Copy of the last value of hinge + Matrix4x4 hingeOffsetMatrix; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// SpinScaleQuatRenderable Handles creates a spinning scaled quaternion controlled +// effect. +// +class SpinScaleQuatRenderable: + public ChildOffsetRenderable +{ + public: + SpinScaleQuatRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Logical *visible, // turns the object on and off + Scalar z_spin_rate); // spins the object about z (radians/frame) + + ~SpinScaleQuatRenderable(); + + Logical + TestInstance() const; + + virtual void + Execute(); + + protected: + Quaternion + *myRotationQuaternion; + Vector3D + *myScaleVector; + Logical + *myVisible, + OldVisible; + Scalar + myZSpinRate, + OldZSpin; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// BallJointRenderable Handles controlling a joint by way of a munga eulers +// +class BallJointRenderable: + public ChildOffsetRenderable +{ + public: + BallJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler); // Euler angles to control rotation of the ball joint + + ~BallJointRenderable(); + + Logical + TestInstance() const; + + virtual void + Execute(); + + protected: + const EulerAngles + *myEuler; // Pointer to the hinge attribute we use to modify the DCS + EulerAngles + oldEuler; // Copy of the last value of hinge + Matrix4x4 eulerMatrix; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// BallTranslateJointRenderable Handles controlling a joint by way of a munga eulers +// +class BallTranslateJointRenderable: + public ChildOffsetRenderable +{ + public: + BallTranslateJointRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + const EulerAngles *my_euler, // Euler angles to control rotation of the ball joint + const Point3D *my_translation); // offset for the translation part of the joint + + ~BallTranslateJointRenderable(); + + Logical + TestInstance() const; + + virtual void + Execute(); + + protected: + const Point3D + *myTranslation; + Point3D + oldTranslation; + Matrix4x4 jointMatrix; + + const EulerAngles + *myEuler; // Pointer to the hinge attribute we use to modify the DCS + EulerAngles + oldEuler; // Copy of the last value of hinge +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// POVTranslocateRenderable generates a translocation effect from the point of +// view of a player. +class POVTranslocateRenderable: + public VideoRenderable // from the POV of the player +{ +public: + POVTranslocateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + StateIndicator *effect_trigger, // State dial we use to control the translocation + unsigned effect_control_state); // State that controls start/end of the effect + + ~POVTranslocateRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + +protected: + enum TranslocateState + { + IdleState, + FlashScreenState, + InitialCollapseState, + WaitForReincarnateState, + ExpandRevealState + }; + + TranslocateState + myState; + + int + myEffectControlState; + + Scalar + myRotateY, + myRotateYSpeed, + myCollapseEnd; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_INSTANCE + *myInstance; + + dpl_DCS + *myParentDCS, // Pointer to our parent DCS + *myDCS; + + dpl_ZONE + *myDeathZone, + *myZone; + + d3d_OBJECT *myTranslocateSphere; + Matrix4x4 localToWorld; + bool visible; + LPDIRECT3DDEVICE9 myDevice; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// POVStartEndRenderable generates a translocation effect from the point of +// view of a player. +class POVStartEndRenderable: + public VideoRenderable // from the POV of the player +{ +public: + POVStartEndRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL zone the world is in + dpl_ZONE *death_zone, // DPL zone the player's VTV and death effect are in + dpl_VIEW *this_view, // The view containing our eye + StateIndicator *effect_trigger, // State dial we use to control the translocation + float red_fog, // Fog color + float green_fog, + float blue_fog, + float near_fog, // The near fog plane + float far_fog, // The far fog plane + unsigned start_mission_state, // State that signals start of mission + unsigned end_mission_state); // State that signals end of mission + + ~POVStartEndRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + +protected: + enum StartEndState + { + WaitForStartState, + FlashScreenState, + FadeInState, + MissionRunningState, + FadeOutState + }; + + StartEndState + myState; + + int + myStartMissionState, // Signals mission is starting but player can't move yet + myEndMissionState; // Signals mission is ending + + float + myFogRed, + myFogGreen, + myFogBlue, + myFogNear, + myFogFar; + + Scalar + myStateTimer; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_ZONE + *myDeathZone, + *myZone; + + dpl_VIEW + *myView; + +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ReticleRenderable drawing a static or dynamic reticle in the 2D layer of the +// screen. +// +class ReticleRenderable : + public VideoRenderable +{ + public: + ReticleRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Reticle **my_reticle, // points to renderable reticle pointer that points to entity's reticle + dpl_VIEW *this_view); // the view associated with our eye + + ~ReticleRenderable(); + + Logical TestInstance() const; + + void Execute(); + void Render(int pass, const D3DXMATRIX *viewTransform); + + protected: + + // Last known position of the reticle + Vector2DOf myOldReticlePosition; + + // Points to renderer's reticle pointer + Reticle **rendererReticle; + + // Points directly to reticle in entity + Reticle *myReticle; + + dpl_VIEW *myView; + + dpl2d_DISPLAY *myReticleDisplayList, *myPositionDisplayList; + + LPDIRECT3DVERTEXBUFFER9 mVB; +}; + +#define MAX_PLAYER_NAMES 12 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shows Player bitmap for the CameraShip +// +// +class CameraShipHUDRenderable : + public VideoRenderable +{ + public: + + CameraShipHUDRenderable( + Entity *entity, + ExecutionType execution_type, + int *player_index, + Logical *display_ranking_window + ); + + ~CameraShipHUDRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + void Render(int pass, const D3DXMATRIX *viewTransform); + + protected: + + int + playerCount; + + int + oldFollowedPlayerIndex, + *followedPlayerIndex; + + int + **playerRank, + *oldPlayerRank; + + Logical + *displayRankingWindow, + oldDisplayRankingWindow; + + dpl_OBJECT + *playerNameObject[MAX_PLAYER_NAMES], + *ordinalObject[MAX_PLAYER_NAMES]; + + dpl_DCS + *followedNameDCS, + *followedOrdinalDCS; + + dpl_INSTANCE + *followedNameInstance, + *followedOrdinalInstance; + + dpl_DCS + *rankingWindowDCS, + **nameDCS, + **rankDCS; + + dpl_INSTANCE + **nameInstance, + **rankInstance; + + LPDIRECT3DVERTEXBUFFER9 mVB; +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This class is used to store a stack of threat vectors +// +class VectorStackElement: + public Plug +{ + public: + VectorStackElement( + float add_time, // Time when this threat was added + Vector2DOf *vector_to_stack) // The vector to stack up + {myAddTime = add_time; myVector = *vector_to_stack;myRecent=True;} + + ~VectorStackElement(){}; + + Logical + TestInstance() const + {Check(&myVector);return(True);} + + Vector2DOf + myVector; + float + myAddTime; + Logical + myRecent; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DCSMorphObjectRenderable a subclass not intended to be used on it's own, it +// encapsulates the information that needed to construct a destination dpl_Object +// by morphing two existing objects into it. +// +class DCSMorphObjectRenderable: + public VideoRenderable +{ + public: + DCSMorphObjectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask); // intersection mask for the object + + ~DCSMorphObjectRenderable(); + + Logical + TestInstance() const; + + dpl_DCS* + GetDCS() + {return myDCS;} + + void + Execute(); + + protected: + int32 + myMorphMode; + Scalar + oldMorphControl, + *myMorphControl; + dpl_OBJECT + *myStartObject, + *myEndObject, + *myDPLObject; + dpl_ZONE + *myDPLZone; + dpl_ISECT_MODE + myIntersectMode; + uint32 + myIntersectMask; + dpl_DCS + *myDCS; // The dpl DCS we create to hold the instance of this object + dpl_INSTANCE + *myInstance; // Instance that we hang on the DCS +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ScalingExplosionRenderable Handles controlling a joint by way of a munga HINGE class +// attribute. +// +class ScalingExplosionRenderable: + public ChildOffsetRenderable +{ + public: + ScalingExplosionRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // This will be the scaling explosion object + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + Vector3D *control_vector, // Effect control vector, Y is acceleration, X, Z are velocity + Vector3D *accel_vector, // rate of change of control vector + Scalar gravity, + int *trigger); + + ~ScalingExplosionRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + int + *myTrigger; + Scalar + myVelocity, + myGravity; + Point3D + myTranslation; + Vector3D + myVelocityChange, + myScalingVector, // Controls scaling of the explosion + myVelocityVector; // Scaling velocity (rate of change) +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RootMorphRenderable handles an entity that is assumed to be attached at the root +// of the DCS hiearchy. That is, it's connected to the scene rather than to +// another DCS. The root automatically connects up to entity->localToWorld +// +class RootMorphRenderable: + public DCSMorphObjectRenderable +{ + public: + RootMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask); // intersection mask for the object + + ~RootMorphRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + LinearMatrix + oldLocalToWorld; // The value of this matrix the last time through + +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ChildMorphRenderable +// +class ChildMorphRenderable: + public DCSMorphObjectRenderable +{ + public: + ChildMorphRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_OBJECT *destination_object, // destination + dpl_OBJECT *start_object, // start object + dpl_OBJECT *end_object, // end object + Scalar *morph_control, // pointer to control variable + int32 morph_mode, // Defines type of morph to do + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + dpl_DCS *parent_DCS); // the parent DCS we will be offsetting from + + ~ChildMorphRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// OneShotDelayRenderable +// This renderable delays for a fixed amount after it's creation, then turns on +// a trigger attribute. It is used for the triggering of other renderables a +// fixed time after an object is created. + +class OneShotDelayRenderable: + public VideoRenderable +{ + public: + OneShotDelayRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to wait before raising the trigger + Scalar duration_time = 0.0f // How long trigger is up (0.0 == stay up) + ); + + ~OneShotDelayRenderable(); + + Logical + TestInstance() const; + + int* + GetTriggerAttribute() + {return &myTriggerAttribute;} + + void + Execute(); + + protected: + enum + { + WaitingForTriggerTime, + WaitingForTriggerEndTime, + WaitingForEternity + } myState; + Logical + myEndTimeFlag; + Scalar + myTriggerTime, + myTriggerEndTime; + int + myTriggerAttribute; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// SweepRenderable +// When triggered this renderable sweeps it's output attribute from 0.0 to 1.0 +// over a preset time interval. Used for controling morphs. +class SweepRenderable: + public VideoRenderable +{ + public: + enum SweepFunction + { + Y_EQUALS_X = 0, + Y_SQR_X + }; + + SweepRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_time, // How long to take to sweep from 0 to 1 + int cycles, // number of times to cycle before stopping + int *trigger, // Starts the sweep generator when it goes 1 + Scalar start_value = 0.0f, // Initial value of sweep + Scalar end_value = 1.0f, // Final value of sweep + SweepFunction sweep_function = Y_EQUALS_X // function applied to sweep + ); + + ~SweepRenderable(); + + Logical + TestInstance() const; + + Scalar* + GetSweepAttribute() + {return &mySweepAttribute;} + + void + Execute(); + + protected: + int + fakeTrigger, + oldMyTrigger, + *myTrigger, + myCycleCount, + myCyclesLeft; + SweepFunction + mySweepFunction; + Scalar + myStartValue, + myEndValue, + mySweepStart, + mySweepTime, + mySweepAttribute; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLEffectRenderable +// This routine handles the creation of a DPL special effect whenever the +// trigger attribute changes. This is an edge triggered renderable and will +// generate an effect on ANY form of state change. The only way to effect the +// size and speed of the effect is by way of the DPL effect tables. + +class DPLEffectRenderable: + public VideoRenderable +{ + public: + DPLEffectRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + int effect_type, // DPL effect number to trigger + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~DPLEffectRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + int + *myTrigger, + oldMyTrigger, + myEffectType; + dpl_DCS + *myEffectDCS; + Point3D + myEffectOffset; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class PullFogRenderable: + public VideoRenderable +{ + public: + PullFogRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical *light_1, + Logical *light_2); // address containing the trigger + ~PullFogRenderable(); + Logical + TestInstance() const; + void + Execute(); + protected: + Logical + *myLight1, + *myLight2, + myOldLight1, + myOldLight2; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLPSFXRenderable +// This routine handles the creation of a DPL special effect whenever the +// trigger attribute changes. This is an edge triggered renderable and will +// generate an effect on ANY form of state change. The only way to effect the +// size and speed of the effect is by way of the DPL effect tables. + +class DPLPSFXRenderable: + public VideoRenderable +{ + public: + DPLPSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + int *trigger, // address containing the trigger + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~DPLPSFXRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_PARTICLESTART_EFFECT_INFO + myPSFXInfo; + int + *myTrigger, + myOldTrigger; + dpl_DCS + *myEffectDCS; + Point3D + myEffectOffset; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLPSFXStateRenderable +// This routine triggers a pfx whenever a state dial transitions to a designated +// state. +// NOTE this currently does NOT trigger if the state dial is in the trigger state +// when this renderable is created. +// + +class DPLPSFXStateRenderable: + public VideoRenderable +{ + public: + + DPLPSFXStateRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + StateIndicator *effect_trigger, // Trigger effect when this state changes + unsigned my_trigger, // The state to edge trigger on + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~DPLPSFXStateRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_PARTICLESTART_EFFECT_INFO + myPSFXInfo; + unsigned + myTriggerState; + StateIndicator + *myStateDial; + dpl_DCS + *myEffectDCS; + Point3D + myEffectOffset; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DPLMaterialRenderable +// This renderable creates a DPL Material structure and encapsulates it so +// it will be properly deleted when the object it's part of gets deleted. +class DPLMaterialRenderable: + public VideoRenderable +{ + public: + DPLMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red, // Material's ambient component + Scalar ambient_green, + Scalar ambient_blue, + Scalar emissive_red, // Material's emissive component + Scalar emissive_green, + Scalar emissive_blue, + Scalar diffuse_red, // Material's diffuse component + Scalar diffuse_green, + Scalar diffuse_blue, + Scalar specular_red, // Material's specular component + Scalar specular_green, + Scalar specular_blue, + Scalar specular_shininess, + Scalar opacity_red, // Material's opacity + Scalar opacity_green, + Scalar opacity_blue, + dpl_TEXTURE *texture, // Material's texture pointer + Scalar z_dither, // Material's Z dither value + int fog_immune); // Material's Fog Imunity value + + ~DPLMaterialRenderable(); + + dpl_MATERIAL* + GetMaterial() + {return myMaterial;} + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_MATERIAL + *myMaterial; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for MorphMaterialRenderable +// This renderable takes two material specifications and loads up a third +// material with a morph between the first two. +class MorphMaterialRenderable: + public DPLMaterialRenderable +{ + public: + MorphMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar ambient_red_1, // Material's ambient component + Scalar ambient_green_1, + Scalar ambient_blue_1, + Scalar emissive_red_1, // Material's emissive component + Scalar emissive_green_1, + Scalar emissive_blue_1, + Scalar diffuse_red_1, // Material's diffuse component + Scalar diffuse_green_1, + Scalar diffuse_blue_1, + Scalar specular_red_1, // Material's specular component + Scalar specular_green_1, + Scalar specular_blue_1, + Scalar specular_shininess_1, + Scalar opacity_red_1, // Material's opacity + Scalar opacity_green_1, + Scalar opacity_blue_1, + dpl_TEXTURE *texture_1, // Material's texture pointer + Scalar z_dither_1, // Material's Z dither value + int fog_immune_1, // Material's Fog Imunity value + Scalar ambient_red_2, // Material's ambient component + Scalar ambient_green_2, + Scalar ambient_blue_2, + Scalar emissive_red_2, // Material's emissive component + Scalar emissive_green_2, + Scalar emissive_blue_2, + Scalar diffuse_red_2, // Material's diffuse component + Scalar diffuse_green_2, + Scalar diffuse_blue_2, + Scalar specular_red_2, // Material's specular component + Scalar specular_green_2, + Scalar specular_blue_2, + Scalar specular_shininess_2, + Scalar opacity_red_2, // Material's opacity + Scalar opacity_green_2, + Scalar opacity_blue_2, + Scalar z_dither_2, // Material's Z dither value + Scalar *morph_control); + + ~MorphMaterialRenderable(); + + dpl_MATERIAL* + GetMaterial() + {return myMaterial;} + + Logical + TestInstance() const; + + void + Execute(); + + protected: + int + myFogImmune1; + dpl_TEXTURE + *myTexture1; + + Scalar + myAmbientRed1, + myAmbientGreen1, + myAmbientBlue1, + myEmissiveRed1, + myEmissiveGreen1, + myEmissiveBlue1, + myDiffuseRed1, + myDiffuseGreen1, + myDiffuseBlue1, + mySpecularRed1, + mySpecularGreen1, + mySpecularBlue1, + mySpecularShininess1, + myOpacityRed1, + myOpacityGreen1, + myOpacityBlue1, + myZDither1, + myAmbientRed2, + myAmbientGreen2, + myAmbientBlue2, + myEmissiveRed2, + myEmissiveGreen2, + myEmissiveBlue2, + myDiffuseRed2, + myDiffuseGreen2, + myDiffuseBlue2, + mySpecularRed2, + mySpecularGreen2, + mySpecularBlue2, + mySpecularShininess2, + myOpacityRed2, + myOpacityGreen2, + myOpacityBlue2, + myZDither2, + *myMorphControl, + oldMorphControl, + myAmbientRed, + myAmbientGreen, + myAmbientBlue, + myEmissiveRed, + myEmissiveGreen, + myEmissiveBlue, + myDiffuseRed, + myDiffuseGreen, + myDiffuseBlue, + mySpecularRed, + mySpecularGreen, + mySpecularBlue, + mySpecularShininess, + myOpacityRed, + myOpacityGreen, + myOpacityBlue, + myZDither; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for DPLDamageMaterialRenderable +// This renderable handles modifying a material in response to damage. We +// get the pointer to an existing DPL material on startup and we get out +// color and texture settings from that +class DPLDamageMaterialRenderable: + public VideoRenderable +{ + public: + DPLDamageMaterialRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_MATERIAL *damage_material, // The material we want to control + Scalar *damage_attribute, // The attribute containing the current damage level + Scalar damage_percent); // Degradation factor to make damaged material + + ~DPLDamageMaterialRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_MATERIAL + *myMaterial; + Scalar + *myDamageAttribute, + oldDamageAttribute, + myAmbientRed1, + myAmbientGreen1, + myAmbientBlue1, + myEmissiveRed1, + myEmissiveGreen1, + myEmissiveBlue1, + myDiffuseRed1, + myDiffuseGreen1, + myDiffuseBlue1, + mySpecularRed1, + mySpecularGreen1, + mySpecularBlue1, + mySpecularShininess1, + myOpacityRed1, + myOpacityGreen1, + myOpacityBlue1, + myAmbientRed2, + myAmbientGreen2, + myAmbientBlue2, + myEmissiveRed2, + myEmissiveGreen2, + myEmissiveBlue2, + myDiffuseRed2, + myDiffuseGreen2, + myDiffuseBlue2, + mySpecularRed2, + mySpecularGreen2, + mySpecularBlue2, + mySpecularShininess2, + myOpacityRed2, + myOpacityGreen2, + myOpacityBlue2, + myAmbientRed, + myAmbientGreen, + myAmbientBlue, + myEmissiveRed, + myEmissiveGreen, + myEmissiveBlue, + myDiffuseRed, + myDiffuseGreen, + myDiffuseBlue, + mySpecularRed, + mySpecularGreen, + mySpecularBlue, + mySpecularShininess, + myOpacityRed, + myOpacityGreen, + myOpacityBlue; +}; +// From here to the row of ### is pretty kludgy stuff to allow dave to prototype +// some explosion stuff. +// I expect to replace most of it within a week with the all-new micro +// renderable system. +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// InstanceSwitchRenderable +class InstanceSwitchRenderable: + public VideoRenderable +{ + public: + InstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // instance on when trigger is.... + int *trigger); // true if the instance is on, false if off + + ~InstanceSwitchRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Logical + mySense; + dpl_INSTANCE + *myInstance; + int + *myTriggerAttribute, + oldTriggerAttribute; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// StateInstanceSwitchRenderable +class StateInstanceSwitchRenderable: + public VideoRenderable +{ + public: + StateInstanceSwitchRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_INSTANCE *this_instance, // the instance to control + Logical sense, // true to turn on in this state, false for off + StateIndicator *state_dial, // State dial we use to control the on/off + unsigned trigger_state); // State that we look for + + ~StateInstanceSwitchRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Logical + myLastInstanceState, + mySense; + dpl_INSTANCE + *myInstance; + unsigned + myTriggerState; + StateIndicator + *myStateDial; + +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// MakeDCSFall +class MakeDCSFall: + public VideoRenderable +{ + public: + MakeDCSFall( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_DCS *this_DCS, // the DCS to control + Scalar gravity, // Gravity in meters/sec squared + int *trigger); // true if the instance is on, false if off + + ~MakeDCSFall(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_DCS + *myDCS; + int + *myTrigger, + fakeTrigger, + oldMyTrigger; + Point3D + myDisplacement; + Scalar + myFallStart, + myHalfAcceleration; +}; + + +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~End of the new renderable class hiearchy~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~Dynamic Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//########################################################################## +class DPLEyeRenderable: // this renderable handles a dynamic eyepoint + public HierarchicalDrawComponent +{ +public: + DPLEyeRenderable( + Entity* This_Entity, + const LinearMatrix& Offset_Matrix, + HierarchicalDrawComponent* Parent, + EulerAngles* eyepoint_rotation // Pointer to attribute that contains eye rotations + ); + ~DPLEyeRenderable(); + + dpl_DCS* + GetDCS() + {return myDCS;} + + Logical + TestInstance() const; + + virtual void + Execute(); + +protected: + dpl_DCS + *myDCS, + *myParentDCS; + + LinearMatrix + myOrientationMatrix; + + EulerAngles + *myEyepointRotation, + oldEyepointRotation; + + Matrix4x4 camMatrix; + LinearMatrix oldLocalToWorld; // The value of this matrix the last time through + + Entity + *myEntity; + + LPDIRECT3DDEVICE9 myDevice; + bool mForceUpdate; +}; + +//########################################################################## +class DPLChildPointRenderable: // this is a child DCS carrying an instance + public HierarchicalDrawComponent +{ +public: + DPLChildPointRenderable( + Entity *This_Entity, + bool isDeathZone, + d3d_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + HierarchicalDrawComponent *Parent, + Point3D *my_point + ); + ~DPLChildPointRenderable(); + + dpl_DCS* + GetDCS() + {return myDCS;} + + Logical + TestInstance() const; + +protected: + + void + Execute(); + + dpl_DCS + *myOffsetDCS, + *myDCS, + *myParentDCS; + + dpl_INSTANCE + *myInstance; + + LinearMatrix + OrientationMatrix; + + Entity + *myEntity; + Point3D + *myPoint, + OldPoint; +}; +//########################################################################## +class DPLScaleRenderable: // This is a DCS that responds to scaling + public HierarchicalDrawComponent +{ +public: + DPLScaleRenderable( + Entity *This_Entity, + bool isDeathZone, + d3d_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + HierarchicalDrawComponent *Parent, + Vector3D *my_scale_vector, + Logical *visible + ); + ~DPLScaleRenderable(); + +// dpl_DCS* // we don't allow this (yet) because it prevents +// GetDCS() // people from hooking up children to this renderable +// {return myDCS;} + + Logical + TestInstance() const; + + virtual void Execute(); + +protected: + + Logical + *myVisible, + OldVisible; + dpl_DCS + *myDCS, + *myParentDCS; + + dpl_INSTANCE + *myInstance; + + AffineMatrix + OffsetMatrix; + + Entity + *myEntity; + + Vector3D + *myScaleVector, + OldScaleVector; + + Matrix4x4 transMatrix; + d3d_OBJECT *myObject; +}; +//########################################################################## +class DPLScaleQuatRenderable: // This is a DCS that responds to scaling and quaterninons + public HierarchicalDrawComponent +{ +public: + DPLScaleQuatRenderable( + Entity *This_Entity, + bool isDeathZone, + d3d_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + HierarchicalDrawComponent *Parent, + Quaternion *rotation_quaternion, + Vector3D *my_scale_vector, + Logical *visible + ); + ~DPLScaleQuatRenderable(); + +// dpl_DCS* // we don't allow this (yet) because it prevents +// GetDCS() // people from hooking up children to this renderable +// {return myDCS;} + + Logical + TestInstance() const; + +protected: + + void + Execute(); + + Logical + *myVisible, + OldVisible; + + dpl_DCS + *myDCS, + *myParentDCS; + + dpl_INSTANCE + *myInstance; + + AffineMatrix + OffsetMatrix; + + Entity + *myEntity; + + Quaternion + *myRotationQuaternion, + OldRotationQuaternion; + + Vector3D + *myScaleVector, + OldScaleVector; + + Matrix4x4 tempMatrix; + d3d_OBJECT *myObject; +}; +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~Static Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~these renderables remain constant after construction~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//########################################################################## +class DPLStaticChildRenderable: // this is a child DCS carrying an instance + public HierarchicalDrawComponent +{ +public: + DPLStaticChildRenderable( + Entity *This_Entity, + bool isDeathZone, + d3d_OBJECT *Graphic_Object, + dpl_ISECT_MODE Intersect_Mode, + uint32 Intersect_Mask, + const LinearMatrix &Offset_Matrix, + HierarchicalDrawComponent *Parent_DCS + ); + ~DPLStaticChildRenderable(); + + dpl_DCS* GetDCS() { return myDCS; } + + dpl_INSTANCE* GetInstance() { return myInstance; } + + Logical TestInstance() const; + + virtual void Execute(); +protected: + dpl_DCS *myDCS, *myParentDCS; + + dpl_INSTANCE *myInstance; + + Matrix4x4 OrientationMatrix; + d3d_OBJECT *myObject; + + Entity *myEntity; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~Special Effects Renderables~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class DPLSFXRenderable: // A renderable that spawns special effects + public HierarchicalDrawComponent +{ +public: + DPLSFXRenderable( + Entity *This_Entity, // Entity to attach the effect to + bool isDeathZone, // DPL zone everything will be in + const Point3D &Offset_Point, // Point offset from the parent DCS + HierarchicalDrawComponent *Parent, // Parent DCS (can be NULL for world) + StateIndicator *Effect_Trigger, // Trigger effect when this attribute changes + int Trigger_State, // Trigger effect when in this state + int Effect_Type, // Type of effect to trigger + Scalar Repeat_Speed // Effect repeat speed. + ); + + ~DPLSFXRenderable(); + + dpl_DCS* + GetDCS() + {return myParentDCS;} + + Logical + TestInstance() const; + +protected: + + void + Execute(); + + int + myEffectType, + myEffectTriggerState, + myEffectTriggerOld; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_DCS + *myParentDCS; + + Point3D + myOffsetPoint; + + Scalar + myRepeatSpeed, + myLastEffect; + + ParticleEmitter mEmitter; + Entity *myEntity; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class DPLRepeatSFXRenderable: // A renderable that spawns special effects + public HierarchicalDrawComponent +{ +public: + DPLRepeatSFXRenderable( + Entity *This_Entity, + bool isDeathZone, + const Point3D &Offset_Point, + HierarchicalDrawComponent *Parent, // offset is relative to this + int Effect_Type, // type code for the effect + Scalar *Speed + ); + + ~DPLRepeatSFXRenderable(); + + dpl_DCS* GetDCS() { return myParentDCS; } + + Logical TestInstance() const; + +protected: + + void Execute(); + void Render(bool isSemiTransparent); + + Entity *myEntity; + + dpl_DCS *myParentDCS; + HierarchicalDrawComponent *myParent; + + Point3D myOffsetPoint; + + int myEffectType; + ParticleEmitter mEmitter; + LinearMatrix mOldLocalToWorld; // The value of this matrix the last time through + Matrix4x4 mTransMatrix; + + Scalar *mySpeed, myLastSmoke; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +class DPLTranslocationRenderable: // A renderable for the UFT translocation efffec + public HierarchicalDrawComponent // from the POV of the player +{ +public: + DPLTranslocationRenderable( + Entity *This_Entity, // Entity to attach the effect to + bool isDeathZone, // DPL zone everything will be in + StateIndicator *Effect_Trigger, // Trigger effects off of this state dial + Point3D *Drop_Zone_Location, // Attribute that holds where the new drop will be + unsigned Drop_Zone_State + ); + + ~DPLTranslocationRenderable(); + +// dpl_DCS* +// GetDCS() +// {return myParentDCS;} + + Logical + TestInstance() const; + +protected: + enum TranslocateState + { + IdleState, + InitialExpandState, + HoldAtSizeState, + ColapseState + }; + + TranslocateState + myState; + + void + Execute(); + + int + myDropZoneState, + myEffectType, + myEffectTriggerOld; + + Scalar + myEffectTimer; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_INSTANCE + *myInstance; + + dpl_DCS + *myDCS; + + dpl_ZONE + *myZone; + + Entity + *myEntity; + + Point3D + *myDropZoneLocation; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// This is brand new stuff as of 5/12/96 +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// DependantRenderable +// This is a class of renderable that has other dependant renderables which it +// will execute on command. This is a base for this type of renderable and is +// not ment to be used by itself. +// +class DependantRenderable: + public VideoRenderable +{ + public: + DependantRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type // How/when to execute the renderable + ); + + ~DependantRenderable(); + + void + AddDependantRenderable(Component *dependant); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + SChainOf + dependantRenderableSocket; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ScalarTriggerRenderable +// This renderable will run all it's dependants whenever a scalar value that +// it's watching changes. +// +class ScalarTriggerRenderable: + public DependantRenderable +{ + public: + ScalarTriggerRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar *watched_value, // we run dependants when this changes + Scalar watched_precision // watched_value must change by this much + ); + + ~ScalarTriggerRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Scalar + *myWatchedValue, // Pointer to the Scalar we're watching + myOldWatchedValue, // The last value of that scalar we saw + myPrecision; // Change must be at least this big to register + +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// TimeCullRenderable +// This renderable will run all it's dependants at a set frequency based on +// a clock value supplied by the culling system. +// +class TimeCullRenderable: + public DependantRenderable +{ + public: + TimeCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Scalar delay_between_runs // Time delay between executions of dependants + ); + + ~TimeCullRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + Scalar + nextRunTime, + delayBetweenRuns; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// MechCullRenderable +// +class MechCullRenderable: + public DependantRenderable +{ + public: + MechCullRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + Logical always_run_all, // If true, disable culling and run everything + bool isDeathZone // Switch off this zone when the mech goes off screen + ); + + ~MechCullRenderable(); + + Logical + TestInstance() const; + void + AddDependantLegRenderable(Component *dependant); + void + Execute(); + + protected: + Logical + myMechWasVisible, + myAlwaysRunAll; + dpl_ZONE + *myZone; + Scalar + myNextRootUpdate, + myRootUpdateRate, + myNextLegUpdate, + myLegUpdateRate; + SChainOf + legRenderableSocket; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for OnePSFXRenderable +// This renderable triggers off a single PSFX effect and then hangs around and +// kills the effect when the renderable goes away. This is useful for things +// like missiles which you want to leave a smoke trail that stops if the object +// is destroyed. You REALLY want to do this whenever you attach an effect to +// a DCS since if the DCS goes away the DPL renderer will go wackey. +// + +class OnePSFXRenderable: + public VideoRenderable +{ + public: + OnePSFXRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + dpl_PARTICLESTART_EFFECT_INFO *psfx_definition, // name of file with the PFX description in it + HierarchicalDrawComponent *parent, // DCS the effect is relative to (may be NULL) + Point3D *offset_point); // Offset (or world coordinants if DCS is NULL) + + ~OnePSFXRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + dpl_PARTICLESTART_EFFECT_INFO + myPSFXInfo; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Constructor for TranslocationRenderable +// This renderable does the UFT translocation effect from the perspective of +// someone else watching the person translocating. We connect this to the +// player object and uses information from that object to position itself. +// +class TranslocationRenderable: + public VideoRenderable +{ +public: + TranslocationRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + bool isDeathZone, // DPL zone everything will be in + StateIndicator *effect_trigger, // Trigger effects off of this state dial + Point3D *drop_zone_location, // Attribute that holds where the new drop will be + unsigned drop_zone_state // State that indicates drop zone is valid (starts effect) + ); + + ~TranslocationRenderable(); + + Logical + TestInstance() const; + +protected: + enum TranslocateState + { + IdleState, + InitialExpandState, + HoldAtSizeState, + ColapseState + }; + + TranslocateState + myState; + + void + Execute(); + + int + myDropZoneState, + myEffectType; + + Scalar + myEffectTimer; + + StateIndicator + *myEffectTrigger; // trigger effect when this changes + + dpl_INSTANCE + *myInstance; + + dpl_DCS + *myDCS; + + dpl_ZONE + *myZone; + + Point3D + *myDropZoneLocation; + + d3d_OBJECT *myTranslocateSphere; + Matrix4x4 localToWorld; + bool visible; + LPDIRECT3DDEVICE9 myDevice; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// SpinScaleQuatWatcherRenderable This is used to create a laser style effect +// that has a directional control, scale and an axial spin at a pre-set speed +// (used for PPC's) +// +class SpinScaleQuatWatcherRenderable: + public ChildOffsetRenderable +{ + public: + SpinScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector, // Scales the object + Scalar z_spin_rate); // spins the object about z (radians/frame) + + ~SpinScaleQuatWatcherRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + StateIndicator + *myControl; + unsigned + myTriggerState; + Quaternion + *myRotationQuaternion; + Vector3D + *myScaleVector; + Logical + myVisible; + Scalar + myZSpinRate, + OldZSpin; +}; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// ScaleQuatWatcherRenderable This is used to create a laser style effect +// that has a directional control and scaling +// +class ScaleQuatWatcherRenderable: + public ChildOffsetRenderable +{ + public: + ScaleQuatWatcherRenderable( + Entity *entity, // Entity to attach the renderable to + ExecutionType execution_type, // How/when to execute the renderable + d3d_OBJECT *graphical_object, // object to hang on the DCS, may be a list later + bool isDeathZone, // DPL Zone this stuff will live in (for culling) + dpl_ISECT_MODE intersect_mode, // type of intersections to do on this object + uint32 intersect_mask, // intersection mask for the object + HierarchicalDrawComponent *parent, // the parent DCS we will be offsetting from + LinearMatrix *offset_matrix, // offset matrix to be applied prior to joint DCS + StateIndicator *control, // the state dial that controls this renderable + unsigned effect_trigger_state,// the state that turns on the renderable + Quaternion *rotation_quaternion,// rotates the object + Vector3D *scale_vector); // Scales the object + + ~ScaleQuatWatcherRenderable(); + + Logical + TestInstance() const; + + void + Execute(); + + protected: + StateIndicator + *myControl; + unsigned + myTriggerState; + Quaternion + *myRotationQuaternion; + Vector3D + *myScaleVector; + Logical + myVisible; +}; diff --git a/MUNGA_L4/L4VIDTUL.cpp b/MUNGA_L4/L4VIDTUL.cpp new file mode 100644 index 0000000..9131983 --- /dev/null +++ b/MUNGA_L4/L4VIDTUL.cpp @@ -0,0 +1,10 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4video.h" +#include "l4tool.h" + +ResourceDescription::ResourceID L4Tool::CreateModelVideoStreamResource(ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories *directories) +{ + return DPLRenderer::CreateModelVideoStreamResource(resource_file, model_name, model_file, directories); +} diff --git a/MUNGA_L4/L4WRHOUS.cpp b/MUNGA_L4/L4WRHOUS.cpp new file mode 100644 index 0000000..3fe6ca0 --- /dev/null +++ b/MUNGA_L4/L4WRHOUS.cpp @@ -0,0 +1,40 @@ +#include "mungal4.h" +#pragma hdrstop + +#include "l4wrhous.h" + +#if defined(LOCAL_TEST) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +//####################################################################### +// Warehouse +//####################################################################### +L4Warehouse::L4Warehouse() : Warehouse() +{ + Check_Pointer(this); + Check_Fpu(); +} + +L4Warehouse::~L4Warehouse() +{ + Check(this); + Check_Fpu(); +} + +void L4Warehouse::Purge() +{ + Check(this); + + gaugeImageBin.Purge(); + Warehouse::Purge(); + + Check_Fpu(); +} + +Logical L4Warehouse::TestInstance() const +{ + return Warehouse::TestInstance(); +} diff --git a/MUNGA_L4/L4WRHOUS.h b/MUNGA_L4/L4WRHOUS.h new file mode 100644 index 0000000..d6d2b8e --- /dev/null +++ b/MUNGA_L4/L4WRHOUS.h @@ -0,0 +1,18 @@ +#pragma once + +#include "..\munga\wrhous.h" +#include "l4gauima.h" + +//####################################################################### +// L4Warehouse +//####################################################################### +class L4Warehouse : public Warehouse +{ +public: + L4Warehouse(); + ~L4Warehouse(); + Logical TestInstance() const; + void Purge(); + + WarehouseBinOf gaugeImageBin; +}; \ No newline at end of file diff --git a/MUNGA_L4/MUNGAL4.H b/MUNGA_L4/MUNGAL4.H new file mode 100644 index 0000000..eb43e78 --- /dev/null +++ b/MUNGA_L4/MUNGAL4.H @@ -0,0 +1,16 @@ +#pragma once + +#include "..\munga\munga.h" + +#define __DPMI32__ +#include + +#if !defined(NO_PRECOMPILED_HEADERS) + +#include "..\munga\graph2d.h" + +#include "l4host.h" +#include "l4app.h" + +#endif + diff --git a/MUNGA_L4/Munga_L4 VS2008.vcproj b/MUNGA_L4/Munga_L4 VS2008.vcproj new file mode 100644 index 0000000..3016efa --- /dev/null +++ b/MUNGA_L4/Munga_L4 VS2008.vcproj @@ -0,0 +1,1695 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MUNGA_L4/Munga_L4.vcproj b/MUNGA_L4/Munga_L4.vcproj new file mode 100644 index 0000000..332ea5e --- /dev/null +++ b/MUNGA_L4/Munga_L4.vcproj @@ -0,0 +1,1763 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/MUNGA_L4/WTPresets.cpp b/MUNGA_L4/WTPresets.cpp new file mode 100644 index 0000000..047f309 --- /dev/null +++ b/MUNGA_L4/WTPresets.cpp @@ -0,0 +1,47 @@ +#include "L4AUDLVL.h" + +bool PRESET_isImplemented(int bank, int presetn) +{ + PRESETINFO preset = allPresets[bank-1][presetn]; + + if (preset.sampleNum <= 0 || preset.sampleNum >= 5) + { + return false; + } + + for (int i=0; i < preset.sampleNum; i++) + { + if (preset.samples[i].implemented) + { + return true; + } + } + + return false; +} + +int PRESET_getNumSamples(int bank, int preset) +{ + return allPresets[bank-1][preset].sampleNum; +} + +SAMPLEINFO PRESET_getSampleInfo(int bank, int preset, int sampleInd) +{ + SAMPLEINFO default; + default.chan = SampleChannel::CHANNEL_CENTER; + default.file = ""; + default.implemented = false; + default.loop = SampleLoop::LoopAtWill; + + if (sampleInd < 0 || sampleInd >= allPresets[bank-1][preset].sampleNum) + { + return default; + } + + return allPresets[bank-1][preset].samples[sampleInd]; +} + +void PRESET_setBufferIndex(int bank, int preset, int sampleInd, int index) +{ + allPresets[bank-1][preset].samples[sampleInd].bufferIndex = index; +} \ No newline at end of file diff --git a/MUNGA_L4/libDPL/dpl/DPLUTILS.H b/MUNGA_L4/libDPL/dpl/DPLUTILS.H new file mode 100644 index 0000000..dbd03fe --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/DPLUTILS.H @@ -0,0 +1,408 @@ +/* + * ---------------------------------------------------------------------------- + * + * Copyright 1994 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: dplutils.h,v $ + * Revision : $Revision: 1.3 $ + * Date : $Date: 1995/05/19 09:23:43 $ + * Author : $Author: nga $ + * + * Description : + * + * Notes : + * + * History : + * + * $Log: dplutils.h,v $ + * Revision 1.3 1995/05/19 09:23:43 nga + * Added texture enable/disable functions. + * + * Revision 1.2 1995/04/26 20:09:51 nga + * Added "special" functions. + * + * Revision 1.1 1995/03/10 15:58:16 nga + * Initial revision + * + * ---------------------------------------------------------------------------- + */ + +#ifndef _DPLUTILS_H +#define _DPLUTILS_H + + +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * !!! - temporary definitions to make PP5 build. + */ + +#define dpl_SetExtnGeoLoadFunc dpl_SetExtnObjectLoadFunc +#define dpl_SetExtnTexLoadFunc dpl_SetExtnTexmapLoadFunc +#define dpl_b2zRead NULL + + +/* + * Types. + */ + +/* dPL load mode. */ +typedef enum +{ + dpl_load_normal = 0x00, + dpl_load_nocache = 0x01, + dpl_load_noload = 0x02, + dpl_load_noreference = 0x04 +} dpl_LOAD_MODE; + +/* dPL look up mode. */ +typedef enum +{ + dpl_lookup_normal = 0x00, + dpl_lookup_nocreate = 0x01, + dpl_lookup_define = 0x02, + dpl_lookup_noreference = 0x04 +} dpl_LOOKUP_MODE; + +/* dPL path type. */ +typedef enum +{ + dpl_path_system, + dpl_path_user, + dpl_path_offset +} dpl_PATH_TYPE; + +/* dPL create/delete callback function type. */ +typedef void (dpl_CREATE_DELETE_CALLBACK)(dpl_TYPE type, void *handle); + +/* dPL special callback function type. */ +typedef void (dpl_SPECIAL_CALLBACK)(dpl_TYPE type, void *handle, + char8 *special, uint32 special_len); + +/* dPL material name callback function type. */ +typedef char8 *(dpl_MATERIAL_NAME_CALLBACK)(char8 *mat_name); + + +/* + * Prototypes. + */ + +extern void +dpl_SetObjectFileCacheSize(uint32 size); + +extern uint32 +dpl_GetObjectFileCacheSize(void); + +extern void +dpl_SetTexmapFileCacheSize(uint32 size); + +extern uint32 +dpl_GetTexmapFileCacheSize(void); + +extern void +dpl_SetMaterialFileCacheSize(uint32 size); + +extern uint32 +dpl_GetMaterialFileCacheSize(void); + +extern void +dpl_SetMaterialItemCacheSize(uint32 size); + +extern uint32 +dpl_GetMaterialItemCacheSize(void); + +extern void +dpl_SetHandleCacheSize(uint32 size); + +extern uint32 +dpl_GetHandleCacheSize(void); + +/* Add a path to object search path. */ +extern void +dpl_AddToObjectFilePath(char8 *path, dpl_PATH_TYPE type); + +/* Set entire object search path. */ +extern void +dpl_SetObjectFilePath(char8 *sys_path, char8 *user_path, char8 *offset); + +/* Get entire object search path. */ +extern char8 * +dpl_GetObjectFilePath(void); + +/* Associate an extension with a object load function. */ +extern void +dpl_SetExtnObjectLoadFunc(char8 *extn, dpl_LOAD_FUNCTION *load_func); + +/* Get a load function associated with an extension. */ +extern dpl_LOAD_FUNCTION * +dpl_GetExtnObjectLoadFunc(char8 *e); + +/* Get object file extensions. */ +extern char8 * +dpl_GetObjectFileExtns(void); + +/* Add a path to texmap search path. */ +extern void +dpl_AddToTexmapFilePath(char8 *path, dpl_PATH_TYPE type); + +/* Set entire texmap search path. */ +extern void +dpl_SetTexmapFilePath(char8 *sys_path, char8 *user_path, char8 *offset); + +/* Get entire texmap search path. */ +extern char8 * +dpl_GetTexmapFilePath(void); + +/* Associate an extension with a texmap load function. */ +extern void +dpl_SetExtnTexmapLoadFunc(char8 *extn, dpl_LOAD_FUNCTION *load_func); + +/* Get a load function associated with an extension. */ +extern dpl_LOAD_FUNCTION * +dpl_GetExtnTexmapLoadFunc(char8 *e); + +/* Get texmap file extensions. */ +extern char8 * +dpl_GetTexmapFileExtns(void); + +/* Add a path to material search path. */ +extern void +dpl_AddToMaterialFilePath(char8 *path, dpl_PATH_TYPE type); + +/* Set entire material search path. */ +extern void +dpl_SetMaterialFilePath(char8 *sys_path, char8 *user_path, char8 *offset); + +/* Get entire material search path. */ +extern char8 * +dpl_GetMaterialFilePath(void); + +/* Set texture load enable. */ +void +dpl_SetTextureLoadEnable(int32 i); + +/* Get texture load enable. */ +int32 +dpl_GetTextureLoadEnable(void); + +/* Set detail texture load enable. */ +void +dpl_SetDetailTextureLoadEnable(int32 i); + +/* Get detail texture load enable. */ +int32 +dpl_GetDetailTextureLoadEnable(void); + + +/* + * Built-in load functions. + */ + +/* bgf object file reader. */ +extern void * +dpl_bgfRead(char8 *); + +/* vtx texmap file reader. */ +extern void * +dpl_vtxRead(char8 *); + +/* SGI texmap file reader. */ +extern void * +dpl_sgiRead(char8 *); + +/* TGA texmap file reader. */ +extern void * +dpl_tgaRead(char8 *); + + +/* + * Find file & perform the loading function, based on extension returning + * NULL where the load fails. + */ + +extern dpl_OBJECT * +dpl_LoadObject(char8 *fname, dpl_LOAD_MODE mode); + +extern void +dpl_UnloadObject(dpl_OBJECT *o); + +extern dpl_TEXMAP * +dpl_LoadTexmap(char8 *fname, dpl_LOAD_MODE mode); + +extern void +dpl_UnloadTexmap(dpl_TEXMAP *t); + + +/* + * dPL lookup functions. + */ + +extern dpl_MATERIAL * +dpl_LookupMaterial(char8 *name, dpl_LOOKUP_MODE mode, int32 *status); + +extern void +dpl_ReferenceMaterial(dpl_MATERIAL *m); + +extern void +dpl_UnreferenceMaterial(dpl_MATERIAL *m); + +extern char8 * +dpl_LookupMaterialName(dpl_MATERIAL *m); + +extern dpl_MATERIAL * +dpl_GetFirstMaterial(char8 **name); + +extern dpl_MATERIAL * +dpl_GetNextMaterial(char8 **name); + +extern dpl_TEXTURE * +dpl_LookupTexture(char8 *name, dpl_LOOKUP_MODE mode, int32 *status); + +extern void +dpl_ReferenceTexture(dpl_TEXTURE *t); + +extern void +dpl_UnreferenceTexture(dpl_TEXTURE *t); + +extern char8 * +dpl_LookupTextureName(dpl_TEXTURE *t); + +extern dpl_TEXTURE * +dpl_GetFirstTexture(char8 **name); + +extern dpl_TEXTURE * +dpl_GetNextTexture(char8 **name); + +extern dpl_RAMP * +dpl_LookupRamp(char8 *name, dpl_LOOKUP_MODE mode, int32 *status); + +extern void +dpl_ReferenceRamp(dpl_RAMP *r); + +extern void +dpl_UnreferenceRamp(dpl_RAMP *r); + +extern char8 * +dpl_LookupRampName(dpl_RAMP *r); + +extern dpl_RAMP * +dpl_GetFirstRamp(char8 **name); + +extern dpl_RAMP * +dpl_GetNextRamp(char8 **name); + +extern dpl_LOD * +dpl_LookupLod(dpl_OBJECT *object, char8 *name, dpl_LOOKUP_MODE mode, + int32 *status); + +extern void +dpl_ReferenceLod(dpl_LOD *l); + +extern void +dpl_UnreferenceLod(dpl_LOD *l); + +extern char8 * +dpl_LookupLodName(dpl_LOD *l); + +extern dpl_LOD * +dpl_GetFirstLod(char8 **name); + +extern dpl_LOD * +dpl_GetNextLod(char8 **name); + +extern dpl_GEOGROUP * +dpl_LookupGeogroup(dpl_OBJECT *object, char8 *name, dpl_LOOKUP_MODE mode, + int32 *status); + +extern void +dpl_ReferenceGeogroup(dpl_GEOGROUP *g); + +extern void +dpl_UnreferenceGeogroup(dpl_GEOGROUP *g); + +extern dpl_GEOGROUP * +dpl_GetFirstGeogroup(char8 **name); + +extern dpl_GEOGROUP * +dpl_GetNextGeogroup(char8 **name); + +extern char8 * +dpl_LookupGeogroupName(dpl_GEOGROUP *g); + +extern char8 * +dpl_LookupGeogroupSpecial(dpl_GEOGROUP *g, uint32 *len); + +extern char8 * +dpl_LookupObjectFileName(dpl_OBJECT *o); + +extern char8 * +dpl_LookupObjectName(dpl_OBJECT *o); + +extern char8 * +dpl_LookupObjectSpecial(dpl_OBJECT *o, uint32 *len); + +extern char8 * +dpl_LookupTexmapFileName(dpl_TEXMAP *t); + + +/* + * dPL callback function. + */ + +extern void +dpl_SetCreateNodeCallback(dpl_CREATE_DELETE_CALLBACK *func); + +extern dpl_CREATE_DELETE_CALLBACK * +dpl_GetCreateNodeCallback(void); + +extern void +dpl_SetDeleteNodeCallback(dpl_CREATE_DELETE_CALLBACK *func); + +extern dpl_CREATE_DELETE_CALLBACK * +dpl_GetDeleteNodeCallback(void); + +extern void +dpl_SetSpecialCallback(dpl_SPECIAL_CALLBACK *func); + +extern dpl_SPECIAL_CALLBACK * +dpl_GetSpecialCallback(void); + +extern void +dpl_SetMaterialNameCallback(dpl_MATERIAL_NAME_CALLBACK *func); + +extern dpl_MATERIAL_NAME_CALLBACK * +dpl_GetMaterialNameCallback(void); + + +/* + * dPL error and warning message function. + */ + +extern void +dpl_SetWarnLogFile(FILE *fp); + +extern void +dpl_Warn(dpl_WARN_LEVEL l, char8 *format, ...); + + +/* + * dPL Utilities version. + */ + +extern char8 * +dpl_UtilsVersion(void); + +#ifdef __cplusplus +} +#endif + + +#endif /* _DPLUTILS_H */ diff --git a/MUNGA_L4/libDPL/dpl/DPL_2D.H b/MUNGA_L4/libDPL/dpl/DPL_2D.H new file mode 100644 index 0000000..ef06cbd --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/DPL_2D.H @@ -0,0 +1,123 @@ +#ifndef dpl_2d_h +#define dpl_2d_h +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define WORDS_PER_DISPLAY_CHUNK 30 + +typedef struct s_dpl2d_display { + void *remote; + struct s_dpl2d_display *next; + struct s_dpl2d_display *tail; + int32 size; + int32 open; + int32 data[WORDS_PER_DISPLAY_CHUNK]; +} dpl2d_DISPLAY; + +typedef enum dpl2d_OPEN_MODE +{ + dpl2d_open_mode_error, + dpl2d_open_mode_clear, + dpl2d_open_mode_append +} dpl2d_OPEN_MODE; + +typedef enum dpl2d_CLIP_MODE +{ + dpl2d_clip_mode_error, + dpl2d_clip_mode_OR, + dpl2d_clip_mode_AND, + dpl2d_clip_mode_XOR, + dpl2d_clip_mode_SET, + dpl2d_clip_mode_CLEAR +} dpl2d_CLIP_MODE; + +typedef int32 *dpl_2d_snapshot; + +typedef float32 dpl2d_MATRIX [6]; + +/* displaylist creation, destruction */ + +extern dpl2d_DISPLAY *dpl2d_NewDisplayList ( void ); + +extern int32 dpl2d_DeleteDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_OpenDisplayList ( dpl2d_DISPLAY *display, dpl2d_OPEN_MODE append ); + +extern int32 dpl2d_CloseDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_FlushDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenPolyline ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClosePolyline ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenLines ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddCloseLines ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenPolypoint ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClosePolypoint ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddPoint ( dpl2d_DISPLAY *display, float32 x, float32 y ); + +extern int32 dpl2d_AddCircle( dpl2d_DISPLAY *display, float32 x, float32 y, float32 r, int32 filled ); + +extern int32 dpl2d_AddPushState ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddPopState ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddSetColor ( dpl2d_DISPLAY *display, float32 r, float32 g, float32 b ); + +extern int32 dpl2d_AddSetAlpha ( dpl2d_DISPLAY *display, float32 a ); + +extern int32 dpl2d_AddSetMatrix ( dpl2d_DISPLAY *display, dpl2d_MATRIX ); + +extern int32 dpl2d_AddConcatMatrix ( dpl2d_DISPLAY *display, dpl2d_MATRIX, int32 post ); + +extern int32 dpl2d_AddSetLineWidth ( dpl2d_DISPLAY *display, + float32 w ); + +/* clip region support */ +extern int32 dpl2d_AddFullScreenClipRegion ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClearClipRegion ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenClipPolygon ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddCloseClipPolygon ( dpl2d_DISPLAY *display, + dpl2d_CLIP_MODE mode ); + +extern int32 dpl2d_AddClipCircle ( dpl2d_DISPLAY *display, + float32 x, float32 y, float32 rad, + dpl2d_CLIP_MODE mode ); + + +extern int32 dpl2d_AddCallDisplayList ( dpl2d_DISPLAY *display, + dpl2d_DISPLAY *sub_display ); + +extern int32 dpl2d_SetViewDisplayList ( dpl_VIEW *v, dpl2d_DISPLAY *disp ); + +extern dpl2d_DISPLAY *dpl2d_GetViewDisplayList ( dpl_VIEW *v ); + +/* and now the 2-D matrix support */ + +extern void dpl2d_IdMatrix ( dpl2d_MATRIX m ); +extern void dpl2d_TranslateMatrix ( dpl2d_MATRIX m, + float32 x, float32 y ); +extern void dpl2d_RotateMatrix ( dpl2d_MATRIX m, + float32 angle ); +extern void dpl2d_ScaleMatrix ( dpl2d_MATRIX m, + float32 sx, float32 sy ); +extern void dpl2d_ConcatMatrix ( dpl2d_MATRIX m, + dpl2d_MATRIX a, + dpl2d_MATRIX b ); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/MUNGA_L4/libDPL/dpl/DPL_PRIV.H b/MUNGA_L4/libDPL/dpl/DPL_PRIV.H new file mode 100644 index 0000000..0f5425d --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/DPL_PRIV.H @@ -0,0 +1,531 @@ +#ifndef dpltyp_h +#define dpltyp_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpltypes.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Flesh out all the datatypes + + History : Rev 1.0, 18 / 06 / 1994 + 1.1, 22 / 06 / 1994 fixed unimplementable lists by + introducing dpl_superlist + 1.2, 27 / 06 / 1994 dislocated heirarchy from instances + and dropped back to matrix-only DCS + 2.0 16 / 11 / 1994 angusification started + + **************************** */ + +#include +#include + +#define OFF_SITE 1 + +#ifdef i860 +#define REMOTE 1 +#endif + +#define dpl_arg_sep '~' + +#define dcs_node_enable 0x1 +#define dcs_subtree_enable 0x2 +#define dcs_no_view_concat 0x4 + +#define dcs_billboard_x 0x8 +#define dcs_billboard_y 0x10 +#define dcs_billboard_z 0x20 +#define dcs_explode_geo 0x40 +#define dcs_ignore_geo 0x80 + +#define dcs_inherit_lmodel 0x100 +#define dcs_force_eval_lmodel 0x200 +#define dcs_near_field 0x400 +#define dcs_bounded 0x800 +#define dcs_backwards 0x1000 +#define dcs_uniform_scale 0x2000 + +#define dpl_draw_faceted 0x0000 +#define dpl_draw_smooth 0x0001 +#define dpl_draw_colored 0x0002 +#define dpl_draw_luminance 0x0004 +#define dpl_draw_textured 0x0008 +#define dpl_draw_3dtextured 0x0010 +#define dpl_draw_front 0x0200 +#define dpl_draw_back 0x0400 +#define dpl_draw_edges 0x0800 +#define dpl_draw_wireframe 0x1000 +#define dpl_draw_last 0x2000 +#define dpl_draw_envmapped 0x4000 +#define dpl_draw_flipped 0x8000 +#define dpl_draw_f_emissive 0x0020 +#define dpl_draw_b_emissive 0x0040 + +#define dpl_X 0 +#define dpl_Y 1 +#define dpl_Z 2 +#define dpl_W 3 + +#ifdef _DOS +#define dpl_path_separator '\\' +#else +#define dpl_path_separator '/' +#endif + +/* + NOTE in rpc implementations, the rather large overhead + of the dpl_node dplnode is never passed over to the + remote renderer, its just in the host space for management +*/ + +typedef struct s_dplnode* (*node_create_function)( void ); + +typedef struct s_dplnode { + int32 clean; + void *app_specific; + void *remote; /* this MUST be 1st word of REMOTE data */ + dpl_TYPE type_check; +} dpl_node; + +typedef struct s_dplremote_node { + void *remote; + dpl_TYPE type_check; +} dpl_remote_node; + +#ifdef REMOTE +#define dpl_node dpl_remote_node +#endif + +typedef struct s_dpl_chain_node { + dpl_node node; + struct s_dpl_chain_node *next_node; + struct s_dpldcs *dcs; +} dpl_chain_node; + +typedef int32 (*load_function)( dpl_node *, char * ); + +typedef struct s_dpllist { + dpl_node *item; + dpl_TYPE type_check; + struct s_dpllist *next; + struct s_dpllist *prev; +} dpl_list; + +/* + the dpl_superlist is used as the head node for + dpl_lists +*/ + +typedef struct s_dplsuperlist { + dpl_node *dplnode; + + dpl_list *last_accessed; + dpl_list *head; + dpl_list *tail; +} dpl_superlist; + +typedef float32 dpl_POINT [4]; +typedef float32 dpl_MATRIX[4][4]; + +typedef union { + double dbl_MATRIX[8]; + dpl_MATRIX matrix; +} dpl_dblMATRIX; + +/* introduce local datatypes */ + + +/* + +The renderer is currently blowing off way too much storage on the card, +which stands to sense when each polygon is around 144 bytes, 80 bytes for the +vertex and 64 for the connection structure. The currently unused datatypes +below will eventually attempt to buy back a lot of storage by moving away +from linked lists and towards packed structures + +*/ + + +typedef struct s_rvert { + dpl_POINT position; /* 0 */ + dpl_POINT normcol; /* 16 */ + float32 texcoords [3]; /* 32 */ + struct s_rvert *next; /* 44 */ + dpl_POINT xform_posn; /* 48 */ + float32 rendered_color[3]; /* 64 */ + int32 touched; /* 76 */ +} dpl_VERTEX; + +typedef struct s_conn { + struct s_conn *next; /* 0 */ + int32 n_verts; /* 4 */ + dpl_VERTEX* indices[6]; /* 8 */ + dpl_POINT planeEqn; /* 32 */ + float32 rendered_color[3]; /* 48 */ + int32 touched; /* 60 */ +} dpl_CONNECTION; + + +/* we will only use this structure for polys, not spheres, + so the W-coordinate (radius) holds the touched word + */ + +typedef struct s_ivert { + float32 position[3]; /* 3 */ + int32 touched; /* 4 */ + dpl_POINT normcol; /* 8 */ + float32 texcoords [2]; /* 10 total = 40 bytes */ +} dpl_idealVERTEX; + +typedef struct s_iconn { + dpl_POINT planeEqn; /* 4 */ + dpl_idealVERTEX* indices[6]; /* 10 */ +} dpl_idealCONNECTION; /* total 40 bytes */ + +typedef struct s_oconn { + float planeEqn[3]; + int touched; + int indices[6]; +} dpl_outputCONNECTION; /* total 40 bytes */ + + +/* + it looks like we can drop polygon storage down to 80 bytes + per poly, rather than 144, so we can achieve around 80% more + database storage + + the assumption is that we use connection[3] == NULL as the triangle + spotter. is this iffy? it lets us keep hexes for performance. + + planeEqn[3] = touched for output conns, so we have 32 bytes, giving + a 72 byte triangle and _doubling_ storage. + + in order to make this work, we will need a single PMESH of worst-case + size hanging round in memory. So xforming and lighting will no longer + happen in-place, but the destination for the work will always be the + same area of memory. So we'll get better cache and page coherence. + + It is recommended that we drop PMESH size from 6 to 4. + + The VERTEX pointers in the connection structure must now become + byte indices, so we just add on the base address of the VERTEX + structure. + + The only problem is special effects - the sphere effects are just dealt + with by keeping spherelists in the old vertex format; triangle effects + may be more difficult to deal with. + + */ + + + +/* flesh out the datatypes in dpltypes.h */ + +#if 0 +struct s_dpl_statistics { + float32 polys_in_last_frame; + float32 last_edit_time; + float32 last_cull_time; + float32 last_frame_time; + float32 last_frame_time_sb; + float32 polys_per_second; + float32 polys_per_second_sb; +} dpl_STATISTICS; + +#endif + +struct s_dpldcs { + dpl_node dplnode; + dpl_chain_node *nodes; + struct s_dplzone *zone; + dpl_MATRIX matrix; + int32 traversal; /* overload billboards in here for compactness */ + struct s_dpldcs *parent; + struct s_dpldcs *sibling; + struct s_dpldcs *child; + int32 lighting_mask; + dpl_POINT bounds[2]; +#ifdef REMOTE + dpl_dblMATRIX invModel; + float sphere_scale, sphere_big_scale; +#endif +} ; +struct s_dplzone { + dpl_node dplnode; + + int32 view_enable; +} ; +struct s_dplview { + dpl_chain_node dplnode; + + int32 view_id; + int32 pipe; + float32 x0, y0, x1, y1, zeye; + float32 x_size, y_size; + float32 hither_clip; + float32 yon_clip; + float32 back_color[3]; + int32 fog_enable; + float32 fog[5]; /* near, phar, r, g, b */ + struct s_dplview *share_view; + void *display_2d; +} ; +struct s_dpllight { + dpl_chain_node dplnode; + + dpl_LIGHT_TYPE light_type; + float32 color [3]; + float32 radius [2]; /* for radial lights */ + float32 umbra [2]; /* for conical lights */ + int32 lighting_mask; +#ifdef REMOTE + float32 position[3]; +#endif +}; +struct s_dpltexture { + dpl_node dplnode; + + struct s_dpltexmap *texmap; + + int32 minify; + int32 magnify; + int32 alpha; + int32 wrap_u; + int32 wrap_v; + int32 detail; + float32 u0; + float32 v0; + float32 du; + float32 dv; + float32 animate_time; + int32 bitslice; + int32 delta_size; + int32 delta_offs; +}; +struct s_dpltexmap { + dpl_node dplnode; + + int32 *texels; + int32 u_size; + int32 v_size; + int32 bits_per_texel; + int32 alpha; +#ifdef REMOTE + int32 hwareSize; + int32 hwareOffs; + int32 bilinear; + void *cell; +#endif +}; +struct s_dplmtl { + dpl_node dplnode; + + struct s_dpltexture *texture; + struct s_dpltexture *environment; + int32 immunity; + struct s_dplramp *ramp; + float32 emissive [3]; + float32 ambient [3]; + float32 diffuse [3]; + float32 opacity [3]; + float32 specular [4]; + float32 dither; +#ifdef REMOTE + float surf_opacity; + float *specular_table; + int32 pxpl5_cntl_word; + float du, dv; + float alpha_c, alpha_r; + int32 alpha_texture; + int32 cull_frame; +#endif +}; +struct s_dplramp { + dpl_node dplnode; + + float32 color0 [3]; + float32 color1 [3]; + int32 cntl_word; +}; +struct s_dplinstance { + dpl_chain_node dplnode; + + dpl_ISECT_MODE intersectmode; + int32 visibility; + struct s_dplobject *object; + struct s_dpllod *forcelod; + struct s_dplmtl *f_material; + struct s_dplmtl *b_material; + int32 intersect_mask; + int32 wireframe; +#ifdef REMOTE + int32 frame_count; + int32 last_LOD_index; +#endif +}; +#define MAX_LODS_PER_OBJECT 16 + +struct s_dplobject { + dpl_node dplnode; + + dpl_superlist lod_list; + dpl_POINT lod_hot_spot; + float32 lod_ranges[MAX_LODS_PER_OBJECT]; + float32 lod_fade_range; + int32 invalid_lods; + int32 clone; +#ifdef REMOTE + int32 lod_count; + float32 bounds[2][4]; + dpl_POINT sphere_bounds; +#endif +}; +struct s_dpllod { + dpl_node dplnode; + + float32 bounds[2][4]; + struct s_dplobject *parent; + dpl_superlist geogroup_list; + float32 hot_spot[3]; +#ifdef REMOTE + dpl_POINT sphere_bounds; +#endif +}; +struct s_dplgeogroup { + dpl_node dplnode; + + float32 bounds[2][4]; + struct s_dpllod *parent; + int32 draw_mode; + dpl_superlist geometry_list; + struct s_dplmtl *f_material; + struct s_dplmtl *b_material; + float32 decal_offs; + int32 lock; +#ifdef REMOTE + dpl_POINT sphere_bounds; + int32 clean; +#endif +}; +struct s_dplgeometry { + dpl_node dplnode; + + dpl_GEO_TYPE geometry_type; + dpl_VERTEX_TYPE vertex_type; + int32 num_vertices; + struct s_dplgeogroup *parent; + dpl_CONNECTION *connections; + dpl_VERTEX *vertices; + float lineWidth, pointSize; + +#ifdef REMOTE + int32 variable_alpha; + int32 n_connections; + int32 n_vertices; + dpl_CONNECTION *connection_tail; + dpl_VERTEX *vertex_tail; + int32 packed; +#endif + +}; +#if 0 +struct s_dpl_status { + int32 ok; +} dpl_STATUS; +#endif + + +/* ****************************************** + + BEWARE ! ! ! ! ! + + FOR REASONS OF STORAGE AND APPLICATIONS EFFICIENCY, THE FOLLOWING + DATA TYPES ARE N O T SUPERSETS OF DPL_NODE + + BE CAREFUL DEALING WITH VERTICES + +*/ + +/* typedefs for tracing performance */ + +typedef struct s_dpl_version { + int32 host; + int32 major_version; + int32 minor_version; + int32 firmware_major_version; + int32 firmware_minor_version; + char detailed[256]; +} dpl_VERSION; + +/* ********************************************************** + a scene contains a list of root-node dcs's, a list of zones + and a list of views + */ + +typedef struct s_dplscene { + dpl_node dplnode; + + dpl_superlist zone_list; + dpl_superlist view_list; + dpl_superlist dcs_list; + dpl_superlist light_list; +} dpl_SCENE; + +typedef enum { + dpl_artic_matrix, + dpl_artic_singleX, + dpl_artic_singleY, + dpl_artic_singleZ, + dpl_artic_quaternion +} dpl_ARTICULATION; + +/* additional geometry types - keep small for switch optim */ + +#define vpx_geo_type_f_t_dam 16 +#define vpx_geo_type_sca 17 +#define vpx_geo_type_undamage 18 +#define vpx_geo_type_f_t_undam 19 +#define vpx_geo_type_damage_set 20 + +#define dpl_morph_vertices 0x1 +#define dpl_morph_normals 0x2 +#define dpl_morph_texcoords 0x4 +#define dpl_morph_colors 0x8 + + + +typedef void (*vfptr)(); + +extern void * +dpl_svtRead(char8 *, int32 bilinear ); + +extern void * +dpl_bilRead(char8 *); + +extern void * +dpl_glmRead(char8 *); + +extern void +dpl_explodeTexels ( dpl_TEXMAP *tm, + int32 *dest_texels, + uint8 *src_texels, + int32 n_texels, + int32 start, int32 bilinear ); + + +#define POLY_FBITS 12 +#define SPHERE_FBITS 24 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/DPL_VPX.H b/MUNGA_L4/libDPL/dpl/DPL_VPX.H new file mode 100644 index 0000000..e24bc62 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/DPL_VPX.H @@ -0,0 +1,220 @@ +#ifndef dpl_vpx_h +#define dpl_vpx_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define VPX 1 +#include + +extern void +dpl_SetDeferredDeletes ( int32 d ); + +extern void +dpl_SetTextureScroll ( dpl_TEXTURE *t, float u, float v, float du, float dv ); + +extern void +dpl_SetGeomScaleFactor ( float32 geomscale ); + +extern void +dpl_SetDCSTraversal ( dpl_DCS *d, int32 trav ); + +extern void dpl_SetDCSXAxis ( dpl_DCS *d, float32 sin, float32 cos ); +extern void dpl_SetDCSYAxis ( dpl_DCS *d, float32 sin, float32 cos ); +extern void dpl_SetDCSZAxis ( dpl_DCS *d, float32 sin, float32 cos ); + +extern void +dpl_SetDCSQuaternion ( dpl_DCS *d, float32 *quaternion_stuff, float32 *xlate ); + +extern void +dpl_FlushDCSArticulations ( dpl_DCS **d ); + +extern void +dpl_SetObjectAdditiveLODs ( dpl_OBJECT *o ); + +extern void +dpl_SetMaterialDitherZ ( dpl_MATERIAL *m, float32 dither ); + +extern void +dpl_install_sfx ( int32 sfx_code, + dpl_TEXTURE *t, + int32 bang_type, + float frag_size, + float frag_velocity, + float vertical_bias, + float switch_off, + float cook_r, + float cook_g, + float cook_b, + float variance, + float gravity, + float cool, + float opacity_cool, + int32 fragments, + int32 iterations, + int32 immunity ); + +extern void +dpl_SetMaterialFogImmunity ( dpl_MATERIAL *m, int32 immunity ); + +extern void dpl_SetDCSExplodeGeo ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSIgnoreGeo ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSInheritLmodel ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSForceEvalLmodel ( dpl_DCS *d, int32 on ); + +extern void dpl_Damagize ( dpl_GEOGROUP *, dpl_MATERIAL *); +extern void dpl_UnDamagize ( dpl_GEOGROUP * ); +extern void dpl_Punchize ( dpl_GEOGROUP * ); +extern void dpl_Geometrize ( dpl_GEOMETRY *, int32 triangle_code ); + +extern dpl_INSTANCE * +dpl_RapidSectPixel ( float32 xp, float32 yp, + float32 radius, + uint32 mask, + float32 *xi, float32 *yi, float32 *zi, + dpl_DCS **d, dpl_GEOGROUP **gg, dpl_GEOMETRY ** g); + +extern void +dpl_RandomTable ( char *table ); + +extern int32 * +dpl_TouchNode ( int32 *list, void *n ); + +extern int32 +dpl_FlushNodes ( int32 *list ); + +extern void +dpl_SetMinRetraces ( int32 retraces ); + +extern void +dpl_KillEffectAtDCS ( dpl_DCS *dcs ); + +void +dpl_KillParticlefxRange ( int32 min, int32 max ); + +extern void +dpl_RedrawScene ( void ); + +extern void +dpl_PutAppSpecific ( void *node, void *app_specific ); + +extern void* +dpl_GetAppSpecific ( void *node ); + +extern void +dpl_MorphObject ( dpl_OBJECT *dest, + dpl_OBJECT *start, + dpl_OBJECT *end, + float32 alpha, + int32 morph_mode ); +extern void +dpl_MorphGeometry ( dpl_GEOMETRY *dest, + dpl_GEOMETRY *start, + dpl_GEOMETRY *end, + float32 alpha, + int32 morph_mode ); +extern void +dpl_MorphMaterial ( dpl_MATERIAL *dest, + dpl_MATERIAL *start, + dpl_MATERIAL *end, + float32 alpha, + int32 morph_mode ); + +extern void +dpl_TimedMorphObject ( dpl_OBJECT *dest, + dpl_OBJECT *start, + dpl_OBJECT *end, + float32 time, + int32 morph_mode, + float32 a, + float32 b, + float32 c, + float32 d ); +extern void +dpl_TimedMorphMaterial ( dpl_MATERIAL *dest, + dpl_MATERIAL *start, + dpl_MATERIAL *end, + float32 time, + int32 morph_mode, + float32 a, + float32 b, + float32 c, + float32 d ); + + +extern void dpl_SFXTexels2D ( dpl_TEXMAP *tm, + uint32 *texels ); + +extern void dpl_FakeTextureSize ( dpl_TEXTURE *t, int32 delta_size, int32 delta_offs ); + +extern void dpl_SetDCSLightingMask ( dpl_DCS *d, int32 mask ); +extern int32 dpl_GetDCSLightingMask ( dpl_DCS *d ); + +extern void dpl_SetLightLightingMask ( dpl_LIGHT *d, int32 mask ); +extern int32 dpl_GetLightLightingMask ( dpl_LIGHT *d ); + +extern void dpl_SetDCSNearField ( dpl_DCS *d, int32 on ); + +extern int32 +dpl_FreeMemory ( void ); + +extern int +dpl_bslReplace ( char8 *name, dpl_TEXTURE *tex ); + +extern void +dpl_tgaReplace(char8 *file, dpl_TEXTURE *tex ); + +extern void +dpl_DisableSyncOnCreate ( void ); + +extern void +dpl_EnableSyncOnCreate ( void ); + +extern void +dpl_SetDCSBound(dpl_DCS *d, float *minimax ); + +extern float32 +dpl_GetDCSBound(dpl_DCS *d ); + +extern void +dpl_PerfStats ( void ); + +extern void +dpl_SetLodStress ( float32 s ); + +extern +void dpl_SetGeogroupDrawLast(dpl_GEOGROUP *gg, int32 last_on); + +extern +int32 dpl_GetGeogroupDrawLast(dpl_GEOGROUP * gg); + +extern +void dpl_GetObjectBounds( dpl_OBJECT *o, float32 *b ); + +int32 +dpl_GetGeometryNumConnections(dpl_GEOMETRY *g ); + +void +dpl_GetGeometryConnections ( dpl_GEOMETRY *g, + int32 *v, + int32 offset, + int32 n ); + + +extern void +dpl_SetGeometryShadowVolume ( dpl_GEOMETRY *g ); + +extern void +dpl_SetGeometryLightVolume ( dpl_GEOMETRY *g, int imm ); + +extern void +dpl_CleanupGeogroup ( dpl_GEOGROUP *gg, int renorm_facets ); + +extern void +dpl_ReInit(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/MATRIX.H b/MUNGA_L4/libDPL/dpl/MATRIX.H new file mode 100644 index 0000000..80b53a1 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/MATRIX.H @@ -0,0 +1,47 @@ +#ifndef matrix_h +#define matrix_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpl.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Introduces all the datatypes and functions + used by the dpl interface + + History : Rev 1.0, 18 / 06 / 1994 + +**************************** */ + +#include +#include +#include + +extern void dpl_SetAngleMode( int degrees ); +extern void dpl_IdMatrix ( dpl_MATRIX m ); +extern void dpl_Translate ( dpl_MATRIX m, float32 dx, float32 dy, float32 dz ); +extern void dpl_Rotate ( dpl_MATRIX m, float32 angle, int32 axis ); +extern void dpl_Scale ( dpl_MATRIX m, float32 x, float32 y, float32 z ); +extern void dpl_Concat ( dpl_MATRIX m, dpl_MATRIX a, dpl_MATRIX b ); +extern void dpl_Invert ( dpl_MATRIX inverse, dpl_MATRIX mat ); +extern void dpl_XformPoint ( dpl_POINT q, dpl_POINT p, dpl_MATRIX m ); + +extern void dpl_IdMatrixDCS ( dpl_DCS *d ); +extern void dpl_TranslateDCS ( dpl_DCS *d, float32 dx, float32 dy, float32 dz ); +extern void dpl_RotateDCS ( dpl_DCS *d, float32 angle, int32 axis ); +extern void dpl_ScaleDCS ( dpl_DCS *d, float32 x, float32 y, float32 z ); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/dpl.h b/MUNGA_L4/libDPL/dpl/dpl.h new file mode 100644 index 0000000..319baa8 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/dpl.h @@ -0,0 +1,590 @@ +/***************************************************************************** + + PROJECT: + dPL + + FILE: + dpl.h + + CONTENTS: + Public include with function prototypes. + +*****************************************************************************/ + +#ifndef _DPL_H +#define _DPL_H + +/* include type definitions */ +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* Create Elements */ + +extern dpl_ZONE *dpl_NewZone(void); +extern dpl_VIEW *dpl_NewView(void); +extern dpl_DCS *dpl_NewDCS(void); +extern dpl_INSTANCE *dpl_NewInstance(void); +extern dpl_LIGHT *dpl_NewLight(void); +extern dpl_TEXTURE *dpl_NewTexture(void); +extern dpl_TEXMAP *dpl_NewTexmap(void); +extern dpl_MATERIAL *dpl_NewMaterial(void); +extern dpl_OBJECT *dpl_NewObject(void); +extern dpl_LOD *dpl_NewLod(void); +extern dpl_GEOGROUP *dpl_NewGeogroup(void); +extern dpl_GEOMETRY *dpl_NewGeometry(void); +extern dpl_RAMP *dpl_NewRamp(void); + +/* Connect Structure */ + +extern void dpl_AddViewToScene(dpl_VIEW *v); +extern void dpl_AddDCSToScene(dpl_DCS *d); +extern void dpl_AddDCSToDCS(dpl_DCS *parent, dpl_DCS *child); +extern void dpl_AddInstanceToDCS(dpl_DCS *d, dpl_INSTANCE *i); +extern void dpl_AddLodToObject(dpl_OBJECT *o, dpl_LOD *l); +extern void dpl_AddGeogroupToLod(dpl_LOD *l, dpl_GEOGROUP *gg); +extern void dpl_AddGeometryToGeogroup(dpl_GEOGROUP *gg, dpl_GEOMETRY *g); + +/* Querry Structure */ + +extern dpl_VIEW *dpl_GetSceneView(int32 n); +extern dpl_DCS *dpl_GetSceneDCS(int32 n); +extern dpl_DCS *dpl_GetDCSChildDCS(dpl_DCS *parent, int32 n); +extern dpl_DCS *dpl_GetDCSParentDCS(dpl_DCS *child); +extern dpl_INSTANCE *dpl_GetDCSInstance(dpl_DCS *d, int32 n); +extern dpl_LOD *dpl_GetObjectLod(dpl_OBJECT *o, int32 n); +extern dpl_GEOGROUP *dpl_GetLodGeogroup(dpl_LOD *l, int32 n); +extern dpl_GEOMETRY *dpl_GetGeogroupGeometry(dpl_GEOGROUP *gg, int32 n); + +/* Disonnect Structure */ + +extern void dpl_RemoveViewFromScene(dpl_VIEW *v); +extern void dpl_RemoveDCSFromScene(dpl_DCS *d); +extern void dpl_RemoveDCSFromDCS(dpl_DCS *parent, dpl_DCS *child); +extern void dpl_RemoveInstanceFromDCS(dpl_DCS *d, dpl_INSTANCE *i); +extern void dpl_RemoveLodFromObject(dpl_OBJECT *o, dpl_LOD *lod); +extern void dpl_RemoveGeogroupFromLod(dpl_LOD *l, dpl_GEOGROUP *gg); +extern void dpl_RemoveGeometryFromGeogroup(dpl_GEOGROUP *gg, dpl_GEOMETRY *g); + +/* Delete Elements */ + +extern void dpl_DeleteZone(dpl_ZONE *z); +extern void dpl_DeleteView(dpl_VIEW *v); +extern void dpl_DeleteDCS(dpl_DCS *d); +extern void dpl_DeleteInstance(dpl_INSTANCE *i); +extern void dpl_DeleteLight(dpl_LIGHT *l); +extern void dpl_DeleteTexture(dpl_TEXTURE *t); +extern void dpl_DeleteTexmap(dpl_TEXMAP *tm); +extern void dpl_DeleteMaterial(dpl_MATERIAL *m); +extern void dpl_DeleteObject(dpl_OBJECT *o); +extern void dpl_DeleteLod(dpl_LOD *l); +extern void dpl_DeleteGeogroup(dpl_GEOGROUP *gg); +extern void dpl_DeleteGeometry(dpl_GEOMETRY *g); +extern void dpl_DeleteRamp(dpl_RAMP *); + +/* Scene Coherence */ + +extern void dpl_FlushZone(dpl_ZONE *z); +extern void dpl_FlushView(dpl_VIEW *v); +extern void dpl_FlushDCS(dpl_DCS *d); +extern void dpl_FlushInstance(dpl_INSTANCE *i); +extern void dpl_FlushLight(dpl_LIGHT *l); +extern void dpl_FlushTexture(dpl_TEXTURE *t); +extern void dpl_FlushTexmap(dpl_TEXMAP *tm); +extern void dpl_FlushMaterial(dpl_MATERIAL *m); +extern void dpl_FlushObject(dpl_OBJECT *o); +extern void dpl_FlushLod(dpl_LOD *l); +extern void dpl_FlushGeogroup(dpl_GEOGROUP *gg); +extern void dpl_FlushGeometry(dpl_GEOMETRY *g); +extern void dpl_FlushRamp(dpl_RAMP *); + +/* Modal Render Changes */ + +/* Render modes may be set and querried using these functions, this enables + modes like; wireframe rendering, single buffered rendering and the + graphical display of performance information. */ + +extern void dpl_SetRenderProperty(dpl_RENDER_PROP prp, dpl_RENDER_VALUE val, + void *data); +extern dpl_RENDER_VALUE dpl_GetRenderProperty(dpl_RENDER_PROP prp, + void *data); +extern void dpl_SetPipeWindow(int32 pipe, + int32 x0, int32 y0, int32 x1, int32 y1); +extern void dpl_GetPipeWindow(int32 pipe, + int32 *x0, int32 *y0, int32 *x1, int32 *y1); +extern void dpl_SetWindowName(int32 pipe, char8 *name); +extern char8 *dpl_GetWindowName(int32 pipe); +extern void dpl_SetDesktopStereo(int32 pipe, int32 mode); +extern int32 dpl_GetDesktopStereo(int32 pipe); +extern void dpl_SetFrameRate(float32 rate); +extern float32 dpl_GetFrameRate(void); + +/* Direct Render Calls */ + +/* These calls render the scene to all views and allow the application to + lock and therefore synch to the frame rate. In multi processor SGI + implementations this will lock to the cull rather than the render + process. */ + +extern void dpl_DrawScene(void); +extern void dpl_WaitSceneComplete(void); +extern int32 dpl_DrawSceneComplete(void); + +/* DCS */ + +/* Positional information may be set in a DCS in the form of a 4x4 matrix. */ + +extern void dpl_SetDCSMatrix(dpl_DCS *d, float32 *m); +extern float32 *dpl_GetDCSMatrix(dpl_DCS *d); + +/* DCS nodes may be billboarded around any set of axes. This makes them + automatically orient towards the view reguardless of their position + relative to the viewpoint. Multiple axes may be set by adding or bitwise + oring the axis definitions together. */ + +extern void dpl_SetDCSReorientAxes(dpl_DCS *d, dpl_REORIENT_AXES a); +extern dpl_REORIENT_AXES dpl_GetDCSReorientAxes(dpl_DCS *d); + +/* For switching and lighting model purposes a DCS has an associated zone + which it occupies. */ + +extern void dpl_SetDCSZone(dpl_DCS *d, dpl_ZONE *z); +extern dpl_ZONE *dpl_GetDCSZone(dpl_DCS *d); + +/* Zone */ + +/* Zones provide a means of controlling geometry switching on a per view + basis and may be used to associate groups of light sources with + particular DCS hierarchies. */ + +/* Sets rendering of the zone on for all views */ +extern void dpl_SetZoneAllViewsOn(dpl_ZONE *z); + +/* Sets rendering of the zone off for all views */ +extern void dpl_SetZoneAllViewsOff(dpl_ZONE *z); + +/* Sets rendering of the zone for the specified view on */ +extern void dpl_SetZoneViewOn(dpl_ZONE *z, dpl_VIEW *v); + +/* Sets rendering of the zone for the specified view off */ +extern void dpl_SetZoneViewOff(dpl_ZONE *z, dpl_VIEW *v); + +/* gets the rendering status of the zone in the view */ +extern int32 dpl_GetZoneView(dpl_ZONE *z, dpl_VIEW *v); + +/* sets all 32 views for this zone based on a bitmask*/ +extern void dpl_SetZoneBitmask(dpl_ZONE *z, uint32 m); + +/* gets a bitmask of all 32 views for this zone */ +extern uint32 dpl_GetZoneBitmask(dpl_ZONE *z); + +/* Instance */ + +/* Instances provide a means of copying an object without explicitly + recreating it in the database. All instances therefore reference an + object, any object may be multiply referenced by several instances. + Material overrides may be applied to all geometry below an instance. + Any material override applied to an instance will change the material + of those geosets which have no lock applied to the material or geoset. */ + +extern void dpl_SetInstanceObject(dpl_INSTANCE *, dpl_OBJECT *); + +extern dpl_OBJECT *dpl_GetInstanceObject(dpl_INSTANCE *); + +extern void dpl_SetInstanceForceLOD(dpl_INSTANCE *i, dpl_LOD *l); + +extern dpl_LOD *dpl_GetInstanceForceLOD(dpl_INSTANCE *i); + +extern void dpl_SetInstanceVisibility(dpl_INSTANCE *i, int32 v); + +extern int32 dpl_GetInstanceVisibility(dpl_INSTANCE *i); + +extern void dpl_SetInstanceIntersect(dpl_INSTANCE *i, dpl_ISECT_MODE m); + +extern dpl_ISECT_MODE dpl_GetInstanceIntersect(dpl_INSTANCE *i); + +extern void dpl_SetInstanceSectMask(dpl_INSTANCE *i, uint32 mask); + +extern uint32 dpl_GetInstanceSectMask(dpl_INSTANCE *i); + + +/* Object */ + +/* Objects contain lod nodes which switch according to ranging information + associated wit the object */ + +extern void dpl_SetObjectLodRange(dpl_OBJECT *o, + int32 transition, float32 range); + +extern void dpl_InvalidateObjectLodRanges(dpl_OBJECT *o); + +extern float32 dpl_GetObjectLodRange(dpl_OBJECT *o, int32 transition); + +extern void dpl_SetObjectLodHotSpot(dpl_OBJECT *o, + float32 x, float32 y, float32 z); + +extern void dpl_GetObjectLodHotSpot(dpl_OBJECT *o, + float32 *x, float32 *y, float32 *z); + +extern void dpl_SetObjectLodFadeRange(dpl_OBJECT *o, float32 range); + +extern float32 dpl_GetObjectLodFadeRange(dpl_OBJECT *o); + +extern void dpl_SetInstanceFrontMaterial(dpl_INSTANCE *i, dpl_MATERIAL *m); +extern void dpl_SetInstanceBackMaterial(dpl_INSTANCE *i, dpl_MATERIAL *m); +extern dpl_MATERIAL *dpl_GetInstanceFrontMaterial(dpl_INSTANCE *i); +extern dpl_MATERIAL *dpl_GetInstanceBackMaterial(dpl_INSTANCE *i); + +/* Light */ + +extern void dpl_SetLightDCS(dpl_LIGHT *, dpl_DCS *); +extern dpl_DCS *dpl_GetLightDCS(dpl_LIGHT *); +extern void dpl_SetLightType(dpl_LIGHT *l, dpl_LIGHT_TYPE t); +extern dpl_LIGHT_TYPE dpl_GetLightType(dpl_LIGHT *l); +extern void dpl_SetLightColor(dpl_LIGHT *l, float32 r, float32 g, float32 b); +extern void dpl_GetLightColor(dpl_LIGHT *l, + float32 *r, float32 *g, float32 *b); +extern void dpl_SetLightRadii(dpl_LIGHT *l, float32 r0, float32 r1); +extern void dpl_GetLightRadii(dpl_LIGHT *l, float32 *r0,float32 *r1); +extern void dpl_SetLightUmbra(dpl_LIGHT *l, float32 exp, float32 th); +extern void dpl_GetLightUmbra(dpl_LIGHT *l, float32 *exp, float32 *th); + +/* View */ + +extern void dpl_ViewShare(dpl_VIEW *master, dpl_VIEW *slave); +extern void dpl_SetViewDCS(dpl_VIEW *v, dpl_DCS *d); +extern dpl_DCS *dpl_GetViewDCS(dpl_VIEW *v); +extern void dpl_SetViewClipPlanes(dpl_VIEW *v, float32 hither, float32 yon); +extern void dpl_GetViewClipPlanes(dpl_VIEW *v, float32 *hither, float32 *yon); +extern void dpl_SetViewBackGround(dpl_VIEW *v, + float32 r, float32 g, float32 b); +extern void dpl_GetViewBackGround(dpl_VIEW *v, + float32 *r, float32 *g, float32 *b); +extern void dpl_SetViewFog(dpl_VIEW *v, dpl_FOG_TYPE enable, + float32 r, float32 g, float32 b, float32 neer, float32 phar); +extern void dpl_GetViewFog(dpl_VIEW *v, dpl_FOG_TYPE *enable, + float32 *r, float32 *g, float32 *b, float32 *neer, float32 *phar); +extern void dpl_SetViewPipe(dpl_VIEW *v, int32 pipe); +extern int32 dpl_GetViewPipe(dpl_VIEW *v); +extern void dpl_SetViewPort(dpl_VIEW *v, + float32 x0, float32 y0, float32 x1, float32 y1); +extern void dpl_GetViewPort(dpl_VIEW *v, + float32 *x0, float32 *y0, float32 *x1, float32 *y1); +extern void dpl_SetViewProjection(dpl_VIEW *v, float32 x0, float32 y0, + float32 x1, float32 y1, float32 zeye); +extern void dpl_GetViewProjection(dpl_VIEW *v, float32 *x0, float32 *y0, + float32 *x1, float32 *y1, float32 *zeye); +extern void dpl_SetViewNumber(dpl_VIEW *v, int32 n); +extern int32 dpl_GetViewNumber(dpl_VIEW *v); +extern void dpl_SetViewZClearOnly(dpl_VIEW *v, int32 mode); +extern int32 dpl_GetViewZClearOnly(dpl_VIEW *v); + +/* Material */ + +/* Various illumination properties of a material may be set independently. */ + +extern void dpl_SetMaterialAmbient(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialAmbient(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialEmissive(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialEmissive(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialDiffuse(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialDiffuse(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialSpecular(dpl_MATERIAL *m, + float32 r, float32 g, float32 b, float32 shininess); + +extern void dpl_GetMaterialSpecular(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b, float32 *shininess); + +extern void dpl_SetMaterialOpacity(dpl_MATERIAL *m, + float32 r, float32 g, float32 b); + +extern void dpl_GetMaterialOpacity(dpl_MATERIAL *m, + float32 *r, float32 *g, float32 *b); + +extern void dpl_SetMaterialTexture(dpl_MATERIAL *m, dpl_TEXTURE *t); + +extern dpl_TEXTURE *dpl_GetMaterialTexture(dpl_MATERIAL *m); + +extern void dpl_SetMaterialEnvironment(dpl_MATERIAL *m, dpl_TEXTURE *t); + +extern dpl_TEXTURE *dpl_GetMaterialEnvironment(dpl_MATERIAL *m); + +extern void dpl_SetMaterialRamp(dpl_MATERIAL *, dpl_RAMP *); + +extern dpl_RAMP *dpl_GetMaterialRamp(dpl_MATERIAL *); + +/* Texture */ +/* Texture manipulation commands allow control over the various modes + associated with applying texmaps to polygons. Particular importance is + attached to the dpl_FlushTexture() function listed in a previous section. + Potentially, many of the mode changes associated with these commands + require a prohibitive ammount of time to be applied on some systems. + With write-back cacheing it is likely that applications will have to + flush a texture on most platforms before any modifications take effect, + this should be done as infrequently as possible, prefferably after all + modifications have been requested. Functions below allow various + properties to be set to particular parameter values. Hopefully this leads + to a flexible and extensible interface. For a list of properties see the + enumerated type definitions earlier in this document. */ + +extern void dpl_SetTextureProperty(dpl_TEXTURE *t, + dpl_TEX_PROP prp, dpl_TEX_VALUE val, void *data); + +extern dpl_TEX_VALUE dpl_GetTextureProperty(dpl_TEXTURE *t, + dpl_TEX_PROP prp, void *data); + +extern void dpl_SetTextureTexmap(dpl_TEXTURE *t, dpl_TEXMAP *tm); + +extern dpl_TEXMAP *dpl_GetTextureTexmap(dpl_TEXTURE *t); + +/* Texmap */ +/* These functions allow the creation of texmaps both from image files on + disk and from image data in memory. Using the high level loading + function eliminates the need to set the texmap dimensions. + Finally it is important to remember that this may be information used + to create a texture and not actual texture itself (I think this applies + to all target platforms & others may make a copy), so the texel memory + should be freed after the call. */ + +extern void dpl_SetTexmapEdgeSize(dpl_TEXMAP *, int32, int32); + +extern void dpl_GetTexmapEdgeSize(dpl_TEXMAP *tm, int32 *u, int32 *v); + +extern void dpl_SetTexmapTexelSize(dpl_TEXMAP *, int32); + +extern int32 dpl_GetTexmapTexelSize(dpl_TEXMAP *tm); + +extern void dpl_UpdateTexmapTexels2D(dpl_TEXMAP *, uint8 *, int32, int32); + +extern void dpl_GetTexmapTexels2D(dpl_TEXMAP *, uint8 *, int32, int32); + +/* throws away the texmap and saves some resources */ +extern void dpl_InvalidateTexels(dpl_TEXMAP *tm); + +/* Geogroup */ + +/* A material lock may be placed at the level of the geogroup which will + prevent material chain operations or override commands affecting its + material. */ + +/* set a geogroups front material */ +extern void dpl_SetGeogroupFrontMaterial(dpl_GEOGROUP *g, dpl_MATERIAL *m); + +/* set a geogroups back material */ +extern void dpl_SetGeogroupBackMaterial(dpl_GEOGROUP *g, dpl_MATERIAL *m); + +/* get a geogroups front material */ +extern dpl_MATERIAL *dpl_GetGeogroupFrontMaterial(dpl_GEOGROUP *g); + +/* get a geogroups back material */ +extern dpl_MATERIAL *dpl_GetGeogroupBackMaterial(dpl_GEOGROUP *g); + +/* lock a geogroups material */ +extern void dpl_SetGeogroupMaterialLockOn(dpl_GEOGROUP *m); + +/* unlock a geogroups material */ +extern void dpl_SetGeogroupMaterialLockOff(dpl_GEOGROUP *m); + +/* find out if a geogroups material is locked */ +extern int32 dpl_GetGeogroupMaterialLock(dpl_GEOGROUP *m); + +/* set decal displace value */ +void dpl_SetGeogroupDecalDisplace(dpl_GEOGROUP *, int32); + +/* returns decal displace on */ +int32 dpl_GetGeogroupDecalDisplace(dpl_GEOGROUP *); + +/* set wireframe TRUE or filled FALSE */ +void dpl_SetGeogroupWireframe(dpl_GEOGROUP *, int32); + +/* return wireframe TRUE or filled FALSE */ +int32 dpl_GetGeogroupWireframe(dpl_GEOGROUP *); + + +/* Geometry */ + +/* Functions are provided to create renderable database geometry from arrays + of co-ordinate information and connection lists. This is done by + specifying which type of geometry is required first. Next the vertex type + of the geometry is specified, then number of vertices. + Once this is done the vertices are passed vertice values may be set + in blocks of arbitrary sizes. + This information may be followed by an edge connection list or text + string or nothing depending on the type of geometry. Finally the geometry + is flushed to greate the requested primitives. Subsequent reads and + writes of this geometry information are possible. Of particular + importance to the creation of the geometric primitives is the type of + vertex being sent to the renderer. This determines how the primitive is + drawn in the scene, (cooked, illuminated, textured), and prepares the dPL + creation functions to expect vertex information in a particular form. + Vertex properties which may be set using the type specification function + above are enumerated as dpl_VERTEX_TYPE. These types may be added or + bitwise OR'd together to prepare dPL to receive the information. When the + contiguous block of vertices is passed the dPL uses the vertex type as a + guide to the size of each vertex and what information it holds. */ + + +/* determine the type of geometry to be held */ +extern void dpl_SetGeometryGeoType(dpl_GEOMETRY *g, dpl_GEO_TYPE gt); + +/* read the type of geometry held */ +extern dpl_GEO_TYPE dpl_GetGeometryGeoType(dpl_GEOMETRY *g); + +/* sets vertex type prior to creation, also determines space */ +extern void dpl_SetGeometryVertexType(dpl_GEOMETRY *g, dpl_VERTEX_TYPE vt); + +/* gets vertex type */ +extern dpl_VERTEX_TYPE dpl_GetGeometryVertexType(dpl_GEOMETRY *g); + +/* sets the number of vertices in the geometry */ +extern void dpl_SetGeometryNumVertices(dpl_GEOMETRY *g, int32 n); + +/* obtains the vertex count for geometry */ +extern int32 dpl_GetGeometryNumVertices(dpl_GEOMETRY *g); + +/* set values in n vertices starting from offset */ +extern void dpl_UpdateGeometryVertices(dpl_GEOMETRY *g, + float32 *v, int32 offset, int32 n); + +/* sends an edge connection list for some forms of geometry */ +extern void dpl_AddGeometryConnections(dpl_GEOMETRY *g, int32 *c, + int32 numpolys, int32 polysize); + +/* sends a strip connection list. */ +extern void dpl_AddGeometryStrip(dpl_GEOMETRY *g, int32 *c, + int32 numpolys, int32 polysize); + +/* sends a text string for display as text by geometry */ +extern void dpl_SetGeometryText(dpl_GEOMETRY *g, char8 *text); + +/* obtains n geometry vertices starting at offset */ +extern void dpl_GetGeometryVertices(dpl_GEOMETRY *g, + float32 *v, int32 offset, int32 n); + +/* gets the text string being displayed by text geometry */ +extern char8 *dpl_GetGeometryText(dpl_GEOMETRY *g); + +/* optimises and freezes geometry */ +extern void dpl_OptimiseGeometry(dpl_GEOMETRY *); + +/* set geometry subdivisions */ +extern void dpl_SetGeometryDice(dpl_GEOMETRY *, uint16, uint16); + +/* querry geometry subdivisions */ +extern void dpl_GetGeometryDice(dpl_GEOMETRY *, uint16 *, uint16 *); + +/* set the texture for textured font */ +void dpl_SetFontTexture(dpl_TEXTURE *); + +/* get the texture for textured font */ +dpl_TEXTURE *dpl_GetFontTexture(void); + +/* Setup & Cleanup */ + +extern int32 dpl_Init(int32 argc, char8 **argv); + +extern void dpl_Config(void); + +extern void dpl_Exit(int32 exit_code); + +/* Reporting Control */ + +extern void dpl_SetWarningLevel(dpl_WARN_LEVEL w); + +extern int32 dpl_GetWarningLevel(void); + +extern char8 *dpl_Version(void); + +/* these functions return types with defined contents */ + +extern dpl_STATISTICS *dpl_Statistics(void); + +extern dpl_STATUS *dpl_Status(void); + +dpl_CAPABILITY *dpl_GetCapability(void); + +/* Frame Store Query */ +/* These functions obtain a packed array of 8 bit red, green, blue & alpha + colour information from the currently displayed frame store associated + with a dpl_VIEW. A single pixel from the image is stored in each + unsigned integer in the hexadecimal form 0xRRGGBBAA, as can be seen the + high order 8 bits contain red, then green is stored then blue followed + by alpha information in the lowest order 8 bits. What is written to the + alpha bits is not specified at this stage but these may ultimately yield + useful information. Pixels will be written left to right(internal fast + loop) bottom to top(outside slow loop). The first function will return a + malloc'd block of packed information and returns it's size based on the + information in the dpl_VIEW structure, the application should free this + block when done with the image. The second function expects to be passed + the memory address of a contiguous block of memory where the write is to + be made and the dimensions of the required image, specifying the start + position and image size allows a portion of the frame store to be copied + to memory. There should be enough information allocated in the memory + block for an image of the requested size to be written. Values for display + portions incompatible with the dpl_VIEW information will produce undefined + results. */ + +extern uint32 *dpl_GetFrameStore(dpl_VIEW *v, int32 *x, int32 *y); + +extern void dpl_ReadFrameStore(dpl_VIEW *v, uint32 *pixels, + int32 startx, int32 starty, int32 sizex, int32 sizey); + +/* Intersection Functions */ +/* Intersection functions are used to determine the point of intersection + between a vector and the database contents. Vectors may be specified in + world co-ordinates or as a position on the viewport of a dpl_VIEW. + Depending upon the intersect mode set for the database instance + intersected, some of the fields may not return valid values. */ + +extern dpl_INSTANCE *dpl_SectVector(float32, float32, float32, + float32, float32, float32, uint32, + float32 *, float32 *, float32 *, + dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); +extern dpl_INSTANCE *dpl_SectPixel(dpl_VIEW *, float32, float32, uint32, + float32 *, float32 *, float32 *, + dpl_DCS **, dpl_GEOGROUP **, dpl_GEOMETRY **); + +/* Special Effects */ + +/* Provision is made for special effects to be requested by an application. + The idea here is that common rendering effects which might eat bandwidth + to the renderer or prove difficult to code using dPL can be implemented + in the renderer and initiated with a single high level dPL request then + left to look pretty: fire and forget rendering effects. Only explosions + have been considered so far but this interface may be extended as new + requirements arise. */ + +/* request an effect of the desired type and here's the type specific data + for the effect */ + +extern void *dpl_Effect(dpl_EFFECT_TYPE e, dpl_DCS *d, void *data); + +/* ramp stuff */ + +extern void dpl_SetRampComponents(dpl_RAMP *ramp, + float32 r0, float32 g0, float32 b0, + float32 r1, float32 g1, float32 b1); + +extern void dpl_GetRampComponents(dpl_RAMP *ramp, + float32 *r0, float32 *g0, float32 *b0, + float32 *r1, float32 *g1, float32 *b1); + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MUNGA_L4/libDPL/dpl/dpltypes.h b/MUNGA_L4/libDPL/dpl/dpltypes.h new file mode 100644 index 0000000..919aaa0 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/dpltypes.h @@ -0,0 +1,387 @@ +/***************************************************************************** + + PROJECT: + dPL + + FILE: + dpltypes.h + + CONTENTS: + Public type definitions for the dPL library. + +*****************************************************************************/ + +#ifndef _DPL_TYPES_H +#define _DPL_TYPES_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* dpl_TYPE definitions are used as tokenised identifiers for the various + coarse dPL database elements. */ + +typedef enum dpl_TYPE +{ + dpl_type_error, + dpl_type_scene, + dpl_type_zones, + dpl_type_view, + dpl_type_instance, + dpl_type_dcs, + dpl_type_light, + dpl_type_object, + dpl_type_lod, + dpl_type_geogroup, + dpl_type_geometry, + dpl_type_material, + dpl_type_texture, + dpl_type_texmap, + dpl_type_ramp +} dpl_TYPE; + +/* dpl_LIGHT_TYPE definitions are light type tokens identifying the behaviour + of a particular dPL light. */ + +typedef enum dpl_LIGHT_TYPE +{ + dpl_light_type_error, + dpl_light_type_disable, + dpl_light_type_ambient, + dpl_light_type_directional, + dpl_light_type_point, + dpl_light_type_conical +} dpl_LIGHT_TYPE; + +/* dpl_GEO_TYPE indicates which form of data a geometry database element + represents. */ + +typedef enum dpl_GEO_TYPE +{ + dpl_geo_type_error, + dpl_geo_type_empty, + dpl_geo_type_tristrip, + dpl_geo_type_polystrip, + dpl_geo_type_polygon, + dpl_geo_type_pmesh, + dpl_geo_type_string, + dpl_geo_type_lines, + dpl_geo_type_polyline, + dpl_geo_type_polypoints, + dpl_geo_type_spheres +} dpl_GEO_TYPE; + +/* dpl_ISECT_MODE is used to determine how detailed an intersection + calculation is to be performed by the renderer for a given instance, + providing a means of controlling the amount of time taken to obtain + intersection information. */ + +typedef enum dpl_ISECT_MODE +{ + dpl_isect_mode_error, + dpl_isect_mode_obj, + dpl_isect_mode_geogroup, + dpl_isect_mode_geometry +} dpl_ISECT_MODE; + +/* dpl_MORPH_MODE selects a mode of interpolation between the low level + geometry. */ + +typedef enum dpl_MORPH_MODE +{ + dpl_morph_mode_error, + dpl_morph_mode_simple, + dpl_morph_mode_blend +} dpl_MORPH_MODE; + +/* dpl_TEX_PROP are the various properties of a texture which may be + manipulated to control a texmaps application over polygons. */ + +typedef enum dpl_TEX_PROP +{ + dpl_tex_prop_error, + dpl_tex_prop_spheremap, + dpl_tex_prop_wrap, + dpl_tex_prop_wrapu, + dpl_tex_prop_wrapv, + dpl_tex_prop_minfilter, + dpl_tex_prop_magfilter, + dpl_tex_prop_alpha, + dpl_tex_prop_detail, + dpl_tex_prop_reduce, + dpl_tex_prop_bitslice +} dpl_TEX_PROP; + +/* dpl_TEX_VALUE are the values which may be assigned to the texture property + fields in a texture elements. */ + +typedef enum dpl_TEX_VALUE +{ + dpl_tex_value_error, + dpl_tex_value_on, + dpl_tex_value_off, + dpl_tex_value_repeat, + dpl_tex_value_clamp, + dpl_tex_value_select, + dpl_tex_value_blend, + dpl_tex_value_cut, + dpl_tex_value_blendcut, + dpl_tex_value_point, + dpl_tex_value_bilinear, + dpl_tex_value_trilinear, + dpl_tex_value_bicubic, + dpl_tex_value_sharpen, + dpl_tex_value_mipmap_point, + dpl_tex_value_mipmap_linear, + dpl_tex_value_mipmap_bilinear, + dpl_tex_value_mipmap_trilinear, + dpl_tex_value_mipmap_quadlinear, + dpl_tex_value_slice_mode0, + dpl_tex_value_slice_mode1, + dpl_tex_value_slice_mode2, + dpl_tex_value_slice_mode3, + dpl_tex_value_slice_mode4, + dpl_tex_value_slice_mode5, + dpl_tex_value_slice_mode6, + dpl_tex_value_slice_mode7, + dpl_tex_value_slice_mode8 +} dpl_TEX_VALUE; + +/* dpl_RENDER_PROP specifies global rendering properties which may be set to + affect output in all views. */ + +typedef enum dpl_RENDER_PROP +{ + dpl_render_prop_error, + dpl_render_prop_wireframe, + dpl_render_prop_report, + dpl_render_prop_singlebuffer, + dpl_render_prop_framerate, + dpl_render_prop_antialias, + dpl_render_prop_windowed, + dpl_render_prop_textured, + dpl_render_prop_LODscale, + dpl_render_prop_phase +} dpl_RENDER_PROP; + +/* dpl_RENDER_VALUE defines the values which may be used to set the render + properties. */ + +typedef enum dpl_RENDER_VALUE +{ + dpl_render_value_error, + dpl_render_value_on, + dpl_render_value_off, + dpl_render_value_increase, + dpl_render_value_decrease, + dpl_render_value_lock, + dpl_render_value_float, + dpl_render_value_free, + dpl_render_value_limit +} dpl_RENDER_VALUE; + +/* dpl_VERTEX_TYPE definitions are light type tokens identifying the behaviour + of a particular dPL light. */ + +typedef enum dpl_VERTEX_TYPE +{ + dpl_vertex_type_error = 0x00, + dpl_vertex_coord = 0x01, + dpl_vertex_normal = 0x02, + dpl_vertex_rgba = 0x04, + dpl_vertex_luminance = 0x08, + dpl_vertex_texture2D = 0x10, + dpl_vertex_texture3D = 0x20, + dpl_vertex_radius = 0x40 +} dpl_VERTEX_TYPE; + +/* dpl_REORIENT_AXES may be combined with an OR operation to switch billboard + axes at DCS nodes. */ + +typedef enum dpl_REORIENT_AXES +{ + dpl_reorient_axes_none = 0x00, + dpl_reorient_axes_x = 0x01, + dpl_reorient_axes_y = 0x02, + dpl_reorient_axes_z = 0x04 +} dpl_REORIENT_AXES; + +/* dpl_EFFECT_TYPE definitions are used in high level requests for specific + types of effect from the dpl renderer. */ + +typedef enum dpl_EFFECT_TYPE +{ + dpl_effect_type_explosion, + dpl_effect_type_particlestart, + dpl_effect_type_particlestop, + dpl_effect_type_particle +} dpl_EFFECT_TYPE; + +/* dpl_WARN_LEVEL defines the various warning levels avaliable from the + renderer */ + +typedef enum dpl_WARN_LEVEL +{ + dpl_warn_fatal, + dpl_warn_warn, + dpl_warn_notice, + dpl_warn_info, + dpl_warn_debug, + dpl_warn_fp_debug +} dpl_WARN_LEVEL; + +/* dpl_FOG_TYPE defines the various types of fog which can be applied to + a dpl_VIEW, support for the various types is platform dependent */ +typedef enum dpl_FOG_TYPE +{ + dpl_fog_type_error, /* error (feedback from querry) */ + dpl_fog_type_off, /* turn off fog for view */ + dpl_fog_type_vertex_lin, /* apply linear fog per vertex */ + dpl_fog_type_vertex_exp, /* exponential fog */ + dpl_fog_type_vertex_exp2, /* exponential squared fog */ + dpl_fog_type_pixel_lin, /* apply linear fog per pixel */ + dpl_fog_type_pixel_exp, /* exponential fog */ + dpl_fog_type_pixel_exp2 /* exponential squared fog */ +} dpl_FOG_TYPE; + +typedef struct s_dpldcs dpl_DCS; + +typedef struct s_dplview dpl_VIEW; + +typedef struct s_dpllight dpl_LIGHT; + +typedef struct s_dplzone dpl_ZONE; + +typedef struct s_dplmtl dpl_MATERIAL; + +typedef struct s_dplramp dpl_RAMP; + +typedef struct s_dpltexture dpl_TEXTURE; + +typedef struct s_dpltexmap dpl_TEXMAP; + +typedef struct s_dplinstance dpl_INSTANCE; + +typedef struct s_dplobject dpl_OBJECT; + +typedef struct s_dpllod dpl_LOD; + +typedef struct s_dplgeogroup dpl_GEOGROUP; + +typedef struct s_dplgeometry dpl_GEOMETRY; + +typedef void *dpl_LOAD_FUNCTION(char8 *); + +typedef struct dpl_EXPLOSION_EFFECT_INFO { + float32 x, y, z; /* positional information */ + int32 type; /* existing explosion options */ + dpl_TEXTURE *tex; /* explosion texture */ +} dpl_EXPLOSION_EFFECT_INFO; + +typedef struct dpl_PARTICLESTART_EFFECT_INFO { + int32 identifier; /* the identifying tag of this effect */ + + int32 maximum_issue; /* maximum number to be released */ + float32 release_period; /* the period for which particles will be + released */ + float32 rate; /* the rate at which particles will be + released */ + + float32 px, py, pz, pv; /* position of release and radius of the + variation in position */ + + float32 velx, vely, velz; /* initial velocity of particles */ + float32 velxv, velyv, velzv; /* variation of particle velocity */ + + float32 rad, radv; /* size of particle radius and variation in + the particle radius */ + float32 exp, expv; /* rate of expansion and variation in that + rate */ + float32 dexp, dexpv; /* rate of change of expansion and variation + in that rate */ + + float32 accelx, accely, accelz; /* acceleration of particles */ + float32 accelxv, accelyv, accelzv;/* and its variation */ + float32 atten, attenv; /* resistance to particle motion and it's + variation*/ + + float32 sRi, sGi, sBi, sAi; /* start colour interior */ + float32 sRiv, sGiv, sBiv, sAiv; /* and its variation */ + float32 sRo, sGo, sBo, sAo; /* start colour exterior */ + float32 sRov, sGov, sBov, sAov; /* and its variation */ + + float32 eRi, eGi, eBi, eAi; /* end colour interior */ + float32 eRiv, eGiv, eBiv, eAiv; /* and its variation */ + float32 eRo, eGo, eBo, eAo; /* end colour exterior */ + float32 eRov, eGov, eBov, eAov; /* and its variation */ + + float32 colour_warp; /* a warp factor allowing the interpolation + of the above colours to be weighted towards + the beginning or end using a gamma function + 1.0 = no weighting */ + + float32 alpha_warp; /* a warp factor for alpha (as above) */ + + float32 dur, durv; /* duration and variation in duration of + particles */ + + dpl_TEXTURE *tex; /* particle texture (if supported) */ +} dpl_PARTICLESTART_EFFECT_INFO; + +typedef struct dpl_PARTICLESTOP_EFFECT_INFO { + int32 identifier; /* the identifying tag of all effects + you want to stop */ +} dpl_PARTICLESTOP_EFFECT_INFO; + +typedef struct dpl_PARTICLE_EFFECT_INFO { + float32 px, py, pz; /* position of release */ + float32 velx, vely, velz; /* initial velocity of particle */ + float32 rad; /* size of particle radius */ + float32 exp; /* rate of expansion */ + float32 dexp; /* rate of change of expansion and variation */ + + float32 accelx, accely, accelz; /* acceleration of particle */ + + float32 atten; /* resistance to particle motion */ + + float32 sRi, sGi, sBi, sAi; /* start colour interior */ + float32 sRo, sGo, sBo, sAo; /* start colour exterior */ + + float32 eRi, eGi, eBi, eAi; /* end colour interior */ + float32 eRo, eGo, eBo, eAo; /* end colour exterior */ + + float32 colour_warp; /* a warp factor allowing the interpolation + of the above colours to be weighted towards + the beginning or end using a gamma function + 1.0 = no weighting */ + + float32 alpha_warp; /* a warp factor for alpha (as above) */ + + float32 dur; /* duration of particle */ + + dpl_TEXTURE *tex; /* particle texture (if supported) */ +} dpl_PARTICLE_EFFECT_INFO; + +typedef struct dpl_STATISTICS { + float32 framerate; +} dpl_STATISTICS; + +typedef struct dpl_STATUS { + int32 state; +} dpl_STATUS; + +typedef struct dpl_CAPABILITY { + /* is textured rendering supported */ + int32 textured_rendering; + /* is texture font specification supported */ + int32 font_texture_update; +} dpl_CAPABILITY; + +#ifdef __cplusplus +} +#endif + +#endif diff --git a/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H b/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H new file mode 100644 index 0000000..add5cce --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/DPL2DTAG.H @@ -0,0 +1,33 @@ +#ifndef dpl_2dtag_h +#define dpl_2dtag_h + +typedef enum { + dpl2d_open_polyline, + dpl2d_close_polyline, + dpl2d_open_polypoint, + dpl2d_close_polypoint, + dpl2d_open_polygon, + dpl2d_close_polygon, + dpl2d_open_lines, + dpl2d_close_lines, + dpl2d_point, + dpl2d_circle, + + dpl2d_open_clip_polygon, + dpl2d_close_clip_polygon, + dpl2d_clip_circle, + dpl2d_clip_full, + dpl2d_clip_none, + + dpl2d_set_drawcolor, + dpl2d_set_matrix, + dpl2d_concat_matrix, + dpl2d_push_state, + dpl2d_pop_state, + + dpl2d_call_displaylist, + dpl2d_set_linewidth, + dpl2d_set_alpha +} dpl_2d_tag; + +#endif diff --git a/MUNGA_L4/libDPL/dpl/vpx/DPL_2D.H b/MUNGA_L4/libDPL/dpl/vpx/DPL_2D.H new file mode 100644 index 0000000..ef06cbd --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/DPL_2D.H @@ -0,0 +1,123 @@ +#ifndef dpl_2d_h +#define dpl_2d_h +#ifdef __cplusplus +extern "C" { +#endif + +#include + +#define WORDS_PER_DISPLAY_CHUNK 30 + +typedef struct s_dpl2d_display { + void *remote; + struct s_dpl2d_display *next; + struct s_dpl2d_display *tail; + int32 size; + int32 open; + int32 data[WORDS_PER_DISPLAY_CHUNK]; +} dpl2d_DISPLAY; + +typedef enum dpl2d_OPEN_MODE +{ + dpl2d_open_mode_error, + dpl2d_open_mode_clear, + dpl2d_open_mode_append +} dpl2d_OPEN_MODE; + +typedef enum dpl2d_CLIP_MODE +{ + dpl2d_clip_mode_error, + dpl2d_clip_mode_OR, + dpl2d_clip_mode_AND, + dpl2d_clip_mode_XOR, + dpl2d_clip_mode_SET, + dpl2d_clip_mode_CLEAR +} dpl2d_CLIP_MODE; + +typedef int32 *dpl_2d_snapshot; + +typedef float32 dpl2d_MATRIX [6]; + +/* displaylist creation, destruction */ + +extern dpl2d_DISPLAY *dpl2d_NewDisplayList ( void ); + +extern int32 dpl2d_DeleteDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_OpenDisplayList ( dpl2d_DISPLAY *display, dpl2d_OPEN_MODE append ); + +extern int32 dpl2d_CloseDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_FlushDisplayList ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenPolyline ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClosePolyline ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenLines ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddCloseLines ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenPolypoint ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClosePolypoint ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddPoint ( dpl2d_DISPLAY *display, float32 x, float32 y ); + +extern int32 dpl2d_AddCircle( dpl2d_DISPLAY *display, float32 x, float32 y, float32 r, int32 filled ); + +extern int32 dpl2d_AddPushState ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddPopState ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddSetColor ( dpl2d_DISPLAY *display, float32 r, float32 g, float32 b ); + +extern int32 dpl2d_AddSetAlpha ( dpl2d_DISPLAY *display, float32 a ); + +extern int32 dpl2d_AddSetMatrix ( dpl2d_DISPLAY *display, dpl2d_MATRIX ); + +extern int32 dpl2d_AddConcatMatrix ( dpl2d_DISPLAY *display, dpl2d_MATRIX, int32 post ); + +extern int32 dpl2d_AddSetLineWidth ( dpl2d_DISPLAY *display, + float32 w ); + +/* clip region support */ +extern int32 dpl2d_AddFullScreenClipRegion ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddClearClipRegion ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddOpenClipPolygon ( dpl2d_DISPLAY *display ); + +extern int32 dpl2d_AddCloseClipPolygon ( dpl2d_DISPLAY *display, + dpl2d_CLIP_MODE mode ); + +extern int32 dpl2d_AddClipCircle ( dpl2d_DISPLAY *display, + float32 x, float32 y, float32 rad, + dpl2d_CLIP_MODE mode ); + + +extern int32 dpl2d_AddCallDisplayList ( dpl2d_DISPLAY *display, + dpl2d_DISPLAY *sub_display ); + +extern int32 dpl2d_SetViewDisplayList ( dpl_VIEW *v, dpl2d_DISPLAY *disp ); + +extern dpl2d_DISPLAY *dpl2d_GetViewDisplayList ( dpl_VIEW *v ); + +/* and now the 2-D matrix support */ + +extern void dpl2d_IdMatrix ( dpl2d_MATRIX m ); +extern void dpl2d_TranslateMatrix ( dpl2d_MATRIX m, + float32 x, float32 y ); +extern void dpl2d_RotateMatrix ( dpl2d_MATRIX m, + float32 angle ); +extern void dpl2d_ScaleMatrix ( dpl2d_MATRIX m, + float32 sx, float32 sy ); +extern void dpl2d_ConcatMatrix ( dpl2d_MATRIX m, + dpl2d_MATRIX a, + dpl2d_MATRIX b ); + +#ifdef __cplusplus +} +#endif +#endif + diff --git a/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H b/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H new file mode 100644 index 0000000..f7ba1e6 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/DPL_MEM.H @@ -0,0 +1,24 @@ +#ifndef dpl_mem_h +#define dpl_mem_h + +#ifdef __cplusplus +extern "C" { +#endif + +extern void *dpl_malloc ( int n_bytes ); +extern void *dpl_calloc ( size_t n, size_t size ); +extern void dpl_free ( void *ptr ); +extern void dpl_free_all ( void ); + +extern void dpl_tracemem ( void ); + +#ifndef dpl_mem_c +#define free dpl_free +#define malloc dpl_malloc +#define calloc dpl_calloc +#endif + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/vpx/DPL_PRIV.H b/MUNGA_L4/libDPL/dpl/vpx/DPL_PRIV.H new file mode 100644 index 0000000..0f5425d --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/DPL_PRIV.H @@ -0,0 +1,531 @@ +#ifndef dpltyp_h +#define dpltyp_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpltypes.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Flesh out all the datatypes + + History : Rev 1.0, 18 / 06 / 1994 + 1.1, 22 / 06 / 1994 fixed unimplementable lists by + introducing dpl_superlist + 1.2, 27 / 06 / 1994 dislocated heirarchy from instances + and dropped back to matrix-only DCS + 2.0 16 / 11 / 1994 angusification started + + **************************** */ + +#include +#include + +#define OFF_SITE 1 + +#ifdef i860 +#define REMOTE 1 +#endif + +#define dpl_arg_sep '~' + +#define dcs_node_enable 0x1 +#define dcs_subtree_enable 0x2 +#define dcs_no_view_concat 0x4 + +#define dcs_billboard_x 0x8 +#define dcs_billboard_y 0x10 +#define dcs_billboard_z 0x20 +#define dcs_explode_geo 0x40 +#define dcs_ignore_geo 0x80 + +#define dcs_inherit_lmodel 0x100 +#define dcs_force_eval_lmodel 0x200 +#define dcs_near_field 0x400 +#define dcs_bounded 0x800 +#define dcs_backwards 0x1000 +#define dcs_uniform_scale 0x2000 + +#define dpl_draw_faceted 0x0000 +#define dpl_draw_smooth 0x0001 +#define dpl_draw_colored 0x0002 +#define dpl_draw_luminance 0x0004 +#define dpl_draw_textured 0x0008 +#define dpl_draw_3dtextured 0x0010 +#define dpl_draw_front 0x0200 +#define dpl_draw_back 0x0400 +#define dpl_draw_edges 0x0800 +#define dpl_draw_wireframe 0x1000 +#define dpl_draw_last 0x2000 +#define dpl_draw_envmapped 0x4000 +#define dpl_draw_flipped 0x8000 +#define dpl_draw_f_emissive 0x0020 +#define dpl_draw_b_emissive 0x0040 + +#define dpl_X 0 +#define dpl_Y 1 +#define dpl_Z 2 +#define dpl_W 3 + +#ifdef _DOS +#define dpl_path_separator '\\' +#else +#define dpl_path_separator '/' +#endif + +/* + NOTE in rpc implementations, the rather large overhead + of the dpl_node dplnode is never passed over to the + remote renderer, its just in the host space for management +*/ + +typedef struct s_dplnode* (*node_create_function)( void ); + +typedef struct s_dplnode { + int32 clean; + void *app_specific; + void *remote; /* this MUST be 1st word of REMOTE data */ + dpl_TYPE type_check; +} dpl_node; + +typedef struct s_dplremote_node { + void *remote; + dpl_TYPE type_check; +} dpl_remote_node; + +#ifdef REMOTE +#define dpl_node dpl_remote_node +#endif + +typedef struct s_dpl_chain_node { + dpl_node node; + struct s_dpl_chain_node *next_node; + struct s_dpldcs *dcs; +} dpl_chain_node; + +typedef int32 (*load_function)( dpl_node *, char * ); + +typedef struct s_dpllist { + dpl_node *item; + dpl_TYPE type_check; + struct s_dpllist *next; + struct s_dpllist *prev; +} dpl_list; + +/* + the dpl_superlist is used as the head node for + dpl_lists +*/ + +typedef struct s_dplsuperlist { + dpl_node *dplnode; + + dpl_list *last_accessed; + dpl_list *head; + dpl_list *tail; +} dpl_superlist; + +typedef float32 dpl_POINT [4]; +typedef float32 dpl_MATRIX[4][4]; + +typedef union { + double dbl_MATRIX[8]; + dpl_MATRIX matrix; +} dpl_dblMATRIX; + +/* introduce local datatypes */ + + +/* + +The renderer is currently blowing off way too much storage on the card, +which stands to sense when each polygon is around 144 bytes, 80 bytes for the +vertex and 64 for the connection structure. The currently unused datatypes +below will eventually attempt to buy back a lot of storage by moving away +from linked lists and towards packed structures + +*/ + + +typedef struct s_rvert { + dpl_POINT position; /* 0 */ + dpl_POINT normcol; /* 16 */ + float32 texcoords [3]; /* 32 */ + struct s_rvert *next; /* 44 */ + dpl_POINT xform_posn; /* 48 */ + float32 rendered_color[3]; /* 64 */ + int32 touched; /* 76 */ +} dpl_VERTEX; + +typedef struct s_conn { + struct s_conn *next; /* 0 */ + int32 n_verts; /* 4 */ + dpl_VERTEX* indices[6]; /* 8 */ + dpl_POINT planeEqn; /* 32 */ + float32 rendered_color[3]; /* 48 */ + int32 touched; /* 60 */ +} dpl_CONNECTION; + + +/* we will only use this structure for polys, not spheres, + so the W-coordinate (radius) holds the touched word + */ + +typedef struct s_ivert { + float32 position[3]; /* 3 */ + int32 touched; /* 4 */ + dpl_POINT normcol; /* 8 */ + float32 texcoords [2]; /* 10 total = 40 bytes */ +} dpl_idealVERTEX; + +typedef struct s_iconn { + dpl_POINT planeEqn; /* 4 */ + dpl_idealVERTEX* indices[6]; /* 10 */ +} dpl_idealCONNECTION; /* total 40 bytes */ + +typedef struct s_oconn { + float planeEqn[3]; + int touched; + int indices[6]; +} dpl_outputCONNECTION; /* total 40 bytes */ + + +/* + it looks like we can drop polygon storage down to 80 bytes + per poly, rather than 144, so we can achieve around 80% more + database storage + + the assumption is that we use connection[3] == NULL as the triangle + spotter. is this iffy? it lets us keep hexes for performance. + + planeEqn[3] = touched for output conns, so we have 32 bytes, giving + a 72 byte triangle and _doubling_ storage. + + in order to make this work, we will need a single PMESH of worst-case + size hanging round in memory. So xforming and lighting will no longer + happen in-place, but the destination for the work will always be the + same area of memory. So we'll get better cache and page coherence. + + It is recommended that we drop PMESH size from 6 to 4. + + The VERTEX pointers in the connection structure must now become + byte indices, so we just add on the base address of the VERTEX + structure. + + The only problem is special effects - the sphere effects are just dealt + with by keeping spherelists in the old vertex format; triangle effects + may be more difficult to deal with. + + */ + + + +/* flesh out the datatypes in dpltypes.h */ + +#if 0 +struct s_dpl_statistics { + float32 polys_in_last_frame; + float32 last_edit_time; + float32 last_cull_time; + float32 last_frame_time; + float32 last_frame_time_sb; + float32 polys_per_second; + float32 polys_per_second_sb; +} dpl_STATISTICS; + +#endif + +struct s_dpldcs { + dpl_node dplnode; + dpl_chain_node *nodes; + struct s_dplzone *zone; + dpl_MATRIX matrix; + int32 traversal; /* overload billboards in here for compactness */ + struct s_dpldcs *parent; + struct s_dpldcs *sibling; + struct s_dpldcs *child; + int32 lighting_mask; + dpl_POINT bounds[2]; +#ifdef REMOTE + dpl_dblMATRIX invModel; + float sphere_scale, sphere_big_scale; +#endif +} ; +struct s_dplzone { + dpl_node dplnode; + + int32 view_enable; +} ; +struct s_dplview { + dpl_chain_node dplnode; + + int32 view_id; + int32 pipe; + float32 x0, y0, x1, y1, zeye; + float32 x_size, y_size; + float32 hither_clip; + float32 yon_clip; + float32 back_color[3]; + int32 fog_enable; + float32 fog[5]; /* near, phar, r, g, b */ + struct s_dplview *share_view; + void *display_2d; +} ; +struct s_dpllight { + dpl_chain_node dplnode; + + dpl_LIGHT_TYPE light_type; + float32 color [3]; + float32 radius [2]; /* for radial lights */ + float32 umbra [2]; /* for conical lights */ + int32 lighting_mask; +#ifdef REMOTE + float32 position[3]; +#endif +}; +struct s_dpltexture { + dpl_node dplnode; + + struct s_dpltexmap *texmap; + + int32 minify; + int32 magnify; + int32 alpha; + int32 wrap_u; + int32 wrap_v; + int32 detail; + float32 u0; + float32 v0; + float32 du; + float32 dv; + float32 animate_time; + int32 bitslice; + int32 delta_size; + int32 delta_offs; +}; +struct s_dpltexmap { + dpl_node dplnode; + + int32 *texels; + int32 u_size; + int32 v_size; + int32 bits_per_texel; + int32 alpha; +#ifdef REMOTE + int32 hwareSize; + int32 hwareOffs; + int32 bilinear; + void *cell; +#endif +}; +struct s_dplmtl { + dpl_node dplnode; + + struct s_dpltexture *texture; + struct s_dpltexture *environment; + int32 immunity; + struct s_dplramp *ramp; + float32 emissive [3]; + float32 ambient [3]; + float32 diffuse [3]; + float32 opacity [3]; + float32 specular [4]; + float32 dither; +#ifdef REMOTE + float surf_opacity; + float *specular_table; + int32 pxpl5_cntl_word; + float du, dv; + float alpha_c, alpha_r; + int32 alpha_texture; + int32 cull_frame; +#endif +}; +struct s_dplramp { + dpl_node dplnode; + + float32 color0 [3]; + float32 color1 [3]; + int32 cntl_word; +}; +struct s_dplinstance { + dpl_chain_node dplnode; + + dpl_ISECT_MODE intersectmode; + int32 visibility; + struct s_dplobject *object; + struct s_dpllod *forcelod; + struct s_dplmtl *f_material; + struct s_dplmtl *b_material; + int32 intersect_mask; + int32 wireframe; +#ifdef REMOTE + int32 frame_count; + int32 last_LOD_index; +#endif +}; +#define MAX_LODS_PER_OBJECT 16 + +struct s_dplobject { + dpl_node dplnode; + + dpl_superlist lod_list; + dpl_POINT lod_hot_spot; + float32 lod_ranges[MAX_LODS_PER_OBJECT]; + float32 lod_fade_range; + int32 invalid_lods; + int32 clone; +#ifdef REMOTE + int32 lod_count; + float32 bounds[2][4]; + dpl_POINT sphere_bounds; +#endif +}; +struct s_dpllod { + dpl_node dplnode; + + float32 bounds[2][4]; + struct s_dplobject *parent; + dpl_superlist geogroup_list; + float32 hot_spot[3]; +#ifdef REMOTE + dpl_POINT sphere_bounds; +#endif +}; +struct s_dplgeogroup { + dpl_node dplnode; + + float32 bounds[2][4]; + struct s_dpllod *parent; + int32 draw_mode; + dpl_superlist geometry_list; + struct s_dplmtl *f_material; + struct s_dplmtl *b_material; + float32 decal_offs; + int32 lock; +#ifdef REMOTE + dpl_POINT sphere_bounds; + int32 clean; +#endif +}; +struct s_dplgeometry { + dpl_node dplnode; + + dpl_GEO_TYPE geometry_type; + dpl_VERTEX_TYPE vertex_type; + int32 num_vertices; + struct s_dplgeogroup *parent; + dpl_CONNECTION *connections; + dpl_VERTEX *vertices; + float lineWidth, pointSize; + +#ifdef REMOTE + int32 variable_alpha; + int32 n_connections; + int32 n_vertices; + dpl_CONNECTION *connection_tail; + dpl_VERTEX *vertex_tail; + int32 packed; +#endif + +}; +#if 0 +struct s_dpl_status { + int32 ok; +} dpl_STATUS; +#endif + + +/* ****************************************** + + BEWARE ! ! ! ! ! + + FOR REASONS OF STORAGE AND APPLICATIONS EFFICIENCY, THE FOLLOWING + DATA TYPES ARE N O T SUPERSETS OF DPL_NODE + + BE CAREFUL DEALING WITH VERTICES + +*/ + +/* typedefs for tracing performance */ + +typedef struct s_dpl_version { + int32 host; + int32 major_version; + int32 minor_version; + int32 firmware_major_version; + int32 firmware_minor_version; + char detailed[256]; +} dpl_VERSION; + +/* ********************************************************** + a scene contains a list of root-node dcs's, a list of zones + and a list of views + */ + +typedef struct s_dplscene { + dpl_node dplnode; + + dpl_superlist zone_list; + dpl_superlist view_list; + dpl_superlist dcs_list; + dpl_superlist light_list; +} dpl_SCENE; + +typedef enum { + dpl_artic_matrix, + dpl_artic_singleX, + dpl_artic_singleY, + dpl_artic_singleZ, + dpl_artic_quaternion +} dpl_ARTICULATION; + +/* additional geometry types - keep small for switch optim */ + +#define vpx_geo_type_f_t_dam 16 +#define vpx_geo_type_sca 17 +#define vpx_geo_type_undamage 18 +#define vpx_geo_type_f_t_undam 19 +#define vpx_geo_type_damage_set 20 + +#define dpl_morph_vertices 0x1 +#define dpl_morph_normals 0x2 +#define dpl_morph_texcoords 0x4 +#define dpl_morph_colors 0x8 + + + +typedef void (*vfptr)(); + +extern void * +dpl_svtRead(char8 *, int32 bilinear ); + +extern void * +dpl_bilRead(char8 *); + +extern void * +dpl_glmRead(char8 *); + +extern void +dpl_explodeTexels ( dpl_TEXMAP *tm, + int32 *dest_texels, + uint8 *src_texels, + int32 n_texels, + int32 start, int32 bilinear ); + + +#define POLY_FBITS 12 +#define SPHERE_FBITS 24 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/vpx/DPL_VPX.H b/MUNGA_L4/libDPL/dpl/vpx/DPL_VPX.H new file mode 100644 index 0000000..e24bc62 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/DPL_VPX.H @@ -0,0 +1,220 @@ +#ifndef dpl_vpx_h +#define dpl_vpx_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define VPX 1 +#include + +extern void +dpl_SetDeferredDeletes ( int32 d ); + +extern void +dpl_SetTextureScroll ( dpl_TEXTURE *t, float u, float v, float du, float dv ); + +extern void +dpl_SetGeomScaleFactor ( float32 geomscale ); + +extern void +dpl_SetDCSTraversal ( dpl_DCS *d, int32 trav ); + +extern void dpl_SetDCSXAxis ( dpl_DCS *d, float32 sin, float32 cos ); +extern void dpl_SetDCSYAxis ( dpl_DCS *d, float32 sin, float32 cos ); +extern void dpl_SetDCSZAxis ( dpl_DCS *d, float32 sin, float32 cos ); + +extern void +dpl_SetDCSQuaternion ( dpl_DCS *d, float32 *quaternion_stuff, float32 *xlate ); + +extern void +dpl_FlushDCSArticulations ( dpl_DCS **d ); + +extern void +dpl_SetObjectAdditiveLODs ( dpl_OBJECT *o ); + +extern void +dpl_SetMaterialDitherZ ( dpl_MATERIAL *m, float32 dither ); + +extern void +dpl_install_sfx ( int32 sfx_code, + dpl_TEXTURE *t, + int32 bang_type, + float frag_size, + float frag_velocity, + float vertical_bias, + float switch_off, + float cook_r, + float cook_g, + float cook_b, + float variance, + float gravity, + float cool, + float opacity_cool, + int32 fragments, + int32 iterations, + int32 immunity ); + +extern void +dpl_SetMaterialFogImmunity ( dpl_MATERIAL *m, int32 immunity ); + +extern void dpl_SetDCSExplodeGeo ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSIgnoreGeo ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSInheritLmodel ( dpl_DCS *d, int32 on ); +extern void dpl_SetDCSForceEvalLmodel ( dpl_DCS *d, int32 on ); + +extern void dpl_Damagize ( dpl_GEOGROUP *, dpl_MATERIAL *); +extern void dpl_UnDamagize ( dpl_GEOGROUP * ); +extern void dpl_Punchize ( dpl_GEOGROUP * ); +extern void dpl_Geometrize ( dpl_GEOMETRY *, int32 triangle_code ); + +extern dpl_INSTANCE * +dpl_RapidSectPixel ( float32 xp, float32 yp, + float32 radius, + uint32 mask, + float32 *xi, float32 *yi, float32 *zi, + dpl_DCS **d, dpl_GEOGROUP **gg, dpl_GEOMETRY ** g); + +extern void +dpl_RandomTable ( char *table ); + +extern int32 * +dpl_TouchNode ( int32 *list, void *n ); + +extern int32 +dpl_FlushNodes ( int32 *list ); + +extern void +dpl_SetMinRetraces ( int32 retraces ); + +extern void +dpl_KillEffectAtDCS ( dpl_DCS *dcs ); + +void +dpl_KillParticlefxRange ( int32 min, int32 max ); + +extern void +dpl_RedrawScene ( void ); + +extern void +dpl_PutAppSpecific ( void *node, void *app_specific ); + +extern void* +dpl_GetAppSpecific ( void *node ); + +extern void +dpl_MorphObject ( dpl_OBJECT *dest, + dpl_OBJECT *start, + dpl_OBJECT *end, + float32 alpha, + int32 morph_mode ); +extern void +dpl_MorphGeometry ( dpl_GEOMETRY *dest, + dpl_GEOMETRY *start, + dpl_GEOMETRY *end, + float32 alpha, + int32 morph_mode ); +extern void +dpl_MorphMaterial ( dpl_MATERIAL *dest, + dpl_MATERIAL *start, + dpl_MATERIAL *end, + float32 alpha, + int32 morph_mode ); + +extern void +dpl_TimedMorphObject ( dpl_OBJECT *dest, + dpl_OBJECT *start, + dpl_OBJECT *end, + float32 time, + int32 morph_mode, + float32 a, + float32 b, + float32 c, + float32 d ); +extern void +dpl_TimedMorphMaterial ( dpl_MATERIAL *dest, + dpl_MATERIAL *start, + dpl_MATERIAL *end, + float32 time, + int32 morph_mode, + float32 a, + float32 b, + float32 c, + float32 d ); + + +extern void dpl_SFXTexels2D ( dpl_TEXMAP *tm, + uint32 *texels ); + +extern void dpl_FakeTextureSize ( dpl_TEXTURE *t, int32 delta_size, int32 delta_offs ); + +extern void dpl_SetDCSLightingMask ( dpl_DCS *d, int32 mask ); +extern int32 dpl_GetDCSLightingMask ( dpl_DCS *d ); + +extern void dpl_SetLightLightingMask ( dpl_LIGHT *d, int32 mask ); +extern int32 dpl_GetLightLightingMask ( dpl_LIGHT *d ); + +extern void dpl_SetDCSNearField ( dpl_DCS *d, int32 on ); + +extern int32 +dpl_FreeMemory ( void ); + +extern int +dpl_bslReplace ( char8 *name, dpl_TEXTURE *tex ); + +extern void +dpl_tgaReplace(char8 *file, dpl_TEXTURE *tex ); + +extern void +dpl_DisableSyncOnCreate ( void ); + +extern void +dpl_EnableSyncOnCreate ( void ); + +extern void +dpl_SetDCSBound(dpl_DCS *d, float *minimax ); + +extern float32 +dpl_GetDCSBound(dpl_DCS *d ); + +extern void +dpl_PerfStats ( void ); + +extern void +dpl_SetLodStress ( float32 s ); + +extern +void dpl_SetGeogroupDrawLast(dpl_GEOGROUP *gg, int32 last_on); + +extern +int32 dpl_GetGeogroupDrawLast(dpl_GEOGROUP * gg); + +extern +void dpl_GetObjectBounds( dpl_OBJECT *o, float32 *b ); + +int32 +dpl_GetGeometryNumConnections(dpl_GEOMETRY *g ); + +void +dpl_GetGeometryConnections ( dpl_GEOMETRY *g, + int32 *v, + int32 offset, + int32 n ); + + +extern void +dpl_SetGeometryShadowVolume ( dpl_GEOMETRY *g ); + +extern void +dpl_SetGeometryLightVolume ( dpl_GEOMETRY *g, int imm ); + +extern void +dpl_CleanupGeogroup ( dpl_GEOGROUP *gg, int renorm_facets ); + +extern void +dpl_ReInit(void); + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H b/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H new file mode 100644 index 0000000..80b53a1 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/MATRIX.H @@ -0,0 +1,47 @@ +#ifndef matrix_h +#define matrix_h +#ifdef __cplusplus +extern "C" { +#endif + +/* ************************************************** + + Copyright DIVISION Limited (c) 1994 + All rights reserved + + + File : dpl.h + Project : dpl interface + Author : PJA + Date : 18/6/94 + + Function: Introduces all the datatypes and functions + used by the dpl interface + + History : Rev 1.0, 18 / 06 / 1994 + +**************************** */ + +#include +#include +#include + +extern void dpl_SetAngleMode( int degrees ); +extern void dpl_IdMatrix ( dpl_MATRIX m ); +extern void dpl_Translate ( dpl_MATRIX m, float32 dx, float32 dy, float32 dz ); +extern void dpl_Rotate ( dpl_MATRIX m, float32 angle, int32 axis ); +extern void dpl_Scale ( dpl_MATRIX m, float32 x, float32 y, float32 z ); +extern void dpl_Concat ( dpl_MATRIX m, dpl_MATRIX a, dpl_MATRIX b ); +extern void dpl_Invert ( dpl_MATRIX inverse, dpl_MATRIX mat ); +extern void dpl_XformPoint ( dpl_POINT q, dpl_POINT p, dpl_MATRIX m ); + +extern void dpl_IdMatrixDCS ( dpl_DCS *d ); +extern void dpl_TranslateDCS ( dpl_DCS *d, float32 dx, float32 dy, float32 dz ); +extern void dpl_RotateDCS ( dpl_DCS *d, float32 angle, int32 axis ); +extern void dpl_ScaleDCS ( dpl_DCS *d, float32 x, float32 y, float32 z ); + + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H b/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H new file mode 100644 index 0000000..9fb2347 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/TRICODER.H @@ -0,0 +1,35 @@ +#ifndef tricoder_h +#define tricoder_h + +#ifdef __cplusplus +extern "C" { +#endif + +#define triangle_intro_bits 0x0f + +#define triangle_opacity_intro 0x01 +#define triangle_unopacity_intro 0x02 +#define triangle_dmg_set_intro 0x03 +#define triangle_dmg_clear_intro 0x04 +#define triangle_sca_intro 0x05 +#define triangle_dmg2enbl_intro 0x06 +#define triangle_undmg2enbl_intro 0x07 +#define triangle_bright32_intro 0x08 +#define triangle_dark32_intro 0x09 +#define triangle_fifty_intro 0x0a +#define triangle_surfopacity_intro 0x0b +#define triangle_albright32_intro 0x0c +#define triangle_aldark32_intro 0x0d +#define triangle_albrightfog_intro 0x0e + +#define triangle_texture_bit 0x010 +#define triangle_dither_bit 0x020 +#define triangle_gouraud_bit 0x040 +#define triangle_enbl2dmg_bit 0x080 +#define triangle_white_bit 0x100 +#define triangle_emiss_bit 0x200 + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H b/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H new file mode 100644 index 0000000..abe9ea3 --- /dev/null +++ b/MUNGA_L4/libDPL/dpl/vpx/VR_PROT.H @@ -0,0 +1,95 @@ +#ifndef vr_prot_h +#define vr_prot_h +#ifdef __cplusplus +extern "C" { +#endif + +typedef enum vr_action { + vr_init_action, + + vr_create_action, + vr_delete_action, + vr_flush_action, + + vr_sect_pixel_action, + vr_sect_vector_action, + + vr_dcs_nest_action, + vr_dcs_link_action, + vr_dcs_prune_action, + + vr_draw_scene_action, + vr_draw_scene_complete_action, + + vr_list_add_action, + vr_list_remove_action, + + vr_morph_action, + + vr_version_action, + vr_statistics_action, + vr_readpixels_action, + + vr_hspcode_action, + vr_860code_action, + vr_860data_action, + vr_860bss_action, + vr_860args_action, + + vr_set_geom_text_action, + vr_update_geom_verts_action, + vr_get_geom_verts_action, + vr_add_geom_connections_action, + vr_set_texmap_texels_action, + vr_sfx_action, + vr_install_sfx_action, + vr_psfx_action, + vr_install_psfx_action, + vr_flush_dcs_artic_action, + vr_damage_action, + vr_random_table_action, + vr_gamma_table_action, + vr_kill_sfx_action, + vr_geometrize_action, + vr_clone_object_action, + vr_set_sect_pixel_action, + vr_set_warning_action, + vr_set_render_prop_action, + vr_create_2d_display_action, + vr_delete_2d_display_action, + vr_flush_2d_display_action, + vr_freemem_action, + vr_sync_action, + vr_get_bounds_action, + vr_get_geom_connections_action, + vr_get_geom_numconnections_action, + vr_cleanup_gg_action, + vr_clear_dcs_action, + vr_remove_dcs_action, + vr_add_dcs_action +} vr_action; + +/* some i860 states for transputer-side monitoring */ + +#define state_vr_rcv_wait_lock 0 +#define state_vr_rcv_wait_ack 1 +#define state_vr_send_wait_lock 2 +#define state_vr_send_wait_ack 3 +#define state_vr_dma_wait_lock 4 +#define state_vr_dma_wait_ack 5 +#define state_vr_dma_spin_lock 6 +#define state_vr_texels_wait_lock 7 +#define state_vr_texels_wait_ack 8 +#define state_vr_texels_spin_lock 9 +#define state_vr_cull 10 +#define state_vr_draw 11 + +#define state_monitor 0 + +#define set_state(a,b,c) if (state_monitor) set_i860_state(a,b,c) +#define aux_state(a,b,c) if (state_monitor) set_i860_auxstate(a,b,c) + +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dsys/DIVTYPES.DEF b/MUNGA_L4/libDPL/dsys/DIVTYPES.DEF new file mode 100644 index 0000000..e54115a --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DIVTYPES.DEF @@ -0,0 +1,75 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: VL + * MODULE: basictypes.def + * + * File: $RCSfile: divtypes.def,v $ + * Revision: $Revision: 2.3 $ + * Date: $Date: 1995/04/27 10:40:16 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divtypes.def,v 2.3 1995/04/27 10:40:16 jeff beta $ + * + * FUNCTION: + * This module is used to hold the parameterised definitions of the basic + * types used throughout the system for all the machines supported. When + * porting to a new architecture all type stuff should be modified in + * here. There should be no machine dependant code anywhere else! + * + * each of the basic type int8 uint8 etc, etc is defined in terms of + * standard ansi 'C' types here, and given a enum name for conveniance. + * + * char8 is used for cases where the signedness of the byte is irelevent + * such as in character strings etc. + * The format is DEF_TYPE ( , , ) + * + * $Log: divtypes.def,v $ + * Revision 2.3 1995/04/27 10:40:16 jeff + * *** empty log message *** + * + * Revision 2.2 1994/09/08 12:35:33 jeff + * added windows basic types. + * + * Revision 2.1 1994/04/08 13:50:14 jeff + * Importded from 2.0 tree. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#if defined (_WIN31) + +DEF_TYPE( CHAR8, char8, char) +DEF_TYPE( INT8, int8, signed char) +DEF_TYPE( UINT8, uint8, unsigned char) +DEF_TYPE( INT16, int16, signed int) +DEF_TYPE( UINT16, uint16, unsigned int) +DEF_TYPE( INT32, int32, signed long) +DEF_TYPE( UINT32, uint32, unsigned long) +DEF_TYPE( FLOAT32, float32, float) +DEF_TYPE( FLOAT64, float64, double) + +#else + +DEF_TYPE( CHAR8, char8, char) +DEF_TYPE( INT8, int8, signed char) +DEF_TYPE( UINT8, uint8, unsigned char) +DEF_TYPE( INT16, int16, signed short) +DEF_TYPE( UINT16, uint16, unsigned short) +DEF_TYPE( INT32, int32, signed int) +DEF_TYPE( UINT32, uint32, unsigned int) +DEF_TYPE( FLOAT32, float32, float) +DEF_TYPE( FLOAT64, float64, double) + +#endif + +/* + * Note we may need to put ifdefs back in here for some machines IE 64Bit + * processors ? + */ diff --git a/MUNGA_L4/libDPL/dsys/DIVTYPES.H b/MUNGA_L4/libDPL/dsys/DIVTYPES.H new file mode 100644 index 0000000..956dbff --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DIVTYPES.H @@ -0,0 +1,73 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: vl + * MODULE: divtypes.h + * + * File: $RCSfile: divtypes.h,v $ + * Revision: $Revision: 2.11 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divtypes.h,v 2.11 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * + * This file contains standard type definitions used by all higher + * levels in the system. + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DIVTYPES_H +#define _DIVTYPES_H + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * mangle the divtypes.def file to get machine specific low level + * definitions for all our basic types. + */ +#define DEF_TYPE(a,b,c) typedef c b; +#include +#undef DEF_TYPE + +///* +// * generate an enum list of all the symbolic values for the types. +// */ +//#define DEF_TYPE(a,b,c) a, +typedef enum dpDivType { +//#include +LAST_TYPE +} dpDivType; +//#undef DEF_TYPE +#define BASIC_TYPE_CNT ((int)LAST_TYPE) + +/* + * A structure to define the names etc of the basic types for internal + * use. + */ +typedef struct dpTypeSpec{ + char8 endian16[3]; + char8 endian32[5]; + struct { + char8 *name; + uint32 size; + uint32 alignment; + }Sizes[BASIC_TYPE_CNT]; +} dpTypeSpec; + +extern void dpGenDivTypes(dpTypeSpec *spec); + +#ifdef __cplusplus +} +#endif +#endif /* _DIVTYPES_H */ + + diff --git a/MUNGA_L4/libDPL/dsys/DIVVERS.H b/MUNGA_L4/libDPL/dsys/DIVVERS.H new file mode 100644 index 0000000..216bfd1 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DIVVERS.H @@ -0,0 +1,54 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: dp + * MODULE: divvers.c + * + * File: $RCSfile: divvers.h,v $ + * Revision: $Revision: 1.6 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: divvers.h,v 1.6 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * macro to aid the printing of version no's for components. + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DIVVERS_H +#define _DIVVERS_H + +#include +#define divVersion(filep,module,description,version) \ +do { \ + static int done = 0; \ + static char *vstring = "@(#)Division dVS. " module " - " description \ + ". Version " version ". " __DATE__ ; \ + if (done == 0) { \ + fprintf (stdout, "%s\n", &vstring [4]); \ + if (filep) \ + fprintf (filep, "%s\n", &vstring [4]); \ + } \ + done = 1; \ +} while (0) + +#define div3rdPartyVersion(filep,party,description,version,date) \ +do { \ + static int done = 0; \ + static char *vstring = party ". " description \ + ". Version " version ". " date ; \ + if (done == 0) { \ + fprintf (stdout, "%s\n", vstring); \ + if (filep) \ + fprintf (filep, "%s\n", vstring ); \ + } \ + done = 1; \ +} while (0) + +#endif diff --git a/MUNGA_L4/libDPL/dsys/DLINK.H b/MUNGA_L4/libDPL/dsys/DLINK.H new file mode 100644 index 0000000..9b7efb8 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DLINK.H @@ -0,0 +1,258 @@ +/******************************************************************************/ +/* */ +/* ###### ### # # ### ##### ### ####### # # */ +/* # # # # # # # # # # # ## # */ +/* # # # # # # # # # # # # # */ +/* # # # # # # ##### # # # # # # */ +/* # # # # # # # # # # # # # */ +/* # # # # # # # # # # # # ## */ +/* ###### ### # ### ##### ### ####### # # */ +/* */ +/* # ##### ##### ####### */ +/* ## # # # # # */ +/* # # # # # # # */ +/* # ###### ###### ###### */ +/* # # # # */ +/* # # # # # # # */ +/* ##### ##### ##### ##### */ +/* */ +/* Copyright (c) Division Limited. All rights reserved */ +/* */ +/* This Document may not, in whole or in part, be copied, photocopied, */ +/* reproduced, translated, or reduced to any electronic medium or machine */ +/* readable form without prior written consent from Division Ltd. */ +/* */ +/******************************************************************************/ + +#if !defined _DLINK_H_ +#define _DLINK_H_ + + +#if defined __cplusplus +extern "C" { +#endif + +/* This is the interface between dlink and the user. */ +/* It keeps track of which device we are talking to (via the */ +/* device driver file descriptor. It also keeps track of the protocol mode */ + +#if defined _UNIX + +typedef struct dbi_interface *DBI_INTERFACE_PTR; +typedef struct dbi_interface +{ + int fd; + int protocol; + +} DBI_INTERFACE; + +#else /* NOT _UNIX */ + +typedef void *DBI_INTERFACE_PTR; /* Redirect into the linkio structures */ + +#endif /* _UNIX */ + + + + + + + + + + + + +/* Open a dLink Device */ +/* On a success, returns a pointer that acts as a handle for all further operations. */ +/* When operations on this handle are finished, dlink_closeDevice should be called to */ +/* off any resources associated with the handle. In the unix world, dlink_initDevice */ +/* should be passed a filename that corresponds to the device being used. eg. /dev/dbi01 */ +/* Will return NULL, and print a message on error */ + +extern DBI_INTERFACE_PTR dlink_initDevice (char *deviceName); + + + + + + +/* Close a dLink Device */ +/* Attempts to free off any resources associated with a dLink device handle */ +/* which is passed into the routine. Returns 0 on success. On error, will print */ +/* a message and return (-1). */ +/* After a successful dlink_closeDevice, the dLink device pointer is no longer valid. */ + +extern int dlink_closeDevice (DBI_INTERFACE_PTR interface); + + + + + + +/* Reset the device associated with the dLink device handle. */ +/* This has the effect of resetting the hardware that is associated with the dLink */ +/* device handle passed into the routine. */ +/* Will return 0 on success, or print a message and return (-1) on error */ + +extern int dlink_resetDevice (DBI_INTERFACE_PTR interface); + + + + + + + +/* Write RAW data */ +/* Similar to the UNIX write system call. */ +/* Attempts to write nob bytes of data starting from the address in data to */ +/* the device associated with the dLink device handle passed in. */ +/* Returns the number of bytes written. */ +/* If an error occurs, will print a message and return (-1). */ + +extern int dlink_write (DBI_INTERFACE_PTR interface, char *data, unsigned int nob); + + + + + + + + + +/* Read RAW data */ +/* Similar to the UNIX read system call. */ +/* Attempts to read nob bytes of data starting to the address in data from */ +/* the device associated with the dLink device handle passed in. */ +/* Returns the number of bytes read. */ +/* If an error occurs, will print a message and return (-1). */ + +extern int dlink_read (DBI_INTERFACE_PTR interface, char *data, unsigned int nob); + + + + + + + + + +/* See if the link is ready */ +/* If there is input from the device waiting will return non-zero, */ +/* otherwise will return zero. */ +extern int dlink_inputReady (DBI_INTERFACE_PTR interface); + + + + + + + + + + + + + + + + + + +/* Send out a protocol packet */ +/* Attempts to send a protocol packet to the device associated with the dLink */ +/* device handle passed to the routine. */ +/* Parameters are as follows; + + interface dLink device handle. + data Address of data. + nob Number of bytes to send. Must be a multiple of 4, + and no more than 1020 bytes, as defined by the + protocol used. + protocolTag A protocol tag that will be interpreted by the + user code at the destination process. + target The ID of the destination process. Can be 0x0 to 0xFF, + where 0xFF is a broadcast message. + toIserver 0 for a non-Iserver message, 1 for a packet destined for + an Iserver. + needsFlipping. Specifies whether the data is affected by machine Endian + properties. If set to 1, dLink will automatically flip + the data on despatch. dLink will only do this if the + host machine is reverse endian to the destination. + If either needsFlipping is 0, or the host machined is the + same endian to the destination, no byte flipping is + performed. + + Returns 0 on success, or -1 and a message on error. */ + +extern int dlink_sendProtocolPacket (DBI_INTERFACE_PTR interface, + char *data, unsigned int nob, + int protocolTag, + int target, int toIserver, + int needsFlipping); + + + + + + + + +/* Receive a protocol packet */ +/* Attempts to read a protocol packet from the device associated with the dLink */ +/* device handle passed to the routine. */ +/* Parameters are as follows; + + interface dLink device handle. + data Address of where the data is to be read. + nob Pointer to the number of bytes actually received. + + protocolTag Currently not used. Pass in NULL. + target Pointer to the ID of the sender of the data. + toIserver Pointer saying whether the message was from an Iserver. + 1 will be placed here if the message is from an Iserver, + 0 otherwise. + needsFlipping. Specifies whether the data is affected by machine Endian + properties. If set to 1, dLink will automatically flip + the data on arrival. dLink will only do this if the + host machine is reverse endian to the destination. + If either needsFlipping is 0, or the host machined is the + same endian to the destination, no byte flipping is + performed. +*/ +/* Returns 0 on success, or -1 and a message on error. */ + +extern int dlink_recvProtocolPacket (DBI_INTERFACE_PTR interface, + char *data, unsigned int *nob, + int *protocolTag, + int *target, int *fromIserver, + int needsFlipping); + + + + + + + + + + +/* Switch dLink Error messages to come from the given */ +/* file descriptor. If the descriptor is NULL, then */ +/* error messages will be switched off */ +/* Parameters are as follows; + + fd Pointer to a file descriptor. If the pointer is NULL + then dlink error messages will be switched off, otherwise + dlink error messages will be sent over the given file + descriptor after the call. +*/ + +extern void dlink_setErrorFile (FILE *fd); + + +#if defined __cplusplus +} +#endif + +#endif diff --git a/MUNGA_L4/libDPL/dsys/DM.H b/MUNGA_L4/libDPL/dsys/DM.H new file mode 100644 index 0000000..e8fc5fd --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DM.H @@ -0,0 +1,635 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: matrix/linear algebra mosdule + * MODULE: dmtypes.h + * + * File: $RCSfile: dm.h,v $ + * Revision: $Revision: 2.23 $ + * Date: $Date: 1995/05/18 09:46:38 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: dm.h,v 2.23 1995/05/18 09:46:38 jeff beta $ + * + * FUNCTION: + * This file contains the external declarations of the dm library + * routines and types. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DMTYPES_H +#define _DMTYPES_H + +#include + +#if defined(_TRANSPUTER) || defined(_I860) +/* + * These are not defined on transputers. + */ +#define M_E 2.71828182845904523540 +#define M_LOG2E 1.44269504088896340740 +#define M_LOG10E 0.43429448190325182765 +#define M_LN2 0.69314718055994530942 +#define M_LN10 2.30258509299404568402 +#define M_PI 3.14159265358979323846 +#define M_PI_2 1.57079632679489661923 +#define M_PI_4 0.78539816339744830962 +#define M_1_PI 0.31830988618379067154 +#define M_2_PI 0.63661977236758134308 +#define M_2_SQRTPI 1.12837916709551257390 +#define M_SQRT2 1.41421356237309504880 +#define M_SQRT1_2 0.70710678118654752440 +#endif + +#ifdef _TRANSPUTER +#include +#else +#include +#endif + +#ifdef _I860 +#define const /*broken pgcc doesn't understand const properly*/ +#endif + +/* Windows mathf functions. */ +#if defined(_WIN31) || defined(_DOS) +#define fabsf(x) (float) fabs((double)(x)) +#define sqrtf(x) (float) sqrt((double)(x)) +#define sinf(x) (float) sin((double)(x)) +#define cosf(x) (float) cos((double)(x)) +#define asinf(x) (float) asin((double)(x)) +#define acosf(x) (float) acos((double)(x)) +#endif + + +#include +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif +/* + * The basic linear algebra types. + */ +typedef enum { + DM_X = 0, + DM_Y = 1, + DM_Z = 2, + DM_W = 3, + DM_PITCH = 0, + DM_YAW = 1, + DM_ROLL = 2 +} dmIndex; + +typedef float32 dmVector[3]; +typedef float32 dmScale[3]; +typedef float32 dmPoint[3]; +typedef float32 dmEuler[3]; +typedef float32 dmQuaternion[4]; +typedef float32 dmMatrix[4][4]; + +typedef struct { + dmMatrix pos; + dmVector linearVel; + dmVector linearAccn; + dmVector angularVel; + dmVector angularAccn; +} dmPosition, *dmPosition_Ptr; + +/* + * Small value used to check floating point values for equality + * or smallness. This number is withing 2 bits of the smallest + * representable relative differance between two numbers. + */ +#define DM_EPSILON ((float32)(FLT_EPSILON * 4.0f)) + +/* + * fast macros for common ops. + */ +#define dmSqr(x) ((x) * (x)) + +#define dmCrossProd3(r,a,b) \ +do { \ + float32 _ax = (a)[DM_X], _bx = (b)[DM_X]; \ + float32 _ay = (a)[DM_Y], _by = (b)[DM_Y]; \ + float32 _az = (a)[DM_Z], _bz = (b)[DM_Z]; \ + \ + (r)[DM_X] = (_ay * _bz) - (_az * _by); \ + (r)[DM_Y] = (_az * _bx) - (_ax * _bz); \ + (r)[DM_Z] = (_ax * _by) - (_ay * _bx); \ +} while (0) + +#define dmDotProd3(x, y) ( ((x)[DM_X] * (y)[DM_X]) \ + + ((x)[DM_Y] * (y)[DM_Y]) \ + + ((x)[DM_Z] * (y)[DM_Z])) + +#define dmDotProd4(x, y) ( ((x)[DM_X] * (y)[DM_X]) \ + + ((x)[DM_Y] * (y)[DM_Y]) \ + + ((x)[DM_Z] * (y)[DM_Z]) \ + + ((x)[DM_W] * (y)[DM_W])) + +#define dmLength3(x) sqrtf( dmSqr(x[DM_X]) \ + +dmSqr(x[DM_Y]) \ + +dmSqr(x[DM_Z])) + +#define dmVectorCrossProd(r,a,b) dmCrossProd3((r),(a),(b)) +#define dmVectorDotProd(a,b) dmDotProd3((a),(b)) +#define dmVectorLength(a) dmLength3(a) + + + +#define dmScaleInvert(d,s) (((d)[DM_X] = 1.0f/(s)[DM_X]), \ + ((d)[DM_Y] = 1.0f/(s)[DM_Y]), \ + ((d)[DM_Z] = 1.0f/(s)[DM_Z])) + +#define dmVectorInvert(d,s) (((d)[DM_X] = -(s)[DM_X]), \ + ((d)[DM_Y] = -(s)[DM_Y]), \ + ((d)[DM_Z] = -(s)[DM_Z])) + + +#define dmDegToRad(x) ((x) * ((float32) M_PI / 180.0)) +#define dmRadToDeg(x) ((x) * ((float32) M_1_PI * 180.0)) + + + +/* + * Optimised and Safe trig functions. + */ +extern void dmSinCosf(float32 *s, + float32 *c, + float32 angle); +extern float32 dmSafeAtan2(float32 opposite, + float32 adjacent); + +/* + * Copy functions + */ +#ifdef _TRANSPUTER +#include +#define dmMatCopy(d,s) memcpy(d,s,sizeof(dmMatrix)) +#define dmQuatCopy(d,s) memcpy(d,s,sizeof(dmQuaternion)) +#define dmEulerCopy(d,s) memcpy(d,s,sizeof(dmEuler)) +#define dmVectorCopy(d,s) memcpy(d,s,sizeof(dmVector)) +#define dmPointCopy(d,s) memcpy(d,s,sizeof(dmPoint)) +#define dmScaleCopy(d,s) memcpy(d,s,sizeof(dmScale)) +#define dmPosCopy(d,s) ((d) = (s)) +#define __dmCopy3(d,s) memcpy(d,s,3 * sizeof(float32)) +#define __dmCopy4(d,s) memcpy(d,s,4 * sizeof(float32)) +#else +#define __dmCopy3(d,s) do { \ + (d)[DM_X] = (s)[DM_X]; \ + (d)[DM_Y] = (s)[DM_Y]; \ + (d)[DM_Z] = (s)[DM_Z]; \ +} while (0) + +#define __dmCopy4(d,s) do { \ + (d)[DM_X] = (s)[DM_X]; \ + (d)[DM_Y] = (s)[DM_Y]; \ + (d)[DM_Z] = (s)[DM_Z]; \ + (d)[DM_W] = (s)[DM_W]; \ +} while (0) + +#define dmMatCopy(d,s) do { \ + __dmCopy4((d)[DM_X],(s)[DM_X]); \ + __dmCopy4((d)[DM_Y],(s)[DM_Y]); \ + __dmCopy4((d)[DM_Z],(s)[DM_Z]); \ + __dmCopy4((d)[DM_W],(s)[DM_W]); \ +} while (0) + +#define dmQuatCopy(d,s) __dmCopy4(d,s) +#define dmEulerCopy(d,s) __dmCopy3(d,s) +#define dmVectorCopy(d,s) __dmCopy3(d,s) +#define dmPointCopy(d,s) __dmCopy3(d,s) +#define dmScaleCopy(d,s) __dmCopy3(d,s) + +#define dmPosCopy(d,s) (*(d) = *(s)) +#endif + +/* + * Ident functions. + */ +#define dmMatIdent(m) dmMatCopy(m, dmIdentM) +#define dmQuatIdent(q) dmQuatCopy(q, dmIdentQ) +#define dmEulerIdent(e) dmEulerCopy(e, dmIdentE) +#define dmVectorIdent(v) dmVectorCopy(v, dmIdentV) +#define dmPointIdent(p) dmPointCopy(p, dmIdentP) +#define dmScaleIdent(s) dmScaleCopy(s, dmIdentS) +#define dmPosIdent(p) dmPosCopy(p, &dmIdentPos) + +extern const dmMatrix dmIdentM; +extern const dmQuaternion dmIdentQ; +extern const dmEuler dmIdentE; +extern const dmVector dmIdentV; +extern const dmPoint dmIdentP; +extern const dmScale dmIdentS; +extern const dmPosition dmIdentPos; + +extern void (dmMatIdent)(dmMatrix mat); +extern void (dmQuatIdent)(dmQuaternion q); +extern void (dmEulerIdent)(dmEuler e); +extern void (dmVectorIdent)(dmVector s); +extern void (dmPointIdent)(dmPoint s); +extern void (dmScaleIdent)(dmScale s); +extern void (dmPosIdent)(dmPosition_Ptr p); + +/* + * initialisation functions + */ +#define dmEulerSet(e,p,y,r) ((e)[DM_PITCH] = (p), \ + (e)[DM_YAW] = (y), \ + (e)[DM_ROLL] = (r)) + +#define dmEulerSetD(e,p,y,r) ((e)[DM_PITCH] = dmDegToRad(p), \ + (e)[DM_YAW] = dmDegToRad(y), \ + (e)[DM_ROLL] = dmDegToRad(r)) + +#define dmQuatSet(q,x,y,z,w) ((q)[DM_X] = (x), \ + (q)[DM_Y] = (y), \ + (q)[DM_Z] = (z), \ + (q)[DM_W] = (w)) + +#define dmPointSet(p,x,y,z) ((p)[DM_X] = (x), \ + (p)[DM_Y] = (y), \ + (p)[DM_Z] = (z)) + +#define dmVectorSet(v,x,y,z) ((v)[DM_X] = (x), \ + (v)[DM_Y] = (y), \ + (v)[DM_Z] = (z)) + +#define dmScaleSet(s,x,y,z) ((s)[DM_X] = (x), \ + (s)[DM_Y] = (y), \ + (s)[DM_Z] = (z)) + + +extern void (dmEulerSet)(dmEuler e, + float32 pitch, + float32 yaw, + float32 roll); +extern void (dmEulerSetD)(dmEuler e, + float32 pitch, + float32 yaw, + float32 roll); +extern void (dmQuatSet)(dmQuaternion q, + float32 x, + float32 y, + float32 z, + float32 w); +extern void (dmPointSet)(dmPoint p, + float32 x, + float32 y, + float32 z); +extern void (dmVectorSet)(dmVector p, + float32 x, + float32 y, + float32 z); +extern void (dmScaleSet)(dmScale p, + float32 x, + float32 y, + float32 z); + +/* + * Matrix generation functions + */ +#define dmMatFromScale(m,s) do { \ + dmMatIdent(m); \ + (m)[DM_X][DM_X] = s[DM_X]; \ + (m)[DM_Y][DM_Y] = s[DM_Y]; \ + (m)[DM_Z][DM_Z] = s[DM_Z]; \ +} while (0) + +#define dmMatFromEuler(m,e) do { \ + dmQuaternion __q; \ + dmQuatFromEuler(__q,e); \ + dmMatFromQuat(m,__q); \ +} while (0) + +#define dmMatFromPoint(m,p) do { \ + dmMatIdent(m); \ + m[DM_W][DM_X] = p[DM_X]; \ + m[DM_W][DM_Y] = p[DM_Y]; \ + m[DM_W][DM_Z] = p[DM_Z]; \ +} while (0) + +#define dmMatFromPointEulerScale(m, p,e,s) do { \ + dmMatFromScale(m,s); \ + dmMatRotEuler(m,e); \ + m[DM_W][DM_X] = p[DM_X]; \ + m[DM_W][DM_Y] = p[DM_Y]; \ + m[DM_W][DM_Z] = p[DM_Z]; \ +} while (0) + +#define dmMatFromPointQuatScale(m, p,q,s) do { \ + dmMatFromScale(m,s); \ + dmMatRotQuat(m,q); \ + m[DM_W][DM_X] = p[DM_X]; \ + m[DM_W][DM_Y] = p[DM_Y]; \ + m[DM_W][DM_Z] = p[DM_Z]; \ +} while (0) + +extern void dmMatFromQuat( dmMatrix mat, + const dmQuaternion quat); +extern void dmMatFromGeneralQuat( dmMatrix mat, + const dmQuaternion quat); +extern void (dmMatFromEuler)( dmMatrix m, + const dmEuler e); +extern void (dmMatFromScale)( dmMatrix m, + const dmScale s); +extern void (dmMatFromPoint)( dmMatrix m, + const dmPoint p); +extern void (dmMatFromPointEulerScale)( dmMatrix m, + const dmPoint p, + const dmEuler e, + const dmScale s); +extern void (dmMatFromPointQuatScale)( dmMatrix m, + const dmPoint p, + const dmQuaternion q, + const dmScale s); + + + +/* + * matrix manipulation functions. + */ +#define dmMatRotQuat(m,q) do { \ + dmMatrix __m; \ + dmMatFromQuat(__m, (q)); \ + dmMatMultH((m),(m),__m); \ +} while (0) + +#define dmMatRotEuler(m, e) do { \ + dmMatrix __m; \ + dmMatFromEuler(__m,e); \ + dmMatMultH((m), (m), __m); \ +} while (0) + + +extern void dmMatRotX(dmMatrix m, + float32 angle); +extern void dmMatRotY(dmMatrix m, + float32 angle); +extern void dmMatRotZ(dmMatrix m, + float32 angle); + +extern void (dmMatRotEuler)( dmMatrix m, + const dmEuler e); +extern void (dmMatRotQuat)( dmMatrix m, + const dmQuaternion q); +extern void dmMatScale( dmMatrix m, + const dmScale s); + +extern void dmMatXlate( dmMatrix m, + const dmVector v); + +extern void dmMatInvertH( dmMatrix inv, + const dmMatrix mat); + +extern void dmMatMultH( dmMatrix res, + const dmMatrix left, + const dmMatrix right); + +extern int dmMatInvert( dmMatrix inv, + const dmMatrix mat); + +extern void dmMatMult( dmMatrix res, + const dmMatrix left, + const dmMatrix right); + +/* + * Quaternion manipulation ops. + */ +#define dmQuatNorm(x) do { \ + if ((x)[DM_W] < 0.0f) { \ + (x)[DM_X] = -(x)[DM_X]; \ + (x)[DM_Y] = -(x)[DM_Y]; \ + (x)[DM_Z] = -(x)[DM_Z]; \ + (x)[DM_W] = -(x)[DM_W]; \ + } \ +}while(0) + +extern void dmQuatInvert( dmQuaternion res, + const dmQuaternion q); +extern void dmQuatMult( dmQuaternion res, + const dmQuaternion left, + const dmQuaternion right); +extern void dmQuatMake( dmQuaternion quat, + const dmVector axis, + float32 angle); +extern void dmQuatMakeUnitAxis( dmQuaternion rot, + const dmVector axis, + float angle); +extern void (dmQuatNorm)(dmQuaternion q); + + +/* + * Conversions between Euler angles and + * quaternions. + */ + +extern void dmQuatFromEuler( dmQuaternion quat, + const dmEuler erot); + +extern void dmEulerFromQuat( dmEuler e, + const dmQuaternion q); + + +/* + * Functions to split matricies in various ways. + */ + +#define dmPointFromMat(p,m) dmPointQuatScaleFromMat((p), NULL, NULL, (m)) +#define dmScaleFromMat(s,m) dmPointQuatScaleFromMat(NULL, NULL, (s), (m)) +#define dmQuatFromMat(q,m) dmPointQuatScaleFromMat(NULL, (q), NULL, (m)) +#define dmEulerFromMat(e,m) dmPointEulerScaleFromMat(NULL, (e), NULL, (m)) + +extern int (dmQuatFromMat)( dmQuaternion quat, + const dmMatrix mat); +extern int (dmEulerFromMat)( dmEuler e, + const dmMatrix m); +extern int (dmPointFromMat)( dmPoint p, + const dmMatrix m); +extern int (dmScaleFromMat)( dmScale s, + const dmMatrix m); + +extern int dmPointQuatScaleFromMat( dmPoint p, + dmQuaternion q, + dmScale s, + const dmMatrix m); + +extern int dmPointEulerScaleFromMat( dmPoint p, + dmEuler e, + dmScale s, + const dmMatrix m); + +/* + * Functions to manipulate vectors and points + * using matricies, quaternions, rotations and scales + */ +#define __dmAdd3(r,a,b) ((r)[DM_X] = (a)[DM_X] + (b)[DM_X], \ + (r)[DM_Y] = (a)[DM_Y] + (b)[DM_Y], \ + (r)[DM_Z] = (a)[DM_Z] + (b)[DM_Z]) +#define __dmSub3(r,a,b) ((r)[DM_X] = (a)[DM_X] - (b)[DM_X], \ + (r)[DM_Y] = (a)[DM_Y] - (b)[DM_Y], \ + (r)[DM_Z] = (a)[DM_Z] - (b)[DM_Z]) +#define __dmScale3(r,a,b) ((r)[DM_X] = (a)[DM_X] * (b)[DM_X], \ + (r)[DM_Y] = (a)[DM_Y] * (b)[DM_Y], \ + (r)[DM_Z] = (a)[DM_Z] * (b)[DM_Z]) + +#define __dmScaleScalar3(r,a,b) ((r)[DM_X] = (a)[DM_X] * b, \ + (r)[DM_Y] = (a)[DM_Y] * b, \ + (r)[DM_Z] = (a)[DM_Z] * b) + + +#define __dmRotEuler3(r,a,b) \ +do { \ + dmQuaternion __q; \ + dmQuatFromEuler(__q,b); \ + __dmRotQuat3((r),(a),__q); \ +} while (0) + +extern void __dmRotQuat3( float32 *r, + const float32 *a, + const dmQuaternion q); + +#define dmVectorAdd(r,a,b) __dmAdd3(r,a,b) +#define dmVectorSub(r,a,b) __dmSub3(r,a,b) +#define dmPointSub(r,a,b) __dmSub3(r,a,b) +#define dmPointAddVector(r,a,b) __dmAdd3(r,a,b) + +#define dmVectorScale(r,a,b) __dmScale3(r,a,b) +#define dmPointScale(r,a,b) __dmScale3(r,a,b) +#define dmVectorScaleScalar(r,a,b) __dmScaleScalar3(r,a,b) +#define dmVectorRotQuat(r,v,q) __dmRotQuat3(r,v,q) +#define dmPointRotQuat(r,p,q) __dmRotQuat3(r,p,q) + +#define dmVectorRotEuler(r,v,e) __dmRotEuler3(r,v,e) +#define dmPointRotEuler(r,p,e) __dmRotEuler3(r,p,e) + + +extern void (dmVectorAdd)( dmVector r, + const dmVector a, + const dmVector b); + +extern void (dmVectorSub)( dmVector r, + const dmVector a, + const dmVector b); + +extern void (dmPointSub)( dmVector r, + const dmPoint a, + const dmPoint b); + +extern void (dmPointAddVector)( dmPoint r, + const dmPoint a, + const dmVector b); + +extern void (dmVectorScale)( dmVector r, + const dmVector a, + const dmScale b); + +extern void (dmVectorScaleScalar)( dmVector r, + const dmVector a, + float32 b); + +extern void (dmPointScale)( dmPoint r, + const dmPoint a, + const dmScale b); + +extern void (dmVectorRotQuat)( dmVector r, + const dmVector v, + const dmQuaternion); + +extern void (dmVectorRotEuler)( dmVector r, + const dmEuler e, + const dmVector v); + + +extern void (dmPointRotQuat)( dmPoint r, + const dmPoint p, + const dmQuaternion q); +extern void (dmPointRotEuler)( dmPoint r, + const dmPoint p, + const dmEuler e); + +extern void dmVectorXformMat( dmVector r, + const dmVector v, + const dmMatrix m); +extern void dmPointXformMat( dmPoint r, + const dmPoint v, + const dmMatrix m); + + + +/* + * Dead reckoning et al. Actually most of these functions only + * deal with zero order stuff. + */ + +#define dmPosFromMat(p,m) do { \ + dmMatCopy((p)->pos, m); \ + dmVectorIdent((p)->linearVel); \ + dmVectorIdent((p)->linearAccn); \ + dmVectorIdent((p)->angularVel); \ + dmVectorIdent((p)->angularAccn); \ +} while (0) + +#define dmPosFromPointEulerScale(p,p2,e,s) do { \ + dmMatFromPointEulerScale((p)->pos,(p2),(e),(s)); \ + dmVectorIdent((p)->linearVel); \ + dmVectorIdent((p)->linearAccn); \ + dmVectorIdent((p)->angularVel); \ + dmVectorIdent((p)->angularAccn); \ +}while(0) + +#define dmPosFromPointQuatScale(p,p2,q,s) do { \ + dmMatFromPointQuatScale((p)->pos,(p2),(q),(s)); \ + dmVectorIdent((p)->linearVel); \ + dmVectorIdent((p)->linearAccn); \ + dmVectorIdent((p)->angularVel); \ + dmVectorIdent((p)->angularAccn); \ +}while(0) + +extern void (dmPosFromMat)( dmPosition_Ptr p, + const dmMatrix m); +extern void (dmPosFromPointEulerScale)( dmPosition_Ptr p, + const dmPoint p2, + const dmEuler e, + const dmScale s); +extern void (dmPosFromPointQuatScale)( dmPosition_Ptr p, + const dmPoint p2, + const dmQuaternion q, + const dmScale s); + +extern void dmDeadReckon( dmMatrix m, + float32 time, + const dmPosition_Ptr pos); +/* + * + * given four points a, b, c, d defining two line segments AB and CD, + * generate a matrix m that will transform AB to CD. + * If the length of either line segment is zero, the results are undefined. + */ +extern void dmPointToPoint(dmMatrix m, + dmPoint a, + dmPoint b, + dmPoint c, + dmPoint d); + + + +/* + * version function + */ +extern void dmVersion(FILE *fp); + + + +#ifdef __cplusplus +} +#endif +#endif /*_DMTYPES_H */ diff --git a/MUNGA_L4/libDPL/dsys/DP.H b/MUNGA_L4/libDPL/dsys/DP.H new file mode 100644 index 0000000..efbe63d --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DP.H @@ -0,0 +1,47 @@ +/* + * PROJECT: dVS + * SUBSYSTEM: dp + * MODULE: dp.h + * + * + * File: $RCSfile: dp.h,v $ + * Revision: $Revision: 2.9 $ + * Date: $Date: 1995/05/18 09:36:22 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: dp.h,v 2.9 1995/05/18 09:36:22 jeff beta $ + * + * FUNCTION: + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, photocopied, + * reproduced, translated, or reduced to any electronic medium or + * machine readable form without prior written consent from Division + * Ltd. + */ + +#ifndef _DP_H +#define _DP_H 1 + +#ifdef _cplusplus +extern "C" { +#endif + +#if defined (_UNIX) +#include +#elif defined (_TRANSPUTER) || defined (_I860) +#include +#elif defined (_WIN31) +#include +#else +#error "Unknown processor type " +#endif + +#ifdef _cplusplus +} +#endif + +#endif /* _DP_H */ diff --git a/MUNGA_L4/libDPL/dsys/DS.H b/MUNGA_L4/libDPL/dsys/DS.H new file mode 100644 index 0000000..39e3619 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DS.H @@ -0,0 +1,48 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: ds.h,v $ + * REVISION: $Revision: 1.6 $ + * Date: $Date: 1995/05/18 09:39:38 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: ds.h,v 1.6 1995/05/18 09:39:38 jeff beta $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#ifndef _DS_H +#define _DS_H + +#ifdef __cplusplus +extern "C" { +#endif + +typedef struct +{ + char *string; +}DStringTraverseInfo; + +extern void dsVersion(FILE *fp); +char *dStringFromOptions (char *string, int *size, char *name, ...); +char *dStringFirstString (char *string, DStringTraverseInfo *info); +char *dStringNextOption (char *option, DStringTraverseInfo *info); + + +#define DS_END_OF_OPTIONS '\0' + + +#ifdef __cplusplus +} +#endif +#endif /*_DS_H */ diff --git a/MUNGA_L4/libDPL/dsys/DTCP.H b/MUNGA_L4/libDPL/dsys/DTCP.H new file mode 100644 index 0000000..1d1b2fb --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DTCP.H @@ -0,0 +1,165 @@ +/* + * PROJECT: dvs + * SUBSYSTEM: net + * MODULE: dtcp.h + * + * File: $RCSfile: dtcp.h,v $ + * Revision: $Revision: 1.3 $ + * Date: $Date: 1995/03/10 17:09:52 $ + * Author: $Author: john $ + * RCS Ident: $Id: dtcp.h,v 1.3 1995/03/10 17:09:52 john Exp $ + * + * FUNCTION: + * header file for host independant socket access. + * + * $Log: dtcp.h,v $ + * Revision 1.3 1995/03/10 17:09:52 john + * *** empty log message *** + * + * Revision 1.2 1995/01/13 16:09:46 jeff + * ci for new build system. + * + * Revision 1.1 1994/12/05 09:33:35 jeff + * First post-manager check in. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef __DTCP_H +#define __DTCP_H + +#include +#include +#include +#include +#ifdef _IRIX5 +#include +#endif +#include +#include +#include +#include +#include +#include +#include +#include +#include + +# ifdef __cplusplus +extern "C" { +# endif + + +#if defined ( _SYSV42) +#ifdef _DVS_AGENT +#define TCP_TLI + +#else +#define TCP_BSD +#endif +#else +#if defined (_HPUX) || defined (_IRIX) +#define TCP_BSD +#else +#error Undefined system type +#endif +#endif + +#ifdef TCP_TLI +#include +#include + +#define dsock_open dsock_tli_open +#define dsock_bind_listen dsock_tli_bind_listen +#define dsock_buffer_size dsock_tli_buffer_size +#define dsock_select_io dsock_tli_select_io +#define dsock_async_io dsock_tli_async_io +#define dsock_async_signal dsock_tli_async_signal +#define dsock_allow_broadcast dsock_tli_allow_broadcast +#define dsock_set_timeout dsock_tli_set_timeout +#define dsock_sendto dsock_tli_sendto +#define dsock_recvfrom dsock_tli_recvfrom +#define dsock_send dsock_tli_send +#define dsock_recv dsock_tli_recv +#define dsock_getFirst_socket dsock_tli_getFirst_socket +#define dsock_getNext_socket dsock_tli_getNext_socket +#define dsock_connect dsock_tli_connect +#define dsock_connect_addr dsock_tli_connect_addr +#define dsock_listen_accept dsock_tli_listen_accept +#define dsock_acceptClose dsock_tli_acceptClose +#define dsock_recvConnect dsock_tli_recvConnect +#define dsock_enableAsyncWrite dsock_tli_enableAsyncWrite +#define dsock_disableAsyncWrite dsock_tli_diableAsyncWrite +#define dsock_close dsock_tli_close +#define dsock_error dsock_tli_error +#define dsock_errno dsock_tli_errno +#endif + +#include + +#define DTCP_UDP 0x00000001 +#define DTCP_TCP 0x00000002 + +#define DTCP_INET 0x00000001 +#define DTCP_UNIX 0x00000002 + +#define DTCP_READ 1 +#define DTCP_WRITE 2 +#define DTCP_EXCEPTION 3 +#define DTCP_ERR 4 +#define DTCP_HUP 5 + +#define DTCP_LISTEN -2 +#define DTCP_CONNECT -3 +#define DTCP_DATA -4 +#define DTCP_EXDATA -5 +#define DTCP_DISCONNECT -6 +#define DTCP_ERROR -7 +#define DTCP_UDERR -8 +#define DTCP_ORDREL -9 +#define DTCP_TIMEOUT -10 + + +void dsockVersion(FILE *fp); +int dsock_open(int family, int type); +int dsock_bind_listen(int sock, int family, int inet_addr, short *port, int qlength); +int dsock_buffer_size(int sock, int bufferSize); +void dsock_select_io(int sock); +int dsock_async_io(int sock); +int dsock_async_signal(void); +int dsock_allow_broadcast (int sock); +void dsock_set_timeout(struct timeval *t); +int dsock_sendto (int sock, void *msg, int size, struct sockaddr_in *dst); +int dsock_recvfrom (int sock, void *msg, int size, struct sockaddr_in *from); +int dsock_send (int sock, void *msg, int size); +int dsock_recv (int sock, void *msg, int size); +int dsock_getFirst_socket (int *ioType); +int dsock_getNext_socket (int *ioType); +int dsock_connect(int sock, struct sockaddr_in *dst); +int dsock_connect_addr(int sock, int family, int inet_addr, short *port ); +int dsock_listen_accept(int sock, struct sockaddr_in *addr); +int dsock_acceptClose(int fd); +int dsock_recvConnect(int fd); +int dsock_enableAsyncWrite(int fd); +int dsock_disableAsyncWrite(int fd); +int dsock_close(int fd); + + +void dsock_error(char *string); +int32 dsock_flipWord(int32 value); +int16 dsock_flipShort(int16 value); + +extern int dsock_errno; + + +# ifdef __cplusplus +} +# endif +#endif /* DTCP_H */ diff --git a/MUNGA_L4/libDPL/dsys/DU.H b/MUNGA_L4/libDPL/dsys/DU.H new file mode 100644 index 0000000..e517b0b --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/DU.H @@ -0,0 +1,214 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: du + * MODULE: du.h + * + * File: $RCSfile: du.h,v $ + * Revision: $Revision: 2.17 $ + * Date: $Date: 1995/05/18 09:40:33 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: du.h,v 2.17 1995/05/18 09:40:33 jeff beta $ + * + * FUNCTION: + * external declarations of functions in the du library. + * + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DU_H +#define _DU_H + +#include + +#include + +#ifdef _WIN31 +#include +#define malloc farmalloc +#endif + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * searching fopen/searching flook functions. + */ + +#define SF_READ 1 +#define SF_WRITE 2 +#define SF_EXEC 4 +#define SF_EXIST 8 + +typedef enum { DU_PATH_SYSTEM, DU_PATH_USER, DU_PATH_OFFSET } duPathType; + +typedef struct duPathIterator +{ + void *entry; +} duPathIterator; + +extern void duVersion(FILE *fp); + +extern void *duConvertPathToTable(char *sysPath, + char *userPath, + char *offset); +extern void *duAddPathToTable(void *table, + char *path, + duPathType type); +extern FILE *duSearchingFopen(char *fileName, + void *pathList, + char **extensions, + char *mode, + char *fullPath, + int maxFullPathSize, + int *extensionIndex, + int absolute); +extern int duSearchingFlook(char *fileName, + void *pathList, + char **extensions, + int32 mode, + char *fullPath, + int maxFullPathSize, + int *extensionIndex, + int absolute); +char *duPathIterateInit(duPathIterator *iter, void *table); +char *duPathIterate(duPathIterator *iter); +void *duPathRemoveEntry(void *table, char *entry); +void duPathDelete(void *table); +void duSfSearchPath(char *searchPath); +void duSfSearchVariable(char *searchVariable); + +/* + * Functions for efficient allocation of many identically sized blocks. + */ + +/* + * many small chunks are allocated at once. One of these + * structures manages that. + */ +typedef struct duBlkAllocChunk duBlkAllocChunk; + +/* + * the block header. Contains house keeping info for the block allocator. + */ +typedef struct duBlkCtrl { + duBlkAllocChunk *freeChunks; /* Ptr to linked list of free blocks */ + void *freeList; /* Pointer to the free list */ + uint32 totalItems; /* Total number of block items */ + uint32 freeItems; /* Total number of free items */ + uint32 chunkSize; /* Number of items to alloc at once */ + uint32 itemAlign; /* Alignment of units in bytes. */ + uint32 itemSize; /* Size of items in bytes */ +} duBlkCtrl; +extern void duBlkAllocConstruct(duBlkCtrl *ctrlBlock, + uint32 is, + uint32 cs, + uint32 align); +typedef void* (*duAllocFunc)(uint32); +typedef void (*duFreeFunc)(void*); + +extern void duBlkAllocDestruct(duBlkCtrl *ctrlBlock, + duFreeFunc ffunc); +extern void *duBlkAlloc(duBlkCtrl *ctrlBlock, + duAllocFunc afunc); +extern void duBlkFree(duBlkCtrl *ctrlBlock, void *item); + +/* + * Functions to manipulate hash tables. + */ +typedef int32 (*duHfunc)(void *key, int32 size); +typedef int (*duCfunc)(void *a, void *b); +typedef struct duHashElem duHashElem; +typedef struct duHashTab duHashTab; + +/* + * the following is used if iterating over all the elements in a hash + * table. It keeps track of where in the table you are for use with the + * iteration functions. + */ +typedef struct duHashIterator { + duHashTab *h; + int32 bucket; + duHashElem *e; +} duHashIterator; + +extern void *duHashLookup (duHashTab *t, void *key); +extern void duHashInstall (duHashTab *t, void *key, void *datum); + +#define duHashRemove(t, key) duHashRemoveK((t), (key), NULL) +#define duHashRemoveK(t, key, old) duHashRemoveKDatum ((t), (key), NULL, (old) ) + +extern void *duHashRemoveKDatum (duHashTab *t, void *key, void *d, void **old_key); +extern duHashTab *duNewHashTab (int32 Size, duHfunc hashfun, + duCfunc cmpfun); +extern void duDeleteHashTab (duHashTab *t); + +#define duHashIterateInit(iter, t) \ + duHashIterateInitK(iter, t, NULL) + +#define duHashIterate(iter) \ + duHashIterateK(iter, NULL) + +extern void *duHashIterateInitK (duHashIterator *iter, duHashTab *t, + void **key); +extern void *duHashIterateK (duHashIterator *iter, void **key); + + + + +void __duVerboseStart(int level); +void __duDebugStart(int level, char *file, int line); +void __duVerboseMessage(char *format, ...); +uint32 duVerbose_SetLevel(uint32 level); +uint32 duVerbose_GetLevel(void) ; +uint32 duDebug_SetLevel(uint32 level); +uint32 duDebug_GetLevel(void); +FILE *duDebug_SetLogFile(FILE *, int mode); +char *duDebug_SetName(char *, int mode); +void duDebug_Quiet(void); +void duDebug_VeryQuiet(void); +void duDebug_Noisy(void); +void duWarn(char *format, ...); +void duError(char *format, ...); +void duFatal(char *format, ...); + +extern uint32 __duVerbose_level; +extern uint32 __duDebug_level; + +#define DU_DEBUG_DONT_OVERIDE 0 +#define DU_DEBUG_OVERIDE 1 + +#define duVerbose(x,y) do { \ + if (__duVerbose_level & (x)) \ + { \ + __duVerboseStart(x); \ + __duVerboseMessage y; \ + } \ + } while (0) + +#ifdef NDEBUG +#undef duDebug +#define duDebug(x,y) ((void)0) +#else +#undef duDebug +#define duDebug(x,y) do { \ + if (__duDebug_level & (x)) \ + { \ + __duDebugStart(x, __FILE__, __LINE__); \ + __duVerboseMessage y; \ + } \ + } while (0) +#endif + + +#ifdef __cplusplus +} +#endif +#endif /*_DU_H */ diff --git a/MUNGA_L4/libDPL/dsys/FILELIB.H b/MUNGA_L4/libDPL/dsys/FILELIB.H new file mode 100644 index 0000000..4f66386 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/FILELIB.H @@ -0,0 +1,315 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: filelib.h,v $ +-- Revision : $Revision: 1.9 $ +-- Date : $Date: 95/05/16 13:46:20 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __FILELIB_H__ +#define __FILELIB_H__ + +#include + +#ifndef _PFILE +#ifdef _PF_LOCAL +#include "pfile.h" +#else +#include +#endif +#endif + +/*****************************************************************************/ +/* filelib error numbers */ +#define dflENO_READ 0x2001 +#define dflENO_WRITE 0x2002 +#define dflENO_CPATH 0x2003 +#define dflENO_CNAME 0x2004 +#define dflENO_PERMIT 0x2005 +#define dflENO_DIR 0x2006 +#define dflENO_RMFILE 0x2007 +#define dflENO_RMDIR 0x2008 +#define dflENO_USAGE 0x2009 + +#define dfl_STDIN_NAME "stdin" +#define dfl_STDOUT_NAME "stdout" + +extern char *progname ; + +#define dfl_SET_TO_LITTLE 0 +#define dfl_SET_TO_BIG 1 + +#define dflPATHDIV '/' +#define dflREPPATHDIV '\\' + +#ifndef _UNIX +#define dflDRIVEDIV ':' +#endif + +/**************************************************************************** + * File reading and writing routines. + */ + +typedef struct dflFILETYPE +{ + char *name ; + FILE *fp ; + int32 endian ; + char *buf, *bufEnd; + int32 remain ; + int32 filePos, endPos ; +} dflFILE, *dflFILEPTR ; + +#define dfl_BUFFER_SIZE 8192 + +void +dflSetEndian(dflFILEPTR file, int32 OutEndian) ; +dflFILEPTR +dflOpen(char *name, char *mode, int32 OutEndian) ; +int32 +dflClose(dflFILEPTR file) ; + +/**************************************************************************** + * File reading routines + */ +int32 +dflSeek(dflFILEPTR fl, int32 offset, int32 whence) ; +int32 +dflUngetc(char c, dflFILEPTR fl); +int32 +_dflGetc(dflFILEPTR fl) ; +int32 +_dflRead(void *ptr, int32 size, dflFILEPTR fl) ; + +#define dflTell(fl) ((fl)->filePos - (fl)->remain) +#define dflGetc(fl) \ + (((fl)->remain) ? \ + ((int32) *((fl)->bufEnd - ((fl)->remain)--)) : \ + _dflGetc(fl)) +#define dflRead(ptr,size,fl) \ + (((fl)->remain >= (size)) ? \ + ( memcpy((ptr),((fl)->bufEnd - (fl)->remain),(size)) , \ + (fl)->remain -= (size), (int32) dpgSUCCESS) : \ + _dflRead(ptr,size,fl)) + +#define dflError(fl) ((int32) ferror(fl->fp)) + + +int32 +dflRead1byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn1byte(dflFILEPTR fl, int32 n, void *dest) ; +int32 +dflRead2byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn2byte(dflFILEPTR fl, int32 n, void *dest) ; +int32 +dflRead4byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn4byte(dflFILEPTR fl, int32 n, void *dest) ; +int32 +dflRead8byte(dflFILEPTR fl, void *dest) ; +int32 +dflReadn8byte(dflFILEPTR fl, int32 n, void *dest) ; + +/**************************************************************************** + * File writing routines + */ + +void +dflWriteint8(dflFILEPTR fl, int8 i) ; +void +dflWriteuint8(dflFILEPTR fl, uint8 i) ; +void +dflWriteint16(dflFILEPTR fl, int16 i) ; +void +dflWriteuint16(dflFILEPTR fl, uint16 i) ; +void +dflWriteint32(dflFILEPTR fl, int32 i) ; +void +dflWritefloat32(dflFILEPTR fl, float32 f) ; +void +dflWritefloat64(dflFILEPTR fl, float64 f) ; +void +dflWritestr(dflFILEPTR fl, void *source, int32 size) ; + + +/*************************************************************************** + * File name manipulation routines + * + * Major re-write on 11/2/95 due to the introduction of material files. This + * led to the need of hierarchical break down of files from all geometry + * converters (i.e. dxf2vdi). As they all use the same structure the routines + * have been placed into this library. + */ +/***************************************************************************** +* PLEASE NOTE:- These file name manipulation routines expect unix style * +* names, even on dos, a simple call to dflFormatName should * +* solve any potential problems. * +*****************************************************************************/ + +/**************************************************************************** + * dflFormatName + * + * Converts all file names to unix style, i.e. all '\\' to '/' + * Should be called for every file name! + */ +void +dflFormatName(char *name) ; + +/**************************************************************************** + * dflSplitName - splits the given file name into is 3 constituent parts. + * If path, body or ext are NULL, no problems, that part isn't done. + * returns dymanically allocated strings, the path will have the closing + * '/' and neither the body ext will have the dividing '.' + */ +void +dflSplitName(char *FName, char **path, char **body, char **ext) ; + +/***************************************************************************** + * dflComposeName - Opposite to SplitName, i.e. given the 3 parts, it joins + * them together. Any of them can be NULL. If the body starts with a '/' then + * the path is ignored. if the path doesnt end with a '/' then one is inserted + * if the extension is NULL or "" then no '.' is inserted at the end of body. + */ +char * +dflComposeName(char *path, char *body, char *ext) ; + +/**************************************************************************** + * dflCreateName - same as dflComposeName, only excepts 3 paths and joins + * them together, any can be NULL. + */ +char * +dflCreateName(char *basePath, char *midPath, char *extPath, + char *base, char *ext) ; + +/*************************************************************************** + * dflBackupName - Checks for existance of the file 'filename', if it exists, + * it creates a backup filename 'BackName' by either inserting the + * "division.sav" directory into the path, or if the environment variable + * ${division.sav} is set then it is asumed to be the absolute output path + * and the base name of 'filename' is appended. If the file 'BackName' exists + * then it is removed, and 'filename' is moved to 'BackName'. + * + * Returns -1 if an error occured or the number of paths created. + * 'BackName is a dynamically allocated string which must be freed be the + * user + */ +int32 +dflBackupName(char *filename, char **Backup) ; + +/**************************************************************************** + * dflRemoveBackup - removes everything generated from a call to dflBackupName + * Requires the return value to determine how many directories are to be + * removed. If backing up 2 or more files it is important to Remove the backup + * in an reversed order, soley because the first one will have created any + * required directies and its return value will be non zero, these directies + * can only be removed after all the the backup files have been removed. + * returns dpgERROR if failed to remove something, else returns dpgSUCCESS + */ +int32 +dflRemoveBackup(char *backName, int32 noDirs) ; + +/**************************************************************************** + * dflTempName - Creates a temporary file name based on the given file name. + * returns NULL on failure, dynamically allocated string otherwise. + */ +char * +dflTempName(char *fname) ; + +#define dflUSEMID 0x01 +#define dflASCII 0x02 +#define dflLIBRARY 0x04 +char * +dflCreateVtxName(char *basePath, int32 useMid, char *extPath, char *base) ; +char * +dflCreateBgfName(char *basePath, int32 useMid, char *extPath, char *base, + dpfFILETYPE OutMode) ; +char * +dflCreateBmfName(char *basePath, int32 useMid, char *extPath, char *base, + dpfFILETYPE OutMode, int libOut) ; +char * +dflCreateVdiName(char *basePath, int32 useMid, char *extPath, char *base, + int libOut) ; + +/************************************************************************** + * Create Path + * creates a single path given the path string, last path must terminate in + * a '/' else it will not be tested for. + * + * Return -1 on an error (dpgERROR), else the number of directories created. + */ +int32 +dflCreatePath(char *path) ; +/************************************************************************** + * dflCreatePaths - Sets up the division path structure given the base and + * extended paths and whether to use mid paths, all required + * paths are created, which includes material, geometry, texture, vdifiles + * and the vdi library path. + */ +int32 +dflCreatePaths(char *basePath, int32 useMid, char *extPath) ; + +/************************************************************************ + * dflCreateBaseName + * creates a base name (bit between the path and the extension) ready + * for a Compose or CreateName. if the numb is less than zero, it is + * ignored, if dosName is non-zero then the output name will be no long + * than 8 chars. + */ +char * +dflCreateBaseName(char *base, int32 numb, int32 dosName) ; + + +#define byte8_flip(p) do { \ + char ___t; \ + ___t=p[0]; \ + p[0]=p[7]; \ + p[7]=___t; \ + ___t=p[1]; \ + p[1]=p[6]; \ + p[6]=___t; \ + ___t=p[2]; \ + p[2]=p[5]; \ + p[5]=___t; \ + ___t=p[3]; \ + p[3]=p[4]; \ + p[4]=___t; \ +} while (0) + +#define byte4_flip(p) do { \ + char ___t; \ + ___t=p[0]; \ + p[0]=p[3]; \ + p[3]=___t; \ + ___t=p[1]; \ + p[1]=p[2]; \ + p[2]=___t; \ +} while (0) + +#define byte2_flip(p) do { \ + char ___t; \ + ___t=p[0]; \ + p[0]=p[1]; \ + p[1]=___t; \ +} while (0) + + +#endif /* __FILELIB_H__ */ + diff --git a/MUNGA_L4/libDPL/dsys/GETPARAM.H b/MUNGA_L4/libDPL/dsys/GETPARAM.H new file mode 100644 index 0000000..1fa78af --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/GETPARAM.H @@ -0,0 +1,73 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: getparam.h,v $ +-- Revision : $Revision: 1.6 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __GETPARAM_H__ +#define __GETPARAM_H__ + +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +/*****************************************************************************/ +/* getparam error numbers */ +#define dgpENO_STREXP 0x3001 +#define dgpENO_UNKOPT 0x3002 +#define dgpENO_USAGE 0x3003 +#define dgpENO_RSRCF 0x3004 + +/**************************************************************************** + * getparam monitor numbers */ +#define dgpMON_OPTIONS 0x00001000 +#define dgpMON_FILES 0x00002000 + + +#define dgp_END 0 +#define dgp_NO_STR 1 +#define dgp_D_STR 2 +#define dgp_DJOIN_STR 3 +#define dgp_DAFTER_STR 4 +#define dgp_DBOTH_STR 5 +#define dgp_O_STR 6 +#define dgp_OJOIN_STR 7 +#define dgp_OAFTER_STR 8 +#define dgp_OBOTH_STR 9 + +typedef struct { + char optname[15] ; + int32 opttype ; + int32 optreturn ; +} dgpTABLE, *dgpTABLEPTR ; + +extern char *progname ; + +int32 +dgpGetopt(int32 argc, char *argv[], dgpTABLEPTR table, + int32 *NoFiles, char **files[], char **str1, char **str2) ; + +void +dgpFreeFiles(int32 NoFiles, char *files[]) ; + +#endif /* __GETPARAM_H__ */ diff --git a/MUNGA_L4/libDPL/dsys/MAPFILE.H b/MUNGA_L4/libDPL/dsys/MAPFILE.H new file mode 100644 index 0000000..fe4a62c --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/MAPFILE.H @@ -0,0 +1,99 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1994 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: mapfile.h,v $ +-- Revision : $Revision: 1.3 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __MAPFILE_H__ +#define __MAPFILE_H__ + +#ifdef _PF_LOCAL +#include "ptool.h" +#else +#include +#endif + +/* Error Numbers */ +#define dmpENO_OPEN 0x50001 +#define dmpENO_FORM 0x50002 + +typedef struct dmpMATFILETYPE +{ + char *name ; + dpfFILEPTR file ; + struct dmpMATFILETYPE *next ; +} dmpMATFILE, *dmpMATFILEPTR ; + +typedef struct dmpBLOCKTYPE +{ + char *name ; + int32 ignore ; + struct dmpBLOCKTYPE *next ; +} dmpBLOCK, *dmpBLOCKPTR ; + +typedef struct dmpMAPPINGTYPE +{ + char *from, *to ; + int32 gotMat ; + int32 gotText ; + dptTEXTURE text ; + struct dmpMAPPINGTYPE *next ; +} dmpMAPPING, *dmpMAPPINGPTR ; + +typedef struct +{ + dmpMATFILEPTR materials ; + dmpMAPPINGPTR mappings ; + dmpBLOCKPTR blocks ; +} dmpFILE, *dmpFILEPTR ; + +dmpFILEPTR +dmpCreateFile(void) ; +dmpMATFILEPTR +dmpCreateMatFile(void) ; +int32 +dmpAddMatFile(dmpFILEPTR mp, dmpMATFILEPTR mat) ; +dmpBLOCKPTR +dmpCreateBlock(void) ; +int32 +dmpAddBlock(dmpFILEPTR mp, dmpBLOCKPTR blk) ; +dmpMAPPINGPTR +dmpCreateMapping(void) ; +int32 +dmpAddMapping(dmpFILEPTR mp, dmpMAPPINGPTR map) ; +void +dmpFreeFile(dmpFILEPTR mp) ; +dmpMAPPINGPTR +dmpFindMapping(dmpFILEPTR mp, char *name) ; +dpfMATERIALPTR +dmpFindMaterial(dmpFILEPTR mp, char *name) ; +dpfTEXTUREPTR +dmpFindTexture(dmpFILEPTR mp, char *name) ; +dmpBLOCKPTR +dmpFindBlock(dmpFILEPTR mp, char *name) ; + +int32 +dmpGetMapFile(dmpFILEPTR mp, char *fileName) ; +int32 +dmpSaveFile(char *name, dmpFILEPTR file) ; + + +#endif /* __MAPFILE */ diff --git a/MUNGA_L4/libDPL/dsys/PARSER.H b/MUNGA_L4/libDPL/dsys/PARSER.H new file mode 100644 index 0000000..c531ec2 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/PARSER.H @@ -0,0 +1,122 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: parser.h,v $ + * REVISION: $Revision: 1.8 $ + * Date: $Date: 1995/05/18 09:41:31 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: parser.h,v 1.8 1995/05/18 09:41:31 jeff beta $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _PARSER_H +#define _PARSER_H + +#ifdef __cplusplus +extern "C" { +#endif +#define PARSER_MAX_TOKEN_SIZE 2048 +#define PARSER_MATCH_CASE 0 +#define PARSER_ANY_CASE 1 + +/* + * macros for testing char classes + */ +#define PARSER_LEX_START 1 +#define PARSER_LEX_CONTINUE 2 +#define parserStartChar(f,x) ((f)->LexClass[(x)] & PARSER_LEX_START ) +#define parserContinueChar(f,x) ((f)->LexClass[(x)] & PARSER_LEX_CONTINUE ) + +/* + * tokens returned by parser functions + */ +#define PARSER_OK 0 +#define PARSER_ERR -1 +#define PARSER_EOF -2 +#define PARSER_STRING -3 +#define PARSER_INT -4 +#define PARSER_FLOAT -5 +#define PARSER_PUSH -6 +#define PARSER_POP -7 +#define PARSER_QUOTED_STRING -8 + +/* + * used to hold pre-processing state info. + * Contents are not made public. + */ +typedef struct pprocState pprocState; + +typedef struct dParseKeyTab +{ + int tok; + char *name; + int matchCase; +} dParseKeyTab; + + +typedef struct dParseFile +{ + int errorFlag; + int seeIncludes; + int pushedBackToken; + float fpNumber; + long iNumber; + char *buffer; + int bufSize; + int bufPos; + dParseKeyTab *keyTab; + int charNo; + pprocState *ppstate; + char LexClass[128]; +} dParseFile, *dParseFilePtr; + +extern void parserVersion(FILE *openfp); +extern dParseFilePtr parserCreate(char *name, + FILE *openfp, + dParseKeyTab *keyTable, + int bufferSize, + FILE *(*fileFinder)(const char *), + const char *startChars, + const char *continueChars, + int seeIncludes); +extern void parserDestroy(dParseFilePtr fptr); + +extern dParseFilePtr parserOpenFile(char *name, + FILE *fp, + dParseKeyTab *keyTable, + int bufferSize, + FILE *(*fileFinder)(const char *), + const char *startChars, + const char *continueChars, + int seeIncludes); +extern void parserCloseFile(dParseFilePtr fPtr); + +extern int parserGetc(dParseFilePtr fptr); +extern int parserUngetc(dParseFilePtr fptr, char c); + +extern char *parserTokenToString(dParseFilePtr fptr, const int token); +extern int parserPushToken(dParseFilePtr fptr, const int token); +extern int parserNextToken(dParseFilePtr fptr); + +extern char *parserMatchString(dParseFilePtr fptr); +extern int parserMatchInt(dParseFilePtr fptr, int *num); +extern int parserMatchFloat(dParseFilePtr fptr, float *num); +extern int parserMatchCharacter(dParseFilePtr fptr, char c); + +extern const char *parserCurrentFile(dParseFilePtr fptr); +extern int parserCurrentLine(dParseFilePtr fptr); +#ifdef __cplusplus +} +#endif +#endif diff --git a/MUNGA_L4/libDPL/dsys/PFBIZTAG.H b/MUNGA_L4/libDPL/dsys/PFBIZTAG.H new file mode 100644 index 0000000..8893a2c --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/PFBIZTAG.H @@ -0,0 +1,197 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * File: $RCSfile: pfbiztag.h,v $ + * Revision: $Revision: 1.13 $ + * Date: $Date: 1995/10/06 10:47:30 $ + * Author: $Author: bill $ + * RCS Ident: $Id: pfbiztag.h,v 1.13 1995/10/06 10:47:30 bill Exp $ + * + * FUNCTION: + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef __PFBIZTAG_H__ +#define __PFBIZTAG_H__ + +#ifdef __cplusplus +extern "C" { +#endif + +/* PUBLIC DEFINES =======================================*/ +/* Biz v1.0 tag defines */ +#define dpf_BIZ_PATCH 34 +#define dpf_BIZ_STRIP 35 +#define dpf_BIZ_TRISTRIP 0 +#define dpf_BIZ_POLYSTRIP 1 +#define dpf_BIZ_DONE 37 + +/* Biz v2.x tag defines */ +#define dpfB_0_COMMENT_TAG 0x0000 +#define dpfB_HEADER_TAG 0x0003 +#define dpfB_PROPAGATED_COMMENT_TAG 0x0004 +#define dpfB_BIZ_DONE 0x0005 +#define dpfB_TEXTURE_TAG 0x0010 +#define dpfB_TEXTURE_MAP_TAG 0x0011 +#define dpfB_TEXTURE_MINIFY_TAG 0x0012 +#define dpfB_TEXTURE_MAGNIFY_TAG 0x0013 +#define dpfB_TEXTURE_ALPHA_TAG 0x0014 +#define dpfB_TEXTURE_WRAP_U_TAG 0x0015 +#define dpfB_TEXTURE_WRAP_V_TAG 0x0016 +#define dpfB_TEXTURE_DETAIL_TAG 0x0017 +#define dpfB_TEXTURE_BITSLICE_TAG 0x0018 +#define dpfB_MATERIAL_TAG 0x0020 +#define dpfB_MATERIAL_TEXTURE_TAG 0x0021 +#define dpfB_MATERIAL_ENVIRONMENT_TAG 0x0022 +#define dpfB_MATERIAL_AMBIENT_TAG 0x0023 +#define dpfB_MATERIAL_DIFFUSE_TAG 0x0024 +#define dpfB_MATERIAL_SPECULAR_TAG 0x0025 +#define dpfB_MATERIAL_EMISSIVE_TAG 0x0026 +#define dpfB_MATERIAL_OPACITY_TAG 0x0027 +#define dpfB_MATERIAL_RAMP_TAG 0x0028 +#define dpfB_RAMP_TAG 0x0030 +#define dpfB_RAMP_DATA_TAG 0x0031 +#define dpfB_OBJECT_TAG 0x0040 +#define dpfB_LOD_TAG 0x0041 +#define dpfB_PATCH_TAG 0x0042 +#define dpfB_POLYGON_TAG 0x0043 +#define dpfB_TRISTRIP_TAG 0x0044 +#define dpfB_POLYSTRIP_TAG 0x0045 +#define dpfB_PMESH_TAG 0x0046 +#define dpfB_CONNECTION_LIST_TAG 0x0047 +#define dpfB_SPHERE_LIST_TAG 0x0048 +#define dpfB_SPHERE_TAG 0x0049 +#define dpfB_LINE_TAG 0x004a +#define dpfB_TEXT_TAG 0x004b +#define dpfB_TEXT_STRING_TAG 0x004c +#define dpfB_PCONN_LIST_TAG 0x004d +#define dpfB_PSTRIP_LIST_TAG 0x004e +#define dpfB_POINT_LIST_TAG 0x0050 + +#define dpfB_BOUND_TAG 0x0070 +#define dpfB_BBOX_TAG 0x0071 +#define dpfB_BSPHERE_TAG 0x0072 + +#define dpfB_LINE_NODE_TAG 0x0080 +#define dpfB_VERTEX_XYZ_TAG 0x0080 +#define dpfB_VERTEX_XYZ_N_TAG 0x0081 +#define dpfB_VERTEX_XYZ_RGBA_TAG 0x0082 +#define dpfB_VERTEX_XYZ_UV_TAG 0x0088 +#define dpfB_VERTEX_XYZ_N_UV_TAG 0x0089 +#define dpfB_VERTEX_XYZ_RGBA_UV_TAG 0x008A + +#define dpfB_2_COMMENT_TAG 0x2000 +#define dpfB_VERSION_TAG 0x2002 +#define dpfB_DATE_TAG 0x2003 +#define dpfB_TIME_TAG 0x2004 +#define dpfB_SCALE_TAG 0x2005 +#define dpfB_PRECISION_TAG 0x2006 +#define dpfB_FILETYPE_TAG 0x2007 +#define dpfB_SV_NAME_TAG 0x2008 +#define dpfB_MATERIAL_NAME_TAG 0x2008 +#define dpfB_RAMP_NAME_TAG 0x2008 +#define dpfB_TEXTURE_NAME_TAG 0x2008 +#define dpfB_UNIT_TAG 0x2009 +#define dpfB_SCOPE_TAG 0x200a +#define dpfB_SV_F_MATERIAL_TAG 0x2030 +#define dpfB_SV_B_MATERIAL_TAG 0x2031 +#define dpfB_SV_PLANE_TAG 0x2032 +#define dpfB_SV_DRAW_MODE_TAG 0x2033 +#define dpfB_SV_DECAL_TAG 0x2034 +#define dpfB_SV_FACETED_TAG 0x2035 +#define dpfB_SV_VERTEX_TAG 0x2036 +#define dpfB_SV_SPECIAL_TAG 0x2037 +#define dpfB_SV_LOCK_TAG 0x2039 +#define dpfB_SPHERE_DICE_V_TAG 0x2040 +#define dpfB_SPHERE_DICE_U_TAG 0x2041 +#define dpfB_LINE_THICKNESS_TAG 0x2042 +#define dpfB_TEXT_FONT_TAG 0x2043 +#define dpfB_TEXT_SCALE_TAG 0x2044 +#define dpfB_TEXT_ORIENTATION_TAG 0x2045 + +#define dpfB_LOD_DISTANCE_TAG 0x2046 +#define dpfB_LOD_REFERENCE_TAG 0x2047 +#define dpfB_LOD_TRANSITION_TAG 0x2048 + +#define dpfB_POINT_SIZE_TAG 0x2049 + +#define dpfB_BAUTO_TAG 0x2070 +#define dpfB_BLODNAME_TAG 0x2071 +#define dpfB_BOBJNAME_TAG 0x2072 + +#define dpfB_NO_DEF_TAGS 256 +#define dpfB_NO_CON_TAGS 256 + +#define dpfValidTag(tag) \ + ((((tag) & 0x1fff) > 0x00ff) ? 0 : \ + ((tag) & 0x2000) ? dpfB_CON_TAG_INFO[(tag) & 0x00ff] : \ + dpfB_DEF_TAG_INFO[(tag) & 0x00ff] ) + +/* PUBLIC TYPES =========================================*/ + + +/* PUBLIC VARIABLES ======================================*/ + + +extern uint8 dpfB_DEF_TAG_INFO[dpfB_NO_DEF_TAGS] ; +extern uint8 dpfB_CON_TAG_INFO[dpfB_NO_DEF_TAGS] ; + + +#ifdef _dpf_INCLUDE_BIZ_TABLE + +uint8 dpfB_DEF_TAG_INFO[dpfB_NO_DEF_TAGS] = { + 1, 1, 1, 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 3, 3, 3, 3, 3, 3, 3, 3, 1, 3, 3, 1, 3, 3, 0, + 3, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 3, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 1, 0, 0, 0, 1, 1, 1, 0, 1, 0, 0, 0, + 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +} ; +uint8 dpfB_CON_TAG_INFO[dpfB_NO_DEF_TAGS] = { + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 1, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, +} ; + +#endif + +/* PUBLIC FUNCTIONS ======================================*/ + + +#ifdef __cplusplus +} +#endif + +#endif /*__PFBIZTAG_H__ */ diff --git a/MUNGA_L4/libDPL/dsys/PFILE.H b/MUNGA_L4/libDPL/dsys/PFILE.H new file mode 100644 index 0000000..7915812 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/PFILE.H @@ -0,0 +1,1166 @@ +/**************************************************************************** + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: pfile.h,v $ + * Revision : $Revision: 1.15 $ + * Date : $Date: 95/05/16 13:46:35 $ + * Author : $Author: bill $ + * Last Modified : <110595.1427> + * + * Description + * + * Notes + * + * History + * + * $Log: pfile.h,v $ + * Revision 1.15 95/05/16 13:46:35 bill + * Added 1) dos. 2) STRIP_LIST. 3) POINTLIST. 4) biz->bgf + * + * Revision 1.14 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * + **************************************************************************** + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + ****************************************************************************/ + +#ifndef __PFILE_H__ +#define __PFILE_H__ + +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +#include + +/*****************************************************************************/ +/* pfile error numbers */ +#define dpfENO_ROPEN 0x8001 +#define dpfENO_READ 0x8002 +#define dpfENO_WOPEN 0x8003 +#define dpfENO_WRITE 0x8004 +#define dpfENO_CLOSE 0x8005 +#define dpfENO_FORM 0x8006 +#define dpfENO_VALUE 0x8007 +#define dpfENO_USAGE 0x8008 +#define dpfENO_NULL 0x8009 +#define dpfENO_CONV 0x800A + +/*****************************************************************************/ +/* pfile warning levels */ +#define dpfWARN_BADFILE 2 +#define dpfWARN_PROBLEM 3 +/*****************************************************************************/ +/* pfile monitor flags */ +#define dpfMON_READ 0x00100000 +#define dpfMON_WRITE 0x00200000 + +/*****************************************************************************/ +/* Useful constants */ +#define dpf_ALLOW_B2Z 1 +#define dpf_ALLOW_BMF 2 +#define dpf_ALLOW_ALL 3 + +/* max min ranges for types */ +#define dpfRGB_MAX (float32) 1.0 +#define dpfRGB_MIN (float32) 0.0 +#define dpfALPHA_MAX (float32) 1.0 +#define dpfALPHA_MIN (float32) 0.0 +#define dpfV1POWER_MAX (float32) 32.0 +#define dpfV1POWER_MIN (float32) 1.0 +#define dpfV2POWER_MAX (float32) 128.0 +#define dpfV2POWER_MIN (float32) 1.0 +#define dpfOPACITY_MAX (float32) 1.0 +#define dpfOPACITY_MIN (float32) 0.0 +#define dpfDICE_MAX 65565 +#define dpfDICE_MIN 3 +#define dpfDICE_DETER 0 +#define dpfTHICK_MAX 255 +#define dpfTHICK_MIN 1 + +/*****************************************************************************/ +/* Different vertex types */ +#define dpf_VERT_NONE (uint8) 0x0000 +#define dpf_VERT_NORMALS (uint8) 0x0001 +#define dpf_VERT_RGBA (uint8) 0x0002 +#define dpf_VERT_LUMINANCE (uint8) 0x0004 +#define dpf_VERT_TEXTURE (uint8) 0x0008 +#define dpf_VERT_THREED_TEXTURE (uint8) 0x0010 + +/*****************************************************************************/ +/* Different Geometry Types */ +#define dpf_GEOM_UNDEFINED (int32) 0x0000 +#define dpf_GEOM_POLYGON (int32) 0x0043 +#define dpf_GEOM_TRISTRIP (int32) 0x0044 +#define dpf_GEOM_POLYSTRIP (int32) 0x0045 +#define dpf_GEOM_PMESH (int32) 0x0046 +#define dpf_GEOM_SPHERE (int32) 0x0048 +#define dpf_GEOM_LINE (int32) 0x004A +#define dpf_GEOM_TEXT (int32) 0x004B +#define dpf_GEOM_POINT (int32) 0x0050 + +/*****************************************************************************/ +/* Unit conversion scaling factors */ +#define dpfINCHtoMM 25.4 +#define dpfMMtoINCH (1.0/dpfINCHtoMM) +#define dpfINCHtoM 0.0254 +#define dpfMtoINCH (1.0/dpfINCHtoM) + +/*****************************************************************************/ +/* types. */ +/* must never have double precision without global changes */ +/* +#define dpf_DOUBLE_PRECISION +*/ + +typedef enum +{ /* used for indexing arrays, identifying axies etc etc */ + dpf_PITCH = 0, dpf_YAW = 1, dpf_ROLL = 2, + dpfERGBA = 4, dpf_R = 0, dpf_G = 1, dpf_B = 2, + dpf_A = 3, dpf_POWER=3, dpf_LUM = 0, + dpfETEXT = 2, dpf_U = 0, dpf_V = 1, + dpfETHREEDTEXT = 3 +} coord; + +typedef int32 dpfIVECTOR[3] ; /* Generic 4 elem vector. */ +typedef float32 dpfRGBA[dpfERGBA]; +typedef float32 dpfTEXT[dpfETEXT] ; +typedef float32 dpfTHREEDTEXT[dpfETHREEDTEXT] ; + +typedef enum {dpf_B2Z_FILE, dpf_V2Z_FILE, + dpf_VIZ_FILE, dpf_BIZ_FILE, + dpf_UNKNOWN_FILE } dpfFILETYPE; + +typedef enum {dpf_FILE_GEOMETRY=0, dpf_FILE_MATERIAL=1 } dpfFILEFORMAT; + +typedef enum {dpfREAD, dpfWRITE} dpfFILEMODE; + +/* New enumerated types */ +typedef enum { dpf_MIN_DEFAULT=0, dpf_MIN_POINT_SAMPLED=1, + dpf_MIN_BILINEAR=2, dpf_MIN_TRILINEAR=3, + dpf_MIN_MIP_MAP_LINEAR=4, dpf_MIN_MIP_MAP_BILINEAR=5, + dpf_MIN_MIP_MAP_TRILINEAR=6, dpf_MIN_MIP_MAP_QUADLINEAR=7, + dpf_MIN_MIP_MAP_POINT_SAMPLED=8 } dpfMINIFY; +typedef enum { dpf_MAG_DEFAULT=0, dpf_MAG_POINT_SAMPLED=1, + dpf_MAG_BILINEAR=2, dpf_MAG_TRILINEAR=3, + dpf_MAG_BICUBIC=4, dpf_MAG_SHARPEN=5 } dpfMAGNIFY; +typedef enum { dpf_ALPHA_BLEND=0, dpf_ALPHA_CUT=1, + dpf_ALPHA_BLEND_CUT=2 } dpfALPHA ; +typedef enum { dpf_WRAP_REPEAT=0, dpf_WRAP_CLAMP=1, dpf_WRAP_SELECT=2 } dpfWRAP ; +typedef enum { dpf_DETAIL_NONE=0, dpf_DETAIL_ADD=1, + dpf_DETAIL_MODULATE=2 } dpfDETAIL ; +typedef enum { dpf_TRANS_SNAP=0, dpf_TRANS_BLEND=1 } dpfTRANSITION ; +typedef enum { dpf_MAT_NONE=0, dpf_MAT_NAMED=1, + dpf_MAT_DEFAULT=2, dpf_MAT_F_MATERIAL=3 } dpfMATTYPE ; +typedef enum { dpf_MATTXT_NONE=0, dpf_MATTXT_DEFAULT=1, + dpf_MATTXT_NAMED=2 } dpfMATTXTTYPE ; +typedef enum { dpf_PLANE_NORMAL=0, dpf_PLANE_UNDERLAY=1, + dpf_PLANE_OVERLAY=2 } dpfPLANE ; +typedef enum { dpf_FACET_NONE=0, dpf_FACET_BACKFACE=1, + dpf_FACET_FRONTFACE=2, dpf_FACET_TWOFACED=3 } dpfFACET ; +typedef enum { dpf_DM_FILLED=0, dpf_DM_WIREFRAME=1, dpf_DM_DOTTED=2 } dpfDRAWMODE ; +typedef enum { dpf_PREC_SINGLE=0, dpf_PREC_DOUBLE=1 } dpfPRECISION ; +typedef enum { dpf_UNIT_INCH=0, dpf_UNIT_METRE=1 } dpfUNIT ; +typedef enum { dpf_FONT_QUICK=0, dpf_FONT_BITMAP=1, dpf_FONT_VECTOR=2, + dpf_FONT_POLY_2D=3, dpf_FONT_POLY_3D=4, dpf_FONT_TEXTURE=5 } dpfFONT ; +typedef enum { dpf_AUTO_OFF=0, dpf_AUTO_ON=1 } dpfAUTO ; +typedef enum { dpf_LOCK_OFF=0, dpf_LOCK_ON=1 } dpfLOCK ; + +struct dpfSTRINGTYPE ; +typedef struct dpfSTRINGTYPE *dpfSTRINGPTR ; + +struct dpfSURFACETYPE ; +typedef struct dpfSURFACETYPE *dpfSURFACEPTR; + +struct dpfBOUNDTYPE ; +typedef struct dpfBOUNDTYPE *dpfBOUNDPTR ; + +struct dpfTEXTURETYPE ; +typedef struct dpfTEXTURETYPE *dpfTEXTUREPTR ; + +struct dpfRAMPTYPE ; +typedef struct dpfRAMPTYPE *dpfRAMPPTR ; + +struct dpfMATERIALTYPE ; +typedef struct dpfMATERIALTYPE *dpfMATERIALPTR ; + +struct dpfVERTEXTYPE ; +typedef struct dpfVERTEXTYPE *dpfVERTEXPTR ; + +struct dpfSLISTTYPE; +typedef struct dpfSLISTTYPE *dpfSLISTPTR ; + +struct dpfCLISTTYPE; +typedef struct dpfCLISTTYPE *dpfCLISTPTR ; + +struct dpfSPHERENODETYPE ; +typedef struct dpfSPHERENODETYPE *dpfSPHERENODEPTR ; + +struct dpfTEXTNODETYPE ; +typedef struct dpfTEXTNODETYPE *dpfTEXTNODEPTR ; + +struct dpfPOLYGONTYPE ; +typedef struct dpfPOLYGONTYPE *dpfPOLYGONPTR ; + +struct dpfGEOMETRYTYPE ; +typedef struct dpfGEOMETRYTYPE *dpfGEOMETRYPTR ; + +struct dpfPATCHTYPE ; +typedef struct dpfPATCHTYPE *dpfPATCHPTR ; + +struct dpfLODTYPE ; +typedef struct dpfLODTYPE *dpfLODPTR ; + +struct dpfOBJECTTYPE ; +typedef struct dpfOBJECTTYPE *dpfOBJECTPTR ; + +struct dpfHEADERTYPE ; +typedef struct dpfHEADERTYPE *dpfHEADERPTR ; + +struct dpfFILE_TYPE ; +typedef struct dpfFILE_TYPE *dpfFILEPTR ; + +/* ptools declaration */ + +struct dptTRIANGLETYPE ; +typedef struct dptTRIANGLETYPE *dptTRIANGLEPTR ; +struct dptMESHTYPE ; +typedef struct dptMESHTYPE *dptMESHPTR ; + +/*****************************************************************************/ +/* Externally callable Functions. */ +/*****************************************************************************/ +/* Useful macros */ + +#define dpfRGBCmp(a,b) memcmp(a, b, sizeof(float32)*3) +#define dpfRGBACmp(a,b) memcmp(a, b, sizeof(dpfRGBA)) +#define dpfTextCmp(a,b) memcmp(a, b, sizeof(float32)*2) +#define dpfRGBACpy(a,b) memcpy(a, b, sizeof(dpfRGBA)) +#define dpfTextCpy(a,b) memcpy(a, b, sizeof(dpfTEXT)) + +#define dpfBadFloat(f) (((*(long *)&(f) & 0x7f800000L)==0x7f800000L)) + +/*****************************************************************************/ +/* pfsurfac Surfaces */ +void +dpfInitSurface(dpfSURFACEPTR); /* Set to dpfINITSURFACE */ +void +dpfReinitSurface(dpfSURFACEPTR surf); +void +dpfCpySurface(dpfSURFACEPTR surf1, dpfSURFACEPTR surf2) ; +int32 +dpfCmpSurface(dpfSURFACEPTR s1, dpfSURFACEPTR s2) ; +/* if s1 == s2 then return 0, else return non-zero */ + + +/* Set surface characturistics */ +void +dpfSetSurface(dpfSURFACEPTR surf, dpfSURFACEPTR source) ; +/* Set material name literally sets the name to the given pointer, +** so make sure it dynamically allocated and not used by anything else! +** If in doubt use copy name which creates a new dynamically allocated name. +*/ +void +dpfSetSurfaceName(dpfSURFACEPTR surf, char *name) ; +void +dpfSetSurfaceF_Material(dpfSURFACEPTR surf, dpfMATTYPE Material, char *MatName) ; +void +dpfSetSurfaceB_Material(dpfSURFACEPTR surf, dpfMATTYPE Material, char *MatName) ; +void +dpfSetSurfaceVertex(dpfSURFACEPTR surf, uint8 Characturistic, uint8 State) ; +void +dpfSetSurfacePlane(dpfSURFACEPTR surf, dpfPLANE Plane) ; +void +dpfSetSurfaceFacet(dpfSURFACEPTR surf, dpfFACET Facet) ; +void +dpfSetSurfaceDecal(dpfSURFACEPTR surf, int32 decal) ; +void +dpfSetSurfaceDrawMode(dpfSURFACEPTR surf, dpfDRAWMODE DrawMode, uint8 Width) ; +void +dpfSetSurfaceLock(dpfSURFACEPTR surf, dpfLOCK lock) ; +void +dpfSetSurfaceSpecial(dpfSURFACEPTR surf, dpfSTRINGPTR Special) ; + +/* Get surface characturistics */ +/* Returns a pointer to THE name. so don't destroy */ +char * +dpfGetSurfaceName(dpfSURFACEPTR surf) ; +dpfMATTYPE +dpfGetSurfaceF_Material(dpfSURFACEPTR surf, char **MatName) ; +dpfMATTYPE +dpfGetSurfaceB_Material(dpfSURFACEPTR surf, char **MatName) ; +uint8 +dpfGetSurfaceVertex(dpfSURFACEPTR surf) ; +dpfPLANE +dpfGetSurfacePlane(dpfSURFACEPTR surf) ; +dpfFACET +dpfGetSurfaceFacet(dpfSURFACEPTR surf) ; +int32 +dpfGetSurfaceDecal(dpfSURFACEPTR surf) ; +dpfDRAWMODE +dpfGetSurfaceDrawMode(dpfSURFACEPTR surf, uint8 *Width) ; +dpfLOCK +dpfGetSurfaceLock(dpfSURFACEPTR surf) ; +dpfSTRINGPTR +dpfGetSurfaceSpecial(dpfSURFACEPTR surf) ; + + +/* pfvertex Vertices & VertLists */ +/* Vertices */ +void +dpfSetVertexFlag(uint8 vflag, uint8 textCook, uint8 overRide) ; +uint8 +dpfCheckVertexFlag(uint8 vflag, uint8 useOverRide) ; +dpfVERTEXPTR +dpfCreateVertex(void); +dpfVERTEXPTR +dpfCreateVertexBlock(int32 numVerts); +int32 +dpfCreateVertexTable(dpfGEOMETRYPTR geom, dpfVERTEXPTR **table) ; +int32 +dpfAddVertex(dpfGEOMETRYPTR geom, dpfVERTEXPTR vertex) ; +int32 +dpfUnlinkVertex(dpfVERTEXPTR); +int32 +dpfFreeVertex(dpfVERTEXPTR); +int32 +dpfFreeVertexList(dpfVERTEXPTR vert) ; +void +dpfKillVertices() ; + +/* The following calls are used to loop through all the vertices in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetVertexCount(dpfGEOMETRYPTR geom) ; +dpfVERTEXPTR +dpfGetFrstVertex(dpfGEOMETRYPTR geom) ; +dpfVERTEXPTR +dpfGetNextVertex(dpfVERTEXPTR vertex) ; +dpfVERTEXPTR +dpfGetPrevVertex(dpfVERTEXPTR vertex) ; +dpfVERTEXPTR +dpfGetNthVertex(dpfGEOMETRYPTR geom, int32 Nth) ; + + +/* Vertex info */ +void +dpfGetVertexPoint(dpfVERTEXPTR, dmVector) ; +void +dpfGetVertexNormal(dpfVERTEXPTR, dmVector) ; +void +dpfGetVertexColour(dpfVERTEXPTR, dpfRGBA) ; +void +dpfGetVertexTexture(dpfVERTEXPTR, dpfTEXT) ; + +void +dpfSetVertexPoint(dpfVERTEXPTR, dmVector) ; +void +dpfSetVertexNormal(dpfVERTEXPTR, dmVector) ; +void +dpfSetVertexColour(dpfVERTEXPTR, dpfRGBA) ; +void +dpfSetVertexTexture(dpfVERTEXPTR, dpfTEXT) ; + +/* Pmesh functions */ +/* Connection List's */ +dpfCLISTPTR +dpfCreateCList(int32 pcount, int32 fcount); +int32 +dpfAddCList(dpfGEOMETRYPTR geom, dpfCLISTPTR cList) ; +int32 +dpfUnlinkCList(dpfCLISTPTR); +int32 +dpfFreeCList(dpfCLISTPTR); +int32 +dpfFreeCListList(dpfCLISTPTR cList) ; + +/* The following calls are used to loop through all the vertLists in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetCListCount(dpfGEOMETRYPTR geom) ; +dpfCLISTPTR +dpfGetFrstCList(dpfGEOMETRYPTR geom) ; +dpfCLISTPTR +dpfGetNextCList(dpfCLISTPTR cList) ; +dpfCLISTPTR +dpfGetPrevCList(dpfCLISTPTR cList) ; + +/* VertList Info */ +int32 +dpfGetCListPCount(dpfCLISTPTR cList) ; +int32 +dpfGetCListFCount(dpfCLISTPTR cList) ; +int32 * +dpfCreateCListFace(dpfCLISTPTR cList) ; +int32 * +dpfGetCListFace(dpfCLISTPTR cList, int32 fno) ; +void +dpfSetCListFace(dpfCLISTPTR cList, int32 fno, int32 *verts) ; +int32 +dpfFreeCListFace(dpfCLISTPTR cList, int32 fno) ; + +/* Strip List's */ +dpfSLISTPTR +dpfCreateSList(int32 pcount, int32 vcount); +int32 +dpfAddSList(dpfGEOMETRYPTR geom, dpfSLISTPTR sList) ; +int32 +dpfUnlinkSList(dpfSLISTPTR); +int32 +dpfFreeSList(dpfSLISTPTR); +int32 +dpfFreeSListList(dpfSLISTPTR sList) ; + +/* The following calls are used to loop through all the Strip Lists in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetSListCount(dpfGEOMETRYPTR geom) ; +dpfSLISTPTR +dpfGetFrstSList(dpfGEOMETRYPTR geom) ; +dpfSLISTPTR +dpfGetNextSList(dpfSLISTPTR sList) ; +dpfSLISTPTR +dpfGetPrevSList(dpfSLISTPTR sList) ; + +/* Strip List Info */ +int32 +dpfGetSListPCount(dpfSLISTPTR sList) ; +int32 +dpfGetSListVCount(dpfSLISTPTR sList) ; +int32 +dpfAddSListVertex(dpfSLISTPTR sList, int32 vertNo) ; +int32 * +dpfGetSListVertex(dpfSLISTPTR sList, int32 vno) ; +void +dpfSetSListVertex(dpfSLISTPTR sList, int32 vno, int32 vertNo) ; + + +/* Sphere's */ +dpfSPHERENODEPTR +dpfCreateSphereNode(void); +dpfSPHERENODEPTR +dpfCreateSphereNodeBlock(int32 numVLists) ; +int32 +dpfAddSphereNode(dpfGEOMETRYPTR geom, dpfSPHERENODEPTR vertex) ; +int32 +dpfUnlinkSphereNode(dpfSPHERENODEPTR); +int32 +dpfFreeSphereNode(dpfSPHERENODEPTR); +int32 +dpfFreeSphereNodeList(dpfSPHERENODEPTR vertList) ; + + +/* The following calls are used to loop through all the spheres in a +** geometry. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +int32 +dpfGetSphereNodeCount(dpfGEOMETRYPTR geom) ; +dpfSPHERENODEPTR +dpfGetFrstSphereNode(dpfGEOMETRYPTR geom) ; +dpfSPHERENODEPTR +dpfGetNextSphereNode(dpfSPHERENODEPTR vertList) ; +dpfSPHERENODEPTR +dpfGetPrevSphereNode(dpfSPHERENODEPTR vertList) ; + +/* Sphere Info */ +void +dpfGetSphereDice(dpfGEOMETRYPTR geom, uint8 *u_dice, uint8 *v_dice) ; +void +dpfSetSphereDice(dpfGEOMETRYPTR geom, uint8 u_dice, uint8 v_dice) ; + +float32 +dpfGetSphereNodeData(dpfSPHERENODEPTR vertList, dmVector point) ; +void +dpfSetSphereNodeData(dpfSPHERENODEPTR vertList, float32 radius, + dmVector point) ; + +/* Text */ +dpfTEXTNODEPTR +dpfCreateTextNode(void) ; +dpfTEXTNODEPTR +dpfCreateTextNodeBlock(int32 numTexts) ; +int32 +dpfUnlinkTextNode(dpfTEXTNODEPTR text) ; +int32 +dpfAddTextNode(dpfGEOMETRYPTR geom, dpfTEXTNODEPTR text) ; +int32 +dpfFreeTextNode(dpfTEXTNODEPTR text) ; +int32 +dpfFreeTextNodeList(dpfTEXTNODEPTR text) ; + +/* move through text list */ +int32 +dpfGetTextNodeCount(dpfGEOMETRYPTR geom) ; +dpfTEXTNODEPTR +dpfGetFrstTextNode(dpfGEOMETRYPTR geom) ; +dpfTEXTNODEPTR +dpfGetNextTextNode(dpfTEXTNODEPTR text) ; +dpfTEXTNODEPTR +dpfGetPrevTextNode(dpfTEXTNODEPTR text) ; + +/* Get and set text global info */ +dpfFONT +dpfGetTextFont(dpfGEOMETRYPTR geom) ; +void +dpfGetTextOrientation(dpfGEOMETRYPTR geom, dmVector orn) ; +void +dpfGetTextScale(dpfGEOMETRYPTR geom, dmVector scale) ; +void +dpfSetTextFont(dpfGEOMETRYPTR geom, dpfFONT font) ; +void +dpfSetTextOrientation(dpfGEOMETRYPTR geom, dmVector orn) ; +void +dpfSetTextScale(dpfGEOMETRYPTR geom, dmVector scale) ; + +/* get and set text node info */ +void +dpfGetTextNodePoint(dpfTEXTNODEPTR text, dmVector point) ; +char * +dpfGetTextNodeString(dpfTEXTNODEPTR text) ; +void +dpfSetTextNodePoint(dpfTEXTNODEPTR text, dmVector point) ; +void +dpfSetTextNodeString(dpfTEXTNODEPTR text, char *str1) ; + +/* Get and set line global info */ +uint8 +dpfGetLineThickness(dpfGEOMETRYPTR geom) ; +void +dpfSetLineThickness(dpfGEOMETRYPTR geom, uint8 thickness) ; + +/* pfgeomet Geometry & strips & pmeshes etc */ +dpfGEOMETRYPTR +dpfCreatePoint(void) ; +dpfGEOMETRYPTR +dpfCreatePolygon(void) ; +dpfGEOMETRYPTR +dpfCreateTristrip(void); +dpfGEOMETRYPTR +dpfCreatePolystrip(void); +dpfGEOMETRYPTR +dpfCreatePmesh(void); +dpfGEOMETRYPTR +dpfCreateSphere(void); +dpfGEOMETRYPTR +dpfCreateLine(void) ; +dpfGEOMETRYPTR +dpfCreateText(void) ; +int32 +dpfAddGeometry(dpfPATCHPTR patch, dpfGEOMETRYPTR geom) ; +int32 +dpfUnlinkGeometry(dpfGEOMETRYPTR geometry) ; +int32 +dpfFreeGeometry(dpfGEOMETRYPTR); +int32 +dpfFreeFileGeometries(dpfFILEPTR file) ; +int32 +dpfTurnGeometry2Pmesh(dpfGEOMETRYPTR geom) ; + +/* The following calls are used to loop through all the geometries in a +** file. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfPATCHPTR +dpfGetGeometryParent(dpfGEOMETRYPTR geom) ; +dpfGEOMETRYPTR +dpfGetFrstGeometry(dpfPATCHPTR patch) ; +dpfGEOMETRYPTR +dpfGetNextGeometry(dpfGEOMETRYPTR geom) ; +dpfGEOMETRYPTR +dpfGetPrevGeometry(dpfGEOMETRYPTR geom) ; + +/* Geometry info */ +int32 +dpfGetGeometryType(dpfGEOMETRYPTR geom) ; + +/* pfpatch patches */ +dpfPATCHPTR +dpfCreatePatch(void) ; +int32 +dpfAddPatch(dpfLODPTR lod, dpfPATCHPTR patch) ; +int32 +dpfJoinPatch(dpfPATCHPTR patch1, dpfPATCHPTR patch2) ; +int32 +dpfUnlinkPatch(dpfPATCHPTR) ; +int32 +dpfFreePatch(dpfPATCHPTR) ; + +/* The following calls are used to loop through all the patches in an +** LOD. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfLODPTR +dpfGetPatchParent(dpfPATCHPTR patch) ; +dpfPATCHPTR +dpfGetFrstPatch(dpfLODPTR object) ; +dpfPATCHPTR +dpfGetNextPatch(dpfPATCHPTR patch) ; +dpfPATCHPTR +dpfGetPrevPatch(dpfPATCHPTR patch) ; + +/* Get surface pointer for the surface setting and getting calls */ +dpfSURFACEPTR +dpfGetPatchSurface(dpfPATCHPTR patch) ; + +/* pflod LODs */ +dpfLODPTR +dpfCreateLOD(void) ; +int32 +dpfAddLOD(dpfOBJECTPTR object, dpfLODPTR lod) ; +int32 +dpfJoinLOD(dpfLODPTR lod1, dpfLODPTR lod2) ; +int32 +dpfUnlinkLOD(dpfLODPTR) ; +int32 +dpfFreeLOD(dpfLODPTR) ; +int32 +dpfCmpLOD(dpfLODPTR lod1, dpfLODPTR lod2) ; + +/* The following calls are used to loop through all the lods in a +** file. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfOBJECTPTR +dpfGetLODParent(dpfLODPTR) ; +dpfLODPTR +dpfGetFrstLOD(dpfOBJECTPTR) ; +dpfLODPTR +dpfGetNextLOD(dpfLODPTR) ; +dpfLODPTR +dpfGetPrevLOD(dpfLODPTR) ; + +/* LOD info */ +char * +dpfGetLODName(dpfLODPTR lod) ; +void +dpfGetLODDistance(dpfLODPTR lod, float32 *InDist, float32 *OutDist) ; +dpfTRANSITION +dpfGetLODTransition(dpfLODPTR lod) ; +int32 +dpfGetLODReference(dpfLODPTR lod, dmVector reference) ; + +void +dpfSetLODName(dpfLODPTR lod, char *name) ; +void +dpfSetLODDistance(dpfLODPTR lod, float32 InDist, float32 OutDist) ; +void +dpfSetLODTransition(dpfLODPTR lod, dpfTRANSITION Transition) ; +void +dpfSetLODReference(dpfLODPTR lod, int32 referenceFlag, dmVector reference) ; + + +/* pfobject objects */ +dpfOBJECTPTR +dpfCreateObject(void) ; +int32 +dpfAddObject(dpfFILEPTR file, dpfOBJECTPTR object) ; +int32 +dpfJoinObject(dpfOBJECTPTR object1, dpfOBJECTPTR object2) ; +int32 +dpfUnlinkObject(dpfOBJECTPTR) ; +int32 +dpfFreeObject(dpfOBJECTPTR) ; + +/* The following calls are used to loop through all the objects in a +** file. Get Previous has to search a list to find the previous so it +** can be slow. +*/ +dpfFILEPTR +dpfGetObjectParent(dpfOBJECTPTR) ; +dpfOBJECTPTR +dpfGetFrstObject(dpfFILEPTR) ; +dpfOBJECTPTR +dpfGetNextObject(dpfOBJECTPTR) ; +dpfOBJECTPTR +dpfGetPrevObject(dpfOBJECTPTR) ; + +/* Get surface pointer for the surface setting and getting calls */ +dpfSURFACEPTR +dpfGetObjectSurface(dpfOBJECTPTR object) ; + +/* pffile file structure */ +int32 +dpfGetAllFile(char *name, dpfFILEPTR *file, uint8 verMajor, uint8 verMinor) ; +dpfFILEPTR +dpfOpenAllFile(char *name, uint8 verMajor, uint8 verMinor) ; +int32 +dpfGetAllFileBody(dpfFILEPTR file) ; +int32 +dpfGetFile(char *name, dpfFILEPTR *file) ; +dpfFILEPTR +dpfOpenFile(char *name) ; +int32 +dpfGetFileBody(dpfFILEPTR file) ; + +int32 +dpfPutAllFile(char *name, dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutAllFileBody(dpfFILEPTR Dfile,dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutFile(char *name, dpfFILEPTR Sfile) ; +int32 +dpfPutFileBody(dpfFILEPTR Dfile,dpfFILEPTR Sfile) ; +dpfFILEPTR +dpfOpenNewFile(char *name, dpfFILEFORMAT form, dpfFILETYPE fileType) ; + +dpfFILEPTR +dpfCreateFile(char *name) ; +int32 +dpfJoinFile(dpfFILEPTR file1, dpfFILEPTR file2) ; +int32 +dpfCloseFile(dpfFILEPTR file) ; +int32 +dpfFreeFile(dpfFILEPTR) ; +int32 +dpfKillFile(dpfFILEPTR file) ; + +/* File info */ +dpfFILETYPE +dpfGetFileType(dpfFILEPTR file) ; +dpfFILEFORMAT +dpfGetFileFormat(dpfFILEPTR file) ; +char * +dpfGetFileName(dpfFILEPTR file) ; + +/* File info */ +void +dpfSetFileType(dpfFILEPTR file, dpfFILETYPE type) ; +void +dpfSetFileFormat(dpfFILEPTR file,dpfFILEFORMAT format) ; + +/* pfinfo information on struction, read and written */ +int32 +dpfCountFileContent(dpfFILEPTR file) ; +int32 +dpfGetFileNoMaterials(dpfFILEPTR file) ; +int32 +dpfGetFileNoTextures(dpfFILEPTR file) ; +int32 +dpfGetFileNoRamps(dpfFILEPTR file) ; +int32 +dpfGetFileNoObjects(dpfFILEPTR file) ; +int32 +dpfGetFileNoLODs(dpfFILEPTR file) ; +int32 +dpfGetFileNoPatches(dpfFILEPTR file) ; +int32 +dpfGetFileNoGeometries(dpfFILEPTR file) ; +int32 +dpfGetFileNoPolystrips(dpfFILEPTR file) ; +int32 +dpfGetFileNoTristrips(dpfFILEPTR file) ; +int32 +dpfGetFileNoPmeshes(dpfFILEPTR file) ; +int32 +dpfGetFileNoSLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoSFaces(dpfFILEPTR file) ; +int32 +dpfGetFileSFtimesP(dpfFILEPTR file) ; +int32 +dpfGetFileNoCLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoCFaces(dpfFILEPTR file) ; +int32 +dpfGetFileCFtimesP(dpfFILEPTR file) ; +int32 +dpfGetFileNoVertices(dpfFILEPTR file) ; +int32 +dpfGetFileNoTriangles(dpfFILEPTR file) ; +int32 +dpfGetFileTotNoTriangles(dpfFILEPTR file) ; +int32 +dpfGetFileNoSphereLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoSpheres(dpfFILEPTR file) ; +int32 +dpfGetFileNoPointLists(dpfFILEPTR file) ; +int32 +dpfGetFileNoPoints(dpfFILEPTR file) ; +int32 +dpfGetFileNoLines(dpfFILEPTR file) ; +int32 +dpfGetFileNoLineNodes(dpfFILEPTR file) ; +int32 +dpfGetFileNoTexts(dpfFILEPTR file) ; +int32 +dpfGetFileNoTextStrings(dpfFILEPTR file) ; +int32 +dpfGetFileNoPolygons(dpfFILEPTR file) ; +int32 +dpfGetFileNoPolygonVertices(dpfFILEPTR file) ; + + +/* pfmaterl materials */ +dpfMATERIALPTR +dpfCreateMaterial(void) ; +char * +dpfCreateMaterialName(char *extPath, char *library, char *mname) ; +void +dpfCpyMaterial(dpfMATERIALPTR mat1, dpfMATERIALPTR mat2) ; +int32 +dpfCmpMaterial(dpfMATERIALPTR mat1, dpfMATERIALPTR mat2) ; +dpfMATERIALPTR +dpfAddMaterial(dpfFILEPTR file, dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfAddV1Material(dpfFILEPTR file, dpfMATERIALPTR mat) ; +int32 +dpfFreeMaterial(dpfMATERIALPTR mat) ; + +dpfFILEPTR +dpfGetMaterialParent(dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfGetFrstMaterial(dpfFILEPTR file) ; +dpfMATERIALPTR +dpfGetNextMaterial(dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfGetPrevMaterial(dpfMATERIALPTR mat) ; +dpfMATERIALPTR +dpfFindMaterial(dpfFILEPTR fp, char *matName) ; + +/* Set material name literally sets the name to the given pointer, +** so make sure it dynamically allocated and not used by anything else! +** If in doubt use copy name which creates a new dynamically allocated name. +*/ +void +dpfSetMaterialName(dpfMATERIALPTR mat, char *name) ; +void +dpfSetMaterialTexture(dpfMATERIALPTR mat, dpfMATTXTTYPE TxtType, char *name) ; +void +dpfSetMaterialRamp(dpfMATERIALPTR mat, char *name) ; +void +dpfSetMaterialAmbient(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialDiffuse(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialSpecular(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialEmissive(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfSetMaterialOpacity(dpfMATERIALPTR mat,dpfRGBA colour) ; + +/* Returns a pointer to THE name. so don't destroy */ +char * +dpfGetMaterialName(dpfMATERIALPTR mat) ; +dpfMATTXTTYPE +dpfGetMaterialTexture(dpfMATERIALPTR mat, char **name) ; +char * +dpfGetMaterialRamp(dpfMATERIALPTR mat) ; +void +dpfGetMaterialAmbient(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialDiffuse(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialSpecular(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialEmissive(dpfMATERIALPTR mat,dpfRGBA colour) ; +void +dpfGetMaterialOpacity(dpfMATERIALPTR mat,dpfRGBA colour) ; + + +/* pfile General file loading calls */ +void +dpfErrorOn(void) ; +void +dpfErrorOff(void) ; +void +dpfDebugOn(void) ; +void +dpfDebugOff(void) ; + +/* Names and Strings and things */ +char * +dpfCreateName(char *name) ; +char * +dpfDuplicateName(char *name) ; +void +dpfFreeName(char *name) ; +/* the return from cmp is similar to strcmp, ie 0 if the same, else non-zero */ +int32 +dpfCmpName(char *name1, char *name2) ; + +/* Strings can have '\0' in them, so the first byte is the string length */ +/* Create uses the str as its string, copy mallocs more space and copies +** in the string str +*/ +dpfSTRINGPTR +dpfCreateString(void) ; +dpfSTRINGPTR +dpfDuplicateString(dpfSTRINGPTR str) ; +int32 +dpfSetString(dpfSTRINGPTR str, int32 Length, uint8 *theStr) ; +void +dpfFreeString(dpfSTRINGPTR str) ; +/* the return from cmp is similar to strcmp, ie 0 if the same, else non-zero */ +int32 +dpfCmpString(dpfSTRINGPTR str1, dpfSTRINGPTR str2) ; +int32 +dpfGetStringLength(dpfSTRINGPTR str) ; +uint8 * +dpfGetStringString(dpfSTRINGPTR str) ; + +/* pfcheck checks input values */ +float32 +dpfCheckRGB(float32 colour) ; +float32 +dpfCheckAlpha(float32 alpha) ; +float32 +dpfCheckV1Power(float32 power) ; +float32 +dpfCheckPower(float32 power) ; +float32 +dpfCheckOpacity(float32 opacity) ; +uint16 +dpfCheckDice(uint16 dice) ; + +/* ramp stuff */ +dpfRAMPPTR +dpfCreateRamp(void); +int32 +dpfCmpRamp(dpfRAMPPTR r1, dpfRAMPPTR r2) ; +dpfRAMPPTR +dpfAddRamp(dpfFILEPTR file, dpfRAMPPTR r) ; +int32 +dpfFreeRamp(dpfRAMPPTR r) ; + +dpfFILEPTR +dpfGetRampParent(dpfRAMPPTR mat) ; +dpfRAMPPTR +dpfGetFrstRamp(dpfFILEPTR file) ; +dpfRAMPPTR +dpfGetNextRamp(dpfRAMPPTR mat) ; +dpfRAMPPTR +dpfGetPrevRamp(dpfRAMPPTR mat) ; +dpfRAMPPTR +dpfFindRamp(dpfFILEPTR fp, char *rampName) ; + +void +dpfSetRampName(dpfRAMPPTR r, char *a); +void +dpfSetRampData(dpfRAMPPTR r, dpfRGBA a, dpfRGBA b); +char * +dpfGetRampName(dpfRAMPPTR r); +void +dpfGetRampData(dpfRAMPPTR r, dpfRGBA data0, dpfRGBA data1) ; + +/* new boundary stuff */ +dpfBOUNDPTR +dpfCreateBound(void) ; +int32 +dpfUnlinkBound(dpfBOUNDPTR bound) ; +int32 +dpfAddFileBound(dpfFILEPTR file, dpfBOUNDPTR bound) ; +int32 +dpfAddBoundBound(dpfBOUNDPTR prnt, dpfBOUNDPTR bound) ; +int32 +dpfFreeBound(dpfBOUNDPTR bound) ; +dpfFILEPTR +dpfGetBoundFile(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetBoundParent(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetFileBound(dpfFILEPTR file) ; +dpfBOUNDPTR +dpfGetFrstBound(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetNextBound(dpfBOUNDPTR bound) ; +dpfBOUNDPTR +dpfGetPrevBound(dpfBOUNDPTR bound) ; +void +dpfSetBoundSphere(dpfBOUNDPTR bound, int32 present, float32 radius, + dmVector point) ; +void +dpfSetBoundBox(dpfBOUNDPTR bound,int32 present,dmVector bMin,dmVector bMax, dmVector orien) ; +void +dpfSetBoundPmesh(dpfBOUNDPTR bound, dpfGEOMETRYPTR pmesh) ; +void +dpfSetBoundAuto(dpfBOUNDPTR bound, uint8 Auto) ; +void +dpfSetBoundLODName(dpfBOUNDPTR bound, char *name) ; +void +dpfSetBoundObjectName(dpfBOUNDPTR bound, char *name) ; +int32 +dpfGetBoundSphere(dpfBOUNDPTR bound, float32 *radius, dmVector point) ; +int32 +dpfGetBoundBox(dpfBOUNDPTR bound, dmVector bMin, dmVector bMax, dmVector orien) ; +dpfGEOMETRYPTR +dpfGetBoundPmesh(dpfBOUNDPTR bound) ; +uint8 +dpfGetBoundAuto(dpfBOUNDPTR bound) ; +void +dpfCalcBBoxInitialize(dpfBOUNDPTR bound) ; +void +dpfCalcPointBBox(dmVector vec, dmVector MinVec, dmVector MaxVec) ; +int32 +dpfCalcGeometryBBox(dpfGEOMETRYPTR geom, dpfBOUNDPTR bound) ; +int32 +dpfCalcPatchBBox(dpfPATCHPTR patch, dpfBOUNDPTR bound) ; +int32 +dpfCalcLODBBox(dpfLODPTR lod, dpfBOUNDPTR bound) ; +int32 +dpfCalcBBox(dpfFILEPTR file, dpfBOUNDPTR bound) ; +int32 +dpfCalcGeometryBSphere(dpfGEOMETRYPTR geom, dpfBOUNDPTR bound) ; +int32 +dpfCalcPatchBSphere(dpfPATCHPTR patch, dpfBOUNDPTR bound) ; +int32 +dpfCalcBSphere(dpfFILEPTR file, dpfBOUNDPTR bound) ; +int32 +dpfCheckBound(dpfFILEPTR file) ; + +/*** texture stuff ***/ +dpfTEXTUREPTR +dpfCreateTexture(void); +int32 +dpfCpyTexture(dpfTEXTUREPTR txt1, dpfTEXTUREPTR txt2) ; +int32 +dpfCmpTexture(dpfTEXTUREPTR txt1, dpfTEXTUREPTR txt2) ; +dpfTEXTUREPTR +dpfAddTexture(dpfFILEPTR file, dpfTEXTUREPTR txt) ; +int32 +dpfUnlinkTexture(dpfTEXTUREPTR txt) ; +int32 +dpfFreeTexture(dpfTEXTUREPTR txt) ; + +dpfFILEPTR +dpfGetTextureParent(dpfTEXTUREPTR txt) ; +dpfTEXTUREPTR +dpfGetFrstTexture(dpfFILEPTR file) ; +dpfTEXTUREPTR +dpfGetNextTexture(dpfTEXTUREPTR txt) ; +dpfTEXTUREPTR +dpfGetPrevTexture(dpfTEXTUREPTR txt) ; +dpfTEXTUREPTR +dpfFindTexture(dpfFILEPTR fp, char *txtName) ; + +void +dpfSetTextureName(dpfTEXTUREPTR t, char *a); +void +dpfSetTextureMap(dpfTEXTUREPTR t, char *a); +void +dpfSetTextureWrap(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureUWrap(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureVWrap(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureDetail(dpfTEXTUREPTR t, dpfDETAIL detail, char *name) ; +void +dpfSetTextureMinify(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureMagnify(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureAlpha(dpfTEXTUREPTR t, int32 a); +void +dpfSetTextureBitslice(dpfTEXTUREPTR t, uint8 a); + +char * +dpfGetTextureName(dpfTEXTUREPTR t) ; +char * +dpfGetTextureMap(dpfTEXTUREPTR t) ; +void +dpfGetTextureWrap(dpfTEXTUREPTR t, int32 a) ; +dpfWRAP +dpfGetTextureUWrap(dpfTEXTUREPTR t) ; +dpfWRAP +dpfGetTextureVWrap(dpfTEXTUREPTR t) ; +dpfDETAIL +dpfGetTextureDetail(dpfTEXTUREPTR t, char **name) ; +dpfMINIFY +dpfGetTextureMinify(dpfTEXTUREPTR t) ; +dpfMAGNIFY +dpfGetTextureMagnify(dpfTEXTUREPTR t) ; +dpfALPHA +dpfGetTextureAlpha(dpfTEXTUREPTR t) ; +uint8 +dpfGetTextureBitslice(dpfTEXTUREPTR t) ; + + +/*** header stuff ***/ +void +dpfSetFileVersion(dpfFILEPTR f, uint8 i, uint8 j); +void +dpfSetFileDate(dpfFILEPTR f, uint8 i, uint8 j, uint8 k); +void +dpfSetFileTime(dpfFILEPTR f, uint8 i, uint8 j); +void +dpfSetFileUnit(dpfFILEPTR f, dpfUNIT i); +void +dpfSetFileScale(dpfFILEPTR f, float32 i); +void +dpfSetFilePrecision(dpfFILEPTR f, dpfPRECISION i); +void +dpfSetHeaderComment(dpfFILEPTR f, dpfSTRINGPTR i); + +void +dpfGetLibraryVersion(uint8 *i, uint8 *j) ; +int32 +dpfGetFileVersion(dpfFILEPTR f, uint8 *verMajor, uint8 *verMinor) ; +int32 +dpfGetFileDate(dpfFILEPTR f, uint8 *dpfday, uint8 *dpfmonth, uint8 *dpfyear) ; +int32 +dpfGetFileTime(dpfFILEPTR f, uint8 *dpfhours, uint8 *dpfminutes) ; +dpfUNIT +dpfGetFileUnit(dpfFILEPTR f) ; +float32 +dpfGetFileScale(dpfFILEPTR f) ; +dpfPRECISION +dpfGetFilePrecision(dpfFILEPTR f) ; +dpfSTRINGPTR +dpfGetFileComment(dpfFILEPTR f) ; + +/**************** callbacks *******************/ +/* The following functions are used to set callbacks + * for each of several structures. They are called when + * a structure has been completed and would normally be + * linked into the file structure. The procedure is passed + * a pointer to the structure to do with as it wishes and + * returns an integer value. If the return value is 1 the + * structure is freed, otherwise it is linked into the + * file structure as usual. + */ + + +/* new whizzy v1.0 -> v2.0 texture name converter stuff */ +struct dpfVISTEXTURETYPE ; +typedef struct dpfVISTEXTURETYPE *dpfVISTEXTUREPTR; + +dpfVISTEXTUREPTR +dpfCreateV1TextureList(char *mazName) ; +void +dpfSetFileVisList(dpfFILEPTR file, dpfVISTEXTUREPTR visList) ; +void +dpfConvertV1Texture(dpfFILEPTR Sfp, dpfMATERIALPTR Fmat, dpfMATERIALPTR Bmat) ; +void +dpfFreeV1TextureList(dpfVISTEXTUREPTR visList) ; + + +int32 +dpfCheckFile(dpfFILEPTR file) ; + + +#endif /* __PFILE_H__ */ + diff --git a/MUNGA_L4/libDPL/dsys/PFPARSER.H b/MUNGA_L4/libDPL/dsys/PFPARSER.H new file mode 100644 index 0000000..4da9f9e --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/PFPARSER.H @@ -0,0 +1,97 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: pfparser.h,v $ + * REVISION: $Revision: 1.3 $ + * Date: $Date: 95/04/27 23:01:16 $ + * Author: $Author: bill $ + * RCS Ident: $Id: pfparser.h,v 1.3 95/04/27 23:01:16 bill Exp $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +#ifndef __PFPARSER_H__ +#define __PFPARSER_H__ + +#include +#ifdef _PF_LOCAL +#include "pgeneral.h" +#else +#include +#endif + +#define dpp_MATCH_CASE 0 +#define dpp_ANY_CASE 1 + +/* On calls which either succeed or fail, dpgSUCCESS (0) or dpgERROR (-1) + * is returned. On calls to get next token however the following + * return values are also used + */ +#define dppEOF -2 +#define dppSTRING -3 +#define dppNUMBER -4 + +typedef struct dppKEYTAB +{ + int32 tok; + char *name; + int32 matchCase; +} dppKEYTAB ; + + +typedef struct dppFILE +{ + int32 lineNo; + int32 errorFlag; + char *fileName; + FILE *file; + char *whites ; + char comment ; + int32 pushedBackToken; + float number; + char *buffer; + int32 bufSize; + int32 bufPos; + dppKEYTAB *keyTab; +} dppFILE, *dppFILEPTR ; + + + +dppFILEPTR +dppOpenFile (char *name, FILE *fp, const char *whites, char comment, + dppKEYTAB *keyTable, int32 bufferSize); +void +dppCloseFile (dppFILEPTR fPtr); +char * +dppTokenToString (dppFILEPTR fptr, const int32 token); +int32 +dppPushToken (dppFILEPTR fptr, const int32 token); +int32 +dppNextToken (dppFILEPTR fptr); +int32 +dppReadToNextChar(dppFILEPTR fPtr, char endChr) ; +char * +dppMatchString (dppFILEPTR fptr); +int32 +dppMatchInt (dppFILEPTR fptr, int32 *num); +int32 +dppMatchFloat (dppFILEPTR fptr, float *num); +int32 +dppMatchCharacter (dppFILEPTR fptr, char c); +void +dppMoveToNextLine(dppFILEPTR fptr) ; + + +#endif /* __PFPARSER_H__ */ + diff --git a/MUNGA_L4/libDPL/dsys/PGENERAL.H b/MUNGA_L4/libDPL/dsys/PGENERAL.H new file mode 100644 index 0000000..3c6f2ef --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/PGENERAL.H @@ -0,0 +1,183 @@ +/* + * ---------------------------------------------------------------------------- + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: pgeneral.h,v $ + * Revision : $Revision: 1.1 $ + * Date : $Date: 95/04/27 23:01:16 $ + * Author : $Author: bill $ + * Last Modified : <260495.2024> + * + * Description + * + * Notes + * + * History + * + * + * ---------------------------------------------------------------------------- + */ + +/* + * The following functions are provided in this module + * + * Return flags - to be used in all libs and converters + * dpgSUCCESS=0, dpgERROR=-1 + * + * Verbose output setup (special "stderr" & "stdout") + * dpgSetOutput(n) + * + * Verbose warning setup and usage + * dpgSetWarnLevel(n) + * dpgWarn(n,(print stuff)) + * + * Verbose error setup and usage + * variable dpgErrNo - set to the last error num ; + * dpgSetErrorLevel(n) + * dpgError(num, n,(print stuff)) + * + * Verbose monitering setup and usage + * dpgSetMonitorFlag(n) + * dpgMonitor(flag,(print stuff)) + * + * Verbose bad parameter passed error handler + * dpgBadAddress(addr,String) + * + * Dying routine, outputs to the log and if not stderr, out to stderr + * dpgDie(level,(print stuff)) + * + * malloc and calloc routines that print out an error and exit on failure. + * dpgMalloc(size,string) + * dpgRealloc(pnt,size,string) + * dpgCalloc(nel,size,string) + * + * dm macro Extensions + * + */ + +#ifndef __PGENERAL_H__ +#define __PGENERAL_H__ + +#include +#include + +/* The program name must be defined and setup by the program */ +extern char *progname ; + +#define dpgSUCCESS 0 +#define dpgERROR -1 + +/* General error numbers */ + +#define dpgENO_NULL 0x1001 +#define dpgENO_ROPEN 0x1002 +#define dpgENO_READ 0x1003 +#define dpgENO_WOPEN 0x1004 +#define dpgENO_WRITE 0x1005 + +/* Verbose output setup (special "stderr" & "stdout") - returns dpgERROR + * if couldn't open the file, SUCCESS otherwise + */ +extern FILE *dpgLog ; + +int32 +dpgSetOutput(char *name) ; +#define dpgFlush() fflush(dpgLog) +/* internal functions */ + +/* If the next variable is non-zero then when any printing is done, a new + * line will be inserted and the variable will be reset to 0 */ +extern int32 dpgNewLine ; +#define dpgSetNewLine(v) (dpgNewLine=(v)) + +/* Verbose warning setup and usage */ +extern int32 dpgWarnLvl ; + +/* general printing routine */ +extern void dpgPrint(char *format, ...) ; +void +dpgPrintActivity(int32 Cur, int32 Tot) ; + +#define dpgIncWarnLevel() (dpgWarnLvl++) +#define dpgSetWarnLevel(n) (dpgWarnLvl = n) + +extern int32 __dpgWarn(char *format, ...) ; +#define dpgWarn(lvl,p) \ +((lvl <= dpgWarnLvl) ? (__dpgWarn p):dpgSUCCESS) + +/* Verbose error setup and usage */ +extern int32 dpgErrorLvl ; +extern int32 dpgErrNo ; + +#define dpgIncErrorLevel() (dpgErrorLvl++) +#define dpgSetErrorLevel(n) (dpgErrorLvl = n) +extern int32 __dpgError(char *format, ...) ; +#define dpgError(num,lvl,p) \ +((dpgErrNo = num),((lvl <= dpgErrorLvl) ? (__dpgError p):dpgERROR)) + +/* Verbose monitor setup and usage */ +extern int32 dpgMonitorFlg ; + +#define dpgSetMonitorFlag(n) (dpgMonitorFlg = n) +extern int32 __dpgMonitor(char *format, ...) ; +#define dpgMonitor(flag,p) \ +((flag & dpgMonitorFlg) ? (__dpgMonitor p):dpgSUCCESS) +#define dpgTestMonitor(flag) \ +((flag & dpgMonitorFlg) ? dpgERROR:dpgSUCCESS) + +/* Dying routine, outputs to the log and if not stderr, out to stderr - exits + */ +extern void dpgDie(char *format, ...) ; + +#define dpgQDie() \ +do { \ + fprintf(stderr,"Press q to quit.\n") ; \ + if(getchar() == 'q') \ + dpgDie("User requested death\n") ; \ +} while(0) + +/* Verbose bad parameter passed error handler - returns ERROR if addr is + * NULL also does dpgError, returns SUCCESS otherwise + */ +int32 +__dpgBadAddress(char *posStr) ; +#define dpgBadAddress(addr,posStr) \ +((addr == NULL) ? __dpgBadAddress(posStr) : dpgSUCCESS) + + + +/* malloc and calloc routines that print out an error and exit on failure. */ +void * +dpgMalloc(size_t size, char *posStr) ; +void * +dpgRealloc(void *pnt, size_t size, char *posStr) ; +void * +dpgCalloc(size_t noElm, size_t size, char *posStr) ; + + +/* The following are useful dm extensions */ + +#define dmVectorSqrLen(a) \ + (dmSqr((a)[DM_X]) + dmSqr((a)[DM_Y]) + dmSqr((a)[DM_Z])) + +#define dmVectorLen(a) dmVectorLength(a) + +#define dmVectorUnit(a) \ +do { \ + float32 mod ; \ + mod = dmLength3(a) ; \ + (a)[DM_X] /= mod ; \ + (a)[DM_Y] /= mod ; \ + (a)[DM_Z] /= mod ; \ +} while (0) + +#define dmVectorCmp(a,b) memcmp(a,b,sizeof(dmVector)) + + +#endif /* __PGENERAL_H__ */ + diff --git a/MUNGA_L4/libDPL/dsys/PIMAGE.H b/MUNGA_L4/libDPL/dsys/PIMAGE.H new file mode 100644 index 0000000..60bce5a --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/PIMAGE.H @@ -0,0 +1,199 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * File: $RCSfile: pimage.h,v $ + * Revision: $Revision: 1.5 $ + * Date: $Date: 95/04/27 23:01:16 $ + * Author: $Author: bill $ + * RCS Ident: $Id: pimage.h,v 1.5 95/04/27 23:01:16 bill Exp $ + * + * FUNCTION: + * + * + * $Log: pimage.h,v $ + * Revision 1.5 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * Revision 1.4 95/03/21 14:50:22 bill + * Adding the global opacity setter + * + * Revision 1.3 1995/03/10 19:03:01 bill + * Ci for beta release of v2.1 dvs -> dsys change + * + * Revision 1.2 1995/03/10 18:43:29 bill + * Ci for beta release of v2.1 + * + * Revision 1.1 1995/03/06 10:24:34 bill + * Initial revision + * + * Revision 1.4 1994/11/09 17:49:06 bill + * texture type was int32 instead of uint8, read wronge + * + * Revision 1.3 1994/08/30 17:18:09 bill + * Altered -t so it sets the background opacity to a given value (-ve is + * default and preserves inta, rgba and svt opacity values, sets rest to + * 255). + * Also added sgi save -> rgba format. + * + * Revision 1.2 1994/05/13 12:08:51 bill + * File name changing for release. pfile.h->pfile2.h, __pfile.h->__pfile2.h, ptools.h->ptools2.h, __ptools.h->__ptools2.h, filelib.h->filelib2.h, getparam.h->getprm.h. + * + * Revision 1.1 1994/04/15 15:43:18 bill + * new pfile and ptools that cope with spheres lines text and polygons, also uses new FL extension pfl & PF extension dpf + * + * Revision 1.1 1994/02/16 20:30:34 bill + * General edit + * + * + * Copyright (c) 1992 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef __PIMAGE_H__ +#define __PIMAGE_H__ + +#include + +extern char *progname ; + +/**************************************************************************** + * pimage error numbers */ +#define dpiENO_OPEN 0x7001 +#define dpiENO_READ 0x7002 +#define dpiENO_WRITE 0x7003 +#define dpiENO_CLOSE 0x7004 +#define dpiENO_NULL 0x7005 +#define dpiENO_FORM 0x7006 + +/**************************************************************************** + * pimage error numbers */ +#define dpiWARN_PROB 2 + +/**************************************************************************** + * pimage monitor numbers */ +#define dpiMON_POS 0x00010000 +#define dpiMON_PALLET 0x00020000 +#define dpiMON_IMAGE 0x00040000 + +#define VTX_ALLOW_VTX 1 +#define VTX_ALLOW_SVT 2 +#define VTX_ALLOW_OTHER 4 +#define VTX_ALLOW_DIV 3 +#define VTX_ALLOW_ALL 7 + +#define VTX_WIDTH_EIGHT (uint8)1 + +#define VTXcmpIRGB(s1,s2) memcmp(s1,s2,3) +#define VTXcmpIRGBA(s1,s2) memcmp(s1,s2,4) +#define VTXcpyIRGBA(dd,ss) memcpy(dd,ss,sizeof(VTXIRGBA)) + +typedef enum { VTX_GIF_FILE, VTX_BMP_FILE, VTX_SGI_FILE, + VTX_SVT_FILE, VTX_TGA_FILE, VTX_TIF_FILE, + VTX_VTX_FILE, VTX_BSL_FILE, VTX_UNKNOWN_FILE } VTX_IMG_TYPE ; + +typedef enum { VTX_PREC_SINGLE=0, VTX_PREC_DOUBLE=1 } VTXPRECISION ; +/* bsl types */ +#define dpiBSLNOTYPES 9 +typedef enum {dpiBSLTYPE_MONO0=0, dpiBSLTYPE_MONO1=1, dpiBSLTYPE_MONO2=2, + dpiBSLTYPE_MONO3=3, dpiBSLTYPE_MONO4=4, dpiBSLTYPE_MONO5=5, + dpiBSLTYPE_BILINEAR=6, + dpiBSLTYPE_RGB=7, dpiBSLTYPE_RGBA=8 } dpiBSLTYPE ; + +typedef enum VTXcoord { /* used for indexing arrays, identifying axies etc */ + VTXERGBA = 4, VTX_R = 0, VTX_G = 1, VTX_B = 2, VTX_A=3 +} VTXcoord; + +typedef struct +{ + uint8 col[VTXERGBA]; +}VTXIRGBA ; + +typedef struct +{ + float32 col[VTXERGBA]; +}VTXFRGBA ; + +typedef float32 VTXBOXFILTER[3][3] ; + + +struct VTXTEXTURETYPE ; +typedef struct VTXTEXTURETYPE *VTXTEXTUREPTR ; + +struct VTXHEADERTYPE ; +typedef struct VTXHEADERTYPE *VTXHEADERPTR ; + +struct VTXFILETYPE ; +typedef struct VTXFILETYPE *VTXFILEPTR ; + +int32 +VTXgetFile(char *name, VTXFILEPTR *file, int32 allowFile) ; +VTXFILEPTR +VTXopenFile(char *name, int32 allowFile) ; +int32 +VTXgetFileBody(VTXFILEPTR file) ; +int32 +VTXcloseFile(VTXFILEPTR file) ; +int32 +VTXfreeFile(VTXFILEPTR file) ; + +int32 +VTXputFile(char *name, VTXFILEPTR Sfile, VTX_IMG_TYPE fileType) ; +VTXFILEPTR +VTXopenNewFile(char *name, VTX_IMG_TYPE fileType) ; +int32 +VTXputFileBody(VTXFILEPTR Dfile, VTXFILEPTR Sfile) ; + +VTXFILEPTR +VTXcreateFile(char *name) ; +VTXTEXTUREPTR +VTXcreateTexture(void) ; +void +VTXcreateData(VTXTEXTUREPTR texture) ; + +VTXTEXTUREPTR +VTXgetTexture(VTXFILEPTR file) ; +void +VTXgetTextureSize(VTXTEXTUREPTR vtx, int32 *u, int32 *v) ; +uint8 +VTXgetTextureType(VTXTEXTUREPTR vtx) ; +void +VTXgetTextureBgColour(VTXTEXTUREPTR vtx, VTXIRGBA *col) ; +void +VTXsetTextureType(VTXTEXTUREPTR vtx, uint8 type) ; +void +VTXsetTextureBgColour(VTXTEXTUREPTR vtx, VTXIRGBA *col) ; +int32 +VTXaddTexture(VTXFILEPTR file, VTXTEXTUREPTR text) ; + +void +VTXfreeTexture(VTXTEXTUREPTR texture) ; + + +/* returns non-zero on error, zero otherwise. new_quads points to the same or +** a new array of quads. +*/ +int32 +VTXinterpolate(VTXTEXTUREPTR vtx, int32 new_width, int32 new_height) ; +int32 +VTXboxFilter(VTXTEXTUREPTR file, VTXBOXFILTER BoxF) ; +/* if Opacity is < 0 then the alpha is just initialised, else it is set to + * it (range 0 -> 255) + */ +int32 +VTXsetTransparency(VTXTEXTUREPTR vtx, int32 glOpacity, int32 bgOpacity) ; + + +VTXFILEPTR +VTXcreateBSL(char *name, int32 u, int32 v, int32 w) ; +int32 +VTXmergeBSL(VTXFILEPTR Dfp, int32 type, VTXFILEPTR Sfp) ; + +#endif /* __PIMAGE_H__ */ + diff --git a/MUNGA_L4/libDPL/dsys/PTOOL.H b/MUNGA_L4/libDPL/dsys/PTOOL.H new file mode 100644 index 0000000..66a61d7 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/PTOOL.H @@ -0,0 +1,666 @@ +/**************************************************************************** + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: ptool.h,v $ + * Revision : $Revision: 1.18 $ + * Date : $Date: 95/05/16 13:47:00 $ + * Author : $Author: bill $ + * Last Modified : <150595.1203> + * + * Description + * + * Notes + * + * History + * + * $Log: ptool.h,v $ + * Revision 1.18 95/05/16 13:47:00 bill + * Added 1) dos. 2) STRIP_LIST. 3) POINTLIST. 4) biz->bgf + * + * Revision 1.17 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * + **************************************************************************** + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + ****************************************************************************/ + +#ifndef __PTOOL_H__ +#define __PTOOL_H__ + +#ifdef _PF_LOCAL +#include "pfile.h" +#else +#include +#endif + +/*****************************************************************************/ +/* pfile error numbers */ +#define dptENO_NOTIMP 0x8001 +#define dptENO_FORM 0x8002 +#define dptENO_VALUE 0x8003 +#define dptENO_USAGE 0x8004 +#define dptENO_NULL 0x8005 +#define dptENO_INTER 0x8006 +#define dptENO_GRAPH 0x8007 + +/*****************************************************************************/ +/* ptool monitor flags */ +#define dptMON_ALL 0x01000000 + +void +dptGetLibraryVersion(uint8 *M, uint8 *m) ; + +/* returns 0 if the triangle is small, 1 and the normal otherwise +*/ +int32 +dptCalcVTriNorm(dmVector pnt1, dmVector pnt2, dmVector pnt3, + dmVector normal) ; +int32 +dptCalcTriNorm(dpfVERTEXPTR vert1, dpfVERTEXPTR vert2, dpfVERTEXPTR vert3, + dmVector normal) ; +void +dptMatMultVector(dmVector OutVec, dmVector vec, dmMatrix mat) ; + + +/* + * FILE __ptmesh.c + * Creates and saves meshes + */ +#define dpt_OPT_PMESH 0x010000 +#define dpt_OPT_PSTRIP 0x020000 + +dptMESHPTR +dptCreateMesh(int32 hash_size, int32 normals) ; +void +dptFreeMesh(dptMESHPTR mesh) ; +void +dptGetMeshStats(dptMESHPTR mesh) ; +int32 +dptGetMeshNoTriangles(dptMESHPTR mesh) ; +int32 +dptGetMeshNoVertices(dptMESHPTR mesh) ; +int32 +dptGetMeshNoDropTri(dptMESHPTR mesh) ; + +int32 +dptMeshLoadFile(dptMESHPTR mesh, dpfFILEPTR file) ; +int32 +dptMeshLoadObject(dptMESHPTR mesh, dpfOBJECTPTR object) ; +int32 +dptMeshLoadLOD(dptMESHPTR mesh, dpfLODPTR LOD) ; +int32 +dptMeshLoadPatch(dptMESHPTR mesh, dpfPATCHPTR patch) ; +int32 +dptMeshLoadGeometry(dptMESHPTR mesh, dpfGEOMETRYPTR geom) ; +int32 +dptMeshLoadTriangle(dptMESHPTR mesh, dpfVERTEXPTR vert1, dpfVERTEXPTR vert2, + dpfVERTEXPTR vert3) ; + +int32 +dptMeshCalcFaceNormals(dptMESHPTR mesh) ; +void +dptMeshSetVertexPoint(dptMESHPTR mesh, dpfVERTEXPTR vert, dmVector point) ; + +int32 +dptMeshUnloadPatch(dpfPATCHPTR patch, dptMESHPTR mesh, int32 usePmesh) ; +int32 +dptMeshUnloadLOD(dpfLODPTR LOD, dptMESHPTR mesh, int32 usePmesh) ; +int32 +dptMeshUnloadMesh(dptMESHPTR mesh, int32 usePmesh) ; + +/* +** Octize utilitises +** +** must load the file into a mesh using dptMeshLoadFile etc. +** Then use dptOctizeMesh to octize followed by +** dptUnloadOctizedMeshSingle or dptUnloadOctizedMeshMulti +** for single and All file outputs. +*/ +int32 +dptOctizeMesh(dptMESHPTR mesh, dpfIVECTOR div, dmVector Min, dmVector Dif) ; +int32 +dptSpatialiseMesh(dptMESHPTR mesh) ; + +int32 +dptUnloadDividedMeshSingle(dptMESHPTR mesh, int32 octPos, + int32 usePmesh, int32 *noTriangles) ; +int32 +dptUnloadOctizedMeshSingle(dptMESHPTR mesh, dpfIVECTOR pos, + int32 usePmesh, int32 *noTriangles) ; +int32 +dptUnloadDividedMeshAll(dptMESHPTR mesh, int32 usePmesh) ; + + +/* + * File ptbbox + * Gets bounding box of files, objects, patches & geoms + * + * dpfBbox??? must have the MaxVec and MinVec initialized by the user + * before it is first called. + * dpfGetbbox??? Initializes itself, and gets the bounding box and + * difference vector for the structure. + */ +int32 +dptGetBBoxGeometry(dpfGEOMETRYPTR geom, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; +int32 +dptGetBBoxPatch(dpfPATCHPTR patch, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; +int32 +dptGetBBoxLOD(dpfLODPTR LOD, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; +int32 +dptGetBBoxFile(dpfFILEPTR file, dmVector MaxVec, dmVector MinVec, + dmVector differ) ; + +/* + * File ptscale + * scales files, objects, patches & geoms + */ +/* NOTE! :- If dptScaleGeometry or Patch is used it is up to the USER to +** scale all LOD reference points !!! DON'T FORGET. +*/ +int32 +dptScaleGeometry(dpfGEOMETRYPTR geom, int32 normals, dmVector scale) ; +int32 +dptScalePatch(dpfPATCHPTR patch, dmVector scale) ; +int32 +dptScaleObject(dpfOBJECTPTR object, dmVector scale) ; +int32 +dptScaleFile(dpfFILEPTR file, dmVector scale) ; +int32 +dptChangeFileUnit(dpfFILEPTR file, dpfUNIT unit) ; + +int32 +dptScaleNPGeometry(dpfGEOMETRYPTR geom, dmVector scale, dpfIVECTOR NP) ; +int32 +dptScaleNPPatch(dpfPATCHPTR patch, dmVector scale, dpfIVECTOR NP) ; +int32 +dptScaleNPObject(dpfOBJECTPTR object, dmVector scale, dpfIVECTOR NP) ; +int32 +dptScaleNPFile(dpfFILEPTR file, dmVector scale, dpfIVECTOR NP) ; + +/* + * File ptxlate + * translates files, objects, patches & geoms + */ +/* NOTE! :- If dptTranslateGeometry or Patch is used it is up to the USER to +** scale all LOD reference points !!! DON'T FORGET. +*/ +int32 +dptTranslateGeometry(dpfGEOMETRYPTR geom, dmVector trn) ; +int32 +dptTranslatePatch(dpfPATCHPTR patch, dmVector trn) ; +int32 +dptTranslateLOD(dpfLODPTR LOD, dmVector trn) ; +int32 +dptTranslateObject(dpfOBJECTPTR object, dmVector trn) ; +int32 +dptTranslateFile(dpfFILEPTR file, dmVector trn) ; + +/* + * File ptcentre + * Centre's given file + */ +int32 +dptCentreFile(dpfFILEPTR file) ; + +/* + * File ptcoales + * coalesces short patches into longer ones + * reduces file size, execution time + */ +int32 +dptCoalesceLOD(dpfLODPTR LOD) ; +int32 +dptCoalesceObject(dpfOBJECTPTR obj, int32 coalesceLODs, int32 coalesceGEOMs) ; +int32 +dptCoalesceFile(dpfFILEPTR file, int32 coalesceLODs, int32 coalesceGEOMs) ; + +/* + * File pttextur + * Places planar texture co-ordinates on given file + */ +#define dpt_TEXTURE_PLANE 0 +#define dpt_TEXTURE_AXIAL 1 +#define dpt_TEXTURE_CYLINDER 2 + +typedef struct +{ + int32 method ; + int32 noWraps ; + int32 gotSize, gotRef ; + int32 Cswap ; + int32 Uco, Vco ; + int32 axes[3] ; + float32 Usize, Vsize ; + float32 Cangle, Coffset ; + dmVector reference ; + + int32 distort ; +} dptTEXTURE, *dptTEXTUREPTR ; + + +void +dptCorrectTriangleTexture(dptMESHPTR mesh, dpfPATCHPTR patch, + dpfVERTEXPTR vert1, dpfVERTEXPTR vert2, + dpfVERTEXPTR vert3, int32 noWraps, int32 *distort) ; +dpfGEOMETRYPTR +dptCorrectGeometryTexture(dpfGEOMETRYPTR geom, int32 noWraps, int32 *distort) ; + +int32 +dptTextureInit(dptTEXTUREPTR txt, int32 method, int32 NoWraps, int32 gotSize, + int32 gotRef, dmVector MinVec, dmVector differ, + float32 Usize, float32 Vsize, dmVector reference, int32 Uco, + int32 Vco, int32 *axes, int32 Cswap, float32 Cangle) ; +int32 +dptTextureFileInit(dpfFILEPTR file, dptTEXTUREPTR txt, int32 method, + int32 NoWraps, int32 gotSize, int32 gotRef, float32 Usize, + float32 Vsize, dmVector reference, int32 Uco, int32 Vco, + int32 *axes, int32 Cswap, float32 Cangle) ; +dpfGEOMETRYPTR +dptTextureGeometry(dpfGEOMETRYPTR geom, dptTEXTUREPTR txt) ; +int32 +dptTexturePatch(dpfPATCHPTR ptch, dptTEXTUREPTR txt) ; +int32 +dptTextureLOD(dpfLODPTR LOD, dptTEXTUREPTR txt) ; +int32 +dptTextureFile(dpfFILEPTR file, dptTEXTUREPTR txt) ; + +/* + * File __ptrot.c + * rotates files, objects, patches & geoms + * Order the rotations are performed are the same as MAZ + * ie Z, X then Y + */ +/* Matrix point transformers. + * Transforms (Xforms) files using a 4x4 homogeneous matrix, + * Note that translations are performed, hence the use of dmPntXformMat + * + * Used directly by the dptRotate functions. + */ +#define dptVectorXformMat(OutVec,vec,mat) dmPointXformMat(OutVec,vec,mat) +extern void +(dptVectorXformMat)(dmVector OutVec, dmVector vec, dmMatrix mat) ; +int32 +dptXformGeometry(dpfGEOMETRYPTR geom, int32 Normals, dmMatrix rotate) ; +int32 +dptXformPatch(dpfPATCHPTR patch, dmMatrix rotate) ; +int32 +dptXformObject(dpfOBJECTPTR object, dmMatrix rotate) ; +int32 +dptXformFile(dpfFILEPTR file, dmMatrix rotate) ; + +/***************************************************************************** +* NOTE! :- If dptRotateGeometry or Patch is used it is up to the USER to * +* scale all LOD reference points !!! DON'T FORGET. * +*****************************************************************************/ +/* + * Rotation functions use the Xform functions directly, so error messages + * will be dptXform's. + */ +extern void +dptRotateSetup(dmMatrix outMat, dmVector inRot) ; +#define dptRotateGeometry(geom,Normals,rotate) \ + dptXformGeometry(geom,Normals,rotate) +#define dptRotatePatch(patch,rotate) \ + dptXformPatch(patch,rotate) +#define dptRotateObject(object,rotate) \ + dptXformObject(object,rotate) +#define dptRotateFile(file,rotate) \ + dptXformFile(file,rotate) + +/* + * File __pticon.h + * Centre's and scales a given file to produce an icon + */ + +#define dpt_ICONSIZE 1.0 + +int32 +dptIconizeFile(dpfFILEPTR file, float32 size) ; + +/* + * File __ptrond.h + * Rounds given file to the given number of sig. figures + * if the given number is <= 0 then default is used. + */ + +#define dpt_DEFAULTSIGFIG 6 +#define dpt_DEFAULTDPS 4 +#define dpt_DEFAULTWRAP 1 + +int32 +dptRoundFvertex(dpfFILEPTR file, int32 SigFig, int32 dps) ; + +int32 +dptFuzzyJoinFile(dpfFILEPTR file, float32 Dist, int32 WarnDis) ; + +int32 +dptJoinMeshTriangles(dptMESHPTR mesh, float32 distTol, float32 angTol, + int32 *joinCount, int32 Verbose) ; +int32 +dptJoinPatchTriangles(dpfPATCHPTR patch, int32 hash_size, int32 usePmesh, + float32 distTol, float32 angTol, int32 *joinCount, + int32 Verbose) ; + + +typedef struct +{ + /* Check setup parameters */ + int32 dps ; /* decimal places to check to */ + int32 NoWraps ; /* maximum no. of texture wraps */ + int32 autoFix ; /* autoFix on if non-zero */ + int32 disableText ; /* don't fix textures if non-zero */ + int32 splitGeom ; /* if non-zero the split triangle */ + /* rather than distort texture */ + int32 Verbose ; /* run with verbose */ + + /* Things calculated on setup */ + float32 MulFac ; /* Normal modulus accuracy mul factor*/ + + /* No. things found empty */ + int32 emptyLod ; + int32 emptyPatch ; + int32 emptyGeom ; + + /* LOD error report */ + int32 badDummy ; /* got a dummy with other lods */ + int32 badOrder ; /* lods in wrong order - flag only */ + int32 distSame ; /* switch-in == out count */ + int32 distSwap ; /* switch-in > out count */ + int32 overLap ; /* lod switch in overlaps others out */ + + /* geometry bad report */ + int32 badPmeshT ; /* No of bad pmesh triangle connects */ + int32 badSphere ; /* No of spheres with bad radii */ + int32 badLine ; /* No of 0 length lines */ + int32 badPoint ; /* No. points with nans, inc. lod ref*/ + int32 badNorm ; /* No. normals with bad mod */ + int32 badCook ; /* No. rgb's out of range */ + int32 badText ; /* no. nan | text co-ords out of wrap*/ + float32 maxText ; /* the maximum range of a texture */ + + /* boundary report */ + int32 badBBox ; + int32 badBSphere ; + int32 badBPmesh ; + + int32 isBad ; /* Summary flag - if true then error found */ + + /* auto-fix output */ + int32 dropLod ; /* No dropped lods as empty */ + int32 dropPatch ; /* No dropped patches as empty */ + int32 dropGeom ; /* No dropped geometries as empty */ + int32 dropTri ; /* No tri's dropped because duff */ + /* duff cos nan's or pmesh connect */ + int32 dropLine ; /* No lines's dropped cos len = 0 */ + int32 dropSphere ; /* No tri's dropped cos radius = 0 */ + + int32 dropBPart ; /* No B box, sphere and pmeshes drop */ + int32 dropBound ; /* No bounds dropped */ + + int32 normDistort ; /* No normal 0 or nan mods */ + int32 textDistort ; /* No texture distorts (0 if split) */ + int32 newTriCnt ; /* No new tris created from splitting*/ + + int32 isAwful ; /* Summary flag - if true then Distortion */ + +} dptCHECK, *dptCHECKPTR ; + + +int32 +dptCheckLODs(dpfFILEPTR file, dptCHECKPTR check) ; +int32 +dptCheckPatch(dpfPATCHPTR patch, dptCHECKPTR check) ; +void +dptCheckSetup(dptCHECKPTR check, int32 dps, int32 NoWraps, int32 autoFix, + int32 disableText, int32 verbose) ; +int32 +dptCheckFile(dpfFILEPTR file, dptCHECKPTR check, int32 dps, int32 NoWraps, + int32 autoFix, int32 disableText, int32 verbose) ; + +int32 +dptNormalizeMesh(dptMESHPTR mesh, float32 Tolerence, int32 Verbose) ; +int32 +dptNormalPatch(dpfPATCHPTR patch, int32 hash_size, float32 Tolerence, + int32 usePmesh, int32 *DropTri, int32 Verbose) ; + + +/* reduce a patch + * NOTE :- + * Method is a bit field using the following #defines + * verbose is a bit field 0x02=Prompt, 0x04=GL, non-zero=% + */ +#define dptRDC_DUPS 0x0001 +#define dptRDC_DUPD 0x0002 +#define dptRDC_SQUR 0x0004 +#define dptRDC_180 0x0008 +#define dptRDC_360 0x0010 + +int32 +dptReducePatch(dpfPATCHPTR patch, int32 hash_size, float32 Cook_Tol, + float32 Norm_Tol, float32 Tri_Tol, float32 Edge_Tol, + int32 *DropTri, int32 NoIter, int32 usePmesh, int32 Method, + int32 Verbose, float32 WarmInc) ; + +/* +** Reduces the number of faces in a cylinder. +** Tolerences :- +** MaxRadiusTol +** RatioTol - The maximum ratio between the largest and +** smallest end edges. +** NormTol - How correctly shaped the pairs are. +** MaxNoFaces - Max faces in a cylinder -> 2* no of trian. +** MinNoFaces - Min faces in a cylinder +** FinNoFaces - Final no faces. +*/ + + +/* The cylinder structure + * The following rules must be adhered to if blast is to correctly re-create + * them. + * 1) there are 2 different types of cylinders, flat (disks and ring) and + * non-flat (cones and tubes). + * 2) flat cylinders must have a length of 0.0, the larger ring must be + * stored in slot 0 and inner ring or centre in slot 1. PlnNorm and + * CenLine must be the same and point in the direction it is facing. + * Flipping the centLine direction and facing bit in flags (bit 1) + * can be used to change its orientation + * 3) Non-flat tubes have a non-zero length, the CentLine is the direct + * needed to go for the centre point of ring in slot 0 to the centre + * of ring in slot 1. Bit 1 of flags indicates where the cylinder is + * in or outwardly facing, set if in. + * 4) flat disk cylinders are automatically converted to cylinder ends if + * an apropriate cylinder is found. + * 5) Bit 2 of flags gives the orientation of the cylinder in the pipe, if + * set then it is facing the other way. + * 6) Bit 3-5 of flags indicates the part got of a cylinder + * 7) the plane normals must point outwards of a tube if inwardly facing, + * or inwardly if inwardly facing. With a ring, the large radius ring must + * point in the direction the ring faces and it will join that way, the + * smaller must point the oposite way. + */ +#define dptBLAST_FACE 0x0001 +#define dptBLAST_DIR 0x0002 +#define dptBLAST_BODY 0x0004 +#define dptBLAST_END1 0x0008 +#define dptBLAST_END2 0x0010 +#define dptBLAST_DISK 0x0020 +#define dptBLAST_CONE 0x0040 +#define dptBLAST_RING 0x0080 +#define dptBLAST_TUBE 0x0100 + +typedef struct dptCYLINDER_str +{ + int32 noFaces ; + int32 flags ; + float32 Length ; + dmVector CentLine ; + + float32 Radius[2] ; + dmVector Centre[2] ; + dmVector PlnNorm[2] ; + + struct dptCYLINDER_str *next ; + +} dptCYLINDER, *dptCYLINDER_ptr ; + + +typedef struct dptCYLLIST_str +{ + int32 flags[2] ; + int32 NoVert ; + float32 maxRadius ; + float32 minRadius ; + float32 Radius[2] ; + dmVector Centre[2] ; + dmVector PlnNorm[2] ; + dptCYLINDER_ptr EndCyl[2] ; + + struct dptCYLLIST_str *next ; +} dptCYLLIST, *dptCYLLIST_ptr ; + + +typedef struct +{ + dptMESHPTR curMesh ; + dpfPATCHPTR curPatch ; + + int32 BBlast ; + float32 BMaxSideTol ; + float32 BRatioTol ; + float32 BEdgeTol ; + float32 BNormTol ; + + int32 CBlast ; + int32 CStats ; + int32 CMinFcs ; + int32 CMaxFcs ; + int32 CNoRanges ; + float32 *CMinRad ; + float32 *CMaxRad ; + int32 *CFinFcs ; + + /* to be filled */ + int32 KeepParts ; + float32 CRatioTol ; + float32 CNormTol ; + float32 CCentDif ; + float32 CRadDif ; + float32 CTurnTol ; + + /* to be left alone */ + float32 TurnTol ; + float32 cNorm0Tol ; + float32 cNorm90Tol ; + dptCYLLIST_ptr CList_hd, CList_tl ; + dpfVERTEXPTR *TopVerts, *BotVerts ; + +} dptBLAST, *dptBLASTPTR ; + + +int32 +dptBlastPatch(dpfPATCHPTR patch, int32 hash_size, dptBLASTPTR blast, + int32 usePmesh, int32 *DropTri, int32 Verbose) ; + + +int32 +dptTinyKillMesh(dptMESHPTR mesh,float32 Angl_Tol, + int32 Verbose, int32 *SmallTri) ; +int32 +dptTinyKillPatch(dpfPATCHPTR patch, int32 hash_size, + float32 Angl_Tol, int32 usePmesh, + int32 *DropTri, int32 Verbose) ; + + +/* +** ptflip - module to flip the trangle direction face +*/ +int32 +dptFlipAllGeometry(dpfGEOMETRYPTR geom, int32 flipNormals) ; +int32 +dptFlipAllPatch(dpfPATCHPTR patch, int32 flipNormals) ; +int32 +dptFlipAllObject(dpfOBJECTPTR object, int32 flipNormals) ; +int32 +dptFlipAllFile(dpfFILEPTR file, int32 flipNormals) ; + +int32 +dptFlipRightMesh(dptMESHPTR mesh, int32 *flipCount, int32 Verbose) ; +int32 +dptFlipRightPatch(dpfPATCHPTR patch, int32 hash_size, int32 usePmesh, + int32 *DropTri, int32 *flipCount, int32 Verbose) ; + +/* +** hedgehog a given file +*/ +int32 +dptCreateVisualMaterials(dpfFILEPTR file) ; +int32 +dptAddVertexNormalVisual(dpfFILEPTR file, char *matLib, float32 Pscale, + float32 Bscale) ; +int32 +dptAddBoundBoxVisual(dpfFILEPTR file, char *matLib) ; +int32 +dptAddBoundSphereVisual(dpfFILEPTR file, char *matLib, + int32 udice, int32 vdice) ; +int32 +dptAddBoundPmeshVisual(dpfFILEPTR file, char *matLib) ; + +int32 +dptRmvVertexNormalVisual(dpfFILEPTR file) ; +int32 +dptRmvBoundBoxVisual(dpfFILEPTR file) ; +int32 +dptRmvBoundSphereVisual(dpfFILEPTR file) ; +int32 +dptRmvBoundPmeshVisual(dpfFILEPTR file) ; + +int32 +dptCookGeometry(dpfGEOMETRYPTR geom, dpfRGBA col) ; +int32 +dptCookFile(dpfFILEPTR file) ; + +/* Boundary stuff */ +int32 +dptCalcMinBBox(dpfFILEPTR file, int32 res, dpfBOUNDPTR bound) ; +int32 +dptCreateBoundary(dpfFILEPTR file, int32 minBBoxRes, int32 doHierarchy, + int32 keepPmesh, int32 hashSize) ; + +/* Tessellate a polygon, allowing for concavity. + * + * The pmesh must already contain all the required vertices, noPnts is + * a count of the number of points in the polygon (doesnt have to be the + * number of vertices), and vrtlst is an int array of size noPnts giving + * the pmesh vert numbr for the nth point. + * Assumes that the polygon is closed, so vrtlst[0] != vrtLst[noPnts-1] + * should be true. + */ +int32 +dptPolyTessellate(dpfGEOMETRYPTR pmesh, int32 noPnts, int32 *vrtLst) ; + +/* graphics routines */ +int32 +dptInitGraphics(char *name) ; +int32 +dptInitView(dmVector boxMin, dmVector boxDif) ; +int32 +dptEndView(void) ; + +#endif /* __PTOOL_H__ */ diff --git a/MUNGA_L4/libDPL/dsys/VDIFILE.H b/MUNGA_L4/libDPL/dsys/VDIFILE.H new file mode 100644 index 0000000..9b093df --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/VDIFILE.H @@ -0,0 +1,229 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: vdifile.h,v $ +-- Revision : $Revision: 1.4 $ +-- Date : $Date: 95/04/27 23:01:16 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __VDIFILE_H__ + +#define __VDIFILE_H__ + +#ifdef _PF_LOCAL +#include "pfile.h" +#else +#include +#endif + +/* vdifile error numbers */ + + +#define dvf_OBJECT_TYPE 0x01 /* if flag bit set then obj in scene */ +#define dvf_PARENT_TYPE 0x02 /* if flag bit set then obj is parent */ +#define dvf_OBJECT_LIB 0x04 /* if flag bit set obj is a library */ + +#define dvf_TABSIZE 4 + +typedef enum { dvfLIGHT_AMBIENT, dvfLIGHT_DIRECT } dvfLIGHTTYPE ; +typedef enum { dvfSTATE_ON=0, dvfSTATE_OFF } dvfSTATE ; + +extern char *progname ; + +typedef struct dvfMFILETYPE +{ + char *name ; + dpfFILEPTR file ; + struct dvfMFILETYPE *next ; +} dvfMFILE, *dvfMFILEPTR ; + +typedef struct +{ + /* lighting stuff */ + dvfLIGHTTYPE lightType ; + dvfSTATE lightState ; + dpfRGBA colour ; +} dvfLIGHT, *dvfLIGHTPTR ; + +typedef struct dvfOBJECTTYPE +{ + /* Object name, library file name, template name and comment */ + char *name ; + char *libName ; + char *tempName ; + char *comment ; + + /* position in the world relative to parent */ + dmPoint point ; + dmScale scale ; + dmEuler orien ; + + /* visual info */ + char *geomName ; + dpfFILEPTR geometry ; + dvfSTATE geomState ; /* if ON then visible else invisble */ + + /* Light setting of the object */ + dvfLIGHTPTR light ; + + /* User data - do what you want with these. + * Guaranteed to be initialised to 0s and NULLs + */ + int32 userFlags ; + void *userData ; + int32 userFlags2 ; + void *userData2 ; + + /* internal flags */ + int32 flags ; + struct dvfOBJECTTYPE *child_hd, *child_tl ; + struct dvfOBJECTTYPE *next, *objParent ; + struct dvfFILETYPE *fileParent ; +} dvfOBJECT, *dvfOBJECTPTR ; + + +typedef struct dvfFILETYPE +{ + char *fileName, *sceneName ; + char *basePath, *extPath ; + FILE *fp ; + int32 useMid, type ; + int32 disLight ; + int32 tab ; + + int32 userFlags ; + void *userData ; + + dvfOBJECTPTR defs_hd, defs_tl ; + dvfOBJECTPTR scene_hd, scene_tl ; + dvfMFILEPTR mfile_hd ; + dpfFILETYPE outType ; +} dvfFILE, *dvfFILEPTR ; + + +/* Copies sname into dname, correcting any bad characters to '_' + * + * Note:- if the name starts with a non alpha character (inc numeric), + * it is illegal so a pre-pending 'A' is added. For this reason + * dname must be 1 character bigger than sname. + * + * dname can been sname! (if so ensure sname is 1 character bigger) + */ +void +dvfCorrectName(char *dname, char *sname) ; + +/* File setup and saving ****************************************************/ +dvfFILEPTR +dvfCreateFile(void) ; +int32 +dvfSaveFile(dvfFILEPTR file) ; +int32 +dvfFreeFile(dvfFILEPTR file) ; + + +int32 +dvfSetFileName(dvfFILEPTR file, char *name) ; +/* if type is non-zero then the file is a library and saved with the + * extension of .vdl + */ +#define dvfSetFileType(f,t) ((f)->type = t) +#define dvfDisableDefaultLighting(f) ((f)->disLight = 1) +int32 +dvfSetFilePaths(dvfFILEPTR file, dpfFILETYPE outType, char *basePath, + int32 useMid, char *extPath) ; +#define dvfGetFileSceneName(f) ((f)->sceneName) +#define dvfGetFileFileName(f) ((f)->fileName) + +/* Material File calls ******************************************************/ +dvfMFILEPTR +dvfCreateMaterialFile(void) ; +int32 +dvfAddMaterialFile(dvfFILEPTR file, dvfMFILEPTR mfile) ; +int32 +dvfSetMaterialFileName(dvfMFILEPTR mfile, char *name) ; + +/* OBJECT Functions *********************************************************/ +dvfOBJECTPTR +dvfCreateObject(void) ; +void +dvfUnlinkObject(dvfOBJECTPTR object) ; + +/* adding object to the hierarchy */ +int32 +dvfAddDefinitionObject(dvfFILEPTR file, dvfOBJECTPTR object) ; +int32 +dvfAddSceneObject(dvfFILEPTR file, dvfOBJECTPTR object) ; +int32 +dvfAddObjectObject(dvfOBJECTPTR parent, dvfOBJECTPTR object) ; + +/* setting object information */ +int32 +dvfSetObjectName(dvfOBJECTPTR object, char *name) ; +int32 +dvfSetObjectGeometryName(dvfOBJECTPTR object, char *name) ; +#define dvfSetObjectGeometryState(o,s) ((o)->geomState = s) +int32 +dvfSetObjectGeometryFile(dvfOBJECTPTR object, dpfFILEPTR file) ; +int32 +dvfSetObjectLight(dvfOBJECTPTR object, dvfLIGHTPTR light) ; +#define dvfSetObjectPoint(o,p) dmVectorCopy((o)->point,p) +#define dvfSetObjectScale(o,s) dmVectorCopy((o)->scale,s) +#define dvfSetObjectOrien(o,r) dmVectorCopy((o)->orien,r) + +/* Getting information back again */ +#define dvfGetObjectName(o) ((o)->name) +#define dvfGetObjectObjectParent(o) ((o)->objParent) +#define dvfGetObjectFileParent(o) ((o)->fileParent) +#define dvfGetObjectGeometryName(o) ((o)->geomName) +#define dvfGetObjectGeometryFile(o) ((o)->geometry) +#define dvfGetObjectLight(o) ((o)->light) +#define dvfGetObjectPoint(o,p) dmVectorCopy(p,(o)->point) +#define dvfGetObjectScale(o,s) dmVectorCopy(s,(o)->scale) +#define dvfGetObjectOrien(o,r) dmVectorCopy(r,(o)->orien) +#define dvfGetObjectGeometryState(o) ((o)->geomState) + +/* The next makes it a UseLibrary if the file name is not NULL or + * a defineLibrary if NULL + */ +int32 +dvfSetObjectLibrary(dvfOBJECTPTR object, char *filename) ; +/* Sets the library name and object name the use as a Template */ +int32 +dvfSetObjectTemplate(dvfOBJECTPTR object, char *library, char *oname) ; +int32 +dvfSaveFreeGeometry(dvfFILEPTR file, dvfOBJECTPTR object) ; +int32 +dvfFreeObject(dvfOBJECTPTR object) ; +/* Dont use the following as it doesnt up-date pointers */ +int32 +dvfFreeObjectList(dvfOBJECTPTR object) ; + +/* Light Functions **********************************************************/ +dvfLIGHTPTR +dvfCreateLight(void) ; + +#define dvfGetLightType(l) ((l)->lightType) +#define dvfGetLightState(l) ((l)->lightState) +#define dvfGetLightColour(l,c) (dpfRGBCpy(c,(l)->light)) + +#define dvfSetLightType(l,t) ((l)->lightType = t) +#define dvfSetLightState(l,s) ((l)->lightState = s) +#define dvfSetLightColour(l,c) (dpfRGBACpy((l)->colour,c)) + +#endif /* __VDIFILE_H__ */ diff --git a/MUNGA_L4/libDPL/dsys/__PFILE.H b/MUNGA_L4/libDPL/dsys/__PFILE.H new file mode 100644 index 0000000..2bc0543 --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/__PFILE.H @@ -0,0 +1,603 @@ +/**************************************************************************** + * + * Copyright 1995 Division Limited. + * All Rights Reserved + * + * + * System : + * Module : + * Object Name : $RCSfile: __pfile.h,v $ + * Revision : $Revision: 1.15 $ + * Date : $Date: 95/05/16 13:46:17 $ + * Author : $Author: bill $ + * Last Modified : <120595.1125> + * + * Description + * + * Notes + * + * History + * + * $Log: __pfile.h,v $ + * Revision 1.15 95/05/16 13:46:17 bill + * Added 1) dos. 2) STRIP_LIST. 3) POINTLIST. 4) biz->bgf + * + * Revision 1.14 95/04/27 23:01:16 bill + * Major ci for 3.0 Alpha (new: pgeneral, dm) + * + * + **************************************************************************** + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + ****************************************************************************/ + +#ifndef ____PFILE_H__ +#define ____PFILE_H__ + +#include + +#ifdef _PF_LOCAL +#include "filelib.h" +#include "pfile.h" +#else +#include +#include +#endif + + +/* Constant ID strings */ +#define dpfBIZIDstrLen 31 +#define dpfBIZIDstr "biz v1.0 (c) DIVISION Ltd 1992" +#define dpfVIZIDstr "/* viz v1.0 (c) DIVISION Ltd 1992 */\n" + +#define dpfB2ZIDstrLen 8 +#define dpfB2ZIDstr "DIV-BIZ2" +#define dpfV2ZIDstrLen 8 +#define dpfV2ZIDstr "DIV-VIZ2" +#define dpfBMFIDstrLen 8 +#define dpfBMFIDstr "DIV-BMF2" +#define dpfVMFIDstrLen 8 +#define dpfVMFIDstr "DIV-VMF2" + +/* ver change */ +/* 2.00 Initial pfile version */ +/* 2.01 Replairs to pmesh tag and section length tests */ +/* 2.02 pmesh extended to have polygons of upto 255 faces */ +/* 2.03 boundary information added */ +/* 2.04 Line definition change, can now be textured cooked & normalized */ +/* 2.05 Introduction of material libraries */ +/* 2.06 pgeneral way of doing things */ +/* 2.07 STRIP_LISTs and POINTLISTs added to format */ +#define dpf_LIBRARY_MAJOR_VER 2 +#define dpf_LIBRARY_MINOR_VER 07 + +#define dpfSTDINName "Std In" +#define dpfSTDOUTName "Std Out" + +/* new biz v2 max depth constant */ +#define dpf_MAX_DEPTH 10 + +/* load in basic types, struct names and procedure heading which +** can be externally called. +*/ + +#define dpfVBLKSIZE 1024 + +extern uint8 dpfVERTFLAG ; +extern uint8 dpfVERTSIZE ; +extern uint8 dpfVERTNORM ; +extern uint8 dpfVERTRGBA ; +extern uint8 dpfVERTTEXT ; +extern uint8 dpfVERTOVER ; + +/* Now define all the internal structures */ +typedef int32 dpfTOKEN ; + +/* The following is for the new wizzy v1.0 -> v2.0 texture converter */ +typedef struct dpfVISTEXTURETYPE +{ + char *visName ; + char *F_textName, *F_textMap ; + char *B_textName, *B_textMap ; + + struct dpfVISTEXTURETYPE *next ; +} dpfVISTEXTURE ; + + +typedef struct dpfSTRINGTYPE +{ + int32 length ; + uint8 *string ; +} dpfSTRING ; + +typedef struct dpfTEXTURETYPE +{ + char *textName ; + char *fileName ; + + dpfMINIFY minify ; + dpfMAGNIFY magnify ; + dpfALPHA alpha ; + dpfWRAP wrap_U, wrap_V ; + dpfDETAIL detail ; + char *detailName; + uint8 bitslice ; + dpfSTRINGPTR special ; + int32 dataLength ; + struct dpfFILE_TYPE *file; + struct dpfTEXTURETYPE *next ; + +} dpfTEXTURE ; + + +typedef struct dpfRAMPTYPE +{ + char *name ; + dpfRGBA data[2] ; + + dpfSTRINGPTR special ; + int32 dataLength ; + + struct dpfFILE_TYPE *file; + struct dpfRAMPTYPE *next ; +} dpfRAMP ; + +typedef struct dpfMATERIALTYPE +{ + char *name ; + + dpfMATTXTTYPE textureType ; + char *textureName ; + char *rampName ; + dpfRGBA ambient, + diffuse, + specular, + emissive, + opacity ; + dpfSTRINGPTR special ; + int32 dataLength ; + struct dpfFILE_TYPE *file; + struct dpfMATERIALTYPE *next ; + +} dpfMATERIAL ; + + +typedef struct dpfSURFACETYPE +{ + char *name ; + dpfMATTYPE F_Material ; + dpfMATTYPE B_Material ; + char *F_MatName ; + char *B_MatName ; + + dpfPLANE plane ; + dpfFACET facet ; + int32 decal ; + dpfDRAWMODE drawMode ; + uint8 width ; + uint8 vertex ; + dpfLOCK lock ; + dpfSTRINGPTR special ; + +} dpfSURFACE ; + +typedef struct dpfVERTEXTYPE { + struct dpfVERTEXTYPE *next ; + union { + struct dpfGEOMETRYTYPE *geom ; + struct dptTRILISTTYPE *triList ; + } ptr ; + uint8 vertex ; + uint8 flag ; + unsigned short count ; + float32 data[3] ; +} dpfVERTEX ; + +typedef struct dpfVERTBLK { + struct dpfVERTBLK *next ; + dpfVERTEX vert[dpfVBLKSIZE] ; +} dpfVERTBLK, *dpfVERTBLKPTR ; + + +/************************************************************* +* The Following are type defs for the ptmesh utility * +*************************************************************/ + +typedef struct dptTRILISTTYPE +{ + struct dptTRIANGLETYPE *triangle ; + struct dptTRILISTTYPE *next ; +} dptTRILIST, *dptTRILISTPTR ; + +typedef struct dptCONNECTTYPE +{ + struct dptTRIANGLETYPE *connection ; + int32 p1 ; + struct dptCONNECTTYPE *next ; +} dptCONNECT, *dptCONNECTPTR ; + +typedef struct dptTRIANGLETYPE +{ + dpfPATCHPTR patch ; + dpfVERTEXPTR points[3] ; + dptCONNECTPTR connections ; + dmVector normal ; + /* Beware of using the octPos flag. it is used in the flipper, octize, + ** spatial divide and the unloading of meshes + */ + int32 octPos ; + struct dptTRIANGLETYPE *next, *prev ; +} dptTRIANGLE ; + +typedef struct +{ + dpfPATCHPTR patch ; + dptTRIANGLEPTR LTrian, RTrian ; + int32 LVertNo, RVertNo ; + int32 ROrient, LOrient ; + int32 noVerts ; + int32 octPos ; +} dptSAVEBLOCK, *dptSAVEBLOCKPTR ; + +typedef struct dptMESHTYPE { + dpfVERTEXPTR *hash_tbl ; + dptTRIANGLEPTR trian_hd, trian_tl ; + dpfGEOMETRYPTR geom_hd, geom_tl ; + duBlkCtrl conBC, trilBC, trisBC ; + int32 hash_size, normals ; + int32 No_trian, No_verts ; + int32 noGroups ; + int32 DropTri ; +} dptMESH ; + + +/************************************************************/ + + +typedef struct dpfCLISTTYPE +{ + int32 pcount ; + int32 fcount ; + int32 DataLength ; + struct dpfGEOMETRYTYPE *geom; + struct dpfCLISTTYPE *next ; + int32 *faces ; +} dpfCLIST ; + +typedef struct dpfSLISTTYPE +{ + int32 pcount ; + int32 vcount ; + int32 DataLength ; + struct dpfGEOMETRYTYPE *geom; + struct dpfSLISTTYPE *next ; + int32 *faces ; +} dpfSLIST ; + +/* 4th float of point (point[dpf_U]) is used as radius */ +typedef struct dpfSPHERENODETYPE +{ + dmVector point ; + float32 radius ; + struct dpfGEOMETRYTYPE *geom; + struct dpfSPHERENODETYPE *next ; + int32 *block ; +} dpfSPHERENODE ; + +typedef struct dpfTEXTNODETYPE +{ + dmVector point ; + char *string ; + struct dpfGEOMETRYTYPE *geom; + struct dpfTEXTNODETYPE *next ; + int32 *block ; +} dpfTEXTNODE ; + +typedef struct dpfSTRIPTYPE { + dpfVERTEXPTR point_hd, point_tl ; + union + { + uint8 thickness ; + float32 size ; + } data ; + int32 noVertex, pDataLength ; +} dpfSTRIP, *dpfSTRIPPTR ; + +typedef struct dpfPMESHTYPE { + dpfVERTEXPTR point_hd, point_tl ; + dpfCLISTPTR cList_hd, cList_tl ; + dpfSLISTPTR sList_hd, sList_tl ; + int32 noVertex, pDataLength ; + int32 noCList, clDataLength ; + int32 noSList, slDataLength ; +} dpfPMESH, *dpfPMESHPTR ; + +typedef struct dpfSPHERETYPE { + uint16 dice_u, dice_v ; + dpfSPHERENODEPTR sphere_hd, sphere_tl ; + int32 noSphereNode, sDataLength ; +} dpfSPHERE, *dpfSPHEREPTR ; + +typedef struct dpfLETTEXTTYPE { + dpfFONT font ; + dmVector scale, orientation ; + dpfTEXTNODEPTR text_hd, text_tl ; + int32 noTextNode, tDataLength ; +} dpfLETTEXT, *dpfLETTEXTPTR ; + +typedef struct dpfGEOMETRYTYPE +{ + int32 geomType ; + union + { + dpfSTRIPPTR strip ; + dpfPMESHPTR pmesh ; + dpfSPHEREPTR sphere ; + dpfLETTEXTPTR text ; + } u_data ; + int32 dataLength ; + struct dpfPATCHTYPE *patch; + struct dpfGEOMETRYTYPE *next ; +} dpfGEOMETRY ; + + +typedef struct dpfPATCHTYPE { + dpfSURFACE surface; + dpfGEOMETRYPTR geom_hd; + dpfGEOMETRYPTR geom_tl; + int32 dataLength ; + struct dpfLODTYPE *LOD ; + struct dpfPATCHTYPE *next; +} dpfPATCH ; + +typedef struct dpfLODTYPE +{ + char *name ; + float32 inDist, outDist ; + dpfTRANSITION transition ; + int32 referenceFlag ; + dmVector reference ; + dpfPATCHPTR patch_hd; + dpfPATCHPTR patch_tl; + dpfSTRINGPTR special ; + int32 dataLength ; + struct dpfOBJECTTYPE *object; + struct dpfLODTYPE *next ; +} dpfLOD ; + +typedef struct dpfOBJECTTYPE { + dpfSURFACE surface; + dpfLODPTR LOD_hd; + dpfLODPTR LOD_tl; + int32 dataLength ; + struct dpfOBJECTTYPE *next; + struct dpfFILE_TYPE *file; +} dpfOBJECT ; + +typedef struct dpfHEADERTYPE +{ + uint8 verMajor, verMinor; + uint8 day, month, year ; + uint8 hours, minutes ; + uint8 headerLoaded ; + float32 scale ; + dpfPRECISION precision ; + dpfSTRINGPTR comment ; + dpfUNIT unit ; + dpfSTRINGPTR special ; + int32 dataLength ; + dpfFILEFORMAT type; +} dpfHEADER ; + + +typedef struct dpfBOUNDTYPE +{ + char *objectName ; + char *LODName ; + dpfAUTO Auto ; + + uint8 gotBSphere ; + dmVector sphPoint ; + float32 sphRadius ; + + uint8 gotBBox ; + dmVector boxMax, boxMin ; + dmVector boxOrien ; + + dpfGEOMETRYPTR pmesh ; + + dpfSTRINGPTR special ; + int32 dataLength ; + + dpfBOUNDPTR child_hd ; + dpfBOUNDPTR child_tl ; + + dpfBOUNDPTR next ; + dpfBOUNDPTR parent ; + dpfFILEPTR file ; +} dpfBOUND ; + + +/* dpfFILETYPE => dpfFILE_TYPE to stop conflict */ +typedef struct dpfFILE_TYPE +{ + dpfHEADER header ; + + dpfFILETYPE type; + dpfFILEMODE mode; + char *fileName ; + dflFILEPTR fl ; + int32 lineNo, newMaterialCount ; + int32 dataLength, blockDepth, blockEnd[dpf_MAX_DEPTH] ; + + dpfTEXTUREPTR texture_hd ; + dpfTEXTUREPTR texture_tl ; + dpfMATERIALPTR material_hd ; + dpfMATERIALPTR material_tl ; + dpfRAMPPTR ramp_hd ; + dpfRAMPPTR ramp_tl ; + + dpfBOUNDPTR bound ; + + dpfOBJECTPTR object_hd; + dpfOBJECTPTR object_tl; + + dpfTOKEN curtok; + int32 curtag; + float32 semfloat ; + int32 semint ; + + int32 noMaterials, noTextures, noRamps ; + int32 noObjects, noLODs, noPatches ; + int32 noGeometries, noPmeshes ; + int32 noCLists, noCFaces, cFtimesP ; + int32 noSLists, noSFaces, sFtimesP ; + int32 noPolystrips, noTristrips ; + int32 noPolygons, noPolyVerts ; + int32 noVertices, noVertLists, noTriangles ; + int32 noSphereLists, noSpheres ; + int32 noPointLists, noPoints ; + int32 noLineLists, noLines ; + int32 noTextLists, noTexts ; + + dpfVISTEXTUREPTR visList ; + int32 mazSearched ; + char *FtextName, *BtextName ; + uint8 forceVer ; +} dpfFILE ; + +/*****************************************************************************/ +/* Global variables and macros */ +/*****************************************************************************/ + +/* Internal functions */ + +extern int32 (*dpfReadFloatP)(dpfFILEPTR file,float32 *dest); +extern int32 (*dpfReadnFloatP)(dpfFILEPTR file, int32 n, float32 *dest); + +/* Reading data */ +int32 +dpfReadFloatPSS(dpfFILEPTR file,float32 *dest) ; +int32 +dpfReadFloatPSD(dpfFILEPTR file,float32 *dest) ; +int32 +dpfReadFloatPDS(dpfFILEPTR file,float64 *dest) ; +int32 +dpfReadFloatPDD(dpfFILEPTR file,float64 *dest) ; + +int32 +dpfReadnFloatPSS(dpfFILEPTR file,int32 n, float32 *dest) ; +int32 +dpfReadnFloatPSD(dpfFILEPTR file,int32 n, float32 *dest) ; +int32 +dpfReadnFloatPDS(dpfFILEPTR file,int32 n, float64 *dest) ; +int32 +dpfReadnFloatPDD(dpfFILEPTR file,int32 n, float64 *dest) ; + +#define dpfRead1byte(file,dest) dflRead1byte(file->fl,(void *)(dest)) +#define dpfReadn1byte(file,n,dest) dflReadn1byte(file->fl,n,(void *)(dest)) +#define dpfRead2byte(file,dest) dflRead2byte(file->fl,(void *)(dest)) +#define dpfReadn2byte(file,n,dest) dflReadn2byte(file->fl,n,(void *)(dest)) +#define dpfRead4byte(file,dest) dflRead4byte(file->fl,(void *)(dest)) +#define dpfReadn4byte(file,n,dest) dflReadn4byte(file->fl,n,(void *)(dest)) +#define dpfRead8byte(file,dest) dflRead8byte(file->fl,(void *)(dest)) +#define dpfReadn8byte(file,n,dest) dflReadn8byte(file->fl,n,(void *)(dest)) + +/* Writing data */ +#define dpfFwriteint8(file,i) dflWriteint8(file->fl,i) +#define dpfFwriteuint8(file,i) dflWriteuint8(file->fl,i) +#define dpfFwriteint16(file,i) dflWriteint16(file->fl,i) +#define dpfFwriteuint16(file,i) dflWriteuint16(file->fl,i) +#define dpfFwriteint32(file,i) dflWriteint32(file->fl,i) +#define dpfFwritefloat32(file,f) dflWritefloat32(file->fl,f) +#define dpfFwritefloat64(file,f) dflWritefloat64(file->fl,f) +void +dpfFwriteFloatP(dpfFILEPTR file, float32 f) ; + +/* pfcheck checks input values */ +int32 +dpfRgbNotUnit(dpfRGBA r) ; +int32 +dpfRgbNotZero(dpfRGBA r) ; +float32 +dpfCheckRGBValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckAlphaValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckV1PowerValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckV2PowerValue(dpfFILEPTR file, float32) ; +float32 +dpfCheckOpacityValue(dpfFILEPTR file, float32) ; +#define dpfV12v2PowerConvert(p) p +#define dpfV22v1PowerConvert(p) \ + ((p > dpfV1POWER_MAX) ? dpfV1POWER_MAX:p) + +/* Dirty data structure stuff */ +/* Does not unlink from structure so be careful */ +int32 +dpfFreeVertexList(dpfVERTEXPTR vert) ; +int32 +dpfFreeCListList(dpfCLISTPTR cList) ; +int32 +dpfFreeGeometryList(dpfGEOMETRYPTR geometry) ; +int32 +dpfFreeSurfaceNames(dpfSURFACEPTR surface) ; +int32 +dpfFreePatchList(dpfPATCHPTR patch) ; +int32 +dpfFreeLODList(dpfLODPTR lod) ; +int32 +dpfFreeObjectList(dpfOBJECTPTR object) ; + +int32 +dpfFreeBoundList(dpfBOUNDPTR bound) ; +int32 +dpfFreeTextureList(dpfTEXTUREPTR txt) ; +int32 +dpfFreeMaterialList(dpfMATERIALPTR mat) ; +int32 +dpfFreeRampList(dpfRAMPPTR ramp) ; + + +/* Use setSurface, not copySurface, does not free name memory if +** dest suface has already got names +*/ +void +dpfCopySurface(dpfSURFACEPTR dest, dpfSURFACEPTR source); + +dpfFILETYPE +dpfIdentifyFile(dflFILEPTR fp) ; + + +int32 +dpfGetB1FileBody(dpfFILEPTR file) ; +int32 +dpfGetV1FileBody(dpfFILEPTR file) ; +int32 +dpfGetB2FileBody(dpfFILEPTR file) ; +int32 +dpfGetV2FileBody(dpfFILEPTR file) ; +int32 +dpfPutB1FileBody(dpfFILEPTR Dfile, dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutV1FileBody(dpfFILEPTR Dfile, dpfFILEPTR Sfile, dpfFILEPTR matFile) ; +int32 +dpfPutB2FileBody(dpfFILEPTR dest, dpfFILEPTR infile) ; +int32 +dpfPutV2FileBody(dpfFILEPTR dest, dpfFILEPTR infile) ; + +void +dpfConvertV1Texture(dpfFILEPTR Sfp, dpfMATERIALPTR Fmat, dpfMATERIALPTR Bmat) ; + +void +VIZsetLexdfl(dflFILEPTR fl); + +#endif /* ____PFILE_H__ */ diff --git a/MUNGA_L4/libDPL/dsys/__PTOOL.H b/MUNGA_L4/libDPL/dsys/__PTOOL.H new file mode 100644 index 0000000..d99938e --- /dev/null +++ b/MUNGA_L4/libDPL/dsys/__PTOOL.H @@ -0,0 +1,84 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1995 Division Limited. +-- All Rights Reserved +-- +-- +-- System : +-- Module : +-- Object Name : $RCSfile: __ptool.h,v $ +-- Revision : $Revision: 1.11 $ +-- Date : $Date: 95/05/16 13:46:18 $ +-- Author : $Author: bill $ +-- +-- Description +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ +/* __ptools2.h */ +#ifndef ____PTOOL_H__ +#define ____PTOOL_H__ + +#ifdef _PF_LOCAL +#include "ptool.h" +#else +#include +#endif + +/* ver change */ +/* 2.01 Initial version for tools library */ +/* 2.02 New line definitions and coping with texture etc */ +/* 2.03 New material stuff */ +/* 2.04 New STRIP_LIST and POINTLIST */ +#define dpt_LIBRARY_MAJOR_VER 2 +#define dpt_LIBRARY_MINOR_VER 04 + +#define dpt_TINY_float32 1.0e-24 + + + +/************************************************************* +* ptmesh Routines used by other dptOols * +*************************************************************/ + +dpfVERTEXPTR +dptCreateVertex(void) ; +dpfVERTEXPTR +dptMeshAddVertex ( dptMESHPTR mesh, dpfVERTEXPTR Fvert ) ; +dpfVERTEXPTR +dptMeshAddNewVertex(dptMESHPTR mesh, dpfPATCHPTR patch, dmVector point, + dmVector norm, dpfRGBA col, dpfTEXT text) ; +dptTRIANGLEPTR +dptMeshAddTriangle(dptMESHPTR mesh, dpfPATCHPTR patch, dpfVERTEXPTR vert1, + dpfVERTEXPTR vert2, dpfVERTEXPTR vert3) ; +void +dptMeshRemoveTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptMeshUnloadGeometry(dptTRIANGLEPTR start, dptMESHPTR mesh, dpfPATCHPTR patch, + int32 usePmesh) ; +void +dptMeshDisconnectTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptMeshConnectTriangle(dptMESHPTR mesh, dptTRIANGLEPTR trian) ; +void +dptAddGeometryPatch(dptMESHPTR mesh, dpfGEOMETRYPTR geom) ; + + +/* reduce a mesh, used in ptbound */ +int32 +dptrReduceMesh(dptMESHPTR mesh, float32 Norm_tol, float32 Edge_tol, + int32 Verbose) ; + +/* defined in ptreduce, used also in ptflip */ +dptTRIANGLEPTR +dptGetTriangleDuplicate(dptTRIANGLEPTR tri) ; + +#endif /* ____PTOOL_H__ */ + + diff --git a/MUNGA_L4/libDPL/dvs/DM.H b/MUNGA_L4/libDPL/dvs/DM.H new file mode 100644 index 0000000..ed60e72 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/DM.H @@ -0,0 +1,29 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * File: $RCSfile: dm.h,v $ + * Revision: $Revision: 1.3 $ + * Date: $Date: 1995/05/18 09:48:43 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: dm.h,v 1.3 1995/05/18 09:48:43 jeff beta $ + * + * FUNCTION: + * + * + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _DVS_DM_H +#define _DVS_DM_H +#include +#include +#endif /*_DVS_DM_H */ diff --git a/MUNGA_L4/libDPL/dvs/DMELEM.H b/MUNGA_L4/libDPL/dvs/DMELEM.H new file mode 100644 index 0000000..940a4b0 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/DMELEM.H @@ -0,0 +1,132 @@ +/* + * WARNING: machine generated code. + * + * do NOT edit this file, edit the + * original '.epp' file and regenerate this + * one. + */ + +#ifndef ____DMELEM_H +#define ____DMELEM_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Instance number access macros. + */ + + + +/* + * Generated function declarations. + */ +extern int32 ModuleDmInit ( void ); + +extern InstanceNo (VLCreate_dmVector)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmVector)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmVector)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmVector)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmPoint)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmPoint)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmPoint)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmPoint)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmEuler)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmEuler)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmEuler)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmEuler)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmQuaternion)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmQuaternion)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmQuaternion)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmQuaternion)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmScale)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmScale)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmScale)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmScale)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmMatrix)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmMatrix)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmMatrix)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmMatrix)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_dmPosition)(dmPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_dmPosition)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_dmPosition)(InstanceNo ino, dmPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_dmPosition)(InstanceNo ino , dmPosition *data, VLTime *utime); + +#ifdef __VL_INLINE_ACCESS__ +#define VLCreate_dmVector( d, t, m) vlCreateInstance(el_dmVector, 0, (d),(t),(m)) +#define VLDelete_dmVector(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmVector( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmVector(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmPoint( d, t, m) vlCreateInstance(el_dmPoint, 0, (d),(t),(m)) +#define VLDelete_dmPoint(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmPoint( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmPoint(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmEuler( d, t, m) vlCreateInstance(el_dmEuler, 0, (d),(t),(m)) +#define VLDelete_dmEuler(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmEuler( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmEuler(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmQuaternion( d, t, m) vlCreateInstance(el_dmQuaternion, 0, (d),(t),(m)) +#define VLDelete_dmQuaternion(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmQuaternion( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmQuaternion(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmScale( d, t, m) vlCreateInstance(el_dmScale, 0, (d),(t),(m)) +#define VLDelete_dmScale(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmScale( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmScale(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmMatrix( d, t, m) vlCreateInstance(el_dmMatrix, 0, (d),(t),(m)) +#define VLDelete_dmMatrix(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmMatrix( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmMatrix(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_dmPosition( d, t, m) vlCreateInstance(el_dmPosition, 0, (d),(t),(m)) +#define VLDelete_dmPosition(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_dmPosition( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_dmPosition(i,d,t) vlExtractInstance((i),(d),(t)) + +#endif +/* + * Symbolic element names. + */ +extern const ElementHandle el_dmVector; +extern const ElementHandle el_dmPoint; +extern const ElementHandle el_dmEuler; +extern const ElementHandle el_dmQuaternion; +extern const ElementHandle el_dmScale; +extern const ElementHandle el_dmMatrix; +extern const ElementHandle el_dmPosition; + +static const int ElCountDm = 7; + +/* + * Epp declaraions. NOT 'C' - hence the ifdef guard! + */ +#ifdef __EPP__ +%% +extern atomic element dmVector; +extern atomic element dmPoint; +extern atomic element dmEuler; +extern atomic element dmQuaternion; +extern atomic element dmScale; +extern atomic element dmMatrix; +extern atomic element dmPosition; +%% +#endif/* __EPP__ */ +#ifdef __cplusplus +} +#endif +#endif /* ____DMELEM_H */ diff --git a/MUNGA_L4/libDPL/dvs/VC.H b/MUNGA_L4/libDPL/dvs/VC.H new file mode 100644 index 0000000..a009e61 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VC.H @@ -0,0 +1,818 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vctools.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:08 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctools.h,v 0.10 1994/10/05 12:51:14 john Exp jon $ + * + * FUNCTION: + * + * Copyright (c) 1992 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine reable form without prior + * written consent from Division Ltd. + */ + +#ifndef _VCTOOLS_H_ +#define _VCTOOLS_H_ +#ifdef NDEBUG +#define NVCDEBUG 1 +#endif + +#include +#include +#include +#include /* VL definitions */ +#include +#include +#include +#include +#include + +# ifdef __cplusplus +extern "C" { +# endif + +#ifdef _LIB_VC +#include /* VC constant defintions */ +#include "_vcdefs.h" +#include "_vctypes.h" +#include /* VC Type definitions */ +#include +#include +#include + + +#if !defined ( __EPP__) && !defined (_VCELEMEN_C) +#include /* VC Element definitions */ +#endif + +#include "_vcstruct.h" +#include "vcstruct.h" +#include /* Object definitions */ +#include /* Verbose reporting. */ +#include +#include +#include +#include +#include "_vctools.h" +#include "vcmacros.h" +#else + +#include /* VC constant defintions */ +#include +#include /* VC Type definitions */ +#include /* VC Type definitions */ +#include +#include +#if !defined ( __EPP__) && !defined (_VCELEMEN_C) +#include /* VC Element definitions */ +#endif +#include +#include +#include /* Object definitions */ +#include /* Verbose reporting. */ +#include +#include +#include +#include +#include +#endif +/* + * Function definitions + */ +/* + *Create & Initialisation routines + */ +void vcVersion (FILE *fp); + +ActorId VC_InitActor(int *argc, char **argv, char *actorName, + VCActorConfig *actorConfig, uint32 mode, + VC_VersionFunc versionFunc); + +ActorId VC_InitApplication(int *argc, char **argv, VC_VersionFunc versionFunc); +int VCErrorInit(char *agentName, char *actorName, int verboseLevel, int debugLevel, + int log, char *log_ext); + + +/* + * Callback routines + */ + +void VC_MainLoop (void); +void VC_ProcessEvent (VLAction action, VLEventData *eventData); + + +void *VC_GetCallbackHandle(void); + +void *VCSignal_AttachCallback (int sigNum, VC_SignalFunc callback, void *data); +void *VC_AttachExitCallback(VC_ExitFunc function, void *data); +void *VCTimer_AttachPeriodicCallback (float t, VCTimer_Func function, void *data); +void *VCTimer_AttachExpiringCallback (float t, VCTimer_Func function, void *data) ; +int VCTimer_DetachCallback(void *callbackHandle); + +void *VCTimer_AttachCallback (VLTime *time, VLTimerMode mode, + VCTimer_Func function, void *data); +void *VCStream_AttachCallback (int streamId, VC_StreamFunc function, void *data); +void *_VC_AttachCreateCallback (ElementHandle elem, InstanceNo inst, VC_CallbackFunc callback, void *data); +void *_VC_AttachDeleteCallback (ElementHandle elem, InstanceNo inst, VC_CallbackFunc callback, void *data); +void *_VC_AttachUpdateCallback (ElementHandle elem, InstanceNo inst, VC_CallbackFunc callback, void *data); +int VCSignal_DetachCallback (int sigNum, void *callbackHandle); +int VC_DetachExitCallback(void *callbackHandle); +int VCStream_DetachCallback (int streamId, void *callbackHandle); +int _VC_DetachCreateCallback (void *callbackHandle, ElementHandle Element, InstanceNo inst); +int _VC_DetachUpdateCallback (void *callbackHandle, ElementHandle element, InstanceNo instNo); +int _VC_DetachDeleteCallback (void *callbackHandle, ElementHandle element, InstanceNo inst); + +/* + * Miscellaneous routines + */ +int VCPosition_MakePointEulerScale (VCPositionData *pos, dmPoint p, dmEuler e, dmScale s); +int VCPosition_ChangePointEulerScale (VCPositionData *pos, dmPoint p, dmEuler e, dmScale s); +uint32 VC_GetNewVcId(void); +void vcInitEnvironment(void); + + +/* + * Name table stuff + */ +duHashTab *VCInstanceTable_Create(int numEntries); +void VCInstanceTable_Delete(duHashTab *table); +void *VCInstanceTable_Get(duHashTab *table, InstanceNo inst, + int *status); +int VCInstanceTable_Attach(duHashTab *table, InstanceNo inst, void + *data, int flags); +void *VCInstanceTable_Detach(duHashTab *table, InstanceNo inst, + int *status); + + +int VCActor_InitResource (char *nameExtension, char *type, uint32 mode, + VCResource_AllocateFunc allocateFunc, + VCAttribute_InvalidFunc deAllocateFunc, + VCAttribute_RelocateFunc relocateFunc, + VCAttribute_Func updateFunc, void *data); + + +/* + * Body handling functions + */ + +int VCBody_Link (VCBody *body, VCEntity *entity, uint32 linkMode); +int VCBody_Unlink(VCBody *body, uint32 unlinkMode); +VCAttribute *VCBody_GetBodyPart (VCBody *body, char *limbName); +int VCBody_Set (VCBody *body, VCBodyFlyInfoData *flyForward, VCBodyFlyInfoData *flyBackward, + VCBodyFlyInfoData *flyUp, VCBodyFlyInfoData *flyDown, VCBodyFlyInfoData *flyLeft, + VCBodyFlyInfoData *flyRight, VCBodyFlyInfoData *rotLeft, VCBodyFlyInfoData *rotRight, + VCBodyFlyInfoData *rotUp, VCBodyFlyInfoData *rotDown, uint32 *verticalFlyKeyCode, + uint32 *altFlyKeyCode, VCEntity *flyDirectionLimb, VCEntity *altFlyDirectionLimb, + VCEntity *altFlyLimb, uint32 setFlyMode, uint32 clearFlyMode); +int VCBody_Get (VCBody *body, uint32 *actorId, VCBodyFlyInfoData *flyForward, VCBodyFlyInfoData *flyBackward, + VCBodyFlyInfoData *flyUp, VCBodyFlyInfoData *flyDown, VCBodyFlyInfoData *flyLeft, + VCBodyFlyInfoData *flyRight, VCBodyFlyInfoData *rotLeft, VCBodyFlyInfoData *rotRight, + VCBodyFlyInfoData *rotUp, VCBodyFlyInfoData *rotDown, uint32 *verticalFlyKeyCode, + uint32 *altFlyKeyCode, VCEntity **flyDirectionLimb, VCEntity **altFlyDirectionLimb, + VCEntity **altFlyLimb, uint32 *flyMode, char **name, + char **user, char **role); +int VCBody_SetData (VCBody *body, VCBodyData *bodyData); +int VCBody_GetData (VCBody *body, VCBodyData *bodyData); + + + +int VCBody_GetAbsolutePosition(VCBody *body, dmMatrix mat); +int VCBody_SetPosition(VCBody *body, VCAttribute *bodyPart, dmPoint point, dmEuler rotation, dmScale scale, + VCEntity *entity, uint32 flags); + +int VCBody_SetSlowSpeed(VCBody *body, float minSpeed); +int VCBody_SetMaxSpeed(VCBody *body, float maxSpeed); +int VCBody_SetFastSpeed(VCBody *body, float fastSpeed); +int VCBody_SetAcceleration(VCBody *body, float acceleration); +int VCBody_SetSlowRotation(VCBody *body, float minRot); +int VCBody_SetFastRotation(VCBody *body, float fastRot); +int VCBody_SetMaxRotation(VCBody *body, float maxRot); +int VCBody_SetRotateAcceleration(VCBody *body, float acceleration); +int VCBody_SetFlyForwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyBackwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetFlyDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetRotDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_SetVerticalFlyKeyCode(VCBody *body, uint32 keyCode); +int VCBody_SetAltFlyKeyCode(VCBody *body, uint32 keyCode); +int VCBody_SetFlyDirectionLimb(VCBody *body, VCEntity *flyLimb); +int VCBody_SetAltFlyDirectionLimb(VCBody *body, VCEntity *flyLimb); +int VCBody_SetAltFlyLimb(VCBody *body, VCEntity *flyLimb); +int VCBody_SetFlyMode(VCBody *body, uint32 flyMode); +int VCBody_ModifyFlyMode(VCBody *body, uint32 setFlyMode, uint32 clearFlyMode); +int VCBody_GetActorId(VCBody *body, uint32 *actorId); +int VCBody_GetFlyForwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyBackwardInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetFlyDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotLeftInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotRightInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotUpInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetRotDownInfo(VCBody *body, VCBodyFlyInfoData *flyData); +int VCBody_GetVerticalFlyKeyCode(VCBody *body, uint32 *keyCode); +int VCBody_GetAltFlyKeyCode(VCBody *body, uint32 *keyCode); +int VCBody_GetFlyDirectionLimb(VCBody *body, VCEntity **flyLimb); +int VCBody_GetAltFlyDirectionLimb(VCBody *body, VCEntity **flyLimb); +int VCBody_GetAltFlyLimb(VCBody *body, VCEntity **flyLimb); +int VCBody_GetFlyMode(VCBody *body, uint32 *flyMode); +int VCBody_GetName(VCBody *body, char **name); +int VCBody_GetUser(VCBody *body, char **user); +int VCBody_GetRole(VCBody *body, char **role); +int VCBody_SetVisualResourceBackgroundColour(VCBody *body, VCColour colour); +int VCBody_SetVisualResourceNearClip(VCBody *body, float32 nearClip); +int VCBody_SetVisualResourceFarClip(VCBody *body, float32 farClip); +int VCBody_SetVisualResourceFogColour(VCBody *body, VCColour colour, uint32 fogType, uint32 fogMode); +int VCBody_SetVisualResourceNearFog(VCBody *body, float32 nearFog); +int VCBody_SetVisualResourceFarFog(VCBody *body, float32 farFog); +int VCBody_SetAudioResourceResourceFile(VCBody *body, char *resourceFile); +int VCBody_SetAudioResourceVolume(VCBody *body, float32 volume); +int VCBody_SetAudioResourceSpreadingRollOff(VCBody *body, float32 spreadingRollOff); +int VCBody_SetAudioResourceAtmosphericAbsorption(VCBody *body, float32 atmosphericAbsorption); + + +void *VCBody_AttachAttributeCallback (VCBody *body, char *limbName, + ElementHandle element, VCBody_AttributeFunc func, + void *data); +int VC_UseBody(char *name); +void *VC_AttachBodyCreateCallback(VCBody_CreateFunc func , void *data); + + +void *VCBody_AttachInputCallback (VCBody *body, char *limbName, uint32 keyCode, uint32 maxKeyCode, + VCBody_InputFunc func, void *data); +void *VCBody_AttachCollisionCallback (VCBody *body, char *limbName, VCBody_CollisionFunc func, + void *data); +void *VCBody_AttachBodyPartCreateCallback(VCBody *body, VCBody_CreateBodyPartFunc func, + void *data); +int VCEntity_Pick (VCEntity *entity , VCAttribute *bodyPart, + VCEntity_DropFunc dropFunc, void *data); +int VCEntity_Drop(VCEntity *entity, VCAttribute *bodyPart); + + +VCBody *VC_GetFirstBody(VC_Traverse *traverseInfo); +VCBody *VC_GetNextBody(VC_Traverse *traverseInfo); +VCBody * VCAttribute_GetBody (VCAttribute *attribute); +VCAttribute *VCBody_GetFirstAttribute (VCBody *body, char *limbName, ElementHandle elem, + VC_Traverse *traverseInfo); +VCAttribute *VCBody_GetNextAttribute (VC_Traverse *traverseInfo); + + +/* + * Hierarchy function routines + */ + +int VC_SetObjectTableSize(int tabsize); +int VCEntity_GetDefaultNumAttributes(void); +int VCEntity_SetDefaultNumAttributes( int numAttributes); +void VCEntityAposInvalid(VCEntity *entity); +int VCAttribute_Get(VCAttribute *attribute, int doExtract); +VCAttribute *VCAttribute_Create(ElementHandle type, InstanceNo inst); +int32 VCAttribute_Delete(VCAttribute *attribute); +VCEntity *VCEntity_Create (VCPositionData *posp, uint32 count ); +int VCEntity_Delete ( VCEntity *entity , uint32 mode); +int VCEntity_SetRelocateMode (VCEntity *entity,int mode); +int VCEntity_GetRelocateMode (VCEntity *entity); +int VCEntity_AttachAttribute (VCEntity *entity, VCAttribute *attribute); +int VCEntity_DetachAttribute (VCEntity *entity, VCAttribute *attribute); +int VCEntity_Link (VCEntity *parent, VCEntity *child, uint32 mode); +int VCEntity_Unlink ( VCEntity *child, uint32 mode); +VCEntity *VCEntity_GetRoot ( VCEntity *entity); +VCEntity *VC_GetFirstEntity ( VCEntity *entity, uint32 incEntity, VC_Traverse *traverse); +VCEntity *VC_GetNextEntity ( VC_Traverse *traverseInfo ); +int VCEntity_GetAbsolutePosition ( VCEntity *entity, dmMatrix mat) ; +void VCEntity_TraverseInOrder(VCEntity *entity, VCEntity_TraverseFunc func, void *data); +void VCEntity_TraversePostOrder(VCEntity *entity, VCEntity_TraverseFunc func, void *data); + +void *VCAttribute_AttachCreateCallback(VCAttribute *attribute, ElementHandle element, + VCAttribute_Func func, void *data); +void *VCAttribute_AttachDeleteCallback(VCAttribute *attribute, ElementHandle element, + VCAttribute_Func func, void *data); +void *VCAttribute_AttachUpdateCallback(VCAttribute *attribute, ElementHandle element, + VCAttribute_Func func, void *data); +int VCAttribute_DetachCreateCallback(VCAttribute *attribute, ElementHandle element, + void *callbackHandle); +int VCAttribute_DetachUpdateCallback(VCAttribute *attribute, ElementHandle element, + void *callbackHandle); +int VCAttribute_DetachDeleteCallback(VCAttribute *attribute, ElementHandle element, + void *callbackHandle); +int VCEntity_DetachAttributeRelocateCallback(ElementHandle element, VCAttribute *attribute, + void *callbackHandle); +void *VCEntity_AttachAttributeRelocateCallback (ElementHandle element, VCAttribute *attribute, + uint32 mode, VCAttribute_RelocateFunc func, + VCAttribute_InvalidFunc inValidFunc, void *data); +int VCEntity_DetachAttributeCreateCallback(VCEntity *entity, void *callbackHandle); +int VCEntity_DetachAttributeUpdateCallback(VCEntity *entity, void *callbackHandle); + +void *VCEntity_AttachAttributeCreateCallback(VCEntity *entity, VCEntity_AttributeFunc func, + void *data); +void *VCEntity_AttachAttributeUpdateCallback(VCEntity *entity, VCEntity_AttributeFunc func, + void *data); + +int VCEntity_DetachRelocateCallback(VCEntity *entity,void *callbackHandle); +void *VCEntity_AttachRelocateCallback(VCEntity *entity, uint32 mode, VCEntity_RelocateFunc func, + VCEntity_InvalidFunc invalidFunc, void *data); + +VCEntity *VCAttribute_GetFirstEntity(VCAttribute *attribute, VC_Traverse *traverse); +VCEntity *VCAttribute_GetNextEntity(VC_Traverse *traverse); + +int _VCList_AttachUserData(VCUserDataList **list, uint32 vcId, void *data); +void *_VCList_GetUserData(VCUserDataList *list, uint32 vcId); +void *_VCList_DetachUserData(VCUserDataList **list, uint32 vcId); + +int VCEntity_SetAbsolutePosition(VCEntity *entity, VCPositionData *pos); +int VCEntity_SetPosition(VCEntity *entity, VCPositionData *pos); +int VCEntity_SetPositionMatrix(VCEntity *entity, dmMatrix mat); +int VCEntity_SetPositionPoint(VCEntity *entity, dmPoint p); +int VCEntity_SetPositionEuler(VCEntity *entity, dmEuler e); +int VCEntity_SetPositionScale(VCEntity *entity, dmScale s); +int VCEntity_SetPositionEulerScale(VCEntity *entity, dmEuler e, dmScale s); +int VCEntity_SetPositionPointEulerScale(VCEntity *entity, dmPoint p, dmEuler e, dmScale s); +int VCEntity_GetPosition(VCEntity *entity, VCPosition **position); +VCPositionData *VCEntity_GetPositionData(VCEntity *); +int VCEntity_GetPositionPointEulerScale(VCEntity *entity, dmPoint p, + dmEuler e, dmScale s); +int VCEntity_SetPositionLinearVelocity(VCEntity *entity, const dmVector velocity); +int VCEntity_SetPositionLinearAcceleration(VCEntity *entity, const dmVector acceleration); +int VCEntity_SetPositionAngularVelocity(VCEntity *entity, const dmVector velocity); +int VCEntity_SetPositionAngularAcceleration(VCEntity *entity, const dmVector acceleration); +VCAttribute *VCEntity_GetFirstAttribute (VCEntity *entity, ElementHandle elem, + VC_Traverse *traverseInfo); +VCAttribute *VCEntity_GetNextAttribute (VC_Traverse *traverseInfo); +int VCEntity_UpdatePosition(VCEntity *entity); + +void *VCCollision_AttachCreateCallback(VCCollision *collision, VCCollision_Func func, void *data); +void *VCCollision_AttachUpdateCallback(VCCollision *collision, VCCollision_Func func, void *data); +void *VCCollision_AttachDeleteCallback(VCCollision *collision, VCCollision_Func func, void *data); +int VCCollision_DetachCreateCallback(VCCollision *collision, void *callbackHandle); +int VCCollision_DetachUpdateCallback(VCCollision *collision, void *callbackHandle); +int VCCollision_DetachDeleteCallback(VCCollision *collision, void *callbackHandle); +void VCCollision_SetCacheMode(VCCollision *collision, uint32 cacheMode); +uint32 VCCollision_GetCacheMode(VCCollision *collision); + +VCCollision *VCCollision_Create(VCAttribute *attribute, VCCollisionReportData *collReportData, + int numCollisionsReported, int numCollisions); +int VCCollision_Get(VCCollision *collision, VCAttribute **attribute, VCCollisionReportData **collReportData, + int *numCollisionsReported, int *numCollisions); +VCCollision *VCCollision_Set(VCAttribute *attribute, VCCollisionReportData *collReportData, + int numCollisionsReported, int *numCollisions); +VCCollisionReportData *VCCollision_GetFirstCollisionReport(VCCollision *collision, VC_Traverse *traverseInfo); +VCCollisionReportData *VCCollision_GetNextCollisionReport(VC_Traverse *traverseInfo); +int VCCollision_Delete(VCCollision *item); + +void VCIntersection_SetCacheMode(VCIntersection *intersection, uint32 cacheMode); +uint32 VCIntersection_GetCacheMode(VCIntersection *intersection); +void *VCIntersection_AttachCreateCallback(VCIntersection *intersection, VCIntersection_Func func, + void *data); +void *VCIntersection_AttachUpdateCallback(VCIntersection *intersection, VCIntersection_Func func, + void *data); +void *VCIntersection_AttachDeleteCallback(VCIntersection *intersection, VCIntersection_Func func, + void *data); +int VCIntersection_DetachCreateCallback(VCIntersection *intersection, void *callbackHandle); +int VCIntersection_DetachUpdateCallback(VCIntersection *intersection, void *callbackHandle); +int VCIntersection_DetachDeleteCallback(VCIntersection *intersection, void *callbackHandle); +VCIntersection *VCIntersection_Create(VCAttribute *attribute, VCIntersectionReportData *intersectReportData, + int numIntersectionsReported, int numIntersections); +int VCIntersection_Get(VCIntersection *intersection, VCAttribute **attribute, + VCIntersectionReportData **intersectReportData, + int *numIntersectionsReported, int *numIntersections); +VCIntersectionReportData *VCIntersection_GetFirstIntersectionReport(VCIntersection *intersection, + VC_Traverse *traverse); +VCIntersectionReportData *VCIntersection_GetNextIntersectionReport(VC_Traverse *traverse); +int VCIntersection_Delete(VCIntersection *item); + + + + +void VCMaterial_SetCacheMode (VCMaterial *item, uint32 newCacheMode); +uint32 VCMaterial_GetCacheMode (VCMaterial *item); +void *VCMaterial_AttachCreateCallback(VCMaterial *item, VCMaterial_Func func, void *data); +void *VCMaterial_AttachUpdateCallback(VCMaterial *item, VCMaterial_Func func, void *data); +void *VCMaterial_AttachDeleteCallback(VCMaterial *item, VCMaterial_Func func, void *data); +int VCMaterial_DetachCreateCallback(VCMaterial *item, void *callbackHandle); +int VCMaterial_DetachUpdateCallback(VCMaterial *item, void *callbackHandle); +int VCMaterial_DetachDeleteCallback(VCMaterial *item, void *callbackHandle); +VCMaterial *VCMaterial_Create (char *name, uint32 mode, VCColor ambient, VCColor diffuse, + VCSpecular specular, VCColor emissive, + VCColor opacity, char *textureName, char *ramp); +VCMaterial *VCMaterial_CreateData (VCMaterialData *materialData); +int VCMaterial_Get (VCMaterial *item, char **name, uint32 *mode, + VCColor ambient, VCColor diffuse, + VCSpecular specular, VCColor emissive, + VCColor opacity, char **textureName, + char **ramp); +int VCMaterial_GetData (VCMaterial *item, VCMaterialData *materialData); +int VCMaterial_SetData (VCMaterial *item,VCMaterialData *materialData); +int VCMaterial_Set (VCMaterial *item, char *name, uint32 setMode, + uint32 clearMode, VCColor ambient, VCColor diffuse, + VCSpecular specular, VCColor emissive, VCColor opacity, + char *textureName, char *ramp); +int VCMaterial_ModifyMode (VCMaterial *item, uint32 setMode, uint32 clearMode); +int VCMaterial_SetName (VCMaterial *item, char *name); +int VCMaterial_SetMode (VCMaterial *item, uint32 mode); +int VCMaterial_SetAmbient (VCMaterial *item, VCColour ambient); +int VCMaterial_SetDiffuse (VCMaterial *item, VCColour diffuse); +int VCMaterial_SetSpecular (VCMaterial *item, VCSpecular specular); +int VCMaterial_SetEmissive (VCMaterial *item, VCColour emissive); +int VCMaterial_SetOpacity (VCMaterial *item, VCColour opacity); +int VCMaterial_SetTexture (VCMaterial *item, char *texture); +int VCMaterial_SetRamp (VCMaterial *item, char *ramp); + +int VCMaterial_GetName (VCMaterial *item, char **name); +int VCMaterial_GetMode (VCMaterial *item, uint32 *mode); +int VCMaterial_GetAmbient (VCMaterial *item, VCColour ambient); +int VCMaterial_GetDiffuse (VCMaterial *item, VCColour diffuse); +int VCMaterial_GetSpecular (VCMaterial *item, VCSpecular specular); +int VCMaterial_GetEmissive (VCMaterial *item, VCColour emissive); +int VCMaterial_GetOpacity (VCMaterial *item, VCColour opacity); +int VCMaterial_GetTexture (VCMaterial *item, char **texture); +int VCMaterial_GetRamp (VCMaterial *item, char **ramp); +int VCMaterial_Delete (VCMaterial *item); + + +void VCTexture_SetCacheMode (VCTexture *item, uint32 newCacheMode); +uint32 VCTexture_GetCacheMode (VCTexture *item); +void *VCTexture_AttachCreateCallback (VCTexture *item, VCTexture_Func func, void *data); +void *VCTexture_AttachUpdateCallback (VCTexture *item, VCTexture_Func func, void *data); +void *VCTexture_AttachDeleteCallback (VCTexture *item, VCTexture_Func func, void *data); +int VCTexture_DetachCreateCallback (VCTexture *item, void *callbackHandle); +int VCTexture_DetachUpdateCallback (VCTexture *item, void *callbackHandle); +int VCTexture_DetachDeleteCallback (VCTexture *item, void *callbackHandle); +VCTexture *VCTexture_Create (char *name, uint32 mode, uint8 minify, uint8 magnify, + uint8 alpha, uint8 wrapU, uint8 wrapV, + uint8 detailType, char *textureMap, char *detailMap); +VCTexture *VCTexture_CreateData (VCTextureData *textureData); +int VCTexture_Get (VCTexture *item, char **name, uint32 *mode, uint8 *minify, + uint8 *magnify, uint8 *alpha, + uint8 *wrapU, uint8 *wrapV, uint8 *detailType, + char **textureMap, char **detailMap); +int VCTexture_GetData (VCTexture *item, VCTextureData *textureData); +int VCTexture_SetData (VCTexture *item,VCTextureData *textureData); +int VCTexture_Set (VCTexture *item, char *name, uint32 setMode, + uint32 clearMode, uint8 *minify, uint8 *magnify, + uint8 *alpha, uint8 *wrapU, uint8 *wrapV, uint8 *detailType, + char *textureMap, char *detailMap); +int VCTexture_ModifyMode (VCTexture *item, uint32 setMode, uint32 clearMode); +int VCTexture_SetName (VCTexture *item, char *name); +int VCTexture_SetMode (VCTexture *item, uint32 mode); +int VCTexture_SetMinify (VCTexture *item, uint8 minify); +int VCTexture_SetMagnify (VCTexture *item, uint8 magnify); +int VCTexture_SetAlpha (VCTexture *item, uint8 alpha); +int VCTexture_SetWrapU (VCTexture *item, uint8 wrapU); +int VCTexture_SetWrapV (VCTexture *item, uint8 wrapV); +int VCTexture_SetDetailType (VCTexture *item, uint8 detailType); +int VCTexture_SetTextureMap (VCTexture *item, char *textureMap); +int VCTexture_SetDetailMap (VCTexture *item, char *detailMap); +int VCTexture_GetName (VCTexture *item, char **name); +int VCTexture_GetMode (VCTexture *item, uint32 *mode); +int VCTexture_GetMinify (VCTexture *item, uint8 *minify); +int VCTexture_GetMagnify (VCTexture *item, uint8 *magnify); +int VCTexture_GetAlpha (VCTexture *item, uint8 *alpha); +int VCTexture_GetWrapU (VCTexture *item, uint8 *wrapU); +int VCTexture_GetWrapV (VCTexture *item, uint8 *wrapV); +int VCTexture_GetDetailType (VCTexture *item, uint8 *detailType); +int VCTexture_GetTextureMap (VCTexture *item, char **textureMap); +int VCTexture_GetDetailMap (VCTexture *item, char **detailMap); +int VCTexture_Delete (VCTexture *item); + +void VCInput_SetCacheMode (VCInput *item, uint32 newCacheMode); +uint32 VCInput_GetCacheMode (VCInput *item); +VCInput *_VC_GetInput (InstanceNo inst); +void *VCInput_AttachCreateCallback (VCInput *item, VCInput_Func func, void *data); +void *VCInput_AttachUpdateCallback (VCInput *item, uint32 minKeyCode, uint32 maxKeyCode, + VCInput_UpdateFunc func, void *data); +void *VCInput_AttachDeleteCallback (VCInput *item, VCInput_Func func, void *data); +int VCInput_DetachCreateCallback (VCInput *item, void *callbackHandle); + +int VCInput_DetachUpdateCallback (VCInput *item, void *callbackHandle); +int VCInput_DetachDeleteCallback (VCInput *item, void *callbackHandle); +VCInput *VCInput_Create (uint32 size); +int VCInput_Append(VCInput *item, uint32 keyCode, int doUpdate); +int VCInput_Update(VCInput *item); +int VCInput_Delete(VCInput *item); + + + + + + +void VCTracker_SetCacheMode(VCTracker *item, uint32 newCacheMode); +uint32 VCTracker_GetCacheMode(VCTracker *item); +void *VCTracker_AttachCreateCallback(VCTracker *item, VCTracker_Func func, void *data); +void *VCTracker_AttachUpdateCallback(VCTracker *item, VCTracker_Func func, void *data); +void *VCTracker_AttachDeleteCallback(VCTracker *item, VCTracker_Func func, void *data); +int VCTracker_DetachCreateCallback(VCTracker *item, void *callbackHandle); +int VCTracker_DetachUpdateCallback(VCTracker *item, void *callbackHandle); +int VCTracker_DetachDeleteCallback(VCTracker *item, void *callbackHandle); +VCTracker *VCTracker_Create(char *name, uint32 updateRate, uint32 transmissionDelay, dmPoint sourcePosition, + dmEuler sourceEuler, uint32 baudRate, char *deviceType); +VCTracker *VCTracker_CreateData(VCTrackerData *trackerData); +int VCTracker_Get(VCTracker *item, char **name, uint32 *updateRate, uint32 *transmissionDelay, dmPoint sourcePosition, + dmEuler sourceEuler, uint32 *baudRate, char **deviceType); +int VCTracker_GetData(VCTracker *item, VCTrackerData *trackerData); +int VCTracker_SetData (VCTracker *item,VCTrackerData *trackerData); +int VCTracker_Set(VCTracker *item, char *name, uint32 *updateRate, uint32 *transmissionDelay, dmPoint sourcePosition, + dmEuler sourceEuler, uint32 *baudRate, char *deviceType); +int VCTracker_SetName(VCTracker *item, char *name); +int VCTracker_SetUpdateRate(VCTracker *item, uint32 updateRate); +int VCTracker_SetTransmissionDelay(VCTracker *item, uint32 transmissionDelay); +int VCTracker_SetSourcePosition(VCTracker *item, dmPoint sourcePosition); +int VCTracker_SetSourceEuler(VCTracker *item, dmPoint sourceEuler); +int VCTracker_SetBaudRate(VCTracker *item, uint32 baudRate); +int VCTracker_SetDeviceType(VCTracker *item, char *deviceType); +int VCTracker_GetName(VCTracker *item, char **name); +int VCTracker_GetUpdateRate(VCTracker *item, uint32 *updateRate); +int VCTracker_GetTransmissionDelay(VCTracker *item, uint32 *transmissionDelay); +int VCTracker_GetSourcePosition(VCTracker *item, dmPoint sourcePosition); +int VCTracker_GetSourceEuler(VCTracker *item, dmPoint sourceEuler); +int VCTracker_GetBaudRate(VCTracker *item, uint32 *baudRate); +int VCTracker_GetDeviceType(VCTracker *item, char **deviceType); +int VCTracker_Delete(VCTracker *item); + + +void VCPosition_SetCacheMode (VCPosition *item, uint32 newCacheMode); +uint32 VCPosition_GetCacheMode(VCPosition *item); +void *VCPosition_AttachCreateCallback(VCPosition *item, VCPosition_Func func, void *data); +void *VCPosition_AttachUpdateCallback(VCPosition *item, VCPosition_Func func, void *data); +void *VCPosition_AttachDeleteCallback(VCPosition *item, VCPosition_Func func, void *data); +int VCPosition_DetachCreateCallback(VCPosition *item, void *callbackHandle); +int VCPosition_DetachUpdateCallback(VCPosition *item, void *callbackHandle); +int VCPosition_DetachDeleteCallback(VCPosition *item, void *callbackHandle); +VCPosition *VCPosition_Create(dmPosition *pos, uint32 mode); +VCPosition *VCPosition_CreateData(VCPositionData *positionData); +int VCPosition_Get(VCPosition *item, dmPosition *pos, uint32 *mode); +int VCPosition_GetData(VCPosition *item, VCPositionData *positionData); +int VCPosition_SetData (VCPosition *item,VCPositionData *positionData); +int VCPosition_Set(VCPosition *item, dmPosition *pos, uint32 setMode, uint32 clearMode); +int VCPosition_Delete(VCPosition *item); + + +void VCXWindowId_SetCacheMode(VCXWindowId *item, uint32 newCacheMode); +uint32 VCXWindowId_GetCacheMode(VCXWindowId *item); +void * VCXWindowId_AttachCreateCallback(VCXWindowId *item, VCXWindowId_Func func, void *data); +void * VCXWindowId_AttachUpdateCallback(VCXWindowId *item, VCXWindowId_Func func, void *data); +void * VCXWindowId_AttachDeleteCallback(VCXWindowId *item, VCXWindowId_Func func, void *data); +int VCXWindowId_DetachCreateCallback(VCXWindowId *item, void *callbackHandle); +int VCXWindowId_DetachUpdateCallback(VCXWindowId *item, void *callbackHandle); +int VCXWindowId_DetachDeleteCallback(VCXWindowId *item, void *callbackHandle); +VCXWindowId * VCXWindowId_Create(char *name, uint32 windowId, char *serverName); +VCXWindowId * VCXWindowId_CreateData(VCXWindowIdData *xwindowidData); +int VCXWindowId_Get(VCXWindowId *item, char **name, uint32 *windowId, char **serverName); +int VCXWindowId_GetData(VCXWindowId *item, VCXWindowIdData *xwindowidData); +int VCXWindowId_SetData (VCXWindowId *item,VCXWindowIdData *xwindowidData); +int VCXWindowId_Set(VCXWindowId *item, char *name, uint32 *windowId, char *serverName); +int VCXWindowId_SetName(VCXWindowId *item, char *name); +int VCXWindowId_SetWindowId(VCXWindowId *item, uint32 windowId); +int VCXWindowId_SetServerName(VCXWindowId *item, char *serverName); +int VCXWindowId_GetName(VCXWindowId *item, char **name); +int VCXWindowId_GetWindowId(VCXWindowId *item, uint32 *windowId); +int VCXWindowId_GetServerName(VCXWindowId *item, char **serverName); +int VCXWindowId_Delete(VCXWindowId *item); + + +void VCPseudoGravity_SetCacheMode(VCPseudoGravity *item, uint32 newCacheMode); + +uint32 VCPseudoGravity_GetCacheMode(VCPseudoGravity *item); + +void * VCPseudoGravity_AttachCreateCallback(VCPseudoGravity *item, VCPseudoGravity_Func func, void *data); + +void * VCPseudoGravity_AttachUpdateCallback(VCPseudoGravity *item, VCPseudoGravity_Func func, void *data); + +void * VCPseudoGravity_AttachDeleteCallback(VCPseudoGravity *item, VCPseudoGravity_Func func, void *data); + +int VCPseudoGravity_DetachCreateCallback(VCPseudoGravity *item, void *callbackHandle); + +int VCPseudoGravity_DetachUpdateCallback(VCPseudoGravity *item, void *callbackHandle); + +int VCPseudoGravity_DetachDeleteCallback(VCPseudoGravity *item, void *callbackHandle); + +VCPseudoGravity * VCPseudoGravity_Create(uint32 mode, dmVector direction, float32 gravity); + +VCPseudoGravity * VCPseudoGravity_CreateData(VCPseudoGravityData *pseudoGravityData); + +int VCPseudoGravity_Get(VCPseudoGravity *item, uint32 *mode, dmVector direction, float32 *gravity); + +int VCPseudoGravity_GetData(VCPseudoGravity *item, VCPseudoGravityData *pseudoGravityData); + +int VCPseudoGravity_SetData (VCPseudoGravity *item,VCPseudoGravityData *pseudoGravityData); + +int VCPseudoGravity_Set(VCPseudoGravity *item, uint32 setMode, uint32 clearMode, dmVector direction, + float32 *gravity); + +int VCPseudoGravity_ModifyMode(VCPseudoGravity *item, uint32 setMode, uint32 clearMode); +int VCPseudoGravity_SetMode(VCPseudoGravity *item, uint32 mode); + +int VCPseudoGravity_SetDirection(VCPseudoGravity *item, dmVector direction); + +int VCPseudoGravity_SetGravity(VCPseudoGravity *item, float32 gravity); + +int VCPseudoGravity_GetMode(VCPseudoGravity *item, uint32 *mode); + +int VCPseudoGravity_GetDirection(VCPseudoGravity *item, dmVector direction); + +int VCPseudoGravity_GetGravity(VCPseudoGravity *item, float32 *gravity); + +int VCPseudoGravity_Delete(VCPseudoGravity *item); + + + +void VCVisualViewResource_SetCacheMode(VCVisualViewResource *item, uint32 newCacheMode); +uint32 VCVisualViewResource_GetCacheMode(VCVisualViewResource *item); +VCVisualViewResource *_VCVisualViewResource_GetViewFromAttribute(VCAttribute *attribute); +VCAttribute *_VCVisualViewResource_GetAttribute(VCVisualViewResource *view); +void *VCVisualViewResource_AttachCreateCallback(VCVisualViewResource *item, VCVisualViewResource_Func func, void *data); +void *VCVisualViewResource_AttachUpdateCallback(VCVisualViewResource *item, VCVisualViewResource_Func func, void *data); +void *VCVisualViewResource_AttachDeleteCallback(VCVisualViewResource *item, VCVisualViewResource_Func func, void *data); +int VCVisualViewResource_DetachCreateCallback(VCVisualViewResource *item, void *callbackHandle); +int VCVisualViewResource_DetachUpdateCallback(VCVisualViewResource *item, void *callbackHandle); +int VCVisualViewResource_DetachDeleteCallback(VCVisualViewResource *item, void *callbackHandle); +VCVisualViewResource *VCVisualViewResource_Create(char *name, VCAttribute *visualResource, uint32 mode, + dmPoint offset, dmEuler orientation, float32 size[2]); +VCVisualViewResource *VCVisualViewResource_CreateData(VCVisualViewResourceData *viewData); +int VCVisualViewResource_Get(VCVisualViewResource *item, char **name, VCAttribute **visualResource, + uint32 *mode, dmPoint offset, dmEuler orientation, float32 size[2]); +int VCVisualViewResource_GetData(VCVisualViewResource *item, VCVisualViewResourceData *viewData); +int VCVisualViewResource_SetData (VCVisualViewResource *item,VCVisualViewResourceData *viewData); +int VCVisualViewResource_Set(VCVisualViewResource *item, VCAttribute *visualResource, + uint32 setMode, uint32 clearMode, dmPoint offset, + dmEuler orientation, float32 size[2]); + +int VCVisualViewResource_Delete(VCVisualViewResource *item); +int VCVisualViewResource_SetVisualResource(VCVisualViewResource *item, VCAttribute *visualResource); +int VCVisualViewResource_SetMode(VCVisualViewResource *item, uint32 mode); +int VCVisualViewResource_ModifyMode(VCVisualViewResource *item, uint32 setMode, uint32 clearMode); +int VCVisualViewResource_SetOffset(VCVisualViewResource *item, dmPoint offset); +int VCVisualViewResource_SetOrientation(VCVisualViewResource *item, dmEuler orientation); +int VCVisualViewResource_SetSize(VCVisualViewResource *item, float32 size[2]); +int VCVisualViewResource_GetName(VCVisualViewResource *item, char **name); +int VCVisualViewResource_GetVisualResource(VCVisualViewResource *item, VCAttribute **visualResource); +int VCVisualViewResource_GetMode(VCVisualViewResource *item, uint32 *mode); +int VCVisualViewResource_GetOffset(VCVisualViewResource *item, dmPoint offset); +int VCVisualViewResource_GetOrientation(VCVisualViewResource *item, dmEuler orientation); +int VCVisualViewResource_GetSize(VCVisualViewResource *item, float32 size[2]); + +VCVisualViewResource *VCVisualViewResource_GetFirst(VCAttribute *visualResource, VC_Traverse *traverseInfo); +VCVisualViewResource *VCVisualViewResource_GetNext(VC_Traverse *traverseInfo); + + + + + +VCEntity *VC_ConstructAudioVoice(char *voice, VCAttribute **audioAttribute); +VCEntity *VC_ConstructAudioData(VCAudioData *audioData, VCAttribute **audioAttribute); +VCEntity *VC_ConstructLightAmbient(VCColour colour, VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightDirectional(VCColour colour, VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightPoint(VCColour colour, VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightSpot(VCColour colour, float32 exponent, float32 theta, + VCAttribute **lightAttribute); +VCEntity *VC_ConstructLightData(VCLightData *lightData, VCAttribute **lightAttribute); +VCEntity *VC_ConstructVisualGeometry(char *geometry, int collidable, VCAttribute **visualAttribute, + VCAttribute **boundaryAttribute); +VCEntity *VC_ConstructVisualData(VCVisualData *visualData, int collidable, VCAttribute **visualAttribute, + VCAttribute **boundaryAttribute); + + +void VCSync_SetCacheMode(VCSync *item, uint32 newCacheMode); +uint32 VCSync_GetCacheMode(VCSync *item); +void *VC_AttachSyncCallbacks(char *actorName, char *actorType, VCSync_Func updateFunc, + VCSync_Func deleteFunc, void *data); +int VC_DetachSyncCallbacks( void *callbackHandle); +VCSync *VCSync_Create(char *name, char *actorType, VCTime *time); +int VCSync_Get(VCSync *item, char **name, char **actorType, VCTime *time); +int VCSync_Set(VCSync *item, VCTime *time); +int VCSync_SetTime(VCSync *item, VCTime *time); +int VCSync_GetName(VCSync *item, char **name); +int VCSync_GetActorType(VCSync *item, char **type); +int VCSync_GetTime(VCSync *item, VCTime *time); +int VCSync_Delete(VCSync *item); + + +void VCCollideMonitor_SetCacheMode (VCCollideMonitor *item, uint32 newCacheMode); +uint32 VCCollideMonitor_GetCacheMode (VCCollideMonitor *item); +void *VCCollideMonitor_AttachCreateCallback (VCCollideMonitor *item, VCCollideMonitor_Func func, void *data); +void *VCCollideMonitor_AttachUpdateCallback (VCCollideMonitor *item, VCCollideMonitor_Func func, void *data); +void *VCCollideMonitor_AttachDeleteCallback (VCCollideMonitor *item, VCCollideMonitor_Func func, void *data); +int VCCollideMonitor_DetachCreateCallback (VCCollideMonitor *item, void *callbackHandle); +int VCCollideMonitor_DetachUpdateCallback (VCCollideMonitor *item, void *callbackHandle); +int VCCollideMonitor_DetachDeleteCallback (VCCollideMonitor *item, void *callbackHandle); +VCCollideMonitor *VCCollideMonitor_CreateData (VCCollideMonitorData *collideMonitorData); +int VCCollideMonitor_GetData (VCCollideMonitor *item, VCCollideMonitorData *collideMonitorData); +int VCCollideMonitor_SetData (VCCollideMonitor *item,VCCollideMonitorData *collideMonitorData); +int VCCollideMonitor_Delete (VCCollideMonitor *item); + +void VCTrackerMonitor_SetCacheMode (VCTrackerMonitor *item, uint32 newCacheMode); +uint32 VCTrackerMonitor_GetCacheMode (VCTrackerMonitor *item); +void *VCTrackerMonitor_AttachCreateCallback (VCTrackerMonitor *item, VCTrackerMonitor_Func func, void *data); +void *VCTrackerMonitor_AttachUpdateCallback (VCTrackerMonitor *item, VCTrackerMonitor_Func func, void *data); +void *VCTrackerMonitor_AttachDeleteCallback (VCTrackerMonitor *item, VCTrackerMonitor_Func func, void *data); +int VCTrackerMonitor_DetachCreateCallback (VCTrackerMonitor *item, void *callbackHandle); +int VCTrackerMonitor_DetachUpdateCallback (VCTrackerMonitor *item, void *callbackHandle); +int VCTrackerMonitor_DetachDeleteCallback (VCTrackerMonitor *item, void *callbackHandle); +VCTrackerMonitor *VCTrackerMonitor_CreateData (VCTrackerMonitorData *trackerMonitorData); +int VCTrackerMonitor_GetData (VCTrackerMonitor *item, VCTrackerMonitorData *trackerMonitorData); +int VCTrackerMonitor_SetData (VCTrackerMonitor *item,VCTrackerMonitorData *trackerMonitorData); +int VCTrackerMonitor_Delete (VCTrackerMonitor *item); + +void VCVisualMonitor_SetCacheMode (VCVisualMonitor *item, uint32 newCacheMode); +uint32 VCVisualMonitor_GetCacheMode (VCVisualMonitor *item); +void *VCVisualMonitor_AttachCreateCallback (VCVisualMonitor *item, VCVisualMonitor_Func func, void *data); +void *VCVisualMonitor_AttachUpdateCallback (VCVisualMonitor *item, VCVisualMonitor_Func func, void *data); +void *VCVisualMonitor_AttachDeleteCallback (VCVisualMonitor *item, VCVisualMonitor_Func func, void *data); +int VCVisualMonitor_DetachCreateCallback (VCVisualMonitor *item, void *callbackHandle); +int VCVisualMonitor_DetachUpdateCallback (VCVisualMonitor *item, void *callbackHandle); +int VCVisualMonitor_DetachDeleteCallback (VCVisualMonitor *item, void *callbackHandle); +VCVisualMonitor *VCVisualMonitor_CreateData (VCVisualMonitorData *visualMonitorData); +int VCVisualMonitor_GetData (VCVisualMonitor *item, VCVisualMonitorData *visualMonitorData); +int VCVisualMonitor_SetData (VCVisualMonitor *item,VCVisualMonitorData *visualMonitorData); +int VCVisualMonitor_Delete (VCVisualMonitor *item); + +void VCRadiator_SetCacheMode(VCRadiator *item, uint32 newCacheMode); +uint32 VCRadiator_GetCacheMode(VCRadiator *item); +void *VCRadiator_AttachCreateCallback(VCRadiator *item, VCRadiator_Func func, void *data); +void *VCRadiator_AttachUpdateCallback(VCRadiator *item, VCRadiator_Func func, void *data); +void *VCRadiator_AttachDeleteCallback(VCRadiator *item, VCRadiator_Func func, void *data); +int VCRadiator_DetachCreateCallback(VCRadiator *item, void *callbackHandle); +int VCRadiator_DetachUpdateCallback(VCRadiator *item, void *callbackHandle); +int VCRadiator_DetachDeleteCallback(VCRadiator *item, void *callbackHandle); +VCRadiator *VCRadiator_Create (char *name, int32 numPoints, float32 points[VC_RADIATOR_MAX_POINTS]); +VCRadiator *VCRadiator_CreateData(VCRadiatorData *radiatorData); +int VCRadiator_Get (VCRadiator *item, char **name, int32 *numPoints, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_GetData(VCRadiator *item, VCRadiatorData *radiatorData); +int VCRadiator_SetData (VCRadiator *item,VCRadiatorData *radiatorData); +int VCRadiator_Set (VCRadiator *radiator, char *name, int32 *numPoints, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_SetName(VCRadiator *radiator, char *name); +int VCRadiator_SetNumPoints(VCRadiator *radiator, int32 numPoints); +int VCRadiator_SetPoints(VCRadiator *radiator, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_GetName(VCRadiator *radiator, char **name); +int VCRadiator_GetNumPoints(VCRadiator *radiator, int32 *numPoints); +int VCRadiator_GetPoints(VCRadiator *radiator, float32 points[VC_RADIATOR_MAX_POINTS]); +int VCRadiator_Delete(VCRadiator *item); + +void VCRamp_SetCacheMode(VCRamp *item, uint32 newCacheMode); +uint32 VCRamp_GetCacheMode(VCRamp *item); +void *VCRamp_AttachCreateCallback(VCRamp *item, VCRamp_Func func, void *data); +void *VCRamp_AttachUpdateCallback(VCRamp *item, VCRamp_Func func, void *data); +void *VCRamp_AttachDeleteCallback(VCRamp *item, VCRamp_Func func, void *data); +int VCRamp_DetachCreateCallback(VCRamp *item, void *callbackHandle); +int VCRamp_DetachUpdateCallback(VCRamp *item, void *callbackHandle); +int VCRamp_DetachDeleteCallback(VCRamp *item, void *callbackHandle); +VCRamp *VCRamp_Create(char *name, uint32 mode, VCColour minRgb, VCColour maxRgb); +VCRamp *VCRamp_CreateData(VCRampData *rampData); +int VCRamp_Get(VCRamp *item, char **name, uint32 *mode, VCColour minRgb, VCColour maxRgb); +int VCRamp_GetData(VCRamp *item, VCRampData *rampData); +int VCRamp_SetData (VCRamp *item,VCRampData *rampData); +int VCRamp_Set(VCRamp *item, char *name, uint32 setMode, uint32 clearMode, VCColour minRgb, VCColour maxRgb); +int VCRamp_ModifyMode(VCRamp *item, uint32 setMode, uint32 clearMode); +int VCRamp_SetName(VCRamp *item, char *name); +int VCRamp_SetMode(VCRamp *item, uint32 mode); +int VCRamp_SetMinRgb (VCRamp *item, VCColour minRgb); +int VCRamp_SetMaxRgb (VCRamp *item, VCColour maxRgb); +int VCRamp_GetName(VCRamp *item, char **name); +int VCRamp_GetMode(VCRamp *item, uint32 *mode); +int VCRamp_GetMinRgb (VCRamp *item, VCColour minRgb); +int VCRamp_GetMaxRgb (VCRamp *item, VCColour maxRgb); +int VCRamp_Delete(VCRamp *item); + + + + + +int VC_StartGroup(void); +int VC_StopGroup(void); +int32 VC_GetGroup(void); + +int VC_DetachGroupCallback(void *callbackHandle); +void *VC_AttachGroupCallback(VC_GroupFunc function, void *data); + +char *VC_ErrorString(int errno, int errType); +void VC_Perror(char *message); +void VCPrintBadMatrixSplit(dmMatrix mat, char *func, char *file, int line); + +extern VCAttribute *VCFindAttribute (const InstanceNo attrIno); +extern VCEntity * VCFindObject( const InstanceNo obj_ino); + +extern char *VCApplicationName; +extern char *VCDomainName; +extern char *VCDomainExtName; +extern FILE *VCLogFilePtr; +extern int vcerrno; +extern int vcErrType; +# ifdef __cplusplus +} +# endif +#endif diff --git a/MUNGA_L4/libDPL/dvs/VCBODAPP.H b/MUNGA_L4/libDPL/dvs/VCBODAPP.H new file mode 100644 index 0000000..ce27c46 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCBODAPP.H @@ -0,0 +1,47 @@ + +typedef struct +{ + int state; + void *collideEntity; + void *pickEntity; + void *pickRelocateHandle; + void *relocateData; +}VCBodyPartAppInfo; + +typedef struct +{ + VCEntity *entity; + VCAttribute *bodyPart; + VCBody *body; +}VCBodyAppCallbackData; + +typedef struct +{ + VCAttribute *bodyPart; + VCBody *body; +}VCBodyAppRelocateData; + + +#define VC_BODYAPP_COLLIDED 0x00000001 +#define VC_BODYAPP_PICK_PRESSED 0x00000002 + +typedef void (*VCBodyTouchFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyUnTouchFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyPickFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyDropFunc)(VCBodyAppCallbackData *callbackData, void *data); +typedef void (*VCBodyMoveFunc)(VCBodyAppCallbackData *callbackData, void *data); + +typedef struct +{ + void *touchFunc; + void *unTouchFunc; + void *pickFunc; + void *dropFunc; + void *moveFunc; +} VCBodyFuncInfo; + +void *VCBody_AttachInteractionCallbacks(VCBody *body, VCBodyTouchFunc touchFunc, + VCBodyUnTouchFunc unTouchFunc, VCBodyPickFunc pickFunc, + VCBodyDropFunc dropFunc, VCBodyMoveFunc moveFunc, void *data); + +void VCBody_DetachInteractionCallbacks(VCBody *body, void *callbackHandle); diff --git a/MUNGA_L4/libDPL/dvs/VCDATA.H b/MUNGA_L4/libDPL/dvs/VCDATA.H new file mode 100644 index 0000000..a34046c --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCDATA.H @@ -0,0 +1,60 @@ + +#define VCEntity_AttachUserData(e,i,d) _VCList_AttachUserData(&((e)->systemData->userData),i,d) +#define VCEntity_GetUserData(e,i) _VCList_GetUserData((e)->systemData->userData,i) +#define VCEntity_DetachUserData(e,i) _VCList_DetachUserData(&((e)->systemData->userData),i) + +#define VCEntityAttribute_AttachUserData(e,o,i,d) _VCList_AttachUserData(&((e)->attributes[o].userDataList),i,d) +#define VCEntityAttribute_GetUserData(e,o,i) _VCList_GetUserData ((e)->attributes[o].userDataList,i) +#define VCEntityAttribute_DetachUserData(e,o,i) _VCList_DetachUserData (&((e)->attributes[o].userDataList),i) +#define VCAttribute_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCAttribute_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCAttribute_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCMaterial_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCMaterial_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCMaterial_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCCollision_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCCollision_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCCollision_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCTexture_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCTexture_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCTexture_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCInput_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCInput_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCInput_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCIntersection_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCIntersection_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCIntersection_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCTracker_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCTracker_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCTracker_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCPosition_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCPosition_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCPosition_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCXWindowId_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCXWindowId_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCXWindowId_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCPseudoGravity_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCPseudoGravity_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCPseudoGravity_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCVisualViewResource_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->attribute->userDataList),i,d) +#define VCVisualViewResource_GetUserData(a,i) _VCList_GetUserData((a)->attribute->userDataList,i) +#define VCVisualViewResource_DetachUserData(a,i) _VCList_DetachUserData(&((a)->attribute->userDataList),i) +#define VCSync_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCSync_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCSync_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCCollideMonitor_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCCollideMonitor_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCCollideMonitor_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCTrackerMonitor_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCTrackerMonitor_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCTrackerMonitor_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCVisualMonitor_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCVisualMonitor_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCVisualMonitor_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCRadiator_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCRadiator_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCRadiator_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) +#define VCRamp_AttachUserData(a,i,d) _VCList_AttachUserData(&((a)->userDataList),i,d) +#define VCRamp_GetUserData(a,i) _VCList_GetUserData((a)->userDataList,i) +#define VCRamp_DetachUserData(a,i) _VCList_DetachUserData(&((a)->userDataList),i) + diff --git a/MUNGA_L4/libDPL/dvs/VCDEFS.H b/MUNGA_L4/libDPL/dvs/VCDEFS.H new file mode 100644 index 0000000..e89ae0d --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCDEFS.H @@ -0,0 +1,597 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vcdefs.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:10 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcdefs.h,v 1.3 1995/03/22 12:23:51 jeff Exp $ + * + * FUCTION: + * + * + * + * + * Copyright (c) 1992 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + +/*--- Local sizing constants */ + +#define VC_RED 0 +#define VC_GREEN 1 +#define VC_BLUE 2 +#define VC_MAX_OBJECT_ATTRIBUTES 6 + +#define VC_ERRTYPE_NONE 0 +#define VC_ERRTYPE_VL 1 +#define VC_ERRTYPE_DM 2 +#define VC_ERRTYPE_VC 3 +#define VC_ERRTYPE_SYSTEM 4 + +#define VC_MAX_SIGNALS 32 + +#define VC_MAX_SENSORS 4 + +#define VC_RADIATOR_MAX_POINTS 36 +#define VC_RADIATOR_NAME_LENGTH 16 + +#define VC_LIGHT_ENABLE 0x00000004 + +#define VC_LIGHT_MODE_MASK 0x00000003 +#define VC_LIGHT_MODE_DIRECTIONAL 0x00000000 +#define VC_LIGHT_MODE_POINT 0x00000001 +#define VC_LIGHT_MODE_AMBIENT 0x00000002 +#define VC_LIGHT_MODE_SPOT 0x00000003 + +#define VC_LOD_NAME_LENGTH 8 + +#define VC_NO_INSTANCES -1 +#define VC_ALL_INSTANCES 0 +#define VC_FIRST_ATTRIBUTE -1 +#define VC_ALL_ATTRIBUTES -1 + +#define VC_ALL_ELEMENTS 0 +/* + * Values for Visible field in Visual object + */ + +#define VC_ALL_MODES 0xffffffff +#define VC_VISIBLE 0x01 +#define VC_VISUAL_ENABLE 0x01 +#define VC_RMODE_POLYGONAL 0x00 +#define VC_RMODE_WIREFRAME 0x02 +#define VC_RMODE_SPARE1 0x04 +#define VC_RMODE_SPARE2 0x06 +#define VC_VISUAL_BILLBOARD 0x08 +#define VC_VISUAL_NOVECTINTERSECT 0x10 + +#define VC_RMODE_MASK 0x06 + + + +#define VC_VISUALVIEW_MODE_MASK 0x03 +#define VC_VISUALVIEW_RELATIVE_MODE_MASK 0x04 + +#define VC_VISUALVIEW_MODE_MONO 0x00 +#define VC_VISUALVIEW_MODE_LEFT 0x01 +#define VC_VISUALVIEW_MODE_RIGHT 0x02 +#define VC_VISUALVIEW_RELATIVE_MODE_HEAD 0x00 +#define VC_VISUALVIEW_RELATIVE_MODE_EYE 0x04 +#define VC_VISUALVIEW_ENABLE 0x08 + + +#define VC_VISUALRESOURCE_FOG_MASK 0x00070000 +#define VC_VISUALRESOURCE_FOG_MODE_MASK 0x00000010 +#define VC_VISUALRESOURCE_PHASE_MODE_MASK 0x00003000 +#define VC_VISUALRESOURCE_RENDERMODE_MASK 0x00000001 + +#define VC_VISUALRESOURCE_MODE_POLYGONAL 0x00000000 +#define VC_VISUALRESOURCE_MODE_WIREFRAME 0x00000001 +#define VC_VISUALRESOURCE_MODE_STATISTICS 0x00000002 +#define VC_VISUALRESOURCE_MODE_TEXTURE 0x00000004 +#define VC_VISUALRESOURCE_MODE_SINGLE_BUF 0x00000008 +#define VC_VISUALRESOURCE_FOG_MODE_PIXEL 0x00000000 +#define VC_VISUALRESOURCE_FOG_MODE_VERTEX 0x00000010 +#define VC_VISUALRESOURCE_PHASE_MODE_LOCK 0x00000000 +#define VC_VISUALRESOURCE_PHASE_MODE_FLOAT 0x00001000 +#define VC_VISUALRESOURCE_PHASE_MODE_FREE 0x00002000 +#define VC_VISUALRESOURCE_PHASE_MODE_LIMIT 0x00003000 +#define VC_VISUALRESOURCE_ENABLE 0x00008000 +#define VC_VISUALRESOURCE_FOG_DISABLED 0x00000000 +#define VC_VISUALRESOURCE_FOG_LINEAR 0x00010000 +#define VC_VISUALRESOURCE_FOG_EXP 0x00020000 +#define VC_VISUALRESOURCE_FOG_EXP_SQUARED 0x00030000 +#define VC_VISUALRESOURCE_Z_CLEAR_ONLY 0x00080000 + + + +#define VC_NOT_PICKED 3 +#define VC_NOT_DROPPED VC_NOT_PICKED +#define VC_FOUND_DEFAULT 2 +#define VC_FOUND_EXPLICIT 1 +#define VC_OK 0 +#define VC_ERR -1 +#define VC_NOT_FOUND -1 +#define VC_EXISTS -2 +#define VC_BAD_ARGS -3 +#define VC_BAD_ACTOR VL_BAD_ACTOR +/* + * flags to VCAddInstance + */ +#define VC_ADD 0 +#define VC_OVERRIDE 1 +#define VC_FAIL 2 + +#define VC_X 0 +#define VC_Y 1 +#define VC_Z 2 +#define VC_W 3 + +#define VC_MIN_X 0 +#define VC_MIN_Y 1 +#define VC_MIN_Z 2 +#define VC_MAX_X 3 +#define VC_MAX_Y 4 +#define VC_MAX_Z 5 + +#define VC_BOUND_ROT_X 6 +#define VC_BOUND_ROT_Y 7 +#define VC_BOUND_ROT_Z 8 + +#define VC_BOUND_SIZE 9 + + +#define VC_MIN_PITCH 0 +#define VC_MIN_YAW 1 +#define VC_MIN_ROLL 2 +#define VC_MAX_PITCH 3 +#define VC_MAX_YAW 4 +#define VC_MAX_ROLL 5 + +#define VC_RADIUS 3 + +#define VC_CONSTRAIN_ENABLE 0x80000000 +#define VC_CONSTRAIN_MODE_MASK 0x7fffffff + +#define VC_CONSTRAIN_NORMAL 0 +#define VC_CONSTRAIN_HINGE_X 1 +#define VC_CONSTRAIN_HINGE_Y 2 +#define VC_CONSTRAIN_HINGE_Z 3 + + + +#define VC_PICK_CONSTRAINED 0x00000000 +#define VC_PICK_NON_CONSTRAINED 0x00000001 +#define VC_PICK_DROP 0x00000002 +#define VC_PICK_IDLE 0x00000003 + +#define VC_PICK_COMMAND_MASK 0x0000000f + + +/* + * Mice input port types + */ +#define VC_SERIAL 1 +#define VC_PARALLEL 2 +#define VC_PIO 3 + +#define VC_PV100_MOUSE 1 +#define VC_PV200_MOUSE 2 +#define VC_LOGITECH_MOUSE 3 +#define VC_SPACEBALL_MOUSE 4 + + +#define VC_HOOK_ATTACH_MASK 0x0000000f +#define VC_HOOK_DETACH_MASK 0x000000f0 + +#define VC_ATTACH_ABSOLUTE 0x00000001 +#define VC_ATTACH_RELATIVE 0x00000002 +#define VC_DETACH_ABSOLUTE 0x00000010 +#define VC_DETACH_RELATIVE 0x00000020 + +#define VC_LINK_LEAVE_POSITION 0x00000000 +#define VC_LINK_ADJUST_POSITION 0x00000001 +#define VC_LINK_QUIET 0x00000002 +#define VC_UNLINK_LEAVE_POSITION 0x00000000 +#define VC_UNLINK_ADJUST_POSITION 0x00000001 +#define VC_UNLINK_QUIET 0x00000002 +#define VC_UNLINK_DONT_FIX_PARENT_INTEREST 0x00000010 + +#define VC_LOCK_X_VAL 0x00000001 +#define VC_LOCK_Y_VAL 0x00000002 +#define VC_LOCK_Z_VAL 0x00000004 +#define VC_LOCK_X 0x00000010 +#define VC_LOCK_Y 0x00000020 +#define VC_LOCK_Z 0x00000040 +#define VC_LOCK_ROLL_VAL 0x00000100 +#define VC_LOCK_PITCH_VAL 0x00000200 +#define VC_LOCK_YAW_VAL 0x00000400 +#define VC_LOCK_ROLL 0x00001000 +#define VC_LOCK_PITCH 0x00002000 +#define VC_LOCK_YAW 0x00004000 +#define VC_LOCK_FIXED 0x00010000 + +/* + * Body Values + */ + +#define VC_BODY_USE_ENTITY_TRANSLATION 0x00000001 +#define VC_ALL_BODIES -1 + +#define VC_BODY_FLY_ENABLED 0x00000001 +#define VC_BODY_FLY_VERTICAL 0x00000002 +#define VC_BODY_FLY_VERTICAL_ALWAYS 0x00000004 +#define VC_BODY_FLY_FORWARD_SLOW 0x00000008 +#define VC_BODY_FLY_FORWARD_FAST 0x00000010 +#define VC_BODY_FLY_FORWARD_ACCELERATE 0x00000020 +#define VC_BODY_FLY_BACKWARD_SLOW 0x00000040 +#define VC_BODY_FLY_BACKWARD_FAST 0x00000080 +#define VC_BODY_FLY_BACKWARD_ACCELERATE 0x00000100 + +#define VC_BODY_ROT_LEFT_SLOW 0x00000200 +#define VC_BODY_ROT_LEFT_FAST 0x00000400 +#define VC_BODY_ROT_LEFT_ACCELERATE 0x00000800 +#define VC_BODY_ROT_RIGHT_SLOW 0x00001000 +#define VC_BODY_ROT_RIGHT_FAST 0x00002000 +#define VC_BODY_ROT_RIGHT_ACCELERATE 0x00004000 + +#define VC_BODY_FLY_LEFT_SLOW 0x00008000 +#define VC_BODY_FLY_LEFT_FAST 0x00010000 +#define VC_BODY_FLY_LEFT_ACCELERATE 0x00020000 +#define VC_BODY_FLY_RIGHT_SLOW 0x00040000 +#define VC_BODY_FLY_RIGHT_FAST 0x00080000 +#define VC_BODY_FLY_RIGHT_ACCELERATE 0x00100000 + +#define VC_BODY_FLY_UP_SLOW 0x00200000 +#define VC_BODY_FLY_UP_FAST 0x00400000 +#define VC_BODY_FLY_UP_ACCELERATE 0x00800000 +#define VC_BODY_FLY_DOWN_SLOW 0x01000000 +#define VC_BODY_FLY_DOWN_FAST 0x02000000 +#define VC_BODY_FLY_DOWN_ACCELERATE 0x04000000 + + + + +/* + * Flags for new VCActorInit call - MG, March 23, '94 + * + */ + +#define VC_INIT_NOUSER 0x001 /* Don't get user information */ +#define VC_INIT_NOCONFIG 0x002 /* Don't do actor configuration */ + +/* + * Sensor Resource update Mode values + */ + +#define VC_MODE_IMMEDIATE 1 +#define VC_MODE_INDIRECT 2 + +/* + * VCObject Update Modes + */ + +#define VC_REPORT_LOCAL_UPDATES 0x00000001 +#define VC_REPORT_REMOTE_UPDATES 0x00000002 + +/* + * flags for VCPosition mode bit + */ + +#define VC_DEAD_RECKON 0x00000001 + +/* + * Flags passed into VCRelocateHandler & relocate functions + */ + +#define VC_REPORT_ABSOLUTE_POSITION 0x00000000 +#define VC_REPORT_RELATIVE_POSITION 0x00000001 +#define VC_REPORT_DONT_DEAD_RECKON 0x00000002 +#define VC_REPORT_DELAY_RELOCATE 0x00000004 +#define VC_REPORT_POSITION_IN_ENTITY 0x00000010 +#define VC_REPORT_ALL_ENTITIES 0x00000020 + +/* + * Flags to VCDestruct + */ + +#define VC_DESTRUCT_FORCE 0x00000001 +#define VC_DESTRUCT_ATTRIBUTES 0x00000002 +#define VC_DESTRUCT_CHILDREN 0x00000004 + +#define VC_RELOCATE_FIRST_REPORT 0x00000001 +#define VC_RELOCATE_ABSOLUTE 0x00000002 +#define VC_RELOCATE_RELATIVE 0x00000004 +#define VC_RELOCATE_LINKAGE_CHANGE 0x00000008 + +#define VC_HANDLED 0 +#define VC_NOT_HANDLED 1 + +#define VC_COLLISION_ENABLE 0x01 +/* +* Don't know what to do with this +#define VC_COLLISION_SOLID 0x02 +*/ +#define VC_COLLISION_HIERACHY_DISABLE 0x04 +#define VC_COLLISION_PICKABLE 0x08 +#define VC_COLLISION_PICKING 0x10 +#define VC_COLLISION_QUIET 0x20 +#define VC_COLLISION_INV_QUIET 0x40 + +#define VC_COLLISION_SIMPLE 0x000 +#define VC_COLLISION_RADIUS 0x100 +#define VC_COLLISION_GEOMETRY 0x200 +#define VC_COLLISION_BBOX 0x300 + +#define VC_COLLISION_MODE_MASK 0x300 + +#define VC_COLLISION_BOUNDS_VALID 0x400 +#define VC_COLLISION_ZONE 0x800 +#define VC_COLLISION_NO_POSITION 0x1000 +#define VC_COLLISION_NO_VECTOR 0x2000 +#define VC_COLLISION_NO_TIME 0x4000 + +#define VC_COLLISION_RETURN_MASK 0xf0000 +#define VC_COLLISION_RETURN_NONE 0x00000 +#define VC_COLLISION_RETURN_BBOX 0x10000 +#define VC_COLLISION_RETURN_RADIUS 0x20000 +#define VC_COLLISION_RETURN_VALID 0x100000 +#define VC_ATTRIBUTE_MODE_DONT_CACHE 0x000 +#define VC_ATTRIBUTE_MODE_CACHE 0x001 + +#define VC_AUDIORESOURCE_SPREADINGROLLOFF_VALID 0x00000010 +#define VC_AUDIORESOURCE_ATMOSPHERICABSORPTION_VALID 0x00000020 + +#define VC_AUDIO_ENABLE 0x01 +#define VC_AUDIO_ZONED 0x02 +#define VC_AUDIO_SPATIAL_OFF 0x04 + +#define VC_AUDIO_PRIORITY_LOCKED -1 +#define VC_AUDIO_MAX_PRIORITY 127 + + +#define VC_SENSOR_ENABLE 0x00000001 +#define VC_SENSOR_MODE_RELATIVE 0x00000002 +#define VC_SENSOR_FILTER_ENABLE 0x00000004 +#define VC_SENSOR_POSITION_SHARED 0x00000008 +#define VC_SENSOR_REPORT_MASK 0x000000f0 +#define VC_SENSOR_REPORT_NORMAL 0x00000010 +#define VC_SENSOR_REPORT_INTERPOLATE 0x00000020 +#define VC_SENSOR_REPORT_DEADRECKON_1 0x00000030 +#define VC_SENSOR_REPORT_DEADRECKON_2 0x00000040 +#define VC_SENSOR_REPORT_ENABLE 0x00000100 + +#define VC_MATERIAL_ENABLE 0x00000001 + +/* + * Value for texture mode + */ + +#define VC_TEXTURE_ENABLE 0x00000001 + +/* + * Values fot texture minify field + */ + +#define VC_TEXTURE_MIN_POINT_SAMPLED 0x01 +#define VC_TEXTURE_MIN_BILINEAR 0x02 +#define VC_TEXTURE_MIN_TRILINEAR 0x03 +#define VC_TEXTURE_MIN_MIP_MAP_POINT_SAMPLED 0x04 +#define VC_TEXTURE_MIN_MIP_MAP_LINEAR 0x05 +#define VC_TEXTURE_MIN_MIP_MAP_BILINEAR 0x06 +#define VC_TEXTURE_MIN_MIP_MAP_TRILINEAR 0x07 +#define VC_TEXTURE_MIN_MIP_MAP_QUADLINEAR 0x08 + +/* + * Values fot texture magnify field + */ + +#define VC_TEXTURE_MAG_POINT_SAMPLED 0x01 +#define VC_TEXTURE_MAG_BILINEAR 0x02 +#define VC_TEXTURE_MAG_TRILINEAR 0x03 +#define VC_TEXTURE_MAG_BICUBIC 0x04 +#define VC_TEXTURE_MAG_SHARPEN 0x05 + +/* + * Values fot texture alpha field + */ + +#define VC_TEXTURE_ALPHA_BLEND 0x01 +#define VC_TEXTURE_ALPHA_CUT 0x02 +#define VC_TEXTURE_ALPHA_BLEND_CUT 0x03 + +/* + * Values fot texture wrapu/wrapv fields + */ + +#define VC_TEXTURE_WRAP_REPEAT 0x00 +#define VC_TEXTURE_WRAP_CLAMP 0x01 +#define VC_TEXTURE_WRAP_SELECT 0x02 + +/* + * Values fot texture detailType field + */ +#define VC_TEXTURE_DETAIL_ADD 0x01 +#define VC_TEXTURE_DETAIL_MODULATE 0x02 + + + +/* + * Viz query status values + */ + +#define VC_VISUALQUERY_OK 0x00000001 +#define VC_VISUALQUERY_FAIL 0x00000002 + +#define VC_VISUALQUERY_MASK 0xffffff00 + +#define VC_VISUALQUERY_NO_SUBJECT 0x00000100 +#define VC_VISUALQUERY_NOT_FOUND 0x00000200 + +/* + * Viz query modes + */ + +#define VC_VISUALQUERY_OFF 0x00000000 +#define VC_VISUALQUERY_MATERIAL_NAMES 0x00000001 +#define VC_VISUALQUERY_TEXTURE_NAMES 0x00000002 +#define VC_VISUALQUERY_RAMP_NAMES 0x00000003 +#define VC_VISUALQUERY_LOD_NAMES 0x00000004 +#define VC_VISUALQUERY_PATCH_NAMES 0x00000005 +#define VC_VISUALQUERY_MATERIAL 0x00000006 +#define VC_VISUALQUERY_TEXTURE 0x00000007 +#define VC_VISUALQUERY_LOD 0x00000008 + +#define VC_VECTORINTERSECT_ENABLE 0x00000001 +#define VC_VECTORINTERSECT_REPORT_CONTINUOUS 0x00000002 +#define VC_VECTORINTERSECT_REPORT_RELATIVE 0x00000004 + +#define VC_VISUALEFFECT_ENABLE 0x0001 +#define VC_VISUALEFFECT_MODE_MASK 0x0ff0 +#define VC_VISUALEFFECT_MODE_EXPLOSION 0x0010 + + +#define VC_VERBOSE 0x00010000 +#define VC_VERBOSE_MATSPLIT 0x00020000 +#define VC_ZONE_ALL_ACTORS -1 +#define VC_ZONE_VISUAL 0x00000001 +#define VC_ZONE_COLLIDE 0x00000002 +#define VC_ZONE_PHYSICS 0x00000004 +#define VC_ZONE_AUDIO 0x00000008 +#define VC_ZONE_BODY 0x00000010 + +#define VC_ZONE_ENABLE_MASK 0x0000000F +#define VC_ZONE_ENABLED 0x00000000 +#define VC_ZONE_DISABLED 0x00000001 + +/* + * turn on things in a VCDynamics + */ +#define VC_DYNAMICS_ENABLE 0x00000001 +#define VC_DYNAMICS_INERTIA_MASK 0x6 +#define VC_DYNAMICS_INERTIA_POINT_MASS 0x2 +#define VC_DYNAMICS_INERTIA_DISTRIBUTED_MASS 0x4 + +#define VC_DYNAMICS_BOUNCE_MASK 0x00000018 +#define VC_DYNAMICS_BOUNCE_DISBALED 0 +#define VC_DYNAMICS_BOUNCE_SIMPLE 0x00000008 +#define VC_DYNAMICS_BOUNCE_COMPLEX 0x00000010 + +#define VC_DYNAMICS_GRAVITATIONAL_MASS 0x00000020 + + +/* + * indecies into arrays of + * values from an inertial tensor + */ +#define VC_I_XX 0 +#define VC_I_YY 1 +#define VC_I_ZZ 2 +#define VC_I_XY 3 +#define VC_I_YZ 4 +#define VC_I_XZ 5 + +/* + * turn on a VCForce as a force or pure torque (mutually exclusive). + * define whether it acts in local coordinante space (default) + * or world coordinate space. + */ +#define VC_FORCE_MODE_MASK 0x00000003 + +#define VC_FORCE_FORCE 0x00000001 +#define VC_FORCE_TORQUE 0x00000002 +#define VC_FORCE_WCS 0x00000004 +/* + * enable a pseudo-gravitational field + */ +#define VC_PSEUDO_GRAVITY_ENABLE 0x00000001 + +#define VC_LOD_ENABLE 0x000000001 +#define VC_LOD_DYNAMIC 0x000000002 + +#define VC_GEOGROUP_ENABLE 0x00000001 +#define VC_GEOGROUP_DYNAMIC 0x00000002 + +#define VC_GEOGROUP_VERTEX_ONLY 0x00000000 +#define VC_GEOGROUP_VERTEX_NORMALS 0x00000001 +#define VC_GEOGROUP_VERTEX_RGBA 0x00000002 +#define VC_GEOGROUP_VERTEX_LUMINANCE 0x00000004 +#define VC_GEOGROUP_VERTEX_2D_TEXTURE 0x00000008 +#define VC_GEOGROUP_VERTEX_3D_TEXTURE 0x00000010 +#define VC_GEOGROUP_VERTEX_RADIUS 0x00000020 + +#define VC_GEOGROUP_DRAWMODE_SOLID 0x00000000 +#define VC_GEOGROUP_DRAWMODE_WIREFRAME 0x00000001 +#define VC_GEOGROUP_DRAWMODE_DOTTED 0x00000002 + +#define VC_GEOGROUP_LOCK_OFF 0x00000000 +#define VC_GEOGROUP_LOCK_ON 0x00000001 + +#define VC_GEOMETRY_ENABLE 0x00000040 +#define VC_GEOMETRY_TYPE_MASK 0x0000003f + +#define VC_GEOMETRY_TYPE_TRISTRIP 0x00000000 +#define VC_GEOMETRY_TYPE_POLYSTRIP 0x00000001 +#define VC_GEOMETRY_TYPE_POLYGON 0x00000002 +#define VC_GEOMETRY_TYPE_LINE 0x00000003 +#define VC_GEOMETRY_TYPE_SPHERELIST 0x00000004 +#define VC_GEOMETRY_TYPE_PMESH 0x00000005 +#define VC_GEOMETRY_TYPE_TEXT 0x00000006 + +#define VC_GEOMETRY_SPHERELIST_DICE_U 0xfff00000 +#define VC_GEOMETRY_SPHERELIST_DICE_U_SHIFT 20 +#define VC_GEOMETRY_SPHERELIST_DICE_V 0x000fff00 +#define VC_GEOMETRY_SPHERELIST_DICE_V_SHIFT 8 + +#define VC_GEOMETRY_LINE_THICKNESS 0x0000ff00 +#define VC_GEOMETRY_LINE_THICKNESS_SHIFT 8 + +#define VC_CONNECTION_PCOUNT_SHIFT 8 +#define VC_CONNECTION_PCOUNT_MASK 0x0000ff00 + +#define VC_GROUP_START 0 +#define VC_GROUP_END 1 + +#define VC_RAMP_ENABLE 0x00000001 + + +#define VC_INPUTRESOURCE_ENABLE 0x00000001 + + + +#define VC_CACHEMODE_DEFAULT 0 +#define VC_CACHEMODE_DO_CACHE 1 +#define VC_CACHEMODE_DONT_CACHE 2 + + +#define VC_DEBUG_HARCHY 0x00020000 +#define VC_DEBUG_HARCHY_EXTRA 0x00040000 +#define VC_DEBUG_RESOURCE 0x00080000 +#define VC_DEBUG_ENTITY 0x00100000 +#define VC_DEBUG_PICK 0x00200000 +#define VC_DEBUG_BODY_TRAVERSE 0x00400000 +#define VC_DEBUG_ATTRIBUTE 0x00800000 +#define VC_DEBUG_INPUT 0x01000000 +#define VC_DEBUG_TIMER 0x02000000 +#define VC_DEBUG_BODY_RESOURCE 0x04000000 + +#if defined (_TRANSPUTER) || defined (_IRIX) +#define VCWARNING(x) VC_Warn ( #x" at line %d of %s\n",__LINE__, __FILE__) + +#else +#define VCWARNING(x) {int WARNING = #x; \ + VC_Warn ( #x" at line %d of %s\n",__LINE__, __FILE__);} +#endif + +#define VCAwaitEvent(a,m) {_VCDoneWaitEvent = 1;VLAwaitEvent(a,m); } + + diff --git a/MUNGA_L4/libDPL/dvs/VCDTYPES.H b/MUNGA_L4/libDPL/dvs/VCDTYPES.H new file mode 100644 index 0000000..0e93343 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCDTYPES.H @@ -0,0 +1,394 @@ +/*************************************************************************** + * + * PROJECT: dVS + * SUBSYSTEM: VC Toolkit. + * MODULE: VC Type definitions. + * + *************************************************************************** + * + * File: $RCSfile: vctypes.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:11 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctypes.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * + * FUNCTION: + * + * + * + ************************************************************************** + * * + * Copyright (c) 1995 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +#ifndef _VCDTYPES_H +#define _VCDTYPES_H +typedef float32 VCColour[3]; + +#define VCColor VCColour /* For our American Friends !! */ +typedef struct +{ + uint32 secs; + uint32 uSecs; +}VCTime; + +typedef struct +{ + dmPosition dmPos; + uint32 mode; +}VCPositionData; + +typedef struct +{ + uint32 mode; + float32 frameRate; + float32 iod; + float32 convergence; + VCColour background; + float32 nearClip; + float32 farClip; + VCColour fogColour; + float32 nearFog; + float32 farFog; + float32 lodScale; + uint32 actorId; + char *name; +}VCVisualResourceData; + +typedef struct +{ + VCAttribute *visualResource; + uint32 mode; + dmPoint offset; + dmEuler orientation; + float32 size[2]; + char *name; +} VCVisualViewResourceData; + + +typedef struct +{ + uint32 mode; + uint32 flags; + float32 translation[6]; + float32 rotation[6]; +} VCConstraintsData; + +typedef struct +{ + uint32 mode; + VCInput *input; + char *name; +}VCInputResourceData; + +typedef struct { + uint32 mode; + VCTracker *tracker; + uint32 sensorId; + float32 translationScale[3]; + float32 rotationScale[3]; + float32 rotationCurveOrder[3]; + float32 translationCurveOrder[3]; + dmPoint prePosition; + dmPoint postPosition; + dmEuler preEuler; + dmEuler postEuler; + float32 relativeSphere[6]; + VCPosition *position; + VCConstraintsData constraints; + char *name; +} VCSensorResourceData; + +typedef struct +{ + uint32 updateRate; + uint32 transmissionDelay; + dmPoint sourcePosition; + dmEuler sourceEuler; + uint32 baudRate; + char *deviceType; + char *name; +}VCTrackerData; + + +typedef struct +{ + uint32 mode; + VCColour colour; + float32 exponent; + float32 theta; +}VCLightData; + +typedef struct +{ + uint32 mode; + uint32 intersectMask; + VCDynamicVisual *dynamicVisual; + char *geometryName; + char *frontMaterial; + char *backMaterial; + char *lod; +} VCVisualData; + +typedef struct +{ + VCAttribute *boundaryAttr; + uint16 flags; + dmPoint point; + dmVector direction; + VCTime time; +} VCCollisionReportData; + +typedef struct +{ + VCAttribute *boundary; + uint32 numberCollisions; + uint32 numberReportedCollisions; + VCCollisionReportData *collReportData; +}VCCollisionData; + +typedef struct +{ + float32 bound[VC_BOUND_SIZE]; + uint32 mode; + int32 numberCollisions; + VCCollision *collision; + VCDynamicVisual *dynamicVisual; + char *geometry; + char *lod; +}VCBoundaryData; + +typedef struct +{ + VCEntity *entity; + VCAttribute *visual; + InstanceNo patch; + dmPoint point; +}VCIntersectionReportData; + +typedef struct +{ + VCAttribute *vectorIntersect; + uint32 numberIntersections; + uint32 numberReportedIntersections; + VCIntersectionReportData *collReportData; +}VCIntersectionData; + +typedef struct +{ + uint32 mode; + float32 length; + uint32 intersectMask; + int32 numberIntersections; + VCIntersection *intersection; +}VCVectorIntersectData; + + + + +typedef struct +{ + uint32 mode; + int32 loopCount; + float32 gain; + uint16 play; + uint8 velocity; + int8 priority; + char *voice; + char *radiatorName; + char *radiatorFileName; +} VCAudioData; + +typedef struct +{ + uint32 mode; + float32 iad; + float32 volume; + float32 spreadingRollOff; + float32 atmosphericAbsorption; + float32 worldScale; + char *name; + char *hrtf; + char *resourceFile; +} VCAudioResourceData; + +typedef struct +{ + VCEntity *pickEntity; + uint32 mode; + uint32 pickActorId; +}VCPickObjectData; + +typedef struct +{ + uint32 mode; + VCColour ambient; + VCColour diffuse; + VCSpecular specular; + VCColour emissive; + VCColour opacity; + char *name; + char *textureName; + char *ramp; +} VCMaterialData; + +typedef struct +{ + uint32 mode; + uint8 minify; + uint8 magnify; + uint8 alpha; + uint8 wrapU; + uint8 wrapV; + uint8 detailType; + char *name; + char *textureMap; + char *detailMap; +} VCTextureData; + +typedef struct +{ + uint32 actorId; + char *name; + uint32 numAliases; + char **aliases; +} VCBodyPartData; + +typedef struct +{ + char8 *name; + int32 numPoints; + float32 points[VC_RADIATOR_MAX_POINTS]; +} VCRadiatorData; + +typedef struct +{ + uint32 mode; + uint32 type; + dmPoint offset; + float32 info[72]; + char *texture; +}VCVisualEffectData; + +typedef struct +{ + uint32 mode; + uint32 actorMask; +}VCZoneData; + +typedef struct +{ + uint32 mode; + float32 iMass; + float32 gMass; + dmPoint centre; + float32 iTensor[6]; + float32 spring; + float32 damper; + float32 staticFriction; + float32 dynamicFriction; +}VCDynamicsData; + +typedef struct +{ + uint32 mode; + dmVector force; + dmPoint point; +} VCForceData; + +typedef struct +{ + uint32 windowId; + char *serverName; + char *actorName; +} VCXWindowIdData; + +typedef struct +{ + uint32 mode; + dmVector direction; + float32 gravity; +}VCPseudoGravityData; + + +typedef struct +{ + float32 slow_speed; + float32 fast_speed; + float32 acceleration; + float32 max_speed; + uint32 slow_key; + uint32 fast_key; + uint32 accelerate_key; +}VCBodyFlyInfoData; + +typedef struct +{ + uint32 actorId; + VCEntity *bodyRoot; + VCEntity *bodyPosEntity; + VCBodyFlyInfoData fly_forward; + VCBodyFlyInfoData fly_backward; + VCBodyFlyInfoData fly_up; + VCBodyFlyInfoData fly_down; + VCBodyFlyInfoData fly_left; + VCBodyFlyInfoData fly_right; + VCBodyFlyInfoData rot_left; + VCBodyFlyInfoData rot_right; + VCBodyFlyInfoData rot_up; + VCBodyFlyInfoData rot_down; + uint32 verticalFly_key; + uint32 altFly_key; + VCEntity *flyDirectionLimb; + VCEntity *altFlyDirectionLimb; + VCEntity *altFlyLimb; + uint32 flyMode; + char *name; + char *user; + char *role; +} VCBodyData; + +typedef struct +{ + float32 objectInRate; + float32 objectInActive; + float32 objectTests; + char *name; +}VCCollideMonitorData; + +typedef struct +{ + float32 sensorRate[VC_MAX_SENSORS]; + int sensorBaseNumber; + char *name; +}VCTrackerMonitorData; + +typedef struct +{ + float32 headUpdateRate; /* No updates / second */ + float32 geometryUpdates; /* No updates / second */ + float32 frameRate; /* No frames drawn/second */ + float32 drawRate; /* Tri's per second */ + char8 *name; /* Name of the actor. */ +}VCVisualMonitorData; + +typedef struct +{ + uint32 mode; + VCColour minRgb; + VCColour maxRgb; + char* name; +} VCRampData; + +#endif + + + diff --git a/MUNGA_L4/libDPL/dvs/VCDYNAM.H b/MUNGA_L4/libDPL/dvs/VCDYNAM.H new file mode 100644 index 0000000..8e5ef07 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCDYNAM.H @@ -0,0 +1,538 @@ +/*************************************************************************** + * + * PROJECT: dVS + * SUBSYSTEM: VC Toolkit. + * MODULE: VC Type definitions (dynamic geometry). + * + *************************************************************************** + * + * File: $RCSfile: vcdynam.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:12 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcdynam.h,v 1.1 1995/03/10 14:52:46 steve Exp $ + * + * FUNCTION: + * + * + * + ************************************************************************** + * * + * Copyright (c) 1992 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +#ifndef _VCDYNTYPES_H +#define _VCDYNTYPES_H + +/* defines */ + + +/* typedefs */ + +typedef struct VCDynamicVisual_CallbackData VCDynamicVisual_CallbackData; +typedef void (*VCDynamicVisual_Func) (VCDynamicVisual_CallbackData *attributeData, void *data); +typedef struct VCLod_CallbackData VCLod_CallbackData; +typedef void (*VCLod_Func) (VCLod_CallbackData *attributeData, void *data); +typedef struct VCGeogroup_CallbackData VCGeogroup_CallbackData; +typedef void (*VCGeogroup_Func) (VCGeogroup_CallbackData *attributeData, void *data); +typedef struct VCGeometry_CallbackData VCGeometry_CallbackData; +typedef void (*VCGeometry_Func) (VCGeometry_CallbackData *attributeData, void *data); +typedef struct VCText_CallbackData VCText_CallbackData; +typedef void (*VCText_Func) (VCText_CallbackData *attributeData, void *data); +typedef struct VCConnectionList_CallbackData VCConnectionList_CallbackData; +typedef void (*VCConnectionList_Func) (VCConnectionList_CallbackData *attributeData, void *data); + + +typedef struct VCDynamicVisual_Traverse VCDynamicVisual_Traverse; +typedef struct VCLod_Traverse VCLod_Traverse; +typedef struct VCGeogroup_Traverse VCGeogroup_Traverse; +typedef struct VCGeometry_Traverse VCGeometry_Traverse; + +typedef enum { + VC_GEOMETRY_ALL=0x10, + VC_SPHERELIST=VC_GEOMETRY_TYPE_SPHERELIST, + VC_TRISTRIP=VC_GEOMETRY_TYPE_TRISTRIP, + VC_POLYSTRIP=VC_GEOMETRY_TYPE_POLYSTRIP, + VC_POLYGON=VC_GEOMETRY_TYPE_POLYGON, + VC_STRING=VC_GEOMETRY_TYPE_TEXT, + VC_VECTOR=VC_GEOMETRY_TYPE_LINE, + VC_PMESH=VC_GEOMETRY_TYPE_PMESH +} VCGeometry_Type; + +typedef enum { + VC_VERTEX_ALL = 0xff, + VC_VERTEX_XYZ = VC_GEOGROUP_VERTEX_ONLY, + VC_VERTEX_N =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_NORMALS), + VC_VERTEX_RGBA =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_RGBA), + VC_VERTEX_LA =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_LUMINANCE), + VC_VERTEX_UV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_UVW =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_3D_TEXTURE), + VC_VERTEX_NUV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_NORMALS | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_RGBAUV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_RGBA | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_LAUV =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_LUMINANCE | VC_GEOGROUP_VERTEX_2D_TEXTURE), + VC_VERTEX_SPHERE =(VC_GEOGROUP_VERTEX_ONLY | VC_GEOGROUP_VERTEX_RADIUS) +} VCVertex_Type; + +typedef float VCVertexXYZ[3]; +typedef float VCVertexN[6]; +typedef float VCVertexRGBA[7]; +typedef float VCVertexLA[5]; +typedef float VCVertexUV[5]; +typedef float VCVertexUVW[6]; +typedef float VCVertexNUV[8]; +typedef float VCVertexRGBAUV[9]; +typedef float VCVertexLAUV[7]; +typedef float VCVertexSphere[4]; + +typedef float *VCVertex; +typedef uint32 *VCConnection; + +typedef void (*VCDynamicVisual_TraverseFunc) (VCDynamicVisual *item, void *data); +typedef void (*VCLod_TraverseFunc) (VCLod *item, void *data); +typedef void (*VCGeogroup_TraverseFunc) (VCGeogroup *item, void *data); +typedef void (*VCGeometry_TraverseFunc) (VCGeometry *item, void *data); + +/* structures */ + +typedef struct { + uint32 faceCount; + uint32 noConnections; + VCConnection data; +} VCConnectionData; + +typedef struct { + VCConnectionList *connection; + int currentIndex, size, total, currentConnection; + VCConnectionData *connectData; + VCConnection data; +} VCConnection_Reference; + +typedef struct { + VCGeometry *geometry; + int currentIndex, size; + float distance; + VCVertex data; +} VCVertex_Reference; + +typedef struct { + float min[3]; + float max[3]; + float center[3]; +} VCGeometry_BoundBox; + +struct VCDynamicVisual +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCLod *lod; /* pointer to child LOD */ + void *octreeData; /* for future expansion */ + VCAttribute *attribute; /* pointer to parent */ + +}; + +struct VCLod +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCLod *next; /* LODs implemented as linked list */ + VCGeogroup *geogroup; /* pointer to child geogroup */ + void *octreeData; /* for future expansion */ + struct VCDynamicVisual *dvisual; /* pointer to parent */ + +}; + +struct VCGeogroup +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCGeogroup *next; /* GEOGROUPs implemented as linked list */ + VCGeometry *geometry; /* pointer to child geometry */ + void *octreeData; /* for future expansion */ + VCGeometry_BoundBox *boundingBox; /* define extents of attached geometry */ + VCLod *lod; /* pointer to parent */ + VCVertex_Type vertexFormat; /* copy of geogroup setting */ + +}; + +struct VCGeometry +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCGeometry *next; /* GEOMETRY implemented as linked list */ + void *octreeData; /* for future expansion */ + VCGeogroup *geogroup; /* pointer to parent */ + + VCGeometry_Type type; /* used to extract instanceData */ + VCVertex_Type vertexFormat; /* copy of geogroup setting */ + VCGeometry_BoundBox *boundingBox; /* define extents of attached geometry */ + VCConnectionList *connectionList; /* linked list for Pmeshes */ + +}; + +struct VCConnectionList +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + + VCConnectionData *connectData; + VCGeometry *geometry; /* pointer to parent */ + +}; + +struct VCDynamicVisual_CallbackData { + VCDynamicVisual *dvisual; +}; + +struct VCLod_CallbackData { + VCLod *lod; +}; + +struct VCGeogroup_CallbackData { + VCGeogroup *geogroup; +}; + +struct VCGeometry_CallbackData { + VCGeometry *geometry; +}; + +struct VCText_CallbackData { + VCGeometry *geometry; +}; + +struct VCConnectionList_CallbackData { + VCConnectionList *connectionList; + VCGeometry *geometry; +}; + +struct VCDynamicVisual_Traverse { + VCDynamicVisual *dvisual; + VCLod *current; +}; + +struct VCLod_Traverse { + VCLod *lod; + VCGeogroup *current; + VCVertex_Type search; +}; + +struct VCGeogroup_Traverse { + VCGeogroup *geogroup; + VCGeometry *current; + VCGeometry_Type search; +}; + +struct VCGeometry_Traverse { + VCGeometry *geometry; + VCConnectionList *current; +}; + + +/* macros */ + + +#define VCSphereList_Delete(g) VCGeometry_Delete(g) +#define VCSphereList_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCSphereList_Flush(g) VCGeometry_Flush(g) +#define VCSphereList_Create(n,v) VCGeometry_Create(VC_SPHERELIST, \ + VC_VERTEX_SPHERE,n,v,0,NULL) +#define VCGeogroup_AddSphereList(g, n,v) VCGeogroup_AddGeometry(g, \ + VC_SPHERELIST,\ + VC_VERTEX_SPHERE,n,v,0,NULL) + +#define VCPolystrip_Delete(g) VCGeometry_Delete(g) +#define VCPolystrip_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCPolystrip_Flush(g) VCGeometry_Flush(g) +#define VCPolystrip_Create(t,n,v) VCGeometry_Create(VC_POLYSTRIP, \ + t,n,v,0,NULL) +#define VCGeogroup_AddPolystrip(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_POLYSTRIP,\ + t,n,v,0,NULL) + +#define VCTristrip_Delete(g) VCGeometry_Delete(g) +#define VCTristrip_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCTristrip_Flush(g) VCGeometry_Flush(g) +#define VCTristrip_Create(t,n,v) VCGeometry_Create(VC_TRISTRIP, \ + t,n,v,0,NULL) +#define VCGeogroup_AddTristrip(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_TRISTRIP,\ + t,n,v,0,NULL) + +#define VCPolygon_Delete(g) VCGeometry_Delete(g) +#define VCPolygon_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCPolygon_Flush(g) VCGeometry_Flush(g) +#define VCPolygon_Create(t,n,v) VCGeometry_Create(VC_POLYGON, \ + t,n,v,0,NULL) +#define VCGeogroup_AddPolygon(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_POLYGON,\ + t,n,v,0,NULL) + +#define VCVector_Delete(g) VCGeometry_Delete(g) +#define VCVector_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCVector_Flush(g) VCGeometry_Flush(g) +#define VCVector_Create(t,n,v) VCGeometry_Create(VC_VECTOR, \ + t,n,v,0,NULL) +#define VCGeogroup_AddVector(g,t,n,v) VCGeogroup_AddGeometry(g, \ + VC_VECTOR,\ + t,n,v,0,NULL) + +#define VCPmesh_Delete(g) VCGeometry_Delete(g) +#define VCPmesh_ModifyVertexList(g) VCGeometry_Modify(g) +#define VCPmesh_FlushVertexList(g) VCGeometry_Flush(g) +#define VCPmesh_Create(t,n,v,c,l) VCGeometry_Create(VC_PMESH, \ + t,n,v,c,l) +#define VCGeogroup_AddPmesh(g,t,n,v,c,l) VCGeogroup_AddGeometry(g, \ + VC_PMESH,\ + t,n,v,c,l) + +#define VCString_Delete(g) VCText_Delete(g) +#define VCString_Create(s,f,p,o,c) VCText_Create(s,-1,f,p,o,c) +#define VCString_CreateSized(s,z,f,p,o,c) VCText_Create(s,z,f,p,o,c) +#define VCGeogroup_AddString(g,s,z,f,p,o,c) VCGeogroup_AddText(g,s,z,f,p,o,c) +#define VCString_SetMode(g,m) VCText_ModifyMode(g,m,0) +#define VCString_ModifyMode(g,m,c) VCText_ModifyMode(g,m,c) +#define VCString_GetMode(g,m) VCText_GetMode(g,m) +#define VCString_GetFont(g,m) VCText_GetFont(g,m) +#define VCString_GetText(g,m) VCText_GetText(g,m) +#define VCString_GetPositionOrientationScale(g,p,o,s) VCText_GetPositionOrientationScale(g,p,o,s) +#define VCString_SetFont(g,m) VCText_SetFont(g,m) +#define VCString_SetText(g,m) VCText_SetText(g,m) +#define VCString_SetPositionOrientationScale(g,p,o,s) VCText_SetPositionOrientationScale(g,p,o,s) + +#define VCGeogroup_AttachPmesh(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachTristrip(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachPolystrip(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachPolygon(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachVector(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachString(g,p) VCGeogroup_AttachGeometry(g,p) +#define VCGeogroup_AttachSphereList(g,p) VCGeogroup_AttachGeometry(g,p) + +#define VCGeogroup_DetachPmesh(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachTristrip(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachPolystrip(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachPolygon(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachVector(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachString(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCGeogroup_DetachSphereList(g,p) VCGeogroup_DetachGeometry(g,p) +#define VCEntity_AddDynamicVisual(e,v,f,b) VCEntity_AddVisual(e, NULL, v, \ + VC_VISIBLE | VC_RMODE_POLYGONAL, NULL, f, b, 0xffffffff) + +/* prototypes */ +VCDynamicVisual *VCDynamicVisual_Create(char *, uint32); +VCLod *VCDynamicVisual_AddLod(VCDynamicVisual *, char *, float, float, dmPoint); +int VCDynamicVisual_AttachLod(VCDynamicVisual *, VCLod *); +int VCDynamicVisual_DetachLod(VCDynamicVisual *, VCLod *); +VCLod *VCDynamicVisual_GetFirstLod(VCDynamicVisual *item, VCDynamicVisual_Traverse *trv); +VCLod *VCDynamicVisual_GetNextLod(VCDynamicVisual_Traverse *trv); +VCLod *VCDynamicVisual_GetIndexedLod(VCDynamicVisual *item, int index, + VCDynamicVisual_Traverse *trv); +VCLod *VCDynamicVisual_GetNamedLod(VCDynamicVisual *item, char *name, + VCDynamicVisual_Traverse *trv); +int VCDynamicVisual_ApplyPerLod(VCDynamicVisual *item, VCLod_TraverseFunc func, + void *data); +int VCDynamicVisual_ApplyPerGeogroup(VCDynamicVisual *item, VCGeogroup_TraverseFunc func, + void *data); +int VCDynamicVisual_ApplyPerGeometry(VCDynamicVisual *item, VCGeometry_TraverseFunc func, + void *data); +int VCDynamicVisual_GetNearestVertex(VCDynamicVisual *, dmPoint, float, + VCVertex_Reference *); + +VCLod *VCLod_Create(char *, float, float, dmPoint); +int VCLod_Get(VCLod *, char **, float *in, float *out, dmPoint reference); +int VCLod_Set(VCLod *lod, char *, float *in, float *out, dmPoint reference); +int VCLod_SetInOutDistance(VCLod *lod, float in, float out); +int VCLod_SetReference(VCLod *lod, dmPoint reference); +int VCLod_SetName(VCLod *lod, char *); +int VCLod_GetName(VCLod *lod, char **); +int VCLod_GetInOutDistance(VCLod *lod, float *in, float *out); +int VCLod_GetReference(VCLod *lod, dmPoint reference); +int VCLod_GetMode(VCLod *, uint32 *mode); +int VCLod_ModifyMode(VCLod *, uint32 setMode, uint32 clearMode); +int VCLod_AttachLod(VCLod *lod, VCLod *child); +int VCLod_DetachLod(VCLod *lod, VCLod *child); +int VCLod_AttachGeogroup(VCLod *lod, VCGeogroup *geogroup); +int VCLod_DetachGeogroup(VCLod *lod, VCGeogroup *geogroup); +VCGeogroup *VCLod_AddGeogroup(VCLod *lod, + VCVertex_Type, uint32, uint8, uint8, uint8, uint8, + char *, char *); +VCGeogroup *VCLod_GetFirstGeogroup(VCLod *lod, VCVertex_Type search, + VCLod_Traverse *traverse); +VCGeogroup *VCLod_GetNextGeogroup(VCLod_Traverse *traverse); +int VCLod_GetNearestVertex(VCLod *lod, dmPoint point, float dist, + VCVertex_Reference *ref); +int VCLod_ApplyPerGeogroup(VCLod *lod, VCGeogroup_TraverseFunc func, + void *data); +int VCLod_ApplyPerGeometry(VCLod *lod, VCGeometry_TraverseFunc func, + void *data); + + +VCGeogroup *VCGeogroup_Create(VCVertex_Type, uint32, uint8, uint8, uint8, uint8, + char *, char *); +int VCGeogroup_Get(VCGeogroup *group, VCVertex_Type *format, + uint32 *decal, uint8 *faceted, uint8 *lock, + uint8 *drawMode, uint8 *drawWidth, + char **fmat, char **bmat); +int VCGeogroup_Set(VCGeogroup *group, + uint32 *decal, uint8 *faceted, uint8 *lock, + uint8 *drawMode, uint8 *drawWidth, + VCVertex_Type *format, char *fmat, char *bmat); +int VCGeogroup_SetFrontMaterial(VCGeogroup *group, char *fmat); +int VCGeogroup_SetBackMaterial(VCGeogroup *group, char *bmat); +int VCGeogroup_SetMaterialAll(VCGeogroup *group, char *fmat, char *bmat); +int VCGeogroup_SetVertexFormat(VCGeogroup *group, VCVertex_Type format); +int VCGeogroup_SetMode(VCGeogroup *group, uint32 mode); +int VCGeogroup_ModifyMode(VCGeogroup *group, uint32 setMode, uint32 clearMode); +int VCGeogroup_GetMode(VCGeogroup *group, uint32 *mode); +int VCGeogroup_GetFrontMaterial(VCGeogroup *group, char **fmat); +int VCGeogroup_GetBackMaterial(VCGeogroup *group, char **bmat); +int VCGeogroup_GetMaterialAll(VCGeogroup *group, char **fmat, char **bmat); +int VCGeogroup_GetVertexFormat(VCGeogroup *group, VCVertex_Type *format); +int VCGeogroup_AttachGeometry(VCGeogroup *geogroup, VCGeometry *geometry); +int VCGeogroup_DetachGeometry(VCGeogroup *geogroup, VCGeometry *geometry); +VCGeometry *VCGeogroup_GetFirstGeometry(VCGeogroup *geogroup, VCGeometry_Type search, + VCGeogroup_Traverse *traverse); +VCGeometry *VCGeogroup_GetNextGeometry(VCGeogroup_Traverse *traverse); +int VCGeogroup_SetBoundBox(VCGeogroup *geogroup, VCGeometry_BoundBox *bbox); +int VCGeogroup_GetNearestVertex(VCGeogroup *geogroup, dmPoint point, float dist, + VCVertex_Reference *ref); +int VCGeogroup_ApplyPerGeometry(VCGeogroup *group, VCGeometry_TraverseFunc func, + void *data); + +VCGeometry *VCGeometry_Create(VCGeometry_Type, VCVertex_Type, uint32, VCVertex, + uint32, VCConnectionData *); +int VCGeometry_Get(VCGeometry *geometry, uint32 *mode, uint32 *noVertices); +int VCGeometry_Set(VCGeometry *geometry, uint32 setMode, uint32 clearMode, + uint32 noVertices, VCVertex data); +int VCPmesh_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCPmesh_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCTristrip_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCTristrip_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCPolystrip_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCPolystrip_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCPolygon_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCPolygon_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCVector_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCVector_SetThickness(VCGeometry *geometry, uint32 thickness); +int VCVector_GetThickness(VCGeometry *geometry, uint32 *thick); +int VCVector_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCSphereList_SetVertexList(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCSphereList_SetDicingHints(VCGeometry *geometry, uint32 dice_u, uint32 dice_v); +int VCSphereList_GetDicingHints(VCGeometry *geometry, uint32 *dice_u, uint32 *dice_v); +int VCSphereList_GetNoVertices(VCGeometry *geometry, uint32 *noVertices); +int VCGeometry_Modify(VCGeometry *geometry, uint32 noVertices, VCVertex data); +int VCGeometry_Flush(VCGeometry *geometry); +int VCGeometry_AttachConnectionList(VCGeometry *geom, VCConnectionList *connect); +int VCGeometry_GetFirstVertex(VCGeometry *geometry, VCVertex_Reference *ref); +int VCGeometry_GetNextVertex(VCVertex_Reference *ref); +int VCGeometry_GetIndexedVertex(VCGeometry *geometry, uint32 index, + VCVertex_Reference *ref); +VCConnectionList *VCGeometry_GetFirstConnectionList(VCGeometry *geometry, + VCGeometry_Traverse *traverse); +VCConnectionList *VCGeometry_GetNextConnectionList(VCGeometry_Traverse *traverse); +int VCGeometry_SetBoundBox(VCGeometry *geometry, VCGeometry_BoundBox *box); +int VCGeometry_GetNearestVertex(VCGeometry *geometry, dmPoint point, float dist, + VCVertex_Reference *ref); + +VCGeometry *VCText_Create(char *, uint32, uint8, dmPoint, dmEuler, dmScale); +int VCText_ModifyMode(VCGeometry *geometry, uint32 setMode, uint32 clearMode); +int VCText_Set(VCGeometry *geometry, uint8 *font, dmPoint pos, + dmEuler orient, dmScale scale, char *text); +int VCText_Get(VCGeometry *geometry, uint8 *font, dmPoint pos, dmEuler orient, + dmScale scale, char **text); +int VCText_GetMode(VCGeometry *geometry, uint32 *mode); +int VCText_SetFont(VCGeometry *geometry, uint8 font); +int VCText_SetPositionOrientationScale(VCGeometry *geometry, dmPoint pos, + dmEuler orient, dmScale scale); +int VCText_SetText(VCGeometry *geometry, char *text); +int VCText_GetFont(VCGeometry *geometry, uint8 *font); +int VCText_GetPositionOrientationScale(VCGeometry *geometry, dmPoint pos, + dmEuler orient, dmScale scale); +int VCText_GetText(VCGeometry *geometry, char **text); + +VCConnectionList *VCConnectionList_Create(uint32, VCConnectionData *); +int VCConnectionList_Get(VCConnectionList *connect, uint32 *noConnections, VCConnectionData **); +VCConnectionList *VCPmesh_AddConnectionList(VCGeometry *, uint32, VCConnectionData *); +int VCConnectionList_GetFirstConnection(VCConnectionList *connect, + VCConnection_Reference *ref); +int VCConnectionList_GetNextConnection(VCConnection_Reference *ref); +int VCPmesh_GetConnectionData(VCGeometry *, uint32 *, VCConnectionData **); +int VCPmesh_GetFirstConnection(VCGeometry *, VCConnection_Reference *); +int VCPmesh_GetNextConnection(VCConnection_Reference *); + +#endif diff --git a/MUNGA_L4/libDPL/dvs/VCELEMEN.H b/MUNGA_L4/libDPL/dvs/VCELEMEN.H new file mode 100644 index 0000000..ab30a7f --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCELEMEN.H @@ -0,0 +1,840 @@ +/* + * WARNING: machine generated code. + * + * do NOT edit this file, edit the + * original '.epp' file and regenerate this + * one. + */ + +#ifndef ____VCELEMEN_H +#define ____VCELEMEN_H + +#include +#include + +#ifdef __cplusplus +extern "C" { +#endif + +/* + * Instance number access macros. + */ +#define VL_VCObjectPosition_vcPos_ino(x) ((x)+1) +#define VL_VCObjectPosition_parent_ino(x) ((x)+2) +#define VL_VCObject_pos_ino(x) ((x)+1) +#define VL_VCObject_pos_vcPos_ino(x) ((x)+2) +#define VL_VCObject_pos_parent_ino(x) ((x)+3) +#define VL_VCObject_attributes_ino(x) ((x)+4) +#define VL_VCGeometry_header_ino(x) ((x)+1) +#define VL_VCGeometry_vertices_ino(x) ((x)+2) +#define VL_VCText_header_ino(x) ((x)+1) +#define VL_VCText_text_ino(x) ((x)+2) +#define VL_VCConnectionList_header_ino(x) ((x)+1) +#define VL_VCConnectionList_connections_ino(x) ((x)+2) + + + +/* + * Generated function declarations. + */ +extern int32 ModuleVCInit ( void ); + +extern InstanceNo (VLCreateVCTime)(VCTime *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDeleteVCTime)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdateVCTime)(InstanceNo ino, VCTime *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtractVCTime)(InstanceNo ino , VCTime *data, VLTime *utime); + +extern InstanceNo (VLCreateVCColour)(float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDeleteVCColour)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdateVCColour)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtractVCColour)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCPosition)(_VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCPosition)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCPosition)(InstanceNo ino, _VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCPosition)(InstanceNo ino , _VCPosition *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCObjectPosition)(_VCObjectPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCObjectPosition)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCObjectPosition)(InstanceNo ino, _VCObjectPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObjectPosition)(InstanceNo ino , _VCObjectPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObjectPosition_vcPos)(InstanceNo ino, _VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObjectPosition_vcPos)(InstanceNo ino , _VCPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObjectPosition_parent)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObjectPosition_parent)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCObject)(_VCObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCObject)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCObject)(InstanceNo ino, _VCObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject)(InstanceNo ino , _VCObject *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_pos)(InstanceNo ino, _VCObjectPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_pos)(InstanceNo ino , _VCObjectPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_pos_vcPos)(InstanceNo ino, _VCPosition *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_pos_vcPos)(InstanceNo ino , _VCPosition *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_pos_parent)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_pos_parent)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCObject_attributes)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCObject_attributes)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConstraints)(_VCConstraints *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCConstraints)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConstraints)(InstanceNo ino, _VCConstraints *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCConstraints)(InstanceNo ino , _VCConstraints *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCZone)(_VCZone *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCZone)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCZone)(InstanceNo ino, _VCZone *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCZone)(InstanceNo ino , _VCZone *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualMonitor)(_VCVisualMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualMonitor)(InstanceNo ino, _VCVisualMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualMonitor)(InstanceNo ino , _VCVisualMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConfigRequest)(_VCConfigRequest *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCConfigRequest)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConfigRequest)(InstanceNo ino, _VCConfigRequest *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConfigRequest)(InstanceNo ino , _VCConfigRequest *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConfigReply)(_VCConfigReply *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCConfigReply)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConfigReply)(InstanceNo ino, _VCConfigReply *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConfigReply)(InstanceNo ino , _VCConfigReply *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCUser)(_VCUser *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCUser)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCUser)(InstanceNo ino, _VCUser *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCUser)(InstanceNo ino , _VCUser *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCResource)(_VCResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCResource)(InstanceNo ino, _VCResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCResource)(InstanceNo ino , _VCResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCResourceRequest)(_VCResourceRequest *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCResourceRequest)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCResourceRequest)(InstanceNo ino, _VCResourceRequest *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCResourceRequest)(InstanceNo ino , _VCResourceRequest *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCAudio)(_VCAudio *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCAudio)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCAudio)(InstanceNo ino, _VCAudio *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCAudio)(InstanceNo ino , _VCAudio *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCRadiator)(_VCRadiator *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCRadiator)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCRadiator)(InstanceNo ino, _VCRadiator *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCRadiator)(InstanceNo ino , _VCRadiator *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCAudioResource)(_VCAudioResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCAudioResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCAudioResource)(InstanceNo ino, _VCAudioResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCAudioResource)(InstanceNo ino , _VCAudioResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisual)(_VCVisual *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisual)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisual)(InstanceNo ino, _VCVisual *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisual)(InstanceNo ino , _VCVisual *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCMaterial)(_VCMaterial *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCMaterial)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCMaterial)(InstanceNo ino, _VCMaterial *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCMaterial)(InstanceNo ino , _VCMaterial *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCRamp)(_VCRamp *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCRamp)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCRamp)(InstanceNo ino, _VCRamp *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCRamp)(InstanceNo ino , _VCRamp *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTexture)(_VCTexture *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTexture)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTexture)(InstanceNo ino, _VCTexture *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTexture)(InstanceNo ino , _VCTexture *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCLight)(_VCLight *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCLight)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCLight)(InstanceNo ino, _VCLight *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCLight)(InstanceNo ino , _VCLight *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualResource)(_VCVisualResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualResource)(InstanceNo ino, _VCVisualResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualResource)(InstanceNo ino , _VCVisualResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualViewResource)(_VCVisualViewResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualViewResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualViewResource)(InstanceNo ino, _VCVisualViewResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualViewResource)(InstanceNo ino , _VCVisualViewResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCIntersectionReport)(_VCIntersectionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCIntersectionReport)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCIntersectionReport)(InstanceNo ino, _VCIntersectionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCIntersectionReport)(InstanceNo ino , _VCIntersectionReport *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCIntersectionState)(_VCIntersectionState *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCIntersectionState)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCIntersectionState)(InstanceNo ino, _VCIntersectionState *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCIntersectionState)(InstanceNo ino , _VCIntersectionState *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVectorIntersect)(_VCVectorIntersect *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCVectorIntersect)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVectorIntersect)(InstanceNo ino, _VCVectorIntersect *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCVectorIntersect)(InstanceNo ino , _VCVectorIntersect *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualEffect)(_VCVisualEffect *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCVisualEffect)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualEffect)(InstanceNo ino, _VCVisualEffect *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCVisualEffect)(InstanceNo ino , _VCVisualEffect *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCDynamicVisual)(_VCDynamicVisual *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCDynamicVisual)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCDynamicVisual)(InstanceNo ino, _VCDynamicVisual *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCDynamicVisual)(InstanceNo ino , _VCDynamicVisual *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCLod)(_VCLod *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCLod)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCLod)(InstanceNo ino, _VCLod *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCLod)(InstanceNo ino , _VCLod *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCGeogroup)(_VCGeogroup *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCGeogroup)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCGeogroup)(InstanceNo ino, _VCGeogroup *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCGeogroup)(InstanceNo ino , _VCGeogroup *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCGeometryHeader)(_VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCGeometryHeader)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCGeometryHeader)(InstanceNo ino, _VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCGeometryHeader)(InstanceNo ino , _VCGeometryHeader *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCGeometry)(_VCGeometry *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCGeometry)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCGeometry)(InstanceNo ino, _VCGeometry *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCGeometry)(InstanceNo ino , _VCGeometry *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCGeometry_header)(InstanceNo ino, _VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCGeometry_header)(InstanceNo ino , _VCGeometryHeader *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCGeometry_vertices)(InstanceNo ino, float32 *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCGeometry_vertices)(InstanceNo ino , float32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTextData)(_VCTextData *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTextData)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTextData)(InstanceNo ino, _VCTextData *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTextData)(InstanceNo ino , _VCTextData *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCText)(_VCText *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCText)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCText)(InstanceNo ino, _VCText *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCText)(InstanceNo ino , _VCText *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCText_header)(InstanceNo ino, _VCGeometryHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCText_header)(InstanceNo ino , _VCGeometryHeader *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCText_text)(InstanceNo ino, _VCTextData *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCText_text)(InstanceNo ino , _VCTextData *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConnectionListHeader)(_VCConnectionListHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCConnectionListHeader)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConnectionListHeader)(InstanceNo ino, _VCConnectionListHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCConnectionListHeader)(InstanceNo ino , _VCConnectionListHeader *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCConnectionList)(_VCConnectionList *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCConnectionList)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCConnectionList)(InstanceNo ino, _VCConnectionList *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConnectionList)(InstanceNo ino , _VCConnectionList *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCConnectionList_header)(InstanceNo ino, _VCConnectionListHeader *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCConnectionList_header)(InstanceNo ino , _VCConnectionListHeader *data, VLTime *utime); + +extern VLStatus (VLUpdate_VCConnectionList_connections)(InstanceNo ino, uint32 *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCConnectionList_connections)(InstanceNo ino , uint32 *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCCollisionReport)(_VCCollisionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCCollisionReport)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCCollisionReport)(InstanceNo ino, _VCCollisionReport *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCCollisionReport)(InstanceNo ino , _VCCollisionReport *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCCollisionState)(_VCCollisionState *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCCollisionState)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCCollisionState)(InstanceNo ino, _VCCollisionState *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCCollisionState)(InstanceNo ino , _VCCollisionState *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBoundary)(_VCBoundary *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBoundary)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBoundary)(InstanceNo ino, _VCBoundary *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBoundary)(InstanceNo ino , _VCBoundary *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBodyPart)(_VCBodyPart *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBodyPart)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBodyPart)(InstanceNo ino, _VCBodyPart *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBodyPart)(InstanceNo ino , _VCBodyPart *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBodyMonitor)(_VCBodyMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBodyMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBodyMonitor)(InstanceNo ino, _VCBodyMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBodyMonitor)(InstanceNo ino , _VCBodyMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBodyFlyInfo)(_VCBodyFlyInfo *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCBodyFlyInfo)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBodyFlyInfo)(InstanceNo ino, _VCBodyFlyInfo *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCBodyFlyInfo)(InstanceNo ino , _VCBodyFlyInfo *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCBody)(_VCBody *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCBody)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCBody)(InstanceNo ino, _VCBody *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCBody)(InstanceNo ino , _VCBody *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCPickObject)(_VCPickObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCPickObject)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCPickObject)(InstanceNo ino, _VCPickObject *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCPickObject)(InstanceNo ino , _VCPickObject *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTrackerMonitor)(_VCTrackerMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTrackerMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTrackerMonitor)(InstanceNo ino, _VCTrackerMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTrackerMonitor)(InstanceNo ino , _VCTrackerMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCCollideMonitor)(_VCCollideMonitor *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCCollideMonitor)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCCollideMonitor)(InstanceNo ino, _VCCollideMonitor *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCCollideMonitor)(InstanceNo ino , _VCCollideMonitor *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCSensorResource)(_VCSensorResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCSensorResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCSensorResource)(InstanceNo ino, _VCSensorResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCSensorResource)(InstanceNo ino , _VCSensorResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCTracker)(_VCTracker *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCTracker)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCTracker)(InstanceNo ino, _VCTracker *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCTracker)(InstanceNo ino , _VCTracker *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCInputResource)(_VCInputResource *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCInputResource)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCInputResource)(InstanceNo ino, _VCInputResource *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCInputResource)(InstanceNo ino , _VCInputResource *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCInput)(_VCInput *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCInput)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCInput)(InstanceNo ino, _VCInput *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCInput)(InstanceNo ino , _VCInput *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCXWindowId)(_VCXWindowId *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCXWindowId)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCXWindowId)(InstanceNo ino, _VCXWindowId *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCXWindowId)(InstanceNo ino , _VCXWindowId *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCQuery)(_VCQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCQuery)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCQuery)(InstanceNo ino, _VCQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCQuery)(InstanceNo ino , _VCQuery *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCResponse)(_VCResponse *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCResponse)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCResponse)(InstanceNo ino, _VCResponse *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCResponse)(InstanceNo ino , _VCResponse *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCVisualQuery)(_VCVisualQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCVisualQuery)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCVisualQuery)(InstanceNo ino, _VCVisualQuery *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCVisualQuery)(InstanceNo ino , _VCVisualQuery *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCDynamics)(_VCDynamics *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCDynamics)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCDynamics)(InstanceNo ino, _VCDynamics *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCDynamics)(InstanceNo ino , _VCDynamics *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCForce)(_VCForce *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCForce)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCForce)(InstanceNo ino, _VCForce *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCForce)(InstanceNo ino , _VCForce *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCPseudoGravity)(_VCPseudoGravity *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLDelete_VCPseudoGravity)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCPseudoGravity)(InstanceNo ino, _VCPseudoGravity *data, VLTime *time, VLUpdateMode mode); +extern VLStatus (VLExtract_VCPseudoGravity)(InstanceNo ino , _VCPseudoGravity *data, VLTime *utime); + +extern InstanceNo (VLCreate_VCSync)(_VCSync *data, VLTime *time, VLUpdateMode mode, int32 count); +extern VLStatus (VLDelete_VCSync)(InstanceNo ino, VLUpdateMode mode); +extern VLStatus (VLUpdate_VCSync)(InstanceNo ino, _VCSync *data, VLTime *time, VLUpdateMode mode, uint32 count); +extern VLStatus (VLExtract_VCSync)(InstanceNo ino , _VCSync *data, VLTime *utime); + +#ifdef __VL_INLINE_ACCESS__ +#define VLCreateVCTime( d, t, m) vlCreateInstance(el_VCTime, 0, (d),(t),(m)) +#define VLDeleteVCTime(i,m) vlDeleteInstance((i),(m)) +#define VLUpdateVCTime( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtractVCTime(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreateVCColour( d, t, m) vlCreateInstance(el_VCColour, 0, (d),(t),(m)) +#define VLDeleteVCColour(i,m) vlDeleteInstance((i),(m)) +#define VLUpdateVCColour( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtractVCColour(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCPosition( d, t, m) vlCreateInstance(el__VCPosition, 0, (d),(t),(m)) +#define VLDelete_VCPosition(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCPosition( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCPosition(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCObjectPosition( d, t, m) vlCreateInstance(el__VCObjectPosition, 0, (d),(t),(m)) +#define VLDelete_VCObjectPosition(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCObjectPosition( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCObjectPosition(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCObjectPosition_vcPos( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCObjectPosition_vcPos(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCObjectPosition_parent( i, d, t, m) vlUpdateInstance((i) + 2,(d),(t),(m)) +#define VLExtract_VCObjectPosition_parent(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCObject( d, t, m) vlCreateInstance(el__VCObject, 0, (d),(t),(m)) +#define VLDelete_VCObject(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCObject( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCObject(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCObject_pos( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCObject_pos(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCObject_pos_vcPos( i, d, t, m) vlUpdateInstance((i) + 2,(d),(t),(m)) +#define VLExtract_VCObject_pos_vcPos(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLUpdate_VCObject_pos_parent( i, d, t, m) vlUpdateInstance((i) + 3,(d),(t),(m)) +#define VLExtract_VCObject_pos_parent(i, d, t) vlExtractInstance((i) + 3,(d),(t)) + + +#define VLUpdate_VCObject_attributes( i, d, t, m) vlUpdateInstance((i) + 4,(d),(t),(m)) +#define VLExtract_VCObject_attributes(i, d, t) vlExtractInstance((i) + 4,(d),(t)) + + +#define VLCreate_VCConstraints( d, t, m) vlCreateInstance(el__VCConstraints, 0, (d),(t),(m)) +#define VLDelete_VCConstraints(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConstraints( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCConstraints(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCZone( d, t, m) vlCreateInstance(el__VCZone, 0, (d),(t),(m)) +#define VLDelete_VCZone(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCZone( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCZone(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCVisualMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCConfigRequest(d, t, m, c) vlCreateDynamicInstance(el__VCConfigRequest,0,(d),(t),(m),(c)) +#define VLDelete_VCConfigRequest(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConfigRequest( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCConfigRequest(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCConfigReply(d, t, m, c) vlCreateDynamicInstance(el__VCConfigReply,0,(d),(t),(m),(c)) +#define VLDelete_VCConfigReply(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConfigReply( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCConfigReply(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCUser(d, t, m, c) vlCreateDynamicInstance(el__VCUser,0,(d),(t),(m),(c)) +#define VLDelete_VCUser(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCUser( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCUser(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCResource(d, t, m, c) vlCreateDynamicInstance(el__VCResource,0,(d),(t),(m),(c)) +#define VLDelete_VCResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCResourceRequest( d, t, m) vlCreateInstance(el__VCResourceRequest, 0, (d),(t),(m)) +#define VLDelete_VCResourceRequest(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCResourceRequest( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCResourceRequest(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCAudio(d, t, m, c) vlCreateDynamicInstance(el__VCAudio,0,(d),(t),(m),(c)) +#define VLDelete_VCAudio(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCAudio( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCAudio(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCRadiator( d, t, m) vlCreateInstance(el__VCRadiator, 0, (d),(t),(m)) +#define VLDelete_VCRadiator(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCRadiator( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCRadiator(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCAudioResource(d, t, m, c) vlCreateDynamicInstance(el__VCAudioResource,0,(d),(t),(m),(c)) +#define VLDelete_VCAudioResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCAudioResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCAudioResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisual(d, t, m, c) vlCreateDynamicInstance(el__VCVisual,0,(d),(t),(m),(c)) +#define VLDelete_VCVisual(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisual( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisual(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCMaterial(d, t, m, c) vlCreateDynamicInstance(el__VCMaterial,0,(d),(t),(m),(c)) +#define VLDelete_VCMaterial(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCMaterial( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCMaterial(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCRamp(d, t, m, c) vlCreateDynamicInstance(el__VCRamp,0,(d),(t),(m),(c)) +#define VLDelete_VCRamp(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCRamp( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCRamp(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCTexture(d, t, m, c) vlCreateDynamicInstance(el__VCTexture,0,(d),(t),(m),(c)) +#define VLDelete_VCTexture(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTexture( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTexture(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCLight( d, t, m) vlCreateInstance(el__VCLight, 0, (d),(t),(m)) +#define VLDelete_VCLight(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCLight( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCLight(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualResource(d, t, m, c) vlCreateDynamicInstance(el__VCVisualResource,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualViewResource(d, t, m, c) vlCreateDynamicInstance(el__VCVisualViewResource,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualViewResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualViewResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualViewResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCIntersectionReport( d, t, m) vlCreateInstance(el__VCIntersectionReport, 0, (d),(t),(m)) +#define VLDelete_VCIntersectionReport(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCIntersectionReport( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCIntersectionReport(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCIntersectionState(d, t, m, c) vlCreateDynamicInstance(el__VCIntersectionState,0,(d),(t),(m),(c)) +#define VLDelete_VCIntersectionState(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCIntersectionState( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCIntersectionState(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVectorIntersect( d, t, m) vlCreateInstance(el__VCVectorIntersect, 0, (d),(t),(m)) +#define VLDelete_VCVectorIntersect(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVectorIntersect( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCVectorIntersect(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualEffect(d, t, m, c) vlCreateDynamicInstance(el__VCVisualEffect,0,(d),(t),(m),(c)) +#define VLDelete_VCVisualEffect(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualEffect( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCVisualEffect(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCDynamicVisual(d, t, m, c) vlCreateDynamicInstance(el__VCDynamicVisual,0,(d),(t),(m),(c)) +#define VLDelete_VCDynamicVisual(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCDynamicVisual( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCDynamicVisual(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCLod(d, t, m, c) vlCreateDynamicInstance(el__VCLod,0,(d),(t),(m),(c)) +#define VLDelete_VCLod(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCLod( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCLod(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCGeogroup(d, t, m, c) vlCreateDynamicInstance(el__VCGeogroup,0,(d),(t),(m),(c)) +#define VLDelete_VCGeogroup(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCGeogroup( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCGeogroup(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCGeometryHeader( d, t, m) vlCreateInstance(el__VCGeometryHeader, 0, (d),(t),(m)) +#define VLDelete_VCGeometryHeader(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCGeometryHeader( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCGeometryHeader(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCGeometry(d, t, m, c) vlCreateDynamicInstance(el__VCGeometry,0,(d),(t),(m),(c)) +#define VLDelete_VCGeometry(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCGeometry( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCGeometry(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCGeometry_header( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCGeometry_header(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCGeometry_vertices( i, d, t, m,c) vlUpdateDynamicInstance((i) + 2,(d),(t),(m),(c)) +#define VLExtract_VCGeometry_vertices(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCTextData(d, t, m, c) vlCreateDynamicInstance(el__VCTextData,0,(d),(t),(m),(c)) +#define VLDelete_VCTextData(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTextData( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTextData(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCText(d, t, m, c) vlCreateDynamicInstance(el__VCText,0,(d),(t),(m),(c)) +#define VLDelete_VCText(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCText( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCText(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCText_header( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCText_header(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCText_text( i, d, t, m,c) vlUpdateDynamicInstance((i) + 2,(d),(t),(m),(c)) +#define VLExtract_VCText_text(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCConnectionListHeader( d, t, m) vlCreateInstance(el__VCConnectionListHeader, 0, (d),(t),(m)) +#define VLDelete_VCConnectionListHeader(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConnectionListHeader( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCConnectionListHeader(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCConnectionList(d, t, m, c) vlCreateDynamicInstance(el__VCConnectionList,0,(d),(t),(m),(c)) +#define VLDelete_VCConnectionList(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCConnectionList( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCConnectionList(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLUpdate_VCConnectionList_header( i, d, t, m) vlUpdateInstance((i) + 1,(d),(t),(m)) +#define VLExtract_VCConnectionList_header(i, d, t) vlExtractInstance((i) + 1,(d),(t)) + + +#define VLUpdate_VCConnectionList_connections( i, d, t, m,c) vlUpdateDynamicInstance((i) + 2,(d),(t),(m),(c)) +#define VLExtract_VCConnectionList_connections(i, d, t) vlExtractInstance((i) + 2,(d),(t)) + + +#define VLCreate_VCCollisionReport( d, t, m) vlCreateInstance(el__VCCollisionReport, 0, (d),(t),(m)) +#define VLDelete_VCCollisionReport(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCCollisionReport( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCCollisionReport(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCCollisionState(d, t, m, c) vlCreateDynamicInstance(el__VCCollisionState,0,(d),(t),(m),(c)) +#define VLDelete_VCCollisionState(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCCollisionState( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCCollisionState(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBoundary(d, t, m, c) vlCreateDynamicInstance(el__VCBoundary,0,(d),(t),(m),(c)) +#define VLDelete_VCBoundary(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBoundary( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBoundary(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBodyPart(d, t, m, c) vlCreateDynamicInstance(el__VCBodyPart,0,(d),(t),(m),(c)) +#define VLDelete_VCBodyPart(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBodyPart( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBodyPart(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBodyMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCBodyMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCBodyMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBodyMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBodyMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBodyFlyInfo( d, t, m) vlCreateInstance(el__VCBodyFlyInfo, 0, (d),(t),(m)) +#define VLDelete_VCBodyFlyInfo(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBodyFlyInfo( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCBodyFlyInfo(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCBody(d, t, m, c) vlCreateDynamicInstance(el__VCBody,0,(d),(t),(m),(c)) +#define VLDelete_VCBody(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCBody( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCBody(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCPickObject( d, t, m) vlCreateInstance(el__VCPickObject, 0, (d),(t),(m)) +#define VLDelete_VCPickObject(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCPickObject( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCPickObject(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCTrackerMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCTrackerMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCTrackerMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTrackerMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTrackerMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCCollideMonitor(d, t, m, c) vlCreateDynamicInstance(el__VCCollideMonitor,0,(d),(t),(m),(c)) +#define VLDelete_VCCollideMonitor(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCCollideMonitor( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCCollideMonitor(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCSensorResource(d, t, m, c) vlCreateDynamicInstance(el__VCSensorResource,0,(d),(t),(m),(c)) +#define VLDelete_VCSensorResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCSensorResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCSensorResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCTracker(d, t, m, c) vlCreateDynamicInstance(el__VCTracker,0,(d),(t),(m),(c)) +#define VLDelete_VCTracker(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCTracker( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCTracker(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCInputResource(d, t, m, c) vlCreateDynamicInstance(el__VCInputResource,0,(d),(t),(m),(c)) +#define VLDelete_VCInputResource(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCInputResource( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCInputResource(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCInput(d, t, m, c) vlCreateDynamicInstance(el__VCInput,0,(d),(t),(m),(c)) +#define VLDelete_VCInput(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCInput( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCInput(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCXWindowId(d, t, m, c) vlCreateDynamicInstance(el__VCXWindowId,0,(d),(t),(m),(c)) +#define VLDelete_VCXWindowId(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCXWindowId( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCXWindowId(i, d, t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCQuery( d, t, m) vlCreateInstance(el__VCQuery, 0, (d),(t),(m)) +#define VLDelete_VCQuery(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCQuery( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCQuery(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCResponse( d, t, m) vlCreateInstance(el__VCResponse, 0, (d),(t),(m)) +#define VLDelete_VCResponse(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCResponse( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCResponse(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCVisualQuery( d, t, m) vlCreateInstance(el__VCVisualQuery, 0, (d),(t),(m)) +#define VLDelete_VCVisualQuery(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCVisualQuery( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCVisualQuery(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCDynamics( d, t, m) vlCreateInstance(el__VCDynamics, 0, (d),(t),(m)) +#define VLDelete_VCDynamics(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCDynamics( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCDynamics(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCForce( d, t, m) vlCreateInstance(el__VCForce, 0, (d),(t),(m)) +#define VLDelete_VCForce(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCForce( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCForce(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCPseudoGravity( d, t, m) vlCreateInstance(el__VCPseudoGravity, 0, (d),(t),(m)) +#define VLDelete_VCPseudoGravity(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCPseudoGravity( i, d, t, m) vlUpdateInstance((i),(d),(t),(m)) +#define VLExtract_VCPseudoGravity(i,d,t) vlExtractInstance((i),(d),(t)) + +#define VLCreate_VCSync(d, t, m, c) vlCreateDynamicInstance(el__VCSync,0,(d),(t),(m),(c)) +#define VLDelete_VCSync(i,m) vlDeleteInstance((i),(m)) +#define VLUpdate_VCSync( i, d, t, m, c) vlUpdateDynamicInstance((i),(d),(t),(m),(c)) +#define VLExtract_VCSync(i, d, t) vlExtractInstance((i),(d),(t)) + +#endif +/* + * Symbolic element names. + */ +extern const ElementHandle el_VCTime; +extern const ElementHandle el_VCColour; +extern const ElementHandle el__VCPosition; +extern const ElementHandle el__VCObjectPosition; +extern const ElementHandle el__VCObject; +extern const ElementHandle el__VCConstraints; +extern const ElementHandle el__VCZone; +extern const ElementHandle el__VCVisualMonitor; +extern const ElementHandle el__VCConfigRequest; +extern const ElementHandle el__VCConfigReply; +extern const ElementHandle el__VCUser; +extern const ElementHandle el__VCResource; +extern const ElementHandle el__VCResourceRequest; +extern const ElementHandle el__VCAudio; +extern const ElementHandle el__VCRadiator; +extern const ElementHandle el__VCAudioResource; +extern const ElementHandle el__VCVisual; +extern const ElementHandle el__VCMaterial; +extern const ElementHandle el__VCRamp; +extern const ElementHandle el__VCTexture; +extern const ElementHandle el__VCLight; +extern const ElementHandle el__VCVisualResource; +extern const ElementHandle el__VCVisualViewResource; +extern const ElementHandle el__VCIntersectionReport; +extern const ElementHandle el__VCIntersectionState; +extern const ElementHandle el__VCVectorIntersect; +extern const ElementHandle el__VCVisualEffect; +extern const ElementHandle el__VCDynamicVisual; +extern const ElementHandle el__VCLod; +extern const ElementHandle el__VCGeogroup; +extern const ElementHandle el__VCGeometryHeader; +extern const ElementHandle el__VCGeometry; +extern const ElementHandle el__VCTextData; +extern const ElementHandle el__VCText; +extern const ElementHandle el__VCConnectionListHeader; +extern const ElementHandle el__VCConnectionList; +extern const ElementHandle el__VCCollisionReport; +extern const ElementHandle el__VCCollisionState; +extern const ElementHandle el__VCBoundary; +extern const ElementHandle el__VCBodyPart; +extern const ElementHandle el__VCBodyMonitor; +extern const ElementHandle el__VCBodyFlyInfo; +extern const ElementHandle el__VCBody; +extern const ElementHandle el__VCPickObject; +extern const ElementHandle el__VCTrackerMonitor; +extern const ElementHandle el__VCCollideMonitor; +extern const ElementHandle el__VCSensorResource; +extern const ElementHandle el__VCTracker; +extern const ElementHandle el__VCInputResource; +extern const ElementHandle el__VCInput; +extern const ElementHandle el__VCXWindowId; +extern const ElementHandle el__VCQuery; +extern const ElementHandle el__VCResponse; +extern const ElementHandle el__VCVisualQuery; +extern const ElementHandle el__VCDynamics; +extern const ElementHandle el__VCForce; +extern const ElementHandle el__VCPseudoGravity; +extern const ElementHandle el__VCSync; + +static const int ElCountVC = 58; + +/* + * Epp declaraions. NOT 'C' - hence the ifdef guard! + */ +#ifdef __EPP__ +%% +extern atomic element VCTime; +extern atomic element VCColour; +extern atomic element _VCPosition; +extern element _VCObjectPosition; +extern element _VCObject; +extern atomic element _VCConstraints; +extern atomic element _VCZone; +extern atomic element _VCVisualMonitor; +extern atomic element _VCConfigRequest; +extern atomic element _VCConfigReply; +extern atomic element _VCUser; +extern atomic element _VCResource; +extern atomic element _VCResourceRequest; +extern atomic element _VCAudio; +extern atomic element _VCRadiator; +extern atomic element _VCAudioResource; +extern atomic element _VCVisual; +extern atomic element _VCMaterial; +extern atomic element _VCRamp; +extern atomic element _VCTexture; +extern atomic element _VCLight; +extern atomic element _VCVisualResource; +extern atomic element _VCVisualViewResource; +extern atomic element _VCIntersectionReport; +extern atomic element _VCIntersectionState; +extern atomic element _VCVectorIntersect; +extern atomic element _VCVisualEffect; +extern atomic element _VCDynamicVisual; +extern atomic element _VCLod; +extern atomic element _VCGeogroup; +extern atomic element _VCGeometryHeader; +extern element _VCGeometry; +extern atomic element _VCTextData; +extern element _VCText; +extern atomic element _VCConnectionListHeader; +extern element _VCConnectionList; +extern atomic element _VCCollisionReport; +extern atomic element _VCCollisionState; +extern atomic element _VCBoundary; +extern atomic element _VCBodyPart; +extern atomic element _VCBodyMonitor; +extern atomic element _VCBodyFlyInfo; +extern atomic element _VCBody; +extern atomic element _VCPickObject; +extern atomic element _VCTrackerMonitor; +extern atomic element _VCCollideMonitor; +extern atomic element _VCSensorResource; +extern atomic element _VCTracker; +extern atomic element _VCInputResource; +extern atomic element _VCInput; +extern atomic element _VCXWindowId; +extern atomic element _VCQuery; +extern atomic element _VCResponse; +extern atomic element _VCVisualQuery; +extern atomic element _VCDynamics; +extern atomic element _VCForce; +extern atomic element _VCPseudoGravity; +extern atomic element _VCSync; +%% +#endif/* __EPP__ */ +#ifdef __cplusplus +} +#endif +#endif /* ____VCELEMEN_H */ diff --git a/MUNGA_L4/libDPL/dvs/VCELTYPE.H b/MUNGA_L4/libDPL/dvs/VCELTYPE.H new file mode 100644 index 0000000..b7640a3 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCELTYPE.H @@ -0,0 +1,629 @@ +/* + PROJET: + SUBSYSTEM: + MODULE: + + FILE: $RCSfile: vceltype.h,v $ + REVISION: $Revision: 1.1 $ + Date: $Date: 95/05/18 10:24:13 $ + Author: $Author: john $ + RCS Ident: $Id: vceltype.h,v 1.1 1995/03/10 14:52:46 john Exp $ + + FUNCTION: + + + + + Copyright (c) 1992 Division Ltd. + + All Rights Reserved. + + This Document may not, in whole or in part, be copied, + photocopied, reproduced, translated, or reduced to and + electronic medium or machine readable form without prior + written consent from Division Ltd. +*/ +#ifndef VCELTYPE_H +#define VCELTYPE_H +#ifdef _LIB_VC +#include + +#else +#include +#endif + + +#define InstanceNo uint32 /* Define InstanceNo as a basic type !! */ + +#ifndef VCColor +typedef float32 VCColour[3]; +#endif +#ifndef _VCDTYPES_H +typedef struct +{ + uint32 secs; + uint32 uSecs; +}VCTime; +#endif +/* +typedef VCPositionData _VCPosition; +*/ + +/* +typedef struct +{ + uint32 secs; + uint32 uSecs; +}VCTime; +*/ + +typedef struct +{ + dmPosition dmPos; + uint32 mode; +}_VCPosition; + +typedef struct +{ + _VCPosition vcPos; + uint32 parent; +}_VCObjectPosition; + + +typedef struct +{ + uint32 mode; + int32 loopCnt; + float32 gain; + uint16 play; + uint8 velocity; + int8 priority; + char8 voice[1]; +}_VCAudio; + + +typedef struct +{ + char8 name[VC_RADIATOR_NAME_LENGTH]; + int32 numPoints; + float32 points[VC_RADIATOR_MAX_POINTS]; +} _VCRadiator; + + +typedef struct +{ + uint32 mode; + uint32 flags; + float32 point[6]; + float32 rotation[6]; +} _VCConstraints; + +typedef struct +{ + uint32 mode; + uint32 intersectMask; + InstanceNo dynamicIno; + char8 geometry[1]; +} _VCVisual; + + +typedef struct +{ + uint32 mode; + float32 ambient[3]; + float32 diffuse[3]; + float32 specular[4]; + float32 emissive[3]; + float32 opacity[3]; + char8 name[1]; +} _VCMaterial; + +typedef struct +{ + uint32 mode; + uint8 minify; + uint8 magnify; + uint8 alpha; + uint8 wrapU; + uint8 wrapV; + uint8 detailType; + char8 name[1]; +} _VCTexture; + +typedef struct +{ + InstanceNo boundaryIno; + uint16 flags; + dmPoint point; + dmVector direction; + VCTime time; +} _VCCollisionReport; + +typedef struct +{ + InstanceNo myBoundaryIno; + uint32 numberCollisions; + _VCCollisionReport collisions[1]; +} _VCCollisionState; + + +typedef struct +{ + float32 bound[VC_BOUND_SIZE]; + uint32 mode; + int32 numberCollisions; + InstanceNo collisionStateIno; + InstanceNo dynamicVisual; + char8 geometry[1]; +} _VCBoundary; + +/* +typedef struct VCLightData _VCLight; +*/ + +typedef struct +{ + uint32 mode; + VCColour colour; + float32 exponent; + float32 theta; +}_VCLight; + + + +typedef struct +{ + _VCObjectPosition pos; + InstanceNo attributes[VC_MAX_OBJECT_ATTRIBUTES]; +}_VCObject; + +typedef struct +{ + uint32 actorId; + char8 name[1]; +} _VCBodyPart; + +typedef struct +{ + float32 headUpdateRate; /* No updates / second */ + float32 geometryUpdates; /* No updates / second */ + float32 frameRate; /* No frames drawn/second */ + float32 drawRate; /* Tri's per second */ + char8 name[1]; /* Name of the actor. */ +}_VCVisualMonitor; + + +typedef struct +{ + float32 sensorRate[VC_MAX_SENSORS]; /* Sensor updates per second */ + uint32 sensorBaseNumber; + char8 name[1]; /* Name of the actor. */ +}_VCTrackerMonitor; + +typedef struct { + uint32 updateRate; + uint32 transmissionDelay; + dmPoint sourcePosition; + dmEuler sourceEuler; + uint32 baudRate; + char8 name[1]; +} _VCTracker; + +typedef struct { + uint32 mode; + InstanceNo trackerIno; + uint32 sensorId; + float32 scaleTranslate[3]; + float32 scaleRotate[3]; + float32 rotationCurveOrder[3]; + float32 translationCurveOrder[3]; + dmPoint prePosition; + dmPoint postPosition; + dmEuler preEuler; + dmEuler postEuler; + float32 relativeSphere[6]; + InstanceNo positionIno; + _VCConstraints constraints; + char8 name[1]; /* Name of the actor. */ +} _VCSensorResource; + +typedef struct +{ + uint32 mode; + InstanceNo inputIno; + char8 name[1]; /* Name of the actor. */ +} _VCInputResource; + +typedef struct +{ + float32 objectInRate; /* Object updates per second */ + float32 objectInActive; /* Objects that are collidable per second */ + float32 objectTests; /* Number of collision tests per second */ + char8 name[1]; /* Name of the actor. */ +} _VCCollideMonitor; + + +typedef struct +{ + char8 name[1]; /* Name of the actor. */ +} _VCBodyMonitor; + +typedef struct +{ + uint32 mode; + float32 frameRate; + float32 iod; + float32 convergence; + float32 background[3]; + float32 nearClip; + float32 farClip; + float32 fogColour[3]; + float32 nearFog; + float32 farFog; + float32 lodScale; + uint32 actorId; + char8 name[1]; +} _VCVisualResource; + + +typedef struct +{ + InstanceNo visualResourceIno; + uint32 mode; + dmPoint offset; + dmEuler orientation; + float32 size[2]; + char8 name[1]; +} _VCVisualViewResource; + + +typedef struct +{ + float32 slow_speed; + float32 fast_speed; + float32 acceleration; + float32 max_speed; + uint32 slow_key; + uint32 fast_key; + uint32 accelerate_key; +}_VCBodyFlyInfo; + +typedef struct +{ + uint32 actorId; + InstanceNo bodyRoot; + InstanceNo bodyPosObject; + _VCBodyFlyInfo fly_forward; + _VCBodyFlyInfo fly_backward; + _VCBodyFlyInfo fly_up; + _VCBodyFlyInfo fly_down; + _VCBodyFlyInfo fly_left; + _VCBodyFlyInfo fly_right; + _VCBodyFlyInfo rot_left; + _VCBodyFlyInfo rot_right; + _VCBodyFlyInfo rot_up; + _VCBodyFlyInfo rot_down; + uint32 verticalFly_key; + uint32 altFly_key; + InstanceNo flyDirectionLimb; + InstanceNo altFlyDirectionLimb; + InstanceNo altFlyLimb; + uint32 flyMode; + char8 name[1]; +} _VCBody; + +typedef struct +{ + InstanceNo ino; + char8 name[1]; +} _VCConfigRequest; + +typedef struct +{ + InstanceNo user; + int32 verbose; + int32 enable; + char8 log[4]; + char8 config[1]; +} _VCConfigReply; + +typedef struct +{ + char8 name[1]; +} _VCUser; + +typedef struct +{ + InstanceNo resourceIno; + uint8 allocated; + char8 name[1]; +}_VCResource; + +typedef struct +{ + InstanceNo resource; + int32 updated; + InstanceNo serverResource; + uint32 resourceType; +} _VCResourceRequest; + +typedef struct +{ + uint32 mode; + float32 iad; + float32 volume; + float32 spreadingRollOff; + float32 atmosphericAbsorption; + float32 worldScale; + char8 name[1]; +} _VCAudioResource; + +typedef struct +{ + uint32 numWraps; + int32 head; + uint32 input[1]; +}_VCInput; + +typedef struct +{ + InstanceNo pickInstance; + uint32 mode; + uint32 pickActorId; +}_VCPickObject; + +typedef struct { + uint32 windowId; /* Identity of the window */ + char8 name [1]; /* Name of the resource. */ +} _VCXWindowId; + +typedef struct { + + uint32 actorId; + uint32 mode; + InstanceNo subject; +} _VCQuery; + +typedef struct { + uint32 status; + InstanceNo result; +} _VCResponse; + +typedef struct { + _VCQuery query; + _VCResponse response; +} _VCVisualQuery; + +typedef struct +{ + InstanceNo object; + InstanceNo visual; + InstanceNo patch; + dmPoint point; +} _VCIntersectionReport; + +typedef struct +{ + InstanceNo myVectorIntersectIno; + uint32 numberIntersections; + _VCIntersectionReport intersections[1]; +} _VCIntersectionState; + +typedef struct +{ + uint32 mode; + float32 length; + uint32 intersectMask; + int32 numberIntersections; + InstanceNo intersectStateIno; +}_VCVectorIntersect; + +typedef struct +{ + uint32 mode; + uint32 type; + dmPoint offset; + float32 data[72]; + char8 texture[1]; +}_VCVisualEffect; + +typedef struct +{ + uint32 mode; + float32 iMass; + float32 gMass; + dmPoint centre; + float32 iTensor[6]; + float32 spring; + float32 damper; + float32 staticFriction; + float32 dynamicFriction; +}_VCDynamics; + + +typedef struct +{ + uint32 mode; + dmVector force; + dmPoint point; +} _VCForce; + +typedef struct +{ + uint32 mode; + dmVector direction; + float32 gravity; +}_VCPseudoGravity; + +typedef struct +{ + uint32 mode; + uint32 actorMask; +}_VCZone; + +typedef struct +{ + uint32 mode; + InstanceNo lod; + char8 name[1]; +} _VCDynamicVisual; + +typedef struct +{ + uint32 mode; + float32 in; + float32 out; + dmPoint reference; + InstanceNo next; + char8 name[1]; +} _VCLod; + +typedef struct +{ + uint32 mode; + uint8 faceted; + uint8 vertexFormat; + uint8 lock; + uint8 drawMode; + uint8 drawWidth; + int32 decal; + InstanceNo lod; + char8 name[1]; +} _VCGeogroup; + +typedef struct +{ + uint32 mode; + uint32 numVertices; + InstanceNo geogroup; +} _VCGeometryHeader; + +typedef struct +{ + _VCGeometryHeader header; + float32 vertices[1]; +} _VCGeometry; + +typedef struct +{ + uint8 font; + dmPoint position; + dmEuler orientation; + dmScale scale; + char8 text[1]; +} _VCTextData; + +typedef struct +{ + _VCGeometryHeader header; + _VCTextData text; +} _VCText; + +typedef struct +{ + uint32 numConnections; + uint32 mode; + InstanceNo geometry; +} _VCConnectionListHeader; + +typedef struct +{ + _VCConnectionListHeader header; + uint32 connections[1]; +} _VCConnectionList; + +typedef struct +{ + VCTime time; + char8 name[1]; +} _VCSync; + +typedef struct +{ + uint32 mode; + VCColour minRgb; + VCColour maxRgb; + char8 name[1]; +} _VCRamp; + + + + +#undef InstanceNo /* Remove local Instance Number definition */ +#define el_VCPosition el__VCPosition +#define el_VCObjectPosition el__VCObjectPosition +#define el_VCObject el__VCObject +#define el_VCConstraints el__VCConstraints +#define el_VCZone el__VCZone + +#define el_VCVisualMonitor el__VCVisualMonitor +#define el_VCConfigRequest el__VCConfigRequest +#define el_VCConfigReply el__VCConfigReply +#define el_VCUser el__VCUser +#define el_VCResource el__VCResource +#define el_VCResourceRequest el__VCResourceRequest + +#define el_VCAudio el__VCAudio +#define el_VCRadiator el__VCRadiator +#define el_VCAudioResource el__VCAudioResource + + +#define el_VCVisual el__VCVisual +#define el_VCMaterial el__VCMaterial +#define el_VCTexture el__VCTexture +#define el_VCLight el__VCLight +#define el_VCVisualResource el__VCVisualResource +#define el_VCVisualViewResource el__VCVisualViewResource + +#define el_VCIntersect el__VCIntersect +#define el_VCVectorIntersect el__VCVectorIntersect + +#define el_VCIntersectionReport el__VCIntersectionReport +#define el_VCIntersectionState el__VCIntersectionState +#define el_VCNewVectorIntersect el__VCNewVectorIntersect + +#define el_VCVisualEffect el__VCVisualEffect + +#define el_VCCollisionReport el__VCCollisionReport +#define el_VCCollisionState el__VCCollisionState +#define el_VCBoundary el__VCBoundary + +#define el_VCBodyPart el__VCBodyPart +#define el_VCBodyMonitor el__VCBodyMonitor +#define el_VCBodyFlyInfo el__VCBodyFlyInfo +#define el_VCBody el__VCBody +#define el_VCPickObject el__VCPickObject + +#define el_VCTrackerMonitor el__VCTrackerMonitor +#define el_VCCollideMonitor el__VCCollideMonitor + + +#define el_VCSensorResource el__VCSensorResource +#define el_VCTracker el__VCTracker + +#define el_VCInputResource el__VCInputResource +#define el_VCInput el__VCInput + +#define el_VCXWindowId el__VCXWindowId + +#define el_VCQuery el__VCQuery +#define el_VCResponse el__VCResponse +#define el__VCResponse el__VCResponse +#define el_VCVisualQuery el__VCVisualQuery + +#define el_VCDynamics el__VCDynamics +#define el_VCForce el__VCForce +#define el_VCPseudoGravity el__VCPseudoGravity + +#define el_VCDynamicVisual el__VCDynamicVisual +#define el_VCLod el__VCLod +#define el_VCGeogroup el__VCGeogroup +#define el_VCGeometryHeader el__VCGeometryHeader +#define el_VCGeometry el__VCGeometry +#define el_VCTextData el__VCTextData +#define el_VCText el__VCText +#define el_VCConnectionListHeader el__VCConnectionListHeader +#define el_VCConnectionList el__VCConnectionList +#define el_VCSync el__VCSync +#define el_VCRamp el__VCRamp +#endif /* VCELTYPE_H */ diff --git a/MUNGA_L4/libDPL/dvs/VCERROR.H b/MUNGA_L4/libDPL/dvs/VCERROR.H new file mode 100644 index 0000000..c22a795 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCERROR.H @@ -0,0 +1,33 @@ +/* +-- ---------------------------------------------------------------------------- +-- +-- Copyright 1994 Division Limited. +-- All Rights Reserved +-- +-- +-- System : dVS 2.1 +-- Module : libvc +-- Object Name : $RCSfile: vcerror.h,v $ +-- Revision : $Revision: 1.1 $ +-- Date : $Date: 95/05/18 10:24:15 $ +-- Author : $Author: john $ +-- +-- Description +-- Vcerror routines. +-- +-- Notes +-- +-- History +-- +-- +-- ---------------------------------------------------------------------------- +*/ + +#ifndef __VCERROR_H__ +#define __VCERROR_H__ + +void VC_Warn(char *format, ...); +void VC_Error(char *format, ...); +void VC_Fatal(char *format, ...); + +#endif /* __VCERROR_H__ */ diff --git a/MUNGA_L4/libDPL/dvs/VCINPDEF.H b/MUNGA_L4/libDPL/dvs/VCINPDEF.H new file mode 100644 index 0000000..4849101 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCINPDEF.H @@ -0,0 +1,71 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vcinpdef.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:16 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcinpdef.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * + * FUNCTION: + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ + + +/* + * define the modifier values + */ +#define VC_INPUT_RELEASE 0x00010000 +#define VC_INPUT_PRESS 0x00020000 +#define VC_MODIFIER_0 0x00100000 +#define VC_MODIFIER_1 0x00200000 +#define VC_MODIFIER_2 0x00400000 +#define VC_MODIFIER_3 0x00800000 +#define VC_MODIFIER_4 0x01000000 +#define VC_MODIFIER_5 0x02000000 +#define VC_MODIFIER_6 0x04000000 +#define VC_MODIFIER_7 0x08000000 + +#define VC_MODIFIER_CTRL VC_MODIFIER_0 +#define VC_MODIFIER_ALT VC_MODIFIER_1 +#define VC_MODIFIER_ESC VC_MODIFIER_2 + +#define VC_INPUT_CODE_MASK 0x0000ffff +#define VC_INPUT_TYPE 0x000f0000 +#define VC_INPUT_MODIFIER_MASK 0x0ff00000 +#define VC_INPUT_ALL_KEYS 0x0000ffff +#define VC_INPUT_SINGLE_KEY 0x00000000 + +#define VC_BUTTON_0 0x0080 +#define VC_BUTTON_1 0x0081 +#define VC_BUTTON_2 0x0082 +#define VC_BUTTON_3 0x0083 +#define VC_BUTTON_4 0x0084 +#define VC_BUTTON_5 0x0085 +#define VC_BUTTON_6 0x0086 +#define VC_BUTTON_7 0x0087 +#define VC_BUTTON_8 0x0088 +#define VC_BUTTON_9 0x0089 +#define VC_BUTTON_10 0x008a +#define VC_BUTTON_11 0x008b +#define VC_BUTTON_12 0x008c +#define VC_BUTTON_13 0x008d +#define VC_BUTTON_14 0x008e +#define VC_BUTTON_15 0x008f + + + + + + + diff --git a/MUNGA_L4/libDPL/dvs/VCMACROS.H b/MUNGA_L4/libDPL/dvs/VCMACROS.H new file mode 100644 index 0000000..98c946b --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCMACROS.H @@ -0,0 +1,33 @@ +/* + * PROJECT: + * SUBSYSTEM: + * MODULE: + * + * FILE: $RCSfile: vctools.h,v $ + * REVISION: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:16 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctools.h,v 0.10 1994/10/05 12:51:14 john Exp jon $ + * + * FUNCTION: + * + * Copyright (c) 1995 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine reable form without prior + * written consent from Division Ltd. + */ + + + +#ifndef _VCMACROS_H_ +#define _VCMACROS_H_ + +#define VC_GetEntityRelocateMode() VCEntity_GetRelocateMode(NULL) +#define VC_SetEntityRelocateMode(m) VCEntity_SetRelocateMode(NULL,m) +#define VCBody_SetVisualResourceBackgroundColor(b,c) VCBody_SetVisualResourceBackgroundColour(b,c) +#define VCBody_SetVisualResourceFogColor(b,c,t,m) VCBody_SetVisualResourceFogColour(b,c,t,m) +#endif diff --git a/MUNGA_L4/libDPL/dvs/VCOBJECT.H b/MUNGA_L4/libDPL/dvs/VCOBJECT.H new file mode 100644 index 0000000..cf95747 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCOBJECT.H @@ -0,0 +1,686 @@ +/*************************************************************************** + * <210493.1436> + * PROJECT: dVS + * SUBSYSTEM: VCTools. + * MODULE: VC Object definitions. + * + *************************************************************************** + * + * File: $RCSfile: vcobject.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:17 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcobject.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * Creator: Jon Green. + * + * + * + ************************************************************************** + * * + * Copyright (c) 1992,1993,1994,1995 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +/*--- Include Definitions */ + +#ifndef _VCOBJECT_H +#define _VCOBJECT_H 1 + +/* Spin functions */ +#define VCEntity_SpinX(e,a) VCEntity_Spin(e,VC_X,a) +#define VCEntity_SpinY(e,a) VCEntity_Spin(e,VC_Y,a) +#define VCEntity_SpinZ(e,a) VCEntity_Spin(e,VC_Z,a) + +int VCEntity_Rotate (VCEntity *e, dmPoint centre, int axis, float angle); +int VCEntity_RotateX (VCEntity *e, float angle); +int VCEntity_RotateY (VCEntity *e, float angle); +int VCEntity_RotateZ (VCEntity *e, float angle); + + +int VCEntity_Spin (VCEntity *e, int axis, float angle); +int VCEntity_Scale (VCEntity *e, float sx, float sy, float sz); +int VCEntity_Resize (VCEntity *entity, float sx, float sy, float sz); +int VCEntity_Translate (VCEntity *e, float dx, float dy, float dz); + + +VCAttribute *VCVisual_Create (char *visual_name, VCDynamicVisual *dynamicVIsual, uint32 mode, char *lod, + char *frontMaterial, char *backMaterial, + uint32 intersectMask); +int VCVisual_Set (VCAttribute *attribute, char *visual_name, VCDynamicVisual *dynamicVisual, + uint32 setMode, uint32 clearMode, char *lod, char *frontMaterial, + char *backMaterial, uint32 setIntersectMask, + uint32 clearIntersectMask); +int VCVisual_Get (VCAttribute *attribute, char **visual_name, + VCDynamicVisual **dynamicVisual, + uint32 *mode, char **lod, char **frontMaterial, char **backMaterial, + uint32 *intersectMask); +VCAttribute *VCVisual_CreateData (VCVisualData *visualData); +int VCVisual_SetData (VCAttribute *attribute,VCVisualData *visualData); +int VCVisual_GetData (VCAttribute *attribute, VCVisualData *visualData); + +VCAttribute *VCEntity_AddVisual (VCEntity *entity, char *visual_name, VCDynamicVisual *DynamicVisual, + uint32 mode, char *lod, + char *frontMaterial, char *backMaterial, uint32 intersectMask); +VCAttribute *VCEntity_AddVisualData(VCEntity *entity, VCVisualData *visualData); +int VCVisual_SetGeometry (VCAttribute *attribute, char *visual_name); +int VCVisual_SetDynamicVisual (VCAttribute *attribute, VCDynamicVisual *dynamicVisual); +int VCVisual_SetMode (VCAttribute *attribute, uint32 mode); +int VCVisual_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVisual_SetFrontMaterial (VCAttribute *attribute, char *frontMaterial); +int VCVisual_SetBackMaterial (VCAttribute *attribute, char *backMaterial); +int VCVisual_SetLod (VCAttribute *attribute, char *lod); +int VCVisual_SetIntersectMask (VCAttribute *attribute, uint32 intersectMask); +int VCVisual_ModifyIntersectMask (VCAttribute *attribute, uint32 setIntersectMask, + uint32 clearIntersectMask); + +int VCVisual_GetGeometry (VCAttribute *attribute, char **visual_name); +int VCVisual_GetDynamicVisual (VCAttribute *attribute, VCDynamicVisual **dynamicVisual); +int VCVisual_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVisual_GetFrontMaterial (VCAttribute *attribute, char **frontMaterial); +int VCVisual_GetBackMaterial (VCAttribute *attribute, char **backMaterial); +int VCVisual_GetLod (VCAttribute *attribute, char **lod); +int VCVisual_GetIntersectMask (VCAttribute *attribute, uint32 *intersectMask); + +#define VCEntity_AddVisualGeometry(e,g) VCEntity_AddVisual(e, g, NULL, VC_VISIBLE | VC_RMODE_POLYGONAL, NULL, NULL, NULL, 0xffffffff) +#define VCEntity_DetachVisual(e,a) VCEntity_DetachAttribute(e,a) +#define VCVisual_CreateGeometry(g) VCVisual_Create( g, NULL, VC_VISIBLE|VC_RMODE_POLYGONAL, NULL, NULL, NULL, NULL) +#define VCVisual_Delete(a) VCAttribute_Delete(a) + + +VCAttribute *VCBodyPart_Create (char *bodyPart_name, uint32 actorId); +VCAttribute *VCBodyPart_CreateData (VCBodyPartData *bodyPart); +VCAttribute *VCEntity_AddBodyPartData(VCEntity *entity, VCBodyPartData *data); +VCAttribute *VCEntity_AddBodyPart (VCEntity *entity, char *bodyPart_name, uint32 actorId); +int VCBodyPart_Set (VCAttribute *attribute, char *bodyPart_name, + uint32 *actorId); +int VCBodyPart_SetData (VCAttribute *attribute, VCBodyPartData *bodyPart); +int VCBodyPart_SetName (VCAttribute *attribute, char *name); +int VCBodyPart_Get (VCAttribute *attribute, char **bodyPart_name, + uint32 *actorId); +int VCBodyPart_GetData (VCAttribute *attribute, VCBodyPartData *bodyPart); +int VCBodyPart_GetName (VCAttribute *attribute, char **name); +int VCBodyPart_GetActorId (VCAttribute *attribute, uint32 *actorId); + +#define VCEntity_DetachBodyPart(e,a) VCEntity_DetachAttribute(e, a) +#define VCBodyPart_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCPickObject_Create (VCEntity *entity, uint32 mode, uint32 actorId); +VCAttribute *VCPickObject_CreateData (VCPickObjectData *pickData); +int VCPickObject_Set (VCAttribute *attribute, VCEntity *entity, + uint32 setMode, uint32 clearMode, uint32 *actorId); +int VCPickObject_SetData (VCAttribute *attribute, VCPickObjectData *pickData); +int VCPickObject_Get (VCAttribute *attribute, VCEntity **entity, + uint32 *mode, uint32 *actorId); +int VCPickObject_GetData (VCAttribute *attribute, VCPickObjectData *pickData); +VCAttribute *VCEntity_AddPickObjectData(VCEntity *entity, VCPickObjectData *data); +VCAttribute *VCEntity_AddPickObject (VCEntity *entity, VCEntity *pickingEntity, uint32 mode, + uint32 pickActorId); + +#define VCEntity_DetachPickObject(e,a) VCEntity_DetachAttribute(e,a) +#define VCPickObject_Delete(a) VCAttribute_Delete(a) + + + +int VCPickObject_SetMode (VCAttribute *attribute, uint32 mode); +int VCPickObject_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCPickObject_SetPickingEntity (VCAttribute *attribute, VCEntity *entity); +int VCPickObject_SetActorId (VCAttribute *attribute, uint32 actorId); +int VCPickObject_GetMode (VCAttribute *attribute, uint32 *mode); +int VCPickObject_GetPickingEntity (VCAttribute *attribute, VCEntity **entity); +int VCPickObject_GetActorId (VCAttribute *attribute, uint32 *actorId); + + +VCAttribute *VCBoundary_Create (char *geometry, VCDynamicVisual *dynamicVisual, float32 bounds[VC_BOUND_SIZE], + uint32 mode, char *lod , int numCollisions); +VCAttribute *VCBoundary_CreateData (VCBoundaryData *boundaryData); +int VCBoundary_Set (VCAttribute *attribute, char *geometry, VCDynamicVisual *dynamicVisual, + float32 bounds[VC_BOUND_SIZE], uint32 setMode, uint32 clearMode, char *lod , + int32 *numberCollisions); +int VCBoundary_SetData (VCAttribute *attribute, VCBoundaryData *boundaryData); +int VCBoundary_Get (VCAttribute *attribute, char **geometry, VCDynamicVisual **dynamicVisual, + float32 bounds[VC_BOUND_SIZE], uint32 *mode, char **lod, int32 *numberCollisions, + VCCollision **collision); +int VCBoundary_GetData (VCAttribute *attribute, VCBoundaryData *boundaryData); +VCAttribute *VCEntity_AddBoundaryData(VCEntity *entity, VCBoundaryData *data); +VCAttribute *VCEntity_AddBoundary (VCEntity *entity, char *geometry, VCDynamicVisual *dynamicVisual, + float32 bounds[VC_BOUND_SIZE], uint32 mode, char *lod, int numCollisions ); +int VCBoundary_Delete(VCAttribute *attribute); + +#define VCEntity_DetachBoundary(e,a) VCEntity_DetachAttribute(e, a) +#define VCBoundary_CreateBbox(g) VCBoundary_Create(g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_BBOX, NULL, 1) +#define VCBoundary_CreateRadius(g) VCBoundary_Create(g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_RADIUS, NULL, 1) +#define VCBoundary_CreateGeometry(g) VCBoundary_Create(g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_GEOMETRY, NULL, 1) +#define VCEntity_AddBoundaryBbox(e,g) VCEntity_AddBoundary(e,g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_BBOX, NULL, 1) +#define VCEntity_AddBoundaryRadius(e,g) VCEntity_AddBoundary(e, g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_RADIUS, NULL, 1) +#define VCEntity_AddBoundaryGeometry(e,g) VCEntity_AddBoundary(e, g,NULL,NULL, VC_COLLISION_ENABLE | VC_COLLISION_GEOMETRY, NULL, 1) + + +int VCBoundary_ModifyMode(VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCBoundary_SetGeometry(VCAttribute *attribute, char *geometry); +int VCBoundary_SetDynamicVisual(VCAttribute *attribute, VCDynamicVisual *dynamicGeometry); +int VCBoundary_SetBounds(VCAttribute *attribute, float32 bounds[VC_BOUND_SIZE]); +int VCBoundary_SetMode(VCAttribute *attribute, uint32 mode); +int VCBoundary_SetLod(VCAttribute *attribute, char *lod); +int VCBoundary_SetNumberCollisions(VCAttribute *attribute, int32 numberCollisions); +int VCBoundary_GetGeometry(VCAttribute *attribute, char **geometry); +int VCBoundary_GetBounds(VCAttribute *attribute, float32 bounds[VC_BOUND_SIZE]); +int VCBoundary_GetMode(VCAttribute *attribute, uint32 *mode); +int VCBoundary_GetLod(VCAttribute *attribute, char **lod); +int VCBoundary_GetNumberCollisions(VCAttribute *attribute, int32 *numberCollisions); +int VCBoundary_GetCollision(VCAttribute *attribute, VCCollision **collision); +int VCBoundary_GetDynamicVisual(VCAttribute *attribute, VCDynamicVisual **dynamicGeometry); +void *VCBoundary_AttachCollisionCreateCallback(VCAttribute *boundary, VCCollision_Func func, void *data); +void *VCBoundary_AttachCollisionUpdateCallback(VCAttribute *boundary, VCCollision_Func func, void *data); +void *VCBoundary_AttachCollisionDeleteCallback(VCAttribute *boundary, VCCollision_Func func, void *data); +int VCBoundary_DetachCollisionCreateCallback(VCAttribute *boundary, void *callbackHandle); +int VCBoundary_DetachCollisionUpdateCallback(VCAttribute *boundary, void *callbackHandle); +int VCBoundary_DetachCollisionDeleteCallback(VCAttribute *boundary, void *callbackHandle); + +VCAttribute *VCLight_Create (uint32 mode, VCColour colour, float exponent, float theta); +VCAttribute *VCLight_CreateData (VCLightData *lightData); +int VCLight_Get (VCAttribute *attribute, uint32 *mode, VCColour colour, + float *exponent, float *theta); +int VCLight_GetData (VCAttribute *attribute, VCLightData *lightData); +VCAttribute *VCEntity_AddLightData(VCEntity *entity, VCLightData *data); +VCAttribute *VCEntity_AddLight (VCEntity *entity, uint32 mode, float32 *colour, + float exponent, float theta); +int VCLight_Set (VCAttribute *attribute, uint32 setMode, uint32 clearMode, + VCColour colour, float *exponent, float *theta); +int VCLight_SetData (VCAttribute *attribute, VCLightData *lightData); +int VCLight_SetMode (VCAttribute *attribute, uint32 mode); +int VCLight_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCLight_SetColour (VCAttribute *attribute, VCColour colour); +int VCLight_SetUmbra (VCAttribute *attribute, float32 exponent, float theta); + +int VCLight_GetMode (VCAttribute *attribute, uint32 *mode); +int VCLight_GetColour (VCAttribute *attribute, VCColour colour); +int VCLight_GetUmbra (VCAttribute *attribute, float32 *exponent, float32 *theta); + +#define VCEntity_DetachLight(e,a) VCEntity_DetachAttribute(e,a) +#define VCLight_Delete(a) VCAttribute_Delete(a) +#define VCLight_SetColor(a,c) VCLight_SetColour(a,c) +#define VCLight_GetColor(a,c) VCLight_GetColour(a,c) + +#define VCEntity_AddLightDirectional(e,c) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_DIRECTIONAL, c, 0.0f, 0.0f) +#define VCEntity_AddLightAmbient(e,c) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_AMBIENT, c, 0.0f, 0.0f) +#define VCEntity_AddLightPoint(e,c) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_POINT, c, 0.0f, 0.0f) +#define VCEntity_AddLightSpot(e,c,x,t) VCEntity_AddLight(e, VC_LIGHT_ENABLE | VC_LIGHT_MODE_SPOT, c, x, t) + +#define VCLight_CreateDirectional(c) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_DIRECTIONAL, c, 0.0f, 0.0f) +#define VCLight_CreateAmbient(c) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_AMBIENT, c, 0.0f, 0.0f) +#define VCLight_CreatePoint(c) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_POINT, c, 0.0f, 0.0f) +#define VCLight_CreateSpot(c,x,t) VCLight_Create(VC_LIGHT_ENABLE | VC_LIGHT_MODE_SPOT, c, x, t) + +VCAttribute *VCAudio_Create (char *voice, float32 gain, uint8 velocity, + uint32 mode, int32 loopCnt, int8 priority, + char *radiatorName, char *radiatorFileName); +VCAttribute *VCEntity_AddAudioData(VCEntity *entity, VCAudioData *data); +VCAttribute *VCEntity_AddAudio (VCEntity *entity, char *voice, float32 gain, uint8 velocity, + uint32 mode, int32 loopCnt, int8 priority, + char * radiatorName, char *radiatorFileName); +int VCAudio_Set (VCAttribute *attribute, char *voice, + float32 *gain, uint8 *velocity, uint32 setMode, + uint32 clearMode, uint8 play, int32 *loopCnt, int8 *priority, + char *radiatorName, char *radiatorFileName); +int VCAudio_Get (VCAttribute *attribute, char **voice, + float32 *gain, uint8 *velocity, uint32 *mode, + int32 *loopCnt, int8 *priority, + char **radiatorName, char **radiatorFileName); +VCAttribute *VCAudio_CreateData (VCAudioData *audioData); +int VCAudio_GetData (VCAttribute *attribute, VCAudioData *audioData); +int VCAudio_SetData (VCAttribute *attribute, VCAudioData *audioData); + +int VCAudio_SetVoice (VCAttribute *attribute, char *voice); +int VCAudio_SetMode (VCAttribute *attribute, uint32 mode); +int VCAudio_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCAudio_SetGain (VCAttribute *attribute, float32 gain); +int VCAudio_SetVelocity (VCAttribute *attribute, uint8 velocity); +int VCAudio_SetLoopCount (VCAttribute *attribute, int32 loopCnt); +int VCAudio_SetPriority (VCAttribute *attribute, int8 priority); +int VCAudio_SetRadiatorName(VCAttribute *attribute, char *radiator); +int VCAudio_SetRadiatorFile(VCAttribute *attribute, char *radiator); +int VCAudio_Start (VCAttribute *attribute); +int VCAudio_Stop (VCAttribute *attribute); + +int VCAudio_GetVoice (VCAttribute *attribute, char **voice); +int VCAudio_GetMode (VCAttribute *attribute, uint32 *mode); +int VCAudio_GetGain (VCAttribute *attribute, float32 *gain); +int VCAudio_GetVelocity (VCAttribute *attribute, uint8 *velocity); +int VCAudio_GetLoopCount (VCAttribute *attribute, int32 *loopCount); +int VCAudio_GetPriority (VCAttribute *attribute, int8 *priority); +int VCAudio_GetRadiatorName(VCAttribute *attribute, char **radiator); +int VCAudio_GetRadiatorFile(VCAttribute *attribute, char **radiator); + + +#define VCEntity_AddAudioVoice(e,v) VCEntity_AddAudio(e, v, 0, 80, 0, 1, 0, NULL, NULL) +#define VCEntity_DetachAudio(e,a) VCEntity_DetachAttribute(e,a) +#define VCAudio_CreateVoice(v) VCAudio_Create( v, 0, 80, 0, 1, 0, NULL, NULL) +#define VCAudio_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCConstraints_Create (uint32 mode, uint32 flags, float32 points[6], + float32 rotation[6]); +VCAttribute *VCConstraints_CreateData (VCConstraintsData *constraintsData); +int VCConstraints_Get (VCAttribute *attribute, uint32 *mode, uint32 *flags, + float32 points[6], float32 rotation[6]); +int VCConstraints_GetData (VCAttribute *attribute, VCConstraintsData *constraintsData); + +VCAttribute *VCEntity_AddConstraintsData(VCEntity *entity, VCConstraintsData *data); +VCAttribute *VCEntity_AddConstraints(VCEntity *entity, uint32 mode, uint32 flags, + float32 points[6], float32 rotation[6]); +int VCConstraints_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, uint32 setFlags, uint32 clearFlags, + float32 points[6], float32 rotation[6]); +int VCConstraints_SetData (VCAttribute *attribute, VCConstraintsData *constraintsData); + +int VCConstraints_SetMode (VCAttribute *attribute, uint32 mode); +int VCConstraints_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCConstraints_ModifyFlags (VCAttribute *attribute, uint32 setFlags, uint32 clearFlags); +int VCConstraints_SetFlags (VCAttribute *attribute, uint32 flags); +int VCConstraints_SetPoint (VCAttribute *attribute, float32 point[6]); +int VCConstraints_SetRotation (VCAttribute *attribute, float32 rotation[6]); +int VCConstraints_GetMode (VCAttribute *attribute, uint32 *mode); +int VCConstraints_GetFlags (VCAttribute *attribute, uint32 *flags); +int VCConstraints_GetPoint (VCAttribute *attribute, float32 point[6]); +int VCConstraints_GetRotation (VCAttribute *attribute, float32 rotation[6]); + + + + + +VCAttribute *VCEntity_AddConstraintsHinge(VCEntity *entity, uint32 axis, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsHingeX(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsHingeY(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsHingeZ(VCEntity *entity, float32 min, float32 max); + +VCAttribute *VCEntity_AddConstraintsTranslate(VCEntity *entity, uint32 axis, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsTranslateX(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsTranslateY(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsTranslateZ(VCEntity *entity, float32 min, float32 max); + +VCAttribute *VCEntity_AddConstraintsRotate(VCEntity *entity, uint32 axis, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsRotateX(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsRotateY(VCEntity *entity, float32 min, float32 max); +VCAttribute *VCEntity_AddConstraintsRotateZ(VCEntity *entity, float32 min, float32 max); + +VCAttribute *VCConstraints_CreateHinge(uint32 axis, float32 min, float32 max); +VCAttribute *VCConstraints_CreateHingeX(float32 min, float32 max); +VCAttribute *VCConstraints_CreateHingeY(float32 min, float32 max); +VCAttribute *VCConstraints_CreateHingeZ(float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslate(uint32 axis, float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslateX(float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslateY(float32 min, float32 max); +VCAttribute *VCConstraints_CreateTranslateZ(float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotate(uint32 axis, float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotateX(float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotateY(float32 min, float32 max); +VCAttribute *VCConstraints_CreateRotateZ(float32 min, float32 max); + +#define VCEntity_DetachConstraints(e,a) VCEntity_DetachAttribute(e,a) +#define VCConstraints_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCVisualResource_Create (char *name, uint32 mode, float32 frameRate, float32 iod, + float32 convergence, VCColour backGround, + float32 nearClip, float32 farClip, VCColour fogColour, + float32 nearFlog, float32 farFog, float32 lodScale, + uint32 actorId); +VCAttribute *VCVisualResource_CreateData (VCVisualResourceData *visualResource); +int VCVisualResource_Get (VCAttribute *attribute, char **name, uint32 *mode, + float32 *frameRate, float32 *iod, float32 *convergence, + VCColour backGround, float32 *nearClip, float32 *farClip, + VCColour fogColour, float32 *nearFog, float32 *farFog, + float32 *lodScale, uint32 *actorId); +int VCVisualResource_GetData (VCAttribute *attribute, VCVisualResourceData *visualResource); +int VCVisualResource_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *frameRate, float32 *iod, + float32 *convergence, VCColour backGround, + float32 *nearClip, float32 *farClip, VCColour fogColour, + float32 *nearFog, float32 *farFog, float32 *lodScale); +int VCVisualResource_SetData (VCAttribute *attribute, VCVisualResourceData *visualResource); +VCAttribute *VCEntity_AddVisualResourceData(VCEntity *entity, VCVisualResourceData *data); +VCAttribute *VCEntity_AddVisualResource (VCEntity *entity, char *name, uint32 mode, + float32 frameRate, float32 iod, float32 convergence, + VCColour backGround, float32 nearClip, float32 farClip, + VCColour fogColour, float32 nearFlog, float32 farFog, + float32 lodScale, uint32 actorId); + +#define VCEntity_DetachVisualResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCVisualResource_Delete(a) VCAttribute_Delete(a) + +int VCVisualResource_SetMode (VCAttribute *attribute, uint32 mode); +int VCVisualResource_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVisualResource_SetFrameRate (VCAttribute *attribute, float32 frameRate); +int VCVisualResource_SetIod (VCAttribute *attribute, float32 iod); +int VCVisualResource_SetConvergence (VCAttribute *attribute, float32 convergence); +int VCVisualResource_SetBackground (VCAttribute *attribute, VCColour backGround); +int VCVisualResource_SetNearClip (VCAttribute *attribute, float32 nearClip); +int VCVisualResource_SetFarClip (VCAttribute *attribute, float32 farClip); +int VCVisualResource_SetFogColour (VCAttribute *attribute, VCColour fogColour); +int VCVisualResource_SetNearFog (VCAttribute *attribute, float32 nearFog); +int VCVisualResource_SetFarFog (VCAttribute *attribute, float32 farFog); +int VCVisualResource_SetLodScale (VCAttribute *attribute, float32 lodScale); +int VCVisualResource_GetName (VCAttribute *attribute, char **name); +int VCVisualResource_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVisualResource_GetFrameRate (VCAttribute *attribute, float32 *frameRate); +int VCVisualResource_GetIod (VCAttribute *attribute, float32 *iod); +int VCVisualResource_GetConvergence (VCAttribute *attribute, float32 *convergence); +int VCVisualResource_GetBackground (VCAttribute *attribute, VCColour backGround); +int VCVisualResource_GetNearClip (VCAttribute *attribute, float32 *nearClip); +int VCVisualResource_GetFarClip (VCAttribute *attribute, float32 *farClip); +int VCVisualResource_GetFogColour (VCAttribute *attribute, VCColour fogColour); +int VCVisualResource_GetNearFog (VCAttribute *attribute, float32 *nearFog); +int VCVisualResource_GetFarFog (VCAttribute *attribute, float32 *farFog); +int VCVisualResource_GetLodScale(VCAttribute *attribute, float32 *lodScale); +int VCVisualResource_GetActorId(VCAttribute *attribute, uint32 *actorId); + +#define VCVisualResource_SetFogColor(a,c) VCVisualResource_SetFogColour(a,c) +#define VCVisualResource_GetFogColor(a,c) VCVisualResource_GetFogColour(a,c) + +VCAttribute *VCAudioResource_Create (char *name, uint32 mode, float32 iad, float32 volume, + float32 spreadingRollOff, float32 atmosAbsorb,char *hrtf, + char *resourceFileName); +VCAttribute *VCAudioResource_CreateData (VCAudioResourceData *audioData); +VCAttribute *VCEntity_AddAudioResourceData(VCEntity *entity, VCAudioResourceData *data); +VCAttribute *VCEntity_AddAudioResource (VCEntity *entity, char *name, uint32 mode, float32 iad, + float32 volume, float32 spreadingRollOff, float32 atmosAbsorb, + char *hrtf, char *resourceFileName); +int VCAudioResource_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *iad, float32 *volume, + float32 *spreadingRollOff, float32 *atmosphericAbsorption, + char *hrtf, char *resourceFileName); +int VCAudioResource_SetData (VCAttribute *attribute,VCAudioResourceData *audioData); +int VCAudioResource_Get (VCAttribute *attribute, char **name, uint32 *mode, + float32 *iad, float32 *volume, + float32 *spreadingRollOff, float32 *atmosphericAbsorption, + char **hrtf, char **resourceFileName); +int VCAudioResource_GetData (VCAttribute *attribute,VCAudioResourceData *audioData); +#define VCEntity_DetachAudioResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCAudioResource_Delete(a) VCAttribute_Delete(a) + +int VCAudioResource_SetIad (VCAttribute *attribute, float32 iad); +int VCAudioResource_SetMode (VCAttribute *attribute, uint32 mode); +int VCAudioResource_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCAudioResource_SetVolume (VCAttribute *attribute, float32 volume); +int VCAudioResource_SetHrtf (VCAttribute *attribute, char *hrtf); +int VCAudioResource_SetResourceFileName (VCAttribute *attribute, char *resourceName); +int VCAudioResource_SetSpreadingRollOff (VCAttribute *attribute, float32 spreadingRollOff); +int VCAudioResource_SetAtmosphericAbsorption (VCAttribute *attribute, + float32 atmosphericAbsorption); + +int VCAudioResource_GetName (VCAttribute *attribute, char **name); +int VCAudioResource_GetMode (VCAttribute *attribute, uint32 *mode); +int VCAudioResource_GetIad (VCAttribute *attribute, float32 *iad); +int VCAudioResource_GetVolume (VCAttribute *attribute, float32 *volume); +int VCAudioResource_GetHrtf (VCAttribute *attribute, char **hrtf); +int VCAudioResource_GetResourceFileName (VCAttribute *attribute, char **resourceName); +int VCAudioResource_GetSpreadingRollOff (VCAttribute *attribute, + float32 *spreadingRollOff); +int VCAudioResource_GetAtmosphericAbsorption (VCAttribute *attribute, + float32 *atomsphericAbsorption); + + + +VCAttribute *VCInputResource_Create (char *name, uint32 mode, VCInput *input); +VCAttribute *VCInputResource_CreateData (VCInputResourceData *inputData); +VCAttribute *VCEntity_AddInputResourceData(VCEntity *entity, VCInputResourceData *data); +VCAttribute *VCEntity_AddInputResource (VCEntity *entity, char *name, uint32 mode, VCInput *input); +int VCInputResource_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, VCInput *input); +int VCInputResource_SetData (VCAttribute *attribute, VCInputResourceData *inputData); +int VCInputResource_Get (VCAttribute *attribute, char **name, + uint32 *mode, VCInput **input); +int VCInputResource_GetData (VCAttribute *attribute, VCInputResourceData *inputData); +int VCInputResource_SetMode (VCAttribute *attribute, uint32 mode); +int VCInputResource_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCInputResource_GetName (VCAttribute *attribute, char **name); +int VCInputResource_GetMode (VCAttribute *attribute, uint32 *mode); +int VCInputResource_GetInput (VCAttribute *attribute, VCInput **input); + + +#define VCEntity_DetachInputResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCInputResource_Delete(a) VCAttribute_Delete(a) + +VCAttribute *VCSensorResource_Create (char *name, uint32 mode, VCTracker *tracker, uint32 sensorId, + float32 scaleTranslate[3], float32 scaleRotate[3], + float32 translationCurveOrder[3], float32 rotationCurveOrder[3], + dmPoint prePosition, dmPoint postPosition, dmEuler preEuler, + dmEuler postEuler, float32 relativeSphere[6], VCPosition *position, + VCConstraintsData *constraints); +VCAttribute *VCSensorResource_CreateData (VCSensorResourceData *sensorData); +VCAttribute *VCEntity_AddSensorResourceData(VCEntity *entity, VCSensorResourceData *data); +VCAttribute *VCEntity_AddSensorResource (VCEntity *entity, char *name, uint32 mode, VCTracker *tracker, + uint32 sensorId, float32 scaleTranslate[3], + float32 scaleRotate[3],float32 translationCurveOrder[3], + float32 rotationCurveOrder[3], dmPoint prePosition, + dmPoint postPosition, dmEuler preEuler, dmEuler postEuler, + float32 relativeSphere[6], + VCPosition *position, VCConstraintsData *constraints); + +int VCSensorResource_Set (VCAttribute *attribute, uint32 setMode, uint32 clearMode, + float32 scaleTranslate[3], + float32 scaleRotate[3], float32 translationCurveOrder[3], + float32 rotationCurveOrder[3], dmPoint prePosition, + dmPoint postPosition, dmEuler preEuler, dmEuler postEuler, + float32 relativeSphere[6], VCPosition *position, + VCConstraintsData *constraints); +int VCSensorResource_SetData (VCAttribute *attribute, VCSensorResourceData *sensorData); +int VCSensorResource_Get (VCAttribute *attribute, char **name, + uint32 *mode, VCTracker **tracker, uint32 *sensorId, + float32 scaleTranslate[3], float32 scaleRotate[3], + float32 translationCurveOrder[3], float32 rotationCurveOrder[3], + dmPoint prePosition, dmPoint postPosition, dmEuler preEuler, + dmEuler postEuler, float32 relativeSphere[6], + VCPosition **position, VCConstraintsData *constraints); +int VCSensorResource_GetData (VCAttribute *attribute, VCSensorResourceData *sensorData); + + +#define VCEntity_DetachSensorResource(e,a) VCEntity_DetachAttribute(e,a) +#define VCSensorResource_Delete(a) VCAttribute_Delete(a) + +int VCSensorResource_ModifyMode(VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCSensorResource_SetMode(VCAttribute *attribute, uint32 mode); +int VCSensorResource_SetTranslationScale(VCAttribute *attribute, float32 scaleTranslate[3]); +int VCSensorResource_SetRotationScale(VCAttribute *attribute, float32 scaleRotate[3]); +int VCSensorResource_SetTranslationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_SetRotationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_SetPrePosition(VCAttribute *attribute, dmPoint prePosition); +int VCSensorResource_SetPostPosition(VCAttribute *attribute, dmPoint postPosition); +int VCSensorResource_SetPreEuler(VCAttribute *attribute, dmEuler preEuler); +int VCSensorResource_SetPostEuler(VCAttribute *attribute, dmEuler postEuler); +int VCSensorResource_SetRelativeSphere(VCAttribute *attribute, float32 relativeSphere[6]); +int VCSensorResource_SetPosition(VCAttribute *attribute, VCPosition *pos); +int VCSensorResource_SetConstraints(VCAttribute *attribute, VCConstraintsData *constraints); +int VCSensorResource_GetName(VCAttribute *attribute, char **name); +int VCSensorResource_GetMode(VCAttribute *attribute, uint32 *mode); +int VCSensorResource_GetTracker(VCAttribute *attribute, VCTracker **tracker); +int VCSensorResource_GetSensorId(VCAttribute *attribute, uint32 *sensorId); +int VCSensorResource_GetTranslationScale(VCAttribute *attribute, float32 scaleTranslate[3]); +int VCSensorResource_GetRotationScale(VCAttribute *attribute, float32 scaleRotate[3]); +int VCSensorResource_GetTranslationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_GetRotationCurveOrder(VCAttribute *attribute, float32 curveOrder[3]); +int VCSensorResource_GetPrePosition(VCAttribute *attribute, dmPoint prePosition); +int VCSensorResource_GetPostPosition(VCAttribute *attribute, dmPoint postPosition); +int VCSensorResource_GetPreEuler(VCAttribute *attribute, dmEuler preEuler); +int VCSensorResource_GetPostEuler(VCAttribute *attribute, dmEuler postEuler); +int VCSensorResource_GetRelativeSphere(VCAttribute *attribute, float32 relativeSphere[6]); +int VCSensorResource_GetPosition(VCAttribute *attribute, VCPosition **pos); +int VCSensorResource_GetConstraints(VCAttribute *attribute, VCConstraintsData *constraints); + + +VCAttribute *VCVectorIntersect_Create (uint32 mode, float32 length, uint32 mask, + int32 numIntersections); +VCAttribute *VCVectorIntersect_CreateData (VCVectorIntersectData *intersectData); + +VCAttribute *VCEntity_AddVectorIntersectData(VCEntity *entity, VCVectorIntersectData *data); +VCAttribute *VCEntity_AddVectorIntersect (VCEntity *entity, uint32 mode, float32 length, + uint32 mask, int32 numIntersections); +int VCVectorIntersect_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *length, uint32 setMask, + uint32 clearMaks, int32 *numIntersections); +int VCVectorIntersect_SetData (VCAttribute *attribute, VCVectorIntersectData *intersectData); +int VCVectorIntersect_Get (VCAttribute *attribute, uint32 *mode, + float32 *length, uint32 *mask, int32 *numIntersections, + VCIntersection **intersection); +int VCVectorIntersect_GetData (VCAttribute *attribute, VCVectorIntersectData *intersectData); +int VCVectorIntersect_Delete(VCAttribute *attribute); +#define VCEntity_DetachVectorIntersect(e,a) VCEntity_DetachAttribute(e,a) + + +int VCVectorIntersect_SetMode (VCAttribute *attribute, uint32 mode); +int VCVectorIntersect_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVectorIntersect_SetLength (VCAttribute *attribute, float32 kength); +int VCVectorIntersect_SetIntersectMask (VCAttribute *attribute, uint32 mask); +int VCVectorIntersect_ModifyIntersectMask (VCAttribute *attribute, uint32 setMask, + uint32 clearMask); +int VCVectorIntersect_SetNumberIntersections (VCAttribute *attribute, int32 numIntersections); +int VCVectorIntersect_SetIntersection (VCAttribute *attribute, VCIntersection *intersection); + +int VCVectorIntersect_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVectorIntersect_GetLength (VCAttribute *attribute, float32 *length); +int VCVectorIntersect_GetIntersectMask (VCAttribute *attribute, uint32 *mask); +int VCVectorIntersect_GetNumberIntersections (VCAttribute *attribute, int32 numIntersections); +int VCVectorIntersect_GetIntersection (VCAttribute *attribute, VCIntersection **intersection); +void *VCVectorIntersect_AttachIntersectionCreateCallback(VCAttribute *intersect, + VCIntersection_Func func, void *data); +void *VCVectorIntersect_AttachIntersectionUpdateCallback(VCAttribute *intersect, + VCIntersection_Func func, void *data); +void *VCVectorIntersect_AttachIntersectionDeleteCallback(VCAttribute *intersect, + VCIntersection_Func func, void *data); + +int VCVectorIntersect_DetachIntersectionCreateCallback(VCAttribute *intersect, void *callbackHandle); +int VCVectorIntersect_DetachIntersectionUpdateCallback(VCAttribute *intersect, void *callbackHandle); + +int VCVectorIntersect_DetachIntersectionDeleteCallback(VCAttribute *intersect, void *callbackHandle); + + + + + + +VCAttribute *VCVisualEffect_Create (uint32 mode, uint32 type, dmPoint offset, float32 *data, + char *texture); +VCAttribute *VCVisualEffect_CreateData (VCVisualEffectData *visEffectData); +VCAttribute *VCEntity_AddVisualEffectData(VCEntity *entity, VCVisualEffectData *data); +VCAttribute *VCEntity_AddVisualEffect (VCEntity *entity, uint32 mode, uint32 type, + dmPoint offset, float *data, char *texture); +int VCVisualEffect_Set (VCAttribute *attribute, uint32 setMode, uint32 clearMode, + uint32 *type, dmPoint offset, float data[72], char *texture); +int VCVisualEffect_SetData (VCAttribute *attribute,VCVisualEffectData *visEffectData); +int VCVisualEffect_Get (VCAttribute *attribute, uint32 *mode, uint32 *type, + dmPoint offset, float32 data[72], char **texture); +int VCVisualEffect_GetData (VCAttribute *attribute,VCVisualEffectData *visEffectData); +#define VCEntity_DetachVisualEffect(e,a) VCEntity_DetachAttribute(e,a) +#define VCVisualEffect_Delete(a) VCAttribute_Delete(a) +#define VCEntity_AddVisualEffectExplosion(e,t,o,te) VCEntity_AddVisualEffect(e,VC_VISUALEFFECT_MODE_EXPLOSION,t,o,NULL,te) +#define VCVisualEffect_CreateExplosion(t,o,te) VCVisualEffect_Create(VC_VISUALEFFECT_MODE_EXPLOSION,t,o,NULL,te) +#define VCVisualEffect_StartExplosion(a,o) VCVisualEffect_Set(a,VC_VISUALEFFECT_ENABLE,0,NULL,o,NULL,NULL) + +int VCVisualEffect_SetMode (VCAttribute *attribute, uint32 mode); +int VCVisualEffect_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCVisualEffect_SetType (VCAttribute *attribute, uint32 type); +int VCVisualEffect_SetOffset (VCAttribute *attribute, dmPoint offset); +int VCVisualEffect_SetInfo (VCAttribute *attribute, float32 info[72]); +int VCVisualEffect_SetTexture (VCAttribute *attribute, char *texture); + +int VCVisualEffect_GetMode (VCAttribute *attribute, uint32 *mode); +int VCVisualEffect_GetType (VCAttribute *attribute, uint32 *type); +int VCVisualEffect_GetOffset (VCAttribute *attribute, dmPoint offset); +int VCVisualEffect_GetInfo (VCAttribute *attribute, float32 info[72]); +int VCVisualEffect_GetTexture (VCAttribute *attribute, char **texture); + + +VCAttribute *VCDynamics_Create (uint32 mode, float32 imass, float32 gmass, dmPoint centre, + float32 *iTensor, float32 spring, float32 damper, + float32 sFriction, float32 dFriction); +VCAttribute *VCDynamics_CreateData (VCDynamicsData *dynamicData); +int VCDynamics_Get (VCAttribute *attribute, uint32 *mode, float32 *imass, + float32 *gmass, dmPoint centre, float32 itensor[6], + float32 *spring, float32 *damper, float32 *sFriction, + float32 *dFricition); +int VCDynamics_GetData (VCAttribute *attribute, VCDynamicsData *dynamicData); +VCAttribute *VCEntity_AddDynamicsData(VCEntity *entity, VCDynamicsData *data); +VCAttribute *VCEntity_AddDynamics (VCEntity *entity, uint32 mode, float32 imass, float32 gmass, + dmPoint centre, float32 *iTensor, float32 spring, + float32 damper, float32 sFriction, float32 dFriction); +int VCDynamics_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, float32 *imass, float32 *gmass, + dmPoint centre, float32 *iTensor, float32 *spring, + float32 *damper, float32 *sFriction, float32 *dFriction); +int VCDynamics_SetData (VCAttribute *attribute, VCDynamicsData *dynamicData); +#define VCEntity_DetachDynamics(e,a) VCEntity_DetachAttribute(e,a) +#define VCDynamics_Delete(a) VCAttribute_Delete(a) + +int VCDynamics_SetMode (VCAttribute *attribute, uint32 mode); +int VCDynamics_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCDynamics_SetImass (VCAttribute *attribute, float32 imass); +int VCDynamics_SetGmass (VCAttribute *attribute, float32 gmass); +int VCDynamics_SetCentre (VCAttribute *attribute, dmPoint centre); +int VCDynamics_SetItensor (VCAttribute *attribute, float32 *itensor); +int VCDynamics_SetSpring (VCAttribute *attribute, float32 spring); +int VCDynamics_SetDamper (VCAttribute *attribute, float32 damper); +int VCDynamics_SetStaticFriction (VCAttribute *attribute, float32 sFriction); +int VCDynamics_SetDynamicFriction (VCAttribute *attribute, float32 dFriction); +int VCDynamics_GetMode (VCAttribute *attribute, uint32 *mode); +int VCDynamics_GetImass (VCAttribute *attribute, float32 *imass); +int VCDynamics_GetGmass (VCAttribute *attribute, float32 *gmass); +int VCDynamics_GetCentre (VCAttribute *attribute, dmPoint centre); +int VCDynamics_GetItensor (VCAttribute *attribute, float32 itensor[6]); +int VCDynamics_GetSpring (VCAttribute *attribute, float32 *spring); +int VCDynamics_GetDamper (VCAttribute *attribute, float32 *damper); +int VCDynamics_GetStaticFriction (VCAttribute *attribute, float32 *sFriction); +int VCDynamics_GetDynamicFriction (VCAttribute *attribute, float32 *dFriction); + + +VCAttribute *VCForce_Create (uint32 mode, dmVector force, dmPoint point); +VCAttribute *VCForce_CreateData (VCForceData *forceData); +int VCForce_Get (VCAttribute *attribute, uint32 *mode, dmVector force, dmPoint point); +int VCForce_GetData (VCAttribute *attribute, VCForceData *forceData); +VCAttribute *VCEntity_AddForceData(VCEntity *entity, VCForceData *data); +VCAttribute *VCEntity_AddForce (VCEntity *entity, uint32 mode, dmVector force, dmPoint point); +int VCForce_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, dmVector force, dmPoint point); +int VCForce_SetData (VCAttribute *attribute, VCForceData *forceData); + + + +#define VCEntity_DetachForce(e,a) VCEntity_DetachAttribute(e,a) +#define VCForce_Delete(a) VCAttribute_Delete(a) + +int VCForce_SetMode (VCAttribute *attribute, uint32 mode); +int VCForce_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCForce_SetForce (VCAttribute *attribute, dmVector force); +int VCForce_SetPoint (VCAttribute *attribute, dmPoint point); +int VCForce_GetMode (VCAttribute *attribute, uint32 *mode); +int VCForce_GetForce (VCAttribute *attribute, dmVector force); +int VCForce_GetPoint (VCAttribute *attribute, dmPoint point); + + + +VCAttribute *VCZone_Create (uint32 mode, uint32 actorMask); +VCAttribute *VCZone_CreateData (VCZoneData *zoneData); +int VCZone_Get (VCAttribute *attribute, uint32 *mode, uint32 *actorMask); +int VCZone_GetData (VCAttribute *attribute, VCZoneData *zoneData); +VCAttribute *VCEntity_AddZoneData(VCEntity *entity, VCZoneData *data); +VCAttribute *VCEntity_AddZone (VCEntity *entity, uint32 mode, uint32 actorMask); +int32 VCZone_Set (VCAttribute *attribute, uint32 setMode, + uint32 clearMode, uint32 setActorMask, uint32 clearActorMask); +int VCZone_SetData (VCAttribute *attribute, VCZoneData *zoneData); +#define VCEntity_DetachZone(e,a) VCEntity_DetachAttribute(e,a) +#define VCZone_Delete(a) VCAttribute_Delete(a) + +int VCZone_SetMode (VCAttribute *attribute, uint32 mode); +int VCZone_ModifyMode (VCAttribute *attribute, uint32 setMode, uint32 clearMode); +int VCZone_SetActorMask (VCAttribute *attribute, uint32 mask); +int VCZone_ModifyActorMask (VCAttribute *attribute, uint32 setMask, uint32 clearMask); +int VCZone_GetMode(VCAttribute *attribute, uint32 *mode); +int VCZone_GetActorMask(VCAttribute *attribute, uint32 *mask); + + + +#endif /* _VCOBJECT_H */ diff --git a/MUNGA_L4/libDPL/dvs/VCSTRUCT.H b/MUNGA_L4/libDPL/dvs/VCSTRUCT.H new file mode 100644 index 0000000..8aa8d43 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCSTRUCT.H @@ -0,0 +1,215 @@ + +struct VCActorConfig +{ + char *actorName; + char *domainName; + char *domainExtName; + char *userName; + char *userDir; + char *logName; + char *configData; + int32 verbose; + int32 enable; + int32 testMode; + FILE *fpLog; +}; + +struct VCBodyCreate_CallbackData +{ + VCBody *body; +}; + +struct VCBodyAttribute_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + VCAttribute *attribute; +}; + +struct VCBodyPartCreate_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; +}; + +struct VCTimer_CallbackData +{ + uint32 dummy; +}; + + +struct VCExit_CallbackData +{ + uint32 dummy; +}; + +struct VCGroup_CallbackData +{ + uint32 operation; +}; + + + +struct VCBodyInput_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + uint32 keyCode; +}; + +struct VCBodyCollision_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + VCCollision *collision; +}; + +struct VCInput_UpdateCallbackData +{ + VCInput *input; + VCAttribute *inputResource; + uint32 keyCode; +}; + +struct VCInput_CallbackData +{ + VCInput *input; + VCAttribute *inputResource; + uint32 keyCode; +}; + + +struct VCEntityRelocate_CallbackData +{ + VCEntity *entity; + VCPositionData *pos; + uint32 flags; +}; + +struct VCEntityInvalid_CallbackData +{ + VCEntity *entity; +}; + +struct VCAttributeRelocate_CallbackData +{ + VCEntity *entity; + int32 index; + VCAttribute *attribute; + VCPositionData *pos; + uint32 flags; +}; + +struct VCEntityAttribute_CallbackData +{ + VCEntity *entity; + int32 index; + VCAttribute *attribute; +}; + +struct VCAttribute_CallbackData +{ + VCAttribute *attribute; +}; + +struct VCCollision_CallbackData +{ + VCCollision *collision; +}; + +struct VCIntersection_CallbackData +{ + VCIntersection *intersection; +}; + +struct VCMaterial_CallbackData +{ + VCMaterial *material; +}; + +struct VCRadiator_CallbackData +{ + VCRadiator *radiator; +}; + +struct VCXWindowId_CallbackData +{ + VCXWindowId *xwindowId; +}; + +struct VCVisualViewResource_CallbackData +{ + VCVisualViewResource *view; +}; + +struct VCPseudoGravity_CallbackData +{ + VCPseudoGravity *pseudoGravity; +}; + +struct VCResourceAllocate_CallbackData +{ + char *name; +}; + + +struct VCPosition_CallbackData +{ + VCPosition *position; +}; + +struct VCTracker_CallbackData +{ + VCTracker *tracker; +}; + +struct VCSync_CallbackData +{ + VCSync *sync; +}; + +struct VCCollideMonitor_CallbackData +{ + VCCollideMonitor *collideMonitor; +}; + +struct VCTrackerMonitor_CallbackData +{ + VCTrackerMonitor *trackerMonitor; +}; + +struct VCVisualMonitor_CallbackData +{ + VCVisualMonitor *visualMonitor; +}; + +struct VCTexture_CallbackData +{ + VCTexture *texture; +}; + +struct VCRamp_CallbackData +{ + VCRamp *ramp; +}; + +typedef struct +{ + char *configName; + uint32 debug; + char *nameExt; + int logging; + char *logExt; + char *domainName; + int testMode; + uint32 verbose; +}VCCommandLineOptions ; + + +struct VCEntityDrop_CallbackData +{ + VCBody *body; + VCAttribute *bodyPart; + VCEntity *droppedEntity; +}; + diff --git a/MUNGA_L4/libDPL/dvs/VCTYPES.H b/MUNGA_L4/libDPL/dvs/VCTYPES.H new file mode 100644 index 0000000..3727674 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCTYPES.H @@ -0,0 +1,178 @@ +/*************************************************************************** + * + * PROJECT: dVS + * SUBSYSTEM: VC Toolkit. + * MODULE: VC Type definitions. + * + *************************************************************************** + * + * File: $RCSfile: vctypes.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:19 $ + * Author: $Author: john $ + * RCS Ident: $Id: vctypes.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * + * FUNCTION: + * + * + * + ************************************************************************** + * * + * Copyright (c) 1992 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +#ifndef _VCTYPES_H +#define _VCTYPES_H + +typedef struct VCBody VCBody; +typedef struct VCEntity VCEntity; +typedef struct VCAttribute VCAttribute; +typedef struct VCCollision VCCollision; +typedef struct VCIntersection VCIntersection; +typedef struct VCMaterial VCMaterial; +typedef struct VCRadiator VCRadiator; +typedef struct VCXWindowId VCXWindowId; +typedef struct VCVisualViewResource VCVisualViewResource; +typedef struct VCPseudoGravity VCPseudoGravity; +typedef struct VCTexture VCTexture; +typedef struct VCRamp VCRamp; +typedef struct VCInput VCInput; +typedef struct VCPosition VCPosition; +typedef struct VCTracker VCTracker; +typedef struct VCSync VCSync; +typedef struct VCMonitor VCCollideMonitor; +typedef struct VCMonitor VCTrackerMonitor; +typedef struct VCMonitor VCVisualMonitor; +typedef struct VCDynamicVisual VCDynamicVisual; +typedef struct VCLod VCLod; +typedef struct VCGeogroup VCGeogroup; +typedef struct VCGeometry VCGeometry; +typedef struct VCConnectionList VCConnectionList; + + +typedef struct VCCollisionReport_Traverse VCCollisionReport_Traverse; +typedef struct VCIntersectionReport_Traverse VCIntersectionReport_Traverse; +typedef struct VCEntity_Traverse VCEntity_Traverse; +typedef struct VCActorConfig VCActorConfig; +typedef struct VCEntity_AttributeTraverse VCEntity_AttributeTraverse; +typedef struct VCAttribute_EntityTraverse VCAttribute_EntityTraverse; + +typedef struct VCBody_Traverse VCBody_Traverse; +typedef struct VCBody_AttributeTraverse VCBody_AttributeTraverse; +typedef struct VCVisualView_Traverse VCVisualView_Traverse; +typedef struct VCUserDataList VCUserDataList; + +typedef struct VCCallbackFunctions VCCallbackFunctions; +typedef struct VCBodyCreate_CallbackData VCBodyCreate_CallbackData; +typedef struct VCBodyInput_CallbackData VCBodyInput_CallbackData; +typedef struct VCBodyCollision_CallbackData VCBodyCollision_CallbackData; +typedef struct VCBodyAttribute_CallbackData VCBodyAttribute_CallbackData; +typedef struct VCBodyPartCreate_CallbackData VCBodyPartCreate_CallbackData; + +typedef struct VLSignalEvent VCSignal_CallbackData; +typedef struct VLStreamEvent VCStream_CallbackData; +typedef struct VCResourceAllocate_CallbackData VCResourceAllocate_CallbackData; +typedef struct VCCollision_CallbackData VCCollision_CallbackData; +typedef struct VCIntersection_CallbackData VCIntersection_CallbackData; +typedef struct VCMaterial_CallbackData VCMaterial_CallbackData; +typedef struct VCRadiator_CallbackData VCRadiator_CallbackData; +typedef struct VCXWindowId_CallbackData VCXWindowId_CallbackData; +typedef struct VCVisualViewResource_CallbackData VCVisualViewResource_CallbackData; +typedef struct VCPseudoGravity_CallbackData VCPseudoGravity_CallbackData; +typedef struct VCPosition_CallbackData VCPosition_CallbackData; +typedef struct VCTracker_CallbackData VCTracker_CallbackData; +typedef struct VCSync_CallbackData VCSync_CallbackData; +typedef struct VCCollideMonitor_CallbackData VCCollideMonitor_CallbackData; +typedef struct VCTrackerMonitor_CallbackData VCTrackerMonitor_CallbackData; +typedef struct VCVisualMonitor_CallbackData VCVisualMonitor_CallbackData; +typedef struct VCTexture_CallbackData VCTexture_CallbackData; +typedef struct VCRamp_CallbackData VCRamp_CallbackData; +typedef struct VCInput_CallbackData VCInput_CallbackData; +typedef struct VCInput_UpdateCallbackData VCInput_UpdateCallbackData; +typedef struct VCAttribute_CallbackData VCAttribute_CallbackData; +typedef struct VCEntityRelocate_CallbackData VCEntityRelocate_CallbackData; +typedef struct VCEntityInvalid_CallbackData VCEntityInvalid_CallbackData; +typedef struct VCAttributeRelocate_CallbackData VCAttributeRelocate_CallbackData; +typedef struct VCEntityAttribute_CallbackData VCAttributeInvalid_CallbackData; +typedef struct VCEntityAttribute_CallbackData VCEntityAttribute_CallbackData; +typedef struct VCEntityDrop_CallbackData VCEntityDrop_CallbackData; +typedef struct VCTimer_CallbackData VCTimer_CallbackData; +typedef struct VCExit_CallbackData VCExit_CallbackData; +typedef struct VCGroup_CallbackData VCGroup_CallbackData; +typedef float32 VCSpecular[4]; + +/* + * function types for general callback routines + */ + +typedef void (*VC_SignalFunc) (VCSignal_CallbackData *callbackData, void *data); +typedef void (*VC_ExitFunc) (VCExit_CallbackData *callbackData, void *data); +typedef void (*VC_GroupFunc) (VCGroup_CallbackData *callbackData, void *data); +typedef void (*VC_StreamFunc) (VCStream_CallbackData *streamData, void *data); +typedef void (*VC_CallbackFunc) (VLInstanceEvent *instanceData, void *data); + +/* + * function types for body routines + */ + +typedef void (*VC_VersionFunc) (FILE *fp); +typedef void (*VCBody_CreateFunc) (VCBodyCreate_CallbackData *bodyData, void *data); +typedef void (*VCBody_CreateBodyPartFunc) (VCBodyPartCreate_CallbackData *callbackData, void *data); +typedef void (*VCBody_AttributeFunc) (VCBodyAttribute_CallbackData *callbackData, void *data); +typedef void (*VCBody_InputFunc) (VCBodyInput_CallbackData *callbackData, void *data); +typedef void (*VCBody_CollisionFunc) (VCBodyCollision_CallbackData *callbackData, void *data); +typedef void (*VCEntity_DropFunc) (VCEntityDrop_CallbackData *callbackData, void *data); + +/* + * function types for Resource routines + */ + +typedef VCAttribute *(*VCResource_AllocateFunc) (VCResourceAllocate_CallbackData *callbackData, void *data); + +/* + * function types for vchierarchy routines + */ + +typedef void (*VCEntity_TraverseFunc) (VCEntity * entity, void *data); +typedef void (*VCEntity_Func) (VCEntity *entity, int32 index, void *data); +typedef void (*VCAttribute_Func) (VCAttribute_CallbackData *attributeData, void *data); +typedef void (*VCAttribute_RelocateFunc) (VCAttributeRelocate_CallbackData *entityData, void *data); +typedef void (*VCEntity_RelocateFunc) (VCEntityRelocate_CallbackData *entityData, void *data); +typedef void (*VCEntity_InvalidFunc) (VCEntityInvalid_CallbackData *entityData, void *data); +typedef void (*VCEntity_AttributeFunc) (VCEntityAttribute_CallbackData *attributeData, void *data); +typedef void (*VCAttribute_InvalidFunc) (VCAttributeInvalid_CallbackData *atttributeData, void *data); +typedef void (*VCCollision_Func) (VCCollision_CallbackData *callbackData, void *data); +typedef void (*VCIntersection_Func) (VCIntersection_CallbackData *callbackData, void *data); +typedef void (*VCMaterial_Func) (VCMaterial_CallbackData *attributeData, void *data); +typedef void (*VCRadiator_Func) (VCRadiator_CallbackData *attributeData, void *data); +typedef void (*VCXWindowId_Func) (VCXWindowId_CallbackData *attributeData, void *data); +typedef void (*VCVisualViewResource_Func) (VCVisualViewResource_CallbackData *attributeData, void *data); +typedef void (*VCPseudoGravity_Func) (VCPseudoGravity_CallbackData *attributeData, void *data); +typedef void (*VCPosition_Func) (VCPosition_CallbackData *attributeData, void *data); +typedef void (*VCTracker_Func) (VCTracker_CallbackData *attributeData, void *data); +typedef void (*VCSync_Func) (VCSync_CallbackData *attributeData, void *data); +typedef void (*VCCollideMonitor_Func) (VCCollideMonitor_CallbackData *attributeData, void *data); +typedef void (*VCTrackerMonitor_Func) (VCTrackerMonitor_CallbackData *attributeData, void *data); +typedef void (*VCVisualMonitor_Func) (VCVisualMonitor_CallbackData *attributeData, void *data); +typedef void (*VCInput_Func) (VCInput_CallbackData *attributeData, void *data); +typedef void (*VCInput_UpdateFunc) (VCInput_UpdateCallbackData *attributeData, void *data); +typedef void (*VCTexture_Func) (VCTexture_CallbackData *callbackData, void *data); +typedef void (*VCRamp_Func) (VCRamp_CallbackData *callbakData, void *data); +typedef void (*VCTimer_Func) (VCTimer_CallbackData *callbackData, void *data); + +typedef int (VCCallback_QueryFunc) (void *callbackQueryData, void *systemData, void *callbackData); + + + +#endif + + + diff --git a/MUNGA_L4/libDPL/dvs/VCVBOSE.H b/MUNGA_L4/libDPL/dvs/VCVBOSE.H new file mode 100644 index 0000000..b4b5cdd --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VCVBOSE.H @@ -0,0 +1,100 @@ +/*************************************************************************** + * <110793.1226> + * PROJECT: dVS + * SUBSYSTEM: + * MODULE: + * + *************************************************************************** + * + * File: $RCSfile: vcvbose.h,v $ + * Revision: $Revision: 1.1 $ + * Date: $Date: 95/05/18 10:24:20 $ + * Author: $Author: john $ + * RCS Ident: $Id: vcvbose.h,v 1.1 1995/03/10 14:52:46 john Exp $ + * Creator: Jon Green. + * + * FUNCTION: + * + * + * $Log: vcvbose.h,v $ + * Revision 1.1 95/05/18 10:24:20 10:24:20 john (John Harvey) + * Initial revision + * + * Revision 1.1 1995/03/10 14:52:46 john + * Initial revision + * + * Revision 0.6 94/10/05 12:51:43 12:51:43 john (John Harvey) + * Save JH on holiday. - Jon. + * + * Revision 0.5 94/03/30 15:17:49 15:17:49 mark (Mark Greening) + * New VCActorInit and error routines + * + * Revision 0.4 1993/09/24 11:24:53 jon + * Release 2.0.4 + * + * Revision 1.1 93/07/28 14:12:08 jon + * Initial revision + * + * + ************************************************************************** + * * + * Copyright (c) 1992 Division Ltd. * + * * + * All Rights Reserved. * + * * + * This Document may not, in whole or in part, be copied, photocopied, * + * reproduced, translated, or reduced to any electronic medium or * + * machine readable form without prior written consent from Division * + * Ltd. * + * * + *************************************************************************/ + +/*--- Include Definitions */ + +#ifndef _VCVBOSE_H +#define _VCVBOSE_H 1 + +/*--- Include Files */ + +/*--- External References */ + +extern void __vcVerboseStart(int level); +extern void __vcDebugStart(int level, char *file, int line); +extern void __vcVerboseMessage(char *format, ...); +extern uint32 __vcverbose_level; +extern uint32 __vcdebug_level; + +/*--- Local Macro Definitions */ + +#define VC_Verbose(x,y) do { \ + if (__vcverbose_level & (x)) \ + { \ + __vcVerboseStart(x); \ + __vcVerboseMessage y; \ + } \ + } while (0) + +#ifdef NVCDEBUG +#undef VC_Debug +#define VC_Debug(x,y) ((void)0) + +#else +#define VC_Debug(x,y) do { \ + if (__vcdebug_level & (x)) \ + { \ + __vcDebugStart(x, __FILE__, __LINE__); \ + __vcVerboseMessage y; \ + } \ + } while (0) +#endif + +#define VCVerbose_SetLevel(x) (__vcverbose_level = (x)) +#define VCVerbose_GetLevel __vcverbose_level +#define VCDebug_SetLevel(x) (__vcdebug_level = (x)) +#define VCDebug_GetLevel __vcdebug_level + +/*--- Local Type Definitions */ + +/*--- Local Variable Declarations */ + +#endif /* _VCVBOSE_H */ diff --git a/MUNGA_L4/libDPL/dvs/VL.H b/MUNGA_L4/libDPL/dvs/VL.H new file mode 100644 index 0000000..f679850 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VL.H @@ -0,0 +1,476 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: vl + * MODULE: vl.h + * + * File: $RCSfile: vl.h,v $ + * Revision: $Revision: 1.23 $ + * Date: $Date: 1995/05/18 09:43:47 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: vl.h,v 1.23 1995/05/18 09:43:47 jeff beta $ + * + * FUNCTION: + * + * This file contains all the external definitions needed to use + * the vl library. + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _VL_H +#define _VL_H + +#include + +#ifndef _VLTYPES_H +#include +#endif + +/* + * type for return of event info + */ +typedef union VLEventData VLEventData; +typedef struct VLInstanceEvent VLInstanceEvent; + +typedef struct VLSignalEvent VLSignalEvent; +typedef struct VLStreamEvent VLStreamEvent; +typedef struct VLInstInterestEvent VLInstInterestEvent; +typedef struct VLElemInterestEvent VLElemInterestEvent; +typedef struct VLElementConfirmEvent VLElementConfirmEvent; +typedef struct VLElemCreateEvent VLElemCreateEvent; +typedef struct VLTimeServiceEvent VLTimeServiceEvent; +typedef struct VLPeerEvent VLPeerEvent; +typedef struct VLBadEvent VLBadEvent; + + +struct VLInstanceEvent{ + ElementHandle handle; + InstanceNo ino; + int32 repCount; +}; + +struct VLSignalEvent{ + uint32 signal; +}; + +struct VLStreamEvent { + void *buf; + VLStreamId id; + int32 type; +}; + +struct VLInstInterestEvent{ + InstanceNo ino; + uint32 type; + ActorId actor; + EventQ queue; +}; + +struct VLElemInterestEvent{ + ElementHandle handle; + uint32 type; + ActorId actor; + EventQ queue; +}; + +struct VLElementConfirmEvent{ + ElementHandle reference; + ElementHandle confirmed; +}; + +struct VLElemCreateEvent{ + ElementHandle handle; + uint32 descSize; +}; + +struct VLTimeServiceEvent{ + VLTime time; + ActorId who; +}; + +struct VLPeerEvent{ + ActorId peer; +}; + +struct VLBadEvent { + VLStatus stat; +}; + +union VLEventData { + VLInstanceEvent instanceEvent; + VLSignalEvent signalEvent; + VLStreamEvent streamEvent; + VLInstInterestEvent instInterestEvent; + VLElemInterestEvent elemInterestEvent; + VLElementConfirmEvent elementConfirmEvent; + VLElemCreateEvent elemCreateEvent; + VLTimeServiceEvent timeServiceEvent; + VLPeerEvent peerEvent; + VLBadEvent badEvent; +}; + +/* + * fundemenatal element handles, always around. + */ +extern const ElementHandle el_char8; +extern const ElementHandle el_int8; +extern const ElementHandle el_uint8; +extern const ElementHandle el_int16; +extern const ElementHandle el_uint16; +extern const ElementHandle el_int32; +extern const ElementHandle el_uint32; +extern const ElementHandle el_float32; +extern const ElementHandle el_float64; + +/* + * get the version + */ +extern void vlVersion(FILE *fp); + +/* + * Connecting to a database, finding out name etc. + */ +extern ActorId VLAttachActor(const char8 *agentName); +extern VLStatus VLDetachActor(VLExitMode); +extern uint32 VLDomainName(char8 *name, uint32 maxNameLen); +extern AgentId VLDomainId(void); + + +/* + * Creating elements + */ +extern VLStatus VLCreateElement(int32 (*efunc)(void)); + + +/* how epp generated code defines elements.. + * For error free code.. + * + * THIS ROUTINE IS FOR USE BY EPP-GENERATED CODE + * ONLY! + * That is why its name is prefixed with 'vl' not 'VL'. + */ +extern ElementHandle vlCreateElement(char8 *name, + int32 size, + int32 alignment, + int32 atomic, + int32 dynamic, + int32 subelems, ...); + +/* + * extract an element description into a buffer + * that could be transmited to a remote data base and + * used to recreate the element there. Used by agents + * to exchange element information. + */ +extern VLStatus VLExtractElemDesc(ElementHandle h, + ElementDesc *d); + + +/* + * take an element description, probably transmitted from a remote + * machine, and create an element from it. Such an element cannot be + * properly used on the local database, without a 'vlCreateElement()' + * being performed, as offset and alignment information (which is machine + * dependant) is not available here, but the form will be created here + * with a valid element handle. This will speed up future + * vlCreateElement(), or ' VLCreateElemFromDesc()' calls at this database. + * + * THIS CREATE IS ASYNCHRONOUS. + * + * If the element creation needs to be further negotiated with a peer + * database, then a potential for deadlock in the database coms exists. + * To avoid this, VLCreateElemFromDesc() always returns imediately, with + * no status. All return info is put onto the event queue for async handling. + */ +extern VLStatus VLPeerElement(ElementDesc *d, EventQ q); + +/* + * Setting the database peer. + */ +extern VLStatus VLSetPeerActor(EventQ q); + +/* + * Arrange to get an event when the peer attatches to the database, + * error status if there will be no peer. + */ +extern VLStatus VLGetPeerActor(void); + +/* + * check to see if tha database is a master or not. + */ +extern int VLIsMasterP(void); + +/* + * Define the data format (alignment, endianess etc) of a remote + * database to this database. Return value is used to identify + * the source type of remote machines for updates with reformating. + * returns negative if there is any form of error. + */ +extern VLFormat VLDefineFormat(dpTypeSpec *s); + + +/* + * The following calls are needed to find out when a time keeper has + * connected, and to set up the timekeeper, used on those systems that + * use a timekeeper. on systems that have a local timer, these calls will + * always fail. + */ +extern VLStatus VLGetTimeKeeper(void); +extern VLStatus VLSetTimeKeeper(EventQ q); + +/* + * used by a timekeeper to wakeup actors waiting on alarms, on systems + * without a timekeeper this funcion will still work. returns + * VL_ERR_BAD_AGENT if the actor id is not recognised. + */ +extern VLStatus VLWakeUpActor(ActorId actor); + +/* + * change the state of an element to confirmed. This may involve a change + * of element handle , from 'oldh' to 'newh'. To delete an element awaiting + * confirmation set the 'newh' element handle to 0. Will return + * VL_ERR_BAD_ELEM if 'oldh' is not waiting for confirmation or is not an + * element. else returns VL_ERR_OK. + */ +extern VLStatus VLConfirmElement(ElementHandle oldh, ElementHandle newh); + + +/* + * requesting info about other actors interest at this database. + */ +#define VLRegisterElementInterest() VLQRegisterElementInterest(0) +#define VLDeRegisterElementInterest() VLQDeRegisterElementInterest(0) + +extern VLStatus (VLRegisterElementInterest)(void); +extern VLStatus (VLDeRegisterElementInterest)(void); +extern VLStatus VLQRegisterElementInterest(EventQ q); +extern VLStatus VLQDeRegisterElementInterest(EventQ q); +extern VLStatus VLRequestElementInterest(EventQ q, ElementHandle h); + +#define VLRegisterInstanceInterest(x) VLQRegisterInstanceInterest(0,x) +#define VLDeRegisterInstanceInterest(x) VLQDeRegisterInstanceInterest(0,x) + +extern VLStatus (VLRegisterInstanceInterest)(AgentId id); +extern VLStatus (VLDeRegisterInstanceInterest)(AgentId id); +extern VLStatus VLQRegisterInstanceInterest(EventQ q, AgentId); +extern VLStatus VLQDeRegisterInstanceInterest(EventQ q, AgentId); + + +/* + * Low-level routines to create/delete/update/extract + * instances from the database. + * + * THESE ROUTINES SHOULD BE CALLED FROM EPP-GENERATED CODE ONLY + * + * Epp will write type-safe access routines for you, + * + * USE THEM. + */ +#define vlCreateInstance(e,i,d,t,m) vlQCreateDynamicFormattedInstance( 0,(e),(i),(d),(t),(m),-1, -1 ) +#define vlCreateDynamicInstance(e,i,d,t,m,c) vlQCreateDynamicFormattedInstance( 0,(e),(i),(d),(t),(m),-1, (c)) +#define vlQCreateInstance(q,e,i,d,t,m) vlQCreateDynamicFormattedInstance((q),(e),(i),(d),(t),(m),-1, -1 ) +#define vlQCreateDynamicInstance(q,e,i,d,t,m,c) vlQCreateDynamicFormattedInstance((q),(e),(i),(d),(t),(m),-1, (c)) + +extern InstanceNo (vlCreateInstance)(ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); +extern InstanceNo (vlQCreateInstance)(EventQ qid, + ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); + +extern InstanceNo (vlCreateDynamicInstance)(ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern InstanceNo (vlQCreateDynamicInstance)(EventQ qid, + ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern InstanceNo vlQCreateDynamicFormattedInstance(EventQ qid, + ElementHandle elem, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + VLFormat format, + int32 count); + +#define vlDeleteInstance(i,m) vlQDeleteInstance(0,(i),(m)) + +extern VLStatus (vlDeleteInstance)(InstanceNo ino, + VLUpdateMode mode); +extern VLStatus vlQDeleteInstance(EventQ qid, + InstanceNo ino, + VLUpdateMode mode); + +extern VLStatus vlUpdateInstance(InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); + +extern VLStatus vlQUpdateInstance(EventQ qid, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode); + +extern VLStatus vlUpdateDynamicInstance(InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern VLStatus vlQUpdateDynamicInstance(EventQ qid, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + +extern VLStatus vlQUpdateInstanceFormat(EventQ qid, + VLFormat format, + InstanceNo ino, + void *data, + VLTime *vtime, + VLUpdateMode mode, + int32 count); + + +extern VLStatus vlExtractInstance(InstanceNo ino, + void *data, + VLTime *vtime); + + + + +/* + * Miscellaneous instance routines + */ +extern ElementHandle VLInstanceType(InstanceNo ino); +extern uint32 VLInstanceSize(InstanceNo ino, uint32 *icount); +extern int32 VLInstanceOwnership(InstanceNo ino); +extern void *VLInstanceAddress(InstanceNo ino, + VLStatus *status, + VLTime *time, + VLUpdateMode mode, + uint32 count); +extern VLStatus VLInstanceUpdate(InstanceNo ino, + VLTime *vtime, + VLUpdateMode mode); + + +/* + * (de)registering of interest in elements and instances. + */ +#define VLRegisterElement(e, t) VLQRegisterElement(0,(e),(t)) +#define VLDeRegisterElement(e, t) VLQDeRegisterElement(0,(e),(t)) +#define VLRegisterInstance(i, t) VLQRegisterInstance(0,(i),(t)) +#define VLDeRegisterInstance(i, t) VLQDeRegisterInstance(0,(i),(t)) + +extern VLStatus (VLRegisterElement)(ElementHandle e, uint32 type); +extern VLStatus (VLDeRegisterElement)(ElementHandle e, uint32 type); +extern VLStatus (VLRegisterInstance)(InstanceNo ino, uint32 type); +extern VLStatus (VLDeRegisterInstance)(InstanceNo ino, uint32 type); + +extern VLStatus VLQRegisterElement(EventQ q, + ElementHandle e, + uint32 type); +extern VLStatus VLQDeRegisterElement(EventQ q, + ElementHandle e, + uint32 type); +extern VLStatus VLQRegisterInstance(EventQ q, + InstanceNo ino, + uint32 type); +extern VLStatus VLQDeRegisterInstance(EventQ q, + InstanceNo ino, + uint32 type); + + +/* + * Events, and their queues. + */ +#define VLAwaitEvent(e,w) VLQAwaitEvent((e),NULL,(w)) + +extern VLAction (VLAwaitEvent)(VLEventData *ev, + VLWaitMode wait); +extern VLAction VLQAwaitEvent(VLEventData *ev, + EventQ *q, + VLWaitMode wait); +extern VLAction VLSnoopEvent(EventQ qid,VLEventData *ev); + +extern EventQ VLNewEventQueue(void); +extern VLStatus VLDeleteEventQueue(EventQ q); +extern VLStatus VLBlockEventQueue(EventQ q); +extern VLStatus VLClearEventQueue(EventQ q); + + +/* + * signals + */ +extern void VLSigSet(int32 sig); +extern void VLSigUnset(int32 sig); + +/* + * Stream operations + */ +extern VLStreamId VLStreamOpen(char8 *name, + int32 buflen, + void *buffer, + char8 *format ); +extern VLStatus VLStreamWrite(VLStreamId streamId, + int32 type, + uint32 length, + void *data ); +extern VLStatus VLStreamClose(VLStreamId streamId ); + +/* + * Locking and groups + */ +extern VLStatus VLLock(void); +extern VLStatus VLUnlock(void); +extern int32 VLLockStatus(void); + +extern int32 VLGroup(void); +extern int32 VLUnGroup(void); +extern int32 VLGroupStatus(void); + +/* + * Virtual time and timers + */ +extern VLStatus VLVirtualTime(VLTime *t); +extern VLStatus VLSetVirtualTimeSkew(VLTime *t); +extern VLStatus VLGetVirtualTimeSkew(VLTime *t); + +#define VLAddVtimes(r,a,b) dpAddVtimes(r,a,b) +#define VLSubVtimes(r,a,b) dpSubVtimes(r,a,b) + +extern void (VLAddVtimes)(VLTime *r, VLTime *a, VLTime *b); +extern void (VLSubVtimes)(VLTime *r, VLTime *a, VLTime *b); + +extern VLStatus VLTimer(VLTime *period, VLTimerMode mode); + +/* + * converting status numbers, element handles to meaningful messages + */ +extern const char *VLErrorString(VLStatus s); +extern const char *VLElementName(ElementHandle h); + +#endif /* _VL_H */ diff --git a/MUNGA_L4/libDPL/dvs/VLTYPES.H b/MUNGA_L4/libDPL/dvs/VLTYPES.H new file mode 100644 index 0000000..e4e6f7a --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/VLTYPES.H @@ -0,0 +1,161 @@ +/* + * PROJECT: DVS + * SUBSYSTEM: vl + * MODULE: vltypes.h + * + * File: $RCSfile: vltypes.h,v $ + * Revision: $Revision: 1.8 $ + * Date: $Date: 1995/05/18 09:43:47 $ + * Author: $Author: jeff $ + * RCS Ident: $Id: vltypes.h,v 1.8 1995/05/18 09:43:47 jeff beta $ + * + * FUNCTION: + * This file contain the definitions of low-level types that are used + * throughout the vl system. These are all integers under a different + * guise. + * + * Copyright (c) 1994 Division Ltd. + * + * All Rights Reserved. + * + * This Document may not, in whole or in part, be copied, + * photocopied, reproduced, translated, or reduced to any + * electronic medium or machine readable form without prior + * written consent from Division Ltd. + */ +#ifndef _VLTYPES_H +#define _VLTYPES_H + +#include +#include + + +/* + * The basic id type. all the specific id types are typedefed from this. + */ +typedef uint32 IdType; + +typedef IdType InstanceNo; +typedef IdType ElementHandle; +typedef int32 EventQ; +typedef IdType AgentId; +typedef uint16 ActorId; +/*the max number of actors is */ +#define VL_MAX_ACTORS 65534 + +/* ... a bad actorid is indicated by */ +#define VL_BAD_ACTOR ((ActorId) 65535) + +/* ... 'all actors' is indicated by */ +#define VL_ALL_ACTORS ((ActorId) 65535) + + + +typedef void (* VLSigFunc)(int32 sig); + +typedef IdType VLStreamId; +#ifndef VLSTREAM_MAX +#define VLSTREAM_MAX 21 +#endif + +typedef dpVtime VLTime; + +/* + * typedef for passing element descriptions around. + */ +typedef uint32 ElementDesc; + + +/* + * typedefs containing all of the magic flags that might be passed into + * vl, or returned as a status. + */ +typedef enum { + VL_NO_SYNC = 0x00000001, + VL_LOCAL = 0x00000002, + VL_GLOBAL = 0x00000004, + VL_TIME = 0x00000008 +} VLUpdateMode; + +typedef enum { + VL_NOISY = 0x00000000, + VL_QUIET = 0x00000100, + VL_AUDIO_MASK = 0x00000100 +} VLAudibility; + +#define VL_ACTION_NONE 0x00000000 +#define VL_ACTION_CREATE 0x00001000 +#define VL_ACTION_DELETE 0x00002000 +#define VL_ACTION_UPDATE 0x00004000 + +#define VL_ACTION_SIGNAL 0x00010000 +#define VL_ACTION_STREAM 0x00020000 + +#define VL_ACTION_IREG 0x00030000 +#define VL_ACTION_IDEREG 0x00040000 + +#define VL_ACTION_EREG 0x00050000 +#define VL_ACTION_EDEREG 0x00060000 + +#define VL_ACTION_ECREATE 0x00070000 +#define VL_ACTION_EDELETE 0x00080000 +#define VL_ACTION_ECONFIRM 0x00090000 + +#define VL_ACTION_GROUP 0x000a0000 +#define VL_ACTION_UNGROUP 0x000b0000 + +#define VL_ACTION_TIMEOUT 0x000c0000 +#define VL_ACTION_ALARM_REQ 0x000d0000 +#define VL_ACTION_TICK_REQ 0x000e0000 + +#define VL_ACTION_PEER 0x000f0000 +#define VL_ACTION_EXIT 0x00100000 +#define VL_ACTION_BAD 0xffff0000 +typedef uint32 VLAction; + +/* + * index used to identify different format rules + * (endinaess alignment etc) + */ +typedef int32 VLFormat; + +/* update vlerr.c if these are changed */ +typedef enum { + VL_ERR_OK, + VL_ERR_BAD_AGENT, + VL_ERR_BAD_DOMAIN, + VL_ERR_BAD_ELEM, + VL_ERR_BAD_INST, + VL_ERR_BAD_STREAM, + + VL_ERR_BAD_QUEUE, + VL_ERR_BAD_ACTION, + VL_ERR_NOT_SLAVE, + VL_ERR_ALREADY_PEERED, + VL_ERR_TIME, + VL_ERR_FORMAT, + VL_ERR_SEMAPHORE, + VL_ERR_NO_MEM, + VL_ERR_LAST +}VLStatus; + +typedef enum { + VL_DETACH_ACTOR, + VL_DETACH_AGENT, + VL_DETACH_LOCAL, + VL_DETACH_GLOBAL +}VLExitMode; + +typedef enum { + VL_TIME_ALARM, + VL_TIME_TICK, + VL_TIME_OFF +} VLTimerMode; + +typedef enum { + VL_POLL_EVENT, + VL_WAIT_EVENT +} VLWaitMode; + + +#endif /*_VLTYPES_H */ diff --git a/MUNGA_L4/libDPL/dvs/_VCSTRUC.H b/MUNGA_L4/libDPL/dvs/_VCSTRUC.H new file mode 100644 index 0000000..2eb0745 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/_VCSTRUC.H @@ -0,0 +1,569 @@ +#ifndef __VCSTRUCT_H +#define __VSTRUCT_H +struct VCAttribute { + ElementHandle type; /* The element handle */ + InstanceNo ino; + VCEntity *first; + int index; + uint32 mode; + uint32 cacheMode; + uint32 registerMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCCollision +{ + InstanceNo ino; + uint32 status; + uint32 instanceCount; + uint32 collReportCount; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCCollisionReportData *collReportData; + uint32 collReportDataSize; + uint32 collReportDataCount; + uint32 numCollisionsReported; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCIntersection +{ + InstanceNo ino; + uint32 status; + uint32 instanceCount; + uint32 intersectReportCount; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCIntersectionReportData *intersectReportData; + uint32 intersectReportDataSize; + uint32 intersectReportDataCount; + uint32 numIntersectionsReported; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCPosition +{ + InstanceNo ino; + VCEntity *entity; + uint32 status; + uint32 cacheMode; + void *instanceData; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCXWindowId +{ + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCVisualViewResource +{ + InstanceNo ino; + VCAttribute *attribute; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + + +struct VCPseudoGravity +{ + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCMaterial +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCRadiator +{ + + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + + + +struct VCTexture +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCRamp +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCInput +{ + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + uint32 numWraps; + uint32 head; +}; + +struct VCTracker +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCSync +{ + VCSync *next; + InstanceNo ino; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +struct VCMonitor +{ + InstanceNo ino; + char *name; + uint32 status; + uint32 cacheMode; + void *instanceData; + uint32 instanceDataSize; + uint32 instanceDataCount; + VCUserDataList *userDataList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *deleteFunctionList; + VCCallbackFunctions *updateFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; +}; + +typedef struct +{ + VCAttribute *attribute; + VCEntity *next; + int32 index; + int32 flags; + VCUserDataList *userDataList; +} VCAttributeData; + +typedef struct VCEntityData +{ + dmMatrix apos; + VCEntity *newParent; + uint32 traverseMode; + VCCallbackFunctions *createFuncList; + VCCallbackFunctions *updateFuncList; + VCCallbackFunctions *deleteFuncList; + VCUserDataList *userData; + void *vcPosCallbackInfo; + void *objPosCallbackInfo; + VCCallbackFunctions *entityRelocateCallbackList; + uint32 entityRelocateMode; +} VCEntityData; + +struct VCEntity { + VCEntity *parent; /* Local parental ptr */ + VCEntity *child; /* Local child ptr */ + VCEntity *sibling; /* Local sibling ptr */ + _VCObject *object; /* Hierarchy VL data */ + InstanceNo ino; /* VCObject Instance No */ + VCEntityData *systemData; + int numAttributes; + VCAttributeData *attributes;/* Hierarchy data objects */ +}; + + +typedef struct +{ + VCColour backgroundColour; + int backgroundColourSet; + float32 nearClip; + int nearClipSet; + float32 farClip; + int farClipSet; + VCColour fogColour; + uint32 fogMode; + int fogColourSet; + float32 nearFog; + int nearFogSet; + float32 farFog; + int farFogSet; + + void *callbackHandle; + +}_VCBodyVisResInfo; + +typedef struct +{ + char *resourceFile; + float32 volume; + int volumeSet; + float32 spreadingRollOff; + int spreadingRollOffSet; + float32 atmosphericAbsorption; + int atmosphericAbsorptionSet; + void *callbackHandle; +}_VCBodyAudioResInfo; + + +struct VCBody +{ + VCBody *next; + _VCBody *body; + uint32 bodySize; + uint32 bodyCount; + VCEntity *rootEntity; + VCEntity *bodyPosEntity; + InstanceNo ino; + VCCallbackFunctions *bodyPartCreateList; + _VCBodyPartList *bodyPartList; + VCCallbackFunctions *attributeFuncList; + VCCallbackFunctions *inputFuncList; + VCCallbackFunctions *collisionFuncList; + _VCBodyVisResInfo visualInfo; + _VCBodyAudioResInfo audioInfo; +}; + + +struct _VCBody_InputFuncData +{ + uint32 minKeyCode; + uint32 maxKeyCode; + char *limbName; +}; + +struct _VCBody_CollideFuncData +{ + char *limbName; +}; + +struct _VCInput_FuncData +{ + uint32 minKeyCode; + uint32 maxKeyCode; +}; + +struct VCUserDataList +{ + VCUserDataList *next; + uint32 vcId; + void *data; +}; + + +struct VCCollisionReport_Traverse +{ + uint32 instanceCount; + VCCollision *collision; + uint32 nextOffset; +}; + +struct VCIntersectionReport_Traverse +{ + uint32 instanceCount; + VCIntersection *intersection; + uint32 nextOffset; +}; + + + +struct VCEntity_Traverse +{ + VCEntity *currentObject; /* Current hierarchy pos */ + VCEntity *startObject; /* Start hierarchy pos */ +}; + +struct VCAttribute_EntityTraverse +{ + VCEntity *entity; + int32 index; +}; + +struct VCEntity_AttributeTraverse +{ + VCEntity *entity; + int32 nextIndex; + ElementHandle element; +}; + +struct VCBody_Traverse +{ + VCBody *body; +}; + +struct VCVisualView_Traverse +{ + duHashIterator hashIter; + VCAttribute *visResource; +}; + + +struct VCBody_AttributeTraverse +{ + VCBody *body; + char *limbName; /* Request limb */ + ElementHandle element; + _VCBodyPartList *currentBodyPart; + int currentAttribute; + VCBody *currentBody; + VCBody_Traverse bodyTraverseInfo; +}; + + + +struct VCCallbackFunctions +{ + VCCallbackFunctions *next; + VC_CallbackFunc function; + void *data; + void *systemData; +}; + +typedef union +{ + VCEntity_Traverse entityT; + VCEntity_AttributeTraverse entityAttributeT; + VCAttribute_EntityTraverse attributeEntityT; + VCBody_Traverse bodyT; + VCBody_AttributeTraverse bodyAttributeT; + VCCollisionReport_Traverse collReportT; + VCIntersectionReport_Traverse intersectReportT; + VCVisualView_Traverse viewT; +}VC_Traverse; + +typedef struct +{ + ElementHandle element; + char *limbName; +} _VCAttributeElementData; + +typedef struct +{ + InstanceNo inst; + VCCallbackFunctions *functionList; +} _VCInstCallback; + +typedef struct +{ + VCBody *body; + _VCBodyPartList *bodyPart; +}_VCBodyPartInfo; + + +struct _VCTimer_CallbackInfo +{ + VLTime lastTime; + VLTime time; + VLTimerMode mode; +}; + +struct _VCBodyPartList +{ + _VCBodyPartList *next; + VCAttribute *bodyPartAttr; + VCBody *body; + uint32 inputNeeded; +/* + VCEntity *pickedObject; + VCEntity_DropFunc dropFunc; + void *dropData; + VCAttribute *pickAttr; +*/ +}; + +typedef struct +{ + VCAttribute *bodyPartAttr; + VCBody *body; + VCEntity_DropFunc dropFunc; + void *dropData; + VCPickObjectData pickObject; +}_VCBodyPickInfo; + + + +typedef struct +{ + VCCallbackFunctions *relocateFunctionList; + VCCallbackFunctions *createFunctionList; + VCCallbackFunctions *invalidFunctionList; + VCCallbackFunctions *updateFunctionList; + VCCallbackFunctions *deleteFunctionList; + void *createCallbackHandle; + void *updateCallbackHandle; + void *deleteCallbackHandle; + uint32 relocateMode; +} _VCObjectFunctions; + +typedef struct +{ + _VCObjectFunctions functions; + int explicitInstances; + duHashTab *instTable; + ElementHandle element; + uint32 registered; +} _VCAttributeCallback; + +typedef struct +{ + _VCAttributeCallback *callbackList; + int32 listSize; +} _VCAttributeCallbackList; + +typedef struct +{ + void *relocateCallbackHandle; + void *invalidCallbackHandle; +}_VCEntityRelocateCallbackHandles; + + +typedef struct _VCSyncCallbackInfo +{ + struct _VCSyncCallbackInfo *next; + char *actorName; + char *actorType; + VCSync_Func updateFunc; + VCSync_Func deleteFunc; + void *data; +}_VCSyncCallbackInfo; + + + +#endif diff --git a/MUNGA_L4/libDPL/dvs/_VCTYPES.H b/MUNGA_L4/libDPL/dvs/_VCTYPES.H new file mode 100644 index 0000000..ae8a541 --- /dev/null +++ b/MUNGA_L4/libDPL/dvs/_VCTYPES.H @@ -0,0 +1,10 @@ +#ifndef __VCTYPES_H +#define __VCTYPES_H + +typedef struct _VCTimer_CallbackInfo _VCTimer_CallbackInfo; +typedef struct _VCBodyPartList _VCBodyPartList; +typedef struct _VCBody_InputFuncData _VCBody_InputFuncData; +typedef struct _VCBody_CollideFuncData _VCBody_CollideFuncData; +typedef struct _VCInput_FuncData _VCInput_FuncData; + +#endif diff --git a/MUNGA_L4/openal/EFX-Util.h b/MUNGA_L4/openal/EFX-Util.h new file mode 100644 index 0000000..b4a6b4e --- /dev/null +++ b/MUNGA_L4/openal/EFX-Util.h @@ -0,0 +1,422 @@ +/*******************************************************************\ +* * +* EFX-UTIL.H - EFX Utilities functions and Reverb Presets * +* * +* File revision 1.0 * +* * +\*******************************************************************/ + +#ifndef EAXVECTOR_DEFINED +#define EAXVECTOR_DEFINED +typedef struct _EAXVECTOR { + float x; + float y; + float z; +} EAXVECTOR; +#endif + +#ifndef EAXREVERBPROPERTIES_DEFINED +#define EAXREVERBPROPERTIES_DEFINED +typedef struct _EAXREVERBPROPERTIES +{ + unsigned long ulEnvironment; + float flEnvironmentSize; + float flEnvironmentDiffusion; + long lRoom; + long lRoomHF; + long lRoomLF; + float flDecayTime; + float flDecayHFRatio; + float flDecayLFRatio; + long lReflections; + float flReflectionsDelay; + EAXVECTOR vReflectionsPan; + long lReverb; + float flReverbDelay; + EAXVECTOR vReverbPan; + float flEchoTime; + float flEchoDepth; + float flModulationTime; + float flModulationDepth; + float flAirAbsorptionHF; + float flHFReference; + float flLFReference; + float flRoomRolloffFactor; + unsigned long ulFlags; +} EAXREVERBPROPERTIES, *LPEAXREVERBPROPERTIES; +#endif + +#ifndef EFXEAXREVERBPROPERTIES_DEFINED +#define EFXEAXREVERBPROPERTIES_DEFINED +typedef struct +{ + float flDensity; + float flDiffusion; + float flGain; + float flGainHF; + float flGainLF; + float flDecayTime; + float flDecayHFRatio; + float flDecayLFRatio; + float flReflectionsGain; + float flReflectionsDelay; + float flReflectionsPan[3]; + float flLateReverbGain; + float flLateReverbDelay; + float flLateReverbPan[3]; + float flEchoTime; + float flEchoDepth; + float flModulationTime; + float flModulationDepth; + float flAirAbsorptionGainHF; + float flHFReference; + float flLFReference; + float flRoomRolloffFactor; + int iDecayHFLimit; +} EFXEAXREVERBPROPERTIES, *LPEFXEAXREVERBPROPERTIES; +#endif + +#ifndef EAXOBSTRUCTIONPROPERTIES_DEFINED +#define EAXOBSTRUCTIONPROPERTIES_DEFINED +typedef struct _EAXOBSTRUCTIONPROPERTIES +{ + long lObstruction; + float flObstructionLFRatio; +} EAXOBSTRUCTIONPROPERTIES, *LPEAXOBSTRUCTIONPROPERTIES; +#endif + +#ifndef EAXOCCLUSIONPROPERTIES_DEFINED +#define EAXOCCLUSIONPROPERTIES_DEFINED +typedef struct _EAXOCCLUSIONPROPERTIES +{ + long lOcclusion; + float flOcclusionLFRatio; + float flOcclusionRoomRatio; + float flOcclusionDirectRatio; +} EAXOCCLUSIONPROPERTIES, *LPEAXOCCLUSIONPROPERTIES; +#endif + +#ifndef EAXEXCLUSIONPROPERTIES_DEFINED +#define EAXEXCLUSIONPROPERTIES_DEFINED +typedef struct _EAXEXCLUSIONPROPERTIES +{ + long lExclusion; + float flExclusionLFRatio; +} EAXEXCLUSIONPROPERTIES, *LPEAXEXCLUSIONPROPERTIES; +#endif + +#ifndef EFXLOWPASSFILTER_DEFINED +#define EFXLOWPASSFILTER_DEFINED +typedef struct _EFXLOWPASSFILTER +{ + float flGain; + float flGainHF; +} EFXLOWPASSFILTER, *LPEFXLOWPASSFILTER; +#endif + +void ConvertReverbParameters(EAXREVERBPROPERTIES *pEAXProp, EFXEAXREVERBPROPERTIES *pEFXEAXReverb); +void ConvertObstructionParameters(EAXOBSTRUCTIONPROPERTIES *pObProp, EFXLOWPASSFILTER *pDirectLowPassFilter); +void ConvertExclusionParameters(EAXEXCLUSIONPROPERTIES *pExProp, EFXLOWPASSFILTER *pSendLowPassFilter); +void ConvertOcclusionParameters(EAXOCCLUSIONPROPERTIES *pOcProp, EFXLOWPASSFILTER *pDirectLowPassFilter, EFXLOWPASSFILTER *pSendLowPassFilter); + + +/***********************************************************************************************\ +* +* EAX Reverb Presets in legacy format - use ConvertReverbParameters() to convert to +* EFX EAX Reverb Presets for use with the OpenAL Effects Extension. +* +************************************************************************************************/ + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_GENERIC \ + {0, 7.5f, 1.000f, -1000, -100, 0, 1.49f, 0.83f, 1.00f, -2602, 0.007f, 0.00f,0.00f,0.00f, 200, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_PADDEDCELL \ + {1, 1.4f, 1.000f, -1000, -6000, 0, 0.17f, 0.10f, 1.00f, -1204, 0.001f, 0.00f,0.00f,0.00f, 207, 0.002f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_ROOM \ + {2, 1.9f, 1.000f, -1000, -454, 0, 0.40f, 0.83f, 1.00f, -1646, 0.002f, 0.00f,0.00f,0.00f, 53, 0.003f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_BATHROOM \ + {3, 1.4f, 1.000f, -1000, -1200, 0, 1.49f, 0.54f, 1.00f, -370, 0.007f, 0.00f,0.00f,0.00f, 1030, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_LIVINGROOM \ + {4, 2.5f, 1.000f, -1000, -6000, 0, 0.50f, 0.10f, 1.00f, -1376, 0.003f, 0.00f,0.00f,0.00f, -1104, 0.004f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_STONEROOM \ + {5, 11.6f, 1.000f, -1000, -300, 0, 2.31f, 0.64f, 1.00f, -711, 0.012f, 0.00f,0.00f,0.00f, 83, 0.017f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_AUDITORIUM \ + {6, 21.6f, 1.000f, -1000, -476, 0, 4.32f, 0.59f, 1.00f, -789, 0.020f, 0.00f,0.00f,0.00f, -289, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_CONCERTHALL \ + {7, 19.6f, 1.000f, -1000, -500, 0, 3.92f, 0.70f, 1.00f, -1230, 0.020f, 0.00f,0.00f,0.00f, -02, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_CAVE \ + {8, 14.6f, 1.000f, -1000, 0, 0, 2.91f, 1.30f, 1.00f, -602, 0.015f, 0.00f,0.00f,0.00f, -302, 0.022f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_ARENA \ + {9, 36.2f, 1.000f, -1000, -698, 0, 7.24f, 0.33f, 1.00f, -1166, 0.020f, 0.00f,0.00f,0.00f, 16, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_HANGAR \ + {10, 50.3f, 1.000f, -1000, -1000, 0, 10.05f, 0.23f, 1.00f, -602, 0.020f, 0.00f,0.00f,0.00f, 198, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_CARPETTEDHALLWAY \ + {11, 1.9f, 1.000f, -1000, -4000, 0, 0.30f, 0.10f, 1.00f, -1831, 0.002f, 0.00f,0.00f,0.00f, -1630, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_HALLWAY \ + {12, 1.8f, 1.000f, -1000, -300, 0, 1.49f, 0.59f, 1.00f, -1219, 0.007f, 0.00f,0.00f,0.00f, 441, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_STONECORRIDOR \ + {13, 13.5f, 1.000f, -1000, -237, 0, 2.70f, 0.79f, 1.00f, -1214, 0.013f, 0.00f,0.00f,0.00f, 395, 0.020f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_ALLEY \ + {14, 7.5f, 0.300f, -1000, -270, 0, 1.49f, 0.86f, 1.00f, -1204, 0.007f, 0.00f,0.00f,0.00f, -4, 0.011f, 0.00f,0.00f,0.00f, 0.125f, 0.950f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_FOREST \ + {15, 38.0f, 0.300f, -1000, -3300, 0, 1.49f, 0.54f, 1.00f, -2560, 0.162f, 0.00f,0.00f,0.00f, -229, 0.088f, 0.00f,0.00f,0.00f, 0.125f, 1.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_CITY \ + {16, 7.5f, 0.500f, -1000, -800, 0, 1.49f, 0.67f, 1.00f, -2273, 0.007f, 0.00f,0.00f,0.00f, -1691, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_MOUNTAINS \ + {17, 100.0f, 0.270f, -1000, -2500, 0, 1.49f, 0.21f, 1.00f, -2780, 0.300f, 0.00f,0.00f,0.00f, -1434, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_QUARRY \ + {18, 17.5f, 1.000f, -1000, -1000, 0, 1.49f, 0.83f, 1.00f, -10000, 0.061f, 0.00f,0.00f,0.00f, 500, 0.025f, 0.00f,0.00f,0.00f, 0.125f, 0.700f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_PLAIN \ + {19, 42.5f, 0.210f, -1000, -2000, 0, 1.49f, 0.50f, 1.00f, -2466, 0.179f, 0.00f,0.00f,0.00f, -1926, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_PARKINGLOT \ + {20, 8.3f, 1.000f, -1000, 0, 0, 1.65f, 1.50f, 1.00f, -1363, 0.008f, 0.00f,0.00f,0.00f, -1153, 0.012f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_SEWERPIPE \ + {21, 1.7f, 0.800f, -1000, -1000, 0, 2.81f, 0.14f, 1.00f, 429, 0.014f, 0.00f,0.00f,0.00f, 1023, 0.021f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_UNDERWATER \ + {22, 1.8f, 1.000f, -1000, -4000, 0, 1.49f, 0.10f, 1.00f, -449, 0.007f, 0.00f,0.00f,0.00f, 1700, 0.011f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 1.180f, 0.348f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_DRUGGED \ + {23, 1.9f, 0.500f, -1000, 0, 0, 8.39f, 1.39f, 1.00f, -115, 0.002f, 0.00f,0.00f,0.00f, 985, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_DIZZY \ + {24, 1.8f, 0.600f, -1000, -400, 0, 17.23f, 0.56f, 1.00f, -1713, 0.020f, 0.00f,0.00f,0.00f, -613, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.810f, 0.310f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_PSYCHOTIC \ + {25, 1.0f, 0.500f, -1000, -151, 0, 7.56f, 0.91f, 1.00f, -626, 0.020f, 0.00f,0.00f,0.00f, 774, 0.030f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 4.000f, 1.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } + + +// CASTLE PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_CASTLE_SMALLROOM \ + { 26, 8.3f, 0.890f, -1000, -800, -2000, 1.22f, 0.83f, 0.31f, -100, 0.022f, 0.00f,0.00f,0.00f, 600, 0.011f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } +#define REVERB_PRESET_CASTLE_SHORTPASSAGE \ + { 26, 8.3f, 0.890f, -1000, -1000, -2000, 2.32f, 0.83f, 0.31f, -100, 0.007f, 0.00f,0.00f,0.00f, 200, 0.023f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } +#define REVERB_PRESET_CASTLE_MEDIUMROOM \ + { 26, 8.3f, 0.930f, -1000, -1100, -2000, 2.04f, 0.83f, 0.46f, -400, 0.022f, 0.00f,0.00f,0.00f, 400, 0.011f, 0.00f,0.00f,0.00f, 0.155f, 0.030f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } +#define REVERB_PRESET_CASTLE_LONGPASSAGE \ + { 26, 8.3f, 0.890f, -1000, -800, -2000, 3.42f, 0.83f, 0.31f, -100, 0.007f, 0.00f,0.00f,0.00f, 300, 0.023f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } +#define REVERB_PRESET_CASTLE_LARGEROOM \ + { 26, 8.3f, 0.820f, -1000, -1100, -1800, 2.53f, 0.83f, 0.50f, -700, 0.034f, 0.00f,0.00f,0.00f, 200, 0.016f, 0.00f,0.00f,0.00f, 0.185f, 0.070f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } +#define REVERB_PRESET_CASTLE_HALL \ + { 26, 8.3f, 0.810f, -1000, -1100, -1500, 3.14f, 0.79f, 0.62f, -1500, 0.056f, 0.00f,0.00f,0.00f, 100, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } +#define REVERB_PRESET_CASTLE_CUPBOARD \ + { 26, 8.3f, 0.890f, -1000, -1100, -2000, 0.67f, 0.87f, 0.31f, 300, 0.010f, 0.00f,0.00f,0.00f, 1100, 0.007f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } +#define REVERB_PRESET_CASTLE_COURTYARD \ + { 26, 8.3f, 0.420f, -1000, -700, -1400, 2.13f, 0.61f, 0.23f, -1300, 0.160f, 0.00f,0.00f,0.00f, -300, 0.036f, 0.00f,0.00f,0.00f, 0.250f, 0.370f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_CASTLE_ALCOVE \ + { 26, 8.3f, 0.890f, -1000, -600, -2000, 1.64f, 0.87f, 0.31f, 00, 0.007f, 0.00f,0.00f,0.00f, 300, 0.034f, 0.00f,0.00f,0.00f, 0.138f, 0.080f, 0.250f, 0.000f, -5.0f, 5168.6f, 139.5f, 0.00f, 0x20 } + + +// FACTORY PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_FACTORY_ALCOVE \ + { 26, 1.8f, 0.590f, -1200, -200, -600, 3.14f, 0.65f, 1.31f, 300, 0.010f, 0.00f,0.00f,0.00f, 000, 0.038f, 0.00f,0.00f,0.00f, 0.114f, 0.100f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_SHORTPASSAGE \ + { 26, 1.8f, 0.640f, -1200, -200, -600, 2.53f, 0.65f, 1.31f, 0, 0.010f, 0.00f,0.00f,0.00f, 200, 0.038f, 0.00f,0.00f,0.00f, 0.135f, 0.230f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_MEDIUMROOM \ + { 26, 1.9f, 0.820f, -1200, -200, -600, 2.76f, 0.65f, 1.31f, -1100, 0.022f, 0.00f,0.00f,0.00f, 300, 0.023f, 0.00f,0.00f,0.00f, 0.174f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_LONGPASSAGE \ + { 26, 1.8f, 0.640f, -1200, -200, -600, 4.06f, 0.65f, 1.31f, 0, 0.020f, 0.00f,0.00f,0.00f, 200, 0.037f, 0.00f,0.00f,0.00f, 0.135f, 0.230f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_LARGEROOM \ + { 26, 1.9f, 0.750f, -1200, -300, -400, 4.24f, 0.51f, 1.31f, -1500, 0.039f, 0.00f,0.00f,0.00f, 100, 0.023f, 0.00f,0.00f,0.00f, 0.231f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_HALL \ + { 26, 1.9f, 0.750f, -1000, -300, -400, 7.43f, 0.51f, 1.31f, -2400, 0.073f, 0.00f,0.00f,0.00f, -100, 0.027f, 0.00f,0.00f,0.00f, 0.250f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_CUPBOARD \ + { 26, 1.7f, 0.630f, -1200, -200, -600, 0.49f, 0.65f, 1.31f, 200, 0.010f, 0.00f,0.00f,0.00f, 600, 0.032f, 0.00f,0.00f,0.00f, 0.107f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_COURTYARD \ + { 26, 1.7f, 0.570f, -1000, -1000, -400, 2.32f, 0.29f, 0.56f, -1300, 0.140f, 0.00f,0.00f,0.00f, -800, 0.039f, 0.00f,0.00f,0.00f, 0.250f, 0.290f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } +#define REVERB_PRESET_FACTORY_SMALLROOM \ + { 26, 1.8f, 0.820f, -1000, -200, -600, 1.72f, 0.65f, 1.31f, -300, 0.010f, 0.00f,0.00f,0.00f, 500, 0.024f, 0.00f,0.00f,0.00f, 0.119f, 0.070f, 0.250f, 0.000f, -5.0f, 3762.6f, 362.5f, 0.00f, 0x20 } + + +// ICE PALACE PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_ICEPALACE_ALCOVE \ + { 26, 2.7f, 0.840f, -1000, -500, -1100, 2.76f, 1.46f, 0.28f, 100, 0.010f, 0.00f,0.00f,0.00f, -100, 0.030f, 0.00f,0.00f,0.00f, 0.161f, 0.090f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_SHORTPASSAGE \ + { 26, 2.7f, 0.750f, -1000, -500, -1100, 1.79f, 1.46f, 0.28f, -600, 0.010f, 0.00f,0.00f,0.00f, 100, 0.019f, 0.00f,0.00f,0.00f, 0.177f, 0.090f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_MEDIUMROOM \ + { 26, 2.7f, 0.870f, -1000, -500, -700, 2.22f, 1.53f, 0.32f, -800, 0.039f, 0.00f,0.00f,0.00f, 100, 0.027f, 0.00f,0.00f,0.00f, 0.186f, 0.120f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_LONGPASSAGE \ + { 26, 2.7f, 0.770f, -1000, -500, -800, 3.01f, 1.46f, 0.28f, -200, 0.012f, 0.00f,0.00f,0.00f, 200, 0.025f, 0.00f,0.00f,0.00f, 0.186f, 0.040f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_LARGEROOM \ + { 26, 2.9f, 0.810f, -1000, -500, -700, 3.14f, 1.53f, 0.32f, -1200, 0.039f, 0.00f,0.00f,0.00f, 000, 0.027f, 0.00f,0.00f,0.00f, 0.214f, 0.110f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_HALL \ + { 26, 2.9f, 0.760f, -1000, -700, -500, 5.49f, 1.53f, 0.38f, -1900, 0.054f, 0.00f,0.00f,0.00f, -400, 0.052f, 0.00f,0.00f,0.00f, 0.226f, 0.110f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_CUPBOARD \ + { 26, 2.7f, 0.830f, -1000, -600, -1300, 0.76f, 1.53f, 0.26f, 100, 0.012f, 0.00f,0.00f,0.00f, 600, 0.016f, 0.00f,0.00f,0.00f, 0.143f, 0.080f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_COURTYARD \ + { 26, 2.9f, 0.590f, -1000, -1100, -1000, 2.04f, 1.20f, 0.38f, -1000, 0.173f, 0.00f,0.00f,0.00f, -1000, 0.043f, 0.00f,0.00f,0.00f, 0.235f, 0.480f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } +#define REVERB_PRESET_ICEPALACE_SMALLROOM \ + { 26, 2.7f, 0.840f, -1000, -500, -1100, 1.51f, 1.53f, 0.27f, -100, 0.010f, 0.00f,0.00f,0.00f, 300, 0.011f, 0.00f,0.00f,0.00f, 0.164f, 0.140f, 0.250f, 0.000f, -5.0f, 12428.5f, 99.6f, 0.00f, 0x20 } + + +// SPACE STATION PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_SPACESTATION_ALCOVE \ + { 26, 1.5f, 0.780f, -1000, -300, -100, 1.16f, 0.81f, 0.55f, 300, 0.007f, 0.00f,0.00f,0.00f, 000, 0.018f, 0.00f,0.00f,0.00f, 0.192f, 0.210f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPACESTATION_MEDIUMROOM \ + { 26, 1.5f, 0.750f, -1000, -400, -100, 3.01f, 0.50f, 0.55f, -800, 0.034f, 0.00f,0.00f,0.00f, 100, 0.035f, 0.00f,0.00f,0.00f, 0.209f, 0.310f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPACESTATION_SHORTPASSAGE \ + { 26, 1.5f, 0.870f, -1000, -400, -100, 3.57f, 0.50f, 0.55f, 0, 0.012f, 0.00f,0.00f,0.00f, 100, 0.016f, 0.00f,0.00f,0.00f, 0.172f, 0.200f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPACESTATION_LONGPASSAGE \ + { 26, 1.9f, 0.820f, -1000, -400, -100, 4.62f, 0.62f, 0.55f, 0, 0.012f, 0.00f,0.00f,0.00f, 200, 0.031f, 0.00f,0.00f,0.00f, 0.250f, 0.230f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPACESTATION_LARGEROOM \ + { 26, 1.8f, 0.810f, -1000, -400, -100, 3.89f, 0.38f, 0.61f, -1000, 0.056f, 0.00f,0.00f,0.00f, -100, 0.035f, 0.00f,0.00f,0.00f, 0.233f, 0.280f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPACESTATION_HALL \ + { 26, 1.9f, 0.870f, -1000, -400, -100, 7.11f, 0.38f, 0.61f, -1500, 0.100f, 0.00f,0.00f,0.00f, -400, 0.047f, 0.00f,0.00f,0.00f, 0.250f, 0.250f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPACESTATION_CUPBOARD \ + { 26, 1.4f, 0.560f, -1000, -300, -100, 0.79f, 0.81f, 0.55f, 300, 0.007f, 0.00f,0.00f,0.00f, 500, 0.018f, 0.00f,0.00f,0.00f, 0.181f, 0.310f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPACESTATION_SMALLROOM \ + { 26, 1.5f, 0.700f, -1000, -300, -100, 1.72f, 0.82f, 0.55f, -200, 0.007f, 0.00f,0.00f,0.00f, 300, 0.013f, 0.00f,0.00f,0.00f, 0.188f, 0.260f, 0.250f, 0.000f, -5.0f, 3316.1f, 458.2f, 0.00f, 0x20 } + + +// WOODEN GALLEON PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_WOODEN_ALCOVE \ + { 26, 7.5f, 1.000f, -1000, -1800, -1000, 1.22f, 0.62f, 0.91f, 100, 0.012f, 0.00f,0.00f,0.00f, -300, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_SHORTPASSAGE \ + { 26, 7.5f, 1.000f, -1000, -1800, -1000, 1.75f, 0.50f, 0.87f, -100, 0.012f, 0.00f,0.00f,0.00f, -400, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_MEDIUMROOM \ + { 26, 7.5f, 1.000f, -1000, -2000, -1100, 1.47f, 0.42f, 0.82f, -100, 0.049f, 0.00f,0.00f,0.00f, -100, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_LONGPASSAGE \ + { 26, 7.5f, 1.000f, -1000, -2000, -1000, 1.99f, 0.40f, 0.79f, 000, 0.020f, 0.00f,0.00f,0.00f, -700, 0.036f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_LARGEROOM \ + { 26, 7.5f, 1.000f, -1000, -2100, -1100, 2.65f, 0.33f, 0.82f, -100, 0.066f, 0.00f,0.00f,0.00f, -200, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_HALL \ + { 26, 7.5f, 1.000f, -1000, -2200, -1100, 3.45f, 0.30f, 0.82f, -100, 0.088f, 0.00f,0.00f,0.00f, -200, 0.063f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_CUPBOARD \ + { 26, 7.5f, 1.000f, -1000, -1700, -1000, 0.56f, 0.46f, 0.91f, 100, 0.012f, 0.00f,0.00f,0.00f, 100, 0.028f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_SMALLROOM \ + { 26, 7.5f, 1.000f, -1000, -1900, -1000, 0.79f, 0.32f, 0.87f, 00, 0.032f, 0.00f,0.00f,0.00f, -100, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } +#define REVERB_PRESET_WOODEN_COURTYARD \ + { 26, 7.5f, 0.650f, -1000, -2200, -1000, 1.79f, 0.35f, 0.79f, -500, 0.123f, 0.00f,0.00f,0.00f, -2000, 0.032f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 4705.0f, 99.6f, 0.00f, 0x3f } + + +// SPORTS PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_SPORT_EMPTYSTADIUM \ + { 26, 7.2f, 1.000f, -1000, -700, -200, 6.26f, 0.51f, 1.10f, -2400, 0.183f, 0.00f,0.00f,0.00f, -800, 0.038f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } +#define REVERB_PRESET_SPORT_SQUASHCOURT \ + { 26, 7.5f, 0.750f, -1000, -1000, -200, 2.22f, 0.91f, 1.16f, -700, 0.007f, 0.00f,0.00f,0.00f, -200, 0.011f, 0.00f,0.00f,0.00f, 0.126f, 0.190f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPORT_SMALLSWIMMINGPOOL \ + { 26, 36.2f, 0.700f, -1000, -200, -100, 2.76f, 1.25f, 1.14f, -400, 0.020f, 0.00f,0.00f,0.00f, -200, 0.030f, 0.00f,0.00f,0.00f, 0.179f, 0.150f, 0.895f, 0.190f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } +#define REVERB_PRESET_SPORT_LARGESWIMMINGPOOL\ + { 26, 36.2f, 0.820f, -1000, -200, 0, 5.49f, 1.31f, 1.14f, -700, 0.039f, 0.00f,0.00f,0.00f, -600, 0.049f, 0.00f,0.00f,0.00f, 0.222f, 0.550f, 1.159f, 0.210f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } +#define REVERB_PRESET_SPORT_GYMNASIUM \ + { 26, 7.5f, 0.810f, -1000, -700, -100, 3.14f, 1.06f, 1.35f, -800, 0.029f, 0.00f,0.00f,0.00f, -500, 0.045f, 0.00f,0.00f,0.00f, 0.146f, 0.140f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } +#define REVERB_PRESET_SPORT_FULLSTADIUM \ + { 26, 7.2f, 1.000f, -1000, -2300, -200, 5.25f, 0.17f, 0.80f, -2000, 0.188f, 0.00f,0.00f,0.00f, -1100, 0.038f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } +#define REVERB_PRESET_SPORT_STADIUMTANNOY \ + { 26, 3.0f, 0.780f, -1000, -500, -600, 2.53f, 0.88f, 0.68f, -1100, 0.230f, 0.00f,0.00f,0.00f, -600, 0.063f, 0.00f,0.00f,0.00f, 0.250f, 0.200f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } + + +// PREFAB PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_PREFAB_WORKSHOP \ + { 26, 1.9f, 1.000f, -1000, -1700, -800, 0.76f, 1.00f, 1.00f, 0, 0.012f, 0.00f,0.00f,0.00f, 100, 0.012f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } +#define REVERB_PRESET_PREFAB_SCHOOLROOM \ + { 26, 1.86f, 0.690f, -1000, -400, -600, 0.98f, 0.45f, 0.18f, 300, 0.017f, 0.00f,0.00f,0.00f, 300, 0.015f, 0.00f,0.00f,0.00f, 0.095f, 0.140f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } +#define REVERB_PRESET_PREFAB_PRACTISEROOM \ + { 26, 1.86f, 0.870f, -1000, -800, -600, 1.12f, 0.56f, 0.18f, 200, 0.010f, 0.00f,0.00f,0.00f, 300, 0.011f, 0.00f,0.00f,0.00f, 0.095f, 0.140f, 0.250f, 0.000f, -5.0f, 7176.9f, 211.2f, 0.00f, 0x20 } +#define REVERB_PRESET_PREFAB_OUTHOUSE \ + { 26, 80.3f, 0.820f, -1000, -1900, -1600, 1.38f, 0.38f, 0.35f, -100, 0.024f, 0.00f,0.00f,-0.00f, -400, 0.044f, 0.00f,0.00f,0.00f, 0.121f, 0.170f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } +#define REVERB_PRESET_PREFAB_CARAVAN \ + { 26, 8.3f, 1.000f, -1000, -2100, -1800, 0.43f, 1.50f, 1.00f, 0, 0.012f, 0.00f,0.00f,0.00f, 600, 0.012f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x1f } + // for US developers, a caravan is the same as a trailer =o) + + +// DOME AND PIPE PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_DOME_TOMB \ + { 26, 51.8f, 0.790f, -1000, -900, -1300, 4.18f, 0.21f, 0.10f, -825, 0.030f, 0.00f,0.00f,0.00f, 450, 0.022f, 0.00f,0.00f,0.00f, 0.177f, 0.190f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x0 } +#define REVERB_PRESET_PIPE_SMALL \ + { 26, 50.3f, 1.000f, -1000, -900, -1300, 5.04f, 0.10f, 0.10f, -600, 0.032f, 0.00f,0.00f,0.00f, 800, 0.015f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x3f } +#define REVERB_PRESET_DOME_SAINTPAULS \ + { 26, 50.3f, 0.870f, -1000, -900, -1300, 10.48f, 0.19f, 0.10f, -1500, 0.090f, 0.00f,0.00f,0.00f, 200, 0.042f, 0.00f,0.00f,0.00f, 0.250f, 0.120f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x3f } +#define REVERB_PRESET_PIPE_LONGTHIN \ + { 26, 1.6f, 0.910f, -1000, -700, -1100, 9.21f, 0.18f, 0.10f, -300, 0.010f, 0.00f,0.00f,0.00f, -300, 0.022f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x0 } +#define REVERB_PRESET_PIPE_LARGE \ + { 26, 50.3f, 1.000f, -1000, -900, -1300, 8.45f, 0.10f, 0.10f, -800, 0.046f, 0.00f,0.00f,0.00f, 400, 0.032f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x3f } +#define REVERB_PRESET_PIPE_RESONANT \ + { 26, 1.3f, 0.910f, -1000, -700, -1100, 6.81f, 0.18f, 0.10f, -300, 0.010f, 0.00f,0.00f,0.00f, 00, 0.022f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 2854.4f, 20.0f, 0.00f, 0x0 } + + +// OUTDOORS PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_OUTDOORS_BACKYARD \ + { 26, 80.3f, 0.450f, -1000, -1200, -600, 1.12f, 0.34f, 0.46f, -700, 0.069f, 0.00f,0.00f,-0.00f, -300, 0.023f, 0.00f,0.00f,0.00f, 0.218f, 0.340f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } +#define REVERB_PRESET_OUTDOORS_ROLLINGPLAINS \ + { 26, 80.3f, 0.000f, -1000, -3900, -400, 2.13f, 0.21f, 0.46f, -1500, 0.300f, 0.00f,0.00f,-0.00f, -700, 0.019f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } +#define REVERB_PRESET_OUTDOORS_DEEPCANYON \ + { 26, 80.3f, 0.740f, -1000, -1500, -400, 3.89f, 0.21f, 0.46f, -1000, 0.223f, 0.00f,0.00f,-0.00f, -900, 0.019f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } +#define REVERB_PRESET_OUTDOORS_CREEK \ + { 26, 80.3f, 0.350f, -1000, -1500, -600, 2.13f, 0.21f, 0.46f, -800, 0.115f, 0.00f,0.00f,-0.00f, -1400, 0.031f, 0.00f,0.00f,0.00f, 0.218f, 0.340f, 0.250f, 0.000f, -5.0f, 4399.1f, 242.9f, 0.00f, 0x0 } +#define REVERB_PRESET_OUTDOORS_VALLEY \ + { 26, 80.3f, 0.280f, -1000, -3100, -1600, 2.88f, 0.26f, 0.35f, -1700, 0.263f, 0.00f,0.00f,-0.00f, -800, 0.100f, 0.00f,0.00f,0.00f, 0.250f, 0.340f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } + + +// MOOD PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_MOOD_HEAVEN \ + { 26, 19.6f, 0.940f, -1000, -200, -700, 5.04f, 1.12f, 0.56f, -1230, 0.020f, 0.00f,0.00f,0.00f, 200, 0.029f, 0.00f,0.00f,0.00f, 0.250f, 0.080f, 2.742f, 0.050f, -2.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_MOOD_HELL \ + { 26, 100.0f, 0.570f, -1000, -900, -700, 3.57f, 0.49f, 2.00f, -10000, 0.020f, 0.00f,0.00f,0.00f, 300, 0.030f, 0.00f,0.00f,0.00f, 0.110f, 0.040f, 2.109f, 0.520f, -5.0f, 5000.0f, 139.5f, 0.00f, 0x40 } +#define REVERB_PRESET_MOOD_MEMORY \ + { 26, 8.0f, 0.850f, -1000, -400, -900, 4.06f, 0.82f, 0.56f, -2800, 0.000f, 0.00f,0.00f,0.00f, 100, 0.000f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.474f, 0.450f, -10.0f, 5000.0f, 250.0f, 0.00f, 0x0 } + + +// DRIVING SIMULATION PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_DRIVING_COMMENTATOR \ + { 26, 3.0f, 0.000f, 1000, -500, -600, 2.42f, 0.88f, 0.68f, -1400, 0.093f, 0.00f,0.00f,0.00f, -1200, 0.017f, 0.00f,0.00f,0.00f, 0.250f, 1.000f, 0.250f, 0.000f, -10.0f, 5000.0f, 250.0f, 0.00f, 0x20 } +#define REVERB_PRESET_DRIVING_PITGARAGE \ + { 26, 1.9f, 0.590f, -1000, -300, -500, 1.72f, 0.93f, 0.87f, -500, 0.000f, 0.00f,0.00f,0.00f, 200, 0.016f, 0.00f,0.00f,0.00f, 0.250f, 0.110f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x0 } +#define REVERB_PRESET_DRIVING_INCAR_RACER \ + { 26, 1.1f, 0.800f, -1000, 0, -200, 0.17f, 2.00f, 0.41f, 500, 0.007f, 0.00f,0.00f,0.00f, -300, 0.015f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10268.2f, 251.0f, 0.00f, 0x20 } +#define REVERB_PRESET_DRIVING_INCAR_SPORTS \ + { 26, 1.1f, 0.800f, -1000, -400, 0, 0.17f, 0.75f, 0.41f, 0, 0.010f, 0.00f,0.00f,0.00f, -500, 0.000f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10268.2f, 251.0f, 0.00f, 0x20 } +#define REVERB_PRESET_DRIVING_INCAR_LUXURY \ + { 26, 1.6f, 1.000f, -1000, -2000, -600, 0.13f, 0.41f, 0.46f, -200, 0.010f, 0.00f,0.00f,0.00f, 400, 0.010f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10268.2f, 251.0f, 0.00f, 0x20 } +#define REVERB_PRESET_DRIVING_FULLGRANDSTAND \ + { 26, 8.3f, 1.000f, -1000, -1100, -400, 3.01f, 1.37f, 1.28f, -900, 0.090f, 0.00f,0.00f,0.00f, -1500, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10420.2f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_DRIVING_EMPTYGRANDSTAND \ + { 26, 8.3f, 1.000f, -1000, 0, -200, 4.62f, 1.75f, 1.40f, -1363, 0.090f, 0.00f,0.00f,0.00f, -1200, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.000f, -5.0f, 10420.2f, 250.0f, 0.00f, 0x1f } +#define REVERB_PRESET_DRIVING_TUNNEL \ + { 26, 3.1f, 0.810f, -1000, -800, -100, 3.42f, 0.94f, 1.31f, -300, 0.051f, 0.00f,0.00f,0.00f, -300, 0.047f, 0.00f,0.00f,0.00f, 0.214f, 0.050f, 0.250f, 0.000f, -5.0f, 5000.0f, 155.3f, 0.00f, 0x20 } + + +// CITY PRESETS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_CITY_STREETS \ + { 26, 3.0f, 0.780f, -1000, -300, -100, 1.79f, 1.12f, 0.91f, -1100, 0.046f, 0.00f,0.00f,0.00f, -1400, 0.028f, 0.00f,0.00f,0.00f, 0.250f, 0.200f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } +#define REVERB_PRESET_CITY_SUBWAY \ + { 26, 3.0f, 0.740f, -1000, -300, -100, 3.01f, 1.23f, 0.91f, -300, 0.046f, 0.00f,0.00f,0.00f, 200, 0.028f, 0.00f,0.00f,0.00f, 0.125f, 0.210f, 0.250f, 0.000f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x20 } +#define REVERB_PRESET_CITY_MUSEUM \ + { 26, 80.3f, 0.820f, -1000, -1500, -1500, 3.28f, 1.40f, 0.57f, -1200, 0.039f, 0.00f,0.00f,-0.00f, -100, 0.034f, 0.00f,0.00f,0.00f, 0.130f, 0.170f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } +#define REVERB_PRESET_CITY_LIBRARY \ + { 26, 80.3f, 0.820f, -1000, -1100, -2100, 2.76f, 0.89f, 0.41f, -900, 0.029f, 0.00f,0.00f,-0.00f, -100, 0.020f, 0.00f,0.00f,0.00f, 0.130f, 0.170f, 0.250f, 0.000f, -5.0f, 2854.4f, 107.5f, 0.00f, 0x0 } +#define REVERB_PRESET_CITY_UNDERPASS \ + { 26, 3.0f, 0.820f, -1000, -700, -100, 3.57f, 1.12f, 0.91f, -800, 0.059f, 0.00f,0.00f,0.00f, -100, 0.037f, 0.00f,0.00f,0.00f, 0.250f, 0.140f, 0.250f, 0.000f, -7.0f, 5000.0f, 250.0f, 0.00f, 0x20 } +#define REVERB_PRESET_CITY_ABANDONED \ + { 26, 3.0f, 0.690f, -1000, -200, -100, 3.28f, 1.17f, 0.91f, -700, 0.044f, 0.00f,0.00f,0.00f, -1100, 0.024f, 0.00f,0.00f,0.00f, 0.250f, 0.200f, 0.250f, 0.000f, -3.0f, 5000.0f, 250.0f, 0.00f, 0x20 } + + +// MISC ROOMS + +// Env Size Diffus Room RoomHF RoomLF DecTm DcHF DcLF Refl RefDel Ref Pan Revb RevDel Rev Pan EchTm EchDp ModTm ModDp AirAbs HFRef LFRef RRlOff FLAGS +#define REVERB_PRESET_DUSTYROOM \ + { 26, 1.8f, 0.560f, -1000, -200, -300, 1.79f, 0.38f, 0.21f, -600, 0.002f, 0.00f,0.00f,0.00f, 200, 0.006f, 0.00f,0.00f,0.00f, 0.202f, 0.050f, 0.250f, 0.000f, -10.0f, 13046.0f, 163.3f, 0.00f, 0x20 } +#define REVERB_PRESET_CHAPEL \ + { 26, 19.6f, 0.840f, -1000, -500, 0, 4.62f, 0.64f, 1.23f, -700, 0.032f, 0.00f,0.00f,0.00f, -200, 0.049f, 0.00f,0.00f,0.00f, 0.250f, 0.000f, 0.250f, 0.110f, -5.0f, 5000.0f, 250.0f, 0.00f, 0x3f } +#define REVERB_PRESET_SMALLWATERROOM \ + { 26, 36.2f, 0.700f, -1000, -698, 0, 1.51f, 1.25f, 1.14f, -100, 0.020f, 0.00f,0.00f,0.00f, 300, 0.030f, 0.00f,0.00f,0.00f, 0.179f, 0.150f, 0.895f, 0.190f, -7.0f, 5000.0f, 250.0f, 0.00f, 0x0 } diff --git a/MUNGA_L4/openal/al.h b/MUNGA_L4/openal/al.h new file mode 100644 index 0000000..1c2f95b --- /dev/null +++ b/MUNGA_L4/openal/al.h @@ -0,0 +1,732 @@ +#ifndef AL_AL_H +#define AL_AL_H + + + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(_WIN32) && !defined(_XBOX) + /* _OPENAL32LIB is deprecated */ + #if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB) + #define AL_API __declspec(dllexport) + #else + #define AL_API __declspec(dllimport) + #endif +#else + #define AL_API extern +#endif + +#if defined(_WIN32) + #define AL_APIENTRY __cdecl +#else + #define AL_APIENTRY +#endif + +#if TARGET_OS_MAC + #pragma export on +#endif + +/* The OPENAL, ALAPI, and ALAPIENTRY macros are deprecated, but are included for applications porting code + from AL 1.0 */ +#define OPENAL +#define ALAPI AL_API +#define ALAPIENTRY AL_APIENTRY + +#define AL_VERSION_1_0 +#define AL_VERSION_1_1 + + +/** 8-bit boolean */ +typedef char ALboolean; + +/** character */ +typedef char ALchar; + +/** signed 8-bit 2's complement integer */ +typedef char ALbyte; + +/** unsigned 8-bit integer */ +typedef unsigned char ALubyte; + +/** signed 16-bit 2's complement integer */ +typedef short ALshort; + +/** unsigned 16-bit integer */ +typedef unsigned short ALushort; + +/** signed 32-bit 2's complement integer */ +typedef int ALint; + +/** unsigned 32-bit integer */ +typedef unsigned int ALuint; + +/** non-negative 32-bit binary integer size */ +typedef int ALsizei; + +/** enumerated 32-bit value */ +typedef int ALenum; + +/** 32-bit IEEE754 floating-point */ +typedef float ALfloat; + +/** 64-bit IEEE754 floating-point */ +typedef double ALdouble; + +/** void type (for opaque pointers only) */ +typedef void ALvoid; + + +/* Enumerant values begin at column 50. No tabs. */ + +/* bad value */ +#define AL_INVALID -1 + +#define AL_NONE 0 + +/* Boolean False. */ +#define AL_FALSE 0 + +/** Boolean True. */ +#define AL_TRUE 1 + +/** Indicate Source has relative coordinates. */ +#define AL_SOURCE_RELATIVE 0x202 + + + +/** + * Directional source, inner cone angle, in degrees. + * Range: [0-360] + * Default: 360 + */ +#define AL_CONE_INNER_ANGLE 0x1001 + +/** + * Directional source, outer cone angle, in degrees. + * Range: [0-360] + * Default: 360 + */ +#define AL_CONE_OUTER_ANGLE 0x1002 + +/** + * Specify the pitch to be applied, either at source, + * or on mixer results, at listener. + * Range: [0.5-2.0] + * Default: 1.0 + */ +#define AL_PITCH 0x1003 + +/** + * Specify the current location in three dimensional space. + * OpenAL, like OpenGL, uses a right handed coordinate system, + * where in a frontal default view X (thumb) points right, + * Y points up (index finger), and Z points towards the + * viewer/camera (middle finger). + * To switch from a left handed coordinate system, flip the + * sign on the Z coordinate. + * Listener position is always in the world coordinate system. + */ +#define AL_POSITION 0x1004 + +/** Specify the current direction. */ +#define AL_DIRECTION 0x1005 + +/** Specify the current velocity in three dimensional space. */ +#define AL_VELOCITY 0x1006 + +/** + * Indicate whether source is looping. + * Type: ALboolean? + * Range: [AL_TRUE, AL_FALSE] + * Default: FALSE. + */ +#define AL_LOOPING 0x1007 + +/** + * Indicate the buffer to provide sound samples. + * Type: ALuint. + * Range: any valid Buffer id. + */ +#define AL_BUFFER 0x1009 + +/** + * Indicate the gain (volume amplification) applied. + * Type: ALfloat. + * Range: ]0.0- ] + * A value of 1.0 means un-attenuated/unchanged. + * Each division by 2 equals an attenuation of -6dB. + * Each multiplicaton with 2 equals an amplification of +6dB. + * A value of 0.0 is meaningless with respect to a logarithmic + * scale; it is interpreted as zero volume - the channel + * is effectively disabled. + */ +#define AL_GAIN 0x100A + +/* + * Indicate minimum source attenuation + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * Logarthmic + */ +#define AL_MIN_GAIN 0x100D + +/** + * Indicate maximum source attenuation + * Type: ALfloat + * Range: [0.0 - 1.0] + * + * Logarthmic + */ +#define AL_MAX_GAIN 0x100E + +/** + * Indicate listener orientation. + * + * at/up + */ +#define AL_ORIENTATION 0x100F + +/** + * Specify the channel mask. (Creative) + * Type: ALuint + * Range: [0 - 255] + */ +#define AL_CHANNEL_MASK 0x3000 + + +/** + * Source state information. + */ +#define AL_SOURCE_STATE 0x1010 +#define AL_INITIAL 0x1011 +#define AL_PLAYING 0x1012 +#define AL_PAUSED 0x1013 +#define AL_STOPPED 0x1014 + +/** + * Buffer Queue params + */ +#define AL_BUFFERS_QUEUED 0x1015 +#define AL_BUFFERS_PROCESSED 0x1016 + +/** + * Source buffer position information + */ +#define AL_SEC_OFFSET 0x1024 +#define AL_SAMPLE_OFFSET 0x1025 +#define AL_BYTE_OFFSET 0x1026 + +/* + * Source type (Static, Streaming or undetermined) + * Source is Static if a Buffer has been attached using AL_BUFFER + * Source is Streaming if one or more Buffers have been attached using alSourceQueueBuffers + * Source is undetermined when it has the NULL buffer attached + */ +#define AL_SOURCE_TYPE 0x1027 +#define AL_STATIC 0x1028 +#define AL_STREAMING 0x1029 +#define AL_UNDETERMINED 0x1030 + +/** Sound samples: format specifier. */ +#define AL_FORMAT_MONO8 0x1100 +#define AL_FORMAT_MONO16 0x1101 +#define AL_FORMAT_STEREO8 0x1102 +#define AL_FORMAT_STEREO16 0x1103 + +/** + * source specific reference distance + * Type: ALfloat + * Range: 0.0 - +inf + * + * At 0.0, no distance attenuation occurs. Default is + * 1.0. + */ +#define AL_REFERENCE_DISTANCE 0x1020 + +/** + * source specific rolloff factor + * Type: ALfloat + * Range: 0.0 - +inf + * + */ +#define AL_ROLLOFF_FACTOR 0x1021 + +/** + * Directional source, outer cone gain. + * + * Default: 0.0 + * Range: [0.0 - 1.0] + * Logarithmic + */ +#define AL_CONE_OUTER_GAIN 0x1022 + +/** + * Indicate distance above which sources are not + * attenuated using the inverse clamped distance model. + * + * Default: +inf + * Type: ALfloat + * Range: 0.0 - +inf + */ +#define AL_MAX_DISTANCE 0x1023 + +/** + * Sound samples: frequency, in units of Hertz [Hz]. + * This is the number of samples per second. Half of the + * sample frequency marks the maximum significant + * frequency component. + */ +#define AL_FREQUENCY 0x2001 +#define AL_BITS 0x2002 +#define AL_CHANNELS 0x2003 +#define AL_SIZE 0x2004 + +/** + * Buffer state. + * + * Not supported for public use (yet). + */ +#define AL_UNUSED 0x2010 +#define AL_PENDING 0x2011 +#define AL_PROCESSED 0x2012 + + +/** Errors: No Error. */ +#define AL_NO_ERROR AL_FALSE + +/** + * Invalid Name paramater passed to AL call. + */ +#define AL_INVALID_NAME 0xA001 + +/** + * Invalid parameter passed to AL call. + */ +#define AL_ILLEGAL_ENUM 0xA002 +#define AL_INVALID_ENUM 0xA002 + +/** + * Invalid enum parameter value. + */ +#define AL_INVALID_VALUE 0xA003 + +/** + * Illegal call. + */ +#define AL_ILLEGAL_COMMAND 0xA004 +#define AL_INVALID_OPERATION 0xA004 + + +/** + * No mojo. + */ +#define AL_OUT_OF_MEMORY 0xA005 + + +/** Context strings: Vendor Name. */ +#define AL_VENDOR 0xB001 +#define AL_VERSION 0xB002 +#define AL_RENDERER 0xB003 +#define AL_EXTENSIONS 0xB004 + +/** Global tweakage. */ + +/** + * Doppler scale. Default 1.0 + */ +#define AL_DOPPLER_FACTOR 0xC000 + +/** + * Tweaks speed of propagation. + */ +#define AL_DOPPLER_VELOCITY 0xC001 + +/** + * Speed of Sound in units per second + */ +#define AL_SPEED_OF_SOUND 0xC003 + +/** + * Distance models + * + * used in conjunction with DistanceModel + * + * implicit: NONE, which disances distance attenuation. + */ +#define AL_DISTANCE_MODEL 0xD000 +#define AL_INVERSE_DISTANCE 0xD001 +#define AL_INVERSE_DISTANCE_CLAMPED 0xD002 +#define AL_LINEAR_DISTANCE 0xD003 +#define AL_LINEAR_DISTANCE_CLAMPED 0xD004 +#define AL_EXPONENT_DISTANCE 0xD005 +#define AL_EXPONENT_DISTANCE_CLAMPED 0xD006 + + +#if !defined(AL_NO_PROTOTYPES) + +/* + * Renderer State management + */ +AL_API void AL_APIENTRY alEnable( ALenum capability ); + +AL_API void AL_APIENTRY alDisable( ALenum capability ); + +AL_API ALboolean AL_APIENTRY alIsEnabled( ALenum capability ); + + +/* + * State retrieval + */ +AL_API const ALchar* AL_APIENTRY alGetString( ALenum param ); + +AL_API void AL_APIENTRY alGetBooleanv( ALenum param, ALboolean* data ); + +AL_API void AL_APIENTRY alGetIntegerv( ALenum param, ALint* data ); + +AL_API void AL_APIENTRY alGetFloatv( ALenum param, ALfloat* data ); + +AL_API void AL_APIENTRY alGetDoublev( ALenum param, ALdouble* data ); + +AL_API ALboolean AL_APIENTRY alGetBoolean( ALenum param ); + +AL_API ALint AL_APIENTRY alGetInteger( ALenum param ); + +AL_API ALfloat AL_APIENTRY alGetFloat( ALenum param ); + +AL_API ALdouble AL_APIENTRY alGetDouble( ALenum param ); + + +/* + * Error support. + * Obtain the most recent error generated in the AL state machine. + */ +AL_API ALenum AL_APIENTRY alGetError( void ); + + +/* + * Extension support. + * Query for the presence of an extension, and obtain any appropriate + * function pointers and enum values. + */ +AL_API ALboolean AL_APIENTRY alIsExtensionPresent( const ALchar* extname ); + +AL_API void* AL_APIENTRY alGetProcAddress( const ALchar* fname ); + +AL_API ALenum AL_APIENTRY alGetEnumValue( const ALchar* ename ); + + +/* + * LISTENER + * Listener represents the location and orientation of the + * 'user' in 3D-space. + * + * Properties include: - + * + * Gain AL_GAIN ALfloat + * Position AL_POSITION ALfloat[3] + * Velocity AL_VELOCITY ALfloat[3] + * Orientation AL_ORIENTATION ALfloat[6] (Forward then Up vectors) +*/ + +/* + * Set Listener parameters + */ +AL_API void AL_APIENTRY alListenerf( ALenum param, ALfloat value ); + +AL_API void AL_APIENTRY alListener3f( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); + +AL_API void AL_APIENTRY alListenerfv( ALenum param, const ALfloat* values ); + +AL_API void AL_APIENTRY alListeneri( ALenum param, ALint value ); + +AL_API void AL_APIENTRY alListener3i( ALenum param, ALint value1, ALint value2, ALint value3 ); + +AL_API void AL_APIENTRY alListeneriv( ALenum param, const ALint* values ); + +/* + * Get Listener parameters + */ +AL_API void AL_APIENTRY alGetListenerf( ALenum param, ALfloat* value ); + +AL_API void AL_APIENTRY alGetListener3f( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ); + +AL_API void AL_APIENTRY alGetListenerfv( ALenum param, ALfloat* values ); + +AL_API void AL_APIENTRY alGetListeneri( ALenum param, ALint* value ); + +AL_API void AL_APIENTRY alGetListener3i( ALenum param, ALint *value1, ALint *value2, ALint *value3 ); + +AL_API void AL_APIENTRY alGetListeneriv( ALenum param, ALint* values ); + + +/** + * SOURCE + * Sources represent individual sound objects in 3D-space. + * Sources take the PCM data provided in the specified Buffer, + * apply Source-specific modifications, and then + * submit them to be mixed according to spatial arrangement etc. + * + * Properties include: - + * + * Gain AL_GAIN ALfloat + * Min Gain AL_MIN_GAIN ALfloat + * Max Gain AL_MAX_GAIN ALfloat + * Position AL_POSITION ALfloat[3] + * Velocity AL_VELOCITY ALfloat[3] + * Direction AL_DIRECTION ALfloat[3] + * Head Relative Mode AL_SOURCE_RELATIVE ALint (AL_TRUE or AL_FALSE) + * Reference Distance AL_REFERENCE_DISTANCE ALfloat + * Max Distance AL_MAX_DISTANCE ALfloat + * RollOff Factor AL_ROLLOFF_FACTOR ALfloat + * Inner Angle AL_CONE_INNER_ANGLE ALint or ALfloat + * Outer Angle AL_CONE_OUTER_ANGLE ALint or ALfloat + * Cone Outer Gain AL_CONE_OUTER_GAIN ALint or ALfloat + * Pitch AL_PITCH ALfloat + * Looping AL_LOOPING ALint (AL_TRUE or AL_FALSE) + * MS Offset AL_MSEC_OFFSET ALint or ALfloat + * Byte Offset AL_BYTE_OFFSET ALint or ALfloat + * Sample Offset AL_SAMPLE_OFFSET ALint or ALfloat + * Attached Buffer AL_BUFFER ALint + * State (Query only) AL_SOURCE_STATE ALint + * Buffers Queued (Query only) AL_BUFFERS_QUEUED ALint + * Buffers Processed (Query only) AL_BUFFERS_PROCESSED ALint + */ + +/* Create Source objects */ +AL_API void AL_APIENTRY alGenSources( ALsizei n, ALuint* sources ); + +/* Delete Source objects */ +AL_API void AL_APIENTRY alDeleteSources( ALsizei n, const ALuint* sources ); + +/* Verify a handle is a valid Source */ +AL_API ALboolean AL_APIENTRY alIsSource( ALuint sid ); + +/* + * Set Source parameters + */ +AL_API void AL_APIENTRY alSourcef( ALuint sid, ALenum param, ALfloat value ); + +AL_API void AL_APIENTRY alSource3f( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); + +AL_API void AL_APIENTRY alSourcefv( ALuint sid, ALenum param, const ALfloat* values ); + +AL_API void AL_APIENTRY alSourcei( ALuint sid, ALenum param, ALint value ); + +AL_API void AL_APIENTRY alSource3i( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ); + +AL_API void AL_APIENTRY alSourceiv( ALuint sid, ALenum param, const ALint* values ); + +/* + * Get Source parameters + */ +AL_API void AL_APIENTRY alGetSourcef( ALuint sid, ALenum param, ALfloat* value ); + +AL_API void AL_APIENTRY alGetSource3f( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); + +AL_API void AL_APIENTRY alGetSourcefv( ALuint sid, ALenum param, ALfloat* values ); + +AL_API void AL_APIENTRY alGetSourcei( ALuint sid, ALenum param, ALint* value ); + +AL_API void AL_APIENTRY alGetSource3i( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3); + +AL_API void AL_APIENTRY alGetSourceiv( ALuint sid, ALenum param, ALint* values ); + + +/* + * Source vector based playback calls + */ + +/* Play, replay, or resume (if paused) a list of Sources */ +AL_API void AL_APIENTRY alSourcePlayv( ALsizei ns, const ALuint *sids ); + +/* Stop a list of Sources */ +AL_API void AL_APIENTRY alSourceStopv( ALsizei ns, const ALuint *sids ); + +/* Rewind a list of Sources */ +AL_API void AL_APIENTRY alSourceRewindv( ALsizei ns, const ALuint *sids ); + +/* Pause a list of Sources */ +AL_API void AL_APIENTRY alSourcePausev( ALsizei ns, const ALuint *sids ); + +/* + * Source based playback calls + */ + +/* Play, replay, or resume a Source */ +AL_API void AL_APIENTRY alSourcePlay( ALuint sid ); + +/* Stop a Source */ +AL_API void AL_APIENTRY alSourceStop( ALuint sid ); + +/* Rewind a Source (set playback postiton to beginning) */ +AL_API void AL_APIENTRY alSourceRewind( ALuint sid ); + +/* Pause a Source */ +AL_API void AL_APIENTRY alSourcePause( ALuint sid ); + +/* + * Source Queuing + */ +AL_API void AL_APIENTRY alSourceQueueBuffers( ALuint sid, ALsizei numEntries, const ALuint *bids ); + +AL_API void AL_APIENTRY alSourceUnqueueBuffers( ALuint sid, ALsizei numEntries, ALuint *bids ); + + +/** + * BUFFER + * Buffer objects are storage space for sample data. + * Buffers are referred to by Sources. One Buffer can be used + * by multiple Sources. + * + * Properties include: - + * + * Frequency (Query only) AL_FREQUENCY ALint + * Size (Query only) AL_SIZE ALint + * Bits (Query only) AL_BITS ALint + * Channels (Query only) AL_CHANNELS ALint + */ + +/* Create Buffer objects */ +AL_API void AL_APIENTRY alGenBuffers( ALsizei n, ALuint* buffers ); + +/* Delete Buffer objects */ +AL_API void AL_APIENTRY alDeleteBuffers( ALsizei n, const ALuint* buffers ); + +/* Verify a handle is a valid Buffer */ +AL_API ALboolean AL_APIENTRY alIsBuffer( ALuint bid ); + +/* Specify the data to be copied into a buffer */ +AL_API void AL_APIENTRY alBufferData( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ); + +/* + * Set Buffer parameters + */ +AL_API void AL_APIENTRY alBufferf( ALuint bid, ALenum param, ALfloat value ); + +AL_API void AL_APIENTRY alBuffer3f( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); + +AL_API void AL_APIENTRY alBufferfv( ALuint bid, ALenum param, const ALfloat* values ); + +AL_API void AL_APIENTRY alBufferi( ALuint bid, ALenum param, ALint value ); + +AL_API void AL_APIENTRY alBuffer3i( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ); + +AL_API void AL_APIENTRY alBufferiv( ALuint bid, ALenum param, const ALint* values ); + +/* + * Get Buffer parameters + */ +AL_API void AL_APIENTRY alGetBufferf( ALuint bid, ALenum param, ALfloat* value ); + +AL_API void AL_APIENTRY alGetBuffer3f( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); + +AL_API void AL_APIENTRY alGetBufferfv( ALuint bid, ALenum param, ALfloat* values ); + +AL_API void AL_APIENTRY alGetBufferi( ALuint bid, ALenum param, ALint* value ); + +AL_API void AL_APIENTRY alGetBuffer3i( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3); + +AL_API void AL_APIENTRY alGetBufferiv( ALuint bid, ALenum param, ALint* values ); + + +/* + * Global Parameters + */ +AL_API void AL_APIENTRY alDopplerFactor( ALfloat value ); + +AL_API void AL_APIENTRY alDopplerVelocity( ALfloat value ); + +AL_API void AL_APIENTRY alSpeedOfSound( ALfloat value ); + +AL_API void AL_APIENTRY alDistanceModel( ALenum distanceModel ); + +#else /* AL_NO_PROTOTYPES */ + +typedef void (AL_APIENTRY *LPALENABLE)( ALenum capability ); +typedef void (AL_APIENTRY *LPALDISABLE)( ALenum capability ); +typedef ALboolean (AL_APIENTRY *LPALISENABLED)( ALenum capability ); +typedef const ALchar* (AL_APIENTRY *LPALGETSTRING)( ALenum param ); +typedef void (AL_APIENTRY *LPALGETBOOLEANV)( ALenum param, ALboolean* data ); +typedef void (AL_APIENTRY *LPALGETINTEGERV)( ALenum param, ALint* data ); +typedef void (AL_APIENTRY *LPALGETFLOATV)( ALenum param, ALfloat* data ); +typedef void (AL_APIENTRY *LPALGETDOUBLEV)( ALenum param, ALdouble* data ); +typedef ALboolean (AL_APIENTRY *LPALGETBOOLEAN)( ALenum param ); +typedef ALint (AL_APIENTRY *LPALGETINTEGER)( ALenum param ); +typedef ALfloat (AL_APIENTRY *LPALGETFLOAT)( ALenum param ); +typedef ALdouble (AL_APIENTRY *LPALGETDOUBLE)( ALenum param ); +typedef ALenum (AL_APIENTRY *LPALGETERROR)( void ); +typedef ALboolean (AL_APIENTRY *LPALISEXTENSIONPRESENT)(const ALchar* extname ); +typedef void* (AL_APIENTRY *LPALGETPROCADDRESS)( const ALchar* fname ); +typedef ALenum (AL_APIENTRY *LPALGETENUMVALUE)( const ALchar* ename ); +typedef void (AL_APIENTRY *LPALLISTENERF)( ALenum param, ALfloat value ); +typedef void (AL_APIENTRY *LPALLISTENER3F)( ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); +typedef void (AL_APIENTRY *LPALLISTENERFV)( ALenum param, const ALfloat* values ); +typedef void (AL_APIENTRY *LPALLISTENERI)( ALenum param, ALint value ); +typedef void (AL_APIENTRY *LPALLISTENER3I)( ALenum param, ALint value1, ALint value2, ALint value3 ); +typedef void (AL_APIENTRY *LPALLISTENERIV)( ALenum param, const ALint* values ); +typedef void (AL_APIENTRY *LPALGETLISTENERF)( ALenum param, ALfloat* value ); +typedef void (AL_APIENTRY *LPALGETLISTENER3F)( ALenum param, ALfloat *value1, ALfloat *value2, ALfloat *value3 ); +typedef void (AL_APIENTRY *LPALGETLISTENERFV)( ALenum param, ALfloat* values ); +typedef void (AL_APIENTRY *LPALGETLISTENERI)( ALenum param, ALint* value ); +typedef void (AL_APIENTRY *LPALGETLISTENER3I)( ALenum param, ALint *value1, ALint *value2, ALint *value3 ); +typedef void (AL_APIENTRY *LPALGETLISTENERIV)( ALenum param, ALint* values ); +typedef void (AL_APIENTRY *LPALGENSOURCES)( ALsizei n, ALuint* sources ); +typedef void (AL_APIENTRY *LPALDELETESOURCES)( ALsizei n, const ALuint* sources ); +typedef ALboolean (AL_APIENTRY *LPALISSOURCE)( ALuint sid ); +typedef void (AL_APIENTRY *LPALSOURCEF)( ALuint sid, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALSOURCE3F)( ALuint sid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); +typedef void (AL_APIENTRY *LPALSOURCEFV)( ALuint sid, ALenum param, const ALfloat* values ); +typedef void (AL_APIENTRY *LPALSOURCEI)( ALuint sid, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALSOURCE3I)( ALuint sid, ALenum param, ALint value1, ALint value2, ALint value3 ); +typedef void (AL_APIENTRY *LPALSOURCEIV)( ALuint sid, ALenum param, const ALint* values ); +typedef void (AL_APIENTRY *LPALGETSOURCEF)( ALuint sid, ALenum param, ALfloat* value ); +typedef void (AL_APIENTRY *LPALGETSOURCE3F)( ALuint sid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); +typedef void (AL_APIENTRY *LPALGETSOURCEFV)( ALuint sid, ALenum param, ALfloat* values ); +typedef void (AL_APIENTRY *LPALGETSOURCEI)( ALuint sid, ALenum param, ALint* value ); +typedef void (AL_APIENTRY *LPALGETSOURCE3I)( ALuint sid, ALenum param, ALint* value1, ALint* value2, ALint* value3); +typedef void (AL_APIENTRY *LPALGETSOURCEIV)( ALuint sid, ALenum param, ALint* values ); +typedef void (AL_APIENTRY *LPALSOURCEPLAYV)( ALsizei ns, const ALuint *sids ); +typedef void (AL_APIENTRY *LPALSOURCESTOPV)( ALsizei ns, const ALuint *sids ); +typedef void (AL_APIENTRY *LPALSOURCEREWINDV)( ALsizei ns, const ALuint *sids ); +typedef void (AL_APIENTRY *LPALSOURCEPAUSEV)( ALsizei ns, const ALuint *sids ); +typedef void (AL_APIENTRY *LPALSOURCEPLAY)( ALuint sid ); +typedef void (AL_APIENTRY *LPALSOURCESTOP)( ALuint sid ); +typedef void (AL_APIENTRY *LPALSOURCEREWIND)( ALuint sid ); +typedef void (AL_APIENTRY *LPALSOURCEPAUSE)( ALuint sid ); +typedef void (AL_APIENTRY *LPALSOURCEQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, const ALuint *bids ); +typedef void (AL_APIENTRY *LPALSOURCEUNQUEUEBUFFERS)(ALuint sid, ALsizei numEntries, ALuint *bids ); +typedef void (AL_APIENTRY *LPALGENBUFFERS)( ALsizei n, ALuint* buffers ); +typedef void (AL_APIENTRY *LPALDELETEBUFFERS)( ALsizei n, const ALuint* buffers ); +typedef ALboolean (AL_APIENTRY *LPALISBUFFER)( ALuint bid ); +typedef void (AL_APIENTRY *LPALBUFFERDATA)( ALuint bid, ALenum format, const ALvoid* data, ALsizei size, ALsizei freq ); +typedef void (AL_APIENTRY *LPALBUFFERF)( ALuint bid, ALenum param, ALfloat value); +typedef void (AL_APIENTRY *LPALBUFFER3F)( ALuint bid, ALenum param, ALfloat value1, ALfloat value2, ALfloat value3 ); +typedef void (AL_APIENTRY *LPALBUFFERFV)( ALuint bid, ALenum param, const ALfloat* values ); +typedef void (AL_APIENTRY *LPALBUFFERI)( ALuint bid, ALenum param, ALint value); +typedef void (AL_APIENTRY *LPALBUFFER3I)( ALuint bid, ALenum param, ALint value1, ALint value2, ALint value3 ); +typedef void (AL_APIENTRY *LPALBUFFERIV)( ALuint bid, ALenum param, const ALint* values ); +typedef void (AL_APIENTRY *LPALGETBUFFERF)( ALuint bid, ALenum param, ALfloat* value ); +typedef void (AL_APIENTRY *LPALGETBUFFER3F)( ALuint bid, ALenum param, ALfloat* value1, ALfloat* value2, ALfloat* value3); +typedef void (AL_APIENTRY *LPALGETBUFFERFV)( ALuint bid, ALenum param, ALfloat* values ); +typedef void (AL_APIENTRY *LPALGETBUFFERI)( ALuint bid, ALenum param, ALint* value ); +typedef void (AL_APIENTRY *LPALGETBUFFER3I)( ALuint bid, ALenum param, ALint* value1, ALint* value2, ALint* value3); +typedef void (AL_APIENTRY *LPALGETBUFFERIV)( ALuint bid, ALenum param, ALint* values ); +typedef void (AL_APIENTRY *LPALDOPPLERFACTOR)( ALfloat value ); +typedef void (AL_APIENTRY *LPALDOPPLERVELOCITY)( ALfloat value ); +typedef void (AL_APIENTRY *LPALSPEEDOFSOUND)( ALfloat value ); +typedef void (AL_APIENTRY *LPALDISTANCEMODEL)( ALenum distanceModel ); + +#endif /* AL_NO_PROTOTYPES */ + +#if TARGET_OS_MAC + #pragma export off +#endif + +#if defined(__cplusplus) +} /* extern "C" */ +#endif + +#endif /* AL_AL_H */ diff --git a/MUNGA_L4/openal/alc.h b/MUNGA_L4/openal/alc.h new file mode 100644 index 0000000..07e287d --- /dev/null +++ b/MUNGA_L4/openal/alc.h @@ -0,0 +1,273 @@ +#ifndef AL_ALC_H +#define AL_ALC_H + +#if defined(__cplusplus) +extern "C" { +#endif + +#if defined(_WIN32) && !defined(_XBOX) + /* _OPENAL32LIB is deprecated */ + #if defined(AL_BUILD_LIBRARY) || defined (_OPENAL32LIB) + #define ALC_API __declspec(dllexport) + #else + #define ALC_API __declspec(dllimport) + #endif +#else + #define ALC_API extern +#endif + +#if defined(_WIN32) + #define ALC_APIENTRY __cdecl +#else + #define ALC_APIENTRY +#endif + +#if TARGET_OS_MAC + #pragma export on +#endif + +/* The ALCAPI, and ALCAPIENTRY macros are deprecated, but are included for applications porting code + from AL 1.0 */ +#define ALCAPI ALC_API +#define ALCAPIENTRY ALC_APIENTRY + +#define ALC_VERSION_0_1 1 + +typedef struct ALCdevice_struct ALCdevice; +typedef struct ALCcontext_struct ALCcontext; + + +/** 8-bit boolean */ +typedef char ALCboolean; + +/** character */ +typedef char ALCchar; + +/** signed 8-bit 2's complement integer */ +typedef char ALCbyte; + +/** unsigned 8-bit integer */ +typedef unsigned char ALCubyte; + +/** signed 16-bit 2's complement integer */ +typedef short ALCshort; + +/** unsigned 16-bit integer */ +typedef unsigned short ALCushort; + +/** signed 32-bit 2's complement integer */ +typedef int ALCint; + +/** unsigned 32-bit integer */ +typedef unsigned int ALCuint; + +/** non-negative 32-bit binary integer size */ +typedef int ALCsizei; + +/** enumerated 32-bit value */ +typedef int ALCenum; + +/** 32-bit IEEE754 floating-point */ +typedef float ALCfloat; + +/** 64-bit IEEE754 floating-point */ +typedef double ALCdouble; + +/** void type (for opaque pointers only) */ +typedef void ALCvoid; + + +/* Enumerant values begin at column 50. No tabs. */ + +/* bad value */ +#define ALC_INVALID 0 + +/* Boolean False. */ +#define ALC_FALSE 0 + +/* Boolean True. */ +#define ALC_TRUE 1 + +/** + * followed by Hz + */ +#define ALC_FREQUENCY 0x1007 + +/** + * followed by Hz + */ +#define ALC_REFRESH 0x1008 + +/** + * followed by AL_TRUE, AL_FALSE + */ +#define ALC_SYNC 0x1009 + +/** + * followed by Num of requested Mono (3D) Sources + */ +#define ALC_MONO_SOURCES 0x1010 + +/** + * followed by Num of requested Stereo Sources + */ +#define ALC_STEREO_SOURCES 0x1011 + +/** + * errors + */ + +/** + * No error + */ +#define ALC_NO_ERROR ALC_FALSE + +/** + * No device + */ +#define ALC_INVALID_DEVICE 0xA001 + +/** + * invalid context ID + */ +#define ALC_INVALID_CONTEXT 0xA002 + +/** + * bad enum + */ +#define ALC_INVALID_ENUM 0xA003 + +/** + * bad value + */ +#define ALC_INVALID_VALUE 0xA004 + +/** + * Out of memory. + */ +#define ALC_OUT_OF_MEMORY 0xA005 + + +/** + * The Specifier string for default device + */ +#define ALC_DEFAULT_DEVICE_SPECIFIER 0x1004 +#define ALC_DEVICE_SPECIFIER 0x1005 +#define ALC_EXTENSIONS 0x1006 + +#define ALC_MAJOR_VERSION 0x1000 +#define ALC_MINOR_VERSION 0x1001 + +#define ALC_ATTRIBUTES_SIZE 0x1002 +#define ALC_ALL_ATTRIBUTES 0x1003 + +/** + * Capture extension + */ +#define ALC_CAPTURE_DEVICE_SPECIFIER 0x310 +#define ALC_CAPTURE_DEFAULT_DEVICE_SPECIFIER 0x311 +#define ALC_CAPTURE_SAMPLES 0x312 + + +#if !defined(ALC_NO_PROTOTYPES) + +/* + * Context Management + */ +ALC_API ALCcontext * ALC_APIENTRY alcCreateContext( ALCdevice *device, const ALCint* attrlist ); + +ALC_API ALCboolean ALC_APIENTRY alcMakeContextCurrent( ALCcontext *context ); + +ALC_API void ALC_APIENTRY alcProcessContext( ALCcontext *context ); + +ALC_API void ALC_APIENTRY alcSuspendContext( ALCcontext *context ); + +ALC_API void ALC_APIENTRY alcDestroyContext( ALCcontext *context ); + +ALC_API ALCcontext * ALC_APIENTRY alcGetCurrentContext( ALCvoid ); + +ALC_API ALCdevice* ALC_APIENTRY alcGetContextsDevice( ALCcontext *context ); + + +/* + * Device Management + */ +ALC_API ALCdevice * ALC_APIENTRY alcOpenDevice( const ALCchar *devicename ); + +ALC_API ALCboolean ALC_APIENTRY alcCloseDevice( ALCdevice *device ); + + +/* + * Error support. + * Obtain the most recent Context error + */ +ALC_API ALCenum ALC_APIENTRY alcGetError( ALCdevice *device ); + + +/* + * Extension support. + * Query for the presence of an extension, and obtain any appropriate + * function pointers and enum values. + */ +ALC_API ALCboolean ALC_APIENTRY alcIsExtensionPresent( ALCdevice *device, const ALCchar *extname ); + +ALC_API void * ALC_APIENTRY alcGetProcAddress( ALCdevice *device, const ALCchar *funcname ); + +ALC_API ALCenum ALC_APIENTRY alcGetEnumValue( ALCdevice *device, const ALCchar *enumname ); + + +/* + * Query functions + */ +ALC_API const ALCchar * ALC_APIENTRY alcGetString( ALCdevice *device, ALCenum param ); + +ALC_API void ALC_APIENTRY alcGetIntegerv( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *data ); + + +/* + * Capture functions + */ +ALC_API ALCdevice* ALC_APIENTRY alcCaptureOpenDevice( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ); + +ALC_API ALCboolean ALC_APIENTRY alcCaptureCloseDevice( ALCdevice *device ); + +ALC_API void ALC_APIENTRY alcCaptureStart( ALCdevice *device ); + +ALC_API void ALC_APIENTRY alcCaptureStop( ALCdevice *device ); + +ALC_API void ALC_APIENTRY alcCaptureSamples( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ); + +#else /* ALC_NO_PROTOTYPES */ + +typedef ALCcontext * (ALC_APIENTRY *LPALCCREATECONTEXT) (ALCdevice *device, const ALCint *attrlist); +typedef ALCboolean (ALC_APIENTRY *LPALCMAKECONTEXTCURRENT)( ALCcontext *context ); +typedef void (ALC_APIENTRY *LPALCPROCESSCONTEXT)( ALCcontext *context ); +typedef void (ALC_APIENTRY *LPALCSUSPENDCONTEXT)( ALCcontext *context ); +typedef void (ALC_APIENTRY *LPALCDESTROYCONTEXT)( ALCcontext *context ); +typedef ALCcontext * (ALC_APIENTRY *LPALCGETCURRENTCONTEXT)( ALCvoid ); +typedef ALCdevice * (ALC_APIENTRY *LPALCGETCONTEXTSDEVICE)( ALCcontext *context ); +typedef ALCdevice * (ALC_APIENTRY *LPALCOPENDEVICE)( const ALCchar *devicename ); +typedef ALCboolean (ALC_APIENTRY *LPALCCLOSEDEVICE)( ALCdevice *device ); +typedef ALCenum (ALC_APIENTRY *LPALCGETERROR)( ALCdevice *device ); +typedef ALCboolean (ALC_APIENTRY *LPALCISEXTENSIONPRESENT)( ALCdevice *device, const ALCchar *extname ); +typedef void * (ALC_APIENTRY *LPALCGETPROCADDRESS)(ALCdevice *device, const ALCchar *funcname ); +typedef ALCenum (ALC_APIENTRY *LPALCGETENUMVALUE)(ALCdevice *device, const ALCchar *enumname ); +typedef const ALCchar* (ALC_APIENTRY *LPALCGETSTRING)( ALCdevice *device, ALCenum param ); +typedef void (ALC_APIENTRY *LPALCGETINTEGERV)( ALCdevice *device, ALCenum param, ALCsizei size, ALCint *dest ); +typedef ALCdevice * (ALC_APIENTRY *LPALCCAPTUREOPENDEVICE)( const ALCchar *devicename, ALCuint frequency, ALCenum format, ALCsizei buffersize ); +typedef ALCboolean (ALC_APIENTRY *LPALCCAPTURECLOSEDEVICE)( ALCdevice *device ); +typedef void (ALC_APIENTRY *LPALCCAPTURESTART)( ALCdevice *device ); +typedef void (ALC_APIENTRY *LPALCCAPTURESTOP)( ALCdevice *device ); +typedef void (ALC_APIENTRY *LPALCCAPTURESAMPLES)( ALCdevice *device, ALCvoid *buffer, ALCsizei samples ); + +#endif /* ALC_NO_PROTOTYPES */ + +#if TARGET_OS_MAC + #pragma export off +#endif + +#if defined(__cplusplus) +} +#endif + +#endif /* AL_ALC_H */ diff --git a/MUNGA_L4/openal/efx-creative.h b/MUNGA_L4/openal/efx-creative.h new file mode 100644 index 0000000..4ea9da6 --- /dev/null +++ b/MUNGA_L4/openal/efx-creative.h @@ -0,0 +1,151 @@ +#ifndef __efxcreative_h_ +#define __efxcreative_h_ + +/** + * efx-creative.h - Environmental Audio Extensions + * for OpenAL Effects Extension. + * + */ +#ifdef __cplusplus +extern "C" { +#endif + + +/** + * Effect object definitions to be used with alEffect functions. + * + * Effect parameter value definitions, ranges, and defaults + * appear farther down in this file. + */ + +/* AL EAXReverb effect parameters. */ +#define AL_EAXREVERB_DENSITY 0x0001 +#define AL_EAXREVERB_DIFFUSION 0x0002 +#define AL_EAXREVERB_GAIN 0x0003 +#define AL_EAXREVERB_GAINHF 0x0004 +#define AL_EAXREVERB_GAINLF 0x0005 +#define AL_EAXREVERB_DECAY_TIME 0x0006 +#define AL_EAXREVERB_DECAY_HFRATIO 0x0007 +#define AL_EAXREVERB_DECAY_LFRATIO 0x0008 +#define AL_EAXREVERB_REFLECTIONS_GAIN 0x0009 +#define AL_EAXREVERB_REFLECTIONS_DELAY 0x000A +#define AL_EAXREVERB_REFLECTIONS_PAN 0x000B +#define AL_EAXREVERB_LATE_REVERB_GAIN 0x000C +#define AL_EAXREVERB_LATE_REVERB_DELAY 0x000D +#define AL_EAXREVERB_LATE_REVERB_PAN 0x000E +#define AL_EAXREVERB_ECHO_TIME 0x000F +#define AL_EAXREVERB_ECHO_DEPTH 0x0010 +#define AL_EAXREVERB_MODULATION_TIME 0x0011 +#define AL_EAXREVERB_MODULATION_DEPTH 0x0012 +#define AL_EAXREVERB_AIR_ABSORPTION_GAINHF 0x0013 +#define AL_EAXREVERB_HFREFERENCE 0x0014 +#define AL_EAXREVERB_LFREFERENCE 0x0015 +#define AL_EAXREVERB_ROOM_ROLLOFF_FACTOR 0x0016 +#define AL_EAXREVERB_DECAY_HFLIMIT 0x0017 + +/* Effect type definitions to be used with AL_EFFECT_TYPE. */ +#define AL_EFFECT_EAXREVERB 0x8000 + + + + /********************************************************** + * Effect parameter structures, value definitions, ranges and defaults. + */ + +/** + * AL reverb effect parameter ranges and defaults + */ +#define AL_EAXREVERB_MIN_DENSITY 0.0f +#define AL_EAXREVERB_MAX_DENSITY 1.0f +#define AL_EAXREVERB_DEFAULT_DENSITY 1.0f + +#define AL_EAXREVERB_MIN_DIFFUSION 0.0f +#define AL_EAXREVERB_MAX_DIFFUSION 1.0f +#define AL_EAXREVERB_DEFAULT_DIFFUSION 1.0f + +#define AL_EAXREVERB_MIN_GAIN 0.0f +#define AL_EAXREVERB_MAX_GAIN 1.0f +#define AL_EAXREVERB_DEFAULT_GAIN 0.32f + +#define AL_EAXREVERB_MIN_GAINHF 0.0f +#define AL_EAXREVERB_MAX_GAINHF 1.0f +#define AL_EAXREVERB_DEFAULT_GAINHF 0.89f + +#define AL_EAXREVERB_MIN_GAINLF 0.0f +#define AL_EAXREVERB_MAX_GAINLF 1.0f +#define AL_EAXREVERB_DEFAULT_GAINLF 1.0f + +#define AL_EAXREVERB_MIN_DECAY_TIME 0.1f +#define AL_EAXREVERB_MAX_DECAY_TIME 20.0f +#define AL_EAXREVERB_DEFAULT_DECAY_TIME 1.49f + +#define AL_EAXREVERB_MIN_DECAY_HFRATIO 0.1f +#define AL_EAXREVERB_MAX_DECAY_HFRATIO 2.0f +#define AL_EAXREVERB_DEFAULT_DECAY_HFRATIO 0.83f + +#define AL_EAXREVERB_MIN_DECAY_LFRATIO 0.1f +#define AL_EAXREVERB_MAX_DECAY_LFRATIO 2.0f +#define AL_EAXREVERB_DEFAULT_DECAY_LFRATIO 1.0f + +#define AL_EAXREVERB_MIN_REFLECTIONS_GAIN 0.0f +#define AL_EAXREVERB_MAX_REFLECTIONS_GAIN 3.16f +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_GAIN 0.05f + +#define AL_EAXREVERB_MIN_REFLECTIONS_DELAY 0.0f +#define AL_EAXREVERB_MAX_REFLECTIONS_DELAY 0.3f +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_DELAY 0.007f + +#define AL_EAXREVERB_DEFAULT_REFLECTIONS_PAN {0.0f, 0.0f, 0.0f} + +#define AL_EAXREVERB_MIN_LATE_REVERB_GAIN 0.0f +#define AL_EAXREVERB_MAX_LATE_REVERB_GAIN 10.0f +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_GAIN 1.26f + +#define AL_EAXREVERB_MIN_LATE_REVERB_DELAY 0.0f +#define AL_EAXREVERB_MAX_LATE_REVERB_DELAY 0.1f +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_DELAY 0.011f + +#define AL_EAXREVERB_DEFAULT_LATE_REVERB_PAN {0.0f, 0.0f, 0.0f} + +#define AL_EAXREVERB_MIN_ECHO_TIME 0.075f +#define AL_EAXREVERB_MAX_ECHO_TIME 0.25f +#define AL_EAXREVERB_DEFAULT_ECHO_TIME 0.25f + +#define AL_EAXREVERB_MIN_ECHO_DEPTH 0.0f +#define AL_EAXREVERB_MAX_ECHO_DEPTH 1.0f +#define AL_EAXREVERB_DEFAULT_ECHO_DEPTH 0.0f + +#define AL_EAXREVERB_MIN_MODULATION_TIME 0.04f +#define AL_EAXREVERB_MAX_MODULATION_TIME 4.0f +#define AL_EAXREVERB_DEFAULT_MODULATION_TIME 0.25f + +#define AL_EAXREVERB_MIN_MODULATION_DEPTH 0.0f +#define AL_EAXREVERB_MAX_MODULATION_DEPTH 1.0f +#define AL_EAXREVERB_DEFAULT_MODULATION_DEPTH 0.0f + +#define AL_EAXREVERB_MIN_AIR_ABSORPTION_GAINHF 0.892f +#define AL_EAXREVERB_MAX_AIR_ABSORPTION_GAINHF 1.0f +#define AL_EAXREVERB_DEFAULT_AIR_ABSORPTION_GAINHF 0.994f + +#define AL_EAXREVERB_MIN_HFREFERENCE 1000.0f +#define AL_EAXREVERB_MAX_HFREFERENCE 20000.0f +#define AL_EAXREVERB_DEFAULT_HFREFERENCE 5000.0f + +#define AL_EAXREVERB_MIN_LFREFERENCE 20.0f +#define AL_EAXREVERB_MAX_LFREFERENCE 1000.0f +#define AL_EAXREVERB_DEFAULT_LFREFERENCE 250.0f + +#define AL_EAXREVERB_MIN_ROOM_ROLLOFF_FACTOR 0.0f +#define AL_EAXREVERB_MAX_ROOM_ROLLOFF_FACTOR 10.0f +#define AL_EAXREVERB_DEFAULT_ROOM_ROLLOFF_FACTOR 0.0f + +#define AL_EAXREVERB_MIN_DECAY_HFLIMIT AL_FALSE +#define AL_EAXREVERB_MAX_DECAY_HFLIMIT AL_TRUE +#define AL_EAXREVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __efxcreative_h_ */ diff --git a/MUNGA_L4/openal/efx.h b/MUNGA_L4/openal/efx.h new file mode 100644 index 0000000..fece160 --- /dev/null +++ b/MUNGA_L4/openal/efx.h @@ -0,0 +1,737 @@ +#ifndef __efx_h_ +#define __efx_h_ + + +#ifdef __cplusplus +extern "C" { +#endif + +#define ALC_EXT_EFX_NAME "ALC_EXT_EFX" + +/** + * Context definitions to be used with alcCreateContext. + * These values must be unique and not conflict with other + * al context values. + */ +#define ALC_EFX_MAJOR_VERSION 0x20001 +#define ALC_EFX_MINOR_VERSION 0x20002 +#define ALC_MAX_AUXILIARY_SENDS 0x20003 + + + + +/** + * Listener definitions to be used with alListener functions. + * These values must be unique and not conflict with other + * al listener values. + */ +#define AL_METERS_PER_UNIT 0x20004 + + + + +/** + * Source definitions to be used with alSource functions. + * These values must be unique and not conflict with other + * al source values. + */ +#define AL_DIRECT_FILTER 0x20005 +#define AL_AUXILIARY_SEND_FILTER 0x20006 +#define AL_AIR_ABSORPTION_FACTOR 0x20007 +#define AL_ROOM_ROLLOFF_FACTOR 0x20008 +#define AL_CONE_OUTER_GAINHF 0x20009 +#define AL_DIRECT_FILTER_GAINHF_AUTO 0x2000A +#define AL_AUXILIARY_SEND_FILTER_GAIN_AUTO 0x2000B +#define AL_AUXILIARY_SEND_FILTER_GAINHF_AUTO 0x2000C + + + + +/** + * Effect object definitions to be used with alEffect functions. + * + * Effect parameter value definitions, ranges, and defaults + * appear farther down in this file. + */ + +/* Reverb Parameters */ +#define AL_REVERB_DENSITY 0x0001 +#define AL_REVERB_DIFFUSION 0x0002 +#define AL_REVERB_GAIN 0x0003 +#define AL_REVERB_GAINHF 0x0004 +#define AL_REVERB_DECAY_TIME 0x0005 +#define AL_REVERB_DECAY_HFRATIO 0x0006 +#define AL_REVERB_REFLECTIONS_GAIN 0x0007 +#define AL_REVERB_REFLECTIONS_DELAY 0x0008 +#define AL_REVERB_LATE_REVERB_GAIN 0x0009 +#define AL_REVERB_LATE_REVERB_DELAY 0x000A +#define AL_REVERB_AIR_ABSORPTION_GAINHF 0x000B +#define AL_REVERB_ROOM_ROLLOFF_FACTOR 0x000C +#define AL_REVERB_DECAY_HFLIMIT 0x000D + +/* Chorus Parameters */ +#define AL_CHORUS_WAVEFORM 0x0001 +#define AL_CHORUS_PHASE 0x0002 +#define AL_CHORUS_RATE 0x0003 +#define AL_CHORUS_DEPTH 0x0004 +#define AL_CHORUS_FEEDBACK 0x0005 +#define AL_CHORUS_DELAY 0x0006 + +/* Distortion Parameters */ +#define AL_DISTORTION_EDGE 0x0001 +#define AL_DISTORTION_GAIN 0x0002 +#define AL_DISTORTION_LOWPASS_CUTOFF 0x0003 +#define AL_DISTORTION_EQCENTER 0x0004 +#define AL_DISTORTION_EQBANDWIDTH 0x0005 + +/* Echo Parameters */ +#define AL_ECHO_DELAY 0x0001 +#define AL_ECHO_LRDELAY 0x0002 +#define AL_ECHO_DAMPING 0x0003 +#define AL_ECHO_FEEDBACK 0x0004 +#define AL_ECHO_SPREAD 0x0005 + +/* Flanger Parameters */ +#define AL_FLANGER_WAVEFORM 0x0001 +#define AL_FLANGER_PHASE 0x0002 +#define AL_FLANGER_RATE 0x0003 +#define AL_FLANGER_DEPTH 0x0004 +#define AL_FLANGER_FEEDBACK 0x0005 +#define AL_FLANGER_DELAY 0x0006 + +/* Frequencyshifter Parameters */ +#define AL_FREQUENCY_SHIFTER_FREQUENCY 0x0001 +#define AL_FREQUENCY_SHIFTER_LEFT_DIRECTION 0x0002 +#define AL_FREQUENCY_SHIFTER_RIGHT_DIRECTION 0x0003 + +/* Vocalmorpher Parameters */ +#define AL_VOCAL_MORPHER_PHONEMEA 0x0001 +#define AL_VOCAL_MORPHER_PHONEMEA_COARSE_TUNING 0x0002 +#define AL_VOCAL_MORPHER_PHONEMEB 0x0003 +#define AL_VOCAL_MORPHER_PHONEMEB_COARSE_TUNING 0x0004 +#define AL_VOCAL_MORPHER_WAVEFORM 0x0005 +#define AL_VOCAL_MORPHER_RATE 0x0006 + +/* Pitchshifter Parameters */ +#define AL_PITCH_SHIFTER_COARSE_TUNE 0x0001 +#define AL_PITCH_SHIFTER_FINE_TUNE 0x0002 + +/* Ringmodulator Parameters */ +#define AL_RING_MODULATOR_FREQUENCY 0x0001 +#define AL_RING_MODULATOR_HIGHPASS_CUTOFF 0x0002 +#define AL_RING_MODULATOR_WAVEFORM 0x0003 + +/* Autowah Parameters */ +#define AL_AUTOWAH_ATTACK_TIME 0x0001 +#define AL_AUTOWAH_RELEASE_TIME 0x0002 +#define AL_AUTOWAH_RESONANCE 0x0003 +#define AL_AUTOWAH_PEAK_GAIN 0x0004 + +/* Compressor Parameters */ +#define AL_COMPRESSOR_ONOFF 0x0001 + +/* Equalizer Parameters */ +#define AL_EQUALIZER_LOW_GAIN 0x0001 +#define AL_EQUALIZER_LOW_CUTOFF 0x0002 +#define AL_EQUALIZER_MID1_GAIN 0x0003 +#define AL_EQUALIZER_MID1_CENTER 0x0004 +#define AL_EQUALIZER_MID1_WIDTH 0x0005 +#define AL_EQUALIZER_MID2_GAIN 0x0006 +#define AL_EQUALIZER_MID2_CENTER 0x0007 +#define AL_EQUALIZER_MID2_WIDTH 0x0008 +#define AL_EQUALIZER_HIGH_GAIN 0x0009 +#define AL_EQUALIZER_HIGH_CUTOFF 0x000A + +/* Effect type */ +#define AL_EFFECT_FIRST_PARAMETER 0x0000 +#define AL_EFFECT_LAST_PARAMETER 0x8000 +#define AL_EFFECT_TYPE 0x8001 + +/* Effect type definitions to be used with AL_EFFECT_TYPE. */ +#define AL_EFFECT_NULL 0x0000 /* Can also be used as an Effect Object ID */ +#define AL_EFFECT_REVERB 0x0001 +#define AL_EFFECT_CHORUS 0x0002 +#define AL_EFFECT_DISTORTION 0x0003 +#define AL_EFFECT_ECHO 0x0004 +#define AL_EFFECT_FLANGER 0x0005 +#define AL_EFFECT_FREQUENCY_SHIFTER 0x0006 +#define AL_EFFECT_VOCAL_MORPHER 0x0007 +#define AL_EFFECT_PITCH_SHIFTER 0x0008 +#define AL_EFFECT_RING_MODULATOR 0x0009 +#define AL_EFFECT_AUTOWAH 0x000A +#define AL_EFFECT_COMPRESSOR 0x000B +#define AL_EFFECT_EQUALIZER 0x000C + +/** + * Auxiliary Slot object definitions to be used with alAuxiliaryEffectSlot functions. + */ +#define AL_EFFECTSLOT_EFFECT 0x0001 +#define AL_EFFECTSLOT_GAIN 0x0002 +#define AL_EFFECTSLOT_AUXILIARY_SEND_AUTO 0x0003 + +/** + * Value to be used as an Auxiliary Slot ID to disable a source send.. + */ +#define AL_EFFECTSLOT_NULL 0x0000 + + + +/** + * Filter object definitions to be used with alFilter functions. + */ + +/* Lowpass parameters. */ +#define AL_LOWPASS_GAIN 0x0001 +#define AL_LOWPASS_GAINHF 0x0002 + +/* Highpass Parameters */ +#define AL_HIGHPASS_GAIN 0x0001 +#define AL_HIGHPASS_GAINLF 0x0002 + +/* Bandpass Parameters */ +#define AL_BANDPASS_GAIN 0x0001 +#define AL_BANDPASS_GAINLF 0x0002 +#define AL_BANDPASS_GAINHF 0x0003 + +/* Filter type */ +#define AL_FILTER_FIRST_PARAMETER 0x0000 +#define AL_FILTER_LAST_PARAMETER 0x8000 +#define AL_FILTER_TYPE 0x8001 + +/* Filter type definitions to be used with AL_FILTER_TYPE. */ +#define AL_FILTER_NULL 0x0000 /* Can also be used as a Filter Object ID */ +#define AL_FILTER_LOWPASS 0x0001 +#define AL_FILTER_HIGHPASS 0x0002 +#define AL_FILTER_BANDPASS 0x0003 + + +/** + * Effect object functions. + */ + +/* Create Effect objects. */ +typedef void (__cdecl *LPALGENEFFECTS)( ALsizei n, ALuint* effects ); + +/* Delete Effect objects. */ +typedef void (__cdecl *LPALDELETEEFFECTS)( ALsizei n, ALuint* effects ); + +/* Verify a handle is a valid Effect. */ +typedef ALboolean (__cdecl *LPALISEFFECT)( ALuint eid ); + +/* Set an integer parameter for an Effect object. */ +typedef void (__cdecl *LPALEFFECTI)( ALuint eid, ALenum param, ALint value); +typedef void (__cdecl *LPALEFFECTIV)( ALuint eid, ALenum param, ALint* values ); + +/* Set a floating point parameter for an Effect object. */ +typedef void (__cdecl *LPALEFFECTF)( ALuint eid, ALenum param, ALfloat value); +typedef void (__cdecl *LPALEFFECTFV)( ALuint eid, ALenum param, ALfloat* values ); + +/* Get an integer parameter for an Effect object. */ +typedef void (__cdecl *LPALGETEFFECTI)( ALuint eid, ALenum pname, ALint* value ); +typedef void (__cdecl *LPALGETEFFECTIV)( ALuint eid, ALenum pname, ALint* values ); + +/* Get a floating point parameter for an Effect object. */ +typedef void (__cdecl *LPALGETEFFECTF)( ALuint eid, ALenum pname, ALfloat* value ); +typedef void (__cdecl *LPALGETEFFECTFV)( ALuint eid, ALenum pname, ALfloat* values ); + + +/** + * Filter object functions + */ + +/* Create Filter objects. */ +typedef void (__cdecl *LPALGENFILTERS)( ALsizei n, ALuint* filters ); + +/* Delete Filter objects. */ +typedef void (__cdecl *LPALDELETEFILTERS)( ALsizei n, ALuint* filters ); + +/* Verify a handle is a valid Filter. */ +typedef ALboolean (__cdecl *LPALISFILTER)( ALuint fid ); + +/* Set an integer parameter for a Filter object. */ +typedef void (__cdecl *LPALFILTERI)( ALuint fid, ALenum param, ALint value ); +typedef void (__cdecl *LPALFILTERIV)( ALuint fid, ALenum param, ALint* values ); + +/* Set a floating point parameter for an Filter object. */ +typedef void (__cdecl *LPALFILTERF)( ALuint fid, ALenum param, ALfloat value); +typedef void (__cdecl *LPALFILTERFV)( ALuint fid, ALenum param, ALfloat* values ); + +/* Get an integer parameter for a Filter object. */ +typedef void (__cdecl *LPALGETFILTERI)( ALuint fid, ALenum pname, ALint* value ); +typedef void (__cdecl *LPALGETFILTERIV)( ALuint fid, ALenum pname, ALint* values ); + +/* Get a floating point parameter for a Filter object. */ +typedef void (__cdecl *LPALGETFILTERF)( ALuint fid, ALenum pname, ALfloat* value ); +typedef void (__cdecl *LPALGETFILTERFV)( ALuint fid, ALenum pname, ALfloat* values ); + + +/** + * Auxiliary Slot object functions + */ + +/* Create Auxiliary Slot objects. */ +typedef void (__cdecl *LPALGENAUXILIARYEFFECTSLOTS)( ALsizei n, ALuint* slots ); + +/* Delete Auxiliary Slot objects. */ +typedef void (__cdecl *LPALDELETEAUXILIARYEFFECTSLOTS)( ALsizei n, ALuint* slots ); + +/* Verify a handle is a valid Auxiliary Slot. */ +typedef ALboolean (__cdecl *LPALISAUXILIARYEFFECTSLOT)( ALuint slot ); + +/* Set an integer parameter for a Auxiliary Slot object. */ +typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTI)( ALuint asid, ALenum param, ALint value ); +typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTIV)( ALuint asid, ALenum param, ALint* values ); + +/* Set a floating point parameter for an Auxiliary Slot object. */ +typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTF)( ALuint asid, ALenum param, ALfloat value ); +typedef void (__cdecl *LPALAUXILIARYEFFECTSLOTFV)( ALuint asid, ALenum param, ALfloat* values ); + +/* Get an integer parameter for a Auxiliary Slot object. */ +typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTI)( ALuint asid, ALenum pname, ALint* value ); +typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTIV)( ALuint asid, ALenum pname, ALint* values ); + +/* Get a floating point parameter for a Auxiliary Slot object. */ +typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTF)( ALuint asid, ALenum pname, ALfloat* value ); +typedef void (__cdecl *LPALGETAUXILIARYEFFECTSLOTFV)( ALuint asid, ALenum pname, ALfloat* values ); + + + + +/********************************************************** + * Filter ranges and defaults. + */ + +/** + * Lowpass filter + */ + +#define LOWPASS_MIN_GAIN 0.0f +#define LOWPASS_MAX_GAIN 1.0f +#define LOWPASS_DEFAULT_GAIN 1.0f + +#define LOWPASS_MIN_GAINHF 0.0f +#define LOWPASS_MAX_GAINHF 1.0f +#define LOWPASS_DEFAULT_GAINHF 1.0f + +/** + * Highpass filter + */ + +#define HIGHPASS_MIN_GAIN 0.0f +#define HIGHPASS_MAX_GAIN 1.0f +#define HIGHPASS_DEFAULT_GAIN 1.0f + +#define HIGHPASS_MIN_GAINLF 0.0f +#define HIGHPASS_MAX_GAINLF 1.0f +#define HIGHPASS_DEFAULT_GAINLF 1.0f + +/** + * Bandpass filter + */ + +#define BANDPASS_MIN_GAIN 0.0f +#define BANDPASS_MAX_GAIN 1.0f +#define BANDPASS_DEFAULT_GAIN 1.0f + +#define BANDPASS_MIN_GAINHF 0.0f +#define BANDPASS_MAX_GAINHF 1.0f +#define BANDPASS_DEFAULT_GAINHF 1.0f + +#define BANDPASS_MIN_GAINLF 0.0f +#define BANDPASS_MAX_GAINLF 1.0f +#define BANDPASS_DEFAULT_GAINLF 1.0f + + + + + /********************************************************** + * Effect parameter structures, value definitions, ranges and defaults. + */ + +/** + * AL reverb effect parameter ranges and defaults + */ +#define AL_REVERB_MIN_DENSITY 0.0f +#define AL_REVERB_MAX_DENSITY 1.0f +#define AL_REVERB_DEFAULT_DENSITY 1.0f + +#define AL_REVERB_MIN_DIFFUSION 0.0f +#define AL_REVERB_MAX_DIFFUSION 1.0f +#define AL_REVERB_DEFAULT_DIFFUSION 1.0f + +#define AL_REVERB_MIN_GAIN 0.0f +#define AL_REVERB_MAX_GAIN 1.0f +#define AL_REVERB_DEFAULT_GAIN 0.32f + +#define AL_REVERB_MIN_GAINHF 0.0f +#define AL_REVERB_MAX_GAINHF 1.0f +#define AL_REVERB_DEFAULT_GAINHF 0.89f + +#define AL_REVERB_MIN_DECAY_TIME 0.1f +#define AL_REVERB_MAX_DECAY_TIME 20.0f +#define AL_REVERB_DEFAULT_DECAY_TIME 1.49f + +#define AL_REVERB_MIN_DECAY_HFRATIO 0.1f +#define AL_REVERB_MAX_DECAY_HFRATIO 2.0f +#define AL_REVERB_DEFAULT_DECAY_HFRATIO 0.83f + +#define AL_REVERB_MIN_REFLECTIONS_GAIN 0.0f +#define AL_REVERB_MAX_REFLECTIONS_GAIN 3.16f +#define AL_REVERB_DEFAULT_REFLECTIONS_GAIN 0.05f + +#define AL_REVERB_MIN_REFLECTIONS_DELAY 0.0f +#define AL_REVERB_MAX_REFLECTIONS_DELAY 0.3f +#define AL_REVERB_DEFAULT_REFLECTIONS_DELAY 0.007f + +#define AL_REVERB_MIN_LATE_REVERB_GAIN 0.0f +#define AL_REVERB_MAX_LATE_REVERB_GAIN 10.0f +#define AL_REVERB_DEFAULT_LATE_REVERB_GAIN 1.26f + +#define AL_REVERB_MIN_LATE_REVERB_DELAY 0.0f +#define AL_REVERB_MAX_LATE_REVERB_DELAY 0.1f +#define AL_REVERB_DEFAULT_LATE_REVERB_DELAY 0.011f + +#define AL_REVERB_MIN_AIR_ABSORPTION_GAINHF 0.892f +#define AL_REVERB_MAX_AIR_ABSORPTION_GAINHF 1.0f +#define AL_REVERB_DEFAULT_AIR_ABSORPTION_GAINHF 0.994f + +#define AL_REVERB_MIN_ROOM_ROLLOFF_FACTOR 0.0f +#define AL_REVERB_MAX_ROOM_ROLLOFF_FACTOR 10.0f +#define AL_REVERB_DEFAULT_ROOM_ROLLOFF_FACTOR 0.0f + +#define AL_REVERB_MIN_DECAY_HFLIMIT AL_FALSE +#define AL_REVERB_MAX_DECAY_HFLIMIT AL_TRUE +#define AL_REVERB_DEFAULT_DECAY_HFLIMIT AL_TRUE + +/** + * AL chorus effect parameter ranges and defaults + */ +#define AL_CHORUS_MIN_WAVEFORM 0 +#define AL_CHORUS_MAX_WAVEFORM 1 +#define AL_CHORUS_DEFAULT_WAVEFORM 1 + +#define AL_CHORUS_WAVEFORM_SINUSOID 0 +#define AL_CHORUS_WAVEFORM_TRIANGLE 1 + +#define AL_CHORUS_MIN_PHASE (-180) +#define AL_CHORUS_MAX_PHASE 180 +#define AL_CHORUS_DEFAULT_PHASE 90 + +#define AL_CHORUS_MIN_RATE 0.0f +#define AL_CHORUS_MAX_RATE 10.0f +#define AL_CHORUS_DEFAULT_RATE 1.1f + +#define AL_CHORUS_MIN_DEPTH 0.0f +#define AL_CHORUS_MAX_DEPTH 1.0f +#define AL_CHORUS_DEFAULT_DEPTH 0.1f + +#define AL_CHORUS_MIN_FEEDBACK (-1.0f) +#define AL_CHORUS_MAX_FEEDBACK 1.0f +#define AL_CHORUS_DEFAULT_FEEDBACK 0.25f + +#define AL_CHORUS_MIN_DELAY 0.0f +#define AL_CHORUS_MAX_DELAY 0.016f +#define AL_CHORUS_DEFAULT_DELAY 0.016f + +/** + * AL distortion effect parameter ranges and defaults + */ +#define AL_DISTORTION_MIN_EDGE 0.0f +#define AL_DISTORTION_MAX_EDGE 1.0f +#define AL_DISTORTION_DEFAULT_EDGE 0.2f + +#define AL_DISTORTION_MIN_GAIN 0.01f +#define AL_DISTORTION_MAX_GAIN 1.0f +#define AL_DISTORTION_DEFAULT_GAIN 0.05f + +#define AL_DISTORTION_MIN_LOWPASS_CUTOFF 80.0f +#define AL_DISTORTION_MAX_LOWPASS_CUTOFF 24000.0f +#define AL_DISTORTION_DEFAULT_LOWPASS_CUTOFF 8000.0f + +#define AL_DISTORTION_MIN_EQCENTER 80.0f +#define AL_DISTORTION_MAX_EQCENTER 24000.0f +#define AL_DISTORTION_DEFAULT_EQCENTER 3600.0f + +#define AL_DISTORTION_MIN_EQBANDWIDTH 80.0f +#define AL_DISTORTION_MAX_EQBANDWIDTH 24000.0f +#define AL_DISTORTION_DEFAULT_EQBANDWIDTH 3600.0f + +/** + * AL echo effect parameter ranges and defaults + */ +#define AL_ECHO_MIN_DELAY 0.0f +#define AL_ECHO_MAX_DELAY 0.207f +#define AL_ECHO_DEFAULT_DELAY 0.1f + +#define AL_ECHO_MIN_LRDELAY 0.0f +#define AL_ECHO_MAX_LRDELAY 0.404f +#define AL_ECHO_DEFAULT_LRDELAY 0.1f + +#define AL_ECHO_MIN_DAMPING 0.0f +#define AL_ECHO_MAX_DAMPING 0.99f +#define AL_ECHO_DEFAULT_DAMPING 0.5f + +#define AL_ECHO_MIN_FEEDBACK 0.0f +#define AL_ECHO_MAX_FEEDBACK 1.0f +#define AL_ECHO_DEFAULT_FEEDBACK 0.5f + +#define AL_ECHO_MIN_SPREAD (-1.0f) +#define AL_ECHO_MAX_SPREAD 1.0f +#define AL_ECHO_DEFAULT_SPREAD (-1.0f) + +/** + * AL flanger effect parameter ranges and defaults + */ +#define AL_FLANGER_MIN_WAVEFORM 0 +#define AL_FLANGER_MAX_WAVEFORM 1 +#define AL_FLANGER_DEFAULT_WAVEFORM 1 + +#define AL_FLANGER_WAVEFORM_SINUSOID 0 +#define AL_FLANGER_WAVEFORM_TRIANGLE 1 + +#define AL_FLANGER_MIN_PHASE (-180) +#define AL_FLANGER_MAX_PHASE 180 +#define AL_FLANGER_DEFAULT_PHASE 0 + +#define AL_FLANGER_MIN_RATE 0.0f +#define AL_FLANGER_MAX_RATE 10.0f +#define AL_FLANGER_DEFAULT_RATE 0.27f + +#define AL_FLANGER_MIN_DEPTH 0.0f +#define AL_FLANGER_MAX_DEPTH 1.0f +#define AL_FLANGER_DEFAULT_DEPTH 1.0f + +#define AL_FLANGER_MIN_FEEDBACK (-1.0f) +#define AL_FLANGER_MAX_FEEDBACK 1.0f +#define AL_FLANGER_DEFAULT_FEEDBACK (-0.5f) + +#define AL_FLANGER_MIN_DELAY 0.0f +#define AL_FLANGER_MAX_DELAY 0.004f +#define AL_FLANGER_DEFAULT_DELAY 0.002f + +/** + * AL frequency shifter effect parameter ranges and defaults + */ +#define AL_FREQUENCY_SHIFTER_MIN_FREQUENCY 0.0f +#define AL_FREQUENCY_SHIFTER_MAX_FREQUENCY 24000.0f +#define AL_FREQUENCY_SHIFTER_DEFAULT_FREQUENCY 0.0f + +#define AL_FREQUENCY_SHIFTER_MIN_LEFT_DIRECTION 0 +#define AL_FREQUENCY_SHIFTER_MAX_LEFT_DIRECTION 2 +#define AL_FREQUENCY_SHIFTER_DEFAULT_LEFT_DIRECTION 0 + +#define AL_FREQUENCY_SHIFTER_MIN_RIGHT_DIRECTION 0 +#define AL_FREQUENCY_SHIFTER_MAX_RIGHT_DIRECTION 2 +#define AL_FREQUENCY_SHIFTER_DEFAULT_RIGHT_DIRECTION 0 + +#define AL_FREQUENCY_SHIFTER_DIRECTION_DOWN 0 +#define AL_FREQUENCY_SHIFTER_DIRECTION_UP 1 +#define AL_FREQUENCY_SHIFTER_DIRECTION_OFF 2 + +/** + * AL vocal morpher effect parameter ranges and defaults + */ +#define AL_VOCAL_MORPHER_MIN_PHONEMEA 0 +#define AL_VOCAL_MORPHER_MAX_PHONEMEA 29 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA 0 + +#define AL_VOCAL_MORPHER_MIN_PHONEMEA_COARSE_TUNING (-24) +#define AL_VOCAL_MORPHER_MAX_PHONEMEA_COARSE_TUNING 24 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEA_COARSE_TUNING 0 + +#define AL_VOCAL_MORPHER_MIN_PHONEMEB 0 +#define AL_VOCAL_MORPHER_MAX_PHONEMEB 29 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB 10 + +#define AL_VOCAL_MORPHER_PHONEME_A 0 +#define AL_VOCAL_MORPHER_PHONEME_E 1 +#define AL_VOCAL_MORPHER_PHONEME_I 2 +#define AL_VOCAL_MORPHER_PHONEME_O 3 +#define AL_VOCAL_MORPHER_PHONEME_U 4 +#define AL_VOCAL_MORPHER_PHONEME_AA 5 +#define AL_VOCAL_MORPHER_PHONEME_AE 6 +#define AL_VOCAL_MORPHER_PHONEME_AH 7 +#define AL_VOCAL_MORPHER_PHONEME_AO 8 +#define AL_VOCAL_MORPHER_PHONEME_EH 9 +#define AL_VOCAL_MORPHER_PHONEME_ER 10 +#define AL_VOCAL_MORPHER_PHONEME_IH 11 +#define AL_VOCAL_MORPHER_PHONEME_IY 12 +#define AL_VOCAL_MORPHER_PHONEME_UH 13 +#define AL_VOCAL_MORPHER_PHONEME_UW 14 +#define AL_VOCAL_MORPHER_PHONEME_B 15 +#define AL_VOCAL_MORPHER_PHONEME_D 16 +#define AL_VOCAL_MORPHER_PHONEME_F 17 +#define AL_VOCAL_MORPHER_PHONEME_G 18 +#define AL_VOCAL_MORPHER_PHONEME_J 19 +#define AL_VOCAL_MORPHER_PHONEME_K 20 +#define AL_VOCAL_MORPHER_PHONEME_L 21 +#define AL_VOCAL_MORPHER_PHONEME_M 22 +#define AL_VOCAL_MORPHER_PHONEME_N 23 +#define AL_VOCAL_MORPHER_PHONEME_P 24 +#define AL_VOCAL_MORPHER_PHONEME_R 25 +#define AL_VOCAL_MORPHER_PHONEME_S 26 +#define AL_VOCAL_MORPHER_PHONEME_T 27 +#define AL_VOCAL_MORPHER_PHONEME_V 28 +#define AL_VOCAL_MORPHER_PHONEME_Z 29 + +#define AL_VOCAL_MORPHER_MIN_PHONEMEB_COARSE_TUNING (-24) +#define AL_VOCAL_MORPHER_MAX_PHONEMEB_COARSE_TUNING 24 +#define AL_VOCAL_MORPHER_DEFAULT_PHONEMEB_COARSE_TUNING 0 + +#define AL_VOCAL_MORPHER_MIN_WAVEFORM 0 +#define AL_VOCAL_MORPHER_MAX_WAVEFORM 2 +#define AL_VOCAL_MORPHER_DEFAULT_WAVEFORM 0 + +#define AL_VOCAL_MORPHER_WAVEFORM_SINUSOID 0 +#define AL_VOCAL_MORPHER_WAVEFORM_TRIANGLE 1 +#define AL_VOCAL_MORPHER_WAVEFORM_SAWTOOTH 2 + +#define AL_VOCAL_MORPHER_MIN_RATE 0.0f +#define AL_VOCAL_MORPHER_MAX_RATE 10.0f +#define AL_VOCAL_MORPHER_DEFAULT_RATE 1.41f + +/** + * AL pitch shifter effect parameter ranges and defaults + */ +#define AL_PITCH_SHIFTER_MIN_COARSE_TUNE (-12) +#define AL_PITCH_SHIFTER_MAX_COARSE_TUNE 12 +#define AL_PITCH_SHIFTER_DEFAULT_COARSE_TUNE 12 + +#define AL_PITCH_SHIFTER_MIN_FINE_TUNE (-50) +#define AL_PITCH_SHIFTER_MAX_FINE_TUNE 50 +#define AL_PITCH_SHIFTER_DEFAULT_FINE_TUNE 0 + +/** + * AL ring modulator effect parameter ranges and defaults + */ +#define AL_RING_MODULATOR_MIN_FREQUENCY 0.0f +#define AL_RING_MODULATOR_MAX_FREQUENCY 8000.0f +#define AL_RING_MODULATOR_DEFAULT_FREQUENCY 440.0f + +#define AL_RING_MODULATOR_MIN_HIGHPASS_CUTOFF 0.0f +#define AL_RING_MODULATOR_MAX_HIGHPASS_CUTOFF 24000.0f +#define AL_RING_MODULATOR_DEFAULT_HIGHPASS_CUTOFF 800.0f + +#define AL_RING_MODULATOR_MIN_WAVEFORM 0 +#define AL_RING_MODULATOR_MAX_WAVEFORM 2 +#define AL_RING_MODULATOR_DEFAULT_WAVEFORM 0 + +#define AL_RING_MODULATOR_SINUSOID 0 +#define AL_RING_MODULATOR_SAWTOOTH 1 +#define AL_RING_MODULATOR_SQUARE 2 + +/** + * AL autowah effect parameter ranges and defaults + */ +#define AL_AUTOWAH_MIN_ATTACK_TIME 0.0001f +#define AL_AUTOWAH_MAX_ATTACK_TIME 1.0f +#define AL_AUTOWAH_DEFAULT_ATTACK_TIME 0.06f + +#define AL_AUTOWAH_MIN_RELEASE_TIME 0.0001f +#define AL_AUTOWAH_MAX_RELEASE_TIME 1.0f +#define AL_AUTOWAH_DEFAULT_RELEASE_TIME 0.06f + +#define AL_AUTOWAH_MIN_RESONANCE 2.0f +#define AL_AUTOWAH_MAX_RESONANCE 1000.0f +#define AL_AUTOWAH_DEFAULT_RESONANCE 1000.0f + +#define AL_AUTOWAH_MIN_PEAK_GAIN 0.00003f +#define AL_AUTOWAH_MAX_PEAK_GAIN 31621.0f +#define AL_AUTOWAH_DEFAULT_PEAK_GAIN 11.22f + +/** + * AL compressor effect parameter ranges and defaults + */ +#define AL_COMPRESSOR_MIN_ONOFF 0 +#define AL_COMPRESSOR_MAX_ONOFF 1 +#define AL_COMPRESSOR_DEFAULT_ONOFF 1 + +/** + * AL equalizer effect parameter ranges and defaults + */ +#define AL_EQUALIZER_MIN_LOW_GAIN 0.126f +#define AL_EQUALIZER_MAX_LOW_GAIN 7.943f +#define AL_EQUALIZER_DEFAULT_LOW_GAIN 1.0f + +#define AL_EQUALIZER_MIN_LOW_CUTOFF 50.0f +#define AL_EQUALIZER_MAX_LOW_CUTOFF 800.0f +#define AL_EQUALIZER_DEFAULT_LOW_CUTOFF 200.0f + +#define AL_EQUALIZER_MIN_MID1_GAIN 0.126f +#define AL_EQUALIZER_MAX_MID1_GAIN 7.943f +#define AL_EQUALIZER_DEFAULT_MID1_GAIN 1.0f + +#define AL_EQUALIZER_MIN_MID1_CENTER 200.0f +#define AL_EQUALIZER_MAX_MID1_CENTER 3000.0f +#define AL_EQUALIZER_DEFAULT_MID1_CENTER 500.0f + +#define AL_EQUALIZER_MIN_MID1_WIDTH 0.01f +#define AL_EQUALIZER_MAX_MID1_WIDTH 1.0f +#define AL_EQUALIZER_DEFAULT_MID1_WIDTH 1.0f + +#define AL_EQUALIZER_MIN_MID2_GAIN 0.126f +#define AL_EQUALIZER_MAX_MID2_GAIN 7.943f +#define AL_EQUALIZER_DEFAULT_MID2_GAIN 1.0f + +#define AL_EQUALIZER_MIN_MID2_CENTER 1000.0f +#define AL_EQUALIZER_MAX_MID2_CENTER 8000.0f +#define AL_EQUALIZER_DEFAULT_MID2_CENTER 3000.0f + +#define AL_EQUALIZER_MIN_MID2_WIDTH 0.01f +#define AL_EQUALIZER_MAX_MID2_WIDTH 1.0f +#define AL_EQUALIZER_DEFAULT_MID2_WIDTH 1.0f + +#define AL_EQUALIZER_MIN_HIGH_GAIN 0.126f +#define AL_EQUALIZER_MAX_HIGH_GAIN 7.943f +#define AL_EQUALIZER_DEFAULT_HIGH_GAIN 1.0f + +#define AL_EQUALIZER_MIN_HIGH_CUTOFF 4000.0f +#define AL_EQUALIZER_MAX_HIGH_CUTOFF 16000.0f +#define AL_EQUALIZER_DEFAULT_HIGH_CUTOFF 6000.0f + + + + +/********************************************************** + * Source parameter value definitions, ranges and defaults. + */ +#define AL_MIN_AIR_ABSORPTION_FACTOR 0.0f +#define AL_MAX_AIR_ABSORPTION_FACTOR 10.0f +#define AL_DEFAULT_AIR_ABSORPTION_FACTOR 0.0f + +#define AL_MIN_ROOM_ROLLOFF_FACTOR 0.0f +#define AL_MAX_ROOM_ROLLOFF_FACTOR 10.0f +#define AL_DEFAULT_ROOM_ROLLOFF_FACTOR 0.0f + +#define AL_MIN_CONE_OUTER_GAINHF 0.0f +#define AL_MAX_CONE_OUTER_GAINHF 1.0f +#define AL_DEFAULT_CONE_OUTER_GAINHF 1.0f + +#define AL_MIN_DIRECT_FILTER_GAINHF_AUTO AL_FALSE +#define AL_MAX_DIRECT_FILTER_GAINHF_AUTO AL_TRUE +#define AL_DEFAULT_DIRECT_FILTER_GAINHF_AUTO AL_TRUE + +#define AL_MIN_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_FALSE +#define AL_MAX_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE +#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAIN_AUTO AL_TRUE + +#define AL_MIN_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_FALSE +#define AL_MAX_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE +#define AL_DEFAULT_AUXILIARY_SEND_FILTER_GAINHF_AUTO AL_TRUE + + + + +/********************************************************** + * Listener parameter value definitions, ranges and defaults. + */ +#define AL_MIN_METERS_PER_UNIT FLT_MIN +#define AL_MAX_METERS_PER_UNIT FLT_MAX +#define AL_DEFAULT_METERS_PER_UNIT 1.0f + + +#ifdef __cplusplus +} /* extern "C" */ +#endif + +#endif /* __efx_h_ */ diff --git a/MUNGA_L4/openal/xram.h b/MUNGA_L4/openal/xram.h new file mode 100644 index 0000000..5d83662 --- /dev/null +++ b/MUNGA_L4/openal/xram.h @@ -0,0 +1,94 @@ +#include + +// X-RAM Function pointer definitions +typedef ALboolean (__cdecl *EAXSetBufferMode)(ALsizei n, ALuint *buffers, ALint value); +typedef ALenum (__cdecl *EAXGetBufferMode)(ALuint buffer, ALint *value); + +////////////////////////////////////////////////////////////////////////////// +// Query for X-RAM extension +// +// if (alIsExtensionPresent("EAX-RAM") == AL_TRUE) +// X-RAM Extension found +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// X-RAM enum names +// +// "AL_EAX_RAM_SIZE" +// "AL_EAX_RAM_FREE" +// "AL_STORAGE_AUTOMATIC" +// "AL_STORAGE_HARDWARE" +// "AL_STORAGE_ACCESSIBLE" +// +// Query enum values using alGetEnumValue, for example +// +// long lRamSizeEnum = alGetEnumValue("AL_EAX_RAM_SIZE") +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Query total amount of X-RAM +// +// long lTotalSize = alGetInteger(alGetEnumValue("AL_EAX_RAM_SIZE") +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Query free X-RAM available +// +// long lFreeSize = alGetInteger(alGetEnumValue("AL_EAX_RAM_FREE") +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Query X-RAM Function pointers +// +// Use typedefs defined above to get the X-RAM function pointers using +// alGetProcAddress +// +// EAXSetBufferMode eaxSetBufferMode; +// EAXGetBufferMode eaxGetBufferMode; +// +// eaxSetBufferMode = (EAXSetBufferMode)alGetProcAddress("EAXSetBufferMode"); +// eaxGetBufferMode = (EAXGetBufferMode)alGetProcAddress("EAXGetBufferMode"); +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Force an Open AL Buffer into X-RAM (good for non-streaming buffers) +// +// ALuint uiBuffer; +// alGenBuffers(1, &uiBuffer); +// eaxSetBufferMode(1, &uiBuffer, alGetEnumValue("AL_STORAGE_HARDWARE")); +// alBufferData(...); +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Force an Open AL Buffer into 'accessible' (currently host) RAM (good for streaming buffers) +// +// ALuint uiBuffer; +// alGenBuffers(1, &uiBuffer); +// eaxSetBufferMode(1, &uiBuffer, alGetEnumValue("AL_STORAGE_ACCESSIBLE")); +// alBufferData(...); +// +////////////////////////////////////////////////////////////////////////////// + + +////////////////////////////////////////////////////////////////////////////// +// Put an Open AL Buffer into X-RAM if memory is available, otherwise use +// host RAM. This is the default mode. +// +// ALuint uiBuffer; +// alGenBuffers(1, &uiBuffer); +// eaxSetBufferMode(1, &uiBuffer, alGetEnumValue("AL_STORAGE_AUTOMATIC")); +// alBufferData(...); +// +////////////////////////////////////////////////////////////////////////////// \ No newline at end of file diff --git a/MUNGA_L4/sndfile.h b/MUNGA_L4/sndfile.h new file mode 100644 index 0000000..e10a8c5 --- /dev/null +++ b/MUNGA_L4/sndfile.h @@ -0,0 +1,554 @@ +/* +** Copyright (C) 1999-2006 Erik de Castro Lopo +** +** This program is free software; you can redistribute it and/or modify +** it under the terms of the GNU Lesser General Public License as published by +** the Free Software Foundation; either version 2.1 of the License, or +** (at your option) any later version. +** +** This program is distributed in the hope that it will be useful, +** but WITHOUT ANY WARRANTY; without even the implied warranty of +** MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +** GNU Lesser General Public License for more details. +** +** You should have received a copy of the GNU Lesser General Public License +** along with this program; if not, write to the Free Software +** Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. +*/ + +/* +** sndfile.h -- system-wide definitions +** +** API documentation is in the doc/ directory of the source code tarball +** and at http://www.mega-nerd.com/libsndfile/api.html. +*/ + +#ifndef SNDFILE_H +#define SNDFILE_H + +/* This is the version 1.0.X header file. */ +#define SNDFILE_1 + +#include + +/* For the Metrowerks CodeWarrior Pro Compiler (mainly MacOS) */ + +#if (defined (__MWERKS__)) +#include +#else +#include +#endif + +#ifdef __cplusplus +extern "C" { +#endif /* __cplusplus */ + +/* The following file types can be read and written. +** A file type would consist of a major type (ie SF_FORMAT_WAV) bitwise +** ORed with a minor type (ie SF_FORMAT_PCM). SF_FORMAT_TYPEMASK and +** SF_FORMAT_SUBMASK can be used to separate the major and minor file +** types. +*/ + +enum +{ /* Major formats. */ + SF_FORMAT_WAV = 0x010000, /* Microsoft WAV format (little endian default). */ + SF_FORMAT_AIFF = 0x020000, /* Apple/SGI AIFF format (big endian). */ + SF_FORMAT_AU = 0x030000, /* Sun/NeXT AU format (big endian). */ + SF_FORMAT_RAW = 0x040000, /* RAW PCM data. */ + SF_FORMAT_PAF = 0x050000, /* Ensoniq PARIS file format. */ + SF_FORMAT_SVX = 0x060000, /* Amiga IFF / SVX8 / SV16 format. */ + SF_FORMAT_NIST = 0x070000, /* Sphere NIST format. */ + SF_FORMAT_VOC = 0x080000, /* VOC files. */ + SF_FORMAT_IRCAM = 0x0A0000, /* Berkeley/IRCAM/CARL */ + SF_FORMAT_W64 = 0x0B0000, /* Sonic Foundry's 64 bit RIFF/WAV */ + SF_FORMAT_MAT4 = 0x0C0000, /* Matlab (tm) V4.2 / GNU Octave 2.0 */ + SF_FORMAT_MAT5 = 0x0D0000, /* Matlab (tm) V5.0 / GNU Octave 2.1 */ + SF_FORMAT_PVF = 0x0E0000, /* Portable Voice Format */ + SF_FORMAT_XI = 0x0F0000, /* Fasttracker 2 Extended Instrument */ + SF_FORMAT_HTK = 0x100000, /* HMM Tool Kit format */ + SF_FORMAT_SDS = 0x110000, /* Midi Sample Dump Standard */ + SF_FORMAT_AVR = 0x120000, /* Audio Visual Research */ + SF_FORMAT_WAVEX = 0x130000, /* MS WAVE with WAVEFORMATEX */ + SF_FORMAT_SD2 = 0x160000, /* Sound Designer 2 */ + SF_FORMAT_FLAC = 0x170000, /* FLAC lossless file format */ + SF_FORMAT_CAF = 0x180000, /* Core Audio File format */ + + /* Subtypes from here on. */ + + SF_FORMAT_PCM_S8 = 0x0001, /* Signed 8 bit data */ + SF_FORMAT_PCM_16 = 0x0002, /* Signed 16 bit data */ + SF_FORMAT_PCM_24 = 0x0003, /* Signed 24 bit data */ + SF_FORMAT_PCM_32 = 0x0004, /* Signed 32 bit data */ + + SF_FORMAT_PCM_U8 = 0x0005, /* Unsigned 8 bit data (WAV and RAW only) */ + + SF_FORMAT_FLOAT = 0x0006, /* 32 bit float data */ + SF_FORMAT_DOUBLE = 0x0007, /* 64 bit float data */ + + SF_FORMAT_ULAW = 0x0010, /* U-Law encoded. */ + SF_FORMAT_ALAW = 0x0011, /* A-Law encoded. */ + SF_FORMAT_IMA_ADPCM = 0x0012, /* IMA ADPCM. */ + SF_FORMAT_MS_ADPCM = 0x0013, /* Microsoft ADPCM. */ + + SF_FORMAT_GSM610 = 0x0020, /* GSM 6.10 encoding. */ + SF_FORMAT_VOX_ADPCM = 0x0021, /* OKI / Dialogix ADPCM */ + + SF_FORMAT_G721_32 = 0x0030, /* 32kbs G721 ADPCM encoding. */ + SF_FORMAT_G723_24 = 0x0031, /* 24kbs G723 ADPCM encoding. */ + SF_FORMAT_G723_40 = 0x0032, /* 40kbs G723 ADPCM encoding. */ + + SF_FORMAT_DWVW_12 = 0x0040, /* 12 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_16 = 0x0041, /* 16 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_24 = 0x0042, /* 24 bit Delta Width Variable Word encoding. */ + SF_FORMAT_DWVW_N = 0x0043, /* N bit Delta Width Variable Word encoding. */ + + SF_FORMAT_DPCM_8 = 0x0050, /* 8 bit differential PCM (XI only) */ + SF_FORMAT_DPCM_16 = 0x0051, /* 16 bit differential PCM (XI only) */ + + /* Endian-ness options. */ + + SF_ENDIAN_FILE = 0x00000000, /* Default file endian-ness. */ + SF_ENDIAN_LITTLE = 0x10000000, /* Force little endian-ness. */ + SF_ENDIAN_BIG = 0x20000000, /* Force big endian-ness. */ + SF_ENDIAN_CPU = 0x30000000, /* Force CPU endian-ness. */ + + SF_FORMAT_SUBMASK = 0x0000FFFF, + SF_FORMAT_TYPEMASK = 0x0FFF0000, + SF_FORMAT_ENDMASK = 0x30000000 +} ; + +/* +** The following are the valid command numbers for the sf_command() +** interface. The use of these commands is documented in the file +** command.html in the doc directory of the source code distribution. +*/ + +enum +{ SFC_GET_LIB_VERSION = 0x1000, + SFC_GET_LOG_INFO = 0x1001, + + SFC_GET_NORM_DOUBLE = 0x1010, + SFC_GET_NORM_FLOAT = 0x1011, + SFC_SET_NORM_DOUBLE = 0x1012, + SFC_SET_NORM_FLOAT = 0x1013, + SFC_SET_SCALE_FLOAT_INT_READ = 0x1014, + + SFC_GET_SIMPLE_FORMAT_COUNT = 0x1020, + SFC_GET_SIMPLE_FORMAT = 0x1021, + + SFC_GET_FORMAT_INFO = 0x1028, + + SFC_GET_FORMAT_MAJOR_COUNT = 0x1030, + SFC_GET_FORMAT_MAJOR = 0x1031, + SFC_GET_FORMAT_SUBTYPE_COUNT = 0x1032, + SFC_GET_FORMAT_SUBTYPE = 0x1033, + + SFC_CALC_SIGNAL_MAX = 0x1040, + SFC_CALC_NORM_SIGNAL_MAX = 0x1041, + SFC_CALC_MAX_ALL_CHANNELS = 0x1042, + SFC_CALC_NORM_MAX_ALL_CHANNELS = 0x1043, + SFC_GET_SIGNAL_MAX = 0x1044, + SFC_GET_MAX_ALL_CHANNELS = 0x1045, + + SFC_SET_ADD_PEAK_CHUNK = 0x1050, + + SFC_UPDATE_HEADER_NOW = 0x1060, + SFC_SET_UPDATE_HEADER_AUTO = 0x1061, + + SFC_FILE_TRUNCATE = 0x1080, + + SFC_SET_RAW_START_OFFSET = 0x1090, + + SFC_SET_DITHER_ON_WRITE = 0x10A0, + SFC_SET_DITHER_ON_READ = 0x10A1, + + SFC_GET_DITHER_INFO_COUNT = 0x10A2, + SFC_GET_DITHER_INFO = 0x10A3, + + SFC_GET_EMBED_FILE_INFO = 0x10B0, + + SFC_SET_CLIPPING = 0x10C0, + SFC_GET_CLIPPING = 0x10C1, + + SFC_GET_INSTRUMENT = 0x10D0, + SFC_SET_INSTRUMENT = 0x10D1, + + SFC_GET_LOOP_INFO = 0x10E0, + + SFC_GET_BROADCAST_INFO = 0x10F0, + SFC_SET_BROADCAST_INFO = 0x10F1, + + /* Following commands for testing only. */ + SFC_TEST_IEEE_FLOAT_REPLACE = 0x6001, + + /* + ** SFC_SET_ADD_* values are deprecated and will disappear at some + ** time in the future. They are guaranteed to be here up to and + ** including version 1.0.8 to avoid breakage of existng software. + ** They currently do nothing and will continue to do nothing. + */ + SFC_SET_ADD_DITHER_ON_WRITE = 0x1070, + SFC_SET_ADD_DITHER_ON_READ = 0x1071 +} ; + + +/* +** String types that can be set and read from files. Not all file types +** support this and even the file types which support one, may not support +** all string types. +*/ + +enum +{ SF_STR_TITLE = 0x01, + SF_STR_COPYRIGHT = 0x02, + SF_STR_SOFTWARE = 0x03, + SF_STR_ARTIST = 0x04, + SF_STR_COMMENT = 0x05, + SF_STR_DATE = 0x06 +} ; + +/* +** Use the following as the start and end index when doing metadata +** transcoding. +*/ + +#define SF_STR_FIRST SF_STR_TITLE +#define SF_STR_LAST SF_STR_DATE + +enum +{ /* True and false */ + SF_FALSE = 0, + SF_TRUE = 1, + + /* Modes for opening files. */ + SFM_READ = 0x10, + SFM_WRITE = 0x20, + SFM_RDWR = 0x30 +} ; + +/* Public error values. These are guaranteed to remain unchanged for the duration +** of the library major version number. +** There are also a large number of private error numbers which are internal to +** the library which can change at any time. +*/ + +enum +{ SF_ERR_NO_ERROR = 0, + SF_ERR_UNRECOGNISED_FORMAT = 1, + SF_ERR_SYSTEM = 2, + SF_ERR_MALFORMED_FILE = 3, + SF_ERR_UNSUPPORTED_ENCODING = 4 +} ; + +/* A SNDFILE* pointer can be passed around much like stdio.h's FILE* pointer. */ + +typedef struct SNDFILE_tag SNDFILE ; + +/* The following typedef is system specific and is defined when libsndfile is. +** compiled. sf_count_t can be one of loff_t (Linux), off_t (*BSD), +** off64_t (Solaris), __int64_t (Win32) etc. +*/ + +typedef __int64 sf_count_t ; + +#define SF_COUNT_MAX 0x7FFFFFFFFFFFFFFFLL + +/* A pointer to a SF_INFO structure is passed to sf_open_read () and filled in. +** On write, the SF_INFO structure is filled in by the user and passed into +** sf_open_write (). +*/ + +struct SF_INFO +{ sf_count_t frames ; /* Used to be called samples. Changed to avoid confusion. */ + int samplerate ; + int channels ; + int format ; + int sections ; + int seekable ; +} ; + +typedef struct SF_INFO SF_INFO ; + +/* The SF_FORMAT_INFO struct is used to retrieve information about the sound +** file formats libsndfile supports using the sf_command () interface. +** +** Using this interface will allow applications to support new file formats +** and encoding types when libsndfile is upgraded, without requiring +** re-compilation of the application. +** +** Please consult the libsndfile documentation (particularly the information +** on the sf_command () interface) for examples of its use. +*/ + +typedef struct +{ int format ; + const char *name ; + const char *extension ; +} SF_FORMAT_INFO ; + +/* +** Enums and typedefs for adding dither on read and write. +** See the html documentation for sf_command(), SFC_SET_DITHER_ON_WRITE +** and SFC_SET_DITHER_ON_READ. +*/ + +enum +{ SFD_DEFAULT_LEVEL = 0, + SFD_CUSTOM_LEVEL = 0x40000000, + + SFD_NO_DITHER = 500, + SFD_WHITE = 501, + SFD_TRIANGULAR_PDF = 502 +} ; + +typedef struct +{ int type ; + double level ; + const char *name ; +} SF_DITHER_INFO ; + +/* Struct used to retrieve information about a file embedded within a +** larger file. See SFC_GET_EMBED_FILE_INFO. +*/ + +typedef struct +{ sf_count_t offset ; + sf_count_t length ; +} SF_EMBED_FILE_INFO ; + +/* +** Structs used to retrieve music sample information from a file. +*/ + +enum +{ /* + ** The loop mode field in SF_INSTRUMENT will be one of the following. + */ + SF_LOOP_NONE = 800, + SF_LOOP_FORWARD, + SF_LOOP_BACKWARD, + SF_LOOP_ALTERNATING +} ; + +typedef struct +{ int gain ; + char basenote, detune ; + char velocity_lo, velocity_hi ; + char key_lo, key_hi ; + int loop_count ; + + struct + { int mode ; + unsigned int start ; + unsigned int end ; + unsigned int count ; + } loops [16] ; /* make variable in a sensible way */ +} SF_INSTRUMENT ; + + + +/* Struct used to retrieve loop information from a file.*/ +typedef struct +{ + short time_sig_num ; /* any positive integer > 0 */ + short time_sig_den ; /* any positive power of 2 > 0 */ + int loop_mode ; /* see SF_LOOP enum */ + + int num_beats ; /* this is NOT the amount of quarter notes !!!*/ + /* a full bar of 4/4 is 4 beats */ + /* a full bar of 7/8 is 7 beats */ + + float bpm ; /* suggestion, as it can be calculated using other fields:*/ + /* file's lenght, file's sampleRate and our time_sig_den*/ + /* -> bpms are always the amount of _quarter notes_ per minute */ + + int root_key ; /* MIDI note, or -1 for None */ + int future [6] ; +} SF_LOOP_INFO ; + + +/* Struct used to retrieve broadcast (EBU) information from a file. +** Strongly (!) based on EBU "bext" chunk format used in Broadcast WAVE. +*/ +typedef struct +{ char description [256] ; + char originator [32] ; + char originator_reference [32] ; + char origination_date [10] ; + char origination_time [8] ; + int time_reference_low ; + int time_reference_high ; + short version ; + char umid [64] ; + char reserved [190] ; + unsigned int coding_history_size ; + char coding_history [256] ; +} SF_BROADCAST_INFO ; + +typedef sf_count_t (*sf_vio_get_filelen) (void *user_data) ; +typedef sf_count_t (*sf_vio_seek) (sf_count_t offset, int whence, void *user_data) ; +typedef sf_count_t (*sf_vio_read) (void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_write) (const void *ptr, sf_count_t count, void *user_data) ; +typedef sf_count_t (*sf_vio_tell) (void *user_data) ; + +struct SF_VIRTUAL_IO +{ sf_vio_get_filelen get_filelen ; + sf_vio_seek seek ; + sf_vio_read read ; + sf_vio_write write ; + sf_vio_tell tell ; +} ; + +typedef struct SF_VIRTUAL_IO SF_VIRTUAL_IO ; + +/* Open the specified file for read, write or both. On error, this will +** return a NULL pointer. To find the error number, pass a NULL SNDFILE +** to sf_perror () or sf_error_str (). +** All calls to sf_open() should be matched with a call to sf_close(). +*/ + +SNDFILE* sf_open (const char *path, int mode, SF_INFO *sfinfo) ; + +/* Use the existing file descriptor to create a SNDFILE object. If close_desc +** is TRUE, the file descriptor will be closed when sf_close() is called. If +** it is FALSE, the descritor will not be closed. +** When passed a descriptor like this, the library will assume that the start +** of file header is at the current file offset. This allows sound files within +** larger container files to be read and/or written. +** On error, this will return a NULL pointer. To find the error number, pass a +** NULL SNDFILE to sf_perror () or sf_error_str (). +** All calls to sf_open_fd() should be matched with a call to sf_close(). + +*/ + +SNDFILE* sf_open_fd (int fd, int mode, SF_INFO *sfinfo, int close_desc) ; + +SNDFILE* sf_open_virtual (SF_VIRTUAL_IO *sfvirtual, int mode, SF_INFO *sfinfo, void *user_data) ; + +/* sf_error () returns a error number which can be translated to a text +** string using sf_error_number(). +*/ + +int sf_error (SNDFILE *sndfile) ; + +/* sf_strerror () returns to the caller a pointer to the current error message for +** the given SNDFILE. +*/ + +const char* sf_strerror (SNDFILE *sndfile) ; + +/* sf_error_number () allows the retrieval of the error string for each internal +** error number. +** +*/ + +const char* sf_error_number (int errnum) ; + +/* The following three error functions are deprecated but they will remain in the +** library for the forseeable future. The function sf_strerror() should be used +** in their place. +*/ + +int sf_perror (SNDFILE *sndfile) ; +int sf_error_str (SNDFILE *sndfile, char* str, size_t len) ; + + +/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ + +int sf_command (SNDFILE *sndfile, int command, void *data, int datasize) ; + +/* Return TRUE if fields of the SF_INFO struct are a valid combination of values. */ + +int sf_format_check (const SF_INFO *info) ; + +/* Seek within the waveform data chunk of the SNDFILE. sf_seek () uses +** the same values for whence (SEEK_SET, SEEK_CUR and SEEK_END) as +** stdio.h function fseek (). +** An offset of zero with whence set to SEEK_SET will position the +** read / write pointer to the first data sample. +** On success sf_seek returns the current position in (multi-channel) +** samples from the start of the file. +** Please see the libsndfile documentation for moving the read pointer +** separately from the write pointer on files open in mode SFM_RDWR. +** On error all of these functions return -1. +*/ + +sf_count_t sf_seek (SNDFILE *sndfile, sf_count_t frames, int whence) ; + +/* Functions for retrieving and setting string data within sound files. +** Not all file types support this features; AIFF and WAV do. For both +** functions, the str_type parameter must be one of the SF_STR_* values +** defined above. +** On error, sf_set_string() returns non-zero while sf_get_string() +** returns NULL. +*/ + +int sf_set_string (SNDFILE *sndfile, int str_type, const char* str) ; + +const char* sf_get_string (SNDFILE *sndfile, int str_type) ; + +/* Functions for reading/writing the waveform data of a sound file. +*/ + +sf_count_t sf_read_raw (SNDFILE *sndfile, void *ptr, sf_count_t bytes) ; +sf_count_t sf_write_raw (SNDFILE *sndfile, const void *ptr, sf_count_t bytes) ; + +/* Functions for reading and writing the data chunk in terms of frames. +** The number of items actually read/written = frames * number of channels. +** sf_xxxx_raw read/writes the raw data bytes from/to the file +** sf_xxxx_short passes data in the native short format +** sf_xxxx_int passes data in the native int format +** sf_xxxx_float passes data in the native float format +** sf_xxxx_double passes data in the native double format +** All of these read/write function return number of frames read/written. +*/ + +sf_count_t sf_readf_short (SNDFILE *sndfile, short *ptr, sf_count_t frames) ; +sf_count_t sf_writef_short (SNDFILE *sndfile, const short *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_int (SNDFILE *sndfile, int *ptr, sf_count_t frames) ; +sf_count_t sf_writef_int (SNDFILE *sndfile, const int *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_float (SNDFILE *sndfile, float *ptr, sf_count_t frames) ; +sf_count_t sf_writef_float (SNDFILE *sndfile, const float *ptr, sf_count_t frames) ; + +sf_count_t sf_readf_double (SNDFILE *sndfile, double *ptr, sf_count_t frames) ; +sf_count_t sf_writef_double (SNDFILE *sndfile, const double *ptr, sf_count_t frames) ; + +/* Functions for reading and writing the data chunk in terms of items. +** Otherwise similar to above. +** All of these read/write function return number of items read/written. +*/ + +sf_count_t sf_read_short (SNDFILE *sndfile, short *ptr, sf_count_t items) ; +sf_count_t sf_write_short (SNDFILE *sndfile, const short *ptr, sf_count_t items) ; + +sf_count_t sf_read_int (SNDFILE *sndfile, int *ptr, sf_count_t items) ; +sf_count_t sf_write_int (SNDFILE *sndfile, const int *ptr, sf_count_t items) ; + +sf_count_t sf_read_float (SNDFILE *sndfile, float *ptr, sf_count_t items) ; +sf_count_t sf_write_float (SNDFILE *sndfile, const float *ptr, sf_count_t items) ; + +sf_count_t sf_read_double (SNDFILE *sndfile, double *ptr, sf_count_t items) ; +sf_count_t sf_write_double (SNDFILE *sndfile, const double *ptr, sf_count_t items) ; + +/* Close the SNDFILE and clean up all memory allocations associated with this +** file. +** Returns 0 on success, or an error number. +*/ + +int sf_close (SNDFILE *sndfile) ; + +/* If the file is opened SFM_WRITE or SFM_RDWR, call fsync() on the file +** to force the writing of data to disk. If the file is opened SFM_READ +** no action is taken. +*/ + +void sf_write_sync (SNDFILE *sndfile) ; + +#ifdef __cplusplus +} /* extern "C" */ +#endif /* __cplusplus */ + +#endif /* SNDFILE_H */ diff --git a/MUNGA_L4/sos/SOSMAWE.C b/MUNGA_L4/sos/SOSMAWE.C new file mode 100644 index 0000000..1a122af --- /dev/null +++ b/MUNGA_L4/sos/SOSMAWE.C @@ -0,0 +1,443 @@ +/**************************************************************************** + + File : sosmawe.c + + Purpose : Module to handle AWE32 .SBK file uploads + + Date : 1-20-95 + + Programmer(s) : Don Fowler + + Last Updated : 1-29-95 + +**************************************************************************** + Copyright(c) 1992,1995 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include "sosm.h" + +WORD sosMIDIAWE32SetSBKFile( WORD, PSTR ); +WORD sosMIDIAWE32ReleaseSBKFiles( WORD ); +WORD sosMIDIAWE32NoteOn( WORD, WORD, WORD, WORD, WORD, WORD ); +WORD sosMIDIAWE32NoteOff( WORD, WORD, WORD ); + +// maximum number of .SBK files that can be set on the chip +#define _MAX_SBKS 0x10 + +// offset into slot list for .SBK files to start +#define _SBK_SLOT_OFFSET 0x01 + +// size of buffer needed to read in a chunk of .SBK file +#define _READ_BUFFER_SIZE 0x2000 + +// pointer to preset data for awe32 +#ifdef BORLAND +PSTR _lpSOSMIDIAwe32PresetBuffer[ _SOS_MIDI_MAX_DRIVERS ][ _MAX_SBKS ] = { +#else +LPSTR _lpSOSMIDIAwe32PresetBuffer[ _SOS_MIDI_MAX_DRIVERS ][ _MAX_SBKS ] = { +#endif + + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL }, + { _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, + _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL, _NULL } + + }; + +// index into list of presets to the currently available slot, +// start the index at 0 to leave slot 0 open for general midi +// rom on the AWE32 +WORD _wSOSMIDIAwe32PresetIndex[ _SOS_MIDI_MAX_DRIVERS ] = { + + _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET, + _SBK_SLOT_OFFSET, _SBK_SLOT_OFFSET + }; + +/*************************************************************************** + +Function : WORD sosMIDIAWE32SetSBKFile + +Parameters : WORD hDriver + Handle of SOS driver to set SBK file on. + PSTR szFileName + Name of .SBK file to set. + +Returns : -1 if error; otherwise, slot that the .SBK file was + assigned to on the AWE32. + +Description : Stream a .SBK file onto the awe32 and return the slot + streamed to. + +****************************************************************************/ + +WORD sosMIDIAWE32SetSBKFile( WORD hDriver, PSTR szFileName ) +{ + WORD wIndex; + WORD hFile; + WORD wReadSize; + PSTR pDataPtr; +#ifdef BORLAND + SFAR lpTemp; +#endif + + // attempt to find a slot to use for the .SBK file + if( _wSOSMIDIAwe32PresetIndex[ hDriver ] == ( _MAX_SBKS - 1 ) ) + return( -1 ); + + // attempt to open the sbk file + if( ( hFile = open( ( const char * )szFileName, O_RDONLY | O_BINARY ) ) == -1 ) + return( -1 ); + + // attempt to allocate a buffer to use for transfer + if( !( pDataPtr = ( PSTR )malloc( _READ_BUFFER_SIZE ) ) ) + { + // close the file + close( hFile ); + + // return an error + return( -1 ); + } + + // open the awe32 stream +#ifdef BORLAND + if( ( wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 5 ], + lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 5 ]( _NULL, + _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // free the previously allocated memory + free( pDataPtr ); + + // close the file + close( hFile ); + + // return error + return( -1 ); + } + + // read in a chunk of data from the file + if( read( hFile, pDataPtr, wReadSize ) == -1 ) + return( -1 ); + + // get the sample data seek location +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = pDataPtr; + if( ( wIndex = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 8 ], + lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wIndex = _lpSOSMIDIDrvFunction[ hDriver ][ 8 ]( ( LPSTR )pDataPtr, + _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // free the previously allocated memory + free( pDataPtr ); + + // close the file + close( hFile ); + + // return error + return( -1 ); + } + + // seek the file to the sample location + if( lseek( hFile, wIndex, SEEK_SET ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -1 ); + } + + // send chunks of data to the driver + do + { + // read in a chunk of data from the file + if( read( hFile, pDataPtr, wReadSize ) == -1 ) + return( -1 ); + + // send the data to the driver +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = pDataPtr; + if( ( wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ] + [ 6 ], lpTemp, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#else + if( ( wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 6 ]( + ( LPSTR )pDataPtr, _wSOSMIDIAwe32PresetIndex[ hDriver ], 0x00 ) ) == -1 ) +#endif + { + // close the file + close( hFile ); + + // free the memory + free( pDataPtr ); + + // return an error + return( -1 ); + } + } while( wReadSize ); + + // free the temporary memory buffer + free( pDataPtr ); + + // get the preset data size +#ifdef BORLAND + wReadSize = sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 7 ], + lpTemp, 0x00, 0x00 ); +#else + wReadSize = _lpSOSMIDIDrvFunction[ hDriver ][ 7 ]( _NULL, 0x00, 0x00 ); +#endif + + // get the preset location in the file +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = &wIndex; + sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ], lpTemp, + 0x00, 0x00 ); +#else + _lpSOSMIDIDrvFunction[ hDriver ][ 9 ]( ( LPSTR )&wIndex, 0x00, 0x00 ); +#endif + + // allocate the memory for the preset information +#ifdef BORLAND + if( !( _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] = + ( PSTR )malloc( wReadSize ) ) ) +#else + if( !( _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] = + ( LPSTR )malloc( wReadSize ) ) ) +#endif + { + // close the file + close( hFile ); + + // return an error + return( -1 ); + } + + // seek the file to the preset location + if( lseek( hFile, wIndex, SEEK_SET ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -1 ); + } + + // read in the preset information + if( read( hFile, ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ + _wSOSMIDIAwe32PresetIndex[ hDriver ] ], wReadSize ) == -1 ) + { + // close the file + close( hFile ); + + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // return an error + return( -1 ); + } + + // send the preset information to the driver +#ifdef BORLAND + lpTemp.sel = getDS(); + lpTemp.off = _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ]; + if( ( sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 10 ], + lpTemp, 0x00, 0x00 ) ) == -1 ) +#else + if( ( _lpSOSMIDIDrvFunction[ hDriver ][ 10 ]( ( LPSTR ) + _lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ], 0x00, 0x00 ) ) == -1 ) +#endif + { + // free the preset memory + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ _wSOSMIDIAwe32PresetIndex[ hDriver ] ] ); + + // close the file + close( hFile ); + + // return an error + return( -1 ); + } + + // close the SBK file + close( hFile ); + + // increment the preset buffer index to the next available slot + _wSOSMIDIAwe32PresetIndex[ hDriver ]++; + + // return no error + return( _wSOSMIDIAwe32PresetIndex[ hDriver ] ); +} + +/*************************************************************************** + +Function : WORD sosMIDIAWE32ReleaseAllSBKFiles + +Parameters : WORD hDriver + Handle of SOS driver to release .SBK files from + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Release all of the memory associated to the .SBK files + uploaded to the awe32. + +****************************************************************************/ + +WORD sosMIDIAWE32ReleaseSBKFiles( WORD hDriver ) +{ + WORD wIndex; +#ifdef BORLAND + SFAR lpTemp; +#endif + + // call the driver to release all of the .SBK files +#ifdef BORLAND + if( sosMIDIDRVCall32Func( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ], lpTemp, + 0x01, 0x00 ) == -1 ) +#else + if( _lpSOSMIDIDrvFunction[ hDriver ][ 9 ]( ( LPSTR )_NULL, 0x01, 0x00 ) + == -1 ) +#endif + return( -1 ); + + // free the memory allocated for the awe32 preset information + for( wIndex = _SBK_SLOT_OFFSET; wIndex < _wSOSMIDIAwe32PresetIndex[ hDriver ]; + wIndex++ ) + free( ( PSTR )_lpSOSMIDIAwe32PresetBuffer[ hDriver ][ wIndex ] ); + + // reset the available slot index + _wSOSMIDIAwe32PresetIndex[ hDriver ] = _SBK_SLOT_OFFSET; + + // return no error + return( _ERR_NO_ERROR ); +} + +/*************************************************************************** + +Function : WORD sosMIDIAWE32NoteOn + +Parameters : WORD hDriver + Handle of SOS driver + WORD wSlot + .SBK file slot to associate patch to + WORD wChannel + Channel to use + WORD wPatch + Patch to use + WORD wNote + MIDI relative pitch to use + WORD wVelocity + Velocity to use + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Turn a note on + +****************************************************************************/ + +WORD sosMIDIAWE32NoteOn( WORD hDriver, WORD wSlot, WORD wChannel, + WORD wPatch, WORD wNote, WORD wVelocity ) +{ + BYTE szMIDIData[ 0x10 ]; + + // setup the midi data structure to associate a slot to a channel + szMIDIData[ 0 ] = 0xb0 | wChannel; + szMIDIData[ 1 ] = 0x00; + szMIDIData[ 2 ] = wSlot; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x03 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x03 ); +#endif + + // select the patch for the channel + szMIDIData[ 0 ] = 0xc0 | wChannel; + szMIDIData[ 1 ] = wPatch; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x02 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x02 ); +#endif + + // turn the note on with the correct pitch and attack + szMIDIData[ 0 ] = 0x90 | wChannel; + szMIDIData[ 1 ] = wNote; + szMIDIData[ 2 ] = wVelocity; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x02 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x02 ); +#endif + + // return no error + return( _ERR_NO_ERROR ); +} + +/*************************************************************************** + +Function : WORD sosMIDIAWE32NoteOff + +Parameters : WORD hDriver + Handle of SOS driver + WORD wChannel + Channel to use + WORD wNote + MIDI relative pitch to use + +Returns : -1 if error; otherwise, _ERR_NO_ERROR + +Description : Turn a note on + +****************************************************************************/ + +WORD sosMIDIAWE32NoteOff( WORD hDriver, WORD wChannel, WORD wNote ) +{ + BYTE szMIDIData[ 0x10 ]; + + // turn the note off + szMIDIData[ 0 ] = 0x90 | wChannel; + szMIDIData[ 1 ] = wNote; + szMIDIData[ 2 ] = 0x00; +#ifdef BORLAND + sosMIDISendMIDIData( hDriver, ( PSTR )szMIDIData, 0x03 ); +#else + sosMIDISendMIDIData( hDriver, ( LPSTR )szMIDIData, 0x03 ); +#endif + + // return no error + return( _ERR_NO_ERROR ); +} + + + + + + + + diff --git a/MUNGA_L4/sos/bc4/SOS.H b/MUNGA_L4/sos/bc4/SOS.H new file mode 100644 index 0000000..c93a675 --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOS.H @@ -0,0 +1,554 @@ +/**************************************************************************** + + File : sos.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_DEFINED +#define _SOS_DEFINED +#include "sosdefs.h" + +#pragma pack(4) + +typedef struct +{ + PSTR off; + WORD sel; +} SFAR; + +// error definition for sound operating system +#define _SOS_ERR -1 + +// number of drivers allowed to be open at one time +#define _SOS_MAX_DRIVERS 5 + +// structure definition for the capabilities +typedef struct _tagCAPABILITIES +{ + BYTE szDeviceName[ 32 ]; // device name + WORD wDeviceVersion; // device version + WORD wBitsPerSample; // bits per sound sample + WORD wChannels; // stereo/mono sound card + WORD wMinRate; // minimum rate + WORD wMaxRate; // maximum rate + WORD wMixerOnBoard; // board contains mixer + WORD wMixerFlags; // mixer capabilities + WORD wFlags; // miscellaneous flags + SFAR lpPortList; // list of usable ports + SFAR lpDMAList; // list of usable dma channels + SFAR lpIRQList; // list of usable irq channels + SFAR lpRateList; // list of usable rates, -1 if any in min to max + WORD fBackground; // foreground or background driver + WORD wDeviceID; // ID for the device + WORD wTimerID; // ID for the timer + +} _SOS_CAPABILITIES; + +// far pointer to the device capabilities structure +typedef _SOS_CAPABILITIES * PSOSDEVICECAPS; + +// flag types for driver +#define _FLAGS_SIGNED 0x8000 + +// devices that can be loaded +#define _SOUND_BLASTER_8_MONO 0xe000 +#define _SOUND_BLASTER_8_ST 0xe001 +#define _SBPRO_8_ST _SOUND_BLASTER_8_ST +#define _SBPRO_8_MONO 0xe00f +#define _SOUND_MASTER_II_8_MONO 0xe002 +#define _MV_PAS_8_MONO 0xe003 +#define _MV_PAS_16_MONO 0xe004 +#define _MV_PAS_8_ST 0xe005 +#define _MV_PAS_16_ST 0xe006 +#define _ADLIB_GOLD_8_ST 0xe007 +#define _ADLIB_GOLD_16_ST 0xe008 +#define _ADLIB_GOLD_8_MONO 0xe009 +#define _ADLIB_GOLD_16_MONO 0xe00a +#define _MICROSOFT_8_MONO 0xe00b +#define _MICROSOFT_8_ST 0xe00c +#define _MICROSOFT_16_MONO 0xe00d +#define _MICROSOFT_16_ST 0xe00e +#define _SOUND_SOURCE_8_MONO_PC 0xe010 +#define _SOUND_SOURCE_8_MONO_TANDY 0xe011 +#define _GENERAL_PORT_8_MONO 0xe012 +#define _GENERAL_PORT_8_MONO_R 0xe013 +#define _SIERRA_8_MONO 0xe014 +#define _SB16_8_MONO 0xe015 +#define _SB16_8_ST 0xe016 +#define _SB16_16_MONO 0xe017 +#define _SB16_16_ST 0xe018 +#define _ESS_AUDIODRIVE_8_MONO 0xe019 +#define _ESS_AUDIODRIVE_8_ST 0xe01a +#define _ESS_AUDIODRIVE_16_MONO 0xe01b +#define _ESS_AUDIODRIVE_16_ST 0xe01c +#define _SOUNDSCAPE_8_MONO 0xe01d +#define _SOUNDSCAPE_8_ST 0xe01e +#define _SOUNDSCAPE_16_MONO 0xe01f +#define _SOUNDSCAPE_16_ST 0xe020 +#define _RAP10_8_MONO 0xe021 +#define _RAP10_16_MONO 0xe022 +#define _GUS_8_MONO 0xe023 +#define _GUS_8_ST 0xe024 +#define _GUS_16_MONO 0xe025 +#define _GUS_16_ST 0xe026 +#define _GUS_MAX_8_MONO 0xe027 +#define _GUS_MAX_8_ST 0xe028 +#define _GUS_MAX_16_MONO 0xe029 +#define _GUS_MAX_16_ST 0xe02a +#define _WAVEJAMMER_8_MONO 0xe02b +#define _WAVEJAMMER_8_ST 0xe02c +#define _WAVEJAMMER_16_MONO 0xe02d +#define _WAVEJAMMER_16_ST 0xe02e +#define _TEMPOCS_8_MONO 0xe02f +#define _TEMPOCS_8_ST 0xe030 +#define _TEMPOCS_16_MONO 0xe031 +#define _TEMPOCS_16_ST 0xe032 +#define _WAVEJAMMERCD_8_MONO 0xe033 +#define _WAVEJAMMERCD_8_ST 0xe034 +#define _WAVEJAMMERCD_16_MONO 0xe035 +#define _WAVEJAMMERCD_16_ST 0xe036 +#define _SOUND_BLASTER_8_MONO_R 0xe050 +#define _MICROSOFT_8_MONO_R 0xe051 +#define _SOUND_MASTER_II_8_MONO_R 0xe052 +#define _ADLIB_GOLD_8_MONO_R 0xe053 +#define _MV_PAS_8_MONO_R 0xe054 +#define _RAP10_8_MONO_R 0xe058 +#define _RAP10_16_MONO_R 0xe059 +#define _SB16_8_MONO_R 0xe05a +#define _SB16_8_ST_R 0xe05b +#define _SB16_16_MONO_R 0xe05c +#define _SB16_16_ST_R 0xe05d +#define _MV_PAS_16_MONO_R 0xe060 +#define _SOUNDSCAPE_8_MONO_R 0xe061 +#define _SOUNDSCAPE_8_ST_R 0xe062 +#define _SOUNDSCAPE_16_MONO_R 0xe063 +#define _SOUNDSCAPE_16_ST_R 0xe064 +#define _ESS_AUDIODRIVE_8_MONO_R 0xe065 +#define _ESS_AUDIODRIVE_8_ST_R 0xe066 +#define _ESS_AUDIODRIVE_16_MONO_R 0xe067 +#define _ESS_AUDIODRIVE_16_ST_R 0xe068 +#define _SPEECH_THING_8_MONO 0xe090 +#define _YAMAHA_8_MONO 0xe106 +#define _INT_SPEAKER_8_MONO 0xe107 + +// call indexes for the loadable drivers +enum +{ + _DRV_INIT, + _DRV_UNINIT, + _DRV_SETRATE, + _DRV_SETACTION, + _DRV_START, + _DRV_STOP, + _DRV_PAUSE, + _DRV_RESUME, + _DRV_CAPABILITIES, + _DRV_PLAY_FOREGROUND, + _DRV_GET_FILL_INFO, + _DRV_GET_CALL_FUNCTIONS, + _DRV_SET_CALL_FUNCTIONS +}; + +// fill info +typedef struct _tagFillInfo + { + + SFAR lpFillHandler; // pointer to fill handler + SFAR lpDMAFillCount; // pointer to dma count + SFAR lpSampleList; // pointer to sample list + SFAR lpDMAMasterVolume; // pointer to dma count + + } _SOS_FILL_INFO; + +// caps info structure +typedef struct _tagCapsInfo + { + + SFAR lpPortList; // pointer to port list + SFAR lpDMAList; // pointer to DMA list + SFAR lpIRQList; // pointer to IRQ list + SFAR lpRateList; // pointer to rate list + + } _SOS_CAPS_INFO; + +// maximum number of available voice +#define _MAX_VOICES 32 + +// structure definition +typedef struct _tagSAMPLE +{ + SFAR samplePtr; // pointer to data buffer + SFAR sampleData; // pointer to active data + SFAR sampleLoopPtr; // pointer for loop back + + WORD sampleLength; // length of sample + WORD sampleIndex; // index into sample + WORD sampleLoopLength; // length of loop + + WORD sampleBytesLeft; // bytes left to play in sample + + WORD sampleLoopPoint; // byte count for loop point + WORD sampleLoopEndLength; // length of remaining chunk + + short sampleFlags; // control sample + short sampleVolume; // volume control + short sampleID; // sample ID + + short sampleChannel; // channel to play sample on + short sampleLoopCount; // loop count + short sampleLastFill; // last fill position + SFAR sampleCallback; // callback function for sample + + WORD samplePitchAdd; + short samplePitchFraction; + + short samplePort; // port to use for non-dma digitized + + WORD sampleTotalBytes; + WORD sampleByteLength; + + short samplePanLocation; + short samplePanSpeed; + short samplePanDirection; + short samplePanStart; + short samplePanEnd; + + short sampleDelayBytes; + short sampleDelayRepeat; + + WORD sampleADPCMPredicted; + short sampleADPCMIndex; + + short sampleRootNoteMIDI; + + WORD sampleTemp1; + +} _SOS_SAMPLE; + +// enumeration for left or right channel +enum +{ + _LEFT_CHANNEL, + _RIGHT_CHANNEL, + _CENTER_CHANNEL, + _INTERLEAVED +}; + +// enumeration for foreground and background +enum +{ + _FOREGROUND, + _BACKGROUND +}; + +// defines for the sample flags +#define _ACTIVE 0x8000 +#define _LOOPING 0x4000 +#define _FIRST_TIME 0x2000 +#define _PENDING_RELEASE 0x1000 +#define _CONTINUE_BLOCK 0x0800 +#define _PITCH_SHIFT 0x0400 +#define _PANNING 0x0200 +#define _VOLUME 0x0100 +#define _TRANSLATE16TO8 0x0080 +#define _STAGE_LOOP 0x0040 +#define _TRANSLATE8TO16 0x0020 +#define _STEREOTOMONO 0x0010 + +// defines for the wParam flags +#define _SINGLE_SAMPLE 0x01 + +#define _SOS_DCAPS_AUTO_REINIT 0x01 +#define _SOS_DCAPS_MPU_401 0x02 +#define _SOS_DCAPS_OPL2 0x04 +#define _SOS_DCAPS_OPL3 0x08 +#define _SOS_DCAPS_OPL4 0x10 +#define _SOS_DCAPS_WAVETABLE 0x20 +#define _SOS_DCAPS_DL_SAMPLES 0x40 +#define _SOS_DCAPS_FIFO_DEVICE 0x80 +#define _SOS_DCAPS_ENV_NEEDED 0x100 +#define _SOS_DCAPS_PSEUDO_DMA1 0x200 +#define _SOS_DCAPS_SIGNED_DATA 0x8000 + +// file header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // number of drivers in the file + WORD wDrivers; + + // offset of first driver + WORD lOffset; + + // size of the file + WORD lFileSize; + +} _FILEHEADER; + +// driver header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // offset of next driver + WORD lNextDriver; + + // size of current driver + WORD wSize; + + // id for the current device + WORD wDeviceID; + + // id for the type of DOS extender + WORD wExtenderType; + +} _DRIVERHEADER; + +// device hardware information +typedef struct +{ + // port to be used + WORD wPort; + + // irq to use + WORD wIRQ; + + // dma channel to se + WORD wDMA; + + // extra parameter + WORD wParam; + +} _SOS_HARDWARE; + +// structure definition for start sample +typedef struct +{ + // pointer to sample + PSTR pSamplePtr; + WORD wFiller2; + + // size of the sample + WORD dwSampleSize; + + // number of times to loop the sample -1 is infinite + WORD wLoopCount; + + // channel to play sample on + WORD wChannel; + + // volume to play sample at + WORD wVolume; + + // id for the sample + WORD wSampleID; + + // far pointer to the callback function + VOID ( cdecl *pCallback )( WORD, WORD, WORD ); + WORD wFiller1; + + // port to use if driver is a non-dma background driver + WORD wSamplePort; + + // flags field + WORD wSampleFlags; + + // total length of sample including loops, etc.. + WORD dwSampleByteLength; + + // loop point for the sample + WORD dwSampleLoopPoint; + WORD dwSampleLoopLength; + + // pitch shifting components + WORD dwSamplePitchAdd; + WORD wSamplePitchFraction; + + // pan components + WORD wSamplePanLocation; + WORD wSamplePanSpeed; + WORD wSamplePanDirection; + WORD wSamplePanStart; + WORD wSamplePanEnd; + + // delay parts + WORD wSampleDelayBytes; + WORD wSampleDelayRepeat; + + // compression components + WORD dwSampleADPCMPredicted; + WORD wSampleADPCMIndex; + + // root note for pitch shifting + WORD wSampleRootNoteMIDI; + + // filler for future upgrades + WORD dwSampleTemp1; + WORD dwSampleTemp2; + WORD dwSampleTemp3; + +} _SOS_START_SAMPLE; + +// structure for initializing a driver +typedef struct +{ + WORD wBufferSize; + SFAR lpBuffer; + BOOL wAllocateBuffer; + WORD wSampleRate; + WORD wParam; + LONG dwParam; + SFAR lpFillHandler; + SFAR lpDriverMemory; + SFAR lpDriverMemoryCS; + SFAR lpTimerMemory; + SFAR lpTimerMemoryCS; + VOID ( *pFillHandler )( VOID ); + WORD wTimerID; + WORD wPhysical; + +} _SOS_INIT_DRIVER; + +// define for the timer types to use +#define _SOS_NORMAL_TIMER 0x00 + +// enumeration for the timer types +enum +{ + _TIMER_8_MONO = 0x1000, + _TIMER_8_ST, + _TIMER_16_MONO, + _TIMER_16_ST, + _TIMER_8_MONO_ULAW, + _TIMER_8_ST_ULAW, + _TIMER_16_MONO_ULAW, + _TIMER_16_ST_ULAW, + _TIMER_8_MONO_REC, + _TIMER_8_MONO_ULAW_REC, + _TIMER_UNDEFINED_1, + _TIMER_UNDEFINED_2, + _TIMER_UNDEFINED_3, + _TIMER_UNDEFINED_4, + _TIMER_UNDEFINED_5, + _TIMER_UNDEFINED_6, + _TIMER_UNDEFINED_7, + _TIMER_UNDEFINED_8, + _TIMER_UNDEFINED_9, + _TIMER_UNDEFINED_A, + _TIMER_UNDEFINED_B, + _TIMER_UNDEFINED_C, + _TIMER_UNDEFINED_D, + _TIMER_UNDEFINED_E, + _TIMER_UNDEFINED_F, + _TIMER_UNDEFINED_10, + _TIMER_UNDEFINED_11, + _TIMER_UNDEFINED_12, + _TIMER_UNDEFINED_13, + _TIMER_UNDEFINED_14, + _TIMER_UNDEFINED_15, + _TIMER_UNDEFINED_16, + _TIMER_8_SOUND_SOURCE, + _TIMER_8_SOUND_SOURCE_TANDY, + _TIMER_8_GENERAL_PORT, + _TIMER_8_GENERAL_PORT_REC +}; + +// define for no slots available +#define _ERR_NO_SLOTS ( WORD )-1 + +// error codes for the system +enum +{ + _ERR_NO_ERROR, + _ERR_DRIVER_NOT_LOADED, + _ERR_INVALID_POINTER, + _ERR_DETECT_INITIALIZED, + _ERR_FAIL_ON_FILE_OPEN, + _ERR_MEMORY_FAIL, + _ERR_INVALID_DRIVER_ID, + _ERR_NO_DRIVER_FOUND, + _ERR_DETECTION_FAILURE, + _ERR_DRIVER_LOADED, + _ERR_INVALID_HANDLE, + _ERR_NO_HANDLES, + _ERR_PAUSED, + _ERR_NOT_PAUSED, + _ERR_INVALID_DATA, + _ERR_DRV_FILE_FAIL, + _ERR_INVALID_PORT, + _ERR_INVALID_IRQ, + _ERR_INVALID_DMA, + _ERR_INVALID_DMA_IRQ +}; + +// maximum number of timer events that can be registered +#define _TIMER_MAX_EVENTS 0x10 + +// flags for the debugging system +#define _SOS_DEBUG_NORMAL 0x0000 +#define _SOS_DEBUG_NO_TIMER 0x0001 +#define _SOS_TIMER_DPMI 0x0002 + +// define for types of DOS extenders +#define _SOS_RATIONAL 0x8000 +#define _SOS_FLASHTECK 0x4000 + +// defines for the types of timers for different +// dos extenders +#define _SOS_TIMER_NEAR 0x8000 +#define _SOS_TIMER_FAR 0x4000 + +// values for callback information +enum +{ + _SAMPLE_PROCESSED, + _SAMPLE_LOOPING, + _SAMPLE_DONE +}; + +// define for special 18.2 callback rate to dos +#define _TIMER_DOS_RATE 0xff00 + +#pragma pack() + +#pragma pack( 1 ) +typedef struct +{ + unsigned region_size; + unsigned offset; + unsigned segment; + unsigned short number_available; + unsigned short number_used; + unsigned page0; + +} EVDS_STRUCT; + +typedef struct +{ + unsigned region_size; + unsigned offset; + unsigned short segment; + unsigned short ID; + unsigned physical; + +} VDS_STRUCT; + +#pragma pack() + +#include "sosdata.h" +#include "sosfnct.h" + +#endif diff --git a/MUNGA_L4/sos/bc4/SOS.INC b/MUNGA_L4/sos/bc4/SOS.INC new file mode 100644 index 0000000..a465464 --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOS.INC @@ -0,0 +1,192 @@ +;*************************************************************************** +; general equates +;*************************************************************************** +_MAX_VOICES equ 32 +_ERR_NO_SLOTS equ -1 +_ERR_NO_ERROR equ 0 +_ERR_INVALID_HANDLE equ 10 +_TRUE equ 1 +_FALSE equ 0 + +;*************************************************************************** +; macro definitions follow +;*************************************************************************** + +; macro for function start +CFuncStart macro + + push ebx + push ecx + push edx + push esi + push edi + push es + + endm + +; macro for function end +CFuncEnd macro + + pop es + pop edi + pop esi + pop edx + pop ecx + pop ebx + + endm + +;*************************************************************************** +; equates for sample flags +;*************************************************************************** +_ACTIVE equ 8000h +_LOOPING equ 4000h +_FIRST_TIME equ 2000h +_PENDING_RELEASE equ 1000h +_CONTINUE_BLOCK equ 0800h +_PITCH_SHIFT equ 0400h +_PANNING equ 0200h +_VOLUME equ 0100h +_TRANSLATE16TO8 equ 0080h +_STAGE_LOOP equ 0040h +_TRANSLATE8TO16 equ 0020h +_STEREOTOMONO equ 0010h +_SKIP_PROCESSED_CB equ 0008h +_SKIP_LOOP_CB equ 0004h +_SKIP_DONE_CB equ 0002h + +;*************************************************************************** +; data stucture definitions follow. +;*************************************************************************** + +_SOS_START_SAMPLE struc + + ; pointer to sample data + pSamplePtr dd 0 + dd 0 + + ; size of the sample + dwSampleSize dd 0 + + ; loop count + wLoopCount dd 0 + + ; channel + wChannel dd 0 + + ; volume + wVolume dd 0 + + ; sample ID + wSampleID dd 0 + + ; call back + pCallback dd 0 + dd 0 + + ; port + wSamplePort dd 0 + + ; flags + wSampleFlags dd 0 + + ; length in bytes + dwSampleByteLength dd 0 + + ; loop point for sample + dwSampleLoopPoint dd 0 + dwSampleLoopLength dd 0 + + ; pitch shifting components + dwSamplePitchAdd dd 0 + wSamplePitchFraction dd 0 + + ; panning components + wSamplePanLocation dd 0 + wSamplePanSpeed dd 0 + wSamplePanDirection dd 0 + wSamplePanStart dd 0 + wSamplePanEnd dd 0 + + ; delay components + wSampleDelayBytes dd 0 + wSampleDelayRepeat dd 0 + + ; compression components + dwSampleADPCMPredict dd 0 + wSampleADPCMIndex dd 0 + + ; root note for MIDI + wSampleRootNoteMIDI dd 0 + + ; filler + dwSampleTemp1 dd 0 + dwSampleTemp2 dd 0 + dwSampleTemp3 dd 0 + + ends + +sampleStartSize equ type _SOS_START_SAMPLE + +; this structure is used inside the timer handlers +timerSAMPLE struc + + samplePtr dq 0 ; pointer to sample data + sampleDataPtr dq 0 ; pointer to active data + sampleLoopPtr dq 0 ; pointer to loop back + + sampleLength dd 0 ; DWORD length of sample + sampleIndex dd 0 ; DWORD index into sample + sampleLoopLength dd 0 ; DWORD length of loop segment + + sampleBytesLeft dd 0 ; bytes left to play + + sampleLoopPoint dd 0 ; byte count for loop point + sampleLoopEndLength dd 0 ; length of end loop point + + sampleFlags dw 0 ; sample flags + sampleVolume dw 0 ; sample attinuation value + sampleID dw 0 ; sample ID value + + sampleChannel dw 0 ; current play channel + sampleLoopCount dw 0 ; loop count + sampleLastFill dw 0 ; last point of filling + sampleCallback dq 0 ; call back function + + samplePitchAdd dd 0 ; pitch shift value + samplePitchFraction dw 0 ; sample pitch fraction + + samplePort dw 0 ; port for non-DMA device + + sampleTotalBytes dd 0 ; total bytes processed + sampleByteLength dd 0 ; actual length of sample + + samplePanLocation dw 0 ; location of pan + samplePanSpeed dw 0 ; speed of pan + samplePanDirection dw 0 ; pan direction +- 1.. + samplePanStart dw 0 ; pan start + samplePanEnd dw 0 ; pan end + + sampleDelayBytes dw 0 ; bytes for delay + sampleDelayRepeat dw 0 ; number of repeats + + sampleADPCMPredicted dd 0 ; predicted value + sampleADPCMIndex dw 0 ; index into table + + sampleRootNoteMIDI dw 0 ; root note for sample + + sampleFraction dw 0 ; reserved + +timerSAMPLE ends + +timerSAMPLESize equ type timerSAMPLE + +; structure to represent a "far" pointer w/selector and offset +SFAR struc + + ; selector and offset + wOffset dd 0 + wSelector dd 0 + +SFAR ends + diff --git a/MUNGA_L4/sos/bc4/SOSDATA.H b/MUNGA_L4/sos/bc4/SOSDATA.H new file mode 100644 index 0000000..eb4677e --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSDATA.H @@ -0,0 +1,112 @@ +/**************************************************************************** + + File : sosdata.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_DATA +#define _SOS_DATA + +#include + +#pragma pack(4) +extern WORD _sosDIGIData_Start; +extern WORD _sosDIGIData_End; +extern WORD _wSOSDriverLinear[]; +extern WORD _wSOSTimerLinear[]; +extern SFAR _lpSOSDriver[]; +extern SFAR _lpSOSTimer[]; +extern SFAR _lpSOSDriverCS[]; +extern SFAR _lpSOSTimerCS[]; +extern BOOL _wSOSDriverLoaded[]; +extern BOOL _wSOSTimerLoaded[]; +extern BOOL _wSOSDriverInitialized[]; +extern WORD _wSOSOutputRate[]; +extern WORD _wSOSDMABuffersize[]; +extern LONG _dwSOSDMABufferPhysical[]; +extern SFAR _lpSOSDMABuffer[]; +extern BOOL _wTimerUsed; +extern SFAR _lpSOSFillHandler[]; +extern WORD _wSOSTimerType[]; +extern WORD _wSOSDriverType[]; +extern SFAR _lpSOSSampleList[][ _MAX_VOICES ]; +extern SFAR _lpSOSDMAIrqCount[]; +extern SFAR _lpSOSDMAFillCount[]; +extern WORD _wSOSTmrNextCount; +extern SFAR _lpSOSOldTimer; +extern WORD _wSOSDriverID[]; +extern _SOS_CAPABILITIES _sSOSDriverCaps[]; +extern WORD _wSOSDMAPortList[]; +extern BYTE _bSOSDMAChannel[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern BYTE _pSOSDriverPath[]; +extern BYTE _pSOSTempDriverPath[]; +extern BOOL _wTIMERUsed; +extern WORD _wTIMERValue; +extern VOID ( * _pTIMEREvents[] )( VOID ); +extern WORD _wTIMEREventRate[]; +extern WORD _dwTIMEREventFraction[]; +extern WORD _dwTIMEREventFractionCurrent[]; +extern BYTE _bSOSMIDITimerSongHandler[]; +extern BYTE _bSOSMIDISongHandle; +extern WORD _wSOSTimerMemHandle[]; +extern WORD _wSOSDriverMemHandle[]; +extern WORD _wSOSRealSeg[]; +extern VOID ( *_pSOSFillHandlerThunks[] )( VOID ); + +extern _FILEHEADER sDETFileHeader; +extern _DRIVERHEADER sDETDriverHeader; +extern _FILEHEADER sLOADFileHeader; +extern _DRIVERHEADER sLOADDriverHeader; +extern BOOL wDETInitialized; +extern WORD wDETLinear; +extern SFAR lpDETDriverBuffer; +extern SFAR lpDETDriverBufferCS; +extern WORD hDETFile; +extern DWORD dwDETDriverIndex; +extern WORD wDETDriverIndexCur; +extern WORD wDETMemHandle; +extern _SOS_CAPABILITIES * pDETDeviceCaps; +extern _SOS_CAPABILITIES sDETCaps; +extern PSTR _pSOSErrorStrings[]; +extern BOOL wSOSBufferAllocated[]; +extern BOOL wSOSSystemInitialized; +extern VDS_STRUCT sSOSVDSInfo; +extern _SOS_FILL_INFO _sSOSFillInfo; +extern WORD _wSOSTimerEventIndex; +extern WORD _wSOSTimerEntered; +extern WORD _wSOSDriverSize[]; +extern WORD _wSOSTimerSize[]; +extern PSTR pDETBuffer; + +#ifdef __cplusplus +extern "C" { +#endif +extern WORD _sosDIGIData1_Start; +extern WORD _sosDIGIData1_End; +extern WORD _sosDIGIData2_Start; +extern WORD _sosDIGIData2_End; +extern BYTE _bTIMERInstalled; +extern BYTE _bTIMERDPMI; +extern WORD wDetectPort; +extern WORD wDetectIRQ; +extern WORD wDetectDMA; +extern WORD wDetectParam; +#ifdef __cplusplus +} +#endif + +#pragma pack() + +#endif + diff --git a/MUNGA_L4/sos/bc4/SOSDEFS.H b/MUNGA_L4/sos/bc4/SOSDEFS.H new file mode 100644 index 0000000..3cacde0 --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSDEFS.H @@ -0,0 +1,65 @@ +/**************************************************************************** + + File : sosdefs.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOSDEFS_DEFINED +#define _SOSDEFS_DEFINED + +#undef _TRUE +#undef _FALSE +#undef _NULL +enum + { + _FALSE, + _TRUE + }; + +#define _NULL 0 + +#ifndef VOID +#define VOID void +#endif +typedef int BOOL; +typedef unsigned int UINT; +typedef unsigned char BYTE; +typedef unsigned WORD; +#ifndef LONG +typedef signed long LONG; +#endif +typedef unsigned long DWORD; + +typedef BYTE * PBYTE; +typedef char * PSTR; +typedef WORD * PWORD; +typedef LONG * PLONG; +typedef VOID * PVOID; + +typedef BYTE * LPBYTE; +typedef BYTE * LPSTR; +typedef WORD * LPWORD; +typedef LONG * LPLONG; +typedef VOID * LPVOID; + +typedef BYTE * HPBYTE; +typedef BYTE * HPSTR; +typedef WORD * HPWORD; +typedef LONG * HPLONG; +typedef VOID * HPVOID; + +typedef unsigned HANDLE; + +#endif + diff --git a/MUNGA_L4/sos/bc4/SOSFNCT.H b/MUNGA_L4/sos/bc4/SOSFNCT.H new file mode 100644 index 0000000..f4ba64d --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSFNCT.H @@ -0,0 +1,209 @@ +/**************************************************************************** + + File : sosfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_FUNCTIONS +#define _SOS_FUNCTIONS + +#pragma pack(4) + +#ifdef __cplusplus // HACK - ECH 96/01/26 +extern "C" { +#endif + +VOID sosDIGILockMemory ( VOID ); +VOID sosDIGIUnLockMemory ( VOID ); +WORD sosDIGIInitSystem ( PSTR, WORD ); +WORD sosDIGIUnInitSystem ( VOID ); +WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE *, + _SOS_INIT_DRIVER *, WORD * ); +WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL ); +WORD sosDIGILoadDriver ( WORD, WORD, SFAR *, SFAR *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadDriver ( WORD ); +WORD sosDIGIGetDeviceCaps ( WORD, PSOSDEVICECAPS ); + +#ifdef PHARLAP +WORD sosDIGIAllocateBuffer ( WORD , WORD *, WORD *, SFAR * ); +#else +WORD sosDIGIAllocateBuffer ( WORD , WORD *, WORD *, SFAR * ); +#endif + +WORD sosDIGIStopSample ( WORD, WORD ); +WORD sosDIGISamplesPlaying ( WORD ); +BOOL sosDIGISampleDone ( WORD, WORD ); +BOOL sosDIGISampleFilling ( WORD, WORD ); +WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE * ); +WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE * ); + + +WORD sosDIGIDetectInit ( PSTR ); +WORD sosDIGIDetectUnInit ( VOID ); +WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES *, WORD * ); +WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES *, WORD * ); +WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES *, WORD * ); +WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE * ); +WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES * ); +WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE * ); +PSTR sosGetErrorString ( WORD ); + +WORD sosDIGILoadTimer ( WORD , SFAR *, SFAR *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadTimer ( WORD ); + +WORD sosTIMERRegisterEvent ( WORD, VOID ( * )( VOID ), WORD * ); +WORD sosTIMERInitSystem ( WORD, WORD ); +WORD sosTIMERUnInitSystem ( WORD ); +WORD sosTIMERSetRate ( WORD ); +WORD sosTIMERRemoveEvent ( WORD ); +WORD sosTIMERAlterEventRate ( WORD, WORD ); +WORD sosTIMERGetEventRate ( WORD ); +VOID sosTIMEROldHandler ( VOID ); +VOID sosTIMERHandler ( VOID ); +VOID sosFillThunk0 ( VOID ); +VOID sosFillThunk1 ( VOID ); +VOID sosFillThunk2 ( VOID ); +VOID sosFillThunk3 ( VOID ); +VOID sosFillThunk4 ( VOID ); + +// functions in soscntl.c +WORD sosDIGISetSampleVolume ( WORD, WORD, WORD ); +WORD sosDIGIGetSampleVolume ( WORD, WORD ); +WORD sosDIGISetChannel ( WORD, WORD, WORD ); +WORD sosDIGIGetChannel ( WORD, WORD ); +WORD sosDIGIGetBytesProcessed ( WORD, WORD ); +WORD sosDIGIGetLoopCount ( WORD, WORD ); +WORD sosDIGISetPanLocation ( WORD, WORD, WORD ); +WORD sosDIGIGetPanLocation ( WORD, WORD ); +DWORD sosDIGISetPitch ( WORD, WORD, DWORD ); +DWORD sosDIGIGetPitch ( WORD, WORD ); +WORD sosDIGIGetDMAPosition ( WORD ); +WORD sosDIGISetPanSpeed ( WORD, WORD, WORD ); +WORD sosDIGIGetPanSpeed ( WORD, WORD ); +WORD sosDIGIGetSampleID ( WORD, WORD ); +WORD sosDIGIGetSampleHandle ( WORD, WORD ); +WORD sosDIGISetMasterVolume ( WORD, WORD ); +#ifdef PHARLAP +VOID sosFreeVDSPage ( WORD, WORD, LONG ); +WORD sosAllocVDSPage ( SFAR *, WORD *, WORD * ); +extern int cdecl sosRealAlloc( int, int *, int * ); +extern void cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD ); +extern int cdecl sosGetCS ( VOID ); +extern int cdecl sosGetES ( VOID ); +#else +WORD sosAllocVDSPage ( SFAR *, WORD *, WORD * ); +VOID sosFreeVDSPage ( WORD, WORD, LONG ); +extern int cdecl sosRealAlloc( int, int *, int * ); +extern int cdecl sosRealFree ( int ); +#endif + +extern BOOL cdecl _sos_read ( WORD, SFAR, WORD, WORD * ); +#ifdef __cplusplus // HACK - ECH 96/01/26 +} +#endif + +#ifdef __cplusplus +extern "C" { +#endif +// sos driver functions +extern int cdecl sosDRVLockMemory ( DWORD, DWORD ); +extern int cdecl sosDRVUnLockMemory ( DWORD, DWORD ); +extern void cdecl sosDRVGetCapsInfo ( SFAR, SFAR, _SOS_CAPABILITIES * ); +extern void cdecl sosDetDRVGetCapsInfo ( SFAR, SFAR, _SOS_CAPABILITIES * ); +extern void cdecl sosDRVGetCapsPtr ( SFAR, SFAR, _SOS_CAPABILITIES * ); +extern void cdecl sosDRVInit ( SFAR, SFAR, int, int, int, int, int, int ); +extern void cdecl sosDRVStart ( SFAR, SFAR, int, int ); +extern void cdecl sosDRVSetRate ( SFAR, SFAR, int ); +extern void cdecl sosDRVSetAction ( SFAR, SFAR ); +extern void cdecl sosDRVStop ( SFAR, SFAR ); +extern void cdecl sosDRVUnInit ( SFAR, SFAR ); +extern void cdecl sosDRVGetFillInfo ( SFAR, SFAR, SFAR, int, int, int, _SOS_FILL_INFO * ); +extern void cdecl sosFillSampleStructs ( PSTR, SFAR ); +extern WORD cdecl sosDetDRVExist ( SFAR, SFAR ); +extern WORD cdecl sosDetDRVGetSettings ( SFAR, SFAR ); +extern WORD cdecl sosCreateAliasCS ( SFAR, SFAR * ); +extern WORD cdecl sosDetDRVVerifySettings( SFAR, WORD, WORD, WORD, SFAR ); +extern WORD cdecl sosDIGIInitForWindows( WORD ); +extern WORD cdecl sosDIGIUnInitForWindows( WORD ); +extern WORD cdecl sosAllocateFarMem ( WORD, PSTR, WORD *, SFAR * ); +extern VOID cdecl sosFreeSelector ( SFAR, DWORD ); +extern WORD cdecl sosMAKEDOSPtr ( PSTR, SFAR * ); +extern VOID cdecl sosDetDRVSetEnvString ( DWORD, PSTR ); +extern PSTR cdecl sosDetDRVGetEnvString ( DWORD ); +extern VOID cdecl sosDetDRVEnvStringInit ( SFAR, SFAR ); +extern VOID cdecl sosDRVSetupCallFunctions( SFAR, SFAR, SFAR, SFAR ); +extern WORD cdecl sosDRVGetFreeMemory ( VOID ); +extern WORD cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * ); +extern WORD cdecl sosDRVFreeVDSStruct ( WORD, WORD ); +extern WORD cdecl sosDRVIsWindowsActive ( VOID ); +extern WORD cdecl sosDRVVDSGetBuffer ( WORD ); +extern WORD cdecl sosDRVVDSFreeBuffer ( WORD ); +extern WORD cdecl sosSetupVDSBufferSize( WORD, WORD ); +extern WORD cdecl sfmemcpy( PSTR, WORD, WORD ); +extern WORD cdecl sfmemcpy1( PSTR, WORD, WORD ); +extern WORD cdecl getDS( VOID ); +extern WORD cdecl getCS( VOID ); +extern WORD cdecl sosDRVMakeDMASelector ( WORD ); +extern WORD cdecl sosDRVFreeDMASelector ( WORD ); +extern WORD cdecl sosSetPageAccess ( WORD, WORD ); +extern VOID cdecl sosCopyToFarMem ( SFAR, PSTR, WORD ); +extern VOID cdecl sosDRVCallFillHandler ( SFAR ); +extern VOID cdecl sosInitDMABuffer( SFAR, WORD, WORD ); +extern VOID cdecl sosDIGISetupDS( VOID ); + +extern void cdecl sosTIMERDRVInit( int wRate, void ( * )( void ) ); +extern void cdecl sosTIMERDRVUnInit( void ); +extern void cdecl sosTIMERDRVHandler( void ); +extern void cdecl sosTIMERDRVFHandler( void ); +extern void cdecl sosTIMERDRVEnable( void ); +extern void cdecl sosTIMERDRVDisable( void ); +extern void cdecl sosTIMERDRVCallOld( void ); +extern void cdecl sosTIMERDRVSetRate( WORD ); +extern void cdecl sosDIGITimer_Start( void ); +extern void cdecl sosDIGITimer_End( void ); +extern void cdecl sosDIGIDrv_Start( void ); +extern void cdecl sosDIGIDrv_End( void ); +extern void cdecl sosInt3( void ); +extern void cdecl sosFARRet( WORD ); +extern void cdecl sosDIGIFARRet( VOID ); +#ifdef __cplusplus +} +#endif + +// memory locking prototypes +VOID sosDIGICaps_Start( VOID ); +VOID sosDIGICaps_End( VOID ); +VOID sosDIGIErr_Start( VOID ); +VOID sosDIGIErr_End( VOID ); +VOID sosDIGITmr_Start( VOID ); +VOID sosDIGITmr_End( VOID ); +VOID sosDIGIStart_Start( VOID ); +VOID sosDIGIStart_End( VOID ); +VOID sosDIGIPlyng_Start( VOID ); +VOID sosDIGIPlyng_End( VOID ); +VOID sosDIGIRate_Start( VOID ); +VOID sosDIGIRate_End( VOID ); +VOID sosDIGIDone_Start( VOID ); +VOID sosDIGIDone_End( VOID ); +VOID sosDIGIDetec_Start( VOID ); +VOID sosDIGIDetec_End( VOID ); +VOID sosDIGIInit_Start( VOID ); +VOID sosDIGIInit_End( VOID ); +VOID sosDIGILoad_Start( VOID ); +VOID sosDIGILoad_End( VOID ); +VOID sosDIGICntl_Start( VOID ); +VOID sosDIGICntl_End( VOID ); + +#pragma pack() + +#endif diff --git a/MUNGA_L4/sos/bc4/SOSM.H b/MUNGA_L4/sos/bc4/SOSM.H new file mode 100644 index 0000000..6009664 --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSM.H @@ -0,0 +1,450 @@ +/**************************************************************************** + + File : sosm.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_MIDI_DEFINED +#define _SOS_MIDI_DEFINED + +#include "sosdefs.h" +#include "sos.h" + +#pragma pack(4) + +#define _SOS_MIDI_ERR -1 + +// number of drivers allowed to be open at one time +#define _SOS_MIDI_MAX_DRIVERS 5 + +// maximum number of allowed channels +#define _SOS_MIDI_MAX_CHANNELS 0x10 + +// structure definition for the capabilities +typedef struct +{ + BYTE szDeviceName[ 32 ]; // device name + WORD wDeviceVersion; // device version + WORD wFlags; // miscellaneous flags + WORD wProcessData; // process data before sending to driver + SFAR lpPortList; // list of usable ports + SFAR lpIRQList; // list of usable irq channels + WORD wDeviceID; // ID for the device + +} _SOS_MIDI_CAPABILITIES; + +// call indexes for the loadable drivers +enum +{ + _DRV_MIDI_GET_CAPS, + _DRV_MIDI_GET_CALL_TABLE, + _DRV_MIDI_SPECIAL1 +}; + +// file header for the driver +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // number of drivers in the file + WORD wDrivers; + + // offset of first driver + WORD lOffset; + + // size of the file + WORD lFileSize; + +} _MIDIFILEHEADER; + +// driver header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // offset of next driver + WORD lNextDriver; + + // size of current driver + WORD wSize; + + // id for the current device + WORD wDeviceID; + + // id for the extender type + WORD wExtenderType; + +} _MIDIDRIVERHEADER; + +// device hardware information +typedef struct +{ + // port to be used + WORD wPort; + + // IRQ for the board + WORD wIRQ; + + // extra parameter + WORD wParam; + +} _SOS_MIDI_HARDWARE; + +// structure for initializing a digital driver +typedef struct +{ + // ID for the digital driver + WORD wDriverID; + + // timer rate to use + WORD wTimerRate; + + // timer callback rate to use + WORD wTimerCallbackRate; + + // max voices for the driver to use + WORD wMaxVoices; + + // velocity sensing flag + WORD wVelocitySensing; + + // init driver info + _SOS_INIT_DRIVER * sDIGIDriverInfo; + + // hardware information + _SOS_HARDWARE * sDIGIHardwareInfo; + +} _SOS_MIDI_DIGI_INIT_DRIVER; + +// structure for initializing a driver +typedef struct +{ + // type of driver to use if using a digital driver + WORD wDIGIDriverID; + + // pointer to driver memory + SFAR lpDriverMemory; + SFAR lpDriverMemoryCS; + + // pointer to digital driver initialization information + _SOS_MIDI_DIGI_INIT_DRIVER * sDIGIInitInfo; + + // miscellaneous WORD parameter for driver + WORD wParam; + + // miscellaneous DWORD parameter for driver + DWORD dwParam; + +} _SOS_MIDI_INIT_DRIVER; + +// structure for starting a song +typedef struct +{ + // pointer to song memory + BYTE * pSongData; + + // pointer to callback function for pertinent song information + VOID ( * pSongCallback )( WORD ); + +} _SOS_MIDI_INIT_SONG; + +// define to indicate that track mapping can be used +// from the midi file for the song +#define _MIDI_MAP_TRACK 0xff + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ]; + +} _SOS_MIDI_TRACK_DEVICE; + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ][ 5 ]; + +} _SOS_MIDI_TRACK_DEVICE1; + +// header for the NDMF format MIDI file +typedef struct +{ + // ID for the file + BYTE szFileID[ 32 ]; + + WORD dwBranchOffset; + WORD temp1; + WORD temp2; + WORD temp3; + +// // name of the instrument file to use with the song +// BYTE szInstrumentFile[ 16 ]; + + // number of tracks in the song + WORD wNDMFTracks; + + // ticks/quarter note song is used at + WORD wTicksQuarterNote; + + // tempo + WORD wTempo; + + // time for song to play at current tempo + WORD wTimeToPlay; + + // channel mapping priority information + WORD wChannelPriority[ _SOS_MIDI_MAX_CHANNELS ]; + + // channel mapping information + _SOS_MIDI_TRACK_DEVICE1 sTrackMap; + + // array of flags for which controllers to restore on a loop/branch + BYTE bCtrlRestore[ 128 ]; + + // pointer to callback function for song to call with + // pertinent information + VOID ( * pSongCallback )( WORD ); + WORD wFiller; + +} _NDMF_FILE_HEADER; + +// header for the tracks in the NDMF format MIDI file +typedef struct +{ + // track number + WORD wTrackNumber; + + // length of the track + WORD wTrackLength; + + // channel used on the track + WORD wChannel; + +} _NDMF_TRACK_HEADER; + +// MIDI event structure +typedef struct +{ + // dummy name to access midi data from + BYTE bMidiData[ 256 ]; + +} _NDMF_MIDI_EVENT; + +// maximum number of songs that can be played at any time +#define _SOS_MIDI_MAX_SONGS 8 + +// maximum number of tracks that can be used +#define _SOS_MIDI_MAX_TRACKS 32 + +// number of driver functions +#define _SOS_MIDI_DRV_FUNCTIONS 13 + +// enumeration for all of the drv functions +enum +{ + _MIDI_DRV_SEND_DATA, + _MIDI_DRV_INIT, + _MIDI_DRV_UNINIT, + _MIDI_DRV_RESET, + _MIDI_DRV_SET_INST_DATA +}; + +// defines for the loadable driver ids +#define _MIDI_SOUND_MASTER_II 0xa000 +#define _MIDI_MPU_401 0xa001 +#define _MIDI_FM 0xa002 +#define _MIDI_OPL2 0xa002 +#define _MIDI_CALLBACK 0xa003 +#define _MIDI_MT_32 0xa004 +#define _MIDI_DIGI 0xa005 +#define _MIDI_INTERNAL_SPEAKER 0xa006 +#define _MIDI_WAVE_TABLE_SYNTH 0xa007 +#define _MIDI_AWE32 0xa008 +#define _MIDI_OPL3 0xa009 +#define _MIDI_GUS 0xa00a + +// structure for the hmi instrument file header +typedef struct +{ + // file id type + BYTE szFileID[ 32 ]; + + // file version + WORD wFileVersion; + + // size of the file + WORD dwFileSize; + +} _HMI_INS_FILE_HEADER; + + +// define for identifying a drum instrument +#define _SOS_MIDI_DRUM_INS ( short )0x8000 + +// maximum number of timer events that can be registered +#define _TIMER_MAX_EVENTS 0x10 + +// structure for digital driver queue element +typedef struct _tagQueueElement +{ + // handle for the sample + WORD wSampleHandle; + + // id for the sample + WORD wSampleID; + + // velocity for the sample + WORD wVelocity; + + // channel for the sample + WORD wChannel; + +} _DIGI_QUEUE_ELEMENT; + +// maximum number of instruments that can be set in the +// digital driver +#define _MAX_INS 128 + +// define for the maximum number of times a channel can be stolen +#define _SOS_MIDI_MAX_LEVELS 0x04 + +// structure for MIDI information to be stored on the local stack +// when a channel is stolen +typedef struct +{ + // used element + BYTE bUsed; + + // last pitch bend information sent + BYTE bPitchBend; + + // channel volume + BYTE bChannelVolume; + + // instrument information + BYTE bInstrument; + + // sustain pedal + BYTE bSustain; + +} _SOS_MIDI_CHANNEL_DATA; + +// flags for the debugging system +#define _SOS_DEBUG_NORMAL 0x0000 +#define _SOS_DEBUG_NO_TIMER 0x0001 + +// ID for 32 bit MIDI file +#define _SOS_MIDI_FILE_ID "HMIMIDIP" + +// structure for branch location controller +typedef struct +{ + // offset from start of track data + WORD dwOffset; + + // branch ID number + BYTE bBranchID; + + // current instrument + BYTE bInstrument; + + // current loop count for temporary storage + // so that a track can be looped without + // needing any data from the program + BYTE bLoopCount; + + // number of controller messages stored + BYTE bCtrlChangeCount; + + // offset of control change information from start of file + WORD lpCtrlChangeData; + WORD lpCtrlChangeDataTemp; + + // reserved fields + WORD wReserved1; + WORD wReserved2; + +} _SOS_BRANCH_POINT; + +#define _SOS_MIDI_FADE_IN 0x01 +#define _SOS_MIDI_FADE_OUT 0x02 +#define _SOS_MIDI_FADE_OUT_STOP 0x04 + +// structure for digital drums to use to store midi information +typedef struct +{ + // current volume + WORD wVolume; + + // current pan position + WORD wPanPosition; + + // reserved + DWORD dwReserved; + +} _SOS_MIDI_DIGI_CHANNEL; + +// instrument file header structure +typedef struct +{ + // file ID + BYTE szID[ 32 ]; + + // file version + WORD wVersion; + + // instruments in file + WORD wInstruments; + + // list of pointers to start sample structures + SFAR * lpStartSample[ _MAX_INS ]; + + DWORD temp1; + DWORD temp2; + +} _WAVE_FILE_HEADER; + +#pragma pack() + +// define for the busy error returned from send data +#define _ERR_DRIVER_BUSY 0xf000 + +// defines for the looping branch controllers +#define _SOS_SET_FLAG 103 +#define _SOS_RESET_FLAG 104 +#define _SOS_BRANCH1 108 +#define _SOS_BRANCH2 109 +#define _SOS_BRANCH3 110 +#define _SOS_BRANCH4 111 +#define _SOS_BRANCH5 112 +#define _SOS_BRANCH6 113 +#define _SOS_BRANCH7 114 +#define _SOS_BRANCH8 115 +#define _SOS_BRANCH9 116 +#define _SOS_BRANCH10 117 +#define _SOS_BRANCH11 118 +#define _SOS_BRANCH12 119 +#define _SOS_BRANCH13 120 +#define _SOS_BRANCH14 121 + +// define for the program change controller flag +#define _SOS_PROGRAM_CHANGE_FLAG 108 + +#include "sosmdata.h" +#include "sosmfnct.h" + +#endif diff --git a/MUNGA_L4/sos/bc4/SOSMAWE.H b/MUNGA_L4/sos/bc4/SOSMAWE.H new file mode 100644 index 0000000..ddcd7d2 --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSMAWE.H @@ -0,0 +1,16 @@ + +#include "sosm.h" + +#ifdef __cplusplus // HACK - ECH 96/01/26 +extern "C" { +#endif + +WORD sosMIDIAWE32SetSBKFile( WORD, PSTR ); +WORD sosMIDIAWE32ReleaseSBKFiles( WORD ); +WORD sosMIDIAWE32NoteOn( WORD, WORD, WORD, WORD, WORD, WORD ); +WORD sosMIDIAWE32NoteOff( WORD, WORD, WORD ); + +#ifdef __cplusplus // HACK - ECH 96/01/26 +} +#endif + diff --git a/MUNGA_L4/sos/bc4/SOSMDATA.H b/MUNGA_L4/sos/bc4/SOSMDATA.H new file mode 100644 index 0000000..71b9ce4 --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSMDATA.H @@ -0,0 +1,125 @@ +/**************************************************************************** + + File : sosmdata.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOS_MIDI_DATA +#define _SOS_MIDI_DATA + +#include "sos.h" + +#pragma pack(4) + +extern WORD _wSOSMIDIDriverLinear[]; +extern SFAR _lpSOSMIDIDriver[]; +extern SFAR _lpSOSMIDIDriverCS[]; +extern WORD _wSOSMIDIMemHandle[]; +extern BOOL _wSOSMIDIDriverLoaded[]; +extern WORD _wSOSMIDIDriverType[]; +extern WORD _wSOSMIDIDriverID[]; +extern DWORD _dwSOSMIDITrackDeltaCurrent[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDIActiveTracks[]; +extern WORD _wSOSMIDITotalTracks[]; +extern DWORD _dwSOSMIDITrackDeltaTime[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDISongPaused[]; +extern WORD _wSOSMIDISongMuted[]; +extern BOOL _wSOSMIDISongActive[]; +extern BYTE _bSOSMIDIEventSize[]; +extern BYTE _bSOSMIDIEventSizeControl[]; +extern _SOS_MIDI_CAPABILITIES * _pSOSMIDIDriverCaps[]; +extern _SOS_MIDI_TRACK_DEVICE * _sSOSMIDITrackMap[]; +extern _NDMF_MIDI_EVENT * _pSOSMIDITrack[][_SOS_MIDI_MAX_TRACKS]; +extern SFAR _lpSOSMIDIDrvFunction[ _SOS_MIDI_MAX_DRIVERS ][ _SOS_MIDI_DRV_FUNCTIONS ]; +extern _NDMF_FILE_HEADER * _sSOSMIDISongHeader[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern WORD _wSOSMIDIEventHandle[]; +extern BYTE _szSOSMIDIDrvFile[]; +extern _MIDIFILEHEADER _sSOSMIDIDRVFileHeader; +extern _MIDIDRIVERHEADER _sSOSMIDIDRVDriverHeader; +extern BOOL _wSOSMIDISysInititalized; +extern SFAR _lpSOSMIDICBCKDrvFunctions[]; +extern VOID ( cdecl *_pSOSMIDICBCKFunctions )( SFAR, WORD, WORD ); +extern WORD _wMIDIDIGISampleQueueHead[]; +extern WORD _wMIDIDIGISampleQueueTail[]; +extern WORD _wMIDIDIGIMaxSamples[]; +extern WORD _wMIDIDIGIUsedSamples[]; +extern _DIGI_QUEUE_ELEMENT _sMIDIDIGIQueue[][ _MAX_VOICES ]; + + +extern SFAR _lpMIDIDIGIDrvFunctions[]; +extern _SOS_START_SAMPLE * _sMIDIDIGIStartSample[][ _MAX_INS ]; +extern _HMI_INS_FILE_HEADER * _sMIDIDIGIInsFileHeader[]; +extern WORD _wMIDIDIGIDriverHandle[]; +extern WORD _wMIDIDIGIDriverInitialized[]; +extern WORD _wMIDIDIGITimerEventHandle[]; +extern WORD _wMIDIDIGIDriverInitMIDI[]; +extern WORD _wMIDIDIGIVelocitySensing[]; +extern BYTE _szMIDIDIGIInsFileID[]; + +extern BYTE _bSOSMIDIMasterVolume; +extern BYTE _bSOSMIDIDeviceChannelVolume[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIMT32SendData; + +extern SFAR lpFake; +extern WORD wFake; + +extern _NDMF_TRACK_HEADER *_pSOSMIDITrackHeaders[][ _SOS_MIDI_MAX_TRACKS ]; +extern BYTE _bSOSMIDIChannelRemap[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIChannelPriority[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerChannel[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerSong[][ _SOS_MIDI_MAX_CHANNELS ]; +extern _SOS_MIDI_CHANNEL_DATA _sSOSMIDIChannelData[][ _SOS_MIDI_MAX_CHANNELS ][ _SOS_MIDI_MAX_LEVELS ]; +extern BYTE _bSOSMIDIChannelDataIndex[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIData[]; +extern BYTE _bSOSMIDIData1[]; +extern BYTE _bSOSMIDIDeviceLowPriority[]; +extern WORD _wSOSMIDIChannelStealing; +extern BYTE _bSOSMIDIDeviceChannelActive[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIDeviceChannelAvailable[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDISongHandle; +extern BYTE _szMIDIMIDIFileID[]; +extern BYTE _pSOSMIDIDriverPath[]; +extern BYTE _pSOSMIDITempDriverPath[]; +extern WORD sosMIDIData_Start; +extern WORD sosMIDIData_End; +extern WORD _wSOSGravisTimerHandle; +extern WORD _wSOSMIDISongVolume[]; + +extern _SOS_BRANCH_POINT * _pMIDIBranchData[][ _SOS_MIDI_MAX_TRACKS ]; +extern WORD ( *_pSOSMIDIBranchCallback[] )( WORD, BYTE, BYTE ); +extern WORD ( *_pSOSMIDILoopCallback[] )( WORD, BYTE, BYTE, BYTE ); +extern WORD ( *_pSOSMIDITriggerCallback[][ 127 ] )( WORD, BYTE, BYTE ); +extern BYTE _bSOSMIDIBranchOccurred; + +extern WORD _wSOSMIDIVolumeFadeDirection[]; +extern DWORD _dwSOSMIDIVolumeFadeFraction[]; +extern DWORD _dwSOSMIDIVolumeFadeVolume[]; +extern WORD _wSOSMIDIVolumeFadeTicks[]; +extern BYTE _bSOSMIDIHandleVolumeFade[]; +extern WORD _wSOSDIGIMIDIHandle[]; +extern SFAR _lpSOSMIDIGusFunction; + +extern _SOS_MIDI_DIGI_CHANNEL _sMIDIDIGIChannel[]; + +extern SFAR _lpMIDIWAVEDrvFunctions[]; +extern WORD _wSOSMIDIChannelMuted[][ _SOS_MIDI_MAX_CHANNELS ]; + +extern BYTE _szPLYMIDIBuffer[]; +extern WORD _wPLYMIDIBufferIndex; +extern WORD _wSOSMIDIDriverSize[]; + +#pragma pack() + +#endif diff --git a/MUNGA_L4/sos/bc4/SOSMFNCT.H b/MUNGA_L4/sos/bc4/SOSMFNCT.H new file mode 100644 index 0000000..9962e7d --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSMFNCT.H @@ -0,0 +1,190 @@ +/**************************************************************************** + + File : sosmfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_MIDI_FUNCTIONS +#define _SOS_MIDI_FUNCTIONS + +#pragma pack(4) + +#ifdef __cplusplus // HACK - ECH 96/01/26 +extern "C" { +#endif + +WORD sosMIDILockMemory ( VOID ); +WORD sosMIDIUnLockMemory ( VOID ); +WORD sosMIDIGetDeviceCaps ( WORD, _SOS_MIDI_CAPABILITIES * ); +WORD sosMIDIInitSystem ( PSTR, WORD ); +WORD sosMIDIUnInitSystem ( VOID ); +WORD sosMIDIInitDriver ( WORD, _SOS_MIDI_HARDWARE *, + _SOS_MIDI_INIT_DRIVER *, WORD * ); +WORD sosMIDIUnInitDriver ( WORD, BOOL ); +WORD sosMIDILoadDriver ( WORD, WORD, SFAR *, SFAR *, PSTR, PSTR, WORD * ); +WORD sosMIDIUnLoadDriver ( WORD ); +WORD sosMIDIInitSong ( _SOS_MIDI_INIT_SONG *, + _SOS_MIDI_TRACK_DEVICE *, + WORD * ); +WORD sosMIDIUnInitSong ( WORD ); +WORD sosMIDIResetSong ( WORD, _SOS_MIDI_INIT_SONG * ); +WORD sosMIDIStartSong ( WORD ); +WORD sosMIDIStopSong ( WORD ); +WORD sosMIDIPauseSong ( WORD, WORD ); +WORD sosMIDIMuteSong ( WORD ); +WORD sosMIDIUnMuteSong ( WORD ); +WORD sosMIDIResumeSong ( WORD ); +BOOL sosMIDISongDone ( WORD ); +WORD sosMIDISongAlterTempo ( WORD, WORD ); +WORD sosMIDIGetDeltaTime ( PSTR, DWORD * ); +WORD sosMIDISongGetTimeToPlay ( WORD ); +BYTE * sosMIDINormalizePtr ( BYTE * ); +WORD sosMIDISetInsData ( WORD, PSTR, WORD ); +WORD sosMIDIResetDriver ( WORD ); +BOOL sosMIDIHandleMIDIData ( WORD, PSTR, WORD, WORD ); +WORD sosMIDISendMIDIData ( WORD, PSTR, WORD ); +VOID sosMIDISetTrackState ( WORD, WORD, WORD ); + +// compiled in drivers function interface +VOID digiGetCallTable ( WORD * ); +VOID callbackGetCallTable ( WORD * ); + +WORD cdecl callbackSendData ( SFAR, WORD, WORD ); +WORD cdecl callbackInit ( SFAR, WORD, WORD ); +WORD cdecl callbackUnInit ( SFAR, WORD, WORD ); +WORD cdecl callbackReset ( SFAR, WORD, WORD ); +WORD cdecl callbackSetInstrumentData ( SFAR, WORD, WORD ); + +// function prototypes +WORD cdecl digiSendData ( SFAR, WORD, WORD ); +WORD cdecl digiInit ( SFAR, WORD, WORD ); +WORD cdecl digiUnInit ( SFAR, WORD, WORD ); +WORD cdecl digiReset ( SFAR, WORD, WORD ); +WORD cdecl digiSetInstrumentData ( SFAR, WORD, WORD ); + +VOID waveGetCallTable ( WORD * ); +WORD cdecl waveSendData ( SFAR, WORD, WORD ); +WORD cdecl waveInit ( SFAR, WORD, WORD ); +WORD cdecl waveUnInit ( SFAR, WORD, WORD ); +WORD cdecl waveReset ( SFAR, WORD, WORD ); +WORD cdecl waveSetInstrumentData ( SFAR, WORD, WORD ); +VOID cdecl waveSampleCallback( WORD, WORD, WORD ); + +WORD cdecl callbackSendDataStub ( SFAR, WORD, WORD ); +WORD cdecl callbackInitStub ( SFAR, WORD, WORD ); +WORD cdecl callbackUnInitStub ( SFAR, WORD, WORD ); +WORD cdecl callbackResetStub ( SFAR, WORD, WORD ); +WORD cdecl callbackSetInstrumentDataStub ( SFAR, WORD, WORD ); + +// function prototypes +WORD cdecl digiSendDataStub ( SFAR, WORD, WORD ); +WORD cdecl digiInitStub ( SFAR, WORD, WORD ); +WORD cdecl digiUnInitStub ( SFAR, WORD, WORD ); +WORD cdecl digiResetStub ( SFAR, WORD, WORD ); +WORD cdecl digiSetInstrumentDataStub ( SFAR, WORD, WORD ); + +WORD cdecl waveSendDataStub ( SFAR, WORD, WORD ); +WORD cdecl waveInitStub ( SFAR, WORD, WORD ); +WORD cdecl waveUnInitStub ( SFAR, WORD, WORD ); +WORD cdecl waveResetStub ( SFAR, WORD, WORD ); +WORD cdecl waveSetInstrumentDataStub ( SFAR, WORD, WORD ); + +VOID digiQueueInit ( WORD, WORD ); +VOID digiQueueUnInit ( WORD ); +WORD digiQueueAddItem ( WORD, WORD, WORD, WORD, WORD ); +WORD digiQueueGetItem ( WORD, WORD ); +WORD digiQueueGetItemWAVE ( WORD ); +WORD digiQueueDeleteItem ( WORD, WORD ); +WORD digiQueueDeleteItemWAVE ( WORD, WORD ); +WORD digiQueueDeleteItemMIDI ( WORD, WORD, WORD ); +WORD digiQueueFindItemMIDI ( WORD, WORD, WORD ); + +// function prototypes +VOID cdecl digiSampleCallback( WORD, WORD, WORD ); + +WORD sosMIDIRegisterBranchFunction ( WORD, WORD ( * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIRegisterLoopFunction ( WORD, WORD ( * )( WORD, BYTE, BYTE, BYTE ) ); +WORD sosMIDIRegisterTriggerFunction( WORD, BYTE, WORD ( * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIBranchToTrackLocation ( WORD, BYTE, BYTE ); +WORD sosMIDIBranchToSongLocation ( WORD, BYTE ); + +//#ifdef __cplusplus // ECH +//extern "C" { +//#endif + +extern void cdecl sosMIDIDRVGetCapsInfo( SFAR, SFAR, PSTR ); +extern void cdecl sosMIDIDRVGetCapsPtr ( SFAR, SFAR, PSTR ); +extern void cdecl sosMIDIDRVGetFuncsPtr( SFAR, SFAR, PSTR ); +extern VOID cdecl sosMIDIDRVSpecialFunction( SFAR, SFAR, WORD, SFAR * ); +extern WORD cdecl xgetES( void ); + +extern WORD cdecl sosMIDIDRVCall32Func( SFAR, SFAR, WORD, WORD ); + +//#ifdef __cplusplus // ECH +//} +//#endif + +BOOL sosMIDIResetChannelStealing ( WORD ); +WORD sosMIDIEnableChannelStealing( WORD ); +VOID sosMIDISongHandler( VOID ); + +WORD sosMIDISetMT32InsData ( WORD, PSTR, WORD ); +WORD sosMIDISetMasterVolume ( BYTE ); +VOID sosMIDIMT32Timer ( VOID ); + +WORD sosMIDISetSongVolume ( WORD, BYTE ); +WORD sosMIDIFadeSong ( WORD, WORD, WORD, BYTE, BYTE, WORD ); +VOID sosMIDIGusFunction( VOID ); +VOID sosMIDIGusFunction1( SFAR ); + +// functions for memory locking +VOID sosMIDICaps_Start( VOID ); +VOID sosMIDICaps_End( VOID ); +VOID sosMIDICbck_Start( VOID ); +VOID sosMIDICbck_End( VOID ); +VOID sosMIDIDigi_Start( VOID ); +VOID sosMIDIDigi_End( VOID ); +VOID sosMIDIDone_Start( VOID ); +VOID sosMIDIDone_End( VOID ); +VOID sosMIDIDq_Start( VOID ); +VOID sosMIDIDq_End( VOID ); +VOID sosMIDIInit_Start( VOID ); +VOID sosMIDIInit_End( VOID ); +VOID sosMIDIIns_Start( VOID ); +VOID sosMIDIIns_End( VOID ); +VOID sosMIDILoad_Start( VOID ); +VOID sosMIDILoad_End( VOID ); +VOID sosMIDIPause_Start( VOID ); +VOID sosMIDIPause_End( VOID ); +VOID sosMIDIPtr_Start( VOID ); +VOID sosMIDIPtr_End( VOID ); +VOID sosMIDISong_Start( VOID ); +VOID sosMIDISong_End( VOID ); +VOID sosMIDISt_Start( VOID ); +VOID sosMIDISt_End( VOID ); +VOID sosMIDITmpo_Start( VOID ); +VOID sosMIDITmpo_End( VOID ); +VOID sosMIDITmr_Start( VOID ); +VOID sosMIDITmr_End( VOID ); +VOID sosMIDIAWE_Start( VOID ); +VOID sosMIDIAWE_End( VOID ); + +void StringOut( BYTE X, BYTE Y, BYTE * String, BYTE Color ); + +#ifdef __cplusplus // HACK - ECH 96/01/26 +} +#endif + +#pragma pack() + +#endif diff --git a/MUNGA_L4/sos/bc4/SOSRES.H b/MUNGA_L4/sos/bc4/SOSRES.H new file mode 100644 index 0000000..4191cc2 --- /dev/null +++ b/MUNGA_L4/sos/bc4/SOSRES.H @@ -0,0 +1,110 @@ +/**************************************************************************** + + File : sosres.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#define _SOS_RESOURCE +#ifndef _SOS_RESOURCE +#define _SOS_RESOURCE + +// structure for resource file header +typedef struct +{ + // file version + WORD wVersion; + + // file size + LONG dwFileSize; + + // number of resources in file + WORD wResCount; + + // offset of resource data from top of file + LONG dwResOffset; + + // offset of sync track from top of file + LONG dwSyncTrackOffset; + +} _RES_FILE_HEADER; + +// structure for resource block header +typedef struct +{ + // resource id + WORD wID; + + // resource type + WORD wResType; + + // offset of next block + LONG dwNextBlock; + + // size of the current resource information + LONG dwResSize; + + // rate to play block at + WORD wBlockRate; + + // id for the sync track to use + WORD wSyncTrackID; + +} _RES_BLOCK_HEADER; + +// structure for sync mark tag +typedef struct _tagSYNCMARK +{ + // ID of the type of mark being used + WORD wID; + + // location in data of sync mark + LONG dwSyncOffset; + + // length of sync block + LONG dwSyncSize; + + // start sample data + _SOS_START_SAMPLE sampleData; + +} _RES_SYNCMARK; + +typedef union +{ + // structure for sync mark tag + _RES_SYNCMARK syncMark; + +} _RES_TAG; + +// union for filter information for prepareWave +typedef union +{ + // filter type + WORD wFilterID; + + // structure for volume + struct volume + { + WORD wVolume; + }; + + // structure for delay + struct delay + { + WORD wDelaySamples; + }; + +} _SOS_FILTER; + + +#endif + diff --git a/MUNGA_L4/sos/wc/SOS.H b/MUNGA_L4/sos/wc/SOS.H new file mode 100644 index 0000000..36b9b68 --- /dev/null +++ b/MUNGA_L4/sos/wc/SOS.H @@ -0,0 +1,553 @@ +/**************************************************************************** + + File : sos.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_DEFINED +#define _SOS_DEFINED +#include "sosdefs.h" + +#pragma pack(4) + +// error definition for sound operating system +#define _SOS_ERR -1 + +// number of drivers allowed to be open at one time +#define _SOS_MAX_DRIVERS 5 + +// structure definition for the capabilities +typedef struct _tagCAPABILITIES +{ + BYTE szDeviceName[ 32 ]; // device name + WORD wDeviceVersion; // device version + WORD wBitsPerSample; // bits per sound sample + WORD wChannels; // stereo/mono sound card + WORD wMinRate; // minimum rate + WORD wMaxRate; // maximum rate + WORD wMixerOnBoard; // board contains mixer + WORD wMixerFlags; // mixer capabilities + WORD wFlags; // miscellaneous flags + short far * lpPortList; // list of usable ports + short far * lpDMAList; // list of usable dma channels + short far * lpIRQList; // list of usable irq channels + short far * lpRateList; // list of usable rates, -1 if any in min to max + WORD fBackground; // foreground or background driver + WORD wDeviceID; // ID for the device + WORD wTimerID; // ID for the timer + +} _SOS_CAPABILITIES; + +// far pointer to the device capabilities structure +typedef _SOS_CAPABILITIES far * LPSOSDEVICECAPS; + +// flag types for driver +#define _FLAGS_SIGNED 0x8000 + +// devices that can be loaded +#define _SOUND_BLASTER_8_MONO 0xe000 +#define _SOUND_BLASTER_8_ST 0xe001 +#define _SBPRO_8_ST _SOUND_BLASTER_8_ST +#define _SBPRO_8_MONO 0xe00f +#define _SOUND_MASTER_II_8_MONO 0xe002 +#define _MV_PAS_8_MONO 0xe003 +#define _MV_PAS_16_MONO 0xe004 +#define _MV_PAS_8_ST 0xe005 +#define _MV_PAS_16_ST 0xe006 +#define _ADLIB_GOLD_8_ST 0xe007 +#define _ADLIB_GOLD_16_ST 0xe008 +#define _ADLIB_GOLD_8_MONO 0xe009 +#define _ADLIB_GOLD_16_MONO 0xe00a +#define _MICROSOFT_8_MONO 0xe00b +#define _MICROSOFT_8_ST 0xe00c +#define _MICROSOFT_16_MONO 0xe00d +#define _MICROSOFT_16_ST 0xe00e +#define _SOUND_SOURCE_8_MONO_PC 0xe010 +#define _SOUND_SOURCE_8_MONO_TANDY 0xe011 +#define _GENERAL_PORT_8_MONO 0xe012 +#define _GENERAL_PORT_8_MONO_R 0xe013 +#define _SIERRA_8_MONO 0xe014 +#define _SB16_8_MONO 0xe015 +#define _SB16_8_ST 0xe016 +#define _SB16_16_MONO 0xe017 +#define _SB16_16_ST 0xe018 +#define _ESS_AUDIODRIVE_8_MONO 0xe019 +#define _ESS_AUDIODRIVE_8_ST 0xe01a +#define _ESS_AUDIODRIVE_16_MONO 0xe01b +#define _ESS_AUDIODRIVE_16_ST 0xe01c +#define _SOUNDSCAPE_8_MONO 0xe01d +#define _SOUNDSCAPE_8_ST 0xe01e +#define _SOUNDSCAPE_16_MONO 0xe01f +#define _SOUNDSCAPE_16_ST 0xe020 +#define _RAP10_8_MONO 0xe021 +#define _RAP10_16_MONO 0xe022 +#define _GUS_8_MONO 0xe023 +#define _GUS_8_ST 0xe024 +#define _GUS_16_MONO 0xe025 +#define _GUS_16_ST 0xe026 +#define _GUS_MAX_8_MONO 0xe027 +#define _GUS_MAX_8_ST 0xe028 +#define _GUS_MAX_16_MONO 0xe029 +#define _GUS_MAX_16_ST 0xe02a +#define _WAVEJAMMER_8_MONO 0xe02b +#define _WAVEJAMMER_8_ST 0xe02c +#define _WAVEJAMMER_16_MONO 0xe02d +#define _WAVEJAMMER_16_ST 0xe02e +#define _TEMPOCS_8_MONO 0xe02f +#define _TEMPOCS_8_ST 0xe030 +#define _TEMPOCS_16_MONO 0xe031 +#define _TEMPOCS_16_ST 0xe032 +#define _WAVEJAMMERCD_8_MONO 0xe033 +#define _WAVEJAMMERCD_8_ST 0xe034 +#define _WAVEJAMMERCD_16_MONO 0xe035 +#define _WAVEJAMMERCD_16_ST 0xe036 +#define _SOUND_BLASTER_8_MONO_R 0xe050 +#define _MICROSOFT_8_MONO_R 0xe051 +#define _SOUND_MASTER_II_8_MONO_R 0xe052 +#define _ADLIB_GOLD_8_MONO_R 0xe053 +#define _MV_PAS_8_MONO_R 0xe054 +#define _RAP10_8_MONO_R 0xe058 +#define _RAP10_16_MONO_R 0xe059 +#define _SB16_8_MONO_R 0xe05a +#define _SB16_8_ST_R 0xe05b +#define _SB16_16_MONO_R 0xe05c +#define _SB16_16_ST_R 0xe05d +#define _MV_PAS_16_MONO_R 0xe060 +#define _SOUNDSCAPE_8_MONO_R 0xe061 +#define _SOUNDSCAPE_8_ST_R 0xe062 +#define _SOUNDSCAPE_16_MONO_R 0xe063 +#define _SOUNDSCAPE_16_ST_R 0xe064 +#define _ESS_AUDIODRIVE_8_MONO_R 0xe065 +#define _ESS_AUDIODRIVE_8_ST_R 0xe066 +#define _ESS_AUDIODRIVE_16_MONO_R 0xe067 +#define _ESS_AUDIODRIVE_16_ST_R 0xe068 +#define _SPEECH_THING_8_MONO 0xe090 +#define _YAMAHA_8_MONO 0xe106 +#define _INT_SPEAKER_8_MONO 0xe107 + +// call indexes for the loadable drivers +enum +{ + _DRV_INIT, + _DRV_UNINIT, + _DRV_SETRATE, + _DRV_SETACTION, + _DRV_START, + _DRV_STOP, + _DRV_PAUSE, + _DRV_RESUME, + _DRV_CAPABILITIES, + _DRV_PLAY_FOREGROUND, + _DRV_GET_FILL_INFO, + _DRV_GET_CALL_FUNCTIONS, + _DRV_SET_CALL_FUNCTIONS +}; + +// fill info +typedef struct _tagFillInfo + { + + LPSTR lpFillHandler; // pointer to fill handler + LPWORD lpDMAFillCount; // pointer to dma count + LPSTR lpSampleList; // pointer to sample list + LPWORD lpDMAMasterVolume; // pointer to dma count + + } _SOS_FILL_INFO; + +// caps info structure +typedef struct _tagCapsInfo + { + + LPSTR lpPortList; // pointer to port list + LPSTR lpDMAList; // pointer to DMA list + LPSTR lpIRQList; // pointer to IRQ list + LPSTR lpRateList; // pointer to rate list + + } _SOS_CAPS_INFO; + +// maximum number of available voice +#define _MAX_VOICES 32 + +// structure definition +typedef struct _tagSAMPLE +{ + LPSTR samplePtr; // pointer to data buffer + LPSTR sampleData; // pointer to active data + LPSTR sampleLoopPtr; // pointer for loop back + + WORD sampleLength; // length of sample + WORD sampleIndex; // index into sample + WORD sampleLoopLength; // length of loop + + WORD sampleBytesLeft; // bytes left to play in sample + + WORD sampleLoopPoint; // byte count for loop point + WORD sampleLoopEndLength; // length of remaining chunk + + short sampleFlags; // control sample + short sampleVolume; // volume control + short sampleID; // sample ID + + short sampleChannel; // channel to play sample on + short sampleLoopCount; // loop count + short sampleLastFill; // last fill position + VOID ( far cdecl * sampleCallback )( WORD, WORD, WORD ); // callback function for sample + + WORD samplePitchAdd; + short samplePitchFraction; + + short samplePort; // port to use for non-dma digitized + + WORD sampleTotalBytes; + WORD sampleByteLength; + + short samplePanLocation; + short samplePanSpeed; + short samplePanDirection; + short samplePanStart; + short samplePanEnd; + + short sampleDelayBytes; + short sampleDelayRepeat; + + WORD sampleADPCMPredicted; + short sampleADPCMIndex; + + short sampleRootNoteMIDI; + + WORD sampleTemp1; + +} _SOS_SAMPLE; + +// enumeration for left or right channel +enum +{ + _LEFT_CHANNEL, + _RIGHT_CHANNEL, + _CENTER_CHANNEL, + _INTERLEAVED +}; + +// enumeration for foreground and background +enum +{ + _FOREGROUND, + _BACKGROUND +}; + +// defines for the sample flags +#define _ACTIVE 0x8000 +#define _LOOPING 0x4000 +#define _FIRST_TIME 0x2000 +#define _PENDING_RELEASE 0x1000 +#define _CONTINUE_BLOCK 0x0800 +#define _PITCH_SHIFT 0x0400 +#define _PANNING 0x0200 +#define _VOLUME 0x0100 +#define _TRANSLATE16TO8 0x0080 +#define _STAGE_LOOP 0x0040 +#define _TRANSLATE8TO16 0x0020 +#define _STEREOTOMONO 0x0010 + +// defines for the wParam flags +#define _SINGLE_SAMPLE 0x01 + +#define _SOS_DCAPS_AUTO_REINIT 0x01 +#define _SOS_DCAPS_MPU_401 0x02 +#define _SOS_DCAPS_OPL2 0x04 +#define _SOS_DCAPS_OPL3 0x08 +#define _SOS_DCAPS_OPL4 0x10 +#define _SOS_DCAPS_WAVETABLE 0x20 +#define _SOS_DCAPS_DL_SAMPLES 0x40 +#define _SOS_DCAPS_FIFO_DEVICE 0x80 +#define _SOS_DCAPS_ENV_NEEDED 0x100 +#define _SOS_DCAPS_PSEUDO_DMA1 0x200 +#define _SOS_DCAPS_SIGNED_DATA 0x8000 + +// file header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // number of drivers in the file + WORD wDrivers; + + // offset of first driver + WORD lOffset; + + // size of the file + WORD lFileSize; + +} _FILEHEADER; + +// driver header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // offset of next driver + WORD lNextDriver; + + // size of current driver + WORD wSize; + + // id for the current device + WORD wDeviceID; + + // id for the type of DOS extender + WORD wExtenderType; + +} _DRIVERHEADER; + +// device hardware information +typedef struct +{ + // port to be used + WORD wPort; + + // irq to use + WORD wIRQ; + + // dma channel to se + WORD wDMA; + + // extra parameter + WORD wParam; + +} _SOS_HARDWARE; + +// structure definition for start sample +typedef struct +{ + // pointer to sample + LPSTR lpSamplePtr; + + // size of the sample + WORD dwSampleSize; + + // number of times to loop the sample -1 is infinite + WORD wLoopCount; + + // channel to play sample on + WORD wChannel; + + // volume to play sample at + WORD wVolume; + + // id for the sample + WORD wSampleID; + + // far pointer to the callback function + VOID ( far cdecl *lpCallback )( WORD, WORD, WORD ); + + // port to use if driver is a non-dma background driver + WORD wSamplePort; + + // flags field + WORD wSampleFlags; + + // total length of sample including loops, etc.. + WORD dwSampleByteLength; + + // loop point for the sample + WORD dwSampleLoopPoint; + WORD dwSampleLoopLength; + + // pitch shifting components + WORD dwSamplePitchAdd; + WORD wSamplePitchFraction; + + // pan components + WORD wSamplePanLocation; + WORD wSamplePanSpeed; + WORD wSamplePanDirection; + WORD wSamplePanStart; + WORD wSamplePanEnd; + + // delay parts + WORD wSampleDelayBytes; + WORD wSampleDelayRepeat; + + // compression components + WORD dwSampleADPCMPredicted; + WORD wSampleADPCMIndex; + + // root note for pitch shifting + WORD wSampleRootNoteMIDI; + + // filler for future upgrades + WORD dwSampleTemp1; + WORD dwSampleTemp2; + WORD dwSampleTemp3; + +} _SOS_START_SAMPLE; + +// structure for initializing a driver +typedef struct +{ + WORD wBufferSize; + LPSTR lpBuffer; + BOOL wAllocateBuffer; + WORD wSampleRate; + WORD wParam; + LONG dwParam; + VOID ( far *lpFillHandler )( VOID ); + LPSTR lpDriverMemory; + LPSTR lpDriverMemoryCS; + LPSTR lpTimerMemory; + LPSTR lpTimerMemoryCS; + WORD wTimerID; + WORD wPhysical; + +} _SOS_INIT_DRIVER; + +// define for the timer types to use +#define _SOS_NORMAL_TIMER 0x00 + +// enumeration for the timer types +enum +{ + _TIMER_8_MONO = 0x1000, + _TIMER_8_ST, + _TIMER_16_MONO, + _TIMER_16_ST, + _TIMER_8_MONO_ULAW, + _TIMER_8_ST_ULAW, + _TIMER_16_MONO_ULAW, + _TIMER_16_ST_ULAW, + _TIMER_8_MONO_REC, + _TIMER_8_MONO_ULAW_REC, + _TIMER_UNDEFINED_1, + _TIMER_UNDEFINED_2, + _TIMER_UNDEFINED_3, + _TIMER_UNDEFINED_4, + _TIMER_UNDEFINED_5, + _TIMER_UNDEFINED_6, + _TIMER_UNDEFINED_7, + _TIMER_UNDEFINED_8, + _TIMER_UNDEFINED_9, + _TIMER_UNDEFINED_A, + _TIMER_UNDEFINED_B, + _TIMER_UNDEFINED_C, + _TIMER_UNDEFINED_D, + _TIMER_UNDEFINED_E, + _TIMER_UNDEFINED_F, + _TIMER_UNDEFINED_10, + _TIMER_UNDEFINED_11, + _TIMER_UNDEFINED_12, + _TIMER_UNDEFINED_13, + _TIMER_UNDEFINED_14, + _TIMER_UNDEFINED_15, + _TIMER_UNDEFINED_16, + _TIMER_8_SOUND_SOURCE, + _TIMER_8_SOUND_SOURCE_TANDY, + _TIMER_8_GENERAL_PORT, + _TIMER_8_GENERAL_PORT_REC +}; + +// define for no slots available +#define _ERR_NO_SLOTS ( WORD )-1 + +// error codes for the system +enum +{ + _ERR_NO_ERROR, + _ERR_DRIVER_NOT_LOADED, + _ERR_INVALID_POINTER, + _ERR_DETECT_INITIALIZED, + _ERR_FAIL_ON_FILE_OPEN, + _ERR_MEMORY_FAIL, + _ERR_INVALID_DRIVER_ID, + _ERR_NO_DRIVER_FOUND, + _ERR_DETECTION_FAILURE, + _ERR_DRIVER_LOADED, + _ERR_INVALID_HANDLE, + _ERR_NO_HANDLES, + _ERR_PAUSED, + _ERR_NOT_PAUSED, + _ERR_INVALID_DATA, + _ERR_DRV_FILE_FAIL, + _ERR_INVALID_PORT, + _ERR_INVALID_IRQ, + _ERR_INVALID_DMA, + _ERR_INVALID_DMA_IRQ, +// STREAM + _ERR_STREAM_PLAYING, + _ERR_STREAM_EMPTY, + _ERR_STREAM_PAUSED, + _ERR_STREAM_NOT_PAUSED +// END +}; + +// maximum number of timer events that can be registered +#define _TIMER_MAX_EVENTS 0x10 + +// flags for the debugging system +#define _SOS_DEBUG_NORMAL 0x0000 +#define _SOS_DEBUG_NO_TIMER 0x0001 +#define _SOS_TIMER_DPMI 0x0002 + +// define for types of DOS extenders +#define _SOS_RATIONAL 0x8000 +#define _SOS_FLASHTECK 0x4000 + +// defines for the types of timers for different +// dos extenders +#define _SOS_TIMER_NEAR 0x8000 +#define _SOS_TIMER_FAR 0x4000 + +// values for callback information +enum +{ + _SAMPLE_PROCESSED, + _SAMPLE_LOOPING, + _SAMPLE_DONE +}; + +// define for special 18.2 callback rate to dos +#define _TIMER_DOS_RATE 0xff00 + +#pragma pack() + +#pragma aux int_3 = "int 3" + +#pragma pack( 1 ) +typedef struct +{ + unsigned region_size; + unsigned offset; + unsigned segment; + unsigned short number_available; + unsigned short number_used; + unsigned page0; + +} EVDS_STRUCT; + +typedef struct +{ + unsigned region_size; + unsigned offset; + unsigned short segment; + unsigned short ID; + unsigned physical; + +} VDS_STRUCT; + +#pragma pack() + +#include "sosdata.h" +#include "sosfnct.h" + +#endif diff --git a/MUNGA_L4/sos/wc/SOSDATA.H b/MUNGA_L4/sos/wc/SOSDATA.H new file mode 100644 index 0000000..fb74154 --- /dev/null +++ b/MUNGA_L4/sos/wc/SOSDATA.H @@ -0,0 +1,110 @@ +/**************************************************************************** + + File : sosdata.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_DATA +#define _SOS_DATA + +#include + +#pragma pack(4) +extern WORD _sosDIGIData_Start; +extern WORD _sosDIGIData_End; +extern WORD _wSOSDriverLinear[]; +extern WORD _wSOSTimerLinear[]; +extern LPSTR _lpSOSDriver[]; +extern LPSTR _lpSOSTimer[]; +extern LPSTR _lpSOSDriverCS[]; +extern LPSTR _lpSOSTimerCS[]; +extern BOOL _wSOSDriverLoaded[]; +extern BOOL _wSOSTimerLoaded[]; +extern BOOL _wSOSDriverInitialized[]; +extern WORD _wSOSOutputRate[]; +extern WORD _wSOSDMABuffersize[]; +extern LONG _dwSOSDMABufferPhysical[]; +extern LPSTR _lpSOSDMABuffer[]; +extern BOOL _wTimerUsed; +extern VOID ( far *_lpSOSFillHandler[] )( VOID ); +extern WORD _wSOSTimerType[]; +extern WORD _wSOSDriverType[]; +extern _SOS_SAMPLE far * _lpSOSSampleList[][ _MAX_VOICES ]; +extern LPWORD _lpSOSDMAIrqCount[]; +extern LPWORD _lpSOSDMAFillCount[]; +extern WORD _wSOSTmrNextCount; +extern VOID ( interrupt far *_lpSOSOldTimer )( VOID ); +extern WORD _wSOSDriverID[]; +extern _SOS_CAPABILITIES _sSOSDriverCaps[]; +extern WORD _wSOSDMAPortList[]; +extern BYTE _bSOSDMAChannel[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern BYTE _pSOSDriverPath[]; +extern BYTE _pSOSTempDriverPath[]; +extern BOOL _wTIMERUsed; +extern WORD _wTIMERValue; +extern VOID ( far * _lpTIMEREvents[] )( VOID ); +extern WORD _wTIMEREventRate[]; +extern WORD _dwTIMEREventFraction[]; +extern WORD _dwTIMEREventFractionCurrent[]; +extern BYTE _bSOSMIDITimerSongHandler[]; +extern BYTE _bSOSMIDISongHandle; +extern WORD _wSOSTimerMemHandle[]; +extern WORD _wSOSDriverMemHandle[]; +extern WORD _wSOSRealSeg[]; + +extern _FILEHEADER _sDETFileHeader; +extern _DRIVERHEADER _sDETDriverHeader; +extern _FILEHEADER sLOADFileHeader; +extern _DRIVERHEADER sLOADDriverHeader; +extern BOOL _wDETInitialized; +extern WORD _wDETLinear; +extern LPSTR _lpDETDriverBuffer; +extern LPSTR _lpDETDriverBufferCS; +extern WORD _hDETFile; +extern DWORD _dwDETDriverIndex; +extern WORD _wDETDriverIndexCur; +extern WORD _wDETMemHandle; +extern LPSOSDEVICECAPS _lpDETDeviceCaps; +extern _SOS_CAPABILITIES _sDETCaps; +extern PSTR _pSOSErrorStrings[]; +extern BOOL _wSOSBufferAllocated[]; +extern BOOL _wSOSSystemInitialized; +extern VDS_STRUCT _sSOSVDSInfo; +extern _SOS_FILL_INFO _sSOSFillInfo; +extern WORD _wSOSTimerEventIndex; +extern WORD _wSOSTimerEntered; +extern WORD _wSOSDriverSize[]; +extern WORD _wSOSTimerSize[]; + +#ifdef __cplusplus +extern "C" { +#endif +extern WORD _sosDIGIData1_Start; +extern WORD _sosDIGIData1_End; +extern WORD _sosDIGIData2_Start; +extern WORD _sosDIGIData2_End; +extern BYTE _bTIMERInstalled; +extern BYTE _bTIMERDPMI; +extern WORD wDetectPort; +extern WORD wDetectIRQ; +extern WORD wDetectDMA; +extern WORD wDetectParam; +#ifdef __cplusplus +} +#endif + +#pragma pack() + +#endif + diff --git a/MUNGA_L4/sos/wc/SOSFNCT.H b/MUNGA_L4/sos/wc/SOSFNCT.H new file mode 100644 index 0000000..264c86e --- /dev/null +++ b/MUNGA_L4/sos/wc/SOSFNCT.H @@ -0,0 +1,208 @@ +/**************************************************************************** + + File : sosfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_FUNCTIONS +#define _SOS_FUNCTIONS + +#ifdef __cplusplus // ECH +extern "C" { +#endif + +#pragma pack(4) + +WORD sosDIGILockMemory ( VOID ); +WORD sosDIGIUnLockMemory ( VOID ); +WORD sosDIGIInitSystem ( LPSTR, WORD ); +WORD sosDIGIUnInitSystem ( VOID ); +WORD sosDIGIInitDriver ( WORD, _SOS_HARDWARE far *, + _SOS_INIT_DRIVER far *, WORD far * ); +WORD sosDIGIUnInitDriver ( WORD, BOOL, BOOL ); +WORD sosDIGILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadDriver ( WORD ); +WORD sosDIGIGetDeviceCaps ( WORD, LPSOSDEVICECAPS ); + +#ifdef PHARLAP +LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * ); +#else +LPSTR sosDIGIAllocateBuffer ( WORD , WORD *, WORD * ); +#endif + +WORD sosDIGIStopSample ( WORD, WORD ); +WORD sosDIGISamplesPlaying ( WORD ); +BOOL sosDIGISampleDone ( WORD, WORD ); +BOOL sosDIGISampleFilling ( WORD, WORD ); +WORD sosDIGIStartSample ( WORD, _SOS_START_SAMPLE far * ); +WORD sosDIGIContinueSample ( WORD, WORD, _SOS_START_SAMPLE far * ); + + +WORD sosDIGIDetectInit ( LPSTR ); +WORD sosDIGIDetectUnInit ( VOID ); +WORD sosDIGIDetectFindHardware ( WORD, _SOS_CAPABILITIES far *, WORD far * ); +WORD sosDIGIDetectFindFirst ( _SOS_CAPABILITIES far *, WORD far * ); +WORD sosDIGIDetectFindNext ( _SOS_CAPABILITIES far *, WORD far * ); +WORD sosDIGIDetectGetSettings ( _SOS_HARDWARE far * ); +WORD sosDIGIDetectGetCaps ( WORD, _SOS_CAPABILITIES far * ); +WORD sosDIGIDetectVerifySettings( _SOS_HARDWARE far * ); +PSTR sosGetErrorString ( WORD ); + +WORD sosDIGILoadTimer ( WORD , LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * ); +WORD sosDIGIUnLoadTimer ( WORD ); + +WORD sosTIMERRegisterEvent ( WORD wCallRate, VOID ( far * lpTimerEvent )( VOID ), WORD far *lpTimerHandle ); +WORD sosTIMERInitSystem ( WORD, WORD ); +WORD sosTIMERUnInitSystem ( WORD ); +WORD sosTIMERSetRate ( WORD ); +WORD sosTIMERRemoveEvent ( WORD ); +WORD sosTIMERAlterEventRate ( WORD, WORD ); +WORD sosTIMERGetEventRate ( WORD ); +VOID far sosTIMEROldHandler ( VOID ); +VOID far sosTIMERHandler ( VOID ); + +// functions in soscntl.c +WORD sosDIGISetSampleVolume ( WORD, WORD, WORD ); +WORD sosDIGIGetSampleVolume ( WORD, WORD ); +WORD sosDIGISetChannel ( WORD, WORD, WORD ); +WORD sosDIGIGetChannel ( WORD, WORD ); +WORD sosDIGIGetBytesProcessed ( WORD, WORD ); +WORD sosDIGIGetLoopCount ( WORD, WORD ); +WORD sosDIGISetPanLocation ( WORD, WORD, WORD ); +WORD sosDIGIGetPanLocation ( WORD, WORD ); +DWORD sosDIGISetPitch ( WORD, WORD, DWORD ); +DWORD sosDIGIGetPitch ( WORD, WORD ); +WORD sosDIGIGetDMAPosition ( WORD ); +WORD sosDIGISetPanSpeed ( WORD, WORD, WORD ); +WORD sosDIGIGetPanSpeed ( WORD, WORD ); +WORD sosDIGIGetSampleID ( WORD, WORD ); +WORD sosDIGIGetSampleHandle ( WORD, WORD ); +WORD sosDIGISetMasterVolume ( WORD, WORD ); +#ifdef PHARLAP +VOID sosFreeVDSPage ( unsigned short, unsigned short, DWORD ); +WORD sosAllocVDSPage ( unsigned short *, unsigned short *, DWORD * ); +#else +WORD sosAllocVDSPage ( LPSTR *, WORD *, WORD * ); +VOID sosFreeVDSPage ( WORD, WORD, LONG ); +#endif + +//#ifdef __cplusplus // ECH +//extern "C" { +//#endif + +#ifdef PHARLAP +extern int cdecl sosRealFree ( int ); +extern BOOL cdecl _sos_read( WORD, LPSTR, WORD, WORD * ); +extern int cdecl sosRealAlloc( int, int *, int * ); +extern void cdecl sosDRVFarMemCopy( LPSTR, LPSTR, WORD ); +extern int cdecl sosGetCS( VOID ); +extern int cdecl sosGetES( VOID ); +#else +extern int cdecl sosRealAlloc ( int, int *, int * ); +extern int cdecl sosRealFree ( int ); +#endif + +// sos driver functions +extern WORD cdecl sosDRVLockMemory ( DWORD, DWORD ); +extern WORD cdecl sosDRVUnLockMemory ( DWORD, DWORD ); +extern void cdecl sosDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * ); +extern void cdecl sosDetDRVGetCapsInfo ( LPSTR, LPSTR, _SOS_CAPABILITIES far * ); +extern void cdecl sosDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_CAPABILITIES far * ); +extern void cdecl sosDRVInit ( LPSTR, LPSTR, int, int, int, int, int, int ); +extern void cdecl sosDRVStart ( LPSTR, LPSTR, int, int ); +extern void cdecl sosDRVSetRate ( LPSTR, LPSTR, int ); +extern void cdecl sosDRVSetAction ( LPSTR, LPSTR ); +extern void cdecl sosDRVStop ( LPSTR, LPSTR ); +extern void cdecl sosDRVUnInit ( LPSTR, LPSTR ); +extern void cdecl sosDRVGetFillInfo ( LPSTR, LPSTR, LPSTR, int, int, int, _SOS_FILL_INFO * ); +extern void cdecl sosFillSampleStructs ( PSTR, LPSTR ); +extern WORD cdecl sosDetDRVExist ( LPSTR, LPSTR ); +extern WORD cdecl sosDetDRVGetSettings ( LPSTR, LPSTR ); +extern WORD cdecl sosDetDRVVerifySettings( LPSTR, WORD, WORD, WORD, LPSTR ); +extern WORD cdecl sosDIGIInitForWindows( WORD ); +extern WORD cdecl sosDIGIUnInitForWindows( WORD ); +extern LPSTR cdecl sosAllocateFarMem ( WORD, PSTR, WORD * ); +extern LPSTR cdecl sosCreateAliasCS ( LPSTR ); +extern VOID cdecl sosFreeSelector ( LPSTR, DWORD ); +extern LPSTR cdecl sosMAKEDOSPtr ( PSTR ); +extern VOID cdecl sosDetDRVSetEnvString ( DWORD, PSTR ); +extern PSTR cdecl sosDetDRVGetEnvString ( DWORD ); +extern VOID cdecl sosDetDRVEnvStringInit ( LPSTR, LPSTR ); +extern VOID cdecl sosDRVSetupCallFunctions( LPSTR, LPSTR, LPSTR, LPSTR ); +extern WORD cdecl sosDRVGetFreeMemory ( VOID ); +extern WORD cdecl sosDRVAllocVDSStruct ( WORD, WORD *, WORD * ); +extern WORD cdecl sosDRVFreeVDSStruct ( WORD, WORD ); +extern WORD cdecl sosDRVIsWindowsActive ( VOID ); +extern WORD cdecl sosDRVVDSGetBuffer ( WORD ); +extern WORD cdecl sosDRVVDSFreeBuffer ( WORD ); +extern WORD cdecl getDS( VOID ); +extern WORD cdecl sosDRVMakeDMASelector ( WORD ); +extern WORD cdecl sosDRVFreeDMASelector ( WORD ); + + +extern void cdecl sosTIMERDRVInit( int wRate, void ( far * )( void ) ); +extern void cdecl sosTIMERDRVUnInit( void ); +extern void cdecl sosTIMERDRVHandler( void ); +extern void cdecl sosTIMERDRVFHandler( void ); +extern void cdecl sosTIMERDRVEnable( void ); +extern void cdecl sosTIMERDRVDisable( void ); +extern void cdecl sosTIMERDRVCallOld( void ); +extern void cdecl sosTIMERDRVSetRate( WORD ); +extern void cdecl sosDIGITimer_Start( void ); +extern void cdecl sosDIGITimer_End( void ); +extern void cdecl sosDIGIDrv_Start( void ); +extern void cdecl sosDIGIDrv_End( void ); +//#ifdef __cplusplus //ECH +//} +//#endif + +// external functions for handling system initialization and +// uninitialization +WORD sosEXDIGInitDriver ( WORD, WORD, WORD, LPSTR, + _SOS_HARDWARE far *, WORD * ); +WORD sosEXDIGIUnInitDriver ( VOID ); + +WORD sosEXDETFindDriver ( WORD, LPSTR, _SOS_HARDWARE far *, + _SOS_CAPABILITIES far * ); + +// memory locking prototypes +VOID sosDIGICaps_Start( VOID ); +VOID sosDIGICaps_End( VOID ); +VOID sosDIGIErr_Start( VOID ); +VOID sosDIGIErr_End( VOID ); +VOID sosDIGITmr_Start( VOID ); +VOID sosDIGITmr_End( VOID ); +VOID sosDIGIStart_Start( VOID ); +VOID sosDIGIStart_End( VOID ); +VOID sosDIGIPlyng_Start( VOID ); +VOID sosDIGIPlyng_End( VOID ); +VOID sosDIGIRate_Start( VOID ); +VOID sosDIGIRate_End( VOID ); +VOID sosDIGIDone_Start( VOID ); +VOID sosDIGIDone_End( VOID ); +VOID sosDIGIDetec_Start( VOID ); +VOID sosDIGIDetec_End( VOID ); +VOID sosDIGIInit_Start( VOID ); +VOID sosDIGIInit_End( VOID ); +VOID sosDIGILoad_Start( VOID ); +VOID sosDIGILoad_End( VOID ); +VOID sosDIGICntl_Start( VOID ); +VOID sosDIGICntl_End( VOID ); + +#pragma pack() + +#ifdef __cplusplus // ECH +} +#endif + +#endif diff --git a/MUNGA_L4/sos/wc/SOSMDATA.H b/MUNGA_L4/sos/wc/SOSMDATA.H new file mode 100644 index 0000000..e6f29c5 --- /dev/null +++ b/MUNGA_L4/sos/wc/SOSMDATA.H @@ -0,0 +1,125 @@ +/**************************************************************************** + + File : sosmdata.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOS_MIDI_DATA +#define _SOS_MIDI_DATA + +#include "sos.h" + +#pragma pack(4) + +extern WORD _wSOSMIDIDriverLinear[]; +extern LPSTR _lpSOSMIDIDriver[]; +extern LPSTR _lpSOSMIDIDriverCS[]; +extern WORD _wSOSMIDIMemHandle[]; +extern BOOL _wSOSMIDIDriverLoaded[]; +extern WORD _wSOSMIDIDriverType[]; +extern WORD _wSOSMIDIDriverID[]; +extern DWORD _dwSOSMIDITrackDeltaCurrent[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDIActiveTracks[]; +extern WORD _wSOSMIDITotalTracks[]; +extern DWORD _dwSOSMIDITrackDeltaTime[][_SOS_MIDI_MAX_TRACKS]; +extern WORD _wSOSMIDISongPaused[]; +extern WORD _wSOSMIDISongMuted[]; +extern BOOL _wSOSMIDISongActive[]; +extern BYTE _bSOSMIDIEventSize[]; +extern BYTE _bSOSMIDIEventSizeControl[]; +extern _SOS_MIDI_CAPABILITIES far * _lpSOSMIDIDriverCaps[]; +extern _SOS_MIDI_TRACK_DEVICE far * _sSOSMIDITrackMap[]; +extern _NDMF_MIDI_EVENT _huge * _lpSOSMIDITrack[][_SOS_MIDI_MAX_TRACKS]; +extern WORD ( cdecl far *_lpSOSMIDIDrvFunction[ _SOS_MIDI_MAX_DRIVERS ][ _SOS_MIDI_DRV_FUNCTIONS ] )( LPSTR, WORD, WORD ); +extern _NDMF_FILE_HEADER far * _sSOSMIDISongHeader[]; +extern _SOS_INIT_DRIVER _sSOSDIGIInitDriver[]; +extern WORD _wSOSMIDIEventHandle[]; +extern BYTE _szSOSMIDIDrvFile[]; +extern _MIDIFILEHEADER _sSOSMIDIDRVFileHeader; +extern _MIDIDRIVERHEADER _sSOSMIDIDRVDriverHeader; +extern BOOL _wSOSMIDISysInititalized; +extern WORD ( cdecl far *_lpSOSMIDICBCKDrvFunctions[] )( LPSTR, WORD, WORD ); +extern VOID ( cdecl far *_lpSOSMIDICBCKFunctions )( LPSTR, WORD, WORD ); +extern WORD _wMIDIDIGISampleQueueHead[]; +extern WORD _wMIDIDIGISampleQueueTail[]; +extern WORD _wMIDIDIGIMaxSamples[]; +extern WORD _wMIDIDIGIUsedSamples[]; +extern _DIGI_QUEUE_ELEMENT _sMIDIDIGIQueue[][ _MAX_VOICES ]; + + +extern WORD ( cdecl far *_lpMIDIDIGIDrvFunctions[] )( LPSTR, WORD, WORD ); +extern _SOS_START_SAMPLE far * _sMIDIDIGIStartSample[][ _MAX_INS ]; +extern _HMI_INS_FILE_HEADER far * _sMIDIDIGIInsFileHeader[]; +extern WORD _wMIDIDIGIDriverHandle[]; +extern WORD _wMIDIDIGIDriverInitialized[]; +extern WORD _wMIDIDIGITimerEventHandle[]; +extern WORD _wMIDIDIGIDriverInitMIDI[]; +extern WORD _wMIDIDIGIVelocitySensing[]; +extern BYTE _szMIDIDIGIInsFileID[]; + +extern BYTE _bSOSMIDIMasterVolume; +extern BYTE _bSOSMIDIDeviceChannelVolume[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIMT32SendData; + +extern LPSTR lpFake; +extern WORD wFake; + +extern _NDMF_TRACK_HEADER _huge *_lpSOSMIDITrackHeaders[][ _SOS_MIDI_MAX_TRACKS ]; +extern BYTE _bSOSMIDIChannelRemap[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIChannelPriority[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerChannel[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIOwnerSong[][ _SOS_MIDI_MAX_CHANNELS ]; +extern _SOS_MIDI_CHANNEL_DATA _sSOSMIDIChannelData[][ _SOS_MIDI_MAX_CHANNELS ][ _SOS_MIDI_MAX_LEVELS ]; +extern BYTE _bSOSMIDIChannelDataIndex[][ _SOS_MIDI_MAX_SONGS ][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIData[]; +extern BYTE _bSOSMIDIData1[]; +extern BYTE _bSOSMIDIDeviceLowPriority[]; +extern WORD _wSOSMIDIChannelStealing; +extern BYTE _bSOSMIDIDeviceChannelActive[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDIDeviceChannelAvailable[][ _SOS_MIDI_MAX_CHANNELS ]; +extern BYTE _bSOSMIDISongHandle; +extern BYTE _szMIDIMIDIFileID[]; +extern BYTE _pSOSMIDIDriverPath[]; +extern BYTE _pSOSMIDITempDriverPath[]; +extern WORD sosMIDIData_Start; +extern WORD sosMIDIData_End; +extern WORD ( cdecl far *_lpSOSMIDIAWEDrvFunctions[5] )( LPSTR, WORD, WORD ); +extern WORD _wSOSGravisTimerHandle; +extern WORD _wSOSMIDISongVolume[]; + +extern _SOS_BRANCH_POINT far * _lpMIDIBranchData[][ _SOS_MIDI_MAX_TRACKS ]; +extern WORD ( far *_lpSOSMIDIBranchCallback[] )( WORD, BYTE, BYTE ); +extern WORD ( far *_lpSOSMIDILoopCallback[] )( WORD, BYTE, BYTE, BYTE ); +extern WORD ( far *_lpSOSMIDITriggerCallback[][ 127 ] )( WORD, BYTE, BYTE ); +extern BYTE _bSOSMIDIBranchOccurred; + +extern WORD _wSOSMIDIVolumeFadeDirection[]; +extern DWORD _dwSOSMIDIVolumeFadeFraction[]; +extern DWORD _dwSOSMIDIVolumeFadeVolume[]; +extern WORD _wSOSMIDIVolumeFadeTicks[]; +extern BYTE _bSOSMIDIHandleVolumeFade[]; +extern WORD _wSOSDIGIMIDIHandle[]; + +extern _SOS_MIDI_DIGI_CHANNEL _sMIDIDIGIChannel[]; + +extern WORD ( cdecl far *_lpMIDIWAVEDrvFunctions[] )( LPSTR, WORD, WORD ); +extern WORD _wSOSMIDIChannelMuted[][ _SOS_MIDI_MAX_CHANNELS ]; + +extern BYTE _szPLYMIDIBuffer[]; +extern WORD _wPLYMIDIBufferIndex; +extern WORD _wSOSMIDIDriverSize[]; + +#pragma pack() + +#endif diff --git a/MUNGA_L4/sos/wc/SOSMFNCT.H b/MUNGA_L4/sos/wc/SOSMFNCT.H new file mode 100644 index 0000000..ce47efb --- /dev/null +++ b/MUNGA_L4/sos/wc/SOSMFNCT.H @@ -0,0 +1,175 @@ +/**************************************************************************** + + File : sosmfnct.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#ifndef _SOS_MIDI_FUNCTIONS +#define _SOS_MIDI_FUNCTIONS + +#ifdef __cplusplus // ECH +extern "C" { +#endif + +#pragma pack(4) + +VOID interrupt far sosMIDITimerHandler ( VOID ); +WORD sosMIDILockMemory ( VOID ); +WORD sosMIDIUnLockMemory ( VOID ); +WORD sosMIDIGetDeviceCaps ( WORD, LPSOSMIDIDEVICECAPS ); +WORD sosMIDIInitSystem ( LPSTR, WORD ); +WORD sosMIDIUnInitSystem ( VOID ); +WORD sosMIDIInitDriver ( WORD, _SOS_MIDI_HARDWARE far *, + _SOS_MIDI_INIT_DRIVER far *, WORD far * ); +WORD sosMIDIUnInitDriver ( WORD, BOOL ); +WORD sosMIDILoadDriver ( WORD, WORD, LPSTR far *, LPSTR far *, PSTR, PSTR, WORD * ); +WORD sosMIDIUnLoadDriver ( WORD ); +WORD sosMIDIInitSong ( _SOS_MIDI_INIT_SONG far *, + _SOS_MIDI_TRACK_DEVICE far *, + WORD far * ); +WORD sosMIDIUnInitSong ( WORD ); +WORD sosMIDIResetSong ( WORD, _SOS_MIDI_INIT_SONG far * ); +WORD sosMIDIStartSong ( WORD ); +WORD sosMIDIStopSong ( WORD ); +WORD sosMIDIPauseSong ( WORD, WORD ); +WORD sosMIDIMuteSong ( WORD ); +WORD sosMIDIUnMuteSong ( WORD ); +WORD sosMIDIResumeSong ( WORD ); +BOOL sosMIDISongDone ( WORD ); +WORD sosMIDISongAlterTempo ( WORD, WORD ); +WORD sosMIDIGetDeltaTime ( LPSTR, DWORD far * ); +WORD sosMIDISongGetTimeToPlay ( WORD ); +BYTE _huge * sosMIDINormalizePtr ( BYTE _huge * ); +WORD sosMIDISetInsData ( WORD, LPSTR, WORD ); +WORD sosMIDIResetDriver ( WORD ); +BOOL sosMIDIHandleMIDIData ( WORD, LPSTR, WORD, WORD ); +WORD sosMIDISendMIDIData ( WORD, LPSTR, WORD ); +// NEW +VOID sosMIDISetTrackState ( WORD, WORD, WORD ); +// END + +// compiled in drivers function interface +LPSTR digiGetCallTable ( VOID ); +LPSTR callbackGetCallTable ( VOID ); +LPSTR aweGetCallTable ( VOID ); + +WORD cdecl far callbackSendData ( LPSTR, WORD, WORD ); +WORD cdecl far callbackInit ( LPSTR, WORD, WORD ); +WORD cdecl far callbackUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far callbackReset ( LPSTR, WORD, WORD ); +WORD cdecl far callbackSetInstrumentData ( LPSTR, WORD, WORD ); + +WORD cdecl far aweSendData ( LPSTR, WORD, WORD ); +WORD cdecl far aweInit ( LPSTR, WORD, WORD ); +WORD cdecl far aweUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far aweReset ( LPSTR, WORD, WORD ); +WORD cdecl far aweSetInstrumentData ( LPSTR, WORD, WORD ); + +// function prototypes +WORD cdecl far digiSendData ( LPSTR, WORD, WORD ); +WORD cdecl far digiInit ( LPSTR, WORD, WORD ); +WORD cdecl far digiUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far digiReset ( LPSTR, WORD, WORD ); +WORD cdecl far digiSetInstrumentData ( LPSTR, WORD, WORD ); + +LPSTR waveGetCallTable ( VOID ); +WORD cdecl far waveSendData ( LPSTR, WORD, WORD ); +WORD cdecl far waveInit ( LPSTR, WORD, WORD ); +WORD cdecl far waveUnInit ( LPSTR, WORD, WORD ); +WORD cdecl far waveReset ( LPSTR, WORD, WORD ); +WORD cdecl far waveSetInstrumentData ( LPSTR, WORD, WORD ); +VOID cdecl far waveSampleCallback( WORD, WORD, WORD ); + +VOID digiQueueInit ( WORD, WORD ); +VOID digiQueueUnInit ( WORD ); +WORD digiQueueAddItem ( WORD, WORD, WORD, WORD, WORD ); +WORD digiQueueGetItem ( WORD, WORD ); +WORD digiQueueGetItemWAVE ( WORD ); +WORD digiQueueDeleteItem ( WORD, WORD ); +WORD digiQueueDeleteItemWAVE ( WORD, WORD ); +WORD digiQueueDeleteItemMIDI ( WORD, WORD, WORD ); +WORD digiQueueFindItemMIDI ( WORD, WORD, WORD ); + +// function prototypes +VOID cdecl far digiSampleCallback( WORD, WORD, WORD ); + +WORD sosMIDIRegisterBranchFunction ( WORD, WORD ( far * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIRegisterLoopFunction ( WORD, WORD ( far * )( WORD, BYTE, BYTE, BYTE ) ); +WORD sosMIDIRegisterTriggerFunction( WORD, BYTE, WORD ( far * )( WORD, BYTE, BYTE ) ); +WORD sosMIDIBranchToTrackLocation ( WORD, BYTE, BYTE ); +WORD sosMIDIBranchToSongLocation ( WORD, BYTE ); + +//#ifdef __cplusplus // ECH +//extern "C" { +//#endif + +extern void cdecl sosMIDIDRVGetCapsInfo( LPSTR, LPSTR, _SOS_MIDI_CAPABILITIES far * ); +extern void cdecl sosMIDIDRVGetCapsPtr ( LPSTR, LPSTR, _SOS_MIDI_CAPABILITIES far * ); +extern void cdecl sosMIDIDRVGetFuncsPtr( LPSTR, LPSTR, LPSTR ); +extern LPSTR cdecl sosMIDIDRVSpecialFunction( LPSTR, LPSTR, WORD ); +extern WORD cdecl xgetES( void ); + +//#ifdef __cplusplus // ECH +//} +//#endif + +BOOL sosMIDIResetChannelStealing ( WORD ); +WORD sosMIDIEnableChannelStealing( WORD ); +VOID far sosMIDISongHandler( VOID ); + +WORD sosMIDISetMT32InsData ( WORD, LPSTR, WORD ); +WORD sosMIDISetMasterVolume ( BYTE ); +VOID far sosMIDIMT32Timer ( VOID ); + +WORD sosMIDISetSongVolume ( WORD, BYTE ); +WORD sosMIDIFadeSong ( WORD, WORD, WORD, BYTE, BYTE, WORD ); + +// functions for memory locking +VOID sosMIDICaps_Start( VOID ); +VOID sosMIDICaps_End( VOID ); +VOID sosMIDICbck_Start( VOID ); +VOID sosMIDICbck_End( VOID ); +VOID sosMIDIDigi_Start( VOID ); +VOID sosMIDIDigi_End( VOID ); +VOID sosMIDIDone_Start( VOID ); +VOID sosMIDIDone_End( VOID ); +VOID sosMIDIDq_Start( VOID ); +VOID sosMIDIDq_End( VOID ); +VOID sosMIDIInit_Start( VOID ); +VOID sosMIDIInit_End( VOID ); +VOID sosMIDIIns_Start( VOID ); +VOID sosMIDIIns_End( VOID ); +VOID sosMIDILoad_Start( VOID ); +VOID sosMIDILoad_End( VOID ); +VOID sosMIDIPause_Start( VOID ); +VOID sosMIDIPause_End( VOID ); +VOID sosMIDIPtr_Start( VOID ); +VOID sosMIDIPtr_End( VOID ); +VOID sosMIDISong_Start( VOID ); +VOID sosMIDISong_End( VOID ); +VOID sosMIDISt_Start( VOID ); +VOID sosMIDISt_End( VOID ); +VOID sosMIDITmpo_Start( VOID ); +VOID sosMIDITmpo_End( VOID ); +VOID sosMIDITmr_Start( VOID ); +VOID sosMIDITmr_End( VOID ); + +void StringOut( BYTE X, BYTE Y, BYTE * String, BYTE Color ); + +#pragma pack() + +#ifdef __cplusplus // ECH +} +#endif + +#endif diff --git a/MUNGA_L4/sos/wc/SOSRES.H b/MUNGA_L4/sos/wc/SOSRES.H new file mode 100644 index 0000000..4191cc2 --- /dev/null +++ b/MUNGA_L4/sos/wc/SOSRES.H @@ -0,0 +1,110 @@ +/**************************************************************************** + + File : sosres.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#define _SOS_RESOURCE +#ifndef _SOS_RESOURCE +#define _SOS_RESOURCE + +// structure for resource file header +typedef struct +{ + // file version + WORD wVersion; + + // file size + LONG dwFileSize; + + // number of resources in file + WORD wResCount; + + // offset of resource data from top of file + LONG dwResOffset; + + // offset of sync track from top of file + LONG dwSyncTrackOffset; + +} _RES_FILE_HEADER; + +// structure for resource block header +typedef struct +{ + // resource id + WORD wID; + + // resource type + WORD wResType; + + // offset of next block + LONG dwNextBlock; + + // size of the current resource information + LONG dwResSize; + + // rate to play block at + WORD wBlockRate; + + // id for the sync track to use + WORD wSyncTrackID; + +} _RES_BLOCK_HEADER; + +// structure for sync mark tag +typedef struct _tagSYNCMARK +{ + // ID of the type of mark being used + WORD wID; + + // location in data of sync mark + LONG dwSyncOffset; + + // length of sync block + LONG dwSyncSize; + + // start sample data + _SOS_START_SAMPLE sampleData; + +} _RES_SYNCMARK; + +typedef union +{ + // structure for sync mark tag + _RES_SYNCMARK syncMark; + +} _RES_TAG; + +// union for filter information for prepareWave +typedef union +{ + // filter type + WORD wFilterID; + + // structure for volume + struct volume + { + WORD wVolume; + }; + + // structure for delay + struct delay + { + WORD wDelaySamples; + }; + +} _SOS_FILTER; + + +#endif + diff --git a/MUNGA_L4/sos/wc/sosdefs.h b/MUNGA_L4/sos/wc/sosdefs.h new file mode 100644 index 0000000..3bd99c0 --- /dev/null +++ b/MUNGA_L4/sos/wc/sosdefs.h @@ -0,0 +1,65 @@ +/**************************************************************************** + + File : sosdefs.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + + +#ifndef _SOSDEFS_DEFINED +#define _SOSDEFS_DEFINED + +#undef _TRUE +#undef _FALSE +#undef _NULL +enum + { + _FALSE, + _TRUE + }; + +#define _NULL 0 + +#ifndef VOID +#define VOID void +#endif +typedef int BOOL; +typedef unsigned int UINT; +typedef unsigned char BYTE; +typedef unsigned WORD; +#ifndef LONG +typedef signed long LONG; +#endif +typedef unsigned long DWORD; + +typedef BYTE * PBYTE; +typedef char near * PSTR; +typedef WORD * PWORD; +typedef LONG * PLONG; +typedef VOID * PVOID; + +typedef BYTE far * LPBYTE; +typedef BYTE far * LPSTR; +typedef WORD far * LPWORD; +typedef LONG far * LPLONG; +typedef VOID far * LPVOID; + +typedef BYTE huge * HPBYTE; +typedef BYTE huge * HPSTR; +typedef WORD huge * HPWORD; +typedef LONG huge * HPLONG; +typedef VOID huge * HPVOID; + +typedef unsigned HANDLE; + +#endif + diff --git a/MUNGA_L4/sos/wc/sosm.h b/MUNGA_L4/sos/wc/sosm.h new file mode 100644 index 0000000..31abbf8 --- /dev/null +++ b/MUNGA_L4/sos/wc/sosm.h @@ -0,0 +1,451 @@ +/**************************************************************************** + + File : sosm.h + + Programmer(s) : Don Fowler, Nick Skrepetos + Date : + + Purpose : Include Files For Zortech C++ Compiler + + Last Updated : + +**************************************************************************** + Copyright(c) 1993,1994 Human Machine Interfaces + All Rights Reserved +****************************************************************************/ + +#pragma once +#include "sosdefs.h" +#include "sos.h" + +#pragma pack(4) + +#define _SOS_MIDI_ERR -1 + +// number of drivers allowed to be open at one time +#define _SOS_MIDI_MAX_DRIVERS 5 + +// maximum number of allowed channels +#define _SOS_MIDI_MAX_CHANNELS 0x10 + +// structure definition for the capabilities +typedef struct +{ + BYTE szDeviceName[ 32 ]; // device name + WORD wDeviceVersion; // device version + WORD wFlags; // miscellaneous flags + WORD wProcessData; // process data before sending to driver + short far * lpPortList; // list of usable ports + short far * lpIRQList; // list of usable irq channels + WORD wDeviceID; // ID for the device + +} _SOS_MIDI_CAPABILITIES; + +#define LPSOSMIDIDEVICECAPS _SOS_MIDI_CAPABILITIES far * + +// call indexes for the loadable drivers +enum +{ + _DRV_MIDI_GET_CAPS, + _DRV_MIDI_GET_CALL_TABLE, + _DRV_MIDI_SPECIAL1 +}; + +// file header for the driver +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // number of drivers in the file + WORD wDrivers; + + // offset of first driver + WORD lOffset; + + // size of the file + WORD lFileSize; + +} _MIDIFILEHEADER; + +// driver header structure +typedef struct +{ + // name ID + BYTE szName[ 32 ]; + + // offset of next driver + WORD lNextDriver; + + // size of current driver + WORD wSize; + + // id for the current device + WORD wDeviceID; + + // id for the extender type + WORD wExtenderType; + +} _MIDIDRIVERHEADER; + +// device hardware information +typedef struct +{ + // port to be used + WORD wPort; + + // IRQ for the board + WORD wIRQ; + + // extra parameter + WORD wParam; + +} _SOS_MIDI_HARDWARE; + +// structure for initializing a digital driver +typedef struct +{ + // ID for the digital driver + WORD wDriverID; + + // timer rate to use + WORD wTimerRate; + + // timer callback rate to use + WORD wTimerCallbackRate; + + // max voices for the driver to use + WORD wMaxVoices; + + // velocity sensing flag + WORD wVelocitySensing; + + // init driver info + _SOS_INIT_DRIVER far * sDIGIDriverInfo; + + // hardware information + _SOS_HARDWARE far * sDIGIHardwareInfo; + +} _SOS_MIDI_DIGI_INIT_DRIVER; + +// structure for initializing a driver +typedef struct +{ + // type of driver to use if using a digital driver + WORD wDIGIDriverID; + + // pointer to driver memory + VOID far * lpDriverMemory; + VOID far * lpDriverMemoryCS; + + // pointer to digital driver initialization information + _SOS_MIDI_DIGI_INIT_DRIVER far * sDIGIInitInfo; + + // miscellaneous WORD parameter for driver + WORD wParam; + + // miscellaneous DWORD parameter for driver + DWORD dwParam; + +} _SOS_MIDI_INIT_DRIVER; + +// structure for starting a song +typedef struct +{ + // pointer to song memory + BYTE _huge * lpSongData; + + // pointer to callback function for pertinent song information + VOID ( far * lpSongCallback )( WORD ); + +} _SOS_MIDI_INIT_SONG; + +// define to indicate that track mapping can be used +// from the midi file for the song +#define _MIDI_MAP_TRACK 0xff + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ]; + +} _SOS_MIDI_TRACK_DEVICE; + +// MIDI channel to device mapping structure +typedef struct +{ + // track to device mapping information + WORD wTrackDevice[ 32 ][ 5 ]; + +} _SOS_MIDI_TRACK_DEVICE1; + +// NEW +// header for the NDMF format MIDI file +typedef struct +{ + // ID for the file + BYTE szFileID[ 32 ]; + + WORD dwBranchOffset; + WORD temp1; + WORD temp2; + WORD temp3; + +// // name of the instrument file to use with the song +// BYTE szInstrumentFile[ 16 ]; + + // number of tracks in the song + WORD wNDMFTracks; + + // ticks/quarter note song is used at + WORD wTicksQuarterNote; + + // tempo + WORD wTempo; + + // time for song to play at current tempo + WORD wTimeToPlay; + + // channel mapping priority information + WORD wChannelPriority[ _SOS_MIDI_MAX_CHANNELS ]; + + // channel mapping information + _SOS_MIDI_TRACK_DEVICE1 sTrackMap; + + // array of flags for which controllers to restore on a loop/branch + BYTE bCtrlRestore[ 128 ]; + + // pointer to callback function for song to call with + // pertinent information + VOID ( far * lpSongCallback )( WORD ); + +} _NDMF_FILE_HEADER; +// END + +// header for the tracks in the NDMF format MIDI file +typedef struct +{ + // track number + WORD wTrackNumber; + + // length of the track + WORD wTrackLength; + + // channel used on the track + WORD wChannel; + +} _NDMF_TRACK_HEADER; + +// MIDI event structure +typedef struct +{ + // dummy name to access midi data from + BYTE bMidiData[ 256 ]; + +} _NDMF_MIDI_EVENT; + +// maximum number of songs that can be played at any time +#define _SOS_MIDI_MAX_SONGS 8 + +// maximum number of tracks that can be used +#define _SOS_MIDI_MAX_TRACKS 32 + +// number of driver functions +#define _SOS_MIDI_DRV_FUNCTIONS 13 + +// enumeration for all of the drv functions +enum +{ + _MIDI_DRV_SEND_DATA, + _MIDI_DRV_INIT, + _MIDI_DRV_UNINIT, + _MIDI_DRV_RESET, + _MIDI_DRV_SET_INST_DATA +}; + +// defines for the loadable driver ids +#define _MIDI_SOUND_MASTER_II 0xa000 +#define _MIDI_MPU_401 0xa001 +#define _MIDI_FM 0xa002 +#define _MIDI_OPL2 0xa002 +#define _MIDI_CALLBACK 0xa003 +#define _MIDI_MT_32 0xa004 +#define _MIDI_DIGI 0xa005 +#define _MIDI_INTERNAL_SPEAKER 0xa006 +#define _MIDI_WAVE_TABLE_SYNTH 0xa007 +#define _MIDI_AWE32 0xa008 +#define _MIDI_OPL3 0xa009 +#define _MIDI_GUS 0xa00a + +// structure for the hmi instrument file header +typedef struct +{ + // file id type + BYTE szFileID[ 32 ]; + + // file version + WORD wFileVersion; + + // size of the file + WORD dwFileSize; + +} _HMI_INS_FILE_HEADER; + + +// define for identifying a drum instrument +#define _SOS_MIDI_DRUM_INS ( short )0x8000 + +// maximum number of timer events that can be registered +#define _TIMER_MAX_EVENTS 0x10 + +// structure for digital driver queue element +typedef struct _tagQueueElement +{ + // handle for the sample + WORD wSampleHandle; + + // id for the sample + WORD wSampleID; + + // velocity for the sample + WORD wVelocity; + + // channel for the sample + WORD wChannel; + +} _DIGI_QUEUE_ELEMENT; + +// maximum number of instruments that can be set in the +// digital driver +#define _MAX_INS 128 + +// define for the maximum number of times a channel can be stolen +#define _SOS_MIDI_MAX_LEVELS 0x04 + +// structure for MIDI information to be stored on the local stack +// when a channel is stolen +typedef struct +{ + // used element + BYTE bUsed; + + // last pitch bend information sent + BYTE bPitchBend; + + // channel volume + BYTE bChannelVolume; + + // instrument information + BYTE bInstrument; + + // sustain pedal + BYTE bSustain; + +} _SOS_MIDI_CHANNEL_DATA; + +// flags for the debugging system +#define _SOS_DEBUG_NORMAL 0x0000 +#define _SOS_DEBUG_NO_TIMER 0x0001 + +// ID for 32 bit MIDI file +#define _SOS_MIDI_FILE_ID "HMIMIDIP" + +// structure for branch location controller +typedef struct +{ + // offset from start of track data + WORD dwOffset; + + // branch ID number + BYTE bBranchID; + + // current instrument + BYTE bInstrument; + + // current loop count for temporary storage + // so that a track can be looped without + // needing any data from the program + BYTE bLoopCount; + + // number of controller messages stored + BYTE bCtrlChangeCount; + + // offset of control change information from start of file + WORD lpCtrlChangeData; + WORD lpCtrlChangeDataTemp; + + // reserved fields + WORD wReserved1; + WORD wReserved2; + +} _SOS_BRANCH_POINT; + +#define _SOS_MIDI_FADE_IN 0x01 +#define _SOS_MIDI_FADE_OUT 0x02 +#define _SOS_MIDI_FADE_OUT_STOP 0x04 + +// structure for digital drums to use to store midi information +typedef struct +{ + // current volume + WORD wVolume; + + // current pan position + WORD wPanPosition; + + // reserved + DWORD dwReserved; + +} _SOS_MIDI_DIGI_CHANNEL; + +// instrument file header structure +typedef struct +{ + // file ID + BYTE szID[ 32 ]; + + // file version + WORD wVersion; + + // instruments in file + WORD wInstruments; + + // list of pointers to start sample structures + _SOS_START_SAMPLE far * lpStartSample[ _MAX_INS ]; + + DWORD temp1; + DWORD temp2; + +} _WAVE_FILE_HEADER; + +#pragma pack() + +// define for the busy error returned from send data +#define _ERR_DRIVER_BUSY 0xf000 + +// NEW +// defines for the looping branch controllers +#define _SOS_SET_FLAG 103 +#define _SOS_RESET_FLAG 104 +#define _SOS_BRANCH1 108 +#define _SOS_BRANCH2 109 +#define _SOS_BRANCH3 110 +#define _SOS_BRANCH4 111 +#define _SOS_BRANCH5 112 +#define _SOS_BRANCH6 113 +#define _SOS_BRANCH7 114 +#define _SOS_BRANCH8 115 +#define _SOS_BRANCH9 116 +#define _SOS_BRANCH10 117 +#define _SOS_BRANCH11 118 +#define _SOS_BRANCH12 119 +#define _SOS_BRANCH13 120 +#define _SOS_BRANCH14 121 + +// define for the program change controller flag +#define _SOS_PROGRAM_CHANGE_FLAG 108 + +// END +#include "sosmdata.h" +#include "sosmfnct.h" \ No newline at end of file diff --git a/MUNGA_L4/tagIdents.h b/MUNGA_L4/tagIdents.h new file mode 100644 index 0000000..f003fbf --- /dev/null +++ b/MUNGA_L4/tagIdents.h @@ -0,0 +1,89 @@ +#pragma once + +enum BIZ_IDENTITIES +{ + COMMENT, + REF_COMMENT, + COMMENT_DICT, + + HEADER, + OLD_COMMENT, + TRAILER, + + TEXTURE = 16, + TEX_MAP, + TEX_MINIFY, + TEX_MAGNIFY, + TEX_ALPHA, + TEX_WRAP_U, + TEX_WRAP_V, + TEX_DETAIL, + TEX_MYSTERY, + + MATERIAL = 32, + MAT_TEXTURE, + MAT_ENVIRONMENT, + MAT_AMBIENT, + MAT_DIFFUSE, + MAT_SPECULAR, + MAT_EMISSIVE, + MAT_OPACITY, + MAT_RAMP, + + RAMP = 48, + RMP_DATA, + + OBJECT = 64, + LOD, + PATCH, + POLYGON, + TRISTRIP, + POLYSTRIP, + PMESH, + PMESH_CONLIST, + SPHERE_LIST, + SPHERE, + LINE_LIST, + TEXT, + TEXT_VAL, + PMESH_CONLIST_NEW, + + VTX_TEX = 96, + + LINE = 128, + + HDR_VERSION = 2002, + HDR_DATE, + HDR_TIME, + HDR_SCALE, + HDR_PRECISION, + HDR_FILETYPE, + GEN_NAME, + HDR_UNIT, + GEN_SCOPE, + + SRF_F_MATERIAL = 2048, + SRF_B_MATERIAL, + SRF_PLANE, + SRF_DRAWMODE, + SRF_DECAL, + SRF_FACETED, + SRF_VERTEX, + SRF_SPECIAL, + SRF_LOCK, + + SPHERE_DICE_V = 2064, + SPHERE_DICE_U, + LINE_THICKNESS, + TEXT_FONT, + TEXT_SCALE, + TEXT_ORIENTATION, + + LOD_DISTANCE = 2070, + LOD_REFERENCE, + LOD_TRANSITION, + + VTX_COLOR = 2096, + VTX_SIZE, + VTX_DIMENSIONS +}; \ No newline at end of file diff --git a/MUNGA_L4/temp.cpp b/MUNGA_L4/temp.cpp new file mode 100644 index 0000000..5b57dd4 --- /dev/null +++ b/MUNGA_L4/temp.cpp @@ -0,0 +1 @@ +#include "L4SERIAL.h" \ No newline at end of file diff --git a/RP/BLOCKER.cpp b/RP/BLOCKER.cpp new file mode 100644 index 0000000..1daf200 --- /dev/null +++ b/RP/BLOCKER.cpp @@ -0,0 +1,271 @@ +#include "rp.h" +#pragma hdrstop + +#include "blocker.h" +#include "..\munga\dropzone.h" +#include "vtv.h" +#include "..\munga\hostmgr.h" +#include "..\munga\app.h" +#include "scorzone.h" +#include "..\munga\nttmgr.h" + +//############################################################################# +//############################### Blocker ############################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Blocker::GetClassDerivations() +{ static Derivation classDerivations(Crusher::GetClassDerivations(), "Blocker"); + return &classDerivations; +} + + +Blocker::SharedData + Blocker::DefaultData( + Blocker::GetClassDerivations(), + Blocker::MessageHandlers, + Blocker::GetAttributeIndex(), + Blocker::StateCount, + (Blocker::MakeHandler)Blocker::Make + ); + +const Receiver::HandlerEntry + Blocker::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Blocker, Score), + MESSAGE_ENTRY(Blocker, DropZoneReply) +}; + +Receiver::MessageHandlerSet + Blocker::MessageHandlers( + ELEMENTS(Blocker::MessageHandlerEntries), + Blocker::MessageHandlerEntries, + Crusher::GetMessageHandlers() + ); + +//############################################################################# +// Message Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void Blocker::DropZoneReplyMessageHandler( + DropZone::ReplyMessage *message + ) +{ + Check(this); + Check(message); + + if (!playerVehicle) + { + CreatePlayerVehicle(message->dropZoneLocation); + InitializePlayerLink(); + SetPerformance(&Blocker::PlayerSimulation); + AlwaysExecute(); + deathCount = 0; + } + else if (deathCount == message->deathCount) + { + if (GetSimulationState() == MissionEndingState) + { + Check_Fpu(); + return; + } + if (GetSimulationState() != DropZoneAcquiredState) + { + ResetAfterDeath(message); + return; + } + } + else + { + return; + } + DeleteAllOffensivePlayers(); + ForceUpdate(); + SetSimulationState(VehicleTranslocatedState); + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + vtv->Reset(message->dropZoneLocation, True); + if (goalEntity) + { + Check(goalEntity); + PointVTVTowardGoal(); + vtv->ForceUpdate(); + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Blocker::AddOffensivePlayer(OffensivePlayer &offensive_player) +{ + Check(this); + Check(offensive_player.offensivePlayer); + RPPlayer *rp_player = offensive_player.offensivePlayer; + // + //--------------------------------------------- + // Death Points awarded if .... + // This Blocker gets hit by a runner + // from the other team with collision Damage! + //--------------------------------------------- + // + if ( (rp_player->playerType == RunnerPlayerType) && + (teamID != rp_player->teamID) && + (offensive_player.damageType == Damage::CollisionDamageType) + ) + { + offensive_player.deathBonus = 500.0f; + } + else + { + offensive_player.deathBonus = 0.0f; + } + offensivePlayerList.AddValue( + &offensive_player, + offensive_player.damageType + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Blocker::ScoreMessageHandler(ScoreMessage *message) +{ + Check(this); + Check(message); + Check(application); + RPPlayer::ScoreMessageHandler(message); + HostManager *host = application->GetHostManager(); + Check(host); + RPPlayer *rp_player = (RPPlayer*) + host->GetEntityPointer(message->pointSender); + if (!rp_player) + { + Check_Fpu(); + return; + } + Check(rp_player); + if ( ((rp_player->playerType == CrusherPlayerType) || (rp_player->playerType == RunnerPlayerType)) && + (rp_player->teamID != teamID) + ) + { + ScoreMessage score_message( + Blocker::ScoreMessageID, + sizeof(Blocker::ScoreMessage), + CrusherScorePointType, + message->scoreAward*1.5f, + GetEntityID() + ); + if(teamRunner) + { + Check(teamRunner); + teamRunner->Dispatch(&score_message); + } + } + + // + // HACK - ECH 7/6/95 - Allow the player vehicle to respond to score + // messages, allows attribute system to be used for scoring + // + Check(playerVehicle); + playerVehicle->RespondToScoreMessage(message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Blocker::PlayerSimulation(Scalar time_slice) +{ + Check(this); + // + //------------------------------------------------------------------------ + // Service the status message queue + //------------------------------------------------------------------------ + // + StatusMessageUpdate(time_slice); + + // + //------------------------------------------------ + // Only one team runner only have to do this once + //------------------------------------------------- + // + Player::PlayerSimulation(time_slice); + if (!teamRunner) + { + InitTeamRunner(); + } + if (teamRunner) + { + Entity *our_vehicle = GetPlayerVehicle(); + Check(our_vehicle); + if (!goalEntity) + { + goalEntity = teamRunner->GetPlayerVehicle(); + if (goalEntity) + { + PointVTVTowardGoal(); + our_vehicle->ForceUpdate(); + } + } + + // + //---------------------------------------------------------------------- + // Otherwise, if we aren't running yet, make sure that we are pointed in + // the correct direction - HACK + //---------------------------------------------------------------------- + // + else if ( + application->GetApplicationState() < Application::RunningMission + ) + { + Scalar alignment = our_vehicle->localToWorld(2,2); + PointVTVTowardGoal(); + if (alignment * goalEntity->localToWorld(2,2) < 0.0f) + { + our_vehicle->ForceUpdate(); + } + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Blocker::Blocker( + MakeMessage *creation_message, + SharedData &shared_data +) +: Crusher(creation_message, shared_data) +{ + StatusMessage + *message = new StatusMessage(NULL,RPStatusMessage::BlockerMessage,1e10); + Register_Object(message); + AddStatusMessage(message); +} + +Blocker::~Blocker() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Blocker* + Blocker::Make(MakeMessage *creation_message) +{ + Check_Fpu(); + return new Blocker(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Blocker::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/BLOCKER.h b/RP/BLOCKER.h new file mode 100644 index 0000000..c5ca69e --- /dev/null +++ b/RP/BLOCKER.h @@ -0,0 +1,72 @@ +#pragma once + +#include "crusher.h" + +//########################################################################## +//########################### Blocker ################################ +//########################################################################## +class Blocker: + public Crusher +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; + +public: + void + DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + void + ScoreMessageHandler(RPPlayer::ScoreMessage *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + + typedef void + (Blocker::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + PlayerSimulation(Scalar time_slice); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + + static Blocker* + Make(MakeMessage *creation_message); + + Blocker( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~Blocker(); + + Logical + TestInstance() const; + + void + AddOffensivePlayer(OffensivePlayer &offensive_player); + + +}; diff --git a/RP/BOOSTER.cpp b/RP/BOOSTER.cpp new file mode 100644 index 0000000..dcc14a5 --- /dev/null +++ b/RP/BOOSTER.cpp @@ -0,0 +1,487 @@ +#include "rp.h" +#pragma hdrstop + +#include "booster.h" +#include "..\munga\controls.h" +#include "rpcnsl.h" +#include "vtv.h" +#include "vtvmppr.h" +#include "..\munga\app.h" +#include "..\munga\hostmgr.h" + +//############################################################################# +// Shared Data Support +// +Booster::SharedData + Booster::DefaultData( + Booster::GetClassDerivations(), + Booster::MessageHandlers, + Booster::GetAttributeIndex(), + Booster::StateCount + ); + +Derivation* Booster::GetClassDerivations() +{ + static Derivation classDerivations(VTVSubsystem::GetClassDerivations(), "Booster"); + return &classDerivations; +} + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + Booster::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Booster, Activate), + MESSAGE_ENTRY(Booster, ConfigureMappables), + MESSAGE_ENTRY(Booster, ChooseButton) +}; + +Receiver::MessageHandlerSet + Booster::MessageHandlers( + ELEMENTS(Booster::MessageHandlerEntries), + Booster::MessageHandlerEntries, + VTVSubsystem::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Booster::ConfigureMappablesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + + //--------------------------------------------------------------------- + // If the hardwired button was pressed, process presses of the mappable + // buttons, otherwise it was released, so erase any temporary mappings + //--------------------------------------------------------------------- + if (message->dataContents > 0) + { + EnterConfiguration( + NULL, // direct target (none here) + this, // receiver + ActivateMessageID, // activation message ID + ChooseButtonMessageID // configuration message ID + ); + } + else + { + ExitConfiguration(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Booster::ChooseButtonMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + // + //--------------------------------------------------------------------- + // Find the control manager of the vehicle, and have it turn off an + // existing mapping of a given type if it is there, otherwise it should + // create a new one + //--------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + VTVControlsMapper* controls = + Cast_Object( + VTVControlsMapper*, + vtv->GetSubsystem(VTV::ControlsMapperSubsystem) + ); + Check(controls); + + controls->AddOrErase(message->dataContents, this, ActivateMessageID); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Booster::ActivateMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + VTV* vtv = GetEntity(); + Check(vtv); + Check(application); + if ( + vtv->GetSimulationState() == VTV::BurningState + || application->GetApplicationState() != Application::RunningMission + ) + { + Check_Fpu(); + return; + } + + if ( + GetSimulationState() != BoosterBurning + && message->dataContents > 0 + && boostersRemaining > 0 + ) + { + SetSimulationState(BoosterBurning); + AlwaysExecute(); + lastPerformance = Now(); + burnTimeRemaining = burnTimeMax; + boostersRemaining -= 1; + ForceUpdate(); + vtv->ForceUpdate(); + + // + //--------------------------------------------------------------- + // Tell the console (if there is one) that we turned on a booster + //--------------------------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVBoosterMessage booster_message(vtv->ownerID, 1); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &booster_message + ); + } + } + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const Booster::IndexEntry + Booster::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Booster, BurnTimeRemaining, burnTimeRemaining), + ATTRIBUTE_ENTRY(Booster, BoostersRemaining, boostersRemaining), + ATTRIBUTE_ENTRY(Booster, ScaleFactor, scaleFactor), + ATTRIBUTE_ENTRY(Booster, SmokeDensity, smokeDensity), + ATTRIBUTE_ENTRY(Booster, PercentDone, percentDone) +}; + +Booster::AttributeIndexSet& Booster::GetAttributeIndex() +{ + static Booster::AttributeIndexSet attributeIndex(ELEMENTS(Booster::AttributePointers), Booster::AttributePointers, VTVSubsystem::GetAttributeIndex()); + return attributeIndex; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Booster::BoosterSimulation(Scalar time_slice) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + + // + //------------------------- + // Apply the Booster + //------------------------- + // + percentDone = (burnTimeMax - burnTimeRemaining) / burnTimeMax; + if(percentDone > 1.0f) + { + percentDone = 1.0f; + } + if(percentDone < 0.0f) + { + percentDone = 0.0f; + } + + switch (GetSimulationState()) + { + case BoosterBurning: + if (burnTimeRemaining > 0.0) + { + scaleFactor = Vector3D(1.0f, 1.0f, 1.0f); + Scalar phase = burnTimeMax - burnTimeRemaining; + if (phase < 0.2f) + { + scaleFactor *= phase/0.2f; + } + else if (burnTimeRemaining < 0.2f) + { + scaleFactor *= burnTimeRemaining; + } + smokeDensity = 1.0f; + burnTimeRemaining -= time_slice; + vtv->localAcceleration.linearMotion.z += acceleration; + vtv->boosterOn = True; + vtv->boosterScale = scaleFactor; + vtv->boosterSmokeDensity = smokeDensity; + } + else + { + SetSimulationState(DefaultState); + ForceUpdate(); + vtv->ForceUpdate(); + scaleFactor = Vector3D::Identity; + smokeDensity = 0.0f; + NeverExecute(); + + // + //---------------------------------------------------------------- + // Tell the console (if there is one) that we turned off a booster + //---------------------------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVBoosterMessage booster_message(vtv->ownerID, 0); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &booster_message + ); + } + } + break; + } + Check_Fpu(); +} + +//############################################################################# +// Damage Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Booster::DeathReset(int reset_command) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + + if (GetSimulationState() == BoosterBurning) + { + // + //---------------------------------------------------------------- + // Tell the console (if there is one) that we turned off a booster + //---------------------------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVBoosterMessage booster_message(vtv->ownerID, 0); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &booster_message + ); + } + } + burnTimeRemaining = 0.0f; + scaleFactor = Vector3D::Identity; + SetSimulationState(DefaultState); + if (reset_command == VTV::FootballReset) + { + boostersRemaining = maxBoosters; + } + NeverExecute(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Booster::DeathShutdown(int) +{ + // + //--------------------------------------------------- + // Don't shutdown anything until we are reincarnated + //--------------------------------------------------- + // + Check_Fpu(); +} + +//############################################################################# +// Constructor and Destructor +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Booster::Booster( + VTV *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + VTVSubsystem( + entity, + subsystem_ID, + subsystem_resource, + DefaultData, + NULL, // not 'direct-mapped' + Booster::ActivateMessageID // message ID to trigger booster + ) +{ + //------------------------------------------- + // Set values + //------------------------------------------- + maxBoosters = subsystem_resource->boosterCount; + boostersRemaining = maxBoosters; + burnTimeMax = subsystem_resource->burnTime; + acceleration = -subsystem_resource->boosterAcceleration; + burnTimeRemaining = 0.0f; // In Seconds + scaleFactor = Vector3D::Identity; + smokeDensity = 0.0f; + percentDone = 1.0f; + NeverExecute(); + + if (entity->GetInstance() != VTV::ReplicantInstance) + { + SetPerformance(&Booster::BoosterSimulation); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Booster::~Booster() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Booster::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ) +{ + Check_Pointer(subsystem_name); + Check_Pointer(subsystem_resource); + Check(subsystem_file); + + if ( + !Subsystem::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + directories + ) + ) + { + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::BoosterClassID; + + // + // Figure out who our voltage source is + // + + if ( + !subsystem_file->GetEntry( + subsystem_name, + "BoosterCount", + &subsystem_resource->boosterCount + ) + ) + { + DEBUG_STREAM << subsystem_name << " missing BoosterCount!\n" << std::flush; + Check_Fpu(); + return False; + } + + if ( + !subsystem_file->GetEntry( + subsystem_name, + "BurnTime", + &subsystem_resource->burnTime + ) + ) + { + DEBUG_STREAM << subsystem_name << " missing BurnTime!\n" << std::flush; + Check_Fpu(); + return False; + } + + if ( + !subsystem_file->GetEntry( + subsystem_name, + "BoosterAcceleration", + &subsystem_resource->boosterAcceleration + ) + ) + { + DEBUG_STREAM << subsystem_name << " missing BoosterAcceleration!\n" << std::flush; + Check_Fpu(); + return False; + } + if (subsystem_resource->boosterAcceleration < 0.0f) + { + DEBUG_STREAM << subsystem_name<<" must have a positive acceleration!\n" << std::flush; + Check_Fpu(); + return False; + } + + Check_Fpu(); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Booster::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/BOOSTER.h b/RP/BOOSTER.h new file mode 100644 index 0000000..5d99c00 --- /dev/null +++ b/RP/BOOSTER.h @@ -0,0 +1,156 @@ +#pragma once + +#include "vtvsub.h" + +//########################################################################## +//##################### Booster::SubsystemResource ################### +//########################################################################## + +struct Booster__SubsystemResource: + public VTVSubsystem::SubsystemResource +{ + int boosterCount; + Scalar + burnTime, + boosterAcceleration; +}; + +//########################################################################## +//############################ Booster ############################### +//########################################################################## + +class Booster: + public VTVSubsystem +{ + friend class VTV; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messageing Support +// +public: + enum { + ActivateMessageID = VTVSubsystem::NextMessageID, + ConfigureMappablesMessageID, + ChooseButtonMessageID, + NextMessageID + }; + + void + ActivateMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigureMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChooseButtonMessageHandler( + ReceiverDataMessageOf *message + ); + +protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + BurnTimeRemainingAttributeID = VTVSubsystem::NextAttributeID, + BoostersRemainingAttributeID, + ScaleFactorAttributeID, + SmokeDensityAttributeID, + PercentDoneAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + ////static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + Scalar burnTimeRemaining; + Scalar boostersRemaining; + Vector3D scaleFactor; + Scalar smokeDensity; + Scalar percentDone; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + enum { + BoosterBurning = Subsystem::StateCount, + StateCount + }; + + typedef void + (Booster::*Performance)(Scalar time_slice); + + void + BoosterSimulation(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Damage Support +// +void + DeathReset(int reset_command); +void + DeathShutdown(int shutdown_command); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef Booster__SubsystemResource SubsystemResource; + + static int + CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ); + + Booster( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Booster(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local data for the Booster class +// +protected: + Scalar burnTimeMax; + Scalar acceleration; + int maxBoosters; +}; diff --git a/RP/CHUTE.cpp b/RP/CHUTE.cpp new file mode 100644 index 0000000..4915e0e --- /dev/null +++ b/RP/CHUTE.cpp @@ -0,0 +1,638 @@ +#include "rp.h" +#pragma hdrstop + +#include "chute.h" +#include "..\munga\fileutil.h" +#include "vtv.h" +#include "..\munga\app.h" +#include "vtvmppr.h" + +//############################################################################# +// Shared Data Support +// +Chute::SharedData + Chute::DefaultData( + Chute::GetClassDerivations(), + Chute::MessageHandlers, + Chute::GetAttributeIndex(), + Chute::StateCount + ); + +Derivation* Chute::GetClassDerivations() +{ static Derivation classDerivations(VTVSubsystem::GetClassDerivations(), "Chute"); + return &classDerivations; +} + + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + Chute::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Chute, Activate), + MESSAGE_ENTRY(Chute, ConfigureMappables), + MESSAGE_ENTRY(Chute, ChooseButton) +}; + +Receiver::MessageHandlerSet + Chute::MessageHandlers( + ELEMENTS(Chute::MessageHandlerEntries), + Chute::MessageHandlerEntries, + VTVSubsystem::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::ConfigureMappablesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + //--------------------------------------------------------------------- + // If the hardwired button was pressed, process presses of the mappable + // buttons, otherwise it was released, so erase any temporary mappings + //--------------------------------------------------------------------- + if (message->dataContents > 0) + { + EnterConfiguration( + NULL, // direct target (none here) + this, // receiver + ActivateMessageID, // activation message ID + ChooseButtonMessageID // configuration message ID + ); + } + else + { + ExitConfiguration(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::ActivateMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + VTV* vtv = GetEntity(); + Check(vtv); + Check(application); + + if ( + vtv->GetSimulationState() == VTV::BurningState + || application->GetApplicationState() != Application::RunningMission + ) + { + Check_Fpu(); + return; + } + + if (message->dataContents > 0) + { + switch (GetSimulationState()) + { + case Ready: + if (vtv->BoosterOn() || DeviantChute()) + { + Check_Fpu(); + return; + } + if (chutesRemaining > 0) + { + SetSimulationState(Deploy); + deployTimeUsed = 0.0f; + chuteOn = 1; + --chutesRemaining; + ForceUpdate(); + lastPerformance = Now(); + AlwaysExecute(); + Check_Fpu(); + } + break; + case Dragging: + ReleaseChute(); + Check_Fpu(); + break; + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::ChooseButtonMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + // + //--------------------------------------------------------------------- + // Find the control manager of the vehicle, and have it turn off an + // existing mapping of a given type if it is there, otherwise it should + // create a new one + //--------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + VTVControlsMapper* controls = + Cast_Object( + VTVControlsMapper*, + vtv->GetSubsystem(VTV::ControlsMapperSubsystem) + ); + Check(controls); + + controls->AddOrErase(message->dataContents, this, ActivateMessageID); + } + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const Chute::IndexEntry + Chute::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Chute, TimeToReady, timeToReady), + ATTRIBUTE_ENTRY(Chute, ChutesRemaining, chutesRemaining), + ATTRIBUTE_ENTRY(Chute, ChuteDirection, chuteDirection), + ATTRIBUTE_ENTRY(Chute, ScaleFactor, scaleFactor), + ATTRIBUTE_ENTRY(Chute, ChuteOn, chuteOn), + ATTRIBUTE_ENTRY(Chute, PercentDone, percentDone) +}; + +Chute::AttributeIndexSet& Chute::GetAttributeIndex() +{ + static Chute::AttributeIndexSet attributeIndex(ELEMENTS(Chute::AttributePointers), Chute::AttributePointers, VTVSubsystem::GetAttributeIndex()); + return attributeIndex; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::ReadUpdateRecord(Simulation::UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + VTVSubsystem::ReadUpdateRecord(message); + UpdateRecord* record = (UpdateRecord*) message; + + chuteDirection = record->chuteDirection; + chuteOn = record->chuteOn; + scaleFactor = record->scaleFactor; + lastPerformance = lastUpdate; + + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::WriteUpdateRecord(Simulation::UpdateRecord *record, int update_model) +{ + Check(this); + Check_Pointer(record); + + VTVSubsystem::WriteUpdateRecord(record, update_model); + UpdateRecord* update = (UpdateRecord*) record; + + update->recordLength = sizeof(*update); + update->chuteDirection = chuteDirection; + update->chuteOn = chuteOn; + update->scaleFactor = scaleFactor; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +static Vector3D forward(0.0f,0.0f,-1.0f); + +void + Chute::ChuteSimulation(Scalar time_slice) +{ + // + //------------------------- + // Apply the Chute + //------------------------- + // + percentDone = percentDone = (reloadTime - timeToReady)/reloadTime; + Check_Fpu(); + + if(percentDone > 1.0f) + { + percentDone = 1.0f; + } + if(percentDone < 0.0f) + { + percentDone = 0.0f; + } + Verify(percentDone >= 0.0f); + Verify(percentDone <= 1.0f); + + int sim_state = GetSimulationState(); + VTV *vtv = GetEntity(); + Check(vtv); + + switch(sim_state) + { + case Loading: + timeToReady -= time_slice; + if (timeToReady <=0.0f) + { + SetSimulationState(Ready); + NeverExecute(); + } + break; + + case Dragging: + if (DeviantChute() || vtv->BoosterOn()) + { + ReleaseChute(); + } + else + { + ApplyDrag(time_slice); + } + break; + + case Deploy: + if (DeviantChute() || vtv->BoosterOn()) + { + ReleaseChute(); + } + else + { + deployTimeUsed += time_slice; + if (deployTimeUsed >= deployTime) + { + scaleFactor.x = 1.0f; + scaleFactor.y = 1.0f; + scaleFactor.z = 1.0f; + SetSimulationState(Dragging); + ForceUpdate(); + } + else + { + deployTimeUsed += time_slice; + scaleFactor.y = scaleFactor.x = ScaleXY(); + scaleFactor.z = ScaleZ(); + deployTimeUsed += time_slice; + } + AlwaysExecute(); + } + ApplyDrag(time_slice); + break; + + case Released: + SetSimulationState(Loading); + break; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::PointChute(Scalar) +{ + if (GetSimulationState() != Dragging || GetSimulationState() != Deploy) + { + Check_Fpu(); + return; + } + + VTV* vtv = GetEntity(); + Check(vtv); + if (!Small_Enough(vtv->localVelocity.linearMotion.LengthSquared())) + { + chuteDirection.Subtract(vtv->localVelocity.linearMotion, forward); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar + Chute::ScaleZ() +{ + Scalar + top_half = 2*(deployTimeUsed) -1 / (deployTimeUsed) + 1; + Scalar + bottom_half = 2*(deployTime) -1 / (deployTime) + 1; + + Scalar result = top_half/bottom_half; + + Check_Fpu(); + return result; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Scalar Chute::ScaleXY() +{ + Scalar + top_half = (deployTimeUsed)*(deployTimeUsed)*(deployTimeUsed); + Check_Fpu(); + + Scalar + bottom_half = (deployTime)*(deployTime)*(deployTime); + + Check_Fpu(); + Scalar result = top_half/bottom_half; + + Check_Fpu(); + + return result; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::ReleaseChute() +{ + SetSimulationState(Released); + chuteOn = 0; + ForceUpdate(); + if (GetEntity()->GetInstance() == VTV::ReplicantInstance) + { + NeverExecute(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void Chute::ApplyDrag(Scalar) +{ + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + + // + // If slow enough automatically release the chute + // + Scalar vel2 = vtv->localVelocity.linearMotion.LengthSquared(); + if(vel2 < minVelocity) + { + ReleaseChute(); + Check_Fpu(); + return; + } + + // + // Calculate the direction to point the chute in + // + chuteDirection.Subtract(vtv->localVelocity.linearMotion, forward); + + // + // Calculate the dragForce to Apply to the VTV + // + Vector3D force; + force.Negate(vtv->localVelocity.linearMotion); + force *= dragForce; + vtv->ApplyLocalAcceleration(force, chuteOffset); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + Chute::DeviantChute() +{ + Check(this); + VTV *vtv = GetEntity(); + Check(vtv); + Check_Fpu(); + return vtv->localVelocity.linearMotion.z > zDeviation; +} + +//############################################################################# +// Damage Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Chute::DeathReset(int reset_command) +{ + Check(this); + if (reset_command == VTV::FootballReset) + { + chutesRemaining = chuteCount; + } + if (reset_command != VTV::MissionReviewReset) + { + SetSimulationState(Ready); + timeToReady = 0.0f; + } + NeverExecute(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void + Chute::DeathShutdown(int) +{ + chuteOn = False; + chuteDirection = Quaternion::Identity; + NeverExecute(); + Check_Fpu(); +} + +//############################################################################# +// Contructor and Destructor +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Chute::Chute( + VTV *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + VTVSubsystem( + entity, + subsystem_ID, + subsystem_resource, + DefaultData, + NULL, // assumes no direct controls mapping + Chute::ActivateMessageID // message ID used for activation + ), + scaleFactor(0.0f,0.0f,0.0f) +{ + //------------------------------------------- + // Set values + //------------------------------------------- + chuteOn = 0; + chuteCount = subsystem_resource->chuteCount; + chutesRemaining = chuteCount; + reloadTime = subsystem_resource->reloadTime; + dragForce = subsystem_resource->dragForce; + deployTime = subsystem_resource->deployTime; + deployTimeUsed = 0.0f; + EntitySegment *site_front_segment = + entity->GetSegment(subsystem_resource->segmentIndex); + + chuteOffset = site_front_segment->GetSegmentToEntity(); + + minVelocity = + subsystem_resource->minVelocity * subsystem_resource->minVelocity; + zDeviation = subsystem_resource->zDeviation; + timeToReady = 0.0f; + chuteDirection = Quaternion::Identity; + percentDone = 1.0f; + SetSimulationState(Ready); + SetPerformance(&Chute::ChuteSimulation); + NeverExecute(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Chute::~Chute() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Chute::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ) +{ + Check(model_file); + Check_Pointer(subsystem_name); + Check_Pointer(subsystem_resource); + Check(subsystem_file); + + if ( + !Subsystem::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + directories + ) + ) + { + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::ChuteClassID; + + // + // Figure out who our voltage source is + // + + if ( + !subsystem_file->GetEntry( + subsystem_name, + "ChuteCount", + &subsystem_resource->chuteCount + ) + ) + { + std::cerr << subsystem_name << " missing ChuteCount!\n"; + return False; + } + + if ( + !subsystem_file->GetEntry( + subsystem_name, + "ReloadTime", + &subsystem_resource->reloadTime + ) + ) + { + std::cerr << subsystem_name << " missing ReloadTime!\n"; + return False; + } + + if ( + !subsystem_file->GetEntry( + subsystem_name, + "DragForce", + &subsystem_resource->dragForce + ) + ) + { + std::cerr << subsystem_name << " missing DragForce!\n"; + return False; + } + if ( + !subsystem_file->GetEntry( + subsystem_name, + "MinVelocity", + &subsystem_resource->minVelocity + ) + ) + { + std::cerr << subsystem_name << " missing MinVelocity!\n"; + return False; + } + if ( + !subsystem_file->GetEntry( + subsystem_name, + "DeployTime", + &subsystem_resource->deployTime + ) + ) + { + std::cerr << subsystem_name << " missing DeployTime!\n"; + return False; + } + Scalar degree; + if ( + !subsystem_file->GetEntry( + subsystem_name, + "MaxRotation", + °ree + ) + ) + { + std::cerr << subsystem_name << " missing MaxRotation!\n"; + return False; + } + else + { + Radian rad(degree); + subsystem_resource->zDeviation = cos(rad); + } + if (subsystem_resource->dragForce < 0.0f) + { + std::cerr << subsystem_name << " must have a positive dragForce!\n"; + return False; + } + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Chute::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/CHUTE.h b/RP/CHUTE.h new file mode 100644 index 0000000..2ba6f3a --- /dev/null +++ b/RP/CHUTE.h @@ -0,0 +1,230 @@ +#pragma once + +#include "vtvsub.h" +#include "..\munga\rotation.h" + +//########################################################################## +//##################### Chute::UpdateRecord ##################### +//########################################################################## + +struct Chute__UpdateRecord : + public VTVSubsystem::UpdateRecord +{ + Quaternion + chuteDirection; + Vector3D + scaleFactor; + int + chuteOn; +}; + +//########################################################################## +//##################### Chute::SubsystemResource ##################### +//########################################################################## + +struct Chute__SubsystemResource: + public VTVSubsystem::SubsystemResource +{ + int chuteCount; + Scalar + reloadTime, + dragForce, + minVelocity; + + Scalar + deployTime; + Scalar + zDeviation; +}; + +//########################################################################## +//############################ Chute ############################### +//########################################################################## + +class Chute: + public VTVSubsystem +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messageing Support +// +public: + enum { + ActivateMessageID = VTVSubsystem::NextMessageID, + ConfigureMappablesMessageID, + ChooseButtonMessageID, + NextMessageID + }; + + void + ActivateMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigureMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChooseButtonMessageHandler( + ReceiverDataMessageOf *message + ); + +protected: + + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + TimeToReadyAttributeID = VTVSubsystem::NextAttributeID, + ChutesRemainingAttributeID, + ChuteDirectionAttributeID, + ScaleFactorAttributeID, + ChuteOnAttributeID, + PercentDoneAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + Scalar + timeToReady; + Scalar + chutesRemaining; + Quaternion + chuteDirection; + Vector3D + scaleFactor; + int + chuteOn; + Scalar + percentDone; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + enum { + Released = VTVSubsystem::StateCount, + Deploy, + Loading, + Ready, + Dragging, + StateCount + }; + typedef Chute__UpdateRecord UpdateRecord; + + typedef void + (Chute::*Performance)(Scalar time_slice); + + void + ChuteSimulation(Scalar time_slice); + void + PointChute(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + VTV* + GetEntity() + {Check(this); return Cast_Object(VTV*, Subsystem::GetEntity());} + +protected: + void + WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Damage Support +// +void + DeathReset(int reset_command); +void + DeathShutdown(int shutdown_command); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef Chute__SubsystemResource SubsystemResource; + + static int + CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + const ResourceDirectories *directories + ); + + Chute( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Chute(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local data for the Chute class +// +private: + int chuteCount; + Scalar reloadTime; + Scalar dragForce; + Scalar minVelocity; + + Point3D + chuteOffset; + + Scalar + deployTime, + deployTimeUsed; + + Scalar + zDeviation; + + void + ApplyDrag(Scalar time_slice); + + int + DeviantChute(); + + void + ReleaseChute(); + + + Scalar + ScaleZ(); + + Scalar + ScaleXY(); + +}; \ No newline at end of file diff --git a/RP/CRUSHER.cpp b/RP/CRUSHER.cpp new file mode 100644 index 0000000..a465558 --- /dev/null +++ b/RP/CRUSHER.cpp @@ -0,0 +1,433 @@ +#include "rp.h" +#pragma hdrstop + +#include "crusher.h" +#include "..\munga\dropzone.h" +#include "vtv.h" +#include "..\munga\hostmgr.h" +#include "..\munga\app.h" +#include "scorzone.h" +#include "..\munga\nttmgr.h" + +//############################################################################# +//############################### Crusher ############################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Crusher::GetClassDerivations() +{ static Derivation classDerivations(RPPlayer::GetClassDerivations(), "Crusher"); + return &classDerivations; +} + + +Crusher::SharedData + Crusher::DefaultData( + Crusher::GetClassDerivations(), + Crusher::GetMessageHandlers(), + Crusher::GetAttributeIndex(), + Crusher::StateCount, + (Crusher::MakeHandler)Crusher::Make + ); + +const Receiver::HandlerEntry + Crusher::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Crusher, Score), + MESSAGE_ENTRY(Crusher, DropZoneReply), + MESSAGE_ENTRY(Crusher, ScoreZoneReply) +}; + +Receiver::MessageHandlerSet& Crusher::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(Crusher::MessageHandlerEntries), Crusher::MessageHandlerEntries, RPPlayer::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Message Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void Crusher::DropZoneReplyMessageHandler( + DropZone::ReplyMessage *message + ) +{ + Check(this); + Check(message); + + if (!playerVehicle) + { + CreatePlayerVehicle(message->dropZoneLocation); + InitializePlayerLink(); + SetPerformance(&Crusher::PlayerSimulation); + AlwaysExecute(); + deathCount = 0; + } + else if (deathCount == message->deathCount) + { + if (GetSimulationState() == MissionEndingState) + { + Check_Fpu(); + return; + } + if (GetSimulationState() != DropZoneAcquiredState) + { + ResetAfterDeath(message); + Check_Fpu(); + return; + } + } + else + { + Check_Fpu(); + return; + } + DeleteAllOffensivePlayers(); + ForceUpdate(); + SetSimulationState(VehicleTranslocatedState); + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + vtv->Reset(message->dropZoneLocation, True); + if (goalEntity) + { + Check(goalEntity); + PointVTVTowardGoal(); + vtv->ForceUpdate(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Crusher::AddOffensivePlayer(OffensivePlayer &offensive_player) +{ + Check(this); + Check(offensive_player.offensivePlayer); + RPPlayer *rp_player = offensive_player.offensivePlayer; + // + //--------------------------------------------- + // Damage & Death Points awarded if .... + // This Crusher gets hit by a runner or a Blocker + // from the other team with collision Damage! + //--------------------------------------------- + // + if ( + ( + rp_player->playerType == BlockerPlayerType + || rp_player->playerType == RunnerPlayerType + ) + && teamID != rp_player->teamID + && offensive_player.damageType == Damage::CollisionDamageType + ) + { + offensive_player.deathBonus = 500.0f; + } + else + { + offensive_player.deathBonus = 0.0f; + } + offensivePlayerList.AddValue( + &offensive_player, + offensive_player.damageType + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Crusher::ScoreMessageHandler(ScoreMessage *message) +{ + Check(this); + Check(message); + Check(application); + + RPPlayer::ScoreMessageHandler(message); + HostManager *host = application->GetHostManager(); + Check(host); + RPPlayer *rp_player = (RPPlayer*) + host->GetEntityPointer(message->pointSender); + if (!rp_player) + { + Check_Fpu(); + return; + } + + Check(rp_player); + if ( + rp_player->playerType == RunnerPlayerType + && rp_player->teamID != teamID + ) + { + Scalar score_award = message->scoreAward * 2.0f; + // + //------------------------------------------------------ + // Create the score award and pass it on to the runner + //------------------------------------------------------ + // + ScoreMessage score_message( + RPPlayer::ScoreMessageID, + sizeof(RPPlayer::ScoreMessage), + CrusherScorePointType, + score_award, + GetEntityID() + ); + if (teamRunner) + { + Check(teamRunner); + teamRunner->Dispatch(&score_message); + } + } + + // + // HACK - ECH 7/6/95 - Allow the player vehicle to respond to score + // messages, allows attribute system to be used for scoring + // + Check(playerVehicle); + playerVehicle->RespondToScoreMessage(message); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Crusher::ScoreZoneReplyMessageHandler( + ScoreZone::ReplyMessage *//message + ) +{ + //empty +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Crusher::PlayerSimulation(Scalar time_slice) +{ + Check(this); + // + //------------------------------------------------------------------------ + // Service the status message queue + //------------------------------------------------------------------------ + // + StatusMessageUpdate(time_slice); + + // + //----------------------------------- + // Find the runners if we haven't yet + //----------------------------------- + // + Player::PlayerSimulation(time_slice); + InitTeamRunner(); + + // + //-------------------------------------------------------------------------- + // If we know who the enemy is, but not what his vehicle is, try to find the + // vehicle + //-------------------------------------------------------------------------- + // + if (enemyRunner) + { + Entity *our_vehicle = GetPlayerVehicle(); + Check(our_vehicle); + if (!goalEntity) + { + goalEntity = enemyRunner->GetPlayerVehicle(); + if (goalEntity) + { + PointVTVTowardGoal(); + our_vehicle->ForceUpdate(); + } + } + + // + //---------------------------------------------------------------------- + // Otherwise, if we aren't running yet, make sure that we are pointed in + // the correct direction - HACK + //---------------------------------------------------------------------- + // + else if ( + application->GetApplicationState() < Application::RunningMission + ) + { + Scalar alignment = our_vehicle->localToWorld(2,2); + PointVTVTowardGoal(); + if (alignment * goalEntity->localToWorld(2,2) < 0.0f) + { + our_vehicle->ForceUpdate(); + } + } + + // + //---------------------------------------------- + // If the game is running, set the goal properly + //---------------------------------------------- + // + else + { + goalEntity = enemyRunner->GetPlayerVehicle(); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Crusher::PointVTVTowardGoal() +{ + Check(this); + Vector3D to_goal(Vector3D::Identity); + + if (goalEntity) + { + // + //------------------------------ + // Find the distance to the goal + //------------------------------ + // + + to_goal.Subtract( + goalEntity->localOrigin.linearPosition, + playerVehicle->localOrigin.linearPosition + ); + + Scalar length_to_goal; + length_to_goal = to_goal.LengthSquared(); + + // + //---------------------------- + // Less than 100 meters away? + //---------------------------- + // + if (length_to_goal < 10000.0f) + { + // + //----------------------------------------------- + // The goalEntity is in front of us so point in + // the same direction as the goalEntity + //----------------------------------------------- + // + playerVehicle->localOrigin.angularPosition.x = 0.0f; + playerVehicle->localOrigin.angularPosition.z = 0.0f; + if (goalEntity->localToWorld(2,2) >= 0.0f) + { + playerVehicle->localOrigin.angularPosition.y = 0.0f; + playerVehicle->localOrigin.angularPosition.w = 1.0f; + } + else + { + playerVehicle->localOrigin.angularPosition.y = 1.0f; + playerVehicle->localOrigin.angularPosition.w = 0.0f; + } + } + else + { + // + //--------------------------------- + // Point toward the goal Entity + // disregard and Y direction + //--------------------------------- + // + playerVehicle->localOrigin.angularPosition.x = 0.0f; + playerVehicle->localOrigin.angularPosition.z = 0.0f; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // is the goal in front or behind me + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (to_goal.z <= 0.0f) + { + playerVehicle->localOrigin.angularPosition.y = 0.0f; + playerVehicle->localOrigin.angularPosition.w = 1.0f; + } + else + { + playerVehicle->localOrigin.angularPosition.y = 1.0f; + playerVehicle->localOrigin.angularPosition.w = 0.0f; + } + } + playerVehicle->localToWorld = playerVehicle->localOrigin; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Crusher::Crusher( + MakeMessage *creation_message, + SharedData &shared_data +) +: RPPlayer(creation_message, shared_data) +{ + StatusMessage + *message = new StatusMessage(NULL,RPStatusMessage::CrusherMessage,1e10); + Register_Object(message); + AddStatusMessage(message); + + teamRunner = NULL; + enemyRunner = NULL; + Check_Fpu(); +} + +Crusher::~Crusher() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Crusher* + Crusher::Make(MakeMessage *creation_message) +{ + Check_Fpu(); + return new Crusher(creation_message); +} + +//############################################################################# +// +void + Crusher::InitTeamRunner() +{ + Check(this); + + Check(application); + EntityManager *entity_mgr = application->GetEntityManager(); + Check(entity_mgr); + EntityGroup *runner_group = entity_mgr->FindGroup("RunnerPlayers"); + if(runner_group) + { + Check(runner_group); + ChainIteratorOf iterator(runner_group->groupMembers); + RPPlayer *runner; + int winning_rank = 10000; + while ((runner = (RPPlayer*) iterator.ReadAndNext()) != NULL) + { + Check(runner); + if (runner->teamID == teamID) + { + teamRunner = runner; + } + else + { + if (runner->playerRanking < winning_rank) + { + enemyRunner = runner; + winning_rank = runner->playerRanking; + } + } + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Crusher::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/CRUSHER.h b/RP/CRUSHER.h new file mode 100644 index 0000000..b438cc7 --- /dev/null +++ b/RP/CRUSHER.h @@ -0,0 +1,81 @@ +#pragma once + +#include "rpplayer.h" + +//########################################################################## +//########################### Crusher ################################ +//########################################################################## +class Crusher: + public RPPlayer +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +public: + void + DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + void + ScoreZoneReplyMessageHandler(ScoreZone__ReplyMessage *message); + void + ScoreMessageHandler(RPPlayer::ScoreMessage *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + + typedef void + (Crusher::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + PlayerSimulation(Scalar time_slice); + + RPPlayer + *teamRunner, + *enemyRunner; + + void + InitTeamRunner(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + static Crusher* + Make(MakeMessage *creation_message); + + Crusher( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~Crusher(); + + Logical + TestInstance() const; + +void + AddOffensivePlayer(OffensivePlayer &offensive_player); + + void + PointVTVTowardGoal(); +}; diff --git a/RP/DEMOPACK.cpp b/RP/DEMOPACK.cpp new file mode 100644 index 0000000..9cf104c --- /dev/null +++ b/RP/DEMOPACK.cpp @@ -0,0 +1,581 @@ +#include "rp.h" +#pragma hdrstop + +#include "demopack.h" +#include "..\munga\line.h" +#include "..\munga\explode.h" +#include "..\munga\boxsolid.h" +#include "..\munga\collasst.h" +#include "..\munga\app.h" +#include "..\munga\interest.h" +#include "vtv.h" +#include "..\munga\hostmgr.h" +#include "..\munga\notation.h" + +//############################################################################# +// Shared Data Support +// +Derivation* DemolitionPack::GetClassDerivations() +{ static Derivation classDerivations(Rivet::GetClassDerivations(), "DemolitionPack"); + return &classDerivations; +} + + +DemolitionPack::SharedData + DemolitionPack::DefaultData( + DemolitionPack::GetClassDerivations(), + DemolitionPack::GetMessageHandlers(), + DemolitionPack::GetAttributeIndex(), + DemolitionPack::StateCount, + (Entity::MakeHandler)DemolitionPack::Make + ); + +//############################################################################# +// Attribute Support +// +#if 0 +const DemolitionPack::IndexEntry + DemolitionPack::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(DemolitionPack, DamageData, damageData) +}; + +DemolitionPack::AttributeIndexSet& DemolitionPack::GetAttributeIndex() +{ + static DemolitionPack::AttributeIndexSet attributeIndex(ELEMENTS(DemolitionPack::AttributePointers), DemolitionPack::AttributePointers, Mover::GetAttributeIndex()); + return attributeIndex; +} +#endif + +//############################################################################# +// Model support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DemolitionPack::MoveAndHunt(Scalar time_slice) +{ + Line + distance_traveled; + distance_traveled = localOrigin.linearPosition; + + // + //----------------------------------------------------------------- + // Apply the standard air resistance and gravity, then project the + // Projectile motion through the time slice and look for collisions + //----------------------------------------------------------------- + // + ApplyAirResistanceAndGravity(); + Point3D old_position(localOrigin.linearPosition); + ApplyWorldAccelerations(time_slice); + + // + //-------------------- + // Do a collision test + //-------------------- + // + MoveCollisionVolume(); + BoxedSolidCollisionList* + collision_list = GetCurrentCollisions(); + + // + //--------------------------------------------------------------------- + // If our solid didn't hit anything, and we are going fast enough, do a + // ray-cast + //--------------------------------------------------------------------- + // + if (!collision_list->GetCollisionCount()) + { + Line + line; + line = localOrigin.linearPosition; + Vector3D + step; + step.Subtract(localOrigin.linearPosition, old_position); + line = step; + Scalar + diameter = collisionTemplate->maxX - collisionTemplate->minX; + if (diameter < line.length) + { + CollideCenterOfMotion(&line, collision_list); + } + } + + // + //------------------------------- + // Process each of the collisions + //------------------------------- + // + Damage collision_damage; + ProcessCollisionList( + collision_list, + time_slice, + old_position, + &collision_damage + ); + + (this->*deadReckoner)(); + Vector3D + error; + error.Subtract( + projectedOrigin.linearPosition, + localOrigin.linearPosition + ); + if (error.LengthSquared() > 0.5f) + { + ForceUpdate(); + } + + // + //---------------------- + // Hunt for VTVs to kill + //---------------------- + // + Check_Fpu(); + Hunt(time_slice); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DemolitionPack::Hunt(Scalar) +{ + if ((lastPerformance - creationTime) >= fuseTime) + { + // + //--------------------------------- + // Test against the tangible movers + //--------------------------------- + // + Check(collisionAssistant); + CollisionAssistant::MovingEntityIterator + iterator(collisionAssistant); + Entity + *entity; + Check(collisionVolume); + while ((entity = iterator.ReadAndNext()) != NULL) + { + // + //------------------------------------------ + // If the mover is not within range, no boom + //------------------------------------------ + // + Vector3D + range; + range.Subtract( + entity->localOrigin.linearPosition, + localOrigin.linearPosition + ); + if ((range.LengthSquared() >= detectionRadiusSquared) && ((lastPerformance - creationTime) <= (fuseTime + 60.0f))) + { + continue; + } + + // + //---------------------------------- + // We got a boom! Make an explosion + //---------------------------------- + // + CondemnToDeathRow(); + Check(application); + ResourceFile *resource_file = application->GetResourceFile(); + Check(resource_file); + ResourceDescription + *explosion_res = resource_file-> + FindResourceDescription(explosionResourceID); + Check(explosion_res); + explosion_res->Lock(); + + Explosion::MakeMessage exp_message( + Explosion::MakeMessageID, + sizeof(Explosion::MakeMessage), + ExplosionClassID, + EntityID::Null, + explosion_res->resourceID, + Explosion::DefaultFlags, + localOrigin, + entity->GetEntityID(), + shootingEntity->GetEntityID() + ); + + explosion_res->Unlock(); + + #if DEBUG_LEVEL>0 + Explosion + *exp = + #endif + Explosion::Make(&exp_message); + Register_Object(exp); + + // + //---------------------------------------------- + // Send a damage message to whoever we hit + //---------------------------------------------- + // + if ((lastPerformance - creationTime) <= (fuseTime + 60.0f)) + { + iterator.First(); + while ((entity = iterator.ReadAndNext()) != NULL) + { + if (entity->GetClassID() == RegisteredClass::VTVClassID) + { + VTV *vtv = Cast_Object(VTV*, entity); + Damage damage_data; + damage_data.damageForce.Subtract( + vtv->localOrigin.linearPosition, + localOrigin.linearPosition + ); + if (damage_data.damageForce.LengthSquared() > blastRadiusSquared) + { + continue; + } + damage_data.damageForce.Normalize(damage_data.damageForce); + damage_data.damageForce *= concussiveForce; + damage_data.damageAmount = damageData.damageAmount; + damage_data.damageType = Damage::ExplosiveDamageType; + // + //------------------------------------------ + // Send a damage message to the thing we hit + //------------------------------------------ + // + Entity::TakeDamageMessage + take_damage( + Entity::TakeDamageMessageID, + sizeof(Entity::TakeDamageMessage), + shootingEntity->GetEntityID(), + 0, + damage_data + ); + entity->Dispatch(&take_damage); + } + } + break; + } + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DemolitionPack::ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ) +{ + Scalar penetration,r; + Scalar elasticity = elasticityCoefficient; + Scalar friction = frictionCoefficient; + + // + //------------------------------------------------------------------------- + // If we have hit a mover, adjust our velocity relative to it, unless we + // have collided with the VTV what dropped us, in which case we will ignore + // the hit + //------------------------------------------------------------------------- + // + BoxedSolid *box = collision.GetTreeVolume(); + Check(box); + Simulation *sim = box->GetOwningSimulation(); + Mover *mover = NULL; + if (sim && sim->IsDerivedFrom(*Mover::GetClassDerivations())) + { + mover = (Mover*)sim; + Check(mover); + if (mover == shootingEntity) + { + Check_Fpu(); + return; + } + worldLinearVelocity -= mover->worldLinearVelocity; + } + + // + //-------------------------------------------------------------------- + // If we really have a collision, do a static bounce off of the normal + // generated + //-------------------------------------------------------------------- + // + if ( + collisionVolume->ProcessCollision( + collision, + worldLinearVelocity, + lastCollisionList, + &damage->surfaceNormal, + &penetration + ) + ) + { + Max_Clamp(penetration, time_slice); + r = penetration / time_slice; + Check_Fpu(); + + StaticBounce( + old_position, + time_slice, + r, + damage->surfaceNormal, + &elasticity, + minimumBounceSpeed, + &friction + ); + + // + //-------------------------- + // Determine collision state + //-------------------------- + // + if (!elasticity && !friction && !mover) + { + SetPerformance(&DemolitionPack::Hunt); + worldLinearVelocity = Vector3D::Identity; + worldLinearAcceleration = Vector3D::Identity; + localVelocity = Motion::Identity; + localAcceleration = Motion::Identity; + ForceUpdate(); + mover = NULL; + } + } + if (mover) + { + worldLinearVelocity += mover->worldLinearVelocity; + } + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DemolitionPack::DemolitionPack( + DemolitionPack::MakeMessage *creation_message, + DemolitionPack::SharedData &virtual_data +): + Rivet(creation_message, virtual_data) +{ + Check_Pointer(this); + + // + //------------------------ + // Setup the initial state + //------------------------ + // + + SetValidFlag(); + InterestZone *interest_zone; + + Check(application); + Check(application->GetInterestManager()); + interest_zone = + application->GetInterestManager()->GetInterestZone(interestZoneID); + Check(interest_zone); + localEnvironment = interest_zone->GetEnvironment(); + Check(localEnvironment); + + // + // + SetDeadReckoner(&DemolitionPack::AcceleratedDeadReckoner); + if (GetInstance() == ReplicantInstance) + { + SetPerformance(&DemolitionPack::DeadReckon); + } + else + { + SetPerformance(&DemolitionPack::MoveAndHunt); + } + + // + // Initialize the Projectile variables + // + ResourceDescription *res = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + + ModelResource* model = (ModelResource*)res->resourceAddress; + Check_Pointer(model); + blastRadiusSquared = model->blastRadiusSquared; + detectionRadiusSquared = model->detectionRadiusSquared; + fuseTime = model->fuseTime; + concussiveForce = model->concussiveForce; + damageData = model->damageData; + explosionResourceID = model->explosionResourceID; + + res->Unlock(); + + HostManager *host_mgr = application->GetHostManager(); + Check(host_mgr); + shootingEntity = + host_mgr->GetEntityPointer(creation_message->shootingEntity); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DemolitionPack* + DemolitionPack::Make(DemolitionPack::MakeMessage *creation_message) +{ + return new DemolitionPack(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DemolitionPack::~DemolitionPack() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateModelResource +// +int + DemolitionPack::CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //----------------------------------------------------------------------- + // If we were not provided a buffer to write the model data into, we must + // create it ourselves. Then make sure that the mover stuff is read in + //----------------------------------------------------------------------- + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + if( + Rivet::CreateModelResource( + resource_file, + model_name, + model_file, + directories, + local_model + ) == -1 + ) + { +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + Check_Fpu(); + return -1; + } + + // + //--------------------------------------- + // Read in the damage amount for the ammo + //--------------------------------------- + // + if( + !model_file->GetEntry( + "gamedata", + "BlastRadius", + &local_model->blastRadiusSquared + ) + ) + { + std::cout << model_name << " missing BlastRadius!\n"; + goto Dump_And_Die; + } + { + local_model->blastRadiusSquared *= local_model->blastRadiusSquared; + } + if( + !model_file->GetEntry( + "gamedata", + "DetectionRadius", + &local_model->detectionRadiusSquared + ) + ) + { + std::cout << model_name << " missing DetectionRadius!\n"; + goto Dump_And_Die; + } + else + { + local_model->detectionRadiusSquared *= local_model->detectionRadiusSquared; + } + if( + !model_file->GetEntry( + "gamedata", + "ConcussiveForce", + &local_model->concussiveForce + ) + ) + { + std::cout << model_name << " missing ConcussiveForce!\n"; + goto Dump_And_Die; + } + if( + !model_file->GetEntry( + "gamedata", + "FuseTime", + &local_model->fuseTime + ) + ) + { + std::cout << model_name << " missing FuseTime!\n"; + goto Dump_And_Die; + } + + // + //------------------------------------------------------------------------- + // If we created the model buffer, then we have the responsibility to write + // it out to the resource file + //------------------------------------------------------------------------- + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DemolitionPack::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/DEMOPACK.h b/RP/DEMOPACK.h new file mode 100644 index 0000000..9ad4912 --- /dev/null +++ b/RP/DEMOPACK.h @@ -0,0 +1,121 @@ +#pragma once + +#include "rivet.h" + +struct DemolitionPack__ModelResource : + public Rivet::ModelResource +{ + Scalar + blastRadiusSquared; + Scalar + detectionRadiusSquared; + Scalar + fuseTime; + Scalar + concussiveForce; +}; + +//########################################################################## +//#################### DemolitionPack ############################# +//########################################################################## + +class DemolitionPack : + public Rivet +{ +public: +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +#if 0 +public: + enum { + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model support +// +public: + enum { + DefaultFlags = Mover::DefaultFlags|NoCollisionTestFlag + }; + + typedef void (DemolitionPack::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + MoveAndHunt(Scalar time_slice); + void + Hunt(Scalar time_slice); + void + ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef DemolitionPack__ModelResource ModelResource; + + static DemolitionPack* + Make(MakeMessage *creation_message); + + DemolitionPack( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~DemolitionPack(); + + Logical + TestInstance() const; + +static int + CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model = NULL + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local Data +// +public: + Scalar + blastRadiusSquared; + + Scalar + detectionRadiusSquared; + + Scalar + fuseTime; + + Scalar + concussiveForce; +}; diff --git a/RP/RIVET.cpp b/RP/RIVET.cpp new file mode 100644 index 0000000..be26953 --- /dev/null +++ b/RP/RIVET.cpp @@ -0,0 +1,503 @@ +#include "rp.h" +#pragma hdrstop + +#include "rivet.h" +#include "..\munga\line.h" +#include "..\munga\explode.h" +#include "..\munga\boxsolid.h" +#include "..\munga\subsystm.h" +#include "..\munga\app.h" +#include "..\munga\hostmgr.h" +#include "..\munga\interest.h" +#include "..\munga\notation.h" + +//############################################################################# +// Shared Data Support +// +Derivation* Rivet::GetClassDerivations() +{ static Derivation classDerivations(Mover::GetClassDerivations(), "Rivet"); + return &classDerivations; +} + + +Rivet::SharedData + Rivet::DefaultData( + Rivet::GetClassDerivations(), + Rivet::GetMessageHandlers(), + Rivet::GetAttributeIndex(), + Rivet::StateCount, + (Entity::MakeHandler)Rivet::Make + ); + +//############################################################################# +// Attribute Support +// +const Rivet::IndexEntry + Rivet::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Rivet, DamageData, damageData) +}; + +Rivet::AttributeIndexSet& Rivet::GetAttributeIndex() +{ + static Rivet::AttributeIndexSet attributeIndex(ELEMENTS(Rivet::AttributePointers), Rivet::AttributePointers, Mover::GetAttributeIndex()); + return attributeIndex; +} + +//############################################################################# +// Model support +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Rivet::MoveToTarget(Scalar time_slice) +{ + Line + distance_traveled; + distance_traveled = localOrigin.linearPosition; + + // + //----------------------------------------------------------------- + // Apply the standard air resistance and gravity, then project the + // Projectile motion through the time slice and look for collisions + //----------------------------------------------------------------- + // + ApplyAirResistanceAndGravity(); + ApplyWorldAccelerations(time_slice); + + Vector3D + motion_vector; + motion_vector.Subtract( + localOrigin.linearPosition, + distance_traveled.origin + ); + distance_traveled = motion_vector; + Check(&distance_traveled); + localToWorld = localOrigin; + + BoxedSolid + *target = FindBoxedSolidHitBy(&distance_traveled, shootingEntity); + // + //------------------------------------------------------- + // If the projectile hit something, sentence it to death! + //------------------------------------------------------- + // + if (target) + { + CondemnToDeathRow(); + Origin + explode_origin = localOrigin; + distance_traveled.FindEnd(&explode_origin.linearPosition); + + // + //----------------------- + // Find the entity we hit + //----------------------- + // + Simulation + *sim = target->GetOwningSimulation(); + Check(sim); + Entity + *entity; + if (sim->IsDerivedFrom(*Subsystem::GetClassDerivations())) + { + Check((Subsystem*)sim); + entity = ((Subsystem*)sim)->GetEntity(); + } + else if (sim->IsDerivedFrom(*Mover::GetClassDerivations())) + { + Mover + *mover = (Mover*)sim; + Check(mover); + + Vector3D + impact_speed; + + impact_speed.Subtract(worldLinearVelocity, mover->worldLinearVelocity); + Scalar + damage_scale = impact_speed.Length() / 350.0f; // HACK + damageData.damageAmount *= damage_scale*damage_scale; + entity = mover; + } + else + { + entity = (Entity*)sim; + } + Check(entity); + + // + //------------------ + // Make an Explosion + //------------------ + // + Check(application); + ResourceFile + *resource_file = application->GetResourceFile(); + Check(resource_file); + ResourceDescription *explosion_res = + resource_file->FindResourceDescription(explosionResourceID); + Check(explosion_res); + explosion_res->Lock(); + + Explosion::MakeMessage exp_message( + Explosion::MakeMessageID, + sizeof(Explosion::MakeMessage), + ExplosionClassID, + EntityID::Null, + explosion_res->resourceID, + Explosion::DefaultFlags, + explode_origin, + entity->GetEntityID(), + shootingEntity->GetEntityID() + ); + + explosion_res->Unlock(); + + #if DEBUG_LEVEL > 0 + Explosion + *exp = + #endif + Explosion::Make(&exp_message); + Register_Object(exp); + // + //------------------------------------------ + // Send a damage message to the thing we hit + //------------------------------------------ + // + Entity::TakeDamageMessage + take_damage( + Entity::TakeDamageMessageID, + sizeof(Entity::TakeDamageMessage), + shootingEntity->GetEntityID(), + 0, + damageData + ); + entity->Dispatch(&take_damage); + } + + // + //--------------------------------------------- + // Otherwise, see if we have to update anything + //--------------------------------------------- + // + else + { + UpdateLocalMotion(); + + // + //------------------------------------------------------------------------ + // Run the dead reckoner, and then see how far apart the two positions are + //------------------------------------------------------------------------ + // + (this->*deadReckoner)(); + Vector3D + error; + error.Subtract( + projectedOrigin.linearPosition, + localOrigin.linearPosition + ); + if (error.LengthSquared() > 0.1f) + { + ForceUpdate(); + } + } + + // + //--------------------------------------------------- + // If the bullet has outlived its lifetime, delete it + //--------------------------------------------------- + // + if ((Now() - creationTime) > RIVET_MAXIMUM_LIFETIME) + { + CondemnToDeathRow(); + } + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Rivet::Rivet( + Rivet::MakeMessage *creation_message, + Rivet::SharedData &virtual_data +): + Mover(creation_message, virtual_data) +{ + Check_Pointer(this); + + // + //------------------------ + // Setup the initial state + //------------------------ + // + + SetValidFlag(); + + Check(application); + Check(application->GetInterestManager()); + InterestZone + *interest_zone = application->GetInterestManager()-> + GetInterestZone(interestZoneID); + Check(interest_zone); + + localEnvironment = interest_zone->GetEnvironment(); + Check(localEnvironment); + + // + // + SetDeadReckoner(&Rivet::AcceleratedDeadReckoner); + if (GetInstance() == ReplicantInstance) + { + SetPerformance(&Rivet::DeadReckon); + } + else + { + SetPerformance(&Rivet::MoveToTarget); + StartCollisionAssistant(); + } + + // + // Initialize the Projectile variables + // + ResourceDescription *res = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + + ModelResource + *model = (ModelResource*)res->resourceAddress; + Check_Pointer(model); + + damageData.damageType = model->damageData.damageType; + damageData.damageAmount = model->damageData.damageAmount; + damageData.damageForce = Vector3D::Identity; + damageData.surfaceNormal.x = 1.0f; + damageData.surfaceNormal.y = 0.0f; + damageData.surfaceNormal.z = 0.0f; + damageData.impactPoint = Point3D::Identity; + explosionResourceID = model->explosionResourceID; + + res->Unlock(); + + HostManager + *host_mgr = application->GetHostManager(); + Check(host_mgr); + + shootingEntity = + host_mgr->GetEntityPointer(creation_message->shootingEntity); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Rivet* + Rivet::Make(Rivet::MakeMessage *creation_message) +{ + return new Rivet(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Rivet::~Rivet() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateModelResource +// +int + Rivet::CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //----------------------------------------------------------------------- + // If we were not provided a buffer to write the model data into, we must + // create it ourselves. Then make sure that the mover stuff is read in + //----------------------------------------------------------------------- + // + ModelResource + *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + if( + Mover::CreateModelResource( + resource_file, + model_name, + model_file, + directories, + local_model + ) == -1 + ) + { +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + Check_Fpu(); + return -1; + } + + // + //--------------------------------------- + // Read in the damage amount for the ammo + //--------------------------------------- + // + if( + !model_file->GetEntry( + "gamedata", + "DamageAmount", + &local_model->damageData.damageAmount + ) + ) + { + std::cout << model_name << " missing DamageAmount!\n"; + goto Dump_And_Die; + } + + // + //---------------------------------------------------------------------- + // Read in the Model Filename of the Explosion renderable, then find its + // resource ID in the resource file + //---------------------------------------------------------------------- + // + const char + *damage_type; + if( + !model_file->GetEntry( + "gamedata", + "DamageType", + &damage_type + ) + ) + { + std::cout << model_name << " missing DamageType!\n"; + goto Dump_And_Die; + } + if (!stricmp(damage_type, "CollisionDamage")) + { + local_model->damageData.damageType = Damage::CollisionDamageType; + } + else if (!stricmp(damage_type, "BallisticDamage")) + { + local_model->damageData.damageType = Damage::BallisticDamageType; + } + else if (!stricmp(damage_type, "ExplosiveDamage")) + { + local_model->damageData.damageType = Damage::ExplosiveDamageType; + } + else if (!stricmp(damage_type, "LaserDamage")) + { + local_model->damageData.damageType = Damage::LaserDamageType; + } + else if (!stricmp(damage_type, "EnergyDamage")) + { + local_model->damageData.damageType = Damage::EnergyDamageType; + } + else + { + std::cout << model_name << " has an unknown DamageType of " << damage_type + << std::endl; + goto Dump_And_Die; + } + // + //---------------------------- + // Init damage fields + //---------------------------- + // + local_model->damageData.damageForce = Vector3D::Identity; + local_model->damageData.surfaceNormal.x = 0.0f; + local_model->damageData.surfaceNormal.y = 1.0f; + local_model->damageData.surfaceNormal.z = 0.0f; + local_model->damageData.impactPoint = Vector3D::Identity; + + // + //---------------------------------------------------------------------- + // Read in the Model Filename of the Explosion renderable, then find its + // resource ID in the resource file + //---------------------------------------------------------------------- + // + const char + *explosion; + if( + !model_file->GetEntry( + "gamedata", + "ExplosionModelFile", + &explosion + ) + ) + { + std::cout << model_name << " missing ExplosionModelFile!\n"; + goto Dump_And_Die; + } + ResourceDescription + *res = resource_file->FindResourceDescription( + explosion, + ResourceDescription::ModelListResourceType + ); + if (!res) + { + std::cout << model_name << " cannot find " << explosion + << " in resource file!\n"; + goto Dump_And_Die; + } + local_model->explosionResourceID = res->resourceID; + + // + //------------------------------------------------------------------------- + // If we created the model buffer, then we have the responsibility to write + // it out to the resource file + //------------------------------------------------------------------------- + // + if (!model) + { + ResourceDescription + *new_res = resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} + +Logical + Rivet::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/RIVET.h b/RP/RIVET.h new file mode 100644 index 0000000..a7207f3 --- /dev/null +++ b/RP/RIVET.h @@ -0,0 +1,178 @@ +#pragma once + +#include "..\munga\mover.h" + +#define RIVET_MAXIMUM_LIFETIME 5.0f + +//###################### Rivet ModelResource #################### + +struct Rivet__ModelResource : + public Mover::ModelResource +{ + Damage + damageData; + ResourceDescription::ResourceID + explosionResourceID; +}; + +//########################################################################## +//##################### Mover::MakeMessage ########################## +//########################################################################## + +class Rivet__MakeMessage: + public Mover::MakeMessage +{ +public: + EntityID + shootingEntity; + + Rivet__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration, + const EntityID &shooter + ): + Mover::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin, + velocity, + acceleration + ), + shootingEntity(shooter) + {} + Rivet__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration, + const EntityID &shooter + ): + Mover::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin, + velocity, + acceleration + ), + shootingEntity(shooter) + {} +}; + +//########################################################################## +//############################# Rivet ################################ +//########################################################################## + +class Rivet : + public Mover +{ +public: +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + DamageDataAttributeID = Mover::NextAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + Damage + damageData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model support +// +public: + enum { + DefaultFlags = + Mover::DefaultFlags|NoCollisionVolumeFlag|NoCollisionTestFlag + }; + + typedef void (Rivet::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + MoveToTarget(Scalar time_slice); + +public: + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef Rivet__ModelResource ModelResource; + typedef Rivet__MakeMessage MakeMessage; + + static Rivet* + Make(MakeMessage *creation_message); + + Rivet( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~Rivet(); + + Logical + TestInstance() const; + + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *notation_file, + const ResourceDirectories *directories, + ModelResource *model = NULL + ); + +protected: + ResourceDescription::ResourceID + explosionResourceID; + Entity + *shootingEntity; +}; + diff --git a/RP/RP.h b/RP/RP.h new file mode 100644 index 0000000..efa8bdc --- /dev/null +++ b/RP/RP.h @@ -0,0 +1,9 @@ +#pragma once + +#include "..\munga\munga.h" + +#if !defined(NO_PRECOMPILED_HEADERS) + #include "vtvsub.h" + #include "vtv.h" + #include "vtvmppr.h" +#endif \ No newline at end of file diff --git a/RP/RPCNSL.cpp b/RP/RPCNSL.cpp new file mode 100644 index 0000000..fadd387 --- /dev/null +++ b/RP/RPCNSL.cpp @@ -0,0 +1,81 @@ +#include "rp.h" +#pragma hdrstop + +#include "rpcnsl.h" + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoredMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVScoredMessage:: + ConsolePlayerVTVScoredMessage(HostID player_host_ID): + NetworkClient::Message( + ConsolePlayerVTVScoredMessageID, + sizeof(ConsolePlayerVTVScoredMessage) + ) +{ + playerHostID = player_host_ID; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVKilledMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVKilledMessage:: + ConsolePlayerVTVKilledMessage( + HostID player_host_ID, + HostID killer_host_ID + ): + NetworkClient::Message( + ConsolePlayerVTVKilledMessageID, + sizeof(ConsolePlayerVTVKilledMessage) + ) +{ + playerHostID = player_host_ID; + killerHostID = killer_host_ID; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVBoosterMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVBoosterMessage:: + ConsolePlayerVTVBoosterMessage( + HostID player_host_ID, + int booster_on + ): + NetworkClient::Message( + ConsolePlayerVTVBoosterMessageID, + sizeof(ConsolePlayerVTVBoosterMessage) + ) +{ + playerHostID = player_host_ID; + boosterOn = booster_on; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoreUpdateMessage ~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVScoreUpdateMessage:: + ConsolePlayerVTVScoreUpdateMessage( + HostID player_host_ID, + int score + ): + NetworkClient::Message( + ConsolePlayerVTVScoreUpdateMessageID, + sizeof(ConsolePlayerVTVScoreUpdateMessage) + ) +{ + playerHostID = player_host_ID; + playerScore = score; +} + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVDamagedMessage ~~~~~~~~~~~~~~~~~~~~~~ +ConsolePlayerVTVDamagedMessage:: + ConsolePlayerVTVDamagedMessage( + HostID player_host_ID, + HostID damager_host_ID, + int loss, + int points_transfered + ): + NetworkClient::Message( + ConsolePlayerVTVDamagedMessageID, + sizeof(ConsolePlayerVTVDamagedMessage) + ) +{ + playerHostID = player_host_ID; + damagerHostID = damager_host_ID; + damageLoss = loss; + pointsTransfered = points_transfered; +} + +//============================================================================== diff --git a/RP/RPCNSL.h b/RP/RPCNSL.h new file mode 100644 index 0000000..1680932 --- /dev/null +++ b/RP/RPCNSL.h @@ -0,0 +1,280 @@ +#pragma once + +#if defined(MAC) + #include "NetworkEndpoint.h" + #include "Participant.h" +#else + #include "..\munga\console.h" +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~ Console Message IDs ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +enum +{ + ConsolePlayerVTVScoredMessageID = 2, + ConsolePlayerVTVKilledMessageID = 3, + ConsolePlayerVTVBoosterMessageID = 4, + ConsolePlayerVTVScoreUpdateMessageID = 5, + ConsolePlayerVTVDamagedMessageID = 6 +}; + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoredMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte +class ConsolePlayerVTVScoredMessage: + public NetworkEndpoint::Message +{ +public: + ConsolePlayerVTVScoredMessage(HostID player_host_ID); + + long + GetPlayerHostID() + {return playerHostID.value();} + +private: + HostID + playerHostID; +}; +#pragma options align=reset +#else +class ConsolePlayerVTVScoredMessage: + public NetworkClient::Message +{ +public: + ConsolePlayerVTVScoredMessage(HostID player_host_ID); + + HostID + GetPlayerHostID() + {return playerHostID;} + +private: + HostID + playerHostID; +}; +#endif + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVKilledMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte +class ConsolePlayerVTVKilledMessage: + public NetworkEndpoint::Message +{ +public: + ConsolePlayerVTVKilledMessage( + HostID player_host_ID, + HostID killer_host_ID + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetKillerHostID() + {return killerHostID.value();} + +private: + HostID + playerHostID; + HostID + killerHostID; +}; +#pragma options align=reset +#else +class ConsolePlayerVTVKilledMessage: + public NetworkClient::Message +{ +public: + ConsolePlayerVTVKilledMessage( + HostID player_host_ID, + HostID killer_host_ID + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + HostID + GetKillerHostID() + {return killerHostID;} + +private: + HostID + playerHostID, + killerHostID; +}; +#endif + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVBoosterMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte +class ConsolePlayerVTVBoosterMessage: + public NetworkEndpoint::Message +{ +public: + ConsolePlayerVTVBoosterMessage( + HostID player_host_ID, + LEDWORD booster_on + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetBoosterOn() + {return boosterOn.value();} + +private: + HostID + playerHostID; + LEDWORD + boosterOn; +}; +#pragma options align=reset +#else +class ConsolePlayerVTVBoosterMessage: + public NetworkClient::Message +{ +public: + ConsolePlayerVTVBoosterMessage( + HostID player_host_ID, + int booster_on + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + int + GetBoosterOn() + {return boosterOn;} + +private: + HostID + playerHostID; + int + boosterOn; +}; +#endif + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVScoreUpdateMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte +class ConsolePlayerVTVScoreUpdateMessage: + public NetworkEndpoint::Message +{ +public: + ConsolePlayerVTVScoreUpdateMessage( + HostID player_host_ID, + LEDWORD score + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetPlayerScore() + {return playerScore.value();} + +private: + HostID + playerHostID; + LEDWORD + playerScore; +}; +#pragma options align=reset +#else +class ConsolePlayerVTVScoreUpdateMessage: + public NetworkClient::Message +{ +public: + ConsolePlayerVTVScoreUpdateMessage( + HostID player_host_ID, + int score + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + int + GetPlayerScore() + {return playerScore;} + +private: + HostID + playerHostID; + int + playerScore; +}; +#endif + +//~~~~~~~~~~~~~~~~~~ ConsolePlayerVTVDamagedMessage ~~~~~~~~~~~~~~~~~~~ +#ifdef MAC +#pragma options align=mac68k4byte +class ConsolePlayerVTVDamagedMessage: + public NetworkEndpoint::Message +{ +public: + ConsolePlayerVTVDamagedMessage( + HostID player_host_ID, + HostID damager_host_ID, + LEDWORD loss, + LEDWORD points_transfered + ); + + long + GetPlayerHostID() + {return playerHostID.value();} + long + GetDamagerHostID() + {return damagerHostID.value();} + long + GetDamageLoss() + {return damageLoss.value();} + long + GetPointsTransfered() + {return pointsTransfered.value();} + +private: + HostID + playerHostID; + HostID + damagerHostID; + LEDWORD + damageLoss; + LEDWORD + pointsTransfered; +}; +#pragma options align=reset +#else +class ConsolePlayerVTVDamagedMessage: + public NetworkClient::Message +{ +public: + ConsolePlayerVTVDamagedMessage( + HostID player_host_ID, + HostID damager_host_ID, + int loss, + int points_transfered + ); + + HostID + GetPlayerHostID() + {return playerHostID;} + HostID + GetDamagerHostID() + {return damagerHostID;} + int + GetDamageLoss() + {return damageLoss;} + int + GetPointsTransfered() + {return pointsTransfered;} + +private: + HostID + playerHostID; + HostID + damagerHostID; + int + damageLoss; + int + pointsTransfered; +}; +#endif diff --git a/RP/RPDIRECT.cpp b/RP/RPDIRECT.cpp new file mode 100644 index 0000000..1dab1ea --- /dev/null +++ b/RP/RPDIRECT.cpp @@ -0,0 +1,197 @@ +#include "rp.h" +#pragma hdrstop + +#include "rpdirect.h" +#include "..\munga\mission.h" +#include "..\munga\app.h" +#include "..\munga\nttmgr.h" +#include "rpplayer.h" + +//############################################################################# +// Shared Data support +// +Derivation* RPCameraDirector::GetClassDerivations() +{ static Derivation classDerivations(CameraDirector::GetClassDerivations(), "RPCameraDirector"); + return &classDerivations; +} + + +RPCameraDirector::SharedData + RPCameraDirector::DefaultData( + RPCameraDirector::GetClassDerivations(), + RPCameraDirector::MessageHandlers, + RPCameraDirector::GetAttributeIndex(), + RPCameraDirector::StateCount, + (CameraDirector::MakeHandler) RPCameraDirector::Make + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPCameraDirector::BeARPDirector(Scalar time_slice) +{ + Check(this); + + Player::PlayerSimulation(time_slice); + UpdateHUD(time_slice); + Logical force_target = False; + + // + //-------------------------------------------------------------- + // Time To Cut To a new Player? (Don't stay on a burning mech!) + //-------------------------------------------------------------- + // + if (timeLeftOnPlayer > 0.0f && application->GetApplicationState() == Application::RunningMission) + { + timeLeftOnPlayer -= time_slice; + return; + } + else if (application->GetApplicationState() == Application::EndingMission) + { + force_target = True; + } + + // + //-------------------------------------------------------------------- + // Look for out target. If we are not in football, follow the leader. + // If we are in martian football, follow the losing runner + //-------------------------------------------------------------------- + // + Player *top_dog; + Scalar new_time; + if (!martianFootball || application->GetSecondsRemainingInGame() < 30.0f) + { + top_dog = FindPlayerByRank(0); + new_time = 0.0f; + } + else + { + Check(application); + EntityManager *entity_mgr = application->GetEntityManager(); + EntityGroup *player_group = entity_mgr->FindGroup("Players"); + top_dog = NULL; + new_time = 20.0f; + if (player_group) + { + RPPlayer + *player, + *first_player=NULL; + ChainIteratorOf iterator(player_group->groupMembers); + while ((player = (RPPlayer*)iterator.ReadAndNext()) != NULL) + { + Check(player); + if (player->playerType == RPPlayer::RunnerPlayerType) + { + if (!first_player) + { + first_player = player; + } + if (player->GetPlayerVehicle() == GetGoalEntity()) + { + while ((player = (RPPlayer*)iterator.ReadAndNext()) != NULL) + { + Check(player); + if (player->playerType == RPPlayer::RunnerPlayerType) + { + top_dog = player; + break; + } + } + } + } + } + if (!top_dog && first_player) + { + top_dog = first_player; + } + } + } + + // + //------------------------------------------------------------------- + // If we have a goal, and it is different from the last one, tell the + // cameras + //------------------------------------------------------------------- + // + if (top_dog) + { + Check(top_dog); + Entity *vehicle = top_dog->GetPlayerVehicle(); + if (vehicle) + { + Check(vehicle); + Entity *goalEntity = GetGoalEntity(); + if (goalEntity != vehicle || force_target) + { + SetGoalEntity(vehicle); + timeLeftOnPlayer = new_time; + Check(cameraShip); + CameraShip::DirectionMessage direction_message( + CameraShip::DirectionMessageID, + sizeof(CameraShip::DirectionMessage), + GetGoalEntity()->GetEntityID(), + 0.0f, + Point3D::Identity + ); + Check(cameraShip); + cameraShip->Dispatch(&direction_message); + } + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPCameraDirector::CreateRPCameraShip(Scalar time_slice) +{ + Check(this); + + CameraDirector::CreateCameraShip(time_slice); + SetPerformance(&RPCameraDirector::BeARPDirector); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPCameraDirector::RPCameraDirector( + RPCameraDirector::MakeMessage *creation_message, + RPCameraDirector::SharedData &virtual_data +) : + CameraDirector(creation_message, virtual_data) +{ + Check_Pointer(creation_message); + currentWatchedPlayer = NULL; + Check(application); + CString scenarion_name = application->GetCurrentMission()->GetScenarioName(); + martianFootball = !scenarion_name.Compare("football"); + if (GetInstance() != ReplicantInstance) + { + SetPerformance(&RPCameraDirector::CreateRPCameraShip); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPCameraDirector* + RPCameraDirector::Make(MakeMessage *creation_message) +{ + return new RPCameraDirector(creation_message); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPCameraDirector::~RPCameraDirector() +{ + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RPCameraDirector::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/RPDIRECT.h b/RP/RPDIRECT.h new file mode 100644 index 0000000..0ceb5ad --- /dev/null +++ b/RP/RPDIRECT.h @@ -0,0 +1,60 @@ +#pragma once + +#include "..\munga\director.h" + +class RPPlayer; + +class RPCameraDirector : + public CameraDirector +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Simulation Support +// +public: + typedef void + (RPCameraDirector::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + CreateRPCameraShip(Scalar); + + void + BeARPDirector(Scalar); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// + RPCameraDirector( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + + static RPCameraDirector* + RPCameraDirector::Make(CameraDirector::MakeMessage *creation_message); + + ~RPCameraDirector(); + + Logical + TestInstance() const; + +protected: + RPPlayer + *currentWatchedPlayer; + + Logical + martianFootball; +}; diff --git a/RP/RPMSSN.cpp b/RP/RPMSSN.cpp new file mode 100644 index 0000000..8407fee --- /dev/null +++ b/RP/RPMSSN.cpp @@ -0,0 +1,28 @@ +#include "rp.h" +#pragma hdrstop + +#include "rpmssn.h" + +//########################################################################## +//########################### Mission ################################ +//########################################################################## + +RPMission::RPMission(NotationFile *notation_file, ResourceFile *resource_file) : Mission(notation_file, resource_file) +{ + Check(notation_file); + Check(resource_file); + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPMission::~RPMission() +{ + +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void RPMission::SetPlayerData(NotationFile*) +{ + Fail("RPMission::SetPlayerData shouldn't be reached\n"); +} diff --git a/RP/RPMSSN.h b/RP/RPMSSN.h new file mode 100644 index 0000000..8536a78 --- /dev/null +++ b/RP/RPMSSN.h @@ -0,0 +1,26 @@ +#pragma once + +#include "..\munga\mission.h" + +//########################################################################## +//########################### Mission ################################ +//########################################################################## + + +class RPMission : public Mission +{ +public: + RPMission(NotationFile *notation_file, ResourceFile *resources); + ~RPMission(); + + void SetPlayerData(NotationFile *notation_file); + + Logical ScoreCompressionOn() + { + Check(this); + return scoreCompression; + } + +protected: + Logical scoreCompression; +}; diff --git a/RP/RPPLAYER.cpp b/RP/RPPLAYER.cpp new file mode 100644 index 0000000..ae10ef0 --- /dev/null +++ b/RP/RPPLAYER.cpp @@ -0,0 +1,1381 @@ +#include "rp.h" +#pragma hdrstop + +#include "rpplayer.h" +#include "..\munga\dropzone.h" +#include "..\munga\mission.h" +#include "scorzone.h" +#include "rpcnsl.h" +#include "..\munga\app.h" +#include "vtv.h" +#include "..\munga\hostmgr.h" +#include "..\munga\nttmgr.h" + +//############################################################################# +//######################## RPPlayer__StatusMessage ###################### +//############################################################################# +MemoryBlock *RPPlayer__StatusMessage::GetAllocatedMemory() +{ + static MemoryBlock allocatedMemory(sizeof(RPPlayer__StatusMessage), RPPlayer__StatusMessage::numberOfAllocatedBlocks, RPPlayer__StatusMessage::numberOfAllocatedBlocks); + return &allocatedMemory; +} + +//############################################################################# +//############################### RPPlayer ############################## +//############################################################################# + +//############################################################################# +// Message Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// General PlayerType Message Handlers +// +const Receiver::HandlerEntry + RPPlayer::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(RPPlayer, TakeDamage), + MESSAGE_ENTRY(RPPlayer, VehicleDead), + MESSAGE_ENTRY(RPPlayer, Score), + MESSAGE_ENTRY(RPPlayer, DropZoneReply), + MESSAGE_ENTRY(RPPlayer, ScoreZoneReply), + MESSAGE_ENTRY(RPPlayer, MissionStarting), + MESSAGE_ENTRY(RPPlayer, MissionEnding) +}; + +Receiver::MessageHandlerSet& RPPlayer::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(RPPlayer::MessageHandlerEntries), RPPlayer::MessageHandlerEntries, Player::GetMessageHandlers()); + return messageHandlers; +} + +//############################################################################# +// Shared Data Support +// +Derivation* RPPlayer::GetClassDerivations() +{ static Derivation classDerivations(Player::GetClassDerivations(), "RPPlayer"); + return &classDerivations; +} + + +RPPlayer::SharedData + RPPlayer::DefaultData( + RPPlayer::GetClassDerivations(), + RPPlayer::GetMessageHandlers(), + RPPlayer::GetAttributeIndex(), + RPPlayer::StateCount, + (RPPlayer::MakeHandler)RPPlayer::Make + ); + + +//############################################################################# +// Attribute Support +// +const RPPlayer::IndexEntry + RPPlayer::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(RPPlayer, GoalEntity, goalEntity) +}; + +RPPlayer::AttributeIndexSet& RPPlayer::GetAttributeIndex() +{ + static RPPlayer::AttributeIndexSet attributeIndex(ELEMENTS(RPPlayer::AttributePointers), + RPPlayer::AttributePointers, + Player::GetAttributeIndex() + ); + return attributeIndex; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +static Origin first_drop; +Entity *first_goal; + +void + RPPlayer::MissionStartingMessageHandler(Message *message) +{ + Check(this); + Check(message); + + Player::MissionStartingMessageHandler(message); + Check(application); + if (application->GetApplicationState() == Application::ResumingMission) + { + Check(playerVehicle); + if (playerVehicle->IsDerivedFrom(*VTV::GetClassDerivations())) + { + currentScore = 1000.0f; + } + } + else + { + first_goal = goalEntity; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::MissionEndingMessageHandler(Message *message) +{ + Player::MissionEndingMessageHandler(message); + + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + if (application->GetApplicationState() == Application::EndingMission) + { + ConsoleApplicationEndMissionMessage + score_message(ownerID, (int)currentScore); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &score_message + ); + } + else + { + ConsoleApplicationAbortMissionMessage + score_message(ownerID); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &score_message + ); + } + } + + lastConsoleUpdate -= 15.0f; + Check(application); + if (application->GetApplicationState() == Application::SuspendingMission) + { + Check(playerVehicle); + if (playerVehicle->IsDerivedFrom(*VTV::GetClassDerivations())) + { + if (first_goal != goalEntity) + { + ScoreZone::ProcessScoreZoneRequestMessage + message( + ScoreZone::ProcessScoreZoneRequestMessageID, + sizeof(ScoreZone::ProcessScoreZoneRequestMessage), + GetEntityID(), + ScoreZoneReplyMessageID, + goalEntity->localOrigin.linearPosition + ); + goalEntity->Dispatch(&message); + } + + VTV *vtv = (VTV*) playerVehicle; + Check(vtv); + vtv->Reset(first_drop, True); + ForceUpdate(); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void RPPlayer::CreatePlayerVehicle(Origin vtv_location) +{ + Check(this); + Check(&vtv_location); + Check(application); + ResourceFile *resources = application->GetResourceFile(); + Check(resources); + Check_Pointer(playerMission->GetGameModel()); + + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + // + // Create MUNGA level vehicles + // + Player::CreatePlayerVehicle(vtv_location); + // + //----------------------------------------------------------------------- + // If the player has made no vehicle yet, make him a new one and link the + // player to it + //----------------------------------------------------------------------- + // + if (!playerVehicle) + { + ResourceDescription *vtv_res = + resources->FindResourceDescription( + playerMission->GetGameModel(), + ResourceDescription::ModelListResourceType + ); + Check(vtv_res); + vtv_res->Lock(); + + VTV::MakeMessage + create_player( + VTV::MakeMessageID, + sizeof(VTV::MakeMessage), + EntityID(host_manager->GetLocalHostID()), + VTV::VTVClassID, + EntityID::Null, + vtv_res->resourceID, + VTV::DefaultFlags|VTV::InitialStasisFlag, + vtv_location, + Motion::Identity, + Motion::Identity, + playerMission->GetBadgeName(), + playerMission->GetColorName() + ); + + vtv_res->Unlock(); + + playerVehicle = application->MakeAndLinkViewpointEntity(&create_player); + Register_Object(playerVehicle); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void RPPlayer::InitializePlayerLink() +{ + Check(this); + + PlayerLinkMessage player_link_message ( + PlayerLinkMessageID, + sizeof(PlayerLinkMessage), + this->GetEntityID() + ); + Check(playerVehicle); + playerVehicle->Dispatch(&player_link_message); + playerVehicle->DispatchToReplicants(&player_link_message); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void RPPlayer::SetGoalToFirstScoreZone() +{ + // + //---------------------------------------------------------- + // Change the goalEntity to the first sequential scorezone + //---------------------------------------------------------- + // + EntityGroup *score_zone_group = + application->GetEntityManager()->FindGroup("ActiveScoreZones"); + if(score_zone_group) + { + ChainIteratorOf iterator(score_zone_group->groupMembers); + ScoreZone *score_zone; + while ((score_zone = (ScoreZone*)iterator.ReadAndNext()) != NULL) + { + if ( + ( + (score_zone->scoreZoneType == LocalSequential) || + (score_zone->scoreZoneType == GlobalSequential) + ) && + score_zone->sequenceNumber == 1 + ) + { + goalEntity = score_zone; + break; + } + } + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void RPPlayer::PointVTVTowardGoal() +{ + Check(this); + + if (!goalEntity) + { + return; + } + Vector3D to_goal; + + to_goal.Subtract( + goalEntity->localOrigin.linearPosition, + playerVehicle->localOrigin.linearPosition + ); + + UnitVector current_heading; + playerVehicle->localToWorld.GetFromAxis(Z_Axis, ¤t_heading); + + Scalar length_to_goal; + + length_to_goal = to_goal.LengthSquared(); + if (length_to_goal > SMALL) + { + Scalar dot_prod; + + dot_prod = (to_goal * current_heading) / Sqrt(length_to_goal); + + if (dot_prod >= 0.0f) + { + Quaternion turn_around; + Quaternion y_roll(0.0f,1.0f,0.0f,0.0); + + Check(playerVehicle); + turn_around.Multiply( + playerVehicle->localOrigin.angularPosition, + y_roll + ); + playerVehicle->localOrigin.angularPosition = turn_around; + playerVehicle->localToWorld = playerVehicle->localOrigin; + playerVehicle->ForceUpdate(); + } + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void RPPlayer::ResetAfterDeath(DropZone::ReplyMessage *message) +{ + Check(this); + Check(message); + + Check(application); + message->deathCount = ++deathCount; + ForceUpdate(); + SetSimulationState(DropZoneAcquiredState); + dropZoneLocation = message->dropZoneLocation; + Time when = Now(); + when += 1.0f; + application->Post(HighEventPriority, this, message, when); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::DropZoneReplyMessageHandler( + DropZone::ReplyMessage *message + ) +{ + Check(this); + Check(message); + + + // + //----------------------------------------------------------------------- + // If the player has made no vehicle yet, make him a new one and link the + // player to it + //----------------------------------------------------------------------- + // + if (!playerVehicle) + { + first_drop = message->dropZoneLocation; + CreatePlayerVehicle(message->dropZoneLocation); + InitializePlayerLink(); + SetGoalToFirstScoreZone(); + switch(playerVehicle->GetClassID()) + { + case VTVClassID: + SetPerformance(&RPPlayer::PlayerSimulation); + break; + case CameraShipClassID: + SetPerformance(&RPPlayer::CameraShipSimulation); + playerRanking = -1; + break; + } + AlwaysExecute(); + deathCount = 0; + } + + // + //------------------------------------------------------------------------- + // Otherwise, just set the new position of the VTV and turn off the burning + // stuff. + //------------------------------------------------------------------------- + // + else if (deathCount == message->deathCount) + { + if (GetSimulationState() == MissionEndingState) + { + Check_Fpu(); + return; + } + if (GetSimulationState() != DropZoneAcquiredState) + { + ResetAfterDeath(message); + return; + } + } + + // + //--------------------------------- + // Make sure we ignore old messages + //--------------------------------- + // + else + { + Check_Fpu(); + return; + } + + // + //----------------------------------- + // Delete All offensivePlayers + //----------------------------------- + // + DeleteAllOffensivePlayers(); + ForceUpdate(); + SetSimulationState(VehicleTranslocatedState); + if (playerVehicle->GetClassID() == VTVClassID) + { + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + vtv->Reset(message->dropZoneLocation, VTV::RegularReset); + } + + // + //--------------------------------------------------- + // Always Point vtv in the direction of the scorezone + //--------------------------------------------------- + // + PointVTVTowardGoal(); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// GetPlayer +// +RPPlayer* + RPPlayer::GetPlayer(EntityID playerID) +{ + Check(this); + Check(&playerID); + + // + //--------------------------------------------------- + // Get the pointer to the RPPlayer from the playerID + //--------------------------------------------------- + // + Check(application); + HostManager *host = application->GetHostManager(); + Check(host); + RPPlayer *rp_player = Cast_Object( + RPPlayer*, + host->GetEntityPointer(playerID) + ); + Check(rp_player); + Check_Fpu(); + return rp_player; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::DeleteAllOffensivePlayers() +{ + VChainIteratorOf + iterator(offensivePlayerList); + OffensivePlayer + *current_player; + + while ((current_player = iterator.GetCurrent()) != NULL) + { + Unregister_Object(current_player); + delete current_player; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::CleanUpOffensivePlayers() +{ + VChainIteratorOf + iterator(offensivePlayerList); + OffensivePlayer + *current_player; + + while ((current_player = iterator.GetCurrent()) != NULL) + { + Check(current_player); + if(Now() - current_player->timeStamp >= 2.0f) + { + OffensivePlayer *stale_player = iterator.GetCurrent(); + Unregister_Object(stale_player); + delete stale_player; + } + else + { + iterator.Next(); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::TakeDamageMessageHandler (TakeDamageMessage *message) +{ + Check(this); + Check(message); + + // + //------------------------------------------------------- + // Scale the damage amount to point loss on this vehicle + //------------------------------------------------------- + // + VTV* + our_vtv = (VTV*)playerVehicle; + Check(our_vtv); + + if (GetSimulationState() != MissionEndingState) + { + Scalar score_loss = message->damageData.damageAmount; + if (message->damageData.damageType == Damage::CollisionDamageType) + { + score_loss *= our_vtv->deathConstant; + } + + ScoreMessage score_message( + RPPlayer::ScoreMessageID, + sizeof(RPPlayer::ScoreMessageID), + DamageScoreLossPointType, + -score_loss, + GetEntityID() + ); + Dispatch(&score_message); + + // + //----------------------------------------------------------- + // Clean up the list, and look for a player to give points to + //----------------------------------------------------------- + // + CleanUpOffensivePlayers(); + + VChainIteratorOf + iterator(offensivePlayerList); + if(iterator.GetCurrent()) + { + // + //-------------------------------------------------------- + // Send a score message to the player at the top + // of the offensivePlayer list the points for this damage + //-------------------------------------------------------- + // + OffensivePlayer *top_player = iterator.GetCurrent(); + RPPlayer *player_points = top_player->offensivePlayer; + if ( + top_player->deathBonus + && top_player->timeStamp < ((RPPlayer*)our_vtv)->lastPerformance + && top_player->offensivePlayer != this + ) + { + if (top_player->deathBonus < 0.0f) + { + score_loss = -score_loss; + } + + ScoreMessage score_message( + RPPlayer::ScoreMessageID, + sizeof(RPPlayer::ScoreMessage), + DamageBonusPointType, + score_loss, + GetEntityID() + ); + if (score_loss < 0.0f) + { + score_message.scoreType = DropZoneHitType; + } + player_points->Dispatch(&score_message); + + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVDamagedMessage + scored_message( + ownerID, + player_points->ownerID, + score_loss, + score_loss + ); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &scored_message + ); + } + } + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::AddOffensivePlayer(OffensivePlayer &offensive_player) +{ + Check(this); + Check(&offensive_player); + + // + //---------------------------------------------------------------- + // Calculate the deathBonus based on playerType and damageType + //---------------------------------------------------------------- + // + if(offensive_player.damageType == Damage::CollisionDamageType) + { + offensive_player.deathBonus = 500.0f; + } + else + { + offensive_player.deathBonus = 0.0f; + } + + offensivePlayerList.AddValue( + &offensive_player, + offensive_player.damageType + ); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::ScoreMessageHandler(ScoreMessage *message) +{ + Check(this); + Check(message); + Check(playerVehicle); + + if (GetSimulationState() == MissionEndingState) + { + return; + } + + // + //------------------------------------------------------------------------- + // If this is a score zone message, tell the console (if there is one) that + // we scored + //------------------------------------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + + switch (message->scoreType) + { + case ScoreZonePointType: + { + Host + *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVScoredMessage + scored_message(ownerID); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &scored_message + ); + } + //------------------------------------- + // Inform pilot of score zone entry + //------------------------------------- + RPPlayer + *player = + (RPPlayer*)host_manager->GetEntityPointer(message->pointSender); + Check(player); + + if (player->playerType != RunnerPlayerType) + { + RPStatusMessage *message = new RPStatusMessage(NULL, RPStatusMessage::ScoreZoneMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *) message); + } + } + break; + + case DeathBonusPointType: + case DropZoneKillType: + { + //------------------------------------- + // Inform pilot of killer's identity + //------------------------------------- + RPPlayer + *killer = + (RPPlayer*)host_manager->GetEntityPointer(message->pointSender); + Check(killer); + + RPStatusMessage *message = new RPStatusMessage(killer, RPStatusMessage::DestroyedMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *) message); + + } + break; + } + + Player::ScoreMessageHandler(message); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::VehicleDeadMessageHandler(VehicleDeadMessage *message) +{ + Check(this); + Check(message); + + if (GetSimulationState() == MissionEndingState) + { + Check_Fpu(); + return; + } + + // + //------------------------------------------------------------------------- + // If this is not the initial death notice, or we are still looking for our + // initial dropzone, let the player handler do its thing + //------------------------------------------------------------------------- + // + if (message->deathCount != -1) + { + Player::VehicleDeadMessageHandler(message); + Check_Fpu(); + return; + } + + // + //------------------------- + // Reset the VTV subsystems + //------------------------- + // + Check(playerVehicle); + VTV + *vtv = (VTV*) playerVehicle; + Check(vtv); + if ((playerType == CrusherPlayerType) || + (playerType == BlockerPlayerType) + ) + { + vtv->DeathShutdown(VTV::FootballReset); + } + else + { + vtv->DeathShutdown(VTV::RegularReset); + } + + // + //---------------------------------------------------- + // See if any other players get points for this death + //---------------------------------------------------- + // + CleanUpOffensivePlayers(); + + HostID + killer_id = ownerID; + VChainIteratorOf + iterator(offensivePlayerList); + if (iterator.GetCurrent()) + { + // + //---------------------------------------------------- + // Yes, send score messages... + //---------------------------------------------------- + // + OffensivePlayer + *offensive_player = iterator.GetCurrent(); + Check(offensive_player); + + ScoreMessage + score_message( + RPPlayer::ScoreMessageID, + sizeof(RPPlayer::ScoreMessage), + DeathBonusPointType, + offensive_player->deathBonus, + GetEntityID() + ); + if (offensive_player->deathBonus < 0.0f) + { + score_message.scoreType = DropZoneKillType; + } + + RPPlayer + *other_player = offensive_player->offensivePlayer; + Check(other_player); + other_player->Dispatch(&score_message); + + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVDamagedMessage + scored_message( + ownerID, + other_player->ownerID, + offensive_player->deathBonus, + offensive_player->deathBonus + ); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &scored_message + ); + } + + // + //---------------------------------------------------- + // ...keep track of the killer... + //---------------------------------------------------- + // + killer_id = other_player->ownerID; + // + //---------------------------------------------------- + // ...and send a notice to the pilot. + //---------------------------------------------------- + // + RPStatusMessage *message = new RPStatusMessage(other_player, RPStatusMessage::DestroyedByMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *)message); + } + else + { + // + //---------------------------------------------------- + // No, tell the pilot that it was self-induced. + //---------------------------------------------------- + // + RPStatusMessage *message = new RPStatusMessage(NULL, RPStatusMessage::PilotErrorMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *) message); + } + + // + //------------------------------------------------ + // Tell the console (if there is one) that we died + //------------------------------------------------ + // + Check(application); + HostManager + *host_manager = application->GetHostManager(); + Check(host_manager); + + Host + *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVKilledMessage killed_message(ownerID, killer_id); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &killed_message + ); + } + + // + //------------------------------------------------------------------------ + // Send a score message of deathpointloss, and notify ourselves again in 5 + // seconds so we can begin looking for the drop zone + //------------------------------------------------------------------------ + // + ScoreMessage + score_message( + RPPlayer::ScoreMessageID, + sizeof(RPPlayer::ScoreMessage), + DeathScoreLossPointType, + -vtv->deathScoreLoss, + GetEntityID() + ); + Dispatch(&score_message); + + Time when = Now(); + when += 5.0f; + message->deathCount = deathCount; + application->Post(HighEventPriority, this, message, when); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::ScoreZoneReplyMessageHandler( + ScoreZone::ReplyMessage *message + ) +{ + Check(this); + Check(message); + if (GetSimulationState() == MissionEndingState) + { + Check_Fpu(); + return; + } + + // + //------------------------------------------------- + // Send Score message if score zone was covered + //------------------------------------------------- + // + ScoreMessage + score_message( + RPPlayer::ScoreMessageID, + sizeof(RPPlayer::ScoreMessageID), + ScoreZonePointType, + message->pointValue, + GetEntityID() + ); + Dispatch(&score_message); + + // + //-------------------------------------------------------------------- + // Change the goalEntity to the new sequential scorezone if necessary + //-------------------------------------------------------------------- + // + + EntityGroup + *score_zone_group = + application->GetEntityManager()->FindGroup("ActiveScoreZones"); + if(score_zone_group) + { + ChainIteratorOf + iterator(score_zone_group->groupMembers); + ScoreZone + *score_zone; + + while ((score_zone = (ScoreZone*) iterator.ReadAndNext()) != NULL) + { + Check(score_zone); + if ( + (score_zone->scoreZoneType == LocalSequential) || + (score_zone->scoreZoneType == GlobalSequential) + ) + { + goalEntity = score_zone; + } + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::PlayerSimulation(Scalar time_slice) +{ + Check(this); + Check(application); + Check(application->GetEntityManager()); + Check(playerVehicle); + + // + //------------------------------------------------------------------------ + // Check for our synchronization signal + //------------------------------------------------------------------------ + // + if ( + (GetSimulationState() == MissionStartingState) && + ((fadeTimeRemaining - time_slice) <= 0.0f) + ) + { + lastConsoleUpdate = Now(); + } + + if (!goalEntity) + { + SetGoalToFirstScoreZone(); + PointVTVTowardGoal(); + } + + // + //------------------------------------------------------------------------ + // Call PlayerSimulation + //------------------------------------------------------------------------ + // + Player::PlayerSimulation(time_slice); + if ( + application->GetApplicationState() != Application::RunningMission + && application->GetApplicationState() != Application::EndingMission + ) + { + return; + } + + // + //------------------------------------------------------------------------ + // Update everybody once per second + //------------------------------------------------------------------------ + // + if (lastPerformance - lastUpdate >= 1.0f) + { + ForceUpdate(); + } + + // + //------------------------------------------------------------------------ + // Update the console every 15 seconds + //------------------------------------------------------------------------ + // + if (lastPerformance - lastConsoleUpdate >= 15.0f) + { + lastConsoleUpdate = lastPerformance; + + // + //--------------------------------------------- + // Tell the console (if there is one) our score + //--------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + Host *console_host = host_manager->GetConsoleHost(); + if (console_host) + { + Check(console_host); + + ConsolePlayerVTVScoreUpdateMessage + score_message(ownerID, (int)currentScore); + + application->SendMessage( + console_host->GetHostID(), + NetworkClient::ConsoleClientID, + &score_message + ); + } + } + + // + //------------------------------------------------------------------------ + // See if there are any zones to check + //------------------------------------------------------------------------ + // + if ( + GetSimulationState() != MissionEndingState + && application->GetApplicationState() == Application::RunningMission + ) + { + EntityGroup *score_zone_group = + application->GetEntityManager()->FindGroup("ActiveScoreZones"); + if(!score_zone_group) + { + Check_Fpu(); + return; + } + // + //---------------------------------- + // If VTV is in a BurningState ie. dead + // Exit from loop and don't check + // score zones + //---------------------------------- + // + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + if (vtv->GetSimulationState() == VTV::BurningState) + { + Check_Fpu(); + return; + } + + // + //---------------------------------- + // Make an iterator and send the + // "do I get points" message to + // all the active score zones + //---------------------------------- + // + Check(score_zone_group); + ChainIteratorOf + iterator(score_zone_group->groupMembers); + ScoreZone::ProcessScoreZoneRequestMessage + message( + ScoreZone::ProcessScoreZoneRequestMessageID, + sizeof(ScoreZone::ProcessScoreZoneRequestMessage), + GetEntityID(), + ScoreZoneReplyMessageID, + playerVehicle->localOrigin.linearPosition + ); + ScoreZone + *score_zone; + while ((score_zone = (ScoreZone*)iterator.ReadAndNext()) != NULL) + { + score_zone->Dispatch(&message); + } + + // + //--------------------------------- + // Get Points for speed if + // going in the right direction + //--------------------------------- + // + AccumulateSpeedPoints(time_slice); + Check_Fpu(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + RPPlayer::CalcRanking() +{ + Check(this); + Player::CalcRanking(); + Check_Fpu(); + return 1; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::CalcFootballRanking() +{ + // + //--------------------------------------- + // Get all players from the Runner group + //--------------------------------------- + // + EntityGroup + *runner_group = + application->GetEntityManager()->FindGroup("RunnerPlayers"); + Check(runner_group); + Player *active_runner; + // + //----------------------------------------------------- + // Iterate through the players add to the sorted chain + //----------------------------------------------------- + // + ChainIteratorOf + iterator(runner_group->groupMembers); + VChainOf + player_rank(NULL, False); + + while ((active_runner = (Player*) iterator.ReadAndNext()) != NULL) + { + player_rank.AddValue(active_runner, active_runner->currentScore); + } + + int num_runners = iterator.GetSize() - 1; + // + //------------------------------------------------ + // Iterate through the chain assigning the rank + //------------------------------------------------ + // + VChainIteratorOf + rank_iterator(player_rank); + + while ((active_runner = rank_iterator.ReadAndNext()) != NULL) + { + active_runner->playerRanking = num_runners; + --num_runners; + } + + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPPlayer::AccumulateSpeedPoints(Scalar time_slice) +{ + Check(this); + Scalar + compression=1.0f; + + if(scoreCompression) + { + Scalar + top_score=-1.0f; + EntityGroup + *player_group = + application->GetEntityManager()->FindGroup("Players"); + Check(player_group); + + Player + *active_player; + // + //----------------------------------------------------- + // Iterate through the players find top ranked player + //----------------------------------------------------- + // + ChainIteratorOf + iterator(player_group->groupMembers); + while ((active_player = (Player*) iterator.ReadAndNext()) != NULL) + { + if (active_player->playerRanking == 0) + { + top_score = active_player->currentScore; + break; + } + } + if (currentScore < (top_score - 400.0f)) + { + compression *= ( (top_score - currentScore) + 400.0f)/800; + } + } + + // + //------------------------------------------------------ + // Get Points for speed if going in the right direction + //------------------------------------------------------ + // + Check(playerVehicle); + Check(goalEntity); + Vector3D + to_goal, + current_heading; + + VTV + *vtv = Cast_Object(VTV*, playerVehicle); + + to_goal.Subtract( + vtv->localOrigin.linearPosition, + goalEntity->localOrigin.linearPosition); + + current_heading = vtv->worldLinearVelocity; + Scalar + length_to_goal, + length_current_heading; + + length_to_goal = to_goal.LengthSquared(); + length_current_heading = current_heading.LengthSquared(); + if (length_to_goal > SMALL && length_current_heading > SMALL) + { + Scalar + dot_prod = (to_goal * current_heading) / + (Sqrt(length_to_goal) * Sqrt(length_current_heading)); + + if (dot_prod <= 0.985f) + { + Scalar + speed_bonus = length_current_heading; + speed_bonus /= POINTS_SPEED_RATIO; + speed_bonus *= time_slice * compression; + + // + //------------------------------------------- + // Send a score message with the speed bonus + //------------------------------------------- + // + ScoreMessage + score_message( + RPPlayer::ScoreMessageID, + sizeof(RPPlayer::ScoreMessageID), + SpeedBonusPointType, + speed_bonus, + GetEntityID() + ); + if (!vtv->insideWorld) + { + score_message.scoreAward = -speed_bonus; + score_message.scoreType = OutOfBoundsType; + } + Dispatch(&score_message); + } + } + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPPlayer::RPPlayer( + RPPlayer::MakeMessage *creation_message, + SharedData &shared_data +): + Player(creation_message, shared_data), + offensivePlayerList(NULL, 0) +{ + currentScore = 1000.0f; + lastConsoleUpdate = Now(); + goalEntity = NULL; + + // + //-------------------------------- + // Get the info from the mission + //-------------------------------- + // + teamID = creation_message->teamID; + scoreCompression = creation_message->scoreCompression; + playerType = (PlayerType) creation_message->playerType; + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPPlayer* + RPPlayer::Make(RPPlayer::MakeMessage *creation_message) +{ + return new RPPlayer(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPPlayer::~RPPlayer() +{ + Check(this); + DeleteAllOffensivePlayers(); + Check_Fpu(); +} + +//############################################################################# +// Offensive Player +// + +RPPlayer__OffensivePlayer::RPPlayer__OffensivePlayer(RPPlayer *offensive_player, int damage_type, Time time_stamp) +{ + // + //----------------------------------------- + // Initialize the offensivePlayer fields + //----------------------------------------- + // + offensivePlayer = offensive_player; + damageType = damage_type; + timeStamp = time_stamp; + deathBonus = 0.0f; + Check_Fpu(); +} + +//############################################################################# +// RP Status message +// +RPPlayer__StatusMessage::RPPlayer__StatusMessage( + RPPlayer *player_involved, + int message_type, + Scalar display_time, + Scalar damage_amount +) : + Player__StatusMessage( + (Player *) player_involved, + message_type, + display_time + ) +{ + damageAmount = damage_amount; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RPPlayer::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/RPPLAYER.h b/RP/RPPLAYER.h new file mode 100644 index 0000000..dfe1eb2 --- /dev/null +++ b/RP/RPPLAYER.h @@ -0,0 +1,417 @@ +#pragma once + +#include "..\munga\player.h" +#include "..\munga\damage.h" +#include "..\munga\vchain.h" + +#define POINTS_SPEED_RATIO 400 + +class ScoreZone__ReplyMessage; +class DropZone__ReplyMessage; +class RPPlayer; + +//########################################################################## +// struct Offensive Player +// + +class RPPlayer__OffensivePlayer: + public Node +{ +public: + RPPlayer__OffensivePlayer() + {} + RPPlayer__OffensivePlayer( + RPPlayer *offensive_player, + int damage_type, + Time time_stamp + ); + + // + //----------------------------------- + // The player who caused the damage + //----------------------------------- + // + RPPlayer + *offensivePlayer; + // + //--------------------------------------------------------------- + // How many points the offensive player gets if this players dies + //--------------------------------------------------------------- + // + Scalar + deathBonus; + // + //------------------------------------------------ + // The type of damage the offensive player caused + //------------------------------------------------ + // + int + damageType; + // + //------------------------------- + // Time the damage was inflicted + //------------------------------- + // + Time + timeStamp; +}; + +//########################################################################## +//#################### RPPlayer::StatusMessage ######################### +//########################################################################## + +class RPPlayer__StatusMessage: + public Player__StatusMessage +{ +public: + RPPlayer__StatusMessage(); + + RPPlayer__StatusMessage( + RPPlayer *player_involved, + int message_type, + Scalar display_time, + Scalar damage_amount = 0.0f + ); + + enum { + DestroyedMessage = Player__StatusMessage::NextMessageType, + DestroyedByMessage, + RunnerMessage, + BlockerMessage, + CrusherMessage, + ScoreZoneMessage, + PilotErrorMessage, + Score2xMessage, + Score4xMessage, + Score8xMessage, + Score16xMessage, + CrushedMessage = Player__StatusMessage::NextMessageType, + CrushedByMessage, + BlockedMessage = Player__StatusMessage::NextMessageType, + BlockedByMessage, + DingedMessage = Player__StatusMessage::NextMessageType, + DingedByMessage, + NextMessageType + }; + + Scalar + damageAmount; + + //------------------------------------------------------ + // Memory block utilization + //------------------------------------------------------ +private: + static MemoryBlock* GetAllocatedMemory(); + enum + { + numberOfAllocatedBlocks=8 // seven kills and a suicide!!! + }; + +public: + void* + operator new(size_t) + {return GetAllocatedMemory()->New();} + void + operator delete(void *where) + { GetAllocatedMemory()->Delete(where);} +}; + +//########################################################################## +//##################### RPPlayer::MakeMessage ######################## +//########################################################################## + +class RPPlayer__MakeMessage: + public Player::MakeMessage +{ +public: + int + teamID; + + Enumeration + playerType; + + Logical + scoreCompression; + + RPPlayer__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int player_bitmap_index, + int player_type, + int team_ID, + Logical score_compression + ): + Player::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin, + player_bitmap_index + ), + teamID(team_ID) + { playerType = player_type; scoreCompression = score_compression;} + + RPPlayer__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int player_bitmap_index, + int player_type, + int team_ID, + Logical score_compression + ): + Player::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin, + player_bitmap_index + ), + teamID(team_ID) + { playerType = player_type; scoreCompression = score_compression;} +}; + +class RPPlayer__ScoreMessage: + public Player::ScoreMessage +{ + public: + int + scoreType; + + EntityID + pointSender; + + RPPlayer__ScoreMessage( + Receiver::MessageID message_ID, + size_t length, + int score_type, + Scalar score_award, + EntityID point_sender + ): + Player::ScoreMessage(message_ID, length, score_award) + { + scoreType = score_type; + pointSender = point_sender; + } +}; + + +//########################################################################## +//########################### Player ################################ +//########################################################################## + +class RPPlayer: + public Player +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +enum { + ScoreZoneReplyMessageID = Player::NextMessageID, + NextMessageID +}; +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + void MissionEndingMessageHandler(Message *message); + void MissionStartingMessageHandler(Message *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Vehicle creation +// +public: + typedef RPPlayer__ScoreMessage ScoreMessage; + typedef RPPlayer__OffensivePlayer OffensivePlayer; + typedef RPPlayer__MakeMessage MakeMessage; + typedef RPPlayer__StatusMessage RPStatusMessage; + +protected: + virtual void + DropZoneReplyMessageHandler( + DropZone__ReplyMessage *message + ); + + virtual void + ScoreZoneReplyMessageHandler( + ScoreZone__ReplyMessage *message + ); + + void + VehicleDeadMessageHandler (VehicleDeadMessage *message); + + virtual void + TakeDamageMessageHandler (TakeDamageMessage *message); + + virtual void + ScoreMessageHandler(ScoreMessage *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Damage Points Support +// + + VChainOf + offensivePlayerList; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum{ + GoalEntityAttributeID = Player::NextAttributeID, + NextAttributeID + }; + + Entity + *goalEntity; + +private: + + static const IndexEntry AttributePointers[]; + +protected: + + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (RPPlayer::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + PlayerSimulation(Scalar time_slice); + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + static RPPlayer* + Make(MakeMessage *creation_message); + + RPPlayer( + MakeMessage *creation_message, + SharedData &shared_data = DefaultData + ); + ~RPPlayer(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Local data +// +public: + enum PlayerType{ + GeneralPlayerType, + RunnerPlayerType, + CrusherPlayerType, + BlockerPlayerType, + CameraShipPlayerType + } playerType; + + enum { + NullPointType = 0, + ScoreZonePointType, + DeathBonusPointType, + DeathScoreLossPointType, + DamageBonusPointType, + DamageScoreLossPointType, + SpeedBonusPointType, + CrusherScorePointType, + DropZoneHitType, + DropZoneKillType, + OutOfBoundsType, + PointTypeCount + }; + + virtual void + AddOffensivePlayer(OffensivePlayer &offensive_player); + + int + teamID; + + int + CalcRanking(); + + void + CalcFootballRanking(); + + virtual Vector3D + GetWorldLinearVelocity() + {return Vector3D(0,0,0);} + +protected: +// +// protected Interface +// + + void + DeleteAllOffensivePlayers(); + + RPPlayer* + GetPlayer(EntityID playerID); + + void + CleanUpOffensivePlayers(); + + void + CreatePlayerVehicle(Origin); + + void + ResetAfterDeath(DropZone__ReplyMessage *message); + + void + InitializePlayerLink(); + + void + SetGoalToFirstScoreZone(); + + virtual void + PointVTVTowardGoal(); + + void + AccumulateSpeedPoints(Scalar time_slice); + + Logical + scoreCompression; + + Time + lastConsoleUpdate; +}; diff --git a/RP/RPREG.cpp b/RP/RPREG.cpp new file mode 100644 index 0000000..1feb678 --- /dev/null +++ b/RP/RPREG.cpp @@ -0,0 +1,186 @@ +#include "rp.h" +#pragma hdrstop + +#include "rpreg.h" +#include "rpmssn.h" +#include "rpplayer.h" +#include "rpdirect.h" +#include "crusher.h" +#include "runner.h" +#include "blocker.h" +#include "vtv.h" +#include "vtvpwr.h" +#include "booster.h" +#include "chute.h" +#include "scorzone.h" +#include "demopack.h" +#include "rivet.h" +#include "weapsys.h" +#include "..\munga\mission.h" +#include "..\munga\hostmgr.h" +#include "..\munga\app.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Registry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//############################################################################# +// Registry +//############################################################################# +// +RPRegistry::RPRegistry(ResourceFile *) +{ +} + +// +//############################################################################# +// ~Registry +//############################################################################# +// +RPRegistry::~RPRegistry() +{ +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Entity::SharedData* + RPRegistry::GetStaticData(ClassID class_ID) +{ + switch (class_ID) + { + case VTVClassID: + return &VTV::DefaultData; + case ScoreZoneClassID: + return &ScoreZone::DefaultData; + case RivetClassID: + return &Rivet::DefaultData; + case DemolitionPackClassID: + return &DemolitionPack::DefaultData; + case RPPlayerClassID: + return &RPPlayer::DefaultData; + case CrusherClassID: + return &Crusher::DefaultData; + case BlockerClassID: + return &Blocker::DefaultData; + case RunnerClassID: + return &Runner::DefaultData; + default: + return Registry::GetStaticData(class_ID); + } +} + +// +//############################################################################# +// GetStaticData +//############################################################################# +// +Player* + RPRegistry::MakePlayer(Mission *mission) +{ + Check_Pointer(mission); + + RPMission *rp_mission = Cast_Object(RPMission*, mission); + + const char* player_name = rp_mission->GetPositionName(); + + int team_id = rp_mission->GetTeamID(); + + Logical score_compression; + score_compression = rp_mission->ScoreCompressionOn(); + + int player_bitmap_index = rp_mission->GetPlayerBitmapIndex(); + + if (strcmp(player_name, "runner") == 0) + { + Runner::MakeMessage + make_player( + Runner::MakeMessageID, + sizeof(Runner::MakeMessage), + RunnerClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + Runner::DefaultFlags, + Origin::Identity, + player_bitmap_index, + RPPlayer::RunnerPlayerType, + team_id, + score_compression + ); + return new Runner(&make_player); + } + + else if (strcmp(player_name, "crusher") == 0) + { + Crusher::MakeMessage + make_player( + Crusher::MakeMessageID, + sizeof(Crusher::MakeMessage), + CrusherClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + Crusher::DefaultFlags, + Origin::Identity, + player_bitmap_index, + RPPlayer::CrusherPlayerType, + team_id, + score_compression + ); + return new Crusher(&make_player); + } + + else if (strcmp(player_name, "blocker") == 0) + { + Blocker::MakeMessage + make_player( + Blocker::MakeMessageID, + sizeof(Blocker::MakeMessage), + BlockerClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + Blocker::DefaultFlags, + Origin::Identity, + player_bitmap_index, + RPPlayer::BlockerPlayerType, + team_id, + score_compression + ); + return new Blocker(&make_player); + } + + else if (strcmp(mission->GetGameModel(), "camera")) + { + RPPlayer::MakeMessage + make_player( + RPPlayer::MakeMessageID, + sizeof(RPPlayer::MakeMessage), + RPPlayerClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + RPPlayer::DefaultFlags, + Origin::Identity, + player_bitmap_index, + RPPlayer::GeneralPlayerType, + team_id, + score_compression + ); + return new RPPlayer(&make_player); + } + + else + { + RPCameraDirector::MakeMessage create_director( + RPCameraDirector::MakeMessageID, + sizeof(RPCameraDirector::MakeMessage), + CameraDirectorClassID, + EntityID::Null, + ResourceDescription::NullResourceID, + RPCameraDirector::DefaultFlags, + Origin::Identity, + player_bitmap_index + ); + return new RPCameraDirector(&create_director); + } +} + diff --git a/RP/RPREG.h b/RP/RPREG.h new file mode 100644 index 0000000..e2b5601 --- /dev/null +++ b/RP/RPREG.h @@ -0,0 +1,51 @@ +#pragma once + +#include "..\munga\registry.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ Registry ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +// +//-------------------------------------------------------------------- +// Registry +// +// Provides construction methods for entities. +// Provides access to a classes static data. +//-------------------------------------------------------------------- +// + +class RPRegistry : public Registry +{ +public: + // + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // Public interface + //-------------------------------------------------------------------- + //-------------------------------------------------------------------- + // + + // + //-------------------------------------------------------------------- + // Construction, Destruction, and testing + //-------------------------------------------------------------------- + // + RPRegistry(ResourceFile *resources); + ~RPRegistry(); + + // + //-------------------------------------------------------------- + // GetStaticData + // + // Provides an interface by which the static data for a class + // may be accessed. + //-------------------------------------------------------------- + // + Entity__SharedData* GetStaticData(ClassID entity_class); + + // + //------------------------- + // Create the player object + //------------------------- + // + Player* MakePlayer(Mission *mission); +}; diff --git a/RP/RPTOOL.cpp b/RP/RPTOOL.cpp new file mode 100644 index 0000000..4decd9b --- /dev/null +++ b/RP/RPTOOL.cpp @@ -0,0 +1,180 @@ +#include "rp.h" +#pragma hdrstop + +#include "rptool.h" +#include "..\munga\fileutil.h" +#include "vtv.h" +#include "scorzone.h" +#include "rivet.h" +#include "demopack.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RPTool::CreateMakeMessage( + const char* class_name, + Entity::MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(class_name,"VTVClassID")) + { + VTV::CreateMakeMessage( + (VTV::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + else if (!stricmp(class_name,"ScoreZoneClassID")) + { + ScoreZone::CreateMakeMessage( + (ScoreZone::MakeMessage*)creation_message, + model_file, + directories + ); + return True; + } + + return + ApplicationTool::CreateMakeMessage( + class_name, + creation_message, + model_file, + directories + ); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPTool::CreateModelResource( + ModelData &model_resources, + const char *model_class, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + if (!stricmp(model_class, "VTVClassID")) + { +#if 0 + strcpy(ops_file_data, ops_name); + strcat(ops_file_data, "::Standard::Vehicle::"); + strcat(ops_file_data, model_name ); + strcpy(ops_file_page, ops_name); + strcat(ops_file_page, "::Standard::VehicleList"); + + ops_file->AppendEntry(ops_file_page, "vehicle", ops_file_data); + ops_file->SetEntry(ops_file_data, "tag", model_name ); + ops_file->SetEntry(ops_file_data, "classID", "RPVh"); + ops_file->AppendEntry(ops_file_data, NULL, (char *)NULL); +#endif + + model_resources.gameResourceID = + VTV::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + model_resources.subsystemResourceID = + VTV::CreateSubsystemStream( + resource_file, + model_name, + model_file, + directories + ); + model_resources.skeletonResourceID = + VTV::CreateSkeletonStream( + resource_file, + model_name, + model_file, + directories + ); + model_resources.damageZoneResourceID = + VTV::CreateDamageZoneStream( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "RivetClassID")) + { + model_resources.gameResourceID = + Rivet::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "DemolitionPackClassID")) + { + model_resources.gameResourceID = + DemolitionPack::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else if (!stricmp(model_class, "ScoreZoneClassID")) + { + model_resources.gameResourceID = + ScoreZone::CreateModelResource( + resource_file, + model_name, + model_file, + directories + ); + } + else + { + ApplicationTool::CreateModelResource( + model_resources, + model_class, + resource_file, + model_name, + model_file, + directories + ); + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + RPTool::CreateControlMappingStream( + const char *model_class, + const char *mapping_name, + NotationFile *mapping_file, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + ) +{ + if (!stricmp(model_class, "VTVClassID")) + { + return + VTV::CreateControlMappingStream( + mapping_name, + mapping_file, + platformTool->GetControlMappingFunction(), + resource_file, + model_name, + model_file, + directories, + current_tool + ); + } + else + { + return -1; + } +} diff --git a/RP/RPTOOL.h b/RP/RPTOOL.h new file mode 100644 index 0000000..a5f88f2 --- /dev/null +++ b/RP/RPTOOL.h @@ -0,0 +1,20 @@ +#pragma once + +#include "..\munga\tool.h" + +//########################################################################## +//############################ RPTool ################################ +//########################################################################## + +class RPTool : public ApplicationTool +{ +protected: + Logical CreateMakeMessage(const char* class_name, Entity::MakeMessage *creation_message, NotationFile *model_file, const ResourceDirectories *directories); + + void CreateModelResource(ModelData &model_resources, const char *model_class, ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories *directories); + + ResourceDescription::ResourceID CreateControlMappingStream(const char *model_class, const char *mapping_name, NotationFile *mapping_file, ResourceFile *resource_file, const char *model_name, NotationFile *model_file, const ResourceDirectories *directories, PlatformTool *current_tool); + +public: + RPTool(PlatformTool *platform) : ApplicationTool(platform) {} +}; diff --git a/RP/RUNNER.cpp b/RP/RUNNER.cpp new file mode 100644 index 0000000..c952f15 --- /dev/null +++ b/RP/RUNNER.cpp @@ -0,0 +1,281 @@ +#include "rp.h" +#pragma hdrstop + +#include "runner.h" +#include "..\munga\dropzone.h" +#include "vtv.h" +#include "..\munga\hostmgr.h" +#include "..\munga\app.h" +#include "scorzone.h" +#include "..\munga\nttmgr.h" + +//############################################################################# +//############################### Runner ############################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +Derivation* Runner::GetClassDerivations() +{ static Derivation classDerivations(RPPlayer::GetClassDerivations(), "Runner"); + return &classDerivations; +} + + +Runner::SharedData + Runner::DefaultData( + Runner::GetClassDerivations(), + Runner::MessageHandlers, + Runner::GetAttributeIndex(), + Runner::StateCount, + (Runner::MakeHandler)Runner::Make + ); + +const Receiver::HandlerEntry + Runner::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(Runner, VehicleDead), + MESSAGE_ENTRY(Runner, Score), + MESSAGE_ENTRY(Runner, DropZoneReply), + MESSAGE_ENTRY(Runner, ScoreZoneReply) +}; + +Receiver::MessageHandlerSet + Runner::MessageHandlers( + ELEMENTS(Runner::MessageHandlerEntries), + Runner::MessageHandlerEntries, + RPPlayer::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Runner::Runner( + MakeMessage *creation_message, + SharedData &shared_data +) +: RPPlayer(creation_message, shared_data) +{ + StatusMessage + *message = new StatusMessage(NULL,RPStatusMessage::RunnerMessage,1e10); + Register_Object(message); + AddStatusMessage(message); + dropZonePenaltyOver.ticks = 0; + scoreMultiplier = 1.0f; + + //---------------------------------------- + // Add to runner group + //---------------------------------------- + EntityManager + *entity_manager = application->GetEntityManager(); + Check(entity_manager); + + EntityGroup + *runner_group = entity_manager->UseGroup("RunnerPlayers"); + Check(runner_group); + + runner_group->Add(this); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Runner* + Runner::Make(MakeMessage *creation_message) +{ + return new Runner(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Runner::AddOffensivePlayer(OffensivePlayer &offensive_player) +{ + Check(offensive_player.offensivePlayer); + RPPlayer *rp_player = offensive_player.offensivePlayer; + // + //--------------------------------------------- + // Death Points awarded if .... + // This Runner gets hit by a crusher, blocker or runner + // from the other team with collision Damage! + //--------------------------------------------- + // + if ( + rp_player->playerType == CrusherPlayerType + && teamID != rp_player->teamID + && offensive_player.damageType == Damage::CollisionDamageType) + { + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + if (vtv->boosterOn) + { + dropZonePenaltyOver.ticks = 0; + } + offensive_player.deathBonus = (Now() <= dropZonePenaltyOver) ? -5000.0f : 500.0f; + } + else + if ( + rp_player->playerType == BlockerPlayerType + && teamID != rp_player->teamID + && offensive_player.damageType == Damage::CollisionDamageType) + { + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + if (vtv->boosterOn) + { + dropZonePenaltyOver.ticks = 0; + } + offensive_player.deathBonus = (Now() <= dropZonePenaltyOver) ? -6666.0f : 0.0f; + } + else + if ( + rp_player->playerType == RunnerPlayerType + && teamID != rp_player->teamID + && offensive_player.damageType == Damage::CollisionDamageType) + { + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + if (vtv->boosterOn) + { + dropZonePenaltyOver.ticks = 0; + } + offensive_player.deathBonus = (Now() <= dropZonePenaltyOver) ? -10000.0f : 0.0f; + } + else + { + offensive_player.deathBonus = 0.0f; + } + + + offensivePlayerList.AddValue(&offensive_player,offensive_player.damageType); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Runner::ScoreMessageHandler(ScoreMessage *message) +{ + RPPlayer::ScoreMessageHandler(message); + switch (message->scoreType) + { + case ScoreZonePointType: + case SpeedBonusPointType: + currentScore += message->scoreAward * scoreMultiplier; + break; + + case DamageScoreLossPointType: + { + if (Now() >= dropZonePenaltyOver) + { + goto Standard_Score; + } + VTV *vtv = (VTV*)playerVehicle; + Check(vtv); + if (vtv->boosterOn) + { + dropZonePenaltyOver.ticks = 0; + goto Standard_Score; + } + } + break; + + default: +Standard_Score: + currentScore += message->scoreAward; + break; + } + + // + // HACK - ECH 7/6/95 - Allow the player vehicle to respond to score + // messages, allows attribute system to be used for scoring + // + Check(playerVehicle); + playerVehicle->RespondToScoreMessage(message); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Runner::ScoreZoneReplyMessageHandler( + ScoreZone::ReplyMessage *message + ) +{ + RPPlayer::ScoreZoneReplyMessageHandler(message); + // + //--------------------------------------------------------- + // double the scoreMultiplier + //--------------------------------------------------------- + // + Check(playerVehicle); + VTV *vtv = (VTV*)playerVehicle; + if (vtv->GetSimulationState() != VTV::BurningState) + { + scoreMultiplier *= 2.0f; + if (scoreMultiplier > 16.0f) + scoreMultiplier = 16.0f; + if (scoreMultiplier == 2.0f) + { + RPStatusMessage *message = new RPStatusMessage(NULL, RPStatusMessage::Score2xMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *) message); + } + if (scoreMultiplier == 4.0f) + { + RPStatusMessage *message = new RPStatusMessage(NULL, RPStatusMessage::Score4xMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *) message); + } + if (scoreMultiplier == 8.0f) + { + RPStatusMessage *message = new RPStatusMessage(NULL, RPStatusMessage::Score8xMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *) message); + } + if (scoreMultiplier == 16.0f) + { + RPStatusMessage *message = new RPStatusMessage(NULL, RPStatusMessage::Score16xMessage, 6.0f); + Register_Object(message); + AddStatusMessage((StatusMessage *) message); + } + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Runner::VehicleDeadMessageHandler(VehicleDeadMessage *message) +{ + Check(this); + Check(message); + + scoreMultiplier = 1.0f; + RPPlayer::VehicleDeadMessageHandler(message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Runner::DropZoneReplyMessageHandler( + DropZone__ReplyMessage *message + ) +{ + Check(this); + Check(message); + + if ( + playerVehicle + && deathCount == message->deathCount + && GetSimulationState() != DropZoneAcquiredState + ) + { + dropZonePenaltyOver = Now(); + dropZonePenaltyOver += 5.0f; + } + + RPPlayer::DropZoneReplyMessageHandler(message); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Runner::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/RUNNER.h b/RP/RUNNER.h new file mode 100644 index 0000000..132f8d0 --- /dev/null +++ b/RP/RUNNER.h @@ -0,0 +1,61 @@ +#pragma once + +#include "rpplayer.h" + +//########################################################################## +//########################### Runner ################################ +//########################################################################## +class Runner : public RPPlayer +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; + +public: + void ScoreZoneReplyMessageHandler(ScoreZone__ReplyMessage *message); + void ScoreMessageHandler(ScoreMessage *message); + void VehicleDeadMessageHandler(VehicleDeadMessage *message); + void DropZoneReplyMessageHandler(DropZone__ReplyMessage *message); + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + + typedef void (Runner::*Performance)(Scalar time_slice); + + void SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + Time dropZonePenaltyOver; + Scalar scoreMultiplier; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + Runner(MakeMessage *creation_message, SharedData &shared_data = DefaultData); + ~Runner() {} + + Logical TestInstance() const; + + static Runner* Make(MakeMessage *creation_message); + + void AddOffensivePlayer(OffensivePlayer &offensive_player); + +}; diff --git a/RP/SCORZONE.cpp b/RP/SCORZONE.cpp new file mode 100644 index 0000000..8a60800 --- /dev/null +++ b/RP/SCORZONE.cpp @@ -0,0 +1,577 @@ +#include "rp.h" +#pragma hdrstop + +#include "scorzone.h" +#include "..\munga\fileutil.h" +#include "..\munga\nttmgr.h" +#include "..\munga\app.h" +#include "..\munga\hostmgr.h" +#include "..\munga\notation.h" + +//############################################################################# +//############################### ScoreZone ############################# +//############################################################################# + +//############################################################################# +// Shared Data Support +// + +Derivation* ScoreZone::GetClassDerivations() +{ + static Derivation classDerivations(Entity::GetClassDerivations(), "ScoreZone"); + return &classDerivations; +} + +ScoreZone::SharedData + ScoreZone::DefaultData( + ScoreZone::GetClassDerivations(), + ScoreZone::MessageHandlers, + ScoreZone::GetAttributeIndex(), + ScoreZone::StateCount, + (Entity::MakeHandler)ScoreZone::Make + ); +//############################################################################# +// Attribute Support +// + +const ScoreZone::IndexEntry + ScoreZone::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(ScoreZone, ScoreZoneType, scoreZoneType), + ATTRIBUTE_ENTRY(ScoreZone, PointValue, pointValue) +}; + +ScoreZone::AttributeIndexSet& ScoreZone::GetAttributeIndex() +{ + static ScoreZone::AttributeIndexSet attributeIndex(ELEMENTS(ScoreZone::AttributePointers), + ScoreZone::AttributePointers, + Entity::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Message Support +// +const Receiver::HandlerEntry + ScoreZone::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(ScoreZone, ProcessScoreZoneRequest) +}; + +Receiver::MessageHandlerSet + ScoreZone::MessageHandlers( + ELEMENTS(ScoreZone::MessageHandlerEntries), + ScoreZone::MessageHandlerEntries, + Entity::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void + ScoreZone::ProcessScoreZoneRequestMessageHandler( + ProcessScoreZoneRequestMessage *message + ) +{ + Check(this); + Check_Pointer(message); + + // + //---------------------------------------- + // Make sure that the score zone is active + //---------------------------------------- + // + EntityGroup *score_zone_group; + if (GetSimulationState() == Active) + { + // + //----------------------------------------------------------- + // If Sequential, hunt for ourselves in the sequential group + //----------------------------------------------------------- + // + Check(application); + EntityManager *entity_mgr = application->GetEntityManager(); + Check(entity_mgr); + if ( + scoreZoneType == LocalSequential + || scoreZoneType == GlobalSequential + ) + { + int new_zone = sequenceNumber + 1; + score_zone_group = entity_mgr->FindGroup("SequentialScoreZones"); + Check(score_zone_group); + ChainIteratorOf iterator(score_zone_group->groupMembers); + ScoreZone + *score_zone, + *first_score_zone = NULL; + + // + //------------------------------------------------------------------ + // Store the first score zone in case we run off the end of the list + //------------------------------------------------------------------ + // + while ((score_zone = (ScoreZone*)iterator.ReadAndNext()) != NULL) + { + Check(score_zone); + if (score_zone->sequenceNumber == 1) + { + first_score_zone = score_zone; + } + if (score_zone->sequenceNumber == new_zone) + { + break; + } + } + if (!score_zone) + { + score_zone = first_score_zone; + } + + if (score_zone->GetSimulationState() == InActive) + { + score_zone->SetSimulationState(Active); + score_zone_group = entity_mgr->FindGroup("ActiveScoreZones"); + Check(score_zone_group); + score_zone_group->Add(score_zone); + } + } + + // + //---------------------------------------------------------------- + // Set the zone as inactive, remove ourselves from the active list + //---------------------------------------------------------------- + // + SetSimulationState(InActive); + score_zone_group = entity_mgr->FindGroup("ActiveScoreZones"); + Check(score_zone_group); + ChainIteratorOf iterator(score_zone_group->groupMembers); + ScoreZone *score_zone; + while ((score_zone = (ScoreZone*)iterator.GetCurrent()) != NULL) + { + if (score_zone == this) + { + iterator.Remove(); + break; + } + iterator.Next(); + } + + // + //----------------------------------- + // Send the points back to the player + //----------------------------------- + // + ReplyMessage + reply( + message->replyMessageID, + sizeof(ReplyMessage), + pointValue + ); + Check(application); + HostManager *host = application->GetHostManager(); + Check(host); + Entity *entity = host->GetEntityPointer(message->requestingEntity); + Check(entity); + entity->Dispatch(&reply); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + ScoreZone::Dispatch(Receiver::Message *message) +{ + Check(this); + Check(message); + + ProcessScoreZoneRequestMessage *score_zone_message = + (ProcessScoreZoneRequestMessage*) message; + if (score_zone_message->messageID == ProcessScoreZoneRequestMessageID) + { + if (!extentBox.Contains(score_zone_message->linearPosition)) + { + Check_Fpu(); + return; + } + } + Entity::Dispatch(score_zone_message); + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ScoreZone::ScoreZone( + ScoreZone::MakeMessage *creation_message, + ScoreZone::SharedData &virtual_data +): + Entity(creation_message, virtual_data) +{ + Check_Pointer(this); + Check_Pointer(creation_message); + + SetValidFlag(); + + //------------------------------------------------- + // Find the drop zone resource in the resource file + //------------------------------------------------- + ResourceFile + *res_file = application->GetResourceFile(); + Check(res_file); + ResourceDescription *res = + res_file->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + + // + // Get ScoreZone Info + // + sequenceNumber = creation_message->sequenceNumber; + + ModelResource + *score_res = (ModelResource*)res->resourceAddress; + + scoreZoneType = score_res->scoreZoneType; + pointValue = score_res->pointValue; + extentBox = score_res->extentBox; + + extentBox.minX += localOrigin.linearPosition.x; + extentBox.minY += localOrigin.linearPosition.y; + extentBox.minZ += localOrigin.linearPosition.z; + + extentBox.maxX += localOrigin.linearPosition.x; + extentBox.maxY += localOrigin.linearPosition.y; + extentBox.maxZ += localOrigin.linearPosition.z; + + SetSimulationState(InActive); + + res->Unlock(); + //--------------------------------------------------------------------- + // Make the sequential score zone list. Only make the first sequential + // score zone active + //--------------------------------------------------------------------- + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *score_zones; + + if (scoreZoneType == LocalSequential || scoreZoneType == GlobalSequential) + { + score_zones = entity_manager->UseGroup("SequentialScoreZones"); + Check(score_zones); + score_zones->Add(this); + if (sequenceNumber == 1) + { + goto Active_Zone; + } + } + + // + //------------------------------------------------ + // If it isn't a sequential, always make it active + //------------------------------------------------ + // + else + { +Active_Zone: + score_zones = entity_manager->UseGroup("ActiveScoreZones"); + Check(score_zones); + SetSimulationState(Active); + score_zones->Add(this); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ScoreZone* + ScoreZone::Make(ScoreZone::MakeMessage *creation_message) +{ + return new ScoreZone(creation_message); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ScoreZone::CreateMakeMessage( + MakeMessage *creation_message, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(creation_message); + Check(model_file); + + if (!Entity::CreateMakeMessage(creation_message, model_file, directories)) + { + Check_Fpu(); + return False; + } + + creation_message->classToCreate = RegisteredClass::ScoreZoneClassID; + creation_message->messageLength = sizeof(*creation_message); + creation_message->instanceFlags = + IndependantInstance|DynamicFlag|MapFlag|TrappedFlag; + + char *p; + creation_message->sequenceNumber = -1; + if ((p = strtok(NULL, " ")) != NULL) + { + creation_message->sequenceNumber = atoi(p); + } + + Check_Fpu(); + return True; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ScoreZone::~ScoreZone() +{ + Check(this); + + if (scoreZoneType == LocalSequential || scoreZoneType == GlobalSequential) + { + Check(application); + EntityManager *entity_mgr = application->GetEntityManager(); + Check(entity_mgr); + EntityGroup *score_zone_group = + entity_mgr->FindGroup("SequentialScoreZones"); + if (score_zone_group) + { + ChainIteratorOf iterator(score_zone_group->groupMembers); + ScoreZone *score_zone = (ScoreZone*)iterator.GetCurrent(); + if (score_zone == this) + { + iterator.Remove(); + if (!iterator.GetCurrent()) + { + entity_mgr->RemoveGroup(score_zone_group); + } + } + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + ScoreZone::CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile * model_file, + const ResourceDirectories *directories, + ModelResource *model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check_Pointer(directories); + + // + // If we were not provided a buffer to write the model data into, we must + // create it ourselves. Then make sure that the model stuff is read in + // + ModelResource *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + + + // + // Get PointValue assigned to this ScoreZone + // + if( + !model_file->GetEntry( + "gamedata", + "PointValue", + &local_model->pointValue + ) + ) + { + std::cerr << model_name << "Missing PointValue" << std::endl; +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + Check_Fpu(); + return -1; + } + // + // Get The ScoreZone Type + // + const char* score_zone_type; + if( + !model_file->GetEntry( + "gamedata", + "ScoreZoneType", + &score_zone_type + ) + ) + { + std::cerr << model_name << "Missing ScoreZoneType" << std::endl; + goto Dump_And_Die; + } + else + { + if(strcmp(score_zone_type,"GlobalOneTime") == 0) + { + local_model->scoreZoneType = GlobalOneTime; + } + else + if(strcmp(score_zone_type,"LocalOneTime") == 0) + { + local_model->scoreZoneType = LocalOneTime; + } + else + if(strcmp(score_zone_type,"GlobalSequential") == 0) + { + local_model->scoreZoneType = GlobalSequential; + } + else + if(strcmp(score_zone_type,"LocalSequential") == 0) + { + local_model->scoreZoneType = LocalSequential; + } + } + // + // Read In the Extent Box from the solid file determined by the + // collision data + // + const char* sld_entry; + if( + !model_file->GetEntry( + "gamedata", + "Extents", + &sld_entry + ) + ) + { + std::cerr << model_name << "Missing .sld Specifications " << std::endl; + goto Dump_And_Die; + } + else + { + char *sld_filename = + MakePathedFilename(directories->collisionDirectory, sld_entry); + Register_Pointer(sld_filename); + + NotationFile *sld_file = new NotationFile(sld_filename); + Register_Object(sld_file); + if(sld_file->PageCount() == 0) + { + std::cerr <MakeEntryList("volume 0","extm"); + Register_Object(sld_namelist); + if (sld_namelist->EntryCount() == 0) + { +Dump_And_Die_2: + Unregister_Pointer(sld_filename); + delete sld_filename; + Unregister_Object(sld_file); + delete sld_file; + Unregister_Object(sld_namelist); + delete sld_namelist; + goto Dump_And_Die; + } + NameList::Entry *extent_entry = sld_namelist->GetFirstEntry(); + while(extent_entry) + { + Scalar value = extent_entry->GetAtof(); + if (strcmp(extent_entry->GetName(),"extminX") == 0) + { + local_model->extentBox.minX = value; + } + else + if (strcmp(extent_entry->GetName(),"extminY") == 0) + { + local_model->extentBox.minY = value; + } + else + if (strcmp(extent_entry->GetName(),"extminZ") == 0) + { + local_model->extentBox.minZ = value; + } + else + if (strcmp(extent_entry->GetName(),"extmaxX") == 0) + { + local_model->extentBox.maxX = value; + } + else + if (strcmp(extent_entry->GetName(),"extmaxY") == 0) + { + local_model->extentBox.maxY = value; + } + else + if (strcmp(extent_entry->GetName(),"extmaxZ") == 0) + { + local_model->extentBox.maxZ = value; + } + else + { + std::cerr << sld_filename << "Improper Extent Format" << std::endl; + goto Dump_And_Die_2; + } + extent_entry = extent_entry->GetNextEntry(); + } + Unregister_Pointer(sld_filename); + delete sld_filename; + Unregister_Object(sld_file); + delete sld_file; + Unregister_Object(sld_namelist); + delete sld_namelist; + } + // + //--------------------------- + // Write out the new resource + //--------------------------- + // + if (!model) + { + ResourceDescription *new_res = + resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Check_Fpu(); + return 0; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + ScoreZone::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/SCORZONE.h b/RP/SCORZONE.h new file mode 100644 index 0000000..22fd24c --- /dev/null +++ b/RP/SCORZONE.h @@ -0,0 +1,271 @@ +#pragma once + +#include "..\munga\entity.h" +#include "..\munga\boxsolid.h" + +enum ScoreZone__ScoreZoneType { + GlobalOneTime, + LocalOneTime, + GlobalSequential, + LocalSequential + } ; + +//########################################################################## +//##################### ScoreZone::ModelResource ##################### +//########################################################################## + +struct ScoreZone__ModelResource +{ + ExtentBox + extentBox; + + ScoreZone__ScoreZoneType + scoreZoneType; + + Scalar + pointValue; + +}; + +//########################################################################## +//#################### ScoreZone::MakeMessage ######################## +//########################################################################## + +class ScoreZone__MakeMessage: + public Entity::MakeMessage +{ +public: + int + sequenceNumber; + + ScoreZone__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int sequence + ): + Entity::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + sequenceNumber(sequence) + {} + ScoreZone__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + int sequence + ): + Entity::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin + ), + sequenceNumber(sequence) + {} +}; + +//########################################################################## +//############ ScoreZone::ProcessScoreRequestMessage ################# +//########################################################################## + +class ScoreZone__ProcessScoreZoneRequestMessage : + public Entity::Message +{ +public: + EntityID + requestingEntity; + + Receiver::MessageID + replyMessageID; + + Vector3D + linearPosition; + + ScoreZone__ProcessScoreZoneRequestMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &reply_to, + Receiver::MessageID reply_ID, + Vector3D vtv_pos + ): + Entity::Message(message_ID, length), + requestingEntity(reply_to), + replyMessageID(reply_ID) + { + linearPosition = vtv_pos; + } +}; + +//########################################################################## +//################# ScoreZone::ReplyMessage ########################## +//########################################################################## + +class ScoreZone__ReplyMessage: + public Entity::Message +{ +public: + Scalar + pointValue; + + ScoreZone__ReplyMessage( + Receiver::MessageID message_ID, + size_t length, + const Scalar point_value=0.0f + ): + Entity::Message(message_ID, length) + { + pointValue = point_value; + } +}; + + //########################################################################## + //########################## ScoreZone ################################ + //########################################################################## + +class ScoreZone: + public Entity +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + + static SharedData DefaultData; + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum { + ProcessScoreZoneRequestMessageID = Entity::NextMessageID, + NextMessageID + }; + + typedef ScoreZone__MakeMessage MakeMessage; + +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; + +public: + + void + Dispatch(Receiver::Message *message); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// + +enum{ + ScoreZoneTypeAttributeID = Entity::NextAttributeID, + PointValueAttributeID, + NextAttributeID +}; + +private: + + static const IndexEntry AttributePointers[]; + +protected: + + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +public: + + Scalar + pointValue; + + typedef ScoreZone__ScoreZoneType ScoreZoneType; + ScoreZoneType + scoreZoneType; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// + + +enum ScoreZoneState{ + Active = Entity::StateCount, + InActive, + StateCount +}; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef ScoreZone__ModelResource ModelResource; + + static ScoreZone* + Make(MakeMessage *creation_message); + + static Logical + CreateMakeMessage( + MakeMessage *creation_stream, + NotationFile *model_file, + const ResourceDirectories *directories + ); + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char* model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource *model=NULL + ); + + ScoreZone( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~ScoreZone(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Scorezone assignment +// + +public: + typedef ScoreZone__ProcessScoreZoneRequestMessage + ProcessScoreZoneRequestMessage; + typedef ScoreZone__ReplyMessage ReplyMessage; + + ExtentBox + extentBox; + int + sequenceNumber; + +protected: + + void + ProcessScoreZoneRequestMessageHandler( + ProcessScoreZoneRequestMessage *message + ); +}; diff --git a/RP/THRUSTER.cpp b/RP/THRUSTER.cpp new file mode 100644 index 0000000..0f02791 --- /dev/null +++ b/RP/THRUSTER.cpp @@ -0,0 +1,401 @@ +#include "rp.h" +#pragma hdrstop + +#include "thruster.h" +#include "vtvmppr.h" +#include "..\munga\boxsolid.h" +#include "vtv.h" + +//############################################################################# +// Shared Data Support +// +Thruster::SharedData + Thruster::DefaultData( + Thruster::GetClassDerivations(), + Thruster::GetMessageHandlers(), + Thruster::GetAttributeIndex(), + Thruster::StateCount + ); + +Derivation* Thruster::GetClassDerivations() +{ + static Derivation classDerivations(Subsystem::GetClassDerivations(), "Thruster"); + return &classDerivations; +} + +//############################################################################# +// Attribute Support +// +const Thruster::IndexEntry + Thruster::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(Thruster, ThrusterOffset, thrusterOffset), + ATTRIBUTE_ENTRY(Thruster, ThrusterPosition, thrusterPosition), + ATTRIBUTE_ENTRY(Thruster, CurrentAcceleration, currentAcceleration), + ATTRIBUTE_ENTRY(Thruster, CurrentHeight, currentHeight), + ATTRIBUTE_ENTRY(Thruster, MaxThrusterRotationRate, maxThrusterRotationRate), + ATTRIBUTE_ENTRY(Thruster, MomentArm, momentArm), + ATTRIBUTE_ENTRY(Thruster, MomentArmLength, momentArmLength) +}; + +Thruster::AttributeIndexSet& Thruster::GetAttributeIndex() +{ + static Thruster::AttributeIndexSet attributeIndex(ELEMENTS(Thruster::AttributePointers), + Thruster::AttributePointers, + Subsystem::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// +void + Thruster::PrimeThruster(Scalar time_slice) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + if (vtv->GetSimulationState() == VTV::BurningState) + { + Check_Fpu(); + return; + } + + VTVControlsMapper* controls = + Cast_Object( + VTVControlsMapper*, + vtv->GetSubsystem(VTV::ControlsMapperSubsystem) + ); + Check(controls); + Vector3D power_demand = controls->powerDemand; + + + // + //------------------------------------------------------------------- + // Rotate the engines so that they can match to power demand requests + //------------------------------------------------------------------- + // + Scalar desire,new_rad; + if ( + controls->controlMode == VTVControlsMapper::BasicMode + && Small_Enough(vtv->localVelocity.linearMotion.z, 1.0f) + ) + { + desire = 0.0f; + } + else if (Small_Enough(power_demand.z) && Small_Enough(power_demand.y)) + { + desire = 0.0f; + } + else + { + desire = Arctan(power_demand.z, power_demand.y); + } + + Check(thrusterPosition); + if (thrusterPosition->GetRadians() < desire) + { + new_rad = + thrusterPosition->GetRadians() + + time_slice * maxThrusterRotationRate; + Max_Clamp(new_rad, desire); + vtv->thrusterAngle = new_rad; + } + else if (thrusterPosition->GetRadians() > desire) + { + new_rad = + thrusterPosition->GetRadians() + - time_slice * maxThrusterRotationRate; + Min_Clamp(new_rad, desire); + vtv->thrusterAngle = new_rad; + } + thrusterPosition->SetRotation(vtv->thrusterAngle); + + if (!Close_Enough(desire, updatedPosition, 10.0f*RAD_PER_DEG)) + { + ForceUpdate(); + updatedPosition = desire; + } + + // + //------------------------------------------------------------------- + // Calculate the vertical thrust based upon the height of each engine + //------------------------------------------------------------------- + // + Verify(vtv->GetMoverCollisionRoot()); + BoundingBoxTreeNode *tree = vtv->GetMoverCollisionRoot(); + + currentHeight = 0.0f; + Point3D test_point; + test_point.Multiply(thrusterOffset, vtv->localToWorld); + tree->FindBoundingBoxUnder(test_point, ¤tHeight); + + Vector3D force; + force.Multiply(power_demand, currentAcceleration); + if (power_demand.y > SMALL) + { + Vector3D ge = Vector3D::Identity; + ge.y = + vtv->groundEffectRange * power_demand.y * powerScale + / (1.0f + vtv->groundEffectDomainSquared*currentHeight*currentHeight); + Check_Fpu(); + Vector3D local_ge; + local_ge.MultiplyByInverse(ge, vtv->localToWorld); + force += local_ge; + } +#if defined(WOOBLY) + vtv->ApplyLocalAcceleration(force, momentArm); +#else + vtv->localAcceleration.linearMotion += force; +#endif + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Thruster::SlaveThruster(Scalar) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + if (vtv->GetSimulationState() == VTV::BurningState) + { + Check_Fpu(); + return; + } + + VTVControlsMapper* controls = + Cast_Object( + VTVControlsMapper*, + vtv->GetSubsystem(VTV::ControlsMapperSubsystem) + ); + Check(controls); + Vector3D power_demand = controls->powerDemand; + + + // + //------------------------------------------------------------------- + // Rotate the engines so that they can match to power demand requests + //------------------------------------------------------------------- + // + thrusterPosition->SetRotation(vtv->thrusterAngle); + + // + //------------------------------------------------------------------- + // Calculate the vertical thrust based upon the height of each engine + //------------------------------------------------------------------- + // + Verify(vtv->GetMoverCollisionRoot()); + BoundingBoxTreeNode *tree = vtv->GetMoverCollisionRoot(); + + currentHeight = 0.0f; + Point3D test_point; + test_point.Multiply(thrusterOffset, vtv->localToWorld); + tree->FindBoundingBoxUnder(test_point, ¤tHeight); + + Vector3D force; + force.Multiply(power_demand, currentAcceleration); + if (power_demand.y > SMALL) + { + Vector3D ge = Vector3D::Identity; + ge.y = + vtv->groundEffectRange * power_demand.y * powerScale + / (1.0f + vtv->groundEffectDomainSquared*currentHeight*currentHeight); + Check_Fpu(); + Vector3D local_ge; + local_ge.MultiplyByInverse(ge, vtv->localToWorld); + force += local_ge; + } +#if defined(WOOBLY) + vtv->ApplyLocalAcceleration(force, momentArm); +#else + vtv->localAcceleration.linearMotion += force; +#endif + Check_Fpu(); +} + +//############################################################################# +// Model Support +// +void + Thruster::PrimeDeadReckon(Scalar time_slice) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + if (vtv->GetSimulationState() == VTV::BurningState) + { + Check_Fpu(); + return; + } + + Check(thrusterPosition); + Scalar new_rad; + if (thrusterPosition->GetRadians() < updatedPosition) + { + new_rad = + thrusterPosition->GetRadians() + + time_slice * maxThrusterRotationRate; + Max_Clamp(new_rad, updatedPosition); + vtv->thrusterAngle = new_rad; + } + else if (thrusterPosition->GetRadians() > updatedPosition) + { + new_rad = + thrusterPosition->GetRadians() + - time_slice * maxThrusterRotationRate; + Min_Clamp(new_rad, updatedPosition); + vtv->thrusterAngle = new_rad; + } + thrusterPosition->SetRotation(vtv->thrusterAngle); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Thruster::SlaveDeadReckon(Scalar) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + if (vtv->GetSimulationState() == VTV::BurningState) + { + Check_Fpu(); + return; + } + + thrusterPosition->SetRotation(vtv->thrusterAngle); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Thruster::ReadUpdateRecord(Simulation::UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + Subsystem::ReadUpdateRecord(message); + UpdateRecord* record = (UpdateRecord*) message; + + updatedPosition = record->thrusterRotation; + + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + Thruster::WriteUpdateRecord(Simulation::UpdateRecord *record, int update_model) +{ + Check(this); + Check_Pointer(record); + + Subsystem::WriteUpdateRecord(record, update_model); + UpdateRecord* update = (UpdateRecord*) record; + + update->recordLength = sizeof(*update); + update->thrusterRotation = updatedPosition; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Thruster::Thruster( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + Subsystem(owner, subsystem_ID, subsystem_resource, DefaultData) +{ + if (owner->GetInstance() != VTV::ReplicantInstance) + { + if (subsystem_resource->primeThruster) + { + SetPerformance(&Thruster::PrimeThruster); + } + else + { + SetPerformance(&Thruster::SlaveThruster); + } + } + else if (subsystem_resource->primeThruster) + { + SetPerformance(&Thruster::PrimeDeadReckon); + } + else + { + SetPerformance(&Thruster::SlaveDeadReckon); + } + + // + // Get the offset from the linear matrix by peeliong + // off the translation part + // + EntitySegment *segment = owner->GetSegment(segmentIndex); + momentArm = thrusterOffset = segment->GetBaseOffset(); + + thrusterOffset.y = owner->GetCollisionTemplate()->minY; + momentArm.y = 0.0f; + momentArmLength = momentArm.Length(); + powerScale = 0.0f; + // + // Get the thruster position from the joint subsystem of the VTV + // + JointSubsystem *joint_subsystem = owner->GetJointSubsystem(); + Check(joint_subsystem); + + thrusterPosition = joint_subsystem->GetJoint(subsystem_resource->jointIndex); + + currentAcceleration = 0.0f; + currentHeight = 0.0f; + maxThrusterRotationRate = subsystem_resource->maxThrusterRotationRate; + updatedPosition = 0.0f; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Thruster::~Thruster() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + Thruster::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/THRUSTER.h b/RP/THRUSTER.h new file mode 100644 index 0000000..9efa7ff --- /dev/null +++ b/RP/THRUSTER.h @@ -0,0 +1,143 @@ +#pragma once + +#include "vtvsub.h" + +class Joint; + +//########################################################################## +//################## Thruster::SubsystemResource ##################### +//########################################################################## + +struct Thruster__SubsystemResource: + public Subsystem::SubsystemResource +{ + int jointIndex; + Scalar maxThrusterRotationRate; + Logical primeThruster; +}; + +//########################################################################## +//################### Thruster::UpdateRecord #################### +//########################################################################## + +struct Thruster__UpdateRecord : + public VTVSubsystem::UpdateRecord +{ + Scalar + thrusterRotation; +}; + +//########################################################################## +//############################ Thruster ############################## +//########################################################################## + +class Thruster: + public Subsystem +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +#if 0 +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + ThrusterOffsetAttributeID = Subsystem::NextAttributeID, + ThrusterPositionAttributeID, + CurrentAccelerationAttributeID, + CurrentHeightAttributeID, + MaxThrusterRotationRateAttributeID, + MomentArmAttributeID, + MomentArmLengthAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + Point3D thrusterOffset; + Joint *thrusterPosition; + Scalar + currentAcceleration, + currentHeight, + maxThrusterRotationRate, + powerScale, + momentArmLength; + Vector3D + momentArm; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (Thruster::*Performance)(Scalar time_slice); + typedef Thruster__UpdateRecord UpdateRecord; + + void + PrimeThruster(Scalar time_slice); + void + SlaveThruster(Scalar time_slice); + void + PrimeDeadReckon(Scalar time_slice); + void + SlaveDeadReckon(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + VTV* + GetEntity() + {Check(this); return Cast_Object(VTV*, Subsystem::GetEntity());} + +protected: + void + WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + + Scalar + updatedPosition; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef Thruster__SubsystemResource SubsystemResource; + Thruster( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~Thruster(); + + Logical + TestInstance() const; +}; diff --git a/RP/VTV.cpp b/RP/VTV.cpp new file mode 100644 index 0000000..2d4eea9 --- /dev/null +++ b/RP/VTV.cpp @@ -0,0 +1,3199 @@ +#include "rp.h" +#pragma hdrstop + +#include "vtv.h" +#include "vtvmppr.h" +#include "vtvpwr.h" +#include "weapsys.h" +#include "thruster.h" +#include "booster.h" +#include "chute.h" +#include "rpplayer.h" +#include "..\munga\door.h" +#include "..\munga\line.h" +#include "..\munga\random.h" +#include "..\munga\fileutil.h" +#include "..\munga\boxsolid.h" +#include "..\munga\app.h" +#include "..\munga\hostmgr.h" +#include "..\munga\namelist.h" + +//############################################################################# +// Shared Data Support +// +Derivation* VTV::GetClassDerivations() +{ static Derivation classDerivations(JointedMover::GetClassDerivations(), "VTV"); + return &classDerivations; +} + + +VTV::SharedData + VTV::DefaultData( + VTV::GetClassDerivations(), + VTV::MessageHandlers, + VTV::GetAttributeIndex(), + VTV::StateCount, + (Entity::MakeHandler)VTV::Make + ); + +//############################################################################# +// Message Support +// +const VTV::HandlerEntry + VTV::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(VTV, TakeDamage), + MESSAGE_ENTRY(VTV, Kavorkian), + MESSAGE_ENTRY(VTV, MarkSpot), + MESSAGE_ENTRY(VTV, RestoreToSpot), + MESSAGE_ENTRY(VTV, ZoomIn), + MESSAGE_ENTRY(VTV, ZoomOut), + MESSAGE_ENTRY(VTV, PlayerLink) +}; + +VTV::MessageHandlerSet + VTV::MessageHandlers( + ELEMENTS(VTV::MessageHandlerEntries), + VTV::MessageHandlerEntries, + JointedMover::GetMessageHandlers() + ); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::PlayerLinkMessageHandler(PlayerLinkMessage *message) +{ + Entity::PlayerLinkMessageHandler(message); + RPPlayer + *rp_player = Cast_Object(RPPlayer*, playerLink); + rp_player->SetPlayerVehicle(this); + + // + //---------------------------------------------------------------------- + // If our player is a runner, add two boosters to each booster subsystem + //---------------------------------------------------------------------- + // + switch (rp_player->playerType) + { + case RPPlayer::RunnerPlayerType: + { + Check_Pointer(subsystemArray); + for (int i=0; iGetClassID() == BoosterClassID) + { + Booster *booster = (Booster*)subsystemArray[i]; + booster->maxBoosters += 2; + booster->boostersRemaining += 2; + } + } + } + } + goto Is_A_Scorer; + + case RPPlayer::GeneralPlayerType: + case RPPlayer::CrusherPlayerType: + case RPPlayer::BlockerPlayerType: +Is_A_Scorer: + rp_player->SetScoringPlayerFlag(); + break; + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::TakeDamageMessageHandler(TakeDamageMessage *message) +{ + Check(this); + Check(message); + + // + //------------------------------------------------- + // Check If the damage was caused by another Player + //------------------------------------------------- + // + Check(application); + HostManager + *host = application->GetHostManager(); + Check(host); + Entity + *offensive_entity = Cast_Object( + Entity*, + host->GetEntityPointer(message->inflictingEntity) + ); + + // + //------------------------------------ + // make sure we can enter something... + //------------------------------------ + // + if (offensive_entity) + { + Check(offensive_entity); + RPPlayer + *offensive_player = (RPPlayer*)offensive_entity->GetPlayerLink(); + + if (offensive_player) + { + // + //--------------------------------------------------------------- + // Notify this player that damaged was caused by offensive_player + //--------------------------------------------------------------- + // + Check(offensive_player); + RPPlayer::OffensivePlayer + *shooter = new RPPlayer::OffensivePlayer( + offensive_player, + message->damageData.damageType, + Now() + ); + Register_Object(shooter); + RPPlayer + *our_player = (RPPlayer*)GetPlayerLink(); + Check(our_player); + our_player->AddOffensivePlayer(*shooter); + } + } + + // + //-------------------------------------------------------------------- + // We we have received a collision packet, we should calculate our own + // damage loss + //-------------------------------------------------------------------- + // + switch (message->damageData.damageType) + { + case Damage::CollisionDamageType: + { + // + //----------------------------------------------------------- + // Find out who hit us, and get our velocity relative to them + //----------------------------------------------------------- + // + Check(application); + HostManager + *host = application->GetHostManager(); + Check(host); + Mover + *mover = (Mover*)host->GetEntityPointer(message->inflictingEntity); + Verify(mover->IsDerivedFrom(Mover::GetClassDerivations())); + Vector3D + v; + v.Subtract(worldLinearVelocity, mover->worldLinearVelocity); + + // + //----------------------------------------------------------------------- + // The normal to bounce against is passed via the damage force, so see if + // it opposes our motion. If not, we can ignore this message + //----------------------------------------------------------------------- + // + if (v*message->damageData.surfaceNormal <= 0.0f) + { + Check_Fpu(); + return; + } + + // + //---------------------------------------------------------------------- + // Otherwise, do a dynamic bounce, and apply the damage to ourselves. + // We save the original positions of the vehicles because we do not know + // what time slice to use + //---------------------------------------------------------------------- + // + Point3D + old_us = localOrigin.linearPosition, + old_them = mover->localOrigin.linearPosition; + Scalar + elasticity = elasticityCoefficient; + + message->damageData.surfaceNormal.x = + -message->damageData.surfaceNormal.x; + message->damageData.surfaceNormal.y = + -message->damageData.surfaceNormal.y; + message->damageData.surfaceNormal.z = + -message->damageData.surfaceNormal.z; + + message->damageData.damageAmount = + DynamicBounce( + mover, + 0.1f, + 1.0f, + message->damageData.surfaceNormal, + &elasticity + ); + localOrigin.linearPosition = old_us; + mover->localOrigin.linearPosition = old_them; + break; + } + + default: + { + message->damageData.damageForce /= moverMass; + Check_Fpu(); + worldLinearVelocity += message->damageData.damageForce; + break; + } + } + Entity::TakeDamageMessageHandler(message); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::KavorkianMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + Damage + damage; + + Check_Pointer(damageZones); + Check(*damageZones); + damage.damageType = Damage::ExplosiveDamageType; + damage.damageAmount = + 1.0f / (*damageZones)->damageScale[Damage::ExplosiveDamageType]; + Check_Fpu(); + damage.damageForce = Vector3D::Identity; + (*damageZones)->TakeDamage(damage); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::MarkSpotMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + savedOrigin = localOrigin; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::RestoreToSpotMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + Reset(savedOrigin, VTV::RegularReset); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::ZoomInMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + targetRangeExponent; + if (--targetRangeExponent < 0.0f) + { + targetRangeExponent = 0.0f; + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::ZoomOutMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + if (++targetRangeExponent > 5.0f) + { + targetRangeExponent = 5.0f; + } + } + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const VTV::IndexEntry + VTV::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(VTV, HeightAboveTerrain, heightAboveTerrain), + ATTRIBUTE_ENTRY(VTV, ThrusterPitch, thrusterPitch), + ATTRIBUTE_ENTRY(VTV, CollisionState, collisionState), + ATTRIBUTE_ENTRY(VTV, CollisionMaterialType, collisionMaterialType), + ATTRIBUTE_ENTRY(VTV, CollisionNormal, collisionNormal), + ATTRIBUTE_ENTRY(VTV, CollisionSpeed, collisionSpeed), + ATTRIBUTE_ENTRY(VTV, EyepointRotation, eyepointRotation), + ATTRIBUTE_ENTRY(VTV, BoosterOn, boosterOn), + ATTRIBUTE_ENTRY(VTV, BoosterScale, boosterScale), + ATTRIBUTE_ENTRY(VTV, BoosterSmokeDensity, boosterSmokeDensity), + ATTRIBUTE_ENTRY(VTV, ForwardVelocity, forwardVelocity), + ATTRIBUTE_ENTRY(VTV, CompassHeading, compassHeading), + ATTRIBUTE_ENTRY(VTV, TargetReticle, targetReticle), + ATTRIBUTE_ENTRY(VTV, NavigationRange, navigationRange), + ATTRIBUTE_ENTRY(VTV, NavigationLinearPosition,navigationLinearPosition), + ATTRIBUTE_ENTRY(VTV, NavigationAngularPosition,navigationAngularPosition), + ATTRIBUTE_ENTRY(VTV, ScoreState, scoreState), + ATTRIBUTE_ENTRY(VTV, ScoreType, scoreType), + ATTRIBUTE_ENTRY(VTV, HornBlast, hornBlast) // HACK - ECH 7/31/95 - For replicants +}; + +VTV::AttributeIndexSet& VTV::GetAttributeIndex() +{ + static VTV::AttributeIndexSet attributeIndex(ELEMENTS(VTV::AttributePointers), + VTV::AttributePointers, + JointedMover::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::SetMappingSubsystem(VTVControlsMapper *mapper) +{ + Check(this); + Check(mapper); + + Check_Pointer(subsystemArray); + if (subsystemArray[ControlsMapperSubsystem]) + { + Unregister_Object(subsystemArray[ControlsMapperSubsystem]); + delete subsystemArray[ControlsMapperSubsystem]; + } + subsystemArray[ControlsMapperSubsystem] = mapper; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTV::BoosterOn() +{ + Check(this); + for(int ii=BasicSubsystemCount;iiGetClassID() == BoosterClassID) + { + Booster + *booster = (Booster*) subsystem; + Check(booster); + if (booster->GetSimulationState() == Booster::BoosterBurning) + { + Check_Fpu(); + return True; + } + } + } + } + Check_Fpu(); + return False; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::MoveAndCollide(Scalar time_slice) +{ + Check(this); + JointSubsystem + *joint_subsystem = GetJointSubsystem(); + Check(joint_subsystem); + Verify(joint_subsystem->GetJointCount()); + + VTVControlsMapper + *mapper = Cast_Object( + VTVControlsMapper*, + GetSubsystem(VTV::ControlsMapperSubsystem) + ); + Check(mapper); + + // + //------------------------------------------------------------------------- + // Figure out the average height and thruster rotation. While doing this, + // calculate the differences in the corner forces so that we can figure out + // the roll and pitch accelerations due to terrain + //------------------------------------------------------------------------- + // + heightAboveTerrain = 0.0f; + thrusterPitch.rotationAmount = 0.0f; + Vector3D difference = Vector3D::Identity; + int valid_thruster=0; + + for (int i=0; icurrentHeight; + switch (joint_subsystem->GetJoint(valid_thruster)->GetJointType()) + { + + case Joint::BallJointType: + thrusterPitch.rotationAmount += + joint_subsystem->GetJoint(valid_thruster)-> + GetEulerAngles().pitch; + break; + case Joint::HingeXJointType: + thrusterPitch.rotationAmount += + joint_subsystem->GetJoint(valid_thruster)-> + GetHinge().rotationAmount; + break; + + } + ++valid_thruster; + + // + //---------------------------------------------------------------- + // Generate the pseudoforce. Ignore the center engines of the VTV + //---------------------------------------------------------------- + // + if ((i == 2 || i == 3) && joint_subsystem->GetJointCount() > 4) + { + continue; + } + if (thruster->thrusterOffset.x > 0.0f) + { + difference.z -= thruster->currentHeight; + } + else + { + difference.z += thruster->currentHeight; + } + if (thruster->thrusterOffset.z > 0.0f) + { + difference.x += thruster->currentHeight; + } + else + { + difference.x -= thruster->currentHeight; + } + } + } + heightAboveTerrain /= joint_subsystem->GetJointCount(); + thrusterPitch.rotationAmount /= joint_subsystem->GetJointCount(); + Check_Fpu(); + + // + //--------------------------------------------------- + // If we are not burning, follow the terrain and turn + //--------------------------------------------------- + // + if (GetSimulationState() != BurningState) + { + difference *= angularSpringFactor / (15.0f + 2.0f*heightAboveTerrain); + Check_Fpu(); + + // + //------------------------------------------------------------------- + // If this is a two-engine VTV, try to straighten out the pitch value + //------------------------------------------------------------------- + // + if (joint_subsystem->GetJointCount() == 2) + { + Scalar + len = + localToWorld(2,1)*localToWorld(2,1) + + localToWorld(1,1)*localToWorld(1,1); + if (!Small_Enough(len)) + { + difference.x = 3.0f*localToWorld(2,1) / Sqrt(len); + Check_Fpu(); + } + difference.z *= 0.5f; + } + else + { + difference *= 0.25f; + } + if (groundEffectDomainSquared) + { + difference.z -= bankFactor * mapper->powerDemand.x; + localAcceleration.angularMotion += difference; + + // + //------------------------------------- + // Stabilize the craft at high altitude + //------------------------------------- + // + if (heightAboveTerrain > 10.0f) + { + Vector3D + world_g = Vector3D::Identity, + local_g, + torque; + + world_g.y = -GetEnvironment()->gravityConstant; + local_g.MultiplyByInverse(world_g, localToWorld); + world_g.y = -1.0f; + torque.Cross(world_g, local_g); + torque *= momentOfInertia; + localAcceleration.angularMotion += torque; + } + } + + // + //--------------------------------------- + // Turn the VTV as required by the mapper + //--------------------------------------- + // + Vector3D + vel; + vel.Multiply(localVelocity.angularMotion, localToWorld); + Scalar + step = mapper->angularVelocityDemand.y - vel.y; + difference = Vector3D::Identity; + if (step > 0.0f) + { + if (maxAngularAcceleration.y * time_slice > step) + { + difference.y += step / time_slice; + Check_Fpu(); + } + else + { + difference.y += maxAngularAcceleration.y; + } + } + else if (step < 0.0f) + { + if (maxAngularAcceleration.y * time_slice > -step) + { + difference.y += step / time_slice; + Check_Fpu(); + } + else + { + difference.y -= maxAngularAcceleration.y; + } + } + + vel.MultiplyByInverse(difference,localToWorld); + localAcceleration.angularMotion += vel; + } + + // + //-------------------------------------------------------------------- + // Apply the standard air resistance and gravity, then project the VTV + // motion through the time slice + //-------------------------------------------------------------------- + // + ApplyAirResistanceAndGravity(); + + Vector3D + old_acceleration = worldLinearAcceleration; + + worldLinearAcceleration.x *= ZIPPY; + worldLinearAcceleration.z *= ZIPPY; + + Point3D + old_position(localOrigin.linearPosition); + ApplyWorldAccelerations(time_slice); + + // + //------------------------------------------------------------------------- + // We have now moved the VTV. We should now update our collision volume to + // the new location and check it against the tree + //------------------------------------------------------------------------- + // + Vector3D + zippy_accel = worldLinearAcceleration, + impact_velocity = localVelocity.linearMotion; + + worldLinearAcceleration = old_acceleration; + MoveCollisionVolume(); + + // + //------------------------------------------- + // If we are going fast enough, do a ray-cast + //------------------------------------------- + // + BoxedSolidCollisionList* collision_list = AllocateCollisionList(); + Line line; + line = old_position; + + Vector3D step; + step.Subtract(localOrigin.linearPosition, old_position); + if (step.LengthSquared() > SMALL) + { + line = step; + Scalar diameter = collisionTemplate->maxX - collisionTemplate->minX; + if (diameter < line.length) + { + CollideCenterOfMotion(&line, collision_list); + } + } + if (!collision_list->GetCollisionCount()) + { + GetCurrentCollisions(collision_list); + } + + // + //------------------------------- + // Process each of the collisions + //------------------------------- + // + collisionTemporaryState = NoCollisionState; + + Damage + collision_damage; + + ProcessCollisionList( + collision_list, + time_slice, + old_position, + &collision_damage + ); + + // + //------------------------- + // Set Collision attributes + //------------------------- + // + if (collision_damage.damageAmount > 0.0f) + { + BoxedSolid + *boxed_solid; + + Check(&(*lastCollisionList)[0]); + boxed_solid = (*lastCollisionList)[0].GetTreeVolume(); + Check(boxed_solid); + collisionMaterialType = boxed_solid->materialType; + + collisionNormal.MultiplyByInverse( + collision_damage.surfaceNormal, + localToWorld + ); + collisionSpeed = -(collisionNormal * impact_velocity); + + if (GetSimulationState() != BurningState) + { + collisionState.SetState(collisionTemporaryState); + } + + // + //--------------------------------------------------------------------- + // Take the damage, allowing any slope less than 45 degrees relative to + // the keel to take one-tenth the damage + //--------------------------------------------------------------------- + // + if (collisionNormal.y > 0.7f) + { + collision_damage.damageAmount *= bottomArmorScale; + } + + Check_Pointer(damageZones); + Check(*damageZones); + + //TODO: IMPORTANT COLLISION CODE HERE + + (*damageZones)->TakeDamage(collision_damage); + + // + //------------------------------------------------------------------ + // If the VTV is burning, apply the world-space force vectors to the + // craft as torque. The spinning will start next frame + //------------------------------------------------------------------ + // + if (GetSimulationState() == BurningState) + { + Vector3D + force, + torque; + Point3D + moment; + + force.MultiplyByInverse(collision_damage.damageForce, localToWorld); + moment.MultiplyByInverse( + (Vector3D)collision_damage.impactPoint, + localToWorld + ); + torque.Cross(moment, force); + torque *= momentOfInertia; + Clamp(torque.x, -20.0f, 20.0f); + Clamp(torque.y, -20.0f, 20.0f); + Clamp(torque.z, -20.0f, 20.0f); + localVelocity.angularMotion += torque; + } + } + else + { + collisionState.SetState(NoCollisionState); + } + + // + //------------------------------------------ + // Check to see if we should blow up the VTV + //------------------------------------------ + // + { + InterestManager + *interest_mgr = application->GetInterestManager(); + Check(interest_mgr); + InterestZone + *zone = interest_mgr->GetInterestZone(interestZoneID); + Check(zone); + BoundingBoxTree + *tree = zone->GetExistanceRoot(); + Check(tree); + Check_Pointer(damageZones); + Check(*damageZones); + insideWorld = + tree->FindBoundingBoxContaining(localOrigin.linearPosition) != NULL; + if (!insideWorld && (*damageZones)->damageLevel < 1.0f) + { + collision_damage.damageType = Damage::ExplosiveDamageType; + collision_damage.damageAmount = + 1.0f / (*damageZones)->damageScale[Damage::ExplosiveDamageType]; + Check_Fpu(); + collision_damage.damageForce = Vector3D::Identity; + Check_Pointer(damageZones); + Check(*damageZones); + (*damageZones)->TakeDamage(collision_damage); + + localVelocity.angularMotion.x += 8.0f * Random - 4.0f; + localVelocity.angularMotion.y += 8.0f * Random - 4.0f; + localVelocity.angularMotion.z += 8.0f * Random - 4.0f; + } + } + worldLinearAcceleration = zippy_accel; + if (collisionState.GetState() == RestState) + { + worldLinearAcceleration = Vector3D::Identity; + } + UpdateLocalMotion(); + + // + //------------------------------------------------- + // Update the stuff that the secondary screen wants + //------------------------------------------------- + // + compassHeading = localToWorld; + forwardVelocity = -3.6f * localVelocity.linearMotion.z; + if (targetRangeExponent > currentRangeExponent) + { + currentRangeExponent += time_slice; + if (currentRangeExponent > targetRangeExponent) + { + currentRangeExponent = targetRangeExponent; + } + navigationRange = 250.0f * pow(2.0f, currentRangeExponent); + } + else if (targetRangeExponent < currentRangeExponent) + { + currentRangeExponent -= time_slice; + if (currentRangeExponent < targetRangeExponent) + { + currentRangeExponent = targetRangeExponent; + } + navigationRange = 250.0f * pow(2.0f, currentRangeExponent); + } + Check_Fpu(); + + // + //------------------------------------------------------------------------ + // Run the dead reckoner, and then see how far apart the two positions are + //------------------------------------------------------------------------ + // + (this->*deadReckoner)(); + + Vector3D + error; + error.Subtract( + projectedOrigin.linearPosition, + localOrigin.linearPosition + ); + Quaternion + angular_deviation; + angular_deviation.Subtract( + projectedOrigin.angularPosition, + localOrigin.angularPosition + ); + if ( + error.LengthSquared() > 0.04f + || Abs(angular_deviation.w) < 0.997f + || collisionState.GetState() != collisionState.GetOldState() + || lastPerformance - lastUpdate > 2.0f + ) + { + ForceUpdate(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::PerformAndWatch( + const Time &till, + MemoryStream *update_stream + ) +{ + Check(this); + Check(&till); + + if (GetInstance() != ReplicantInstance) + { + boosterOn = False; + boosterScale = Vector3D::Identity; + boosterSmokeDensity = 0.0f; + } + JointedMover::PerformAndWatch(till, update_stream); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::WriteUpdateRecord(Simulation::UpdateRecord *message, int update_model) +{ + Check(this); + Check_Pointer(message); + + JointedMover::WriteUpdateRecord(message, update_model); + + UpdateRecord + *record = (UpdateRecord*)message; + + record->recordLength = sizeof(*record); + + record->collisionState = collisionState.GetState(); + record->collisionMaterialType = collisionMaterialType; + record->collisionNormal = collisionNormal; + record->collisionSpeed = collisionSpeed; + + record->boosterOn = boosterOn; + record->boosterScale = boosterScale; + record->boosterSmokeDensity = boosterSmokeDensity; + + record->hornBlast = hornBlast; // HACK - ECH 7/31/95 - For replicants + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::ReadUpdateRecord(Simulation::UpdateRecord *message) +{ + Check(this); + Check_Pointer(message); + + JointedMover::ReadUpdateRecord(message); + + UpdateRecord + *record = (UpdateRecord*)message; + + collisionState.SetState(record->collisionState); + collisionMaterialType = record->collisionMaterialType; + collisionNormal = record->collisionNormal; + collisionSpeed = record->collisionSpeed; + + boosterOn = record->boosterOn; + boosterScale = record->boosterScale; + boosterSmokeDensity = record->boosterSmokeDensity; + + hornBlast = record->hornBlast; // HACK - ECH 7/31/95 - For replicants + + if ( + GetSimulationState() == DefaultState + && simulationState.GetOldState() == BurningState + ) + { + localOrigin = updateOrigin; + + if (IsCollisionVolume()) + { + MoveCollisionVolume(); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ) +{ + Scalar + penetration, + r, + elasticity = elasticityCoefficient, + friction = frictionCoefficient, + added_damage = 0.0f; + Door + *door = NULL; + + // + //----------------------------------------------------------------------- + // Find out if we have hit a mover or something static. Moving collision + // volumes must have an owning entity + //----------------------------------------------------------------------- + // + BoxedSolid + *box = collision.GetTreeVolume(); + Check(box); + + Simulation + *sim = box->GetOwningSimulation(); + if (!sim) + { + goto Static_Bounce; + } + if (sim->IsDerivedFrom(*Mover::GetClassDerivations())) + { + Mover *mover = (Mover*)sim; + + // + //-------------------------------------------------------------------- + // If we hit a mover, make sure that the collision is valid, and if it + // is, calculate the energy_loss + //-------------------------------------------------------------------- + // + if ( + !collisionVolume->ProcessCollision( + collision, + worldLinearVelocity, + lastCollisionList, + &damage->surfaceNormal, + &penetration + ) + ) + { + Check_Fpu(); + return; + } + + // + //-------------------------------------------------------------- + // Make sure that we are not rearending somebody going faster... + //-------------------------------------------------------------- + // + Vector3D + rel_v; + rel_v.Subtract(worldLinearVelocity, mover->worldLinearVelocity); + if (rel_v * damage->surfaceNormal >= -SMALL) + { + Check_Fpu(); + return; + } + + // + //--------------------------------- + // Calculate the moving energy loss + //--------------------------------- + // + Max_Clamp(penetration, time_slice); + r = penetration / time_slice; + Check_Fpu(); + + damage->damageAmount = + DynamicBounce( + mover, + time_slice, + r, + damage->surfaceNormal, + &elasticity + ); + + // + //-------------------------------------------------------------------- + // If we hit another VTV, we will have to send it a damage message and + // enter it into the queue of guys what hit us in the last two seconds + //-------------------------------------------------------------------- + // + if (mover->GetClassID() == VTVClassID) + { + TakeDamageMessage + message( + TakeDamageMessageID, + sizeof(TakeDamageMessage), + GetEntityID(), + 0, + *damage + ); + mover->Dispatch(&message); + + RPPlayer + *offensive_player = (RPPlayer*)mover->GetPlayerLink(); + if (offensive_player) + { + Check(offensive_player); + RPPlayer::OffensivePlayer + *shooter = new RPPlayer::OffensivePlayer( + offensive_player, + message.damageData.damageType, + lastPerformance + ); + Register_Object(shooter); + RPPlayer + *our_player = (RPPlayer*)GetPlayerLink(); + Check(our_player); + our_player->AddOffensivePlayer(*shooter); + } + } + + // + //------------------------------------- + // Set up the collision state correctly + //------------------------------------- + // + goto Set_Collision_State; + } + + // + //-------------------------------------------------------------------------- + // If we hit a moving door, adjust our relative velocity to the door. If we + // get hit by both doors, CRUSH the vtv!!! + //-------------------------------------------------------------------------- + // + else if (sim->IsDerivedFrom(*Door::GetClassDerivations())) + { + door = (Door*)sim; + Check(door); + worldLinearVelocity += door->currentVelocity; + } + + //-------------------------------------------------------------------- + // If we really have a collision, do a static bounce off of the normal + // generated + //-------------------------------------------------------------------- + // +Static_Bounce: + if ( + collisionVolume->ProcessCollision( + collision, + worldLinearVelocity, + lastCollisionList, + &damage->surfaceNormal, + &penetration + ) + ) + { + Max_Clamp(penetration, time_slice); + r = penetration / time_slice; + Check_Fpu(); + + damage->damageAmount = + StaticBounce( + old_position, + time_slice, + r, + damage->surfaceNormal, + &elasticity, + minimumBounceSpeed, + &friction + ) + added_damage; + + // + //---------------------------------------- + // If we have hit a door, look for a crush + //---------------------------------------- + // + if (door) + { + if ( + lastPerformance - lastDoorHit < 0.1f + && doorHitNormal*damage->surfaceNormal < -0.7f + && damageZones[0]->damageLevel < 1.0f + ) + { + damageZones[0]->damageLevel = 1.0f; + } + doorHitNormal = damage->surfaceNormal; + lastDoorHit = lastPerformance; + } + + // + //-------------------------- + // Determine collision state + //-------------------------- + // +Set_Collision_State: + if (!elasticity) + { + if (!friction) + { + if (collisionTemporaryState == NoCollisionState) + { + collisionTemporaryState = RestState; + } + } + else if (collisionTemporaryState != InitialHitState) + { + collisionTemporaryState = SlideState; + } + } + else + { + collisionTemporaryState = InitialHitState; + } + } + + if (door) + { + worldLinearVelocity -= door->currentVelocity; + } + Check_Fpu(); +} + +//############################################################################# +// Scoring support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// HACK - ECH 7/6/95 - Allow the player vehicle to respond to score +// messages, allows attribute system to be used for scoring +// +void + VTV::RespondToScoreMessage(Message *message) +{ + Check(this); + Check(message); + + RPPlayer::ScoreMessage + *score_message = Cast_Object(RPPlayer::ScoreMessage*, message); + + // + // Set the score state and toggle the state to trigger the watchers + // + Check(score_message); + scoreType = score_message->scoreType; + Verify( + score_message->scoreType > RPPlayer::NullPointType && + score_message->scoreType < RPPlayer::PointTypeCount + ); + scoreState.SetState(score_message->scoreType); + scoreState.SetState(RPPlayer::NullPointType); + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTV::VTV( + VTV::MakeMessage *creation_message, + VTV::SharedData &virtual_data +): + JointedMover(creation_message, virtual_data), + collisionState(CollisionStateCount), + collisionNormal(0.0f, 0.0f, 1.0f), + scoreState(RPPlayer::PointTypeCount) +{ + SetValidFlag(); + + // + //------------------------ + // Setup the initial state + //------------------------ + // + Check(application); + Check(application->GetInterestManager()); + + InterestZone + *interest_zone = + application->GetInterestManager()->GetInterestZone(interestZoneID); + Check(interest_zone); + + localEnvironment = interest_zone->GetEnvironment(); + Check(localEnvironment); + + // + //---------------- + // Init attributes + //---------------- + // + collisionMaterialType = BoxedSolid::SteelMaterial; + // collisionNormal = Normal::Identity; // Fails TestInstance + collisionSpeed = 0.0f; + collisionState.SetState(NoCollisionState); + scoreState.SetState(RPPlayer::NullPointType); + scoreType = -1; + boosterOn = False; + boosterScale = Vector3D::Identity; + boosterSmokeDensity = 0.0f; + doorHitNormal = Vector3D::Identity; + lastDoorHit = Time::Null; + heightAboveTerrain = 0.0f; + forwardVelocity = 0.0f; + hornBlast = -1; + insideWorld = True; + thrusterAngle = 0.0f; + + // + //----------------------------- + // Set the correct motion model + //----------------------------- + // + BoxedSolid::Material + material; + + SetDeadReckoner(&VTV::AcceleratedDeadReckoner); + if (GetInstance() == ReplicantInstance) + { + SetPerformance(&VTV::DeadReckon); + material = BoxedSolid::OtherCraftMaterial; + } + else + { + SetPerformance(&VTV::MoveAndCollide); + material = BoxedSolid::OurCraftMaterial; + } + + // + //----------------------------- + // Initialize the VTV variables + //----------------------------- + // + ResourceFile + *res_file = application->GetResourceFile(); + ResourceDescription + *res = res_file->SearchList( + resourceID, + ResourceDescription::GameModelResourceType + ); + Check(res); + res->Lock(); + + ModelResource + *model_resource = (ModelResource*)res->resourceAddress; + Check_Pointer(model_resource); + + groundEffectDomainSquared = model_resource->groundEffectDomainSquared; + groundEffectRange = model_resource->groundEffectRange; + + maxAngularAcceleration = model_resource->maxAngularAcceleration; + maxYawVelocity = model_resource->maxYawVelocity; + angularSpringFactor = model_resource->angularSpringFactor; + bankFactor = model_resource->bankFactor; + maxImpactSpeed = model_resource->maxImpactSpeed; + bottomArmorScale = model_resource->bottomArmorScale; + + Scalar death_speed_km = model_resource->deathSpeed; + // + // Convert to Meters/Second + // + deathSpeed = death_speed_km/3.6f; + deathScoreLoss = model_resource->deathScoreLoss; + powerDive = model_resource->powerDive; + + res->Unlock(); + + deathConstant = (2000 * deathScoreLoss) / + ( + (1 - (elasticityCoefficient * elasticityCoefficient)) * + (deathSpeed * deathSpeed) * moverMass + ); + Check_Fpu(); + + thrusterPitch.rotationAmount = 0.0f; + thrusterPitch.axisNumber = X_Axis; + compassHeading = YawPitchRoll::Identity; + eyepointRotation = EulerAngles::Identity; + + navigationRange = 1000.0; // initial range = 1km + currentRangeExponent = 3.0f; + targetRangeExponent = 3.0f; + + Str_Copy(vehicleBadge, creation_message->vehicleBadge, sizeof(vehicleBadge)); + Str_Copy(vehicleColor, creation_message->vehicleColor, sizeof(vehicleColor)); + + // + //------------------------------------------------- + // Set up secondary display variables + // The indirection is required by the camera ship, + // but may be exploited for viewing the nav + // display at an arbitrary location, if desired. + //------------------------------------------------- + // If 'navigationLinearPosition' is NULL, it will + // extract the position from the entity directly. + // Not so for 'navigationAngularPosition': if it + // is NULL, the display will not 'turn' with the + // vehicle. It must be explicitly set if used. + //------------------------------------------------- + // + navigationLinearPosition = NULL; + navigationAngularPosition = &localOrigin.angularPosition; + // + //--------------------------------------------------- + // Make sure to correctly set the material of the VTV + //--------------------------------------------------- + // + collisionVolume->materialType = material; + + // + //------------------------------------------------------------------------ + // Setup the subsystems. The mapper subsystem will be left blank, so that + // the caller can hook in the appropriate mapper + //------------------------------------------------------------------------ + // + res = + application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::SubsystemModelStreamResourceType + ); + Check(res); + res->Lock(); + + Check_Pointer(res->resourceAddress); + MemoryStream + subsystems(res->resourceAddress, res->resourceSize); + + subsystemCount = *(int*)subsystems.GetPointer() + BasicSubsystemCount; + subsystems.AdvancePointer(sizeof(int)); + Verify(!subsystemArray); + subsystemArray = new (Subsystem (*[subsystemCount])); + Register_Pointer(subsystemArray); + + if (GetInstance() == ReplicantInstance) + { + VTVControlsMapper::SubsystemResource + control_subsystem_resource; + + Str_Copy( + control_subsystem_resource.subsystemName, + "ControlsMapper", + sizeof(control_subsystem_resource.subsystemName) + ); + control_subsystem_resource.classID = TrivialSubsystemClassID; + control_subsystem_resource.subsystemModelSize = + sizeof(control_subsystem_resource); + control_subsystem_resource.segmentIndex = -1; + control_subsystem_resource.subsystemFlags = DontExecuteFlag; + + subsystemArray[ControlsMapperSubsystem] = + new VTVControlsMapper( + this, + VTV::ControlsMapperSubsystem, + &control_subsystem_resource, + VTVControlsMapper::DefaultData + ); + Register_Object(subsystemArray[ControlsMapperSubsystem]); + } + else + { + subsystemArray[ControlsMapperSubsystem] = NULL; + } + + res->Unlock(); + // + //-------------------------------------------------------------------- + // Make the power subsystem. All VTVs have one in the designated slot + //-------------------------------------------------------------------- + // + VTVPower::SubsystemResource + power_subsystem_resource; + + Str_Copy( + power_subsystem_resource.subsystemName, + "Power", + sizeof(power_subsystem_resource.subsystemName) + ); + power_subsystem_resource.classID = TrivialSubsystemClassID; + power_subsystem_resource.subsystemModelSize = + sizeof(power_subsystem_resource); + power_subsystem_resource.maxAcceleration = model_resource->maxAcceleration; + power_subsystem_resource.segmentIndex = -1; + power_subsystem_resource.subsystemFlags = 0; + + + subsystemArray[PowerSubsystem] = + new VTVPower(this, PowerSubsystem, &power_subsystem_resource); + Register_Object(subsystemArray[PowerSubsystem]); + + // + //--------------------------------------------------------------- + // Make the thruster subsystems. We can handle up to 6 thrusters + //--------------------------------------------------------------- + // + Thruster::SubsystemResource + thruster_subsystem_resource; + + Str_Copy( + thruster_subsystem_resource.subsystemName, + "Thruster?", + sizeof(thruster_subsystem_resource.subsystemName) + ); + thruster_subsystem_resource.classID = TrivialSubsystemClassID; + thruster_subsystem_resource.subsystemModelSize = + sizeof(thruster_subsystem_resource); + thruster_subsystem_resource.subsystemFlags = 0; + thruster_subsystem_resource.primeThruster = True; + + // + // Initialize the thruster subsystems from the jointSubystem + // Information + // + + #if DEBUG_LEVEL>0 + JointSubsystem + *joint_subsystem = GetJointSubsystem(); + Check(joint_subsystem); + Verify(joint_subsystem->GetJointCount() <= MAX_THRUSTERS); + #endif + + int i; + for (i=0; ijointIndex[i] == -1 + || model_resource->segmentIndex[i] == -1 + ) + { + subsystemArray[Thruster1Subsystem + i] = NULL; + continue; + } + // + // Append thruster number to subsystem name + // + thruster_subsystem_resource.subsystemName[8] = (char)(i + '0'); + + // + // assign joint and segment Indicies + // + thruster_subsystem_resource.jointIndex = + model_resource->jointIndex[i]; + thruster_subsystem_resource.segmentIndex = + model_resource->segmentIndex[i]; + + // + // Get maxThrusterRotation Rate + // + thruster_subsystem_resource.maxThrusterRotationRate = + model_resource->maxThrusterRotationRate; + + // + // Construct the thruster Subsystem + // + subsystemArray[Thruster1Subsystem + i] = + new Thruster( + this, + Thruster1Subsystem+i, + &thruster_subsystem_resource); + + Register_Object(subsystemArray[Thruster1Subsystem + i]); + thruster_subsystem_resource.primeThruster = False; + } + + // + // Add the JointSubsystem to the subsystemArray + // + subsystemArray[JointSubsystemID] = GetJointSubsystem(); + + // + //--------------------------------------------------- + // Read and process the subsystem array specification + //--------------------------------------------------- + // + for (i=BasicSubsystemCount; isubsystemFlags & Subsystem::DontReplicateFlag) + || GetInstance() != ReplicantInstance + ) + { + switch (subsystem_resource->classID) + { + case RegisteredClass::BoosterClassID: + subsystemArray[i] = + new Booster( + this, + i, + (Booster::SubsystemResource*)subsystem_resource + ); + break; + case RegisteredClass::ChuteClassID: + subsystemArray[i] = + new Chute(this, i, (Chute::SubsystemResource*)subsystem_resource); + break; + case RegisteredClass::RivetGunClassID: + subsystemArray[i] = + new RivetGun(this, i, (RivetGun::SubsystemResource*)subsystem_resource); + break; + case RegisteredClass::LaserDrillClassID: + subsystemArray[i] = + new LaserGun(this, i, (LaserGun::SubsystemResource*)subsystem_resource); + break; + case RegisteredClass::DemolitionPackDropperClassID: + subsystemArray[i] = + new DemolitionPackDropper( + this, + i, + (DemolitionPackDropper::SubsystemResource*)subsystem_resource); + break; + } + Register_Object(subsystemArray[i]); + } + else + { + subsystemArray[i] = NULL; + } + subsystems.AdvancePointer(subsystem_resource->subsystemModelSize); + } + + // + // Read In DamageZones and Create DamageZoneID's + // + + ResourceDescription + *dmg_res = application->GetResourceFile()->SearchList( + resourceID, + ResourceDescription::DamageZoneStreamResourceType + ); + Check(dmg_res); + dmg_res->Lock(); + + DynamicMemoryStream + damage_zone_stream( + dmg_res->resourceAddress, + dmg_res->resourceSize + ); + // + //------------------------------------- + // skip over damageZoneCount in Stream + //------------------------------------- + // + damage_zone_stream.AdvancePointer(sizeof(damageZoneCount)); + // + // Allocate damageZones Array + // + for(int ii=0;iiUnlock(); + // + //-------------------- + // Init the reticle + //-------------------- + // + targetReticle.reticlePosition = model_resource->reticleResource.reticlePosition; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTV::~VTV() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::Reset(const Origin& new_origin, int reset_command) +{ + Check(this); + Check(&new_origin); + + localOrigin = new_origin; + localVelocity = Motion::Identity; + localAcceleration = Motion::Identity; + worldLinearVelocity = Vector3D::Identity; + worldLinearAcceleration = Vector3D::Identity; + localToWorld = localOrigin; + SetSimulationState(VTV::DefaultState); + damageZones[0]->damageLevel = 0.0f; + collisionState.SetState(NoCollisionState); + boosterOn = False; + boosterScale = Vector3D::Identity; + boosterSmokeDensity = 0.0f; + + // + //------------------------- + // Reset subsystems + //------------------------- + // + for(int ii=BasicSubsystemCount;iiDeathReset(reset_command); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTV::DeathShutdown(int shutdown_command) +{ + // + //------------------------- + // Shutdown subsystems + //------------------------- + // + for(int ii=BasicSubsystemCount;iiDeathShutdown(shutdown_command); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + VTV::CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource *model + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //----------------------------------------------------------------------- + // If we were not provided a buffer to write the model data into, we must + // create it ourselves. Then make sure that the model stuff is read in + //----------------------------------------------------------------------- + // + ModelResource + *local_model = model; + if (!local_model) + { + local_model = new ModelResource; + Register_Pointer(local_model); + } + if ( + JointedMover::CreateModelResource( + resource_file, + model_name, + model_file, + directories, + local_model + ) == -1 + ) + { +Dump_And_Die: + if (!model) + { + Unregister_Pointer(local_model); + delete local_model; + } + Check_Fpu(); + return -1; + } + if ( + Reticle::CreateModelResource( + resource_file, + model_name, + model_file, + directories, + &local_model->reticleResource + ) == -1 + ) + { + goto Dump_And_Die; + } + // + //----------------------------- + // Read in the max acceleration + //----------------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "MaxAcceleration", + &local_model->maxAcceleration + ) + ) + { + DEBUG_STREAM << model_name << " missing MaxAcceleration!\n" << std::flush; + goto Dump_And_Die; + } + if ( + !model_file->GetEntry( + "gamedata", + "MaxImpactSpeed", + &local_model->maxImpactSpeed + ) + ) + { + DEBUG_STREAM << model_name << " missing MaxImpactSpeed!\n" << std::flush; + goto Dump_And_Die; + } + + // + //------------------------- + // Read in the bottom armor + //------------------------- + // + local_model->bottomArmorScale = 0.1f; + model_file->GetEntry( + "gamedata", + "BottomArmorScale", + &local_model->bottomArmorScale + ); + + // + //------------------------- + // Read in the bottom armor + //------------------------- + // + local_model->powerDive = 0.0f; + model_file->GetEntry( + "gamedata", + "PowerDive", + &local_model->powerDive + ); + if (local_model->powerDive > 0.0 || local_model->powerDive < -1.0f) + { + DEBUG_STREAM << model_name << " has an invalid powerDive!\n" << std::flush; + goto Dump_And_Die; + } + + // + //----------------------------------- + // Read in the thruster rotation rate + //----------------------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "MaxThrusterRotationRate", + &local_model->maxThrusterRotationRate + ) + ) + { + DEBUG_STREAM << model_name << " missing MaxThrusterRotationRate!\n" << std::flush; + goto Dump_And_Die; + } + + // + //-------------------------------- + // Read in the ground effect stuff + //-------------------------------- + // + if ( + !model_file->GetEntry( + "gamedata", + "GroundEffectDomainSquared", + &local_model->groundEffectDomainSquared + ) + ) + { + DEBUG_STREAM << model_name << " missing GroundEffectDomainSquared!\n" << std::flush; + goto Dump_And_Die; + } + + if ( + !model_file->GetEntry( + "gamedata", + "GroundEffectRange", + &local_model->groundEffectRange + ) + ) + { + DEBUG_STREAM << model_name << " missing GroundEffectRange!\n" << std::flush; + goto Dump_And_Die; + } + + + // + //---------------------------------------- + // Read in the angular acceleration limits + //---------------------------------------- + // + const char *entry; + if ( + !model_file->GetEntry( + "gamedata", + "MaxAngularAcceleration", + &entry + ) + ) + { + DEBUG_STREAM << model_name << " missing MaxAngularAcceleration!\n" << std::flush; + goto Dump_And_Die; + } + sscanf( + entry, + "%f %f %f", + &local_model->maxAngularAcceleration.x, + &local_model->maxAngularAcceleration.y, + &local_model->maxAngularAcceleration.z + ); + + if ( + !model_file->GetEntry( + "gamedata", + "AngularSpringFactor", + &local_model->angularSpringFactor + ) + ) + { + DEBUG_STREAM << model_name << " missing AngularSpringFactor!\n" << std::flush; + goto Dump_And_Die; + } + if ( + !model_file->GetEntry( + "gamedata", + "DeathSpeed", + &local_model->deathSpeed + ) + ) + { + DEBUG_STREAM << model_name << " missing DeathSpeed!\n" << std::flush; + goto Dump_And_Die; + } + if ( + !model_file->GetEntry( + "gamedata", + "DeathScoreLoss", + &local_model->deathScoreLoss + ) + ) + { + DEBUG_STREAM << model_name << " missing DeathScoreLoss!\n" << std::flush; + goto Dump_And_Die; + } + if ( + !model_file->GetEntry( + "gamedata", + "ElasticityCoefficient", + &local_model->elasticityCoefficient + ) + ) + { + DEBUG_STREAM << model_name << " missing ElasticityCoefficient!\n" << std::flush; + goto Dump_And_Die; + } + if ( + !model_file->GetEntry( + "gamedata", + "MaxYawVelocity", + &local_model->maxYawVelocity + ) + ) + { + DEBUG_STREAM << model_name << " missing MaxYawVelocity!\n" << std::flush; + goto Dump_And_Die; + } + local_model->maxYawVelocity *= RAD_PER_DEG; + + if ( + !model_file->GetEntry( + "gamedata", + "BankFactor", + &local_model->bankFactor + ) + ) + { + DEBUG_STREAM << model_name << " missing BankFactor!\n" << std::flush; + goto Dump_And_Die; + } + + // + // Read in Segment and Joint information from the .skl file + // for the thrusters + // + //------------------- + // Find the .skl file + //------------------- + // + const char + *skl_entry; + if ( + !model_file->GetEntry( + "video", + "skeleton", + &skl_entry + ) + ) + { + DEBUG_STREAM << model_name << " is missing .skl file specification!\n" << std::flush; + return -1; + } + char + *skl_filename = + MakePathedFilename(directories->videoDirectory, skl_entry); + Register_Pointer(skl_filename); + + NotationFile + *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!\n" << std::flush; +Dump_And_Die_1: + Unregister_Pointer(skl_filename); + delete[] skl_filename; + Unregister_Object(skl_file); + delete skl_file; + Check_Fpu(); + return ResourceDescription::NullResourceID; + } + + // + // Make a pagelist of all the segments + // + NameList + *segment_pages = skl_file->MakePageList(); + Register_Object(segment_pages); + + NameList::Entry + *segment_entry = segment_pages->GetFirstEntry(); + int segment_count=0; + int joint_count=0; + // + // Initialize the thruster Model Resource info to No Thruster! + // + for(int ii=0;iijointIndex[ii] = -1; + local_model->segmentIndex[ii] = -1; + } + + while(segment_entry) + { + char entry[32]; + Str_Copy(entry, segment_entry->GetName(), sizeof(entry)); + // + // + // Skip LAB_ONLY and Damage_Zones + if( + (strcmp(entry, "LAB_ONLY") == 0) || + (strcmp(entry,"DamageZones") ==0) + ) + { + segment_entry = segment_entry->GetNextEntry(); + continue; + } + if (strncmp(entry,"joint",5)==0) + { + if (!stricmp(entry,"jointrfeng")) + { + local_model->jointIndex[0] = joint_count; + local_model->segmentIndex[0] = segment_count; + } + else if (!stricmp(entry,"jointlfeng")) + { + local_model->jointIndex[1] = joint_count; + local_model->segmentIndex[1] = segment_count; + } + else if (!stricmp(entry,"jointreng") || !stricmp(entry,"jointrmeng")) + { + local_model->jointIndex[2] = joint_count; + local_model->segmentIndex[2] = segment_count; + } + else if (!stricmp(entry,"jointleng") || !stricmp(entry,"jointlmeng")) + { + local_model->jointIndex[3] = joint_count; + local_model->segmentIndex[3] = segment_count; + } + else if (!strcmp(entry,"jointrbeng")) + { + local_model->jointIndex[4] = joint_count; + local_model->segmentIndex[4] = segment_count; + } + else if (!strcmp(entry,"jointlbeng")) + { + local_model->jointIndex[5] = joint_count; + local_model->segmentIndex[5] = segment_count; + } + + ++joint_count; + } + ++segment_count; + segment_entry = segment_entry->GetNextEntry(); + } + + // + //------------------------------------------------------------------------- + // If we created the model buffer, then we have the responsibility to write + // it out to the resource file + //------------------------------------------------------------------------- + // + if (!model) + { + ResourceDescription + *new_res = resource_file->AddResource( + model_name, + ResourceDescription::GameModelResourceType, + 1, + ResourceDescription::Preload, + local_model, + sizeof(*local_model) + ); + Unregister_Pointer(local_model); + delete local_model; + Unregister_Pointer(skl_filename); + delete skl_filename; + Unregister_Object(skl_file); + delete skl_file; + Unregister_Object(segment_pages); + delete segment_pages; + + Check(new_res); + Check_Fpu(); + return new_res->resourceID; + } + else + { + Unregister_Pointer(local_model); + delete local_model; + Unregister_Pointer(skl_filename); + delete skl_filename; + Unregister_Object(skl_file); + delete skl_file; + Unregister_Object(segment_pages); + delete segment_pages; + + Check_Fpu(); + return 0; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + VTV::CreateSubsystemStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .sub file + //------------------- + // + const char + *entry_data; + if ( + !model_file->GetEntry( + "gamedata", + "Subsystems", + &entry_data + ) + ) + { + DEBUG_STREAM << model_name << " is missing .sub file specification!\n" << std::flush; + Check_Fpu(); + return -1; + } + + char + *filename = MakePathedFilename(directories->modelDirectory, entry_data); + Register_Pointer(filename); + + NotationFile + *sys_file = new NotationFile(filename); + Register_Object(sys_file); + if (!sys_file->PageCount()) + { + DEBUG_STREAM << filename << " cannot be found!\n" << std::flush; + Unregister_Pointer(filename); + delete filename; + Unregister_Object(sys_file); + delete sys_file; + Check_Fpu(); + return -1; + } + + // + //------------------------------------------------------- + // Figure out how many subsystems will have to be created + //------------------------------------------------------- + // + NameList + *namelist = sys_file->MakePageList(); + Register_Object(namelist); + NameList::Entry + *entry = namelist->GetFirstEntry(); + + int + count = 0; + while (entry) + { + ++count; + entry = entry->GetNextEntry(); + } + + // + //--------------------------------------------------------------------- + // Step through each of the pages, and create an entry in the subsystem + // stream + //--------------------------------------------------------------------- + // + int + *subsystems = new int[sizeof(RivetGun::SubsystemResource)*count]; + Register_Pointer(subsystems); + + MemoryStream + stream(subsystems,sizeof(RivetGun::SubsystemResource)*count*sizeof(int)); + + *(int*)stream.GetPointer() = count; + stream.AdvancePointer(sizeof(int)); + + entry = namelist->GetFirstEntry(); + while (entry) + { + const char + *subsystem_name = entry->GetName(), + *type; + if ( + !sys_file->GetEntry( + subsystem_name, + "Type", + &type + ) + ) + { + DEBUG_STREAM << model_name << ':' << + subsystem_name << " missing Type!\n" << std::flush; +Dump_And_Die: + Unregister_Pointer(subsystems); + delete[] subsystems; + Unregister_Object(namelist); + delete namelist; + Unregister_Pointer(filename); + delete filename; + Unregister_Object(sys_file); + delete sys_file; + return -1; + } + + Subsystem::SubsystemResource + *subsystem_resource = + (Subsystem::SubsystemResource*)stream.GetPointer(); + if (!strcmp(type, "BoosterClassID")) + { + if ( + Booster::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + (Booster::SubsystemResource*)subsystem_resource, + sys_file, + directories + ) == -1 + ) + { + goto Dump_And_Die; + } + } + else + if (!strcmp(type, "ChuteClassID")) + { + if ( + Chute::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + (Chute::SubsystemResource*)subsystem_resource, + sys_file, + directories + ) == -1 + ) + { + goto Dump_And_Die; + } + } + else if (!strcmp(type, "RivetGunClassID")) + { + if ( + RivetGun::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + (RivetGun::SubsystemResource*)subsystem_resource, + sys_file, + resource_file, + directories + ) == -1 + ) + { + goto Dump_And_Die; + } + } + else if (!strcmp(type, "DemolitionPackDropperClassID")) + { + if ( + DemolitionPackDropper::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + (DemolitionPackDropper::SubsystemResource*)subsystem_resource, + sys_file, + resource_file, + directories + ) == -1 + ) + { + goto Dump_And_Die; + } + } + else if (!strcmp(type, "LaserDrillClassID")) + { + if ( + LaserGun::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + (LaserGun::SubsystemResource*)subsystem_resource, + sys_file, + resource_file, + directories + ) == -1 + ) + { + goto Dump_And_Die; + } + } + else + { + DEBUG_STREAM << model_name << ':' << subsystem_name + << " has an unknown component type of " << type << std::endl << std::flush; + goto Dump_And_Die; + } + + stream.AdvancePointer(subsystem_resource->subsystemModelSize); + entry = entry->GetNextEntry(); + } + + // + //-------------------------------------------------------------------- + // Write the stream out to disk. Size is equal to the byte difference + // between stream and subsystems + //-------------------------------------------------------------------- + // + ResourceDescription + *new_res = resource_file->AddResource( + model_name, + ResourceDescription::SubsystemModelStreamResourceType, + 1, + ResourceDescription::Preload, + subsystems, + (char*)stream.GetPointer() - (char*)subsystems + ); + Check(new_res); + + // + //------------------------- + // Clean up after ourselves + //------------------------- + // + Unregister_Pointer(subsystems); + delete[] subsystems; + Unregister_Object(namelist); + delete namelist; + Unregister_Pointer(filename); + delete filename; + Unregister_Object(sys_file); + delete sys_file; + Check_Fpu(); + return new_res->resourceID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Simulation::SharedData* + VTV::GetSubsystemSharedData(const char *name) +{ + Check_Pointer(name); + + Check_Fpu(); + if (!strcmp(name, "")) + { + return &VTV::DefaultData; + } + else if (!strcmp(name, "BoosterClassID")) + { + return &Booster::DefaultData; + } + else if (!strcmp(name, "ChuteClassID")) + { + return &Chute::DefaultData; + } + else if (!strcmp(name, "Power")) + { + return &VTVPower::DefaultData; + } + else if (!strcmp(name, "ControlsMapper")) + { + return &VTVControlsMapper::DefaultData; + } + else if (!strcmp(name, "RivetGunClassID")) + { + return &RivetGun::DefaultData; + } + else if (!strcmp(name, "LaserDrillClassID")) + { + return &LaserGun::DefaultData; + } + else if (!strcmp(name, "DemolitionPackDropperClassID")) + { + return &DemolitionPackDropper::DefaultData; + } + else + { + return NULL; + } +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +ResourceDescription::ResourceID + VTV::CreateControlMappingStream( + const char* mapping_name, + NotationFile *mapping_file, + FindNameFunction find_name, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + ) +{ + Check(mapping_file); + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + NameList + *namelist = mapping_file->MakePageList(); + Register_Object(namelist); + + NameList::Entry + *entry = namelist->GetFirstEntry(); + int + count=mapping_file->PageCount(); + + if (!count) + { + DEBUG_STREAM << model_name << " is missing control mappings!\n" << std::flush; +Unwind_1: + Unregister_Object(namelist); + delete namelist; + Check_Fpu(); + return -1; + } + + int + *stream = (int*)new ControlsMapping[(count+1)*6]; + Register_Pointer(stream); + int + *mappings = stream; + *mappings++ = count; + int + real_count = 0; + + // + //---------------------------------- + // For each page, create one mapping + //---------------------------------- + // + for (int i=0; iGetName(); + if ( + !mapping_file->GetEntry( + page_name, + "IOMapping", + &control_name + ) + ) + { + DEBUG_STREAM << model_name << ':' << page_name + << " has no IOMapping !\n" << std::flush; +Unwind_2: + Unregister_Pointer(stream); + delete stream; + goto Unwind_1; + } + if (!(*find_name)(control_name, mapping)) + { + DEBUG_STREAM << model_name << ':' << control_name + << " does not exist!\n" << std::flush; + goto Unwind_2; + } + + // + //-------------------------------------------------------- + // Now, find the right subsystem to attach this control to + //-------------------------------------------------------- + // + const char + *subsystem_name; + mapping->subsystemID = Entity::EntitySubsystemID; + char + subsystem_type[80]; + *subsystem_type = '\0'; + if ( + mapping_file->GetEntry( + page_name, + "Subsystem", + &subsystem_name + ) + ) + { + // + //-------------------------------------------------- + // See if this is one of the always there subsystems + //-------------------------------------------------- + // + if (!strcmp(subsystem_name, "ControlsMapper")) + { + mapping->subsystemID = ControlsMapperSubsystem; + Str_Copy(subsystem_type, subsystem_name, sizeof(subsystem_type)); + } + else if (!strcmp(subsystem_name, "Power")) + { + mapping->subsystemID = PowerSubsystem; + Str_Copy(subsystem_type, subsystem_name, sizeof(subsystem_type)); + } + else if (!strncmp(subsystem_name, "Thruster", 8)) + { + mapping->subsystemID = + Thruster1Subsystem + (subsystem_name[8] - '0'); + Str_Copy(subsystem_type, subsystem_name, sizeof(subsystem_type)); + } + + // + //-------------------------------------------------------------- + // Otherwise, we have to open up the subsystem file and find the + // matching page, keeping track of the count + //-------------------------------------------------------------- + // + else + { + const char + *entry_data; + model_file->GetEntry("gamedata", "Subsystems", &entry_data); + + char + *filename = + MakePathedFilename(directories->modelDirectory, entry_data); + Register_Pointer(filename); + + NotationFile + *sys_file = new NotationFile( + filename, + NotationFile::CleanListMode|NotationFile::IgnoreCaseMode + ); + Register_Object(sys_file); + + NameList + *sublist = sys_file->MakePageList(); + Register_Object(sublist); + + NameList::Entry + *subsystem_entry = sublist->GetFirstEntry(); + + // + //----------------------------------------------------------------- + // Look through all the pages of the subsystem file, looking for + // our subsystem. When we find it, remember what number it was and + // what type it was + //----------------------------------------------------------------- + // + mapping->subsystemID = BasicSubsystemCount; + while (subsystem_entry) + { + if (!strcmp(subsystem_entry->GetName(), subsystem_name)) + { + if (!sys_file->GetEntry(subsystem_name, "Type", &entry_data)) + { + DEBUG_STREAM << + model_name << ':' << subsystem_name << + " does not have a 'Type' in file '" << + filename << "'!\n" << std::flush; + } + Str_Copy(subsystem_type, entry_data, sizeof(subsystem_type)); + subsystem_name = entry_data; + break; + } + subsystem_entry = subsystem_entry->GetNextEntry(); + ++mapping->subsystemID; + } + + Unregister_Pointer(filename); + delete filename; + + if (!subsystem_entry) + { + DEBUG_STREAM << model_name << ":subsystem '" << subsystem_name + << "' does not exist!\n" << std::flush; + Unregister_Object(sys_file); + delete sys_file; + + Unregister_Object(sublist); + delete sublist; + + Unregister_Pointer(stream); + delete[] stream; + goto Unwind_1; + } + Unregister_Object(sys_file); + delete sys_file; + + Unregister_Object(sublist); + delete sublist; + } + } + + // + //-------------------------- + // Find the Mode to use + //-------------------------- + // + const char + *entry_string; + if ( + !mapping_file->GetEntry( + page_name, + "Mode", + &entry_string + ) + ) + { + DEBUG_STREAM << + model_name << ':' << page_name << " is missing Mode!\n" << std::flush; +Unwind_3: + Unregister_Pointer(stream); + delete[] stream; + goto Unwind_1; + } + + CString + match_filter_string = entry_string, + mode_string, + null_string = NULL; + + ModeMask + mode_mask; + + mapping->modeMask = (ModeMask) 0; + { + int + i; + + for( + i=0; + (mode_string=match_filter_string.GetNthToken(i)) != null_string; + ++i + ) + { + Logical + result = current_tool->ConvertStringToModeMask( + mode_string, + &mode_mask + ); + + if (result == False) + { + DEBUG_STREAM << + model_name << ':' << + page_name << " has an unsupported Mode type '" << + mode_string << "'\n" << std::flush; + goto Unwind_3; + } + + mapping->modeMask |= mode_mask; + } + + if (i == 0) + { + DEBUG_STREAM << + model_name << ':' << + page_name << " has no Mode specified!\n" << std::flush; + goto Unwind_3; + } + } + // + //------------------------------------ + // Find the type of connection to make + //------------------------------------ + // + const char + *type; + if ( + !mapping_file->GetEntry( + page_name, + "Type", + &type + ) + ) + { + DEBUG_STREAM << + model_name << ':' << + page_name << " is missing type!\n" << std::flush; + goto Unwind_3; + } + + Simulation::SharedData + *shared_data = GetSubsystemSharedData(subsystem_type); + if (!shared_data) + { + DEBUG_STREAM << + model_name << ':' << + subsystem_name << " is an unsupported subsystem!\n" << std::flush; + goto Unwind_3; + } + + // + //---------------------------------------------------------------------- + // If this is an event mapping, we have to have a message ID. + //---------------------------------------------------------------------- + // + if (!strcmp(type, "EventMapping")) + { + mapping->mappingType = ControlsMapping::EventMapping; + const char* message; + if ( + !mapping_file->GetEntry( + page_name, + "MessageID", + &message + ) + ) + { + DEBUG_STREAM << + model_name << ':' << + page_name << " is missing MessageID!\n" << std::flush; + goto Unwind_3; + } + const Receiver::HandlerEntry + *entry = shared_data->activeMessageHandlers->Find(message); + if (!entry) + { + DEBUG_STREAM << + model_name << ':' << + subsystem_name << ':' << + message << " is an unsupported messageID!\n" << std::flush; + goto Unwind_3; + } + mapping->messageID = entry->entryID; + } + + // + //---------------------------------------------------------------------- + // If this is a direct mapping, we have to have an attribute ID. How do + // we find an unknown attribute of an unknown subsystem? + //---------------------------------------------------------------------- + // + else if (!strcmp(type, "DirectMapping")) + { + mapping->mappingType = ControlsMapping::DirectMapping; + const char + *attribute; + if ( + !mapping_file->GetEntry( + page_name, + "AttributeID", + &attribute + ) + ) + { + DEBUG_STREAM << + model_name << ':' << + page_name << " is missing AttributeID!\n" << std::flush; + goto Unwind_3; + } + const Simulation::IndexEntry + *entry = shared_data->activeAttributeIndex->FindEntry(attribute); + if (!entry) + { + DEBUG_STREAM << + model_name << ':' << + subsystem_name << ':' << + attribute << " is an unsupported AttributeID!\n" << std::flush; + goto Unwind_3; + } + mapping->attributeID = entry->entryID; + } + else + { + DEBUG_STREAM << + model_name << ':' << + page_name << " has unknown mapping type!\n" << std::flush; + goto Unwind_3; + } + + mappings = (int*)((char*)mappings + sizeof(ControlsMapping)); + ++real_count; + + // + //------------------------- + // Move to the next mapping + //------------------------- + // + entry = entry->GetNextEntry(); + } + + // + //-------------------------------------------------------------------- + // Write the stream out to disk. Size is equal to the byte difference + // between stream and subsystems + //-------------------------------------------------------------------- + // + *stream = real_count; + ResourceDescription + *new_res = resource_file->AddResource( + mapping_name, + ResourceDescription::ControlMappingStreamResourceType, + 1, + ResourceDescription::Preload, + stream, + (char*)mappings - (char*)stream + ); + Check(new_res); + + // + //------------------------- + // Clean up after ourselves + //------------------------- + // + Unregister_Pointer(stream); + delete[] stream; + Unregister_Object(namelist); + delete namelist; + Check_Fpu(); + return new_res->resourceID; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTV* + VTV::Make(VTV::MakeMessage *creation_message) +{ + Check_Fpu(); + return new VTV(creation_message); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +ResourceDescription::ResourceID + VTV::CreateDamageZoneStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ) +{ + Check(resource_file); + Check_Pointer(model_name); + Check(model_file); + Check_Pointer(directories); + + // + //------------------- + // Find the .skl file + //------------------- + // + const char + *skl_entry; + if ( + !model_file->GetEntry( + "video", + "skeleton", + &skl_entry + ) + ) + { + DEBUG_STREAM << model_name << " is missing .skl file specification!\n" << std::flush; + Check_Fpu(); + return -1; + } + char + *skl_filename = + MakePathedFilename(directories->videoDirectory, skl_entry); + Register_Pointer(skl_filename); + + NotationFile + *skl_file = new NotationFile(skl_filename); + Register_Object(skl_file); + + if (!skl_file->PageCount()) + { + DEBUG_STREAM << skl_filename << " is empty or missing!\n" << std::flush; +Dump_And_Die_1: + Unregister_Pointer(skl_filename); + delete[] skl_filename; + Unregister_Object(skl_file); + delete skl_file; + Check_Fpu(); + return ResourceDescription::NullResourceID; + } + + // + //------------------- + // Find the .dmg file + //------------------- + // + const char + *dmg_entry; + if ( + !model_file->GetEntry( + "gamedata", + "DamageZones", + &dmg_entry + ) + ) + { + DEBUG_STREAM << model_name << " is missing .dmg file specification!\n" << std::flush; + goto Dump_And_Die_1; + } + + char + *dmg_filename = + MakePathedFilename(directories->modelDirectory, dmg_entry); + Register_Pointer(dmg_filename); + + NotationFile + *dmg_file = new NotationFile(dmg_filename); + Register_Object(dmg_file); + + if (!dmg_file->PageCount()) + { + DEBUG_STREAM << dmg_filename << " is empty or missing!\n" << std::flush; +Dump_And_Die_2: + Unregister_Pointer(dmg_filename); + delete[] dmg_filename; + Unregister_Object(dmg_file); + delete dmg_file; + goto Dump_And_Die_1; + } + + // + // Get the number of Damage zones + // + int + dzone_count; + if ( + !skl_file->GetEntry( + "ROOT", + "DZoneCount", + &dzone_count + ) + ) + { + DEBUG_STREAM << model_name << " is missing DZoneCount \n" << std::flush; + goto Dump_And_Die_2; + } + + // + // Make a stream big enough for all the damage zones + // + DynamicMemoryStream + damage_zone_stream; + + // + // write the Damage Zone Count Info from the + // .dmg file to the stream + // + damage_zone_stream << dzone_count; + + // + // Make an entry list of all the entries in the damage zone page + // + NameList + *dzone_namelist = skl_file->MakeEntryList("DamageZones","dz_"); + Register_Object(dzone_namelist); + + if (dzone_namelist->EntryCount() == 0) + { + DEBUG_STREAM << "No dZones listed in DamageZones Page"<GetFirstEntry(); + + while (dzone_entry) + { + ++num_dzones_found; + // + // Get dzone name in .skl file + // + Str_Copy( + current_dzone_name, + dzone_entry->GetName(), + sizeof(current_dzone_name) + ); + + // + // Create the stream for this damage zone + // This Should Default to VTV::DamageZone::Create + // + VTV__DamageZone::CreateStreamedDamageZone( + model_file, + model_name, + skl_file, + current_dzone_name, + &damage_zone_stream, + dmg_file, + directories + ); + // + // Get next dzone entry in this segment page + // + dzone_entry = dzone_entry->GetNextEntry(); + } // End while more dzone_entries + + if(dzone_count != num_dzones_found) + { + DEBUG_STREAM << + "DZoneCount != damage zones found in Page DamageZones"<AddResourceMemoryStream( + model_name, + ResourceDescription::DamageZoneStreamResourceType, + 1, + ResourceDescription::Preload, + &damage_zone_stream + ); + Check(new_res); + // + // Free mem + // + Unregister_Pointer(skl_filename); + delete skl_filename; + Unregister_Object(skl_file); + delete skl_file; + Unregister_Pointer(dmg_filename); + delete dmg_filename; + Unregister_Object(dmg_file); + delete dmg_file; + Unregister_Object(dzone_namelist); + delete dzone_namelist; + Check_Fpu(); + return new_res->resourceID; +} + +//############################################################################# +//VTV::DamageZone +// +void + VTV__DamageZone::TakeDamage(Damage& damage) +{ + Check(this); + Check_Pointer(&damage); + + DamageZone::TakeDamage(damage); + + // + //--------------------------------- + // If the VTV is dead, make it burn + //--------------------------------- + // + VTV + *vtv = (VTV*)GetOwningSimulation(); + Check(vtv); + if (damageLevel >= 1.0f) + { + vtv->SetSimulationState(VTV::BurningState); + } + + // + //---------------------------------------------------------------------- + // If this VTV is linked to a player, send the score loss to that player + //---------------------------------------------------------------------- + // + RPPlayer + *rp_player = (RPPlayer*) vtv->GetPlayerLink(); + if (rp_player) + { + Check(rp_player); + // + //-------------------------------------------------------- + // If we died, send the I'm dead now message to the player + //-------------------------------------------------------- + // + if ( + vtv->GetSimulationState() == VTV::BurningState && + vtv->simulationState.GetOldState() != VTV::BurningState + ) + { + RPPlayer::VehicleDeadMessage + dead( + RPPlayer::VehicleDeadMessageID, + sizeof(RPPlayer::VehicleDeadMessage) + ); + rp_player->Dispatch(&dead); + } + + // + //------------------------------------------- + // Notify this player that damaged was caused + //------------------------------------------- + // + RPPlayer::TakeDamageMessage + damage_message( + RPPlayer::TakeDamageMessageID, + sizeof(RPPlayer::TakeDamageMessage), + rp_player->GetEntityID(), + 0, + damage + ); + rp_player->Dispatch(&damage_message); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTV__DamageZone::VTV__DamageZone(VTV *vtv, int damage_zone_index, MemoryStream *damage_zone_stream) : + DamageZone(vtv, damage_zone_index, damage_zone_stream) +{ + Scalar + dmg_data(vtv->maxImpactSpeed); + + dmg_data /= 3.6f; + + damageScale[Damage::CollisionDamageType] = + 2000.0f + / vtv->moverMass + / (dmg_data*dmg_data) + / ( + 1.0f + - vtv->elasticityCoefficient + * vtv->elasticityCoefficient + ); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTV__DamageZone::CreateStreamedDamageZone( + NotationFile *model_file, + const char *model_name, + NotationFile *skl_file, + const char *damage_zone_name, + MemoryStream *damage_zone_stream, + NotationFile *dmg_file, + const ResourceDirectories *directories + ) +{ + if(!DamageZone::CreateStreamedDamageZone( + model_file, + model_name, + skl_file, + damage_zone_name, + damage_zone_stream, + dmg_file, + directories + ) + ) + { + Check_Fpu(); + return -1; + } + Check_Fpu(); + return True; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTV::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + diff --git a/RP/VTV.h b/RP/VTV.h new file mode 100644 index 0000000..67df69a --- /dev/null +++ b/RP/VTV.h @@ -0,0 +1,524 @@ +#pragma once + +#include "..\munga\jmover.h" +#include "..\munga\vector2d.h" +#include "..\munga\controls.h" +#include "..\munga\normal.h" +#include "..\munga\damage.h" +#include "..\munga\reticle.h" +#include "rptool.h" + +class VTVControlsMapper; +class VTV; +class RPPlayer; + +#define ZIPPY 2.3f +#define MAX_THRUSTERS 6 +//########################################################################## +//#################### VTV::DamageZone ############################ +//########################################################################## + +class VTV__DamageZone : + public DamageZone +{ + public: + VTV__DamageZone( + VTV *vtv, + int damage_zone_index, + MemoryStream *damage_zone_stream + ); + + static Logical + CreateStreamedDamageZone( + NotationFile *model_file, + const char *model_name, + NotationFile *skl_file, + const char *damage_zone_name, + MemoryStream *damage_zone_stream, + NotationFile *dmg_file, + const ResourceDirectories *directories + ); + + void + TakeDamage(Damage& damage); + +}; + +//########################################################################## +//#################### VTV::UpdateMessage ############################ +//########################################################################## + +struct VTV__UpdateRecord: + public JointedMover::UpdateRecord +{ +public: + Enumeration + collisionState, + collisionMaterialType; + Normal + collisionNormal; + Scalar + collisionSpeed; + Logical + boosterOn; + Vector3D + boosterScale; + Scalar + boosterSmokeDensity; + int + hornBlast; // HACK - ECH 7/31/95 - For replicants +}; + +//########################################################################## +//###################### VTV::ModelResource ########################## +//########################################################################## + +struct VTV__ModelResource: + public JointedMover::ModelResource +{ + + Scalar + maxAcceleration, + groundEffectDomainSquared, + groundEffectRange, + maxThrusterRotationRate, + maxYawVelocity, + angularSpringFactor, + bankFactor, + deathSpeed, + deathScoreLoss, + maxImpactSpeed, + bottomArmorScale, + powerDive; + + Vector3D + maxAngularAcceleration; + + int + jointIndex[MAX_THRUSTERS], + segmentIndex[MAX_THRUSTERS]; + + Reticle::ModelResource + reticleResource; +}; + +//########################################################################## +//##################### Mover::MakeMessage ########################## +//########################################################################## + +class VTV__MakeMessage: + public JointedMover::MakeMessage +{ +public: + char + vehicleBadge[20], + vehicleColor[20]; + + VTV__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration, + const char* badge, + const char* color + ): + JointedMover::MakeMessage( + message_ID, + length, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin, + velocity, + acceleration + ) + { + Str_Copy(vehicleBadge, badge, sizeof(vehicleBadge)); + Str_Copy(vehicleColor, color, sizeof(vehicleColor)); + } + + VTV__MakeMessage( + Receiver::MessageID message_ID, + size_t length, + const EntityID &entity_ID, + Entity::ClassID class_ID, + const EntityID &owner_ID, + ResourceDescription::ResourceID resource_ID, + LWord instance_flags, + const Origin &origin, + const Motion &velocity, + const Motion &acceleration, + const char* badge, + const char* color + ): + JointedMover::MakeMessage( + message_ID, + length, + entity_ID, + class_ID, + owner_ID, + resource_ID, + instance_flags, + origin, + velocity, + acceleration + ) + { + Str_Copy(vehicleBadge, badge, sizeof(vehicleBadge)); + Str_Copy(vehicleColor, color, sizeof(vehicleColor)); + } +}; + +//########################################################################## +//############################# VTV ################################## +//########################################################################## + +class VTV: + public JointedMover +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +public: + enum { + KavorkianMessageID = JointedMover::NextMessageID, + MarkSpotMessageID, + RestoreToSpotMessageID, + ZoomInMessageID, + ZoomOutMessageID, + NextMessageID + }; + +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; + + void + TakeDamageMessageHandler(TakeDamageMessage *message); + void + ZoomInMessageHandler( + ReceiverDataMessageOf *message + ); + void + ZoomOutMessageHandler( + ReceiverDataMessageOf *message + ); + void + KavorkianMessageHandler( + ReceiverDataMessageOf *message + ); + void + MarkSpotMessageHandler( + ReceiverDataMessageOf *message + ); + void + RestoreToSpotMessageHandler( + ReceiverDataMessageOf *message + ); + + void + PlayerLinkMessageHandler(PlayerLinkMessage *message); + + Origin savedOrigin; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + HeightAboveTerrainAttributeID = JointedMover::NextAttributeID, + ThrusterPitchAttributeID, + CollisionStateAttributeID, + CollisionMaterialTypeAttributeID, + CollisionNormalAttributeID, + CollisionSpeedAttributeID, + EyepointRotationAttributeID, + BoosterOnAttributeID, + BoosterScaleAttributeID, + BoosterSmokeDensityAttributeID, + ForwardVelocityAttributeID, + CompassHeadingAttributeID, + TargetReticleAttributeID, + NavigationRangeAttributeID, + NavigationLinearPositionAttributeID, + NavigationAngularPositionAttributeID, + ScoreStateAttributeID, + ScoreTypeAttributeID, + HornBlastAttributeID, // HACK - ECH 7/31/95 - For replicants + NextAttributeID + }; + + virtual Vector3D + GetWorldLinearVelocity() + {return worldLinearVelocity;} + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + int hornBlast; // HACK - ECH 7/31/95 - For replicants + Scalar heightAboveTerrain; + Hinge thrusterPitch; + EulerAngles eyepointRotation; + Logical boosterOn; + Vector3D boosterScale; + Scalar boosterSmokeDensity; + Scalar forwardVelocity; + YawPitchRoll compassHeading; + Reticle targetReticle; + + Scalar navigationRange; + Point3D + *navigationLinearPosition; // ptr to linear pos of object or NULL + Quaternion + *navigationAngularPosition; // ptr to angular pos of object or NULL + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model support +// +public: + enum { + BurningState = JointedMover::StateCount, + StateCount + }; + + enum { + ControlsMapperSubsystem, + PowerSubsystem, + Thruster1Subsystem, + Thruster2Subsystem, + Thruster3Subsystem, + Thruster4Subsystem, + Thruster5Subsystem, + Thruster6Subsystem, + JointSubsystemID, + BasicSubsystemCount + }; + + typedef void + (VTV::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + void + SetMappingSubsystem(VTVControlsMapper *mapper); + + void + MoveAndCollide(Scalar time_slice); + + Logical + BoosterOn(); + +protected: + typedef VTV__UpdateRecord UpdateRecord; + + void + WriteUpdateRecord( + Simulation::UpdateRecord *message, + int update_model + ); + void + ReadUpdateRecord(Simulation::UpdateRecord *message); + +public: + Scalar + groundEffectDomainSquared, + groundEffectRange, + angularSpringFactor, + bankFactor, + maxYawVelocity, + powerDive, + thrusterAngle; + Vector3D + maxAngularAcceleration; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Collision support +// +public: + enum { + NoCollisionState = 0, + InitialHitState, + SlideState, + RestState, + CollisionStateCount + }; + + Enumeration + collisionTemporaryState; + StateIndicator + collisionState; + Enumeration + collisionMaterialType; + Normal + collisionNormal; + Scalar + collisionSpeed, + bottomArmorScale; + +protected: + void + PerformAndWatch( + const Time& till, + MemoryStream *update_stream + ); + + void + ProcessCollision( + Scalar time_slice, + BoxedSolidCollision &collision, + const Point3D &old_position, + Damage *damage + ); + + Time + lastDoorHit; + Vector3D + doorHitNormal; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Damage support +// +public: + Scalar + deathSpeed, + deathScoreLoss; + + Scalar + deathConstant; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Scoring support +// +public: + // + // HACK - ECH 7/6/95 - Allow the player vehicle to respond to score + // messages, allows attribute system to be used for scoring + // + void + RespondToScoreMessage(Message *message); + + StateIndicator + scoreState; + + Enumeration + scoreType; + + Logical + insideWorld; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef VTV__ModelResource ModelResource; + typedef VTV__MakeMessage MakeMessage; + typedef VTV__DamageZone DamageZone; + + static VTV* + Make(MakeMessage *creation_message); + + static ResourceDescription::ResourceID + CreateModelResource( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + ModelResource* model=NULL + ); + static ResourceDescription::ResourceID + CreateSubsystemStream( + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories + ); + static ResourceDescription::ResourceID + CreateDamageZoneStream( + ResourceFile *resource_file, + const char *dzone_name, + NotationFile *dmg_file, + const ResourceDirectories *directories + ); + typedef Logical + (*FindNameFunction)( + const char *control_name, + ControlsMapping *mapping + ); + static Simulation::SharedData* + GetSubsystemSharedData(const char *name); + + static ResourceDescription::ResourceID + CreateControlMappingStream( + const char *mapping_name, + NotationFile *mapping_file, + FindNameFunction find_name, + ResourceFile *resource_file, + const char *model_name, + NotationFile *model_file, + const ResourceDirectories *directories, + PlatformTool *current_tool + ); + + VTV( + MakeMessage *creation_message, + SharedData &virtual_data = DefaultData + ); + ~VTV(); + + Logical + TestInstance() const; + + enum { + RegularReset, + FootballReset, + MissionReviewReset + }; + + void + Reset(const Origin &new_origin, int reset_command); + + void + DeathShutdown(int shutdown_command); + + char + vehicleBadge[20], + vehicleColor[20]; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Navigation support +protected: + Scalar + targetRangeExponent, + currentRangeExponent; +public: + + Scalar + maxImpactSpeed; +}; diff --git a/RP/VTVMPPR.cpp b/RP/VTVMPPR.cpp new file mode 100644 index 0000000..d1fed26 --- /dev/null +++ b/RP/VTVMPPR.cpp @@ -0,0 +1,958 @@ +#include "rp.h" +#pragma hdrstop + +#include "vtvmppr.h" +#include "vtvpwr.h" +#include "..\munga\icom.h" +#include "..\munga\app.h" +#include "rpplayer.h" +#include "vtv.h" + +//############################################################################# +// Shared Data Support +// +VTVControlsMapper::SharedData + VTVControlsMapper::DefaultData( + VTVControlsMapper::GetClassDerivations(), + VTVControlsMapper::GetMessageHandlers(), + VTVControlsMapper::GetAttributeIndex(), + VTVControlsMapper::StateCount + ); + +Derivation* VTVControlsMapper::GetClassDerivations() +{ + static Derivation classDerivations(VTVSubsystem::GetClassDerivations(), "VTVControlsMapper"); + return &classDerivations; +} + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + VTVControlsMapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(VTVControlsMapper, ConfigureControls), + MESSAGE_ENTRY(VTVControlsMapper, ConfigureSideSlipMappables), + MESSAGE_ENTRY(VTVControlsMapper, ChooseSideSlip), + MESSAGE_ENTRY(VTVControlsMapper, ConfigureLiftCutMappables), + MESSAGE_ENTRY(VTVControlsMapper, ChooseLiftCut), + MESSAGE_ENTRY(VTVControlsMapper, ConfigureHornMappables), + MESSAGE_ENTRY(VTVControlsMapper, ChooseHorn), + MESSAGE_ENTRY(VTVControlsMapper, ActivateHorn), + MESSAGE_ENTRY(VTVControlsMapper, ConfigurePTTMappables), + MESSAGE_ENTRY(VTVControlsMapper, ChoosePTT), + MESSAGE_ENTRY(VTVControlsMapper, ActivatePTT), + MESSAGE_ENTRY(VTVControlsMapper, ToggleReticle) +}; + +Receiver::MessageHandlerSet& VTVControlsMapper::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(VTVControlsMapper::MessageHandlerEntries), VTVControlsMapper::MessageHandlerEntries, VTVSubsystem::GetMessageHandlers()); + return messageHandlers; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ConfigureControlsMessageHandler( + #if DEBUG_LEVEL>0 + ReceiverDataMessageOf *message + #else + ReceiverDataMessageOf * + #endif + ) +{ + Check(this); + Check(message); + +#if 0 + THIS STUFF IS BASICALLY OBSOLETE + // + //------------------------ + // Get the control manager + //------------------------ + // + Check(application); + ControlsManager *control = application->GetControlsManager(); + Check(control); + + // + //---------------------------------------------------------------------- + // If the config button was pressed, set all hardwired buttons to config + // mode, otherwise set them all back to active mode, and clear out any + // temporary mappings to the mappable buttons + //---------------------------------------------------------------------- + // + if (message->dataContents > 0) + { + if (GetSimulationState() == ConfigurationState) + { + control->SetHardwiredButtonsFilter(ActiveFilter, 0); + control->StopMappableButtonsConfigure( + ConfigurationFilter, + mustMatch, + mayMatch + ); + SetSimulationState(DefaultState); + } + else + { + if (controlMode != BasicMode) + { + control->SetHardwiredButtonsFilter(ConfigurationFilter, 0); + SetSimulationState(ConfigurationState); + } + } + } +#endif + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ConfigureSideSlipMappablesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + //--------------------------------------------------------------------- + // If the hardwired button was pressed, process presses of the mappable + // buttons, otherwise it was released, so erase any temporary mappings + //--------------------------------------------------------------------- + if (message->dataContents > 0) + { + EnterConfiguration( + &sideSlip, // direct target + this, // receiver + (Receiver::MessageID) 0, // activation message ID (none here) + ChooseSideSlipMessageID // configuration message ID + ); + } + else + { + ExitConfiguration(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ChooseSideSlipMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + AddOrErase(message->dataContents, &sideSlip); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ConfigureLiftCutMappablesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + // + //--------------------------------------------------------------------- + // If the hardwired button was pressed, process presses of the mappable + // buttons, otherwise it was released, so erase any temporary mappings + //--------------------------------------------------------------------- + // + if (message->dataContents > 0) + { + EnterConfiguration( + &liftCut, // direct target + this, // receiver + (Receiver::MessageID) 0, // activation message ID (none here) + ChooseLiftCutMessageID // configuration message ID + ); + } + else + { + ExitConfiguration(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ChooseLiftCutMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + AddOrErase(message->dataContents, &liftCut); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ConfigureHornMappablesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + // + //--------------------------------------------------------------------- + // If the hardwired button was pressed, process presses of the mappable + // buttons, otherwise it was released, so erase any temporary mappings + //--------------------------------------------------------------------- + // + + if (message->dataContents > 0) + { + EnterConfiguration( + NULL, // direct target (none here) + this, // receiver + ActivateHornMessageID, // activation message ID + ChooseHornMessageID // configuration message ID + ); + } + else + { + ExitConfiguration(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ChooseHornMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + AddOrErase(message->dataContents, this, ActivateHornMessageID); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ActivateHornMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + hornBlast = message->dataContents; +// hornBlast = (hornBlast == -1) ? 1 : -1; + + // HACK - ECH 7/31/95 - Propagate horn blast + Check(GetEntity()); + GetEntity()->hornBlast = hornBlast; + GetEntity()->ForceUpdate(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ConfigurePTTMappablesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + // + //--------------------------------------------------------------------- + // If the hardwired button was pressed, process presses of the mappable + // buttons, otherwise it was released, so erase any temporary mappings + //--------------------------------------------------------------------- + // + if (message->dataContents > 0) + { + EnterConfiguration( + NULL, // direct target (none here) + this, // receiver + ActivatePTTMessageID, // activation message ID + ChoosePTTMessageID // configuration message ID + ); + } + else + { + ExitConfiguration(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ChoosePTTMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + AddOrErase(message->dataContents, &pttStatus); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ActivatePTTMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + pttStatus = message->dataContents; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::ToggleReticleMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + if (message->dataContents > 0) + { + VTV* vtv = GetEntity(); + Check(vtv); + Reticle *reticle = &vtv->targetReticle; + Check(reticle); + reticle->reticleState = + (Reticle::ReticleState)(reticle->reticleState^Reticle::ReticleOn); + } +} + +//############################################################################# +// Attribute Support +// +const VTVControlsMapper::IndexEntry + VTVControlsMapper::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(VTVControlsMapper, StickPosition, stickPosition), + ATTRIBUTE_ENTRY(VTVControlsMapper, ThrottlePosition, throttlePosition), + ATTRIBUTE_ENTRY(VTVControlsMapper, PedalsPosition, pedalsPosition), + ATTRIBUTE_ENTRY(VTVControlsMapper, ReverseThrust, reverseThrust), + ATTRIBUTE_ENTRY(VTVControlsMapper, LiftCut, liftCut), + ATTRIBUTE_ENTRY(VTVControlsMapper, SideSlip, sideSlip), + ATTRIBUTE_ENTRY(VTVControlsMapper, PowerDemand, powerDemand), + ATTRIBUTE_ENTRY( + VTVControlsMapper, + AngularVelocityDemand, + angularVelocityDemand + ), + ATTRIBUTE_ENTRY(VTVControlsMapper, BrakeLights, brakeLights), + ATTRIBUTE_ENTRY(VTVControlsMapper, LookLeft, lookLeft), + ATTRIBUTE_ENTRY(VTVControlsMapper, LookRight, lookRight), + ATTRIBUTE_ENTRY(VTVControlsMapper, LookBehind, lookBehind), + ATTRIBUTE_ENTRY(VTVControlsMapper, LookUp, lookUp), + ATTRIBUTE_ENTRY(VTVControlsMapper, ControlMode, controlMode), + ATTRIBUTE_ENTRY(VTVControlsMapper, HornBlast, hornBlast), + ATTRIBUTE_ENTRY(VTVControlsMapper, MustMatch, mustMatch), + ATTRIBUTE_ENTRY(VTVControlsMapper, ReverseThrustEngaged,reverseThrustEngaged), // ECH 8/3/95 - HACK - deal with thrust + ATTRIBUTE_ENTRY(VTVControlsMapper, LiftCutEngaged, liftCutEngaged), + ATTRIBUTE_ENTRY(VTVControlsMapper, PTTStatus, pttStatus) +}; + +VTVControlsMapper::AttributeIndexSet& VTVControlsMapper::GetAttributeIndex() +{ + static VTVControlsMapper::AttributeIndexSet attributeIndex(ELEMENTS(VTVControlsMapper::AttributePointers), + VTVControlsMapper::AttributePointers, + VTVSubsystem::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::InterpretControls(Scalar) +{ + Scalar demand; + + Check(this); + + VTV* vtv = GetEntity(); + Check(vtv); + VTVPower *power_system = + Cast_Object(VTVPower*, vtv->GetSubsystem(VTV::PowerSubsystem)); + + // + //---------------------------------------------- + // Make sure the control inputs are within range + //---------------------------------------------- + // + Verify(throttlePosition >= 0.0f && throttlePosition <= 1.0f); + Verify(stickPosition.x >= -1.0f && stickPosition.x <= 1.0f); + Verify(stickPosition.y >= -1.0f && stickPosition.y <= 1.0f); + Verify(pedalsPosition >= -1.0f && pedalsPosition <= 1.0f); + + // + //---------------------------------------------------------------- + // Figure out the proper control model to use based upon the speed + //---------------------------------------------------------------- + // + Scalar lateral_power = power_system->maxAccelerationOutput * ZIPPY; + powerDemand = Vector3D::Identity; + int slow_mode = + fabs(vtv->localVelocity.linearMotion.z) < + lateral_power / vtv->maxYawVelocity; + Check_Fpu(); + angularVelocityDemand = Vector3D::Identity; + Scalar kick_turn = (reverseThrust>0) ? throttlePosition : -throttlePosition; + powerDemand.z = kick_turn; + Logical no_steal = False; + liftCutEngaged = False; + reverseThrustEngaged = False; + + // + //---------------------------------------------------- + // If we are in basic mode, do that autothrottle thing + //---------------------------------------------------- + // + if (controlMode == BasicMode) + { + Scalar desired_speed = + powerDemand.z + * power_system->maxAccelerationOutput + / vtv->negativeLinearDragCoefficients.z; + Check_Fpu(); + Scalar reverse = (reverseThrust>0) ? 1.0f : -1.0f; + + // + //----------------------------------------------------------------------- + // If we have no boosters on, and we are going too fast, and the stick is + // not pushed near full forward, change the throttle setting + //----------------------------------------------------------------------- + // + if ( + !vtv->BoosterOn() + && throttlePosition < 0.1f + && desired_speed > vtv->localVelocity.linearMotion.z + ) + { + no_steal = True; + powerDemand.z = -reverse; + + // ECH 8/3/95 - HACK - deal with thrust + Scalar temp = Abs(vtv->localVelocity.linearMotion.z) / 60.0f; + Clamp(temp, 0.0f, 1.0f); + powerDemand.z *= pow(temp, 0.5f); + } + + // + //-------------------------------------------------------- + // If we are sliding against the engines, go to full power + //-------------------------------------------------------- + // + else if (vtv->localVelocity.linearMotion.z * reverse < 0.0f) + { + no_steal = True; + + // ECH 8/3/95 - HACK - deal with thrust + if (throttlePosition < 0.1f) + { + Scalar temp = Abs(vtv->localVelocity.linearMotion.z) / 60.0f; + Clamp(temp, 0.0f, 1.0f); + powerDemand.z *= pow(temp, 0.5f); + } + } + } + brakeLights = (powerDemand.z * vtv->localVelocity.linearMotion.z) < 0.0f; + + // + //-------------------------------------------------------------------------- + // If we are in slow mode, match the lateral power to the turn rate, giving + // it priority over thrust, so that we will be able to turn a perfect circle + //-------------------------------------------------------------------------- + // + if (slow_mode && sideSlip < 1 && controlMode < MasterMode) + { + angularVelocityDemand.y += stickPosition.x * vtv->maxYawVelocity; + powerDemand.x = + -vtv->maxYawVelocity + * fabs(vtv->localVelocity.linearMotion.z) + * stickPosition.x + / lateral_power; + Check_Fpu(); + if (reverseThrust>0 && vtv->localVelocity.linearMotion.z > 0.0f) + { + powerDemand.x = -powerDemand.x; + } + demand = powerDemand.x*powerDemand.x + powerDemand.z*powerDemand.z; + Check_Fpu(); + if (demand>1.0f) + { + if (powerDemand.z > 0.0f) + { + powerDemand.z = Sqrt(1.0f - powerDemand.x*powerDemand.x); + } + else + { + powerDemand.z = -Sqrt(1.0f - powerDemand.x*powerDemand.x); + } + } + Check_Fpu(); + } + + // + //------------------------------------------------------------------------- + // If we aren't in slow mode, match the turning rate to the power setting + // on the stick, sharing power equally between forward and sideways demands + //------------------------------------------------------------------------- + // + else + { + powerDemand.x = -stickPosition.x; + demand = powerDemand.x*powerDemand.x + powerDemand.z*powerDemand.z; + Check_Fpu(); + + // + //----------------------------------------------------------------------- + // If we are asking for more power than is available, steal from anything + // but braking so we can turn quicker if we are in a wimp mode + //----------------------------------------------------------------------- + // + if (demand>1.0f) + { + if (controlMode < MasterMode && powerDemand.z < 0.0f && !no_steal) + { + powerDemand.z = -Sqrt(1.0f - powerDemand.x*powerDemand.x); + Check_Fpu(); + } + else + { + demand = Sqrt(demand); + powerDemand.x /= demand; + powerDemand.z /= demand; + Check_Fpu(); + } + } + } + + // + //------------------------------------------------------------------------- + // The amount of power required for height as requested by the stick should + // range between 1m height and the service ceiling + //------------------------------------------------------------------------- + // + JointSubsystem *joint_subsystem = vtv->GetJointSubsystem(); + Check(joint_subsystem); + Verify(joint_subsystem->GetJointCount()); + + // + //------------------------------------------------------------------------ + // If the lift cut button is on, go ahead and put all the power on X and Z. + // In basic mode, if the height is greater than 5m and the stick is pushed + // mostly forward + //------------------------------------------------------------------------ + // + if ( + liftCut > 0 + || controlMode < VeteranMode + && stickPosition.y <= -0.8f + && vtv->heightAboveTerrain >= 5.0f + ) + { + powerDemand.y = vtv->powerDive; + if (powerDemand.y) + { + Scalar reduction = Sqrt(1.0f - powerDemand.y*powerDemand.y); + powerDemand.x *= reduction; + powerDemand.z *= reduction; + } + liftCutEngaged = True; + } + + // + //------------------------------------------------------------------------ + // Otherwise, give altitude everything it wants, and split the rest up for + // X and Z + //------------------------------------------------------------------------ + // + else + { + if (!vtv->groundEffectDomainSquared) + { + if (vtv->heightAboveTerrain >= 2.0f) + { + powerDemand.y = 0.0f; + liftCutEngaged = True; + } + else + { + demand = + power_system->maxAccelerationOutput + + joint_subsystem->GetJointCount() * + vtv->groundEffectRange; + powerDemand.y = vtv->GetEnvironment()->gravityConstant/demand; + } + } + else if (controlMode > StandardMode) + { + demand = + power_system->maxAccelerationOutput + + joint_subsystem->GetJointCount() + * (vtv->groundEffectRange + / (1.0f + vtv->groundEffectDomainSquared)); + Check_Fpu(); + demand = vtv->GetEnvironment()->gravityConstant/demand; + powerDemand.y = + 0.5f * ((1.0f - demand) * stickPosition.y + (1.0f + demand)); + Max_Clamp(powerDemand.y, 1.0f); + Check_Fpu(); + } + else + { + Scalar seek_height = vtv->heightAboveTerrain; + Scalar height_clamp = 30.0f; + Max_Clamp(seek_height, height_clamp); + if (stickPosition.y < 0.0f) + { + seek_height = + ::Lerp(seek_height, 1.0f, -stickPosition.y); + } + else + { + seek_height = + ::Lerp(seek_height, height_clamp, stickPosition.y); + } + demand = + power_system->maxAccelerationOutput + + joint_subsystem->GetJointCount() * + ( + vtv->groundEffectRange + / ( + 1.0f + + vtv->groundEffectDomainSquared*seek_height*seek_height + ) + ); + Check_Fpu(); + powerDemand.y = vtv->GetEnvironment()->gravityConstant/demand; + if (controlMode == BasicMode) + { + Max_Clamp(powerDemand.y, 0.85f); + } + else + { + Max_Clamp(powerDemand.y, 1.0f); + } + Check_Fpu(); + } + demand = Sqrt(1.0f - powerDemand.y*powerDemand.y); + powerDemand.x *= demand; + powerDemand.z *= demand; + } + + // + //---------------------------------------------------------- + // Apply the rudders, and simulate a kick turn in basic mode + //---------------------------------------------------------- + // + if (controlMode == BasicMode) + { + Scalar temp = stickPosition.x * stickPosition.x; + temp *= stickPosition.x; + angularVelocityDemand.y += temp * vtv->maxYawVelocity; + } + else if (pedalsPosition < 0.0f) + { + angularVelocityDemand.y -= + vtv->maxYawVelocity * pedalsPosition*pedalsPosition; + } + else + { + angularVelocityDemand.y += + vtv->maxYawVelocity * pedalsPosition*pedalsPosition; + } + + // + //------------------------------------------------------------------------- + // If we are not is slow mode, apply yaw to the craft to sufficient to make + // it turn a perfect circle, then clamp to maximum velocity + //------------------------------------------------------------------------- + // + if (!slow_mode && controlMode < MasterMode && sideSlip < 1) + { + angularVelocityDemand.y += + -powerDemand.x + * ZIPPY + * power_system->maxAccelerationOutput + / fabs(vtv->localVelocity.linearMotion.z); + Check_Fpu(); + if (reverseThrust>0 && vtv->localVelocity.linearMotion.z > 0.0f) + { + powerDemand.x = -powerDemand.x; + } + } + Clamp( + angularVelocityDemand.y, + -vtv->maxYawVelocity, + vtv->maxYawVelocity + ); + + // + //---------------------------------------- + // Turn the eyepoint the direction we want + //---------------------------------------- + // + vtv->eyepointRotation = EulerAngles::Identity; + if (lookLeft > 0) + { + vtv->eyepointRotation.yaw = 0.3f * PI; + } + else if (lookRight > 0) + { + vtv->eyepointRotation.yaw = -0.3f * PI; + } + else if (lookBehind > 0) + { + vtv->eyepointRotation.yaw = PI; + } + else if (lookUp > 0) + { + vtv->eyepointRotation.pitch = PI / 8.0f; + } + + // ECH - HACK - deal with thrust and lift cut + averageOfForwardThrustDemand.Add(powerDemand.z); + forwardThrustDemand = averageOfForwardThrustDemand.CalculateAverage(); + switch (controlMode) + { + case BasicMode: + // Lift cut has been set, see above + // Reverse thrust if demand over 0.15 + reverseThrustEngaged = (forwardThrustDemand > 0.15f); + break; + + case StandardMode: + // Lift cut has been set, see above + // Reverse thrust based on button + reverseThrustEngaged = (reverseThrust > 0); + break; + + case VeteranMode: + case MasterMode: + // Lift cut based on button + // Reverse thrust based on button + liftCutEngaged = (liftCut > 0); + reverseThrustEngaged = (reverseThrust > 0); + break; + } + Check(GetEntity()); + if (GetEntity()->GetSimulationState() == VTV::BurningState) + { + liftCutEngaged = False; + reverseThrustEngaged = False; + } + + // + //---------------------------------------------------------------- + // Send PTT status to intercom + //---------------------------------------------------------------- + // + if (pttStatus != previousPTTStatus) + { + previousPTTStatus = pttStatus; + + Player + *player_pointer = vtv->GetPlayerLink(); + Check(player_pointer); + Icom + *intercom = player_pointer->GetIntercom(); + Check(intercom); + + intercom->SetPTTStatus((Logical) pttStatus > 0); + } + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::CreateTemporaryEventMappings( + Receiver */*receiver*/, + Receiver::MessageID /*config_message_id*/ + ) +{ + Fail("Unhandled mapping!\n"); +} + +void + VTVControlsMapper::RemoveTemporaryEventMappings() +{ + Fail("Unhandled mapping!\n"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::AddOrErase( + unsigned int, + Receiver *, + Receiver::MessageID + ) +{ + Fail("Unhandled mapping!\n"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::AddOrErase( + unsigned int, + ControlsButton * + ) +{ + Fail("Unhandled mapping!\n"); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVControlsMapper::SetConfigurationState(Logical enter_config) +{ + Check(this); + + if (enter_config) + { + if (GetSimulationState() != ConfigurationState) + { + SetSimulationState(ConfigurationState); + NotifyOfConfigurationModeChange(enter_config); + } + } + else + { + if (GetSimulationState() == ConfigurationState) + { + SetSimulationState(DefaultState); + NotifyOfConfigurationModeChange(enter_config); + } + } + Check_Fpu(); +} + +void + VTVControlsMapper::NotifyOfControlModeChange(int /*new_mode*/) +{ + Check(this); + // defaults to no-operation: intended to be processed by + // platform-specific derived class + Check_Fpu(); +} + +void + VTVControlsMapper::NotifyOfConfigurationModeChange(Logical /*new_state*/) +{ + Check(this); + // defaults to no-operation: intended to be processed by + // platform-specific derived class + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVControlsMapper::VTVControlsMapper( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + VTVSubsystem( + owner, + subsystem_ID, + subsystem_resource, + shared_data + ), + averageOfForwardThrustDemand(4) // ECH 8/3/95 - HACK - To deal with reverse thrust +{ + if (owner->GetInstance() == VTV::MasterInstance && owner->IsDynamic()) + { + SetPerformance(&VTVControlsMapper::InterpretControls); + } + + stickPosition.x = 0.0f; + stickPosition.y = 0.0f; + throttlePosition = 0.0f; + pedalsPosition = 0.0f; + + reverseThrust = 0; + liftCut = 0; + sideSlip = 0; + powerDemand = Vector3D::Identity; + angularVelocityDemand = Vector3D::Identity; + brakeLights = 0; + lookLeft = 0; + lookRight = 0; + lookBehind = 0; + lookUp = 0; + hornBlast = 0; + controlMode = BasicMode; + forwardThrustDemand = 0.0f; + liftCutEngaged = False; + reverseThrustEngaged = False; + + pttStatus = 0; + previousPTTStatus = 0; + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVControlsMapper::~VTVControlsMapper() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTVControlsMapper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP/VTVMPPR.h b/RP/VTVMPPR.h new file mode 100644 index 0000000..e347bf6 --- /dev/null +++ b/RP/VTVMPPR.h @@ -0,0 +1,245 @@ +#pragma once + +#include "vtvsub.h" +#include "..\munga\average.h" + +//########################################################################## +//################ VTVControlsMapper::ModelResource ################## +//########################################################################## + +class VTVControlsMapper: + public VTVSubsystem +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging Support +// +public: + enum { + ConfigureControlsMessageID = VTVSubsystem::NextMessageID, + ConfigureSideSlipMappablesMessageID, + ChooseSideSlipMessageID, + ConfigureLiftCutMappablesMessageID, + ChooseLiftCutMessageID, + ConfigureHornMappablesMessageID, + ChooseHornMessageID, + ActivateHornMessageID, + ConfigurePTTMappablesMessageID, + ChoosePTTMessageID, + ActivatePTTMessageID, + ToggleReticleMessageID, + NextMessageID + }; + + void + ConfigureControlsMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigureSideSlipMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChooseSideSlipMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigureLiftCutMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChooseLiftCutMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigureHornMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChooseHornMessageHandler( + ReceiverDataMessageOf *message + ); + void + ActivateHornMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigurePTTMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChoosePTTMessageHandler( + ReceiverDataMessageOf *message + ); + void + ActivatePTTMessageHandler( + ReceiverDataMessageOf *message + ); + void + ToggleReticleMessageHandler( + ReceiverDataMessageOf *message + ); + +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + StickPositionAttributeID = VTVSubsystem::NextAttributeID, + ThrottlePositionAttributeID, + PedalsPositionAttributeID, + ReverseThrustAttributeID, + LiftCutAttributeID, + SideSlipAttributeID, + PowerDemandAttributeID, + AngularVelocityDemandAttributeID, + BrakeLightsAttributeID, + LookLeftAttributeID, + LookRightAttributeID, + LookBehindAttributeID, + LookUpAttributeID, + ControlModeAttributeID, + HornBlastAttributeID, + MustMatchAttributeID, + ReverseThrustEngagedAttributeID, // ECH 8/3/95 - HACK - deal with thrust + LiftCutEngagedAttributeID, + PTTStatusAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + ControlsJoystick stickPosition; + Scalar throttlePosition; + Scalar pedalsPosition; + ControlsButton + reverseThrust, + liftCut, + sideSlip, + rollLeft, + rollRight, + pitchUp, + pitchDown; + Vector3D + powerDemand, + angularVelocityDemand; + + int brakeLights; + ControlsButton + lookLeft, + lookRight, + lookBehind, + lookUp, + hornBlast, + pttStatus; + + // ECH 8/3/95 - HACK - deal with thrust + AverageOf + averageOfForwardThrustDemand; + Scalar + forwardThrustDemand; + Logical + reverseThrustEngaged; + + Logical + liftCutEngaged; + + enum { + BasicMode = 0, + StandardMode, + VeteranMode, + MasterMode + } + controlMode; + + unsigned int + mustMatch, + mayMatch; + +protected: + ControlsButton + previousPTTStatus; // used to detect change in PTT status + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + enum { + ConfigurationState = VTVSubsystem::StateCount, + StateCount + }; + + typedef void + (VTVControlsMapper::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + InterpretControls(Scalar time_slice); + void + SetConfigurationState(Logical enter_config); + + virtual void + CreateTemporaryEventMappings( + Receiver *receiver, + Receiver::MessageID config_message_id + ), + RemoveTemporaryEventMappings(), + AddOrErase( + unsigned int button_ID, + Receiver *target, + Receiver::MessageID message_ID + ), + AddOrErase( + unsigned int button_ID, + ControlsButton *destination + ); + + virtual void + NotifyOfControlModeChange(int new_mode); + + virtual void + NotifyOfConfigurationModeChange(Logical new_state); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + VTVControlsMapper( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data + ); + ~VTVControlsMapper(); + + Logical + TestInstance() const; +}; diff --git a/RP/VTVPWR.cpp b/RP/VTVPWR.cpp new file mode 100644 index 0000000..402cde3 --- /dev/null +++ b/RP/VTVPWR.cpp @@ -0,0 +1,134 @@ +#include "rp.h" +#pragma hdrstop + +#include "vtvpwr.h" +#include "thruster.h" +#include "vtv.h" + +//############################################################################# +// Shared Data Support +// +VTVPower::SharedData + VTVPower::DefaultData( + VTVPower::GetClassDerivations(), + VTVPower::GetMessageHandlers(), + VTVPower::GetAttributeIndex(), + VTVPower::StateCount + ); + +Derivation* VTVPower::GetClassDerivations() +{ + static Derivation classDerivations(Subsystem::GetClassDerivations(), "VTVPower"); + return &classDerivations; +} + +//############################################################################# +// Attribute Support +// +const VTVPower::IndexEntry + VTVPower::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(VTVPower, MaxAccelerationOutput, maxAccelerationOutput) +}; + +VTVPower::AttributeIndexSet& VTVPower::GetAttributeIndex() +{ + static VTVPower::AttributeIndexSet attributeIndex(ELEMENTS(VTVPower::AttributePointers), + VTVPower::AttributePointers, + Subsystem::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// +void + VTVPower::PowerSimulation(Scalar) +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Get pointers to the other subsystems we will have to deal with inside the + // VTV + //-------------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + Scalar average_moment_arm = 0.0f; + + // + //--------------------------------------- + // Find out the average moment arm length + //--------------------------------------- + // + JointSubsystem *joint_subsystem = vtv->GetJointSubsystem(); + Check(joint_subsystem); + Verify(joint_subsystem->GetJointCount()); + + int i; + for (i=0; iGetSubsystem(VTV::Thruster1Subsystem + i); + + if(thruster != NULL) + { + average_moment_arm += thruster->momentArmLength; + } + } + average_moment_arm /= joint_subsystem->GetJointCount(); + Scalar average_accel = maxAccelerationOutput / joint_subsystem->GetJointCount(); + Check_Fpu(); + + for (i=0; iGetSubsystem(VTV::Thruster1Subsystem + i); + + if(thruster != NULL) + { + Check(thruster); + Verify(!Small_Enough(thruster->momentArmLength)); + thruster->powerScale = average_moment_arm / thruster->momentArmLength; + thruster->currentAcceleration = average_accel * thruster->powerScale; + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVPower::VTVPower( + VTV *entity, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + Subsystem(entity, subsystem_ID, subsystem_resource, DefaultData) +{ + if (entity->GetInstance() != VTV::ReplicantInstance) + { + SetPerformance(&VTVPower::PowerSimulation); + } + + maxAccelerationOutput = subsystem_resource->maxAcceleration; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVPower::~VTVPower() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTVPower::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + diff --git a/RP/VTVPWR.h b/RP/VTVPWR.h new file mode 100644 index 0000000..9d7acfb --- /dev/null +++ b/RP/VTVPWR.h @@ -0,0 +1,100 @@ +#pragma once + +#include "vtvsub.h" + +//########################################################################## +//#################### Subsystem::SubsystemResource ################## +//########################################################################## + +struct VTVPower__SubsystemResource: + public Subsystem::SubsystemResource +{ + Scalar + maxAcceleration; +}; + +//########################################################################## +//############################ VTVPower ############################## +//########################################################################## + +class VTVPower: + public Subsystem +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Message Support +// +#if 0 +private: + static const HandlerEntry MessageHandlerEntries[]; + +protected: + static MessageHandlerSet MessageHandlers; +#endif + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + MaxAccelerationOutputAttributeID = Subsystem::NextAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +protected: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute declarations go here +// +public: + Scalar + maxAccelerationOutput; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (VTVPower::*Performance)(Scalar time_slice); + + void + PowerSimulation(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + VTV* + GetEntity() + {Check(this); return Cast_Object(VTV*, Subsystem::GetEntity());} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction +// +public: + typedef VTVPower__SubsystemResource SubsystemResource; + + VTVPower( + VTV *owner, + int subsystem_ID, + SubsystemResource *subsystem + ); + ~VTVPower(); + + Logical + TestInstance() const; +}; diff --git a/RP/VTVSUB.cpp b/RP/VTVSUB.cpp new file mode 100644 index 0000000..5962575 --- /dev/null +++ b/RP/VTVSUB.cpp @@ -0,0 +1,153 @@ +#include "rp.h" +#pragma hdrstop + +#include "vtvsub.h" +#include "vtv.h" +#include "..\munga\app.h" +#include "vtvmppr.h" + +VTVSubsystem::SharedData + VTVSubsystem::DefaultData( + VTVSubsystem::GetClassDerivations(), + VTVSubsystem::GetMessageHandlers(), + VTVSubsystem::GetAttributeIndex(), + VTVSubsystem::StateCount + ); + +Derivation* VTVSubsystem::GetClassDerivations() +{ + static Derivation classDerivations(Subsystem::GetClassDerivations(), "VTVSubsystem"); + return &classDerivations; +} + +//############################################################################# +// Messaging Support +// +//const Receiver::HandlerEntry +// VTVSubsystem::MessageHandlerEntries[]= +//{ +//}; +// +//Receiver::MessageHandlerSet +// VTVSubsystem::MessageHandlers( +// ELEMENTS(VTVSubsystem::MessageHandlerEntries), +// VTVSubsystem::MessageHandlerEntries, +// Subsystem::MessageHandlers +// ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVSubsystem::VTVSubsystem( + VTV *entity, + int subsystem_ID, + SubsystemResource *model, + SharedData &shared_data, + // these two fields added 12-28-95 by cpb + void *control_destination, + Receiver::MessageID message_id +): + Subsystem(entity, subsystem_ID, model, shared_data) +{ + controlDestination = control_destination; + controlMessageID = message_id; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVSubsystem::~VTVSubsystem() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTVSubsystem::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +void + VTVSubsystem::EnterConfiguration( + ControlsButton *direct_target, + Receiver *receiver, + Receiver::MessageID active_message_id, + Receiver::MessageID config_message_id + ) +{ + Check(this); + + Check(application); + ControlsManager + *controls_mgr = application->GetControlsManager(); + Check(controls_mgr); + + //------------------------------------------- + // Tell controls mgr that we're configuring + //------------------------------------------- + controls_mgr->StartMappableButtonsConfigure( + direct_target, // direct mapping (if used) + receiver, // targeted receiver + receiver, // dependant + active_message_id, // activation message ID (if used) + (ModeMask) 0, // remove_mode_mask + (ModeMask) 0 // add_mode_mask + ); + + //----------------------------------------------------------- + // Create temporary mappings for configuration + //----------------------------------------------------------- + Check(GetEntity()); + + VTVControlsMapper + *mapper = (VTVControlsMapper*) GetEntity()->GetSubsystem( + VTV::ControlsMapperSubsystem + ); + + if (mapper != NULL) + { + Check(mapper); + + mapper->CreateTemporaryEventMappings( + receiver, + config_message_id + ); + } + Check_Fpu(); +} + +void + VTVSubsystem::ExitConfiguration() +{ + Check(application); + ControlsManager + *controls_mgr = application->GetControlsManager(); + Check(controls_mgr); + + //------------------------------------------------ + // Tell controls mgr we're through + //------------------------------------------------ + controls_mgr->StopMappableButtonsConfigure( + (ModeMask) 0, // remove_mode_mask + (ModeMask) 0 // add_mode_mask + ); + //----------------------------------------------------------- + // Remove temporary mappings for configuration + //----------------------------------------------------------- + Check(GetEntity()); + + VTVControlsMapper + *mapper = (VTVControlsMapper*) GetEntity()->GetSubsystem( + VTV::ControlsMapperSubsystem + ); + + if (mapper != NULL) + { + Check(mapper); + + mapper->RemoveTemporaryEventMappings(); + } + Check_Fpu(); +} diff --git a/RP/VTVSUB.h b/RP/VTVSUB.h new file mode 100644 index 0000000..34fd7f9 --- /dev/null +++ b/RP/VTVSUB.h @@ -0,0 +1,61 @@ +#pragma once + +#include "..\munga\subsystm.h" +#include "..\munga\controls.h" + +class VTV; + +//########################################################################## +//######################## Subsystem ################################# +//########################################################################## + +class VTVSubsystem : public Subsystem +{ + friend class VTV; + +//########################################################################## +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//########################################################################## +// Messaging support +// + +// No messages handled here + +//########################################################################## +// Construction and Destruction Support +// +public: + ~VTVSubsystem(); + + Logical TestInstance() const; + +protected: + VTVSubsystem(VTV *entity, int subsystem_id, SubsystemResource *model, SharedData &shared_data, void *control_destination = NULL, Receiver::MessageID message_id = (Receiver::MessageID) 0); + +//########################################################################## +// Model support +// +public: + VTV* GetEntity() { return (VTV*)Subsystem::GetEntity(); } + +//########################################################################## +// Mapping support +// +protected: + void EnterConfiguration(ControlsButton *direct_target, Receiver *receiver, Receiver::MessageID active_message_id, Receiver::MessageID config_message_id); + void ExitConfiguration(); + + // 'controlDestination' is a pointer to the "thing" that a button + // is mapped to (if 'direct-mapped'), and 'controlMessageID' indicates + // the message ID that the button is mapped to (if 'event-mapped'). + // These values must be set appropriately in order for gauges to be + // able to determine ownership of mapped buttons. + void *controlDestination; // OBSOLETE? + + Receiver::MessageID controlMessageID; // OBSOLETE? +}; diff --git a/RP/WEAPSYS.cpp b/RP/WEAPSYS.cpp new file mode 100644 index 0000000..42a6697 --- /dev/null +++ b/RP/WEAPSYS.cpp @@ -0,0 +1,1523 @@ +#include "rp.h" +#pragma hdrstop + +#include "weapsys.h" +#include "rivet.h" +#include "demopack.h" +#include "..\munga\line.h" +#include "..\munga\explode.h" +#include "..\munga\boxsolid.h" +#include "vtvmppr.h" +#include "vtv.h" +#include "..\munga\app.h" + +//############################################################################# +// Shared Data Support +// +GenericGun::SharedData + GenericGun::DefaultData( + GenericGun::GetClassDerivations(), + GenericGun::MessageHandlers, + GenericGun::GetAttributeIndex(), + GenericGun::StateCount + ); + +Derivation* GenericGun::GetClassDerivations() +{ + static Derivation classDerivations(VTVSubsystem::GetClassDerivations(), "GenericGun"); + return &classDerivations; +} + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + GenericGun::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(GenericGun, ConfigureMappables), + MESSAGE_ENTRY(GenericGun, ChooseButton) +}; + +Receiver::MessageHandlerSet + GenericGun::MessageHandlers( + ELEMENTS(GenericGun::MessageHandlerEntries), + GenericGun::MessageHandlerEntries, + VTVSubsystem::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GenericGun::ConfigureMappablesMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + //--------------------------------------------------------------------- + // If the hardwired button was pressed, process presses of the mappable + // buttons, otherwise it was released, so erase any temporary mappings + //--------------------------------------------------------------------- + if (message->dataContents > 0) + { + EnterConfiguration( + &triggerState, // direct target + this, // receiver + (Receiver::MessageID) 0, // activation message ID (none here) + ChooseButtonMessageID // configuration message ID + ); + } + else + { + ExitConfiguration(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GenericGun::ChooseButtonMessageHandler( + ReceiverDataMessageOf *message + ) +{ + if (message->dataContents > 0) + { + // + //--------------------------------------------------------------------- + // Find the control manager of the vehicle, and have it turn off an + // existing mapping of a given type if it is there, otherwise it should + // create a new one + //--------------------------------------------------------------------- + // + VTV* vtv = GetEntity(); + Check(vtv); + VTVControlsMapper* controls = + Cast_Object( + VTVControlsMapper*, + vtv->GetSubsystem(VTV::ControlsMapperSubsystem) + ); + Check(controls); + + controls->AddOrErase(message->dataContents, &triggerState); + } + Check_Fpu(); +} + +//############################################################################# +// Attribute Support +// +const GenericGun::IndexEntry + GenericGun::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(GenericGun, TriggerState, triggerState), + ATTRIBUTE_ENTRY(GenericGun, PercentDone, percentDone) +}; + +GenericGun::AttributeIndexSet& GenericGun::GetAttributeIndex() +{ + static GenericGun::AttributeIndexSet attributeIndex(ELEMENTS(GenericGun::AttributePointers), + GenericGun::AttributePointers, + VTVSubsystem::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void GenericGun::CalcAmmoOrigin(Origin *ammo_origin) +{ + Check(this); + VTV *vtv = GetEntity(); + Check(vtv); + // + //------------------------------- + // Check if we are looking behind + //------------------------------- + // + VTVControlsMapper *ctrl_sub = + (VTVControlsMapper *) vtv->GetSubsystem(VTV::ControlsMapperSubsystem); + + LinearMatrix site_transform; + + + if(ctrl_sub->lookBehind > 0) + { + site_transform = siteRearTransform; + } + else + { + site_transform = siteFrontTransform; + } + LinearMatrix temp; + temp.Multiply(site_transform, vtv->localToWorld); + *ammo_origin = temp; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + GenericGun::GenericGunSimulation(Scalar) +{ + VTV *vtv = GetEntity(); + Check(vtv); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // General Firing Simulation + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if ( (triggerState > 0) && (vtv->GetSimulationState() != VTV::BurningState) ) + { + Fire(); + SetSimulationState(Firing); + } + else + { + SetSimulationState(DefaultState); + } + Check_Fpu(); +} + + +//############################################################################# +// Construction And Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GenericGun::GenericGun( + VTV *owner, + int subsystem_ID, + SubsystemResource *sub_res, + SharedData &shared_data +): + VTVSubsystem( + owner, + subsystem_ID, + sub_res, + shared_data, + &triggerState, // direct mapping for controls + (Receiver::MessageID) 0 // assumes no event mapping + ) +{ + Check(owner); + Check_Pointer(sub_res); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Resource Variables + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ammoVideoResourceID = sub_res->ammoVideoResourceID; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Initialize the Trigger to Released + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + triggerState = -1; + oldTriggerState = triggerState; + + SetPerformance(&GenericGun::GenericGunSimulation); + SetSimulationState(DefaultState); + percentDone = 0.0f; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Assumption: No Joints in between a Gun and the + // root node of a vtv, so we can get the + // transformation matrix to get to the + // position of the site so we know where + // the bullet is to come out of + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + EntitySegment *site_front_segment = owner->GetSegment(sub_res->segmentIndex); + Check(site_front_segment); + siteFrontTransform = site_front_segment->GetSegmentToEntity(); + + if(sub_res->rearSiteIndex == -1) + { + siteRearTransform = siteFrontTransform; + } + else + { + EntitySegment *site_rear_segment = owner->GetSegment(sub_res->rearSiteIndex); + Check(site_rear_segment); + siteRearTransform = site_rear_segment->GetSegmentToEntity(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +GenericGun::~GenericGun() +{ + Check(this); + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + GenericGun::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateStreamedSubsystem +// +int + GenericGun::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + ResourceFile *resource_file, + const ResourceDirectories *directories + ) +{ + Check(model_file); + Check_Pointer(model_name); + Check_Pointer(subsystem_name); + Check_Pointer(subsystem_resource); + Check(subsystem_file); + Check(resource_file); + Check_Pointer(directories); + + if ( + !Subsystem::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + directories + ) + ) + { + Check_Fpu(); + return False; + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Save the model size and classID + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::RivetGunClassID; + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the name of the ammo model file which holds + // all the info about the type of ammo this gun shoots + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + const char *ammo_model_file; + if( + !subsystem_file->GetEntry( + subsystem_name, + "AmmoModelFile", + &ammo_model_file + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing AmmoModelFile!\n" << std::flush; + Check_Fpu(); + return False; + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Find the description of the ammo in the current resource file + // Note: The ammo must be build before the gun which uses it + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + ResourceDescription *rivet_desc = + resource_file->FindResourceDescription( + ammo_model_file, + ResourceDescription::ModelListResourceType + ); + if(!rivet_desc) + { + DEBUG_STREAM << + ammo_model_file << " must be std::declared before "<< model_name << + " in the .bld file" << std::endl << std::flush; + Check_Fpu(); + return False; + } + subsystem_resource->ammoVideoResourceID = rivet_desc->resourceID; + const char *rear_site_name; + + if( + !subsystem_file->GetEntry( + subsystem_name, + "RearSiteName", + &rear_site_name + ) + ) + { + subsystem_resource->rearSiteIndex = -1; + } + else + { + subsystem_resource->rearSiteIndex = Get_Segment_Index( + model_file, + model_name, + directories, + rear_site_name); + } + + Check_Fpu(); + return True; +} + +//############################################################################ +//################ Class Rivet Gun ################################## +//############################################################################ + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +RivetGun::SharedData + RivetGun::DefaultData( + RivetGun::GetClassDerivations(), + RivetGun::MessageHandlers, + RivetGun::GetAttributeIndex(), + RivetGun::StateCount + ); + +Derivation* RivetGun::GetClassDerivations() +{ + static Derivation classDerivations(GenericGun::GetClassDerivations(), "RivetGun"); + return &classDerivations; +} + +//############################################################################# +// Attribute Support +// +const RivetGun::IndexEntry + RivetGun::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(RivetGun, TimeToLoaded, timeToLoaded), + ATTRIBUTE_ENTRY(RivetGun, AmmoCount, ammoCount) +}; + +RivetGun::AttributeIndexSet& RivetGun::GetAttributeIndex() +{ + static RivetGun::AttributeIndexSet attributeIndex(ELEMENTS(RivetGun::AttributePointers), + RivetGun::AttributePointers, + GenericGun::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Construction And Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RivetGun::RivetGun( + VTV *owner, + int subsystem_ID, + SubsystemResource *sub_res, + SharedData &shared_data +) + : GenericGun(owner, subsystem_ID, sub_res, shared_data) +{ + Check(owner); + Check_Pointer(sub_res); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get Resource Info + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + maxAmmoCount = sub_res->ammoCount; + ammoCount = maxAmmoCount; + loadTime = sub_res->loadTime; + muzzleVelocity = sub_res->muzzleVelocity; + + timeToLoaded = loadTime; + + SetPerformance(&RivetGun::RivetGunSimulation); + SetSimulationState(Loading); + Check_Fpu(); +} + +RivetGun::~RivetGun() +{ + Check(this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RivetGun::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// + +void RivetGun::CalcAmmoMotion(Motion *ammo_motion) +{ + Check(this); + VTV *vtv = GetEntity(); + Check(vtv); + *ammo_motion = vtv->localVelocity; + ammo_motion->linearMotion.x += muzzleVelocity.x; + ammo_motion->linearMotion.y += muzzleVelocity.y; + ammo_motion->linearMotion.z -= muzzleVelocity.z; + ammo_motion->angularMotion = Vector3D::Identity; + + Check_Fpu(); +} + +//############################################################################# +// Damage Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RivetGun::DeathReset(int reset_command) +{ + // + //--------------------------------------------------- + // Make sure we are not firing and reset variables + //--------------------------------------------------- + // + Check(this); + if (reset_command == VTV::FootballReset) + { + ammoCount = maxAmmoCount; + timeToLoaded = 0.0f; + SetSimulationState(Loaded); + } + else + { + SetSimulationState(Loading); + } + Check_Fpu(); +} + +//############################################################################# +// Model Support +// +void + RivetGun::RivetGunSimulation(Scalar time_slice) +{ + Check(this); + VTV *vtv = GetEntity(); + Check(vtv); + percentDone = (loadTime - timeToLoaded)/ loadTime; + Check_Fpu(); + if(percentDone > 1.0f) + { + percentDone = 1.0f; + } + if(percentDone < 0.0f) + { + percentDone = 0.0f; + } + Verify(percentDone >= 0.0f); + Verify(percentDone <= 1.0f); + switch(GetSimulationState()) + { + case NoAmmo: +Gun_NoAmmo: + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If there is no ammo and we are trying to fire--Misfire + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if( (triggerState > 0) && (vtv->GetSimulationState() != VTV::BurningState) ) + { + SetSimulationState(MisFire); + SetSimulationState(NoAmmo); + } + break; + case Loading: +Gun_Loading: + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See if there is any Ammo Left + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(ammoCount <= 0) + { + SetSimulationState(NoAmmo); + goto Gun_NoAmmo; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Ensure we don't run over our time slice + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Scalar time_left = time_slice - timeToLoaded; + timeToLoaded -= time_slice; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If we are done loading update the time slice + // and goto the firing state + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + + if(timeToLoaded <= 0.0f) + { + timeToLoaded = 0.0f; + time_slice = time_left; + SetSimulationState(Loaded); + goto Gun_Loaded; + } + break; + } + case Loaded: +Gun_Loaded: + if( + (triggerState > 0) + && + (vtv->GetSimulationState() != VTV::BurningState) + ) + { + goto Gun_Firing; + } + break; + case Firing: +Gun_Firing: + SetSimulationState(Firing); + Fire(); + SetSimulationState(Loading); + goto Gun_Loading; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + RivetGun::Fire() +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // std::decrement ammoCount and reset the loadTime + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + --ammoCount; + timeToLoaded = loadTime; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the entity and it's current position + // Add this to the siteTransform to determine + // where to shoot the rivet from + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + + Motion rivet_motion; + CalcAmmoMotion(&rivet_motion); + + // + //----------------------------- + // Move the rivet to the site + //----------------------------- + // + Origin rivet_localOrigin; + CalcAmmoOrigin(&rivet_localOrigin); + + VTV *vtv = GetEntity(); + Check(vtv); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a New Rivet Whose properties are listed in the + // Resource File + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + Rivet::MakeMessage + create_rivet( + Rivet::MakeMessageID, + sizeof(Rivet::MakeMessage), + (Entity::ClassID) Rivet::RivetClassID, + RivetGunClassID, + ammoVideoResourceID, + Rivet::DefaultFlags, + rivet_localOrigin, + rivet_motion, + Motion::Identity, + vtv->GetEntityID() + ); + #if DEBUG_LEVEL>0 + Rivet* my_rivet = Rivet::Make(&create_rivet); + Register_Object(my_rivet); + #else + Rivet::Make(&create_rivet); + #endif + Check_Fpu(); + return 1; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateStreamedSubsystem +// +int + RivetGun::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + ResourceFile *resource_file, + const ResourceDirectories *directories + ) +{ + + if ( + !GenericGun::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + resource_file, + directories + ) + ) + { + Check_Fpu(); + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::RivetGunClassID; + if( + !subsystem_file->GetEntry( + subsystem_name, + "LoadTime", + &subsystem_resource->loadTime + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing LoadTime!\n" << std::flush; + return False; + } + if( + !subsystem_file->GetEntry( + subsystem_name, + "AmmoCount", + &subsystem_resource->ammoCount + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing AmmoCount!\n" << std::flush; + Check_Fpu(); + return False; + } + const char* muzzle_velocity; + if( + !subsystem_file->GetEntry( + subsystem_name, + "MuzzleVelocity", + &muzzle_velocity + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing MuzzleVelocity!\n" << std::flush; + Check_Fpu(); + return False; + } + else + { + Convert_From_Ascii(muzzle_velocity, &subsystem_resource->muzzleVelocity); + } + Check_Fpu(); + return True; +} + + +//############################################################################ +//################ Class Laser Gun ################################## +//############################################################################ + +//############################################################################# +// Shared Data Support +// +LaserGun::SharedData + LaserGun::DefaultData( + LaserGun::GetClassDerivations(), + LaserGun::MessageHandlers, + LaserGun::GetAttributeIndex(), + LaserGun::StateCount + ); + +Derivation* LaserGun::GetClassDerivations() +{ static Derivation classDerivations(GenericGun::GetClassDerivations(), "LaserGun"); + return &classDerivations; +} + + +//############################################################################# +// Attribute Support +// +const LaserGun::IndexEntry + LaserGun::AttributePointers[]= +{ + ATTRIBUTE_ENTRY(LaserGun, FrontLaserOn, frontLaserOn), + ATTRIBUTE_ENTRY(LaserGun, RearLaserOn, rearLaserOn), + ATTRIBUTE_ENTRY(LaserGun, LaserScale, laserScale) +}; + +LaserGun::AttributeIndexSet& LaserGun::GetAttributeIndex() +{ + static LaserGun::AttributeIndexSet attributeIndex(ELEMENTS(LaserGun::AttributePointers), + LaserGun::AttributePointers, + GenericGun::GetAttributeIndex() + ); + return attributeIndex; +} + +//############################################################################# +// Model Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LaserGun::ReadUpdateRecord(Simulation::UpdateRecord *update_record) +{ + Check(this); + Check_Pointer(update_record); + GenericGun::ReadUpdateRecord(update_record); + UpdateRecord *laser_update = (UpdateRecord*) update_record; + + laserScale = laser_update->laserScale; + frontLaserOn = laser_update->frontLaserOn; + rearLaserOn = laser_update->rearLaserOn; + + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LaserGun::WriteUpdateRecord( + Simulation::UpdateRecord *update_record, + int update_model + ) +{ + Check(this); + Check_Pointer(update_record); + + GenericGun::WriteUpdateRecord(update_record, update_model); + UpdateRecord *laser_update = (UpdateRecord*) update_record; + laser_update->recordLength = sizeof(*laser_update); + laser_update->laserScale = laserScale; + laser_update->frontLaserOn = frontLaserOn; + laser_update->rearLaserOn = rearLaserOn; + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LaserGun::CalcPercentDone() +{ + percentDone = chargeLevel / maxChargeLevel; + Verify(percentDone >= 0.0f); + Verify(percentDone <= 1.0f); + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LaserGun::ChargingSimulation(Scalar time_slice) +{ + Check(this); + VTV *vtv = GetEntity(); + Check(vtv); + + chargeLevel += chargePerSecond * time_slice; + if (chargeLevel >= maxChargeLevel) + { + chargeLevel = maxChargeLevel; + SetSimulationState(DefaultState); + } + if (triggerState > 0 && vtv->GetSimulationState() != VTV::BurningState) + { + Fire(); + } + + CalcPercentDone(); + // Check_Fpu(); See CalcPercentDone, above. +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LaserGun::PulseFiringSimulation(Scalar time_slice) +{ + Check(this); + VTV *vtv = GetEntity(); + Check(vtv); + pulseDuration -= time_slice; + if (pulseDuration <= 0.0f) + { + if (triggerState > 0 && vtv->GetSimulationState() != VTV::BurningState) + { + Fire(); + } + else + { + frontLaserOn = False; + rearLaserOn = False; + ForceUpdate(); + SetSimulationState(Charging); + SetPerformance(&LaserGun::ChargingSimulation); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LaserGun::FiringSimulation(Scalar time_slice) +{ + // + //----------------------------------------------------------------------- + // If our time with the laser is done, look at the trigger state and jump + // to either the charging or pulsing state + //----------------------------------------------------------------------- + // + laserDuration -= time_slice; + if (laserDuration <= 0.0f) + { + SetSimulationState(PulseFiring); + SetPerformance(&LaserGun::PulseFiringSimulation); + pulseDuration = maxPulseDuration; + frontLaserOn = False; + rearLaserOn = False; + ForceUpdate(); + } + Check_Fpu(); +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LaserGun::Fire() +{ + Check(this); + + // + //--------------------------------------------- + // Make sure we have enough power before firing + //--------------------------------------------- + // + Scalar drain = drainPerSecond; + if (chargeLevel < drain) + { + SetSimulationState(Misfire); + return False; + } + chargeLevel -= drain; + SetPerformance(&LaserGun::FiringSimulation); + laserDuration = maxLaserDuration; + SetSimulationState(Firing); + ForceUpdate(); + + // + //------------------------------ + // Calculate the max laser line + //----------------------------- + // + Origin laser_origin; + CalcAmmoOrigin(&laser_origin); + + // + //------------------------------- + // Check if we are looking behind + //------------------------------- + // + Vector3D z_axis; + VTV *vtv = GetEntity(); + Check(vtv); + VTVControlsMapper *ctrl_sub = + (VTVControlsMapper *) vtv->GetSubsystem(VTV::ControlsMapperSubsystem); + if (ctrl_sub->lookBehind > 0) + { + z_axis.x = 0.0; z_axis.y = 0.0f; z_axis.z = 1.0; + rearLaserOn = True; + } + else + { + z_axis.x = 0.0f; z_axis.y = 0.0f; z_axis.z = -1.0f; + frontLaserOn = True; + } + Vector3D line_direction; + line_direction.Multiply( z_axis , vtv->localToWorld); + + UnitVector unit_direction; + unit_direction = line_direction; + Line + laser_line(laser_origin.linearPosition, unit_direction, maxLaserLength); + Check(&laser_line); + + // + //------------------------------------ + // See if the laser line hit anything + //------------------------------------ + // + BoxedSolid* target = vtv->FindBoxedSolidHitBy(&laser_line, vtv); + + laserScale.z = laser_line.length / 100.0f; + + Check_Fpu(); + + if (target) + { + // + //----------------------- + // Find the entity we hit + //----------------------- + // + Simulation *sim = target->GetOwningSimulation(); + Check(sim); + Entity *entity; + if (sim->IsDerivedFrom(*Subsystem::GetClassDerivations())) + { + Subsystem *subsys = (Subsystem*)sim; + Check(subsys); + entity = subsys->GetEntity(); + } + else + { + entity = (Entity*)sim; + } + Check(entity); + // + //-------------------------------------------- + // Make the explosion at the end of the laser + //-------------------------------------------- + // + Origin + explode_origin = laser_origin; + laser_line.FindEnd(&explode_origin.linearPosition); + + // + //------------------ + // Make an Explosion + //------------------ + // + Check(application); + ResourceFile + *resource_file = application->GetResourceFile(); + Check(resource_file); + + ResourceDescription + *explosion_res = + resource_file->FindResourceDescription(explosionResourceID); + Check(explosion_res); + explosion_res->Lock(); + + Explosion::MakeMessage + exp_message( + Explosion::MakeMessageID, + sizeof(Explosion::MakeMessage), + ExplosionClassID, + EntityID::Null, + explosion_res->resourceID, + Explosion::DefaultFlags, + explode_origin, + entity->GetEntityID(), + owningEntity->GetEntityID() + ); + + explosion_res->Unlock(); + + #if DEBUG_LEVEL>0 + Explosion + *exp = + #endif + Explosion::Make(&exp_message); + Register_Object(exp); + + // + //-------------------------------------------------------- + // Initialize the Positional info in the damage structure + //-------------------------------------------------------- + // + damageData.damageForce = Vector3D::Identity; + damageData.impactPoint = explode_origin.linearPosition; + // + //------------------------------------------ + // Send a damage message to the thing we hit + //------------------------------------------ + // + Entity::TakeDamageMessage + take_damage( + Entity::TakeDamageMessageID, + sizeof(Entity::TakeDamageMessage), + vtv->GetEntityID(), + 0, + damageData + ); + entity->Dispatch(&take_damage); + Check_Fpu(); + return True; + } + else + { + Check_Fpu(); + return False; + } +} + +//############################################################################# +// Damage Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + LaserGun::DeathReset(int reset_command) +{ + Check(this); + if (reset_command == VTV::FootballReset) + { + chargeLevel = maxChargeLevel; + } + frontLaserOn = False; + rearLaserOn = False; + laserScale.x = 1.0f; + laserScale.y = 1.0f; + laserScale.z = 1.0f; + SetSimulationState(Charging); + SetPerformance(&LaserGun::ChargingSimulation); + ForceUpdate(); + Check_Fpu(); +} + +//############################################################################# +// Construction And Destruction +// +LaserGun::LaserGun( + VTV *owner, + int subsystem_ID, + SubsystemResource *sub_res, + SharedData &shared_data +) + : GenericGun(owner, subsystem_ID, sub_res, shared_data) +{ + Check(owner); + Check_Pointer(&sub_res); + + // + //------------------------------------ + // get values from subsystem resource + //------------------------------------ + // + maxChargeLevel = 1.0f; + maxLaserLength = sub_res->laserLength; + fullChargeDuration = sub_res->fullChargeDuration; + chargePerSecond = sub_res->chargePerSecond; + explosionResourceID = sub_res->explosionResourceID; + maxLaserDuration = sub_res->laserDuration; + maxPulseDuration = sub_res->pulseDuration; + Scalar cycle_time = maxLaserDuration + maxPulseDuration; + damageData = sub_res->damageData; + damageData.damageAmount *= cycle_time; + drainPerSecond = sub_res->drainPerSecond * cycle_time; + + // + //----------------------- + // Init local variables + //----------------------- + // + chargeLevel = 1.0f; + percentDone = 1.0f; + laserDuration = 0.0f; + hitSomething = False; + frontLaserOn = False; + rearLaserOn = False; + laserScale.x = 1.0f; + laserScale.y = 1.0f; + laserScale.z = 1.0f; + pulseDuration = 0.0f; + + SetPerformance(&LaserGun::ChargingSimulation); + if (owner->GetInstance() == VTV::ReplicantInstance) + { + ExecuteOnUpdate(); + } + SetSimulationState(Charging); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +LaserGun::~LaserGun() +{ + +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + LaserGun::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateStreamedSubsystem +// +int + LaserGun::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + ResourceFile *resource_file, + const ResourceDirectories *directories + ) +{ + + if ( + !GenericGun::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + resource_file, + directories + ) + ) + { + Check_Fpu(); + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::LaserDrillClassID; + if( + !subsystem_file->GetEntry( + subsystem_name, + "ChargePerSecond", + &subsystem_resource->chargePerSecond + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing ChargePerSecond!\n" << std::flush; + Check_Fpu(); + return False; + } + if( + !subsystem_file->GetEntry( + subsystem_name, + "DrainPerSecond", + &subsystem_resource->drainPerSecond + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing DrainPerSecond!\n" << std::flush; + Check_Fpu(); + return False; + } + if( + !subsystem_file->GetEntry( + subsystem_name, + "DamageAmount", + &subsystem_resource->damageData.damageAmount + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing DamageAmount!\n" << std::flush; + Check_Fpu(); + return False; + } + else + { + // + //------------------------- + // Initialize damage fields + //------------------------- + // + subsystem_resource->damageData.damageType = Damage::LaserDamageType; + subsystem_resource->damageData.damageForce = Vector3D::Identity; + subsystem_resource->damageData.surfaceNormal.x = 0.0f; + subsystem_resource->damageData.surfaceNormal.y = 1.0f; + subsystem_resource->damageData.surfaceNormal.z = 0.0f; + subsystem_resource->damageData.impactPoint = Vector3D::Identity; + } + if( + !subsystem_file->GetEntry( + subsystem_name, + "FullChargeDuration", + &subsystem_resource->fullChargeDuration + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing FullChargeDuration!\n" << std::flush; + Check_Fpu(); + return False; + } + else + { + // + //----------------- + // Calc chargeLevel + //----------------- + // + subsystem_resource->chargeLevel = + subsystem_resource->fullChargeDuration / + subsystem_resource->drainPerSecond; + } + if( + !subsystem_file->GetEntry( + subsystem_name, + "PulseDuration", + &subsystem_resource->pulseDuration + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing PulseDuration!\n" << std::flush; + Check_Fpu(); + return False; + } + if( + !subsystem_file->GetEntry( + subsystem_name, + "LaserLength", + &subsystem_resource->laserLength + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing LaserLength!\n" << std::flush; + Check_Fpu(); + return False; + } + if( + !subsystem_file->GetEntry( + subsystem_name, + "LaserDuration", + &subsystem_resource->laserDuration + ) + ) + { + DEBUG_STREAM << subsystem_name << "missing LaserDuration!\n" << std::flush; + Check_Fpu(); + return False; + } + // + //---------------------------------------------------------------------- + // Read in the Model Filename of the Explosion renderable, then find its + // resource ID in the resource file + //---------------------------------------------------------------------- + // + const char *explosion; + if( + !subsystem_file->GetEntry( + subsystem_name, + "ExplosionModelFile", + &explosion + ) + ) + { + std::cout << model_name << " missing ExplosionModelFile!\n" << std::flush; + Check_Fpu(); + return False; + } + ResourceDescription *res = + resource_file->FindResourceDescription( + explosion, + ResourceDescription::ModelListResourceType + ); + if (!res) + { + std::cout << model_name << " cannot find " << explosion + << " in resource file!\n" << std::flush; + Check_Fpu(); + return False; + } + subsystem_resource->explosionResourceID = res->resourceID; + return True; +} + + +//############################################################################ +//################ Class DemolitionPackDropper ######################## +//############################################################################ + +//############################################################################# +// Shared Data Support +// +DemolitionPackDropper::SharedData + DemolitionPackDropper::DefaultData( + DemolitionPackDropper::GetClassDerivations(), + DemolitionPackDropper::MessageHandlers, + DemolitionPackDropper::GetAttributeIndex(), + DemolitionPackDropper::StateCount + ); + +Derivation* DemolitionPackDropper::GetClassDerivations() +{ static Derivation classDerivations(RivetGun::GetClassDerivations(), "DemolitionPackDropper"); + return &classDerivations; +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + DemolitionPackDropper::DeathReset(int) +{ + // + //--------------------------------------------------- + // Make sure we are not firing and reset variables + //--------------------------------------------------- + // + Check(this); + SetSimulationState(Loading); + Check_Fpu(); +} + +//############################################################################# +// Construction And Destruction +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DemolitionPackDropper::DemolitionPackDropper( + VTV *owner, + int subsystem_ID, + SubsystemResource *sub_res, + SharedData &shared_data +) + : RivetGun(owner, subsystem_ID, sub_res, shared_data) +{ } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +DemolitionPackDropper::~DemolitionPackDropper() +{ + Check(this); + Check_Fpu(); +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + DemolitionPackDropper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +int + DemolitionPackDropper::Fire() +{ + Check(this); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // std::decrement ammoCount and reset the loadTime + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + --ammoCount; + timeToLoaded = loadTime; + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the entity and it's current position + // Add this to the siteTransform to determine + // where to shoot the rivet from + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + + Motion mine_motion; + CalcAmmoMotion(&mine_motion); + + // + //----------------------------- + // Move the rivet to the site + //----------------------------- + // + Origin mine_localOrigin; + CalcAmmoOrigin(&mine_localOrigin); + + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create a New Mine Whose properties are listed in the + // Resource File + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + VTV *vtv = GetEntity(); + Check(vtv); + DemolitionPack::MakeMessage + create_mine( + DemolitionPack::MakeMessageID, + sizeof(Rivet::MakeMessage), + (Entity::ClassID) DemolitionPack::DemolitionPackClassID, + DemolitionPackDropperClassID, + ammoVideoResourceID, + DemolitionPack::DefaultFlags, + mine_localOrigin, + mine_motion, + Motion::Identity, + vtv->GetEntityID() + ); + #if DEBUG_LEVEL>0 + DemolitionPack* my_mine = DemolitionPack::Make(&create_mine); + Register_Object(my_mine); + #else + DemolitionPack::Make(&create_mine); + #endif + Check_Fpu(); + return 1; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// CreateStreamedSubsystem +// +int + DemolitionPackDropper::CreateStreamedSubsystem( + NotationFile *model_file, + const char *model_name, + const char *subsystem_name, + SubsystemResource *subsystem_resource, + NotationFile *subsystem_file, + ResourceFile *resource_file, + const ResourceDirectories *directories + ) +{ + + if ( + !RivetGun::CreateStreamedSubsystem( + model_file, + model_name, + subsystem_name, + subsystem_resource, + subsystem_file, + resource_file, + directories + ) + ) + { + Check_Fpu(); + return False; + } + + subsystem_resource->subsystemModelSize = sizeof(*subsystem_resource); + subsystem_resource->classID = RegisteredClass::DemolitionPackDropperClassID; + + Check_Fpu(); + return True; +} diff --git a/RP/WEAPSYS.h b/RP/WEAPSYS.h new file mode 100644 index 0000000..f71e3a6 --- /dev/null +++ b/RP/WEAPSYS.h @@ -0,0 +1,548 @@ +#pragma once + +#include "vtvsub.h" +#include "..\munga\linmtrx.h" + +class Motion; + +//############################################################################ +//Generic Gun Subsystem Resource + +struct GenericGun__SubsystemResource : + public VTVSubsystem::SubsystemResource +{ + ResourceDescription::ResourceID ammoVideoResourceID; + + int + rearSiteIndex; +}; + +//############################################################################ +//############### Class Generic Gun ################################## +//############################################################################ + +class GenericGun: + public VTVSubsystem +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging Support +// +public: + enum { + ConfigureMappablesMessageID = VTVSubsystem::NextMessageID, + ChooseButtonMessageID, + NextMessageID + }; + + void + ConfigureMappablesMessageHandler( + ReceiverDataMessageOf *message + ); + void + ChooseButtonMessageHandler( + ReceiverDataMessageOf *message + ); + +protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Attribute Support +// +public: + enum { + TriggerStateAttributeID = VTVSubsystem::NextAttributeID, + PercentDoneAttributeID, + NextAttributeID + }; + +private: + static const IndexEntry AttributePointers[]; + +public: + //static AttributeIndexSet AttributeIndex + static AttributeIndexSet& GetAttributeIndex(); + +// +// public attribute std::declarations go here +// +public: + int + triggerState; + Scalar + percentDone; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + + enum { + Firing = VTVSubsystem::StateCount, + StateCount + }; + + typedef void (GenericGun::*Performance)(Scalar time_slice); + + void + GenericGunSimulation(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + virtual int + Fire() {std::cout<<"GenericGun::Fire() Should not be here!"< +#include "rpl4.h" +#pragma hdrstop + +#include "rpl4pb.h" +#include "..\munga_l4\l4splr.h" +#include "rpl4ver.h" +#include "..\munga\resver.h" +#include "..\munga\resource.h" +// added for game status drawing support +#include "..\munga\player.h" +#include "..\munga\mission.h" +#include "..\munga_l4\l4ctrl.h" +// end add +#include +#include +#include +#include + +#define SPOOL_SIZE 0x600000 + +//#define SCREEN_WIDTH 1024 +//#define SCREEN_HEIGHT 768 + +Byte version[3] = {MAJOR_DATA_VERSION, RELEASE_VERSION, MINOR_DATA_VERSION}; + +char* names[] = {"InitializingState", + "WaitingForEgg", + "LoadingMission", + "WaitingForLaunch", + "LaunchingMission", + "RunningMission", + "EndingMission", + "StoppingMission", + "SuspendingMission", + "ResumingMission", + "AbortingMission", + "CreatingMission", + "ApplicationStateCount"}; + +//########################################################################## +//################## RP4L4Application Globals ######################## +//########################################################################## + +extern const char* const ProgName; +const char* const ProgName = "rpl4"; +Application *rpl4App; +HWND hWnd; + +LRESULT CALLBACK WndProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + switch (uMsg) + { + case WM_CLOSE: + DestroyWindow(hWnd); + return 0; + case WM_DESTROY: + PostQuitMessage(0); + return 0; + } + return DefWindowProc(hWnd, uMsg, wParam, lParam); +} + +int WINAPI WinMain(HINSTANCE hInstance, HINSTANCE hPrevInstance, LPSTR lpCmdLine, int nShowCmd) +{ + char filename[50]; + strcpy_s(filename, 50, "rpl4.log"); + + std::ofstream logfile; + logfile.open(filename); + std::cout.rdbuf(logfile.rdbuf()); + + // load up our environment variables + //controls + if(getenv("L4CONTROLS") == NULL) + putenv("L4CONTROLS=KEYBOARD"); + if(getenv("DPLARG") == NULL) + putenv("DPLARG=1"); + if(getenv("L4DPLCFG") == NULL) + putenv("L4DPLCFG=RPDPL.INI"); + if(getenv("MULTISAMPLE") == NULL) + putenv("MULTISAMPLE=0"); + if(getenv("TARGETFPS") == NULL) + putenv("TARGETFPS=60"); + if(getenv("MAXPARTICLES") == NULL) + putenv("MAXPARTICLES=8192"); + FILE *file; + char line[1024]; + if (fopen_s(&file, "environ.ini", "r") == 0) + { + while (!feof(file)) + { + if (fgets(line, sizeof(line), file)) + { + for (int i = strlen(line); i >= 0; i--) + if (line[i] == '\n' || line[i] == '\r') + line[i] = 0; + putenv(line); + } + } + fclose(file); + } + + DEBUG_STREAM << "Red Planet v4.10" << std::endl << std::flush; + DEBUG_STREAM << "L4CONTROLS=" << getenv("L4CONTROLS") << std::endl << std::flush; + +// GetProcessAffinityMask(GetCurrentProcess(), + DWORD_PTR res = SetThreadAffinityMask(GetCurrentThread(), (DWORD_PTR)1); + if (res == 0) + { + DWORD err = GetLastError(); + DEBUG_STREAM << "Could not set thread affinity. Err Code = " << err << std::endl << std::flush; + } + + // + //---------------------------------------------------------------------- + // Parse command line for an egg notation file name + //---------------------------------------------------------------------- + // + int argc; + LPWSTR* argv = CommandLineToArgvW(GetCommandLineW(), &argc); + Logical run_application = RPL4Application::ParseCommandLine(argc, argv); + if (!run_application) + { + return 1; + } + else + { + Start_Registering(); + } + + // + //------------------------------------------------------------------------- + // Create our window. This is only temporary because this will move after + // the graphics are moved over. + //------------------------------------------------------------------------- + // + WNDCLASS wc; + + if (!hPrevInstance) + { + wc.style = 0; + wc.lpfnWndProc = (WNDPROC) WndProc; + wc.cbClsExtra = 0; + wc.cbWndExtra = 0; + wc.hInstance = hInstance; + wc.hIcon = LoadIcon((HINSTANCE) NULL, IDI_APPLICATION); + wc.hCursor = LoadCursor((HINSTANCE) NULL, IDC_ARROW); + wc.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH); + wc.lpszMenuName = NULL; + wc.lpszClassName = L"MainWndClass"; + + if (!RegisterClass(&wc)) + return FALSE; + } + + + DWORD wsStyle = WS_OVERLAPPED | WS_SYSMENU; + if (L4Application::GetFullscreen()) + wsStyle = WS_POPUP; + hWnd = CreateWindowEx(0, L"MainWndClass", L"RPL4", WS_OVERLAPPEDWINDOW, 0, 0, L4Application::GetScreenWidth(), L4Application::GetScreenHeight(), (HWND)NULL, (HMENU)NULL, hInstance, (LPVOID)NULL); + if (!hWnd) + return FALSE; + + ShowWindow(hWnd, nShowCmd); +#if !_DEBUG + ShowCursor(FALSE); +#endif + + // + //------------------------------------------------------------------------- + // Open the resource file. The brace will help correct the scoping problem + // of destruction the resource file + //------------------------------------------------------------------------- + // + { + StreamableResourceFile resources("rpl4.res", version); + Check(&resources); + + // + //---------------------------------------------- + // Create and initialize the application manager + //---------------------------------------------- + // + ApplicationManager* app_manager; + Application *new_app; + int review_mode = RPL4Application::GetMissionReviewMode(); + if (review_mode > 0) + { + MissionReviewApplicationManager *spool_mgr = new MissionReviewApplicationManager(hInstance, hWnd, atoi(getenv("TARGETFPS")), (review_mode == 2) ? 1 : 2, SPOOL_SIZE); + app_manager = spool_mgr; + Register_Object(app_manager); + + // + //------------------------------------------------------------------- + // Create and initialize the playback application if there is a spool + // file + //------------------------------------------------------------------- + // +#if 1 + CString spoolFileName = L4Application::GetSpoolFileName(); + if (!spoolFileName) + spoolFileName = "last.spl"; + + SpoolFile *spool = spool_mgr->GetStoredSpoolFile(spoolFileName); + if (spool) + { + new_app = new RPL4PlaybackApplication(hInstance, hWnd, &resources, spool); + } else + { + new_app = new RPL4IdleApplication(hInstance, hWnd, &resources); + } + + Register_Object(new_app); + app_manager->StartApplication(new_app); +#else + new_app = new RPL4PlaybackApplication(hInstance, hWnd, &resources, NULL); + Register_Object(new_app); + app_manager->StartApplication(new_app); +#endif + + // + //------------------------------------ + // Initialize the spooling application + //------------------------------------ + // + if (review_mode == 1) + { + new_app = new L4SpoolingApplication(hInstance, hWnd, &resources, RPL4); + Register_Object(new_app); + app_manager->StartApplication(new_app); + } + } + else + { + app_manager = new ApplicationManager(hInstance, hWnd, atoi(getenv("TARGETFPS"))); + Register_Object(app_manager); + + // + //-------------------------------------- + // Create and initialize the application + //-------------------------------------- + // + Application *new_app = new RPL4Application(hInstance, hWnd, &resources); + rpl4App = new_app; + Register_Object(new_app); + SetCursorPos(1680 / 2, 1050 / 2); + app_manager->StartApplication(new_app); + } + + // + //-------------------------- + // Run missions till we done + //-------------------------- + // + app_manager->RunMissions(); + rpl4App = NULL; + Unregister_Object(app_manager); + delete app_manager; + } + + ShowCursor(TRUE); + + Stop_Registering(); + return Exit_Code; +} diff --git a/RP_L4/RPL4.HPP b/RP_L4/RPL4.HPP new file mode 100644 index 0000000..6f031b9 --- /dev/null +++ b/RP_L4/RPL4.HPP @@ -0,0 +1,12 @@ +#if !defined(RPL4_HPP) +# define RPL4_HPP + +# if !defined(RP_HPP) +# include "..\RP\rp.hpp" +# endif + +# if !defined(MUNGAL4_HPP) +# include "..\MUNGA_L4\mungal4.hpp" +# endif + +#endif diff --git a/RP_L4/RPL4.RES b/RP_L4/RPL4.RES new file mode 100644 index 0000000000000000000000000000000000000000..4cfcc4d9e81b730fa9f59a1aa2384fac7ec21287 GIT binary patch literal 819872 zcmeF4d7Kp0)%VZrs{$@W6tq!MTv!xPM1kr7%otH|7Xx7iWt7M=vM3sjt;Q{)Aub5G zwTfHZa7p4$&oG)Xf+?BNJzb~1 zeeSvEu63)bq>M^Si0JMzqP}|*O@XY0d<+>ri0B+h2c+j<9E02i*#xnM5M2uS0Ma-V z-$SbRAvzV(2^qLAjzd0xG!DaYNcC_Whjc;)j=*uq2av}7a2!&-KaNB0g3OwZ&zBR8 z{}a)@JC;x?T|y^A9)WDrP(lkJ8z4;=l+dp4m(b53??F}#FC`jLN|PX~AiVAUNhvLW z@YaF-u75A3wPVX@)-^~pwzb&bd~F&1;<_?=88T#98SS*ZjHW?uhWrci*A->7`}JjX z3S4Dq~`4{B;$IIx{*URW$$g(%e=$bzvjqjGx zkKQYzmmvS%SVq%7D5E3qoROUr4*b>-CeH|5j>nfTjsYJ9YuuFsXzR&C`proEhQ?Z9tC#&nj` z3dk8Bl+)voJ3fSce=Dbjo6G5ANYlT{Y30}Dbn3U|bT6d5tb&>#FYjDI-`k~v%66@w zLkCpQOT#PZkP#Jh#eNlZzyTF>F65PiDrle46|`_d1w97&U`7RPXsMtRPOYH7oLND~ zEvlduXI0R_=Ty+oA@7`5L1Qu%G&5U4_d%B5QbB`mtDr|7s-V3duAoaEsh~B#t)Qw$ zD`?si74!sT@SiGZ9^^-FR?r=9LI0BqS_%2!?-g{-rxo-XWa#G=v=}mfn@ajEE_;*wC^sJbT_2mu9bAifJ(Y=_e%N{a_nA}^dMyIp_SBgVkLbI8Gd*r{qDp{8uP2H@;(%{87enlnSbY&&In60G7TPo>E2;Ejm9k*9f z^&OQo>+VYGg#6@pm9!diPiG~a_FN_X`;|&s_{U1RfmO6eV-;l~YY(ZS zp%bfU0pztKs%ZG6D*B`q-<^f;AWdiE^Ep*?(v?;82BdOH6>W8O6&(k8d}$T+zOIUX z`r9gMhur^Y6*W9wMGMzf(Z`UXFI3S%FIG_o^4^9jvR;8bpH8{T~t?1&p|%yQB4ziR#Vf^YFY_dvQIU2?psagjjN_FAV*E8rooNXG!Jss z#A=kEYU(q)nx;YynNv+~&8?>87gf_17gy8IAYGSKQ{T(MgJgbDO>aULKUhucAx}P3 zO|LytP1pRsn(CgfrX$u?)60LTrtht`&(+Yl-`CJ@A>-E8P>=OBbTs6imuskMLk;cxSq-&7j{3ZYp8cYR&aJAY&mgDP z)Y6mnwM1LgQmR)iodY>(Xf53dxq6>kdVb$p+VQ|zx)$>3LAA7QY%TS&YH8-UT6!BY zdOVInK7|}Ip_Vp6-afdN`W#kElObOn4*er*=`F}*$JNs86L9Y2TDlu@#Sft~1^-X2 zr2);g)CMV;UQ1IUH$uLG9B>l&kXIo4oLoz%L)JmIm;nZ4LQ5@O1Zh6AmVSK>&OaCD zLvDn81v%iSI3Mx~WS{eJKI9X~73bH|9v9$$$T~>+LU15&L!P>*mTE4kr6VEtK|X;T zaw+VGY=jKBtd?$pjQ)8ooeLRsc`cm%qAJwm{ZF(lkT~m`_3%vd2@k^bDlpY2-n!mPWMI z()p0LApP6nGsvfq8EfFv4x}G)J7gmy{S5N#S@;HW$nW46$VSM3PB0*Ckbci0A0UrG zzJe_LJ?wiPeprim_zUu*3%~O=e&Ze3^H-!7GV>!aA$xp`{QOrfeFK^BHF%KIzd@e= z8|j0*2>I$;*hqEs7UY1EI=T;XS!o@;2pLpXN4G#WLar^Zqfa3tD(dK$kcvtigM0{? zQB_AJTh!54Th>v!2Uw7PJ?m(|&ULiUu61-Sz-od@>sQF?IAdWa`*DdgTXobo!xn^cZBsMCe1#Kdg?PgA6#lj($C< zj&45^=RpoRs*aw5lpKw7AvZ$4g7iPOj%GqCj;o_)$Ysal+!N|hp1^^Oo(v}BEy!6X z;REtb>kXpi}@6|xTU`2zTCA<_&P zaR%%;6ShFoi(nVzfV04WtosQ#=iofZM#vuLB0Z3ekk>DQT!P=f6!t;-{~Ug2xg7q1 z^j};@6MhNy)pc|?q~aR*VHwi59C-;Dw4x624_hFkZ-ieVTijGfM?%&?X5NhRAS3R; zxp(1v$Ub-D^ZiH{Wb`WhF61r9a}VNoA404^4tW^A0U4A-I@;^#B1p*^_zH4Z2jT|u zDP+bo;6o~&g`JSkAus+8dEbe&Lq37bd=5;=)ZfEDko5Dg^AB~j@FnO%o_ZN+cm=jW z?t}Dt6}CgReGUGFRJ;y*Ah$yv`wQ}{3;u=lc^heY7aYiokgwi@T^o@W$mI873uMG! zVfR-^=Vqh_lKvXMS5i+0l-ARSkc-OdX&vO;@_Kp-(x;-H_Nl6;g^(8^y{hYJHsn4? zO-()BU5oP|7xk#8w;}y|LVx>u8r`>^E`w}@9I|6QUAt2~y#+ZSRZj!@*VE}c*VAK= zZFi}sXCS}cwVu9#oI3!=_J9qLKEv@n-^5MbtRB}i?oje1=?fd_6q}IqL-YVlo(z z7a`44>gje!$<%uK61 z^f^6k)?)1{?6LFNWkS1J(q=8zuE9RQE*IM9mw0T}V(mKjJJ0S4p_AGC9?$ikFZSW2MB5$n4 z+S_6u(5@BQy>UcnvleTAFRWcBw6~MAS&Oy%gthC1_V$uCYq9nY*gJCsuH9P*?Y@#W zYq55}u=ZG?y`!YfTCBZOSlbfXDM_2PSi3*=*x8%y!7YXM&iGFFgtb_E7wiMtJ%skI zk~V9x_JFW8+slc0!x$ERmP2#oCzo3YLaGLVKj7&04H|0QT6~n;j?H3+++(POw>v zwGYHTpuL08K1kALE!G|#*6u5`$4J_&#oA-T+WmyKC26x3Yp287I|}UvNt?A;dmQ$G z8e%7*JzmmgE!Lh8)=mlSgC%X&V(ssTwfhTgZX<*TS&Ov~!9Gw!>@2i@AZfD}Yabfc z-bH9nl(bokwGRtx?<%wpm$X@nwT}pE4-nduByHAW?IXk5y9w>1ByHAW?W4omy9@1O zByHAW?PJ5*1BLc+k~V9x_VLnpcEs)>v`>(Zuoi1i#y;ThJ%#p(k~V9x_7B6_dkO6+ zk~V9x_EhOR+mgM7_K&0^ti{^Xun)xGAfeqPX|on=?H7F_F2+*w)QBYeYSLjwOIQn z*avd{K%sq(q|I8aeQsF$Aff$JNt?A;n~z~YyZ;y&eN_C+E+>1ti{?_W6!xGv`a>dyu3!zW-ZpfHmp5HXfKttS&Ox=!yY@I zofg{5ByHAW?d8~Wttl)itrYdi3Q3!_So?bHWp-(m(7r*^W-Zpf(f!V2dt;KDByHAW z?VH2e-k2mSX|on<-xAjL#w52&+N{Oew_z{)yR=T!$SWmn)?)43-S0fRy)nrhk~V9x z_MKtvEx6_5IJryGW-ZpfJFLAW_Xb$|SCTesvGzUK2kh=4*!N1>ti{^*g|&NbgKwC9 zzogAtto?xdotMg9T>r85DoLBQSo^`S_EtjsAxWFHSo>k@19opM{QZce&04Je>#+7V zB9*_9v{{R_e~UeKe#Cm?hDRlB)?)3)!rI=r;c-cuwOIR!u(mgDcv8}4E!KVt`#>ta zal_M+Hfyo=>aeyqZpca6ti{@G*kk9X(i=ClOWLf(+H1nv-ngMd(q=8zeg^w;_j|i$ z^TrL&O4_W&+P}jdJKvI&$jeSio3&W`IqaFuo6Yt{(Z9zx9BaI>7HdC`eL&l*tJdO( z&}J>xUKiGGI1k@&#J(VDvleUrA*}87tJX`}ti{?dhPA!c^(9H0wOIS*u=WID$p%TA zwOIR=u=c@1`;U?~Yq9pLVeRh=?bjr2)?)3~!`h8P`wdB(wOIR4VeLbN_M4J6Yq9oQ zVeKCX?LSM}ti{@Y32PrJw7Vp2)?)3q!`c&t_B)a`Yq9pbVeP|&_Ir{xYq9o5?73X> zX2;;+Li>GuBch76So^Qo2egk6+8;>Tti{?NhP5XN?Y~Ldti{?Ng|&|q+8;~Wti{@& zgtd%!X2Lc3nlW-ZpTYop1L(LVGJoo3&Vb>#+8|LVFuYo3&Vb+pxAb zita6GvleTA&;1TNr}pti(c4Mdti{@Wun*+CH;Ud~(q=8z-XW~*jiUQX+N{Oe{lePb zC>o3PyohBj*4_zw?0gS;qv({R&04J8KdkMIqIZ_GS&OxI32S?!=v^gk)?)1e*avE4 zZxp?oq|I8ay?a>O8$}P4v{{R__XulyBd|Lw1Gi4H*g<2^j_14YD7E&)W~|TI`R390i#K z`2l1iq#4#k0xO8yLb0qWk2e{vJta1c$ zT=Dm#u&={~p49&KDruKjdED2FM>FuR-2`a36_#K3$M^ zAn!q#aS#}sM(!{C4Z>~v-yz%%bL;vUkP;u z$XSqj2j@5 zknchG+<9}GPvUy0&?fj9iO+30k4|_*!6OzPd+=CkWh^XARP=RzA)?ae}`M8wZ-_>%iqY(Mv&xu3=T zV(!0ke~bIH+v6w~ACCK1%(t*lLmD6lL&ibA59y0z*wOR_3uaB9SGbO59p0KG zej~p80fhZ?C}bk!FvyXR!y!jO&@FTP)4X7A;plX9n4gpQKgRj9Agz$ukU5aKkOh#_ zAqycpy8QXAGZ#dP|NVUboPqNfL70CQ5Ofn*>%xqQU`$QY-a5=vi%u} ze?HE?5W@VQK`w$^4EZ_a63FF{l;F>7Z7ouKJ${$OUySpwgfRaXkR^~`Lav2e1z8H| z@A79i&si{YKK?1NLDk-@{T=`C|Igyj&e-$klbUDGnAdEpz=|JVUj0R>cDw${-PK{+=lzLZ-}my;C{FHl%eMGGI&0eiD~q_;pzSY( zMV;nYnHueONU_T*GsmLM=F&)Sn`31@(Pk-iq19KrP3segFT`g8mSPw6*0xJ&hjKl% zV?t?%xbhHux8t*vShYrI`+iRmtHM3h+~Iw+KSb|ODD?yl(Pj-*?CPz} zQtfIq$U0k_rS|2PYWL+-R--nHAFIS;7-zFA%A`;QfcY&sYbcW&hkl`(kMUzwt?wJP%XTpC?@iMx{W-paMH=k_owX?YNG#t^lPZEe_;a1~ z1ufN1qw23tZI&9VXU9sTeBDZAH5z2;+oi^Rv$kC-OW!WlU-~hjvP{N=Nq?D)3H`cI znS0DUp&b(niyqKsDP=oznKny_i3BXgt_1a$Vi)O;ta!*fsL`2KwN*hOVRZuT4)BEaL0Qs~TwieC_!YWz5iYoHon1Ywxj? zySah7rfakI^wP*Ng)KEnn@!gK1J@O5`5A~+@{L8nlC zh~>H7#`Uee@Y|j{u`J3xH_kg~f5?oTJ7-4ltI&VEmI^Dp;2)fyS)-g!c+z!|W4Xe| zTH6XAvz*_f^?81eoZriT%wgs|wxr;(#YkZse;&Bkb?75hrzelzt^udgkozm2=KZQ? z&mDW_%sE&=Sa>VJp*DgAbZNbXH!W-LC?EJX49JTCf+m_>NcCc;vaAVCF{`H!B z>^vG-*b-;GVX^b$+VarGYha6I<-T<0zn1KGq;1Rf%g<)NU`27^jr~&W{J6Gk-h8cX zOX~Vj7XRw>iJ$T94D`l3b{=7MeBq64DRzEbTlU|B%aLV0Ie2iIfAzIPudrjcw8t6j z7pz1tys<6C&W~%$XZLX)Rj2ou?Ud=#E9cm@yzrS_j7iy6|g@(TJXh&l4eq>L$6JRjv_rz16`ie~aFi_+hDNgWR*59@SQRXu3G%BpzKV4S*zJ$VR;<9h2ZMCzH9$&$J9L~<{ter;h z`tPb6+fe2jG6(Iioko>)kU`eL$yt<5a~df(Cb_=^i-v2nylV^8w;ip&g}Zj`xYrrK z_^e6D$1aOn`?+N(eyn=eVnkr3cGND93ae>*ZPv7KUD&miHcKf(R$pyac&y!Y$3$(G zGC!0#P@AR9*Ct>ocIDFAb}7D($tpZPM!;^+4N!d7*!QtBm!d_I>Ag`Itp}b^@-wuSsl|Gp_-==<_wANpkkl`-Q>l6kzeS zTYHNiU%_>{VC8DvG{$EM-(w=w@qOl2b7`a#s{u#^o(~{iU+H zEQb`o&Qbbb)+{%T@mc=3qcd&S)45$b

t=Mr}J3yE4ZZWF4r@Qu-4aeU_3&>q3Ke z>HAB~M=^F6xfwklRo1cEX;fHU2K|-m5vwm(eB5#Acw^-;CDv`lFON#BW-l;jR|1yO zU+wD9jtQlY+4TnlEY3ajS5tqqSvqqtN*bG9)V51y{Y{&tj2|;KvEp8y+g4b#S=%lp zR;@B^yA+nmG$ybsJVvH!;rsYy`*d$?HL0znX~#CornLR#kGC;ji19Y9*Pkz3DA{G# zfvG;)b}4D39kf}BT?yt36;^_I0A-B=>EHJw?s+fGoR?$Yrv^E5$aX&1f1n~5 zguYxdmQsIN_l$RJiXZn1D|eGN%Uiomk2K(!^`S8bTNvG6XL)h&oQM8zjz9TZbe5XN z-)g5(y00H;+MCWc!P*fl|nXPWkl7Cm?e!X%!o{fwf zgTBT8QTv2HFBR(*%iFn+Pd)3j`w~~WtkTT>7M}Hxrc2j?$(!Ggj%t^}+WF%(x-4Z5 zY<<584om!v-p-0PyCk>LvfH5_--@%|m1Oz3wb)ko&>nLO7W%1< z?=zohr}0M5_dkPOT{+4fY%YyIeZsXXeoRR7wU+HKtFN|QQh7|wl48|mjnK|Vzi-d| z#YfYWo8Mul)%z2@JW8xwQkL(pE+>r%>{3}LYNyeUiR5;9ac^CUxc?IO;ia|X%VTAZ zKzU5Y^7E1H!ZUfiYkeXpbYj9~dDrLSv%EBtTTe8duk9}-jo$i#_;&d*K~Ah%r)b-y zuu>UqmLK=7UD?IvSP9ao*p(oSTb7ExoSVknd^e5p>-)m2_%WfxYVKrh->b2zzurgf zGfmaDONrG4&oWkGA^}UaOSF#(@=?^Qt=nk#3%!^S^?d@?&4IYz)P^yPwq3UdSeQdj zzzW(0*3d1r?FzE$+i6pkHY=D$u-2Drvx0VE{J5&b5DV9@jM+7%ow~lzF55wWA&seT zv{^xaH5z0gjoD4wcHJ3>`(&)3zgpX9QZGX>0lS+1rk%#1@4-sFXNc7b-@j^zwHS6i zugwbj{(?lTpufOsdeM+w9ABpV1y1obFA#s+N@xCgk8p1CgUD95fV+Qs#RzVCyv%JH>a+h4($ zK>O&8(~`y)?CQEo+peI$&<8MP7g$XfYugp{7y5Du#(cpvg5`}xllmTg-`t7XX$;y0 zmN(vxZozKJ)siq8uA9xP*Hn5@A*6YTQl(&DF49gCK^`51rv_^Uu46X&mb${Z^} zpZtNaT?yLShr+A`eN2_5KkiU`KS{Jh@$*r+C&qi9L41}JU(U%1#tM%rzSnPu6jp+H zfS~UeVGdcewekI>#A*VT8ejV34xe=b=G?I*7>g>b1oHrjzr6leeBVp=Kw9?o?F7$= zS6GC4Ieu%QE3-lSx~R(1zwR#8Iq(;@1a?XHpMuqi zYeX#a7Cj#oR&Jo1kMY}W=^k6xE{xRzTXefr){r#;RE+piSeeTVvYs%=`otV7*TX=0 z>_R?b%jsXQ_2XW!(%N?U*I{_AC0{Ey!g8;>n`G(xOHHFb%e&rTKTni$7XG)>&I(wWQXWpOa^@JZ^WI3mAZtyVnhv+Q7zIS6a!LwHsR@24W{t|1DO0xXi z#jKUN;6|4fzm67b$tcsSou8kWd(L6$+{>CP71w^*U-b=`Up1G;cWyD4#v!-bES)qe z(vBtFR|P->Oa3oVI_Eek;HP+n1IzU5cgckEY*&C z|DHZK9~0Qs5wQJK$4Fu$s>63kgCER*xmM(4luue+;h)SoYW&TAjZvcqY;zFmI*-X`JI zBKqr16jp+JGW_d9_WP|Yy6b9p9ZdZ4sIV?wqRm?C`F?nV?XgwE%(0dXP0q^v*_nIs z>~ixpMxEoOQLsF_;GdVd2gTC819_$+?6LNeA+&o1{}-fmr})Bp0XopiR_twjRX zN1k1cPCJx<<=6La8|KybNy?+k^6H%U?V}%G{{fa)9^>2Pmm&Au1T4RObXj@oulUb= zzeru>>4nRntnIljS_bky{{SN*>_yml?8vm{;$xp+SdK@_0=zA-c9#- zXKy9Wx_j?$Pmo`0Jv4p7o14>ZKN9EjGew+@kIlWhSHtXP^_aEoU&r!!g^uxg{Z3ZT z`}sY++W5Re$N0Q;E$Vq)eY5s?g^uxg=gw5mBU*{|FL)kC(;(4ad+D>^XIJpp`ds1j zaNk40^Y~a-f!||hp<`WE;bWYJ{O2u3R>g^z@1E_K|Cxuy-b;*U*nRh2^fp#ub?v3i^5<$PSCae6qNbf(R{TD>*T12=P?u-Y)N`D+T?%W7rOn!e{zg3n zQ}^(FE3c2%X8ChzUm}gjM~@ZXUxisBGNQ+XzwVLK2)h!z%k#=o*I!MSA&vD7xySVV z<*_o)z%H2;-(Q~zyIOx~+tt*rZ(i@VqFF!(=(x<~(cb!T}o!FdT*W}fy~+kZcj1)H!*yWEG#L4=0sjLUIeXp_}(Pnw~Z!PJA=dL`Srf2W7S-5_JauDx*I^NhL z*UO3fISxx_t%7G4_az8phSa0NE_;qH&U=0o7OmE1T_EbOOnn>I6S?i3`&e|YHz}-9 zzty&DjA!0itaC!)!81T zMQ15}%&sywjq&>?id~rv2K}Yq_f_noPJ?!xZIIPykfncbrsA*6W!iSB z-_JS48+Y(r8s<%Mw`td3rw3S=`%T@X%~I^jEYoHwb|tv)TCvNz!kk^%OSD;vU37sq zOYv83kv2=QD>K_1i(b-ZDQRq4tIbl6<=>Aq31fF`)`jL+xnG!LSvQzt;eE?q zHE4f`UKfh_iIS$1+i3m8X*j zZ!S&D7asg;k;dfng?|_GnDNKRN}FafjTb*?E{%g7md>20lE$1fU+Bkv^tkuu@7dS< z?7KI|`5gYF!{YP6%JkM|`E_9v>aP@H|5a^PFRwqrcJbD!&61w^2oBq|!+0C%{fX`` zl{MTT>o9GWKVO(Z`mkm6-*f4+nj99rr|o<7I&!I-#`yJw8WWqf?efzo);>D#6Bzo=0=jjF%&eXpi* zslj~IXDN1NR%_d(uoBewYCH5RZM#nQ$~L!YS@h*{+AJj|63iFg>Dh&6x#qA|VSPXC zbwmD|Ejx`C^&IK4;@3HT{l(WZa~5TG)@J$75^>Ymx{Y=k71q!#wONYqC-u^1DRynD z(q<`kC3u&*!dhRhZI_b9RVCUi#jYja(`G4lZAzJAt=e9jrPLF&xg*#@M(?kx^{PJ0 zFWas)Dbh}(^sK;~L;KuKWBfWtUe6C!nyfNyyEd1&>nCiZHYKXR{Cu=5XMMW)2m5UYQi<_UZh-cKYF8^_L*AmZRJ%4It@0L~rP_u2 z`U6`M*3yOmD#jdZo-}H+l(?t!w9{B$Ciiu?Y(L?$;@4k_?=$ym+ohy2^SU;xmlyXU z_w=v5D|XSiHG=BwqsP~ko?Yv5c3rs5=`Jh2@4b5|GM_lCpSNnWe7ml;f_6D6L>mx! zp3iTGEUUYSAzSJz2}I~2bddLGLABbbqI@`eRO|Cd5*}Wl6cRB znAz`@(dWKd+HlLF0ZOcP_Z*RGB;deb%}v|qe>qgd)L4!Y0a z?w*epJl5}(>s+RKUcXmfEqLtRJ(sym)y{YK{Gi~m#Yjw8@MvoU>E^T{)$`X&4k)w;c%^CzOAjC&^mxZ|w5acb`20b$QHv0O(?pWEJ&C1ji9Xk%aW+f2|wy<4W zp`bX=ps)|4>ri}+?xTC$LN+fC%NwKh?Pv#RG%dcO!=(y%pkJ~HtS$&|VY?Jo{pCej zYmqq<_sq}g?WGa#1?MfBby@lQar|tq8=|tht}ANSYv6PiV0me@-|L#SU|3Psz`Y9l zzK@s2>vP=yqsHRzoI8Bs?CCS+A)(j``d--Ot?kV3uSa0lN=QDI5?@sOo-$-3ZEKTM zyHr;3al+cWZlmh1UqrR5sPCVFf3tf>P2-U9ZW7#Gux!5v4yTj1udk?;awu3}sS(g^I zs}&rsTl2B<_`WDBR=rBiMOi(EAbl*@!v5;#m2LYl{+wNuHEZokTJqdVTRF^<#>Z*r zx`N2Z{AIfpHmxjRmsfxF%{18c{k`YAcI9W4z@l^9B!ul!SRY?flvO|U7TUBfe;Pg3 z$P?OayY4FPuU3@DbKc4y6AJ5^3thY1goMW0j~;ZZIH2UCW{VE zpX(;>i^Xbi{TJE}?|zv4`S>L4x);J*I3E?3_iT69&XB)o-@>05Dt@2No8YXC%qo7L&NV1R!-qvpWAXcRIE|M^ zW);6rhwGcenitsJ=k9%9{5~D7zqaE{#1>{r?}@`vgIjReejDb z!Q-v4UAQL7c3I+nWLq77g0cF6%jt&I=A?1QqH)jpIB7(8cJVL4u2iNd>msx@mlj~D z?ISbgEttj<92yQDZ()C_tWMO`@)l%q8i((fKaGC9%GY4HY!|-{FbkY11z6ttds+n+ z^V~6mXIjv%V^QZkS%Bq_JH+*p#-eHb8k`dMcf$TsS@mli)%^1z68b;II1VsTWKbxTpZI>33P082?@H!O~=6Wjm``~KhfK2T3s z9~ZTY^G|GHmSR`#FGX2P4k{e?N=$Ua`Wmba5Z=1AtDEw;4H(Ca&d*ZY+TKOeIMJ;m z^4X=by1&0;Q-Sj6w`rYe{w>P>%C#$hT`1;5^Vy}ax>glUBi9p?3)tn~W8n7XyfT#E zu1CidjtPb3)f4$y#p($qjZIG#P2-fYg~wJ3EA`u=zUO*k6?pl4FQu`~>8}+kQE|W(V6Z zA8xF{8e5{8d(LIQjO5RSHug)g^JTwq-|{{_0b3!z{I}MeuogTxer-vGZlW@b%_vT~Hyv{I}lia?TG>-$HmRWXosw@wKt) z^d7Ufv*V@o$~ks9df_v>9PRHWCGU>?QtbTQah%tj%sT7rSIS*L+G8{=^2Ke-+NX2Ez7pj4p*-2e}@y3~~cx zZwP*dPG8tO?=LteG%iSLU)Uz)mtYC6MEAXFmzYyEVV6EjwM)#;ny^c-;`>XDRWW}S-!7#* z()HtnMb18YK1!^dbFMy1t-p%T>&Z5U%j1@A``FSlr@f_Rt2Uw*JB>Qex|3PMhAjtc zh!K`!*Phxe`PxfMOAF=?imy*B=C2h}f5KrkYR80Xmp)7KeM2Z8S95yeyk|pZh4L{G zE0mA1S!&$t=cE5z|3!#XtZ&bhyZIQuo{(5*&yul%^%t+32yfBr9DlC&5%lrH&tqb4 zbXKswXS+JvgO(*>6<=R1|4z96Qtc|f?mHf36o zm6~df)pVM+$1WTIb;O2@|}# zKw`Dor6vJONu&3^6a#5YE!XzFlEwrqF?P4x4bDgF7HzvE7JQ$KB|Wnc+1LbL?{T6Q zboSBv7|W69SjhuQ#l6;GHlEE5Ums6jp+FDk!W>ja`OBz9)+NTn}?Bw=Ohdm(|yt zUEVu%gk=fJqtQBNh`BUcBh0Zf2Wqp1mU-6#;B3BTc#U?ws|@_i9CB?NOA)jMomm!Y)VM`)hEwEOD<^ z_pD(>S$wY-+s0d%wXf0+eN(hNIuz$`n3WD(9~#<5DgF9hVP#)6XIInT%&}4i{gvRI ze2Tvkyem*)C3wf2!s=PPJjRNz)py<4farZ2v)%~H}xjoPgK0pG)}J0@zge(JF>7marfH9dQ(!qT{J(P6zY z*Jb(hU--Gmb721S6I|Q!@S@JA#eIH)6jFAbFZu-hJ=fd(`~+wFBj&-vTeRmV*za1g zpE2k@`^dv^Upbe<({{klcWepfkqREeIo%$^`SQlU=P~mf^K8j?%yNHEIVSf#-h;$Y$^8q1C!5Bh+@ls>-h;$Y$^8q1EbGRkc=r5FaNFQCrG9gtP4b+`ak{r zgebO%KKYY_2d7zI^r=gGoWaj>*jHwRKbPQ(V&}&#)5V^D09z70KVcAT<>x2NU9ezo zI34o;oF?At$Cc1AsOcu)3yn6dq0qhfnr&J^Ueq@2yL<7Se2wa_V1EwhCb$=0dH!VT z7vmjk{Ju_9yABSFA+he!X89cE7Go9e|Kh|1_w@&_e%v>{5Jhv!eUHs9jzfeO}ZwDt6f{pVM7T$aeY9v!-^UFVjwZF+ps>`62Nw@44;G z&-$Q^Xe&2X-gTyM<>q4o7GGF#o?p}xngW> zjGvDZ3-y;VmSYz!HfNU^mSb1$B6D_`VY&V~&zxOkgyqGC>+M4{F<`q%rfZHcLvQ<>ce%+G$kk`&?~@Zazxw5Mm3P)!$_~#5iS0VmUFI zfThgAWc2UDQ|3BsmLKz+(x~mWYM1_fc&c5@(z8pMOUvlnrOc%TSdM-A{?flcQ1utH zO!-USF4bQ$E2+Qq?^{&;#Vk|)(zi?Xm&{7&uLSo~D*m!rhWwSlF2!E~Ry=O zd^Eul`DlXW=3}6(O_+~HSZ+QVVY&HegyrU=5tf^e30Ttg4rdP8>Z?7jl~|Zx>cpI= z5td_DZlF24%&=U4jWB1IWrXGWD{aoMZrO&R^?GxT>^qE4a&&+b%MO*d=jV?&vIjRMwn z-J|U<)viai?Mesym9?nJ6st8&T^-tXDQQf=QheX^qCvafGRI1APoGqVa9sgqi2kZ= zmsGaF%2<^BSevEPIo@-E;@1<(d)*T}vqPE3v{}AQTz^EZzZAO?JpV(vMv;J}&WVa= zM{(-n&50`hvhC9Imtt4o87B$tvRQg|^$XY00lRFUjg1-;o4k4z^&p{MCFhw|OmVj8 zbB~I@0?%EpbNnntCb2-wA>=rN(N z5$;|6EJo_hL&F&~#j-lC6Te1Ez5XoThFqY;*yk49K-J{n=U<WxAC1`M=A#joXdjKFvE9CR zJ}}pz>wD2Y>d$rfF(KMV6D-j_nqZ0c(FDuQMqY0L1ANA*R{4(U0$H1HwM}xyuc(%1-ml>90*QyfjYlezlW>}70>&wmAWrpS0)w+#2yUeg0yOw;-RI~FEcF1u1yD+v&#(2v8(53b9R|wId%=T%-Lmz<=8c8oH@J9 zupGNu4>o6)8J1($l0(edm4Kx@lO(XVfNQDfb1=$!lbGu#ia#sZ)Vnf>lDsQJ@mGR( zWhnl#S$gYD!uJIvdGCh8djBZxSe2dwj<_G*VD23rVC8w|MhPM|>YBOWJ3R99qO$&T z@9@C$f`{&|_xpXJccynKem|s_s8L*w{gGfyLWha?(jYo^2>Mc@W>x8-@U^lzh8>IgX90wJ3I!X zX94ufmrPK~97`40#0dYsh1e-#{LR41peY zG=0`-3+BzihXNbx@HXZB5*mm-^Pj+%PeJa-=cln>4aq?|AZ?ImAY2Dx$Nc%Nr{P0^ zjdgf?(&hgPpQE;WHKpSI&EXC9{dMcNo?yegKhgV-{(I$_m9Z!ROR}q7w(HaK5qQfA z(dXDlO`~KNSjp@fRVw_&R%9)jw1e$09lI3P(0+ooI&K<&=-uPB%Q!?@1GVlnVgBgd zSHFDu&&RBXoH=^;$o>klkVZ4CH6gp6hFwo<+67j?t^}-!4US#A8Sodg*e)Zi_K;mk z(g;?-t^_QOua_FAXCL<0Si~2z62uo`)eH+U5wL4aviJ(v6`M7=Owy_mvoBTVk~{YhC@$+Ho(jY`d71G>t@yVOM=SWqVB!eVn*`6JZxvu*(#S zt+)Vd{4QwO;k@VixLq8ekxe^=Kc#vih=JV_DcXJ-h1Brg^N@ z-+cS+m~!yG#6D^o{XS-E+U^6uE>5k#MepBBthOM_pYx1rSB2L;vL#uI{pH)lpQ76p zWTkB1>#~lIU{}=lJMs%CtLq#~h7G&TqRh@p8WA7LSdHg-_$=Pb>w->^Y%9bI`@axt z69UqCzfj{idu}g+|0A&0m}7OKJYvoG|eP z3YBe%)nJarR-o;MU8w(xw%y&^#pTf$3;s&Rnl07Q$j9`$DV5s!xEaoI>S*>?%AzL0 zD%{={@|SYm(<;-pOL_JJZ641S`kUHz7qV++z+ZQzhs`I~uJ~z8m&*RKEJ_KMuuR{s z70bWXPGhr|Mt+A6HtP$Q6+exq`K&fxW7P8OKMkrBSgf^Tjy%x8uwYDRw1bsdjY~wW|b1JL^!? zn3xu*a}cYUdy2BC7Ee{$e65{7;e0$MP#(de9z|KH>ql9_pJA4gM!UZww0R%wM?X1u zuw6&+kuWRRmt(uaTad*^OM9G=x1P{>Pv;AtEy~MM)A)FM&@$C7aXg&HJicEebe(;4 zR-Ty9W+`dRe4)+CQ--uzie1(=9lHKf>`K5=?HXjzE`642*TDwu(r2l5O*3ehKFjZ$ zpkLzjONvZfqs_|GmovcPG}?VRZPr4s9kQ9w2g*99kN-WqFp-qd% zg73NQm_JTZ$H(aPs$!QJmTOn>wpO;eTYq)aZbxJZyR_?Q)n7eKutYwZV70k1VS?q@ zmAS_R%dsl~>lCj%a&B*eZLQm2EI*SCEt}jalu!TpoXE$Arpi)n?_H zQ*i5h;kW2@;kJSJ;<O7I>Zg+==B-ceYYTTS@Ovi+5SrPxIe zXxpW*GEZo;l$c1sQtYBmZMzg!W`j0MnJ;YmlQv7Si{92|NxpaDD*;QXb26W}cE#^U z2j>B}&f2V>#xnUjpMBlR0Lz&Z#WgT(mVXV5(}&H{e|C&?{{!0Co@v}m@r(l%f1}s; z()|x$W%#}fmlZ!BCA-=U+67iJyZp6j?4K;(mtm(-tb53}=0SKe+$UF9L!IYwi1m+g zSb47DYv-dQ&Ci-9&sP@IA9QAC0gYLUysgH18qed#(a@#b${$ZsHyf ztee-4FNtNRky)nh4Zyu8&m_Nx=v3t6%Ji^zw_>}V=5iGGo(2Ct7G^DPFvGgQvFqrq z4cNsj*ky#Z#Ib9Q3A>mDyArU%@x?Krdyj{dj}0OwblagI%ZZ8PtP32wkdJ0qPD~_c zEphBZKAK@UF`>&6F(KWn^Ni^Caz86he^p{3jl6camjM=AfxOIY&9}Al{V-#AUkZuZ zFZAtV7TPo#V8AZ#ULD&m*S4qi?DFo_VOG+6b=vGPjQ0%x_~SHx4CCGRqupN(-d~fo zaIcObmVK{|HY?A)Ixfrim(IO9w(s*iD<5&8+^fUU$Xj>}Dc`G8h!-{XH{pjv_v&c- z%x5h{pB3x766B@NYBb2=_5AjIKL*n1vW%qBWhHpmitn$^c7thjSZ31bu#BXUOND*k zkAZx2S$WE2{4(USjQGoC8S_^L>nM9@`zu!}>It?hYvCRuZI<8OE=Ek$qaRSk?XA6* zis{Mv6ed_~1^N`Q%Wbz4^eMP(8)Ly=$yooHXVK*_7iU@QwcwT+8|_(i+>gNdxgN^= zxE*VSkL3!V$Los=G2P#@`WF7Z{KuT%%X`fIy*$Sj!zpD!$JqaIyZ+s?=v2oP^2>M6 zqRSsI-#v>izhC};c^2J1C_?-!y6Fq&%~_xpC+{1yW%kzhuO)QNVMG=9Zv(!31@aQ) zRmdM9`{H}-=;V24^2dT3>+tr$@KV|id*<<@>gGabL0Td6Aj2RwZ^rDo#ejl0a)iU< zXW4xW`8$L=8~+2@1o;&5IpiOZFCcs)1D|_l^L+lvf}7x93O+w8kJm#-?c@2+m}h(^ zo*l4ZJbx1XmN@ejM(9=vy-13|QFJLSYZn?fV{wcOLuNcr~!i}U4u zbe8mN-v;~o>#FT1I3$1k9M$*zkWao{NMoLRl_vpSsEvKS%1;C5yYt+Plw;SD{;pj@ zC&SNGi5wTwbAk)}052COl z+<#k$6?~6+CLOfPiP@<6sIUTd#bX7p%fnx;??pP|tYuVK34E`x0%>IHqSqC{XPv|M zfi%YRm%<99F(E6E#&|4$%*)r0QmCij8!yTadn-=+A+b>BBx8M6D(Y6dK7?%_+3gzJ zUcJHE&>C+y{; z@Yn4I?YiC|>z4*uml$Mqf3J9S-?tdF>nMY)F$P(CYP0tAVwF9L`9JUZ6!Ghc{$W;x z=Tj8QM}U&Y=nDG6r+A*P|F~Tz?3Z+r?efQ6& zD8y3yl@ZUUFyOBQ&y-O8C7uHzQWCx0R{f>VQv5}YZcLc)*ARp8)mxk8uTv(B6VT7e z)M&GUzF)=HXtY_PFW1sC2lWm5g_)fVv9kQEL~Yh}UcZoI6ZL%pe@T5`v>TkpEx8|U zuLWj$qJDG&mhe4nYQWeBwv}r8E4bDlX{3+FaoYSXdfDD8;CqZ8X|q9Ar$N?IgDigT zsJtcdS10mQ-lDVej7258ocb{8ct~Z*zE8@MeV>#i`#vd4_I*5-G6zHY{!&@`{!&@` z{!&@`{>n37XveCUqli}8z&9EHbn_)S=*J1hn34Y!}Pt?(JOmN*3z0L`? zLyHr!f_)S8bLc3k{)%Up-=^`sa3f*Y*)Gc|*G!9A7pkn@+IIQ(G%j`P`OUCR@4Ak} zvKeS=-8~a|i=K}X%dsnS*%~GwzU;nEobo8K9D7_A?D6_dQGGA5T)S=+c8z8G^z7Q~ zvYxP6%yBjye+_YBA+tf)mB3%kF6$H5t_1$dT;{N>vJR0t{WLoDDN%0&EYTm-XZiJ) zXcsrT{t_vTo{t_&_{+^lL5fp`JeF6Vb|$xrM0`1MpUf`NUh{fcdDHRN1}DDqtf7ip zwmpAkK1s|9-ghpiO?-}?#^AHr20FG0jJ=P}I=EC^?+}2x5HC7wqsOX8{e^qQTln2{ z@}|XVH^<_88BEzVC9z%peVg2u;4Rf4`b+#@oVG(^p+CW!KI^At;h1oU{@>{Nc)rJK zbYtOxH9m(wMQ8oYW4V2$OpSJZug3j&*FIrgbi2ZFj}k;?5pDH9YsTCV4)dYTGsJVW;n_<9m@t%A8@d zD0jDZ8U<_J#0y;3s>H0879OW@to~M;C4Aq~auu`S`{$GU-nzrKYuLlixHggRt@~^i z<^Gg7jYPk)(}=l_HM(U;_zTy_T~>XEZoklH@wgV(tw^6G;tO>&>Qj_$zmB$_>8@Ev z+bpS$j?EHjbe<^@sH0;)pF*S&bu?ljP)EnM%V%w6v!psYHcO-t`Nu5eW21;Key7uz z(ir!5hwVar0cNtcwxz}K*NVxPX|qHc{d~M?4W7X<<_tVHgWu)*MvQlTiZr&gTM-E@->10@4IB2F zwq3&aE0*_bU=~?_Nz6jMWwX{zd_OS@^_I{f~L_EZqdz4si8cnbo z-B{JX79iQ>=A#Lg@VyBZ$0+Bc36?0^ookZEgz&uy7GKk`!uLk(a^p+?+MFL> z!uKXv!uKXv!uKXvqK?+TF6#SBv>hf`!uKXv!uKXv!e2w|w$?9`TJ4Y zUnW@WA)b4b+wFLB?oxcA&N0S99c_vw(%860YG>{B7#jUAH;qPEZW>LnI40O%a+{Vk zA5E}??@h2cMop!W%cC7%YuG|()Ag6|z1%+PvbgOqWf!N)6syzqm)xf5rcwCb1WWkd z1WWkd1dH1t_PyMu>H16f-ULhd-ULhd-ULhdOK#JW`pX1M_{#)K_)DL)vD8^3(sFS1 zc=Ye_tg2eOpCh$vk+0V(EX$ee&|!V%+Qs*qw6yRV9cNAuP5hw zws>qcK)a9Wv-n;zQ!Kv6Eg8$tN4D#nM85adM`sQMt1s@6+PZ^VB*aAQwXprloVZ7Q z3Krjsg zahfTXcvhEzGKrbQ;u@G=7C8^1wjCbJE|1KT{v-I0E)h^lhns(W7 zZ|Hih$1>nAk7Y8Aa(UGBm;EeDQ!&A1$ca^{evZ}8@nb@;O!$k-qhlA^9@`#KheeHh zukG;aRna~QQuMmeOQRPPGAmv_di{yi8(im@=}!n&g8qb;M&joUH@5rz3Fq2Xoa+jL zweIUbVJo3hJgnXs$rQP-}49kzYmpXmAMr7`=oIhL@?#Pf!PT?trT+}r&L zc9I;c{C{+R`7Add6R<=*LEac9#p7+SzK>H+_^c-|U%1#JI=}!+^b1Yc#r;C=W9r`% ztETaNZ*3>%qMpA*8ujfG_ihc_dJU%$ZQ46)*dCpGqy%fl>m4?0-P#YeS;Ai{`uxuJ z{fgz^B)=ED=UUsY6_cH3i6u!Rt>^bDz+YXJ9ZCHqSS`Cb*SBF;?E8L&@5xQ$x_g~^ zRfiS!{jgz!#Jz4~aewV^^>+{;F3`*lFZ`bX5n}^BB8$T90MNsv(vgtI1g2dQ97{WNQn& zH4pYXDS6FC_GPOo`-2!sjp`0^@amu7!E+hNPTQ?+Fw7pxl1ugpggg3vM zW4kc6%G8@=I>YSY0LT z!seC7`0b;@^2(z=i|YxyF0{7PEc0GB3K^v%eKez z%42+%-zVqscCvo7$Fj$1hFJDEEg8$}lV|IZ#z3EZEZ1Ri`s7}}&`x8rv4S^Fv&YEE z#(duR(Y7lY%d^Y&eSj5v{CKSxBj*M>?PG%LR$hErecf0!FgKLh*=5OVS2!x7w`rbT z9?P*yXAGmVHQ8HfpwWx!w7h{R=R zswmr;?Z9emm#=U0d`Fym)nnOZTdYCic<0S&*P_ldc`Um;8d|gEu?(!^^H_2|YNpXH zL!3srY$s*OWjiU$WEvZ_?+fr^!Y)IGV!~q?hzXBnz+ZORHdKb}_~NpCd`F4%u7EMT zFOBgmYOhW6>U;fm+sj8U?qycISoPMp*{o#qtKRw?o5gjOY?ob!MIIx2Yus#>p*3!H zodY{etZ@@86Kl!rxHn{%V41LM=IVSd%b{X>FfV!f|7hS6XD<<*5A%fNa$Yd7{6#tMygeUG|6 z_PYl>yHI~QYXS|dm$UW?+ZFr0HJ)9WeO$YGi!{b&iFF+-F5BCUujFg**3BAZv!pdh zvDb)*G_G4b*!GvS21);2M%DY+c1dfHV%sJBMISgUBWv$mmb3=xX|A%h)*!iQl-3}{ zW`%t(twGXWdnaN-T7wkZF5!DGR{b?d+N_o@b`8h9Hfz|{4oiyr*ev1uVgGdIbELS} zUwgMG6^{GZb_w6pvYi}%nOJ-0vZS~lqaF8d8l||8%?kToihJ#~cOoXFxQ}g@@VytS ze%!}qdDn-Q*zFMBQF3(hzR9KmPD~_VZ6)SloG}c>Y0cVptq`nD{bAQZSi3S?o8`Sn zUD%bmOq*39?6O${VV6E@OAK7=A!PTXaV-GjS}r>}^Mxv_MVsYaqe$^QIbWlgr|mC~ z)wD-qmKtAYYulx;66B-8qNN7yx>cKXa3EH1cOSpnZCWMyRE zCuGqBQa;9G1?Q}|hH&atoq9rLIr(UW<>sRimYa`8SZ+QVVY&IJ!}8`7?0WTsHp=`+ ziV4ow=-2r?mR+wh>m-|%$S%7-QQuD4HQILd7Iluz!u48@<-|OvGU~MxFO7EJ#E@M! zE16xRM7wSG0nk2XUlP8LeN9?nHT_YrVy_4Iq452tebLrp4!P@%4)>k2vBw=jR%?S1 z){-5=cEz3t@a(c#0lV~B!e6Nu*k7w(#(N*vL(arIAfv{rXP3ijClf5;FQ3Kv__UT? z4okKx0gJ~99A6)Z_|o_N5@vBe8enbW@le1nPNQZ%GAm$LY*uhAIyAkaPnULl36?XL z=CJ;Nv~l@fh?so^pQFaAU^(*>L(?tqck+FiPxCuZIkwitU`-ZvPKxufqpjuHwhq|! zG?$~eb_H3b4Mte2cs>Vq-O--hE}I3rOt381u8Y?sx65Y1t^_O*6C%DiCfv3ocG>pw zv5DuSotSW0vCB}9<-|l{)_T`29aC9KaKHO z$BQ;i^zZZdYZ99 z(U~R1g>PGImc35b5X-)nY=~vA#{kQOzXZ#RizNQy^_^^2rxF*jeQ&RYF_cEZGLc5X zGLc5R9C1v1lH6Z{Wg;d7%Y?rK%b34f;jbsO{gn&PcUZsHW_j(J*QdD0TSv*INNb(0 z*QYSRvVD&}g>_HzK80OR7-HFFC>iTdSU_W6Z}Og#E$S_?&y1Y}okH!}P@#rBw{uj> zU*s_7Wm#CGvxfikx6IhNb7uJe=J`}@f48*3Ie&<9KHll+9#h$Tfj^#UVX?v01 zbC2aaud~Q`;+T5gVx%#SKM&mNy7A~Sq$iKw4(THra)0I1ykGU~xns|qIcEfaF0>)* zsMz^&ZE2di%(lfky0>l1K~K%MZ8>%2BDQ6CAv^ecwx!tlacw!Kj-SzAoqlH7_O>k> zU%wFVv?HorbROHXAAc^iu`R{Uk88_O%dWON#mv->!Ys?&SScFJ_=m2+%cUig3Poe8`hMV0?ANl*k7L_~0bh{__XL~&txodlAo zQ5JC>glz96fsn+PML@(W;*N?N8r-7buDIbkLY@RPDk!d?&M5A?!;CoNpK*r&?_1U9 zc6Hxgs_(lqVf?)FdHuS(s?M)YojSF2b)UL-xOT)NLM0(f9Y2PDA011^N1s1BzOELB z$lp9>TIYn%`abEa0{@zhuj@bv@>;j_F=00kOO8kbE&JoN&h9$zsN;D$$a$5H^*T1_ zc)SkME*m{(O`Q=M-baMDx6 zt&0jW{J#nRAf?$!0Sk4m>XRQC;Jj0b{CF7z<}Tx(b$jo!I($Q~cVRPcmQ92dkJWp} z=CCFvCW95obzLaeAny?axr8-2xt=gB)ct0a@h47SgUHo~b=%JjtM&W3-g}GQ&R^qjG= z?+x5f1U50pY$9z#ld&&hd7GF#)^ogEs>k7Ad7GF#)Tx(&-X;dc3T#4hd7GH* zJ8!eE%QyXDV7o8M1=eKCs2T2cD&uvXiLakva~x)e1FeU3Enj^SZ0!Clbsd;UA9t20w=DE$p4chA52Hgsk$U8i#}*L?5cNLUHK85&YOR=EDy z^ILQ58Y3rOH!#+y22#J4d8EpRTrU_{Us=D3VCZY{z;gBc!#Yl`*`3bVz;Z3`wQaCA z3+tH!%hiuHcVMi3eH}3{R=-@s#Cp&W<+|sy-odUwviloIgCdCNb9b%e7#Lat%HX z^~<%_5ak+t?C6)v`uic+S7-3PuwO3L7KUW^L+vNLR6}Wx9iHJsnoR#?-)Rk{9=C>4 zH9aeY^ZUN%j!E=|eOP_p_{Hn1534(PU)YD$>kCb5laOl?ePO>`))x*#uEG1lez~kK z9EMzj_l5m(SzkB|xd!hG`{lB}u)SQ*>pefh%lzx~f%}|nP7aoQQYX=W^~-hNf%}~N zn!-e)y+H@Y>X++517r2;%lc^a2gUaj{c>#>SgwA3oj)*Ezg#aG7^`1jmko^7Cs+3) z17r2K$HAXF`mwwvWdGxBVs5T&?=?5Wu&a2i{QQe&t0Ki?^_Ow*c}_pp;BBZMYjFF@ z*2ynQ`_s=){x_>T7tQfn|NPbmKlm{tRs-Aq_~_{OtatQmV&QMUX z?ti_N&Y$DU*r%^aVD;-O+)o|J;^pesm;Y^vteo*!{rWm>i252FtG|qc?;qH&d)u$9 zy{!iN^6fEsNvf~*Sbg@@!?K!;ug5-p<@Ql)XJ7sL8hj7C{xZIOVEgJXW4I?q|q_*Wmun{bd|{4}$(O{&3(j_Q^E~zvAq@ z6>|xV+Y^J!)rWQ4KM!2SKCEGuapo@umaA`$Iq?hpiYNIkMmon7mgbl}tVzu=yFVYe zjM=-UbgY>8?Z8<1`MvNa;ZNU()wy$Ex$^C?Gog3C17r2cl}x`O)m(atA8Y%ty7w9$ z*2HeDu+9t$k^kOA5iPO8_2{f^^DXS|vpbg_&`PclEARyqRyWD8+K-QcT-OazE@4eh zuIxKqDr9rg+5K>*FY9;OeE-#lb^8&9rRTqP-;(9OjhdNsX6`d^J@(msXRm>=^1gHW z{_Du2Zb-kIpQLZow}*wL=j@zZt^GxUG72jv*JQBfI=OB>1bq#|*D&b}2g~a#!=fH1 z<7*hoH3_VRYTMM~JVLC2vymbZz?WAWVKZDKfB-X|en8+P#iX{~>+GLs7|zL|gQ z5X!i#pHFm-aB`)xT{~@H-#N+Uu_o&~r}g{I30Ra?^Yh*_cdRc`HjiGbwb~HNBMLM6 z{ZQWDZJ1ayoxV&We~y={;5(O;>1z<*Ij67WF@5uU*~dV>b5(e;b$R|y}9t{Y+*J=So_=&^=U zMr>2{*ga+l`bx2eViPIWQ1q2z4NYHN>1+Ri^))fg`U&LPoOBlLH!xN<-d-Y`*j00i z2QuEeH5ky_tmy<;bB2e76q-{=F7?a!yia0ILE9c0mh?3_tpAz)DbW{mfg;83Pq{hq z{P@;})Rj%(w+?n$9OFV|oOl}JlqMwd>tU9}^<*iFOVa%M;x17Z)5C1iYkcgF48pl* zzt6h;CAF{K)c%xH`%^lrF?*@oUvg@H%D?~pDUXpgus`LB(Z$QwjEx07O8#<(^!D^W zP3x>ZrPJ9%0sZsK+rC6HY%6@%G}u0k57&6rj}^RY(%7iy&;QkZ8hI}4CJk~)?o2M5 zo0QK>%F7tMn-kW=L~|Ld<;tG7ky>L=!#<7P2OYeA-S=TN?9&+T%~`aG;603<9rZr5 zVQZ&HFUQW98&JzU)0;9agqZ9=A`U$KriPe?O7OdZ}!z zes9GTOX=#c;`V9uSmpg!CKp(et6`r;kF|U0n3iE}6qfe2Y}i{d9!qjf0?VFhZ6Cd+ zeH!EBI$m|-_wG#J1=QGAlfJ<6HZgguxP2Pq$_SRXiOI{g(d(;WpT;=3!16XRs9b?f z2&;LY#yYtItn0vP+NUuR%gNQWPh$*L>^_Z=Sjg45Pou}8_v-JzOkX}$?_nDDX^h8G zf8VfAV;mOmnuMkOzci(<+@~=TOJiCOtMXk_9ac8SWc@{RfQEg^BC*tmhgjwBt?IA} z@0unhS03wjm9u`&!8*AL@0v>G3g0yqu}XgnO~%@8pGK|2ii&gm!S-n^$I9Lh@ve#W zyn3A>kFEO^U(w+>=jsc)Rr4Uyqr-wyBsayfpY&13;tXrMU3<+z9auxOEO00in z@7>$#s}8H{%24cAGu;>UH7TruzS?7DbFfQfGtB2=_U_7y;c=024HK(rAJEIBFHgmK?ALwMKA@Mm@_|;w%HG8sDLpV2HSJ$iEmuEQ(>|bW z&y1O8-`p>YjZ+Lo8_{-@2ce5^}2YhtnGR&7wum2&}g}=PpOjY^cHeu z{Xn@~el8KGFKfG1a$z@~nsuMGH_uVjmm$T}qou8qYk_p{DMBvkHl(6l=eKB&e7_A< z$>n4D-z-4`{XB_hI$=Lep`v9tmgu+pqh6 ztfsyY6i>x^?8mac&^XHE;vGbcTupu9w#xR{FPHU&RdTh#YU&GFpY+tMFY619qo}Vo zSoMA3*x0!AzBwVMX1S~{ESKx@O>eHm>e~;oVINSv3kS>TtSDDDk46scnKkZ^3i|5K zQ2$k4#(udP_5tng(E{s1XO4a~Z8)Eyuci)65of)$iST(~XC>zx2_S@`ktip&Uu>{8{;{x+*aG}w>dWU z2CzzXpP&2k3{#}MT%F{7m2#EntG+!ZA8mnEZ}*+fhbqh1FIR(ob?A4?^_8t5`|qbZ zou>UZ84nt<=6J2w@3*NwTKX)vi94p*x?J3To9d%0vHJJg+O{=s6?vQR-z$}uF~8>! zeRRVfncW%6tGtYl?3EE|NYk)KW_OQDto|}K?UA`FSfy>KuZ&ImTDFp_eqYP6u{Qd$ zeJ#u9btH*}@BQM{yLnT(9Tn+n2 zj*b0F_FQgX{ralkKXPpBYieh-kN&w_e;ModkGy=-L*`Ur^_Q_}|Hx-lV)e<@uz%#N zSud}|>epBO{*hy2-v=wMZ722nM_#^(HRR2uy6@Ll{r-_-W4p|)!s^#o!~T)oeJZi~ z^;N%rSV|*m+&_|M!g8#> zIaAdBk>yy~I|?V2ni1P<-b$FR-5*stk!+jwpkzBJ!1dJYTXAuYQpM9?jKoR#y~E$ zvnaVL^%ck^tQfhfb)S8UOncm%H18i-t@}Q##{DC!b)WyHW@gg7e`NLZW1rnO?jKn_ zcI18fv~JzFe`K}p^H|@Gz^c}LfVI_q&y>kk>c>(yrsc76a#dip&{wukBUpWYWp#6a zKrY%wxKCpRRttS)a$Q^IS4QioT6+xSlJ0YIRbXNF;faS{AynkeM83QcI9=m^J zxm=ka-U?yG>>pWe6L~DZS77~Kl=NRsahGKLNmbZy|tQg(%jegAjk&N3- zWdzIHM1x!rSh4#@#@Ibr-X`khs@A>PMEw4d)%pssB-gIjHSa~atx{hZ7Gr|+-?)Ed zwZ8IL8ao>IkBre5?*jR5pnm_zv3Wb`TiMMCr6|5L%;eg2Yk*bh(^rR;&3)JEd7S)g zpTP1pIu`ZDAXO?2!KF#!xO=BBPI(zVSo$mb_uy`*QgM}}We_vB9V<6WMu^1O5SBd`f z`ihY&#cI?S@5-9Wm|`{T6*x9V8)~XY=2j79?7ku%tFeqS-sHgzHj&EJP{x~XR2h>! z8nBcfWo+0#GEQG9R)bAkz9~juDOQZWI+0~;&=)y&lJb5cYeOXJN?%R;M{Z6!6AviW z{lqluC%{s=#{DCern_G$R_3F&yZRfok0b53H?qDp-yW;w3b549BC#6f!gnqbt3qFy zT(=HUuA;uE3#d4*4WciPREpJFUo}{*^;LsaAy+nUy5u@P&y3lhw7fkASaYJWD%xX) zMVT~bZP=gG^@ZJ?OWRO}#n=&vHSv%pEa|Hm>+(&%)fl>aDOTJ4NgY;a?;cj!ewy9_ z)~X#9X=;B`+Uq4!i>A?i#GI;3pZ|ONllp!M!K!3g^xU_e(CO?nJ9*k(vg1zY*lX5Z z%X!6>=Zj=!y5PTS=&C(8~0!~2uobm*!RT-%oXReCw~t#5R)Jo8=; za(emgFYk3cdbrnzUx;2F$8{BP({KKEU2)#Ut>ncJob^JxW7*3Tek3IM;PL?koez@zKZhi7=ob68AZ6mTA zW&CAlWU1p1Wm%}S*1oG`x#Od6a`tlYIeR;MnfBV%PL^-n;o8w-%Ve-HWU1pnR`Iq! z={aM@)qe&DnvqQJtT;`!s_S>?c&Cnwbi7N)W*zU=aixy;=y;zF3>)5aHmq5#QzaSx zm2aBfIY_B~Bc&u3m~wej?vDIUakCZoGKG_dWL}5t5e?bd-|_#!I_4C_4<|T z&+F`_%cre8XTz$+>sPK>{j~Lq*N-|V1v_|PA%E^B?neK}v(t{Cj`Nfwx<^w`~zKPv9YihH0A(hzQOK53V&%tZO7c7#F} zDgxfe=~(8{Wa*xu%cm%uG+CUFKU$}!Dx7%zIU?*N-GJxACPwBejP{q7x3U2m#&VVS zb4t%WyeH^T@r++rZ)y311(H&X{`vSe0wcFyvm9#2(5_#Uq#t1F+DdVHF~Nt4CF-yNaOPE$DX z`g26s({%%$59^N1S6Eh$OB?HP*5%VXSBnRJco*o%>akf@`@Jn+k53eTR*%j6XQuq* zPkBP}y3RtLq)X~?)w=PhHu)}LTRlF*E2sx%^+=n1rs8JkAPwOb=Mz`A$!94&y!=*1 zR$p0NK3n0W$>Kotb@?2H6R$rHxc1D+3?7$a2(`wC&3-7K@flq0m8QN}I*b zNt4Ba;_YUI!im?PBkX3SZoo^!M)XAB`|`A`RULp~+@-Rb-N5^F9n{r$q^^Fy+1m|u z-q9oDGxUGA7W{|2J8S829|KC{b?vYD|4bdO{kw!&c=5{0cDAss9?!DCG;vsu zXDe=R9i*{jVf!!QqxV%x2%n{YmcnSSz6_O*BE9rqk!;j4{O~?o2YO!>S+=F`>9yCS z)45GHx4@kbK7F_2Ic~af;c?;h<(oF~1UQnOb?M2=KXbO-XJ>Dd*}a#QHvJqO)N!n= zS4h_NN}sRK&543i+C1UpIC(42FOF#2kns@y4?6bH5u5Kx`ldKhdUy-AwZd=}<>++% z$F|Oi)c;q6jctKV{XJI)^%u+kuq%gIf91=z5+_HM*W?sJgL9f ze0S6PokZzN>aS-PigvU}|Ea$fk@fd-VTbj%SiIC=)$MPI zQc{1hvOes6!>PZe%9Hww&G(ziH&J@p+M|vdpP=``0KCJ|CAPqY9(%cd}It zxQb7)I$I^1_5JWN-eG&OWjpf&J=+skk}TJM>>-x_T`52EEM2iY7;!r*i+W$7G*0iM z=d4+~cOZhtu_aJ2z@xVE1A05;+02a89!2N}mqqG+{)eY` zZdQ8oE3`M4pMrbD+Pt;5qk5tJ7pCKrK9Y@N*z_75X45hJ9~S@cY&w1(8QQe_)bMjV z&F8_)Y&u5v-%Iw3#S^2~=P8}(b(XHH$n^UDk9xiSU$EVS)52imq3wp@X1n7`vxg3B zH%7?=l(yL@bz_BCjqseV;`CUaP`uNc{%EZMQI{|hz{_EVt^gyCib z8&oE@E~Cid8VzOY_# ze^WSVvSdl+eBlVC-Jpc<9j9YiPXIs0vTnXn;iSppNaWXAp09A?_2-CkpQ{`2d{{E_ ze1$Rpu(CGIKh9QJuU2~a;XPLeZOQm`SxP=Xt$%#dw zefYYw8POd**7C4`^L63sadhqax);XAcZ;weE*|E6=UHG17S`kWisLmmX-Gy~_HMO* z{=@q03zYCl1s>{2L8AV(c6crj&w~{k=F`OULh;OO$#bE2u%G&TI*F1vLbexG@~~}_ zl_$^B70+2huzWmPrUQSU{Xa~XFBT8_R+gO^Y1AP)U!*YNkeg=*;vb^pB?_aDNMFk{ z?OV8J>Eczhmo6P$H9GFz&bvxegahHMhu;JMPu&qsfRE?eKrhaN(q0_sGe%dfS<2gg z#XCYOPv_6A1AJ*LAVoJoUwn24;_IW1GaZxgWrG0v`C)ft&#UGGmXHyE^gAyXAU1on z4s`6v*A>4@{fc~sG>5rsR;^mOj;|lqj*c$t=>#NEf^$@e#FGU`uZ%`Q9#H}kb?l#U zolGOt{j2gw)zy>&iDkju8T#*O+g4jxL@Ol^``bvz!)Sj z5KwQ9hobj22;f2j>azAwz!;>#9jA-8OFK!_sH3&cTF+_-*Y z)E7>(J~h4bR6U|H3coeL6+|ka|Dt4*;`Ubu5hr+;_2t!p}1gV$~Vzmk4a9Vq}XFBYy_ltMk67UC@CT_z=8CxXe3JR z>Gs*IAFx)$JzXY!@8&#Gb>EAMJS~`81R|Wi7r=MN0%nqJn}dG+Ow5l8x^;k*^*wpO z8vSP?`f(;iM6@gNNY!NxMf2l~?W>q1!s&^2Wgak6G>^!Rh}*8y^270elIq@Dhm;!! zkd2P7H)=n1&G1rCTk08m?{~UA}3b-c&dZ%AMf* zfYS3U)|T&s;$z96E#HU4$Ky@NH#T-aqnsZWACKv6`92~(9zEOgeYB;VO71@Oyh;~5 zB8B;79jA4qN)QnB@GT)bZ zUAS^={oDN6a8|1NTqwKPadOBcz zwgnb#E2QkU%TG?bPhLyvj@butow{=QicByXj!|}*3HEsfMuRm;_JwjV))|m&&ghDj ztFwn6+NM!816C3GB%_t}lnA5k5uz=2I50U%H}KJbL#O#P!UlDAf%L2&TMf z?5T@4u3YX`VNPAVdU<9+bn>3PBlbJz9;38hZpW?#i@D-*Fd0;51gNjHgzB<6Nk0_B z-!?(5P#nXbpMojlJy-XJBcFAWz;6WKR~z^&t)0Pv?`ygk({-5NRr443^0V}IHomX7 z0;VrO~lHZRwiv(Y#L!S|BILpR*E!a#IuvI;lhXMidGfqTNFtEicPAqfpRS z6$6M)`Ok&~tw)hx_WBHJY=iBe- z;*5Y#mmVnm0larKLe*JnOo~OMZh%aal)lYjEh=0w$ zAh-A%t||if!}frerOT8*y|Vga#jZTK{Yg;c3H zrThXqtM&h^bfjITYx*+kjf{RAn-Ks$qx0tilKt|FuQ)OX@F(p6{rUypFR28n_4s!e z03N2}HUT0z>SDP9BBP(iW&{94r2)c+0zAE-ccLt#pXr7s&ppi$LUlh^7;%((xenqH z;1>!D%(DJP2Own3iw>_oA*fGCE58T&%RFectpk{n`*h4-Qx}=~kn&gU0B6qDBk5c$ zB&7-UIBuk)*sS9GIuA(4x?q&2f!RyeY#cppbbNgA%50rF6LaPqlqd0I?8z3yq;`KJ zG?b1#(uYAP{kIAu4qb)z`a6Y1D;|e^ESX0B4E_VLP|yGpM(4Kup;HiChN7zVcu5pw-G|81=Mm4vO_F z4*9MPDgUiKpuKe3wpDtbD~z5w9HE;(3y`sx*V$fO3QSFg4DX1|5Fi$QwX4+JJWytT z=>IQD#~@C{hF#phD=aYfYE=OM)pc;X-M4nSkd)nZH{fuOmS-p-t$*%{4cfM# zPBY}-QO$UgM2wC=+EI}_w4|?$A5{xRFPDncJ9{WE);;oIM@d$Ln zf83b(iP9@(kBwcHd}#68mF5+*U3&L>=;zPX@9oX8X$WGGjx+nrKqiyF%l=ay;w%In z=t3RzG_hslB!z0y+->;>FYPde$eUIBeU zT}R(lTtJm!E)88ZB)Q$!l=!VuS^j>V^Qs|3f4|<{QvqRmgz@)_UA#>rS8Z70?rB>- zeyO|XI!v$IUiU*@gBo)DJ#{s%bvZ($M~?{Jmm(4)s(s;*Ztt8 zYq$wZx^dNNCyAAG<0@Y=E2-UENi97k<#_6v)uV2_?A=ht-VKH8-RQbkI<6V(*R5Qy zZxP4Vt6VFEgcuyfN<1vNXRc_c|NJG_Dp^XdxQ@q)*2@#H-i_Id6PgnBVz}ttP;0%L z`r;_1qh1A#*HzGEm*pIyx=|H0UZ|k)LItJwy$VXx4_YD=W<;Mv1&y<)kk%0Sl-1Ch zgYP-w`MmM{^=Egl8sd?SvaA?gyljh%ZM$a2vOP_#LQ3aX1_HVBJI|dc*=#T$&%l0gYRmu9rEA_O-TkP19ob!b7<9#Xk z-yQkfhKD8Fvn0F=rb?FhuS1<^F{btMAMKFq#`fC#fbCiix-rVJ)II!AjF?hvxzEM9 zQe5$@ncKA#UCDia9kEl28-Fyt^B}cm%1U>??EEwJfu=6XXu%xKB#$i~q>?dh+Nuq;9-OXdO4hkddAj^` zO;4Wapx9viRR>`l^K}r;EUPS>^dzwK^Zc!!U6zE?K=#&Q=}%146P^^pb?fL-{iizM z0pDnmE-XB;K+ek7!by+(P*(@#c!`et>F_JF=jfZ=@(tsRZ|7f5@7$sE572=OjE2Nf zcFtCoFr54ud5L3sQ`WT(leS%NfLV3dQ5T9|QEPWUrrmwPrc>xZ9rU&X0 zd^?wghxjIUF?|>wrnh`aUujE$JlL4gux*L5nGKW2K|0X;#X7LDg^$+18bVLd(Z8DB zIaCcrQ84i>2Y(zk4A4 zp}jO?WB2G?3o3m-0cw&cy~F1^!*SctxNvwajmO+)0#3C;8XrzV_goU33G;FyD<8hxcL2U4#Jh+1 z$n!A*S_Y^ipC9q}Qykc3@w}4WQ*qcv>T-xF_TIJRUE#<{loZ`D6y_W|?jMbWOroTS z#0nEK?G=qg$vu@jc03@DM1w5%eMCi`>K!}wjs?slt9R_!Cl6So|4hVk$BqZ)k*doY zisrj8-sM6`!hgCDs^LL-z(~-U>|P(;oDE?*D9bb-%Rn155V_O@ts@Xi*fAOUwrEa;Cq<(c(e-3 z7n9$^TgpjCh&~@7J{&v3{4)JpN2&w?!FPc8E>Kuoz5~T~;Q)LGiLYDWvk6TmuMz~r z63D^g^G&IpV+Zz$jyO80W5**0#KLBw5bKa~EJUqv?7)IEiM(S6Q{$4-HJ~6%DpF^T zt`93mVJ_6?*nwRe`SNh*zXb>D@D^CKt&l=Iu#PClVy@Tk*g?ZF3V{d%?8r7?O_DvT z9E=%GiDL(C)2K|eqgtUg$u_GTjaf&*u_Hu6E-xE(=^Z;BU5>GDYaMV7mwM z36q2L()z{>?8!QgDTkyH_B(dayQd&-BtJ!|j#XGNd~`3_v?ZHn878sh_eAkA4#)Dr&-3k*#CJx(r%RFLV`m@AfB4An$>L*; zgZz+Dr<~)1mv16bup{GJsD%3}q%Gf5#J4ErqaA^lIa=tZgpl*8;#;CP@-sePKKnF3 z&uDUjUq-!=(bHoy0wBh*;~DJ$-Ky&G zqhMD!c05ynNRGN#U4xMPS+N-b0AU4yuw=^93wp;i(fMIIo~?8=dG2Y3&>=dWqcGx7 z-EtjPNB^L(z${t8tlq&25WiMi@7QsA9<-?3w99$1Ma})Q#L>%XN<+p zcSRnwTGW5+6`V-Tle!!GWe*o**x>bkfC z6~8(bFdIqzv>?TInedN35WqFDfY~@z4S2Kw*9s6@r(=eg$v!WiN!?=~tVRZ5_dt!e zgEBNb8x)Qm>+(>3C8*S~14BmW;zBQ|CM3eGZ-r>woI?U>LmsJ4V@v`K!h|t6pf<)s zF)yrxdVV~VNrglP8A^3-Jd{aQ26db;&l6P1G9J&^{f-?>VU3D_OpVW1{2q#6YD^m; zdH9F|k49)W8+DiZ2j2^naL)nwE)d^d1Mt02e5;gqC?_)qFH^Mx%7x;imuhxEAqV|A z@}*9a^wu@%7b%j5tKKK#bw)~W>_M_~2-eMm)%zJVfxS2nR__5}U`Qvv9MOC(%7ev8 zRt5GFfd!MFCXJaqb~fRV>*Bmz^@U_?s#E_<^I-LbYyx{(9xP6>DviB74;Cj`71%2T z7O8#;sXs?{PH&y{zfyr%|Ec`))%*>s-S|+omPsQos6TC}^8FA9-(C23`_0}gZ_vB_ zEBEul;mrd7D|OIW#eN^Kde<50w;q%8X1RRRR}()wtn+61)tszjqBFfLk*FO$sD(@~ z{x17Zd5E(Rc%WD5pxwll^^+>=)k@FvNw2HYbr}^sQm_@#>_NO)Lf%+!7Tyg&l)cmG z_h#uCn~U%N_dU%$7b=*%DKAq|hCz|+?XtQ4^5#T4%gueYZg?Ju)#E$wJ)^U`Dg;}l zL4ZGe&lr6Olk<#OT=0xpT=0xZ(_3LzEiQP*EG~G)EG~G)r0G?bUIV3Y7#@{?@}@jv zq=d8ucc(mKFb~?*#wpJjX@Q34{GCuq??%@>VtL^2!!yQ8GB&P#`PQx(U+>CjW0bX! zUcudkn~-ohTHx=K2{}5^s8xQw&m>S0sB9aB^Icg+FJ+P zQut@mur1r$?TR_fl(UkQAnJ~6Z)c@TBn4kv$IkM8b)OlXt2FDOS7R1AptI6z#L63( z*lcgydj>O9_n|uTu0#h!tH4=>L6`6obwGq8qlM4+w{E`1RyCyMn3sn02A=fAaE!Im z*+X%b-tq9Fub*F93c7H;wo*VTbs;DE1Wjt$cOy;nh2`h#p7o#@eETNU955vRsRXRs@a41`tZx|lpP?u%t!|*WuydXV{ zRxaui96OhVhd3r*F?|>wrnh`!ZH5^UWaThhB^)^k2jAr68Y-qIyexe}ViD z;nzvFHV#WKf8dPHB~lc+!v5j6_7>BZ!1v^b_{9wt$+S4(22Q;#p3pU2j9zhN*PSVc zr3tT-DTgKWV6>wy{@xvyUavCpUOT2;p_kXGUCmTyMPF3-JvbLe8lyMpf`0UQ8y1hB zZGk0cu%KVhoYDI|xL47L1M;`tVd>Sn*1GE#DF1eU13Y zv&gQeLMx`tN3kC2|raMK>dbIftc7qmhtFloXNF?>UF1*GD5!a!=(B zOK->{F~FBQETJM#^$tsKj0Majt9Mv>Qy!41Oz$0T-eD{gvD{(l&3UBivWB8DwbI6u zTir?Pxttm9F^$XefRUnk#Jt1OTk4Q<4ok?koAU1Ipu%D4t=PaN0m=V*%zFpK!e*fm>wV=|h+5&Wgav03d55L<4}^j&sYsnUy8b{p3U4#}9G0+a zBVQiwGKZxPw!orog%sk=QN)MJv3P#%cUYp~7==KD0rufGU`>*Jq#TSHPKm=3ZPTbs zw2!tzYm)7%ax`Wg1&5^&3Awy%nZwe@%8_{9Epu3+D}mA?I&Y(ow};3i@eWI$Xb*uP zp%kBN55bsZ5Ii`3svLr$uIeQ}U1SQ;J1e;(Ag>+_GDYaMV7mwM)02br(q`W>oh-=D zlta=8`yH0(-BS?PGoPYVpH)~eGLh2Y8;lnAgC28 z3B#YCg2g#3{bK{4AajH^7;e8PzA;^g`NcRaUDJ|}%rT^E#TQf>9b1XR5?V;>D?KNP zQaS=>q9d~`3_v?ZIq6#1?fALDQ=AN)Mu-XOj+0zO@eEFU}jQ2xV*oL?3n>-6M@j5_5U zdc1rSiGm#&-&d4yUxl>g+a|t6DIe_!yv%_}HzkCeUlrdH#gU)!`SR5}EPYMs&r10y zAC%?SuNUI^ZvN}y3)(~V(;fz*S#_dMO=}&NZfp-&@33^!Ab>1up*9?6bdhj}S}5{2 zVga%37>A{ADjjK;DK&i=^+rZF$7TdTjKk8m+5!5H>_@?_a9H}b0FfMZ*(yGge;Ag@)3xNBS@brT<7_#G$LuUjIp9 z(Mks-uk><0=_f)%N9clrJpLEG=MWjglJ+v%V$t;;eeR30TMZ5^q-_=&F1HM&}wBfjC!hfSo%eKz z{w@|U8>gxP`I_eU0>sw+T*uFc|B%n5?y(P6BZIJeCdGej2W4n>HYgmH{*;HxFB#_+ zdNE{#E-v(fYC^6XqR)Dp{oD8N1(Mi7Bj65fE+tMe#f`^uBGcQ$2l*soc&64%olv!Roy& zn!x@e4_5C7VqnE0A{~Vl77+)L(a$C;kS=RR~s z=P=Fqz`=6{{x|7hWQl!I{eh9;c+P0rlK5##o#)Jl<}kOGc#bCPIrC?(PI#iDN5Z#o!zZq*1GzTo;B(s8-$r@HlV-SI;bZ1UUd&pp?3}GEVL16S0uaa4 zp)7qE9;Q!%^f5YQv;d#7h4O^qAwGR_S^6+MOkY)}^8y?IO%MN*bw?iHBR_PI4$67C z4(c@aw@6NX@{G>g1;VTxdw~CKIw*Hcn}F|tr%Zj?ua=kCmvB?RMIxgJXh&W1x}JW6 zH8I|Ta32zBuv_|K9>y37xW~>zB5p4o*eBQE(U;n9g6OhGVA7VsAPwz<`;bUO|3jYz zCiZOokuG~=`I64^-CNg|ueC#CpwBD*7RlQcM%iQ96*y<9UCos6U^ji*{|=?0-#cf+ zn$Mw1Q{_x<_U#AIw z_N%`R=cvi!Y!(E4No?Ic_0$=ii)Hw<5A2<`Iko!Kl@>ZvzaG5Ze$kZ?$!%gY_3OcY zHN89a>%qZl83QpL)lk;anDtDpK25DYd21S~Y0-^gT1)>=|9bGdRSF(CVy6^4pEi`$ zr}rpJo_J!jeeUUhKdVnysN6i^#jZYmS7pCm>6yX7`(7Pa>R?75qd)j=ey)FFIY8I6 zf^emZCnLg&;o#E|6K+q27=4&N3=h*MX*$yXUtGariJWrU+4N)goWt_k%A3Vo`Y=39 zKR>`vbZzNPzqS%r79Qg8#DSc}^kI0Io+o(H+sdHfhv8v*uFKMg;bHoDL3&mR4FAL+ zJQ1LUvkC#e*-=?|h>ty%r4Pfy^d=AZW%3Xn%7dIn!(Mf!Y^DeDI7kQe@LnDC2eB)c zd!8|)^Cp4u8Ir!)*rJm@JIyu`39q%nF!c+_PCru{ieM*3v^#9>?|IeneJUTTjxl4T zl67udoUJ;p(-me?__9YvZhrxZ<#`n0!AK zN17~|eRE}J&kQyP4p%!2z;}drr-_d|%Qg%letL>s7XKK<&rm%5ZS#gAE+=)i#ce>u z>^2nHF&YV(L`e}z{hr%Ui1N?p~z0LfSF|V8;aa3 z56E!V`^GxIp-3iT`Gz7p=aH(*8j8lSTeYFcE_uL6(L7>)Ly=wUkaFLdBO6oOo(?KD z6uEaaB5G?w#3S%NI#w%Z8m=xK#cU|Dn-Z@bfNyv4jSs+gU-6w=;EUN%WDoJJAAs+E z;$uURP%kn0?b%XJIzsB<{yNxDB+ReV`)D=afhw6J`1aCqf$rM!JwSXH4#2m!___r? zdySgOs{{eDjI)pUd{b(-p$PVA1BNDrBVavnKrCz)0?)7>RE~wH6&s3R!I?yULy-p$ zgn|?{SkBS)L&{NjChFTz1iLo!<>4;dP-Nd0ShTH>LOkT!uN;eKzWxnGXgEe85MhAL zYy;LL*+a|0nBkOcC_>vbDidx0R%lJKJ**s!Sw~?*kq`;FylmNqA`dS|;+ef{LlL?X zC@rGfP~;KqAu>t)h9U>FhrqZ)DGqE8L0Jrf2gifTAsFhaHWZQIFRQ(iPywV?=|e5x_A`wc}7 zYsX%6LFpd}pP6x^$G~*RK~6;MblganK&BpY|{ieaezFZ74FkJz)KYB69`-WLXQf z$(@Y}Zo(Y}pvdfp5>;euJ7z`{_BwrAl5dct~xBX#?f1=XSR3P{9s!=Li=dA9)~Wgz zkO8sn769_ptNb45!aQiTtpk`+u(t(`D8He|Q`!MGZz%HAJRluw&4wbGnB^OaoFp`q zjy=+cK`8xXg%O9YLVG<$VbMwlB(L=H4Mk4PgH|gYz?1@|FPIxDot4I?!_V-Tle!!GW*u^9mX z)pc0qCF9&eFNTcJ#f4r_O-O`W)(X+Mi?V?@LX zU&tn~b$PHj$*MHAJ`WZrSrym@fkmpHLYms`Z0i4jF8H)aueobBG|4pnCcWnVnC6_| z;9LX$2X!cm=vU=0xY(R)&OhO*`8ykIqwnGeKXV zW5PZ6@fw(;_+!AkT)RPOUNPIH@4j-b-V^CKVy>TH2|-lc(u6QnY(M&IXTm6x-RsiP zhx8v)kNqrQi^_Vn(u39OU36VWMMo8?SETZsJUit*$_MrTujBRoV?U3Dn3D@VAcU+P z=j5`Rp0P70mk%qH>1=G-Km1bvStDz4*b9#5uYnZYmwR{K7j_R#lW4V~Nfx_U&{k4}fV?hdbdG0Pb# zbw_sp_ikt~y&F{4yU}%zdNs6aboKIH zsK0QNjxN`qIqZ|J20DHs5?4d3^0v5fmEV?!vbY*d?~{@C@YEf7?TtU#f^}{$ zOXD$}f~;S>a@DGp%U7&-f|XTCDzZ-A0(W`tvvXB)^|X=X?og5yql=fdE6Hv5JDUfF zl)59YI(C!};=%5K5iJGbgi0;V0zi5H( zcS@?lnK3Z{T&2Sq--a`nZajS5s%5$_BkR0tze zW1hctAGel;V_Ib&(i5KOFq{*0Z8Yo;=|3jmHV!nul&A2W2*6=#z<47bSw zaSWbi>BI0aeG;UP(K!PF_|#D-PZ%EJGXj>S55vRs^MmxEJoAEZ08J0nCHQtO3lH&4 z?qd2dJWOx-lD^WG0(t%?ZHcmhPkEt(bf9<5MO!&#-1qe}I)|zu)0VMM_&=e8a>sOE z@NIbG)OIrJMH2fCa%wvn8AU+M{dd>Fn8Bo#cVOIyM4G>M$Bs{`jFdg5U7?%Lt6j}h zL#K^5Id$s9G7-xi zJ6@besxE6N8tV;JjvW`}0V758h<9!k>UCOjJ)ZY{FR4Syz3)Rdre{4JR5*5A9F2(D znh<&Y^imzGl`{=je~w}tJ6@*5YX{(ax%hZuYn$II#CL9iFUHa0mEvRNA0PD_d4-)3w$=A$>ddn zfR5MorQ-8Vshwj7_GtqKuQtGX{eW25ECilmy`dZnQ7arfu;5H0@7VFifl!db2Fp3R zep5LLbD=)R4(!^%a%EIysaFG=gTt34!RO3EuwSmczb(@ zOcL+d@s9Qo7@EL8Z~Ll{j{w zg|xoXbCM{fBTzmZg@R7%P(Bicf`(}KkVnhQ^3f<1^i_pIJzS-OwE^nEWR7v{_?Xi3 zY;AnH71{L4&KV}L+$q9{kk_bDabS0Qcrt`^^-l#g}YTPxMJ1o)IZ^M~dGTf37`Xy<^Ac2LWVR3$^j& zsEdR0F%~=DZ{|U(mCZ2fsot^U z=JtT~jve0;AY*ZrW5>5+GXyBcvEw^R#~@C{hF#ouV>1E(s_WtoRQ&g10ke_RPYb3w z`0O9~0r>q`z-*kV2E?)B76D@Gey-!^!?)%$se9~$)yN?1o=Nc!+Cf>d?QBqg63h?t zQ28a}+(IvgjL^k}UQkU)g!@q|MB^^X2GT#}k?J(YB+wvC7$GYwAGm>1ST{Wu=V zq(UNt^fGyq_(?pJNmT}QoG@<_RLLSG&)EHr9ZX@3ihxXwf2w1Z5->F;sh8cRw$+Xu zKT~2_f3sr;IhaO#eI zvMP=JJ`WZrSrynH1Qw}&3TbM$v#I}TUGTY(d(BEtwULO44tdU zFi!i7Id<&T=-9F1_2;O+nP6>BN8YhR6Q{&al>BeizG3H=DNWI_<5zS11j|b`S;vmg z2nJJ+{Vd?EDl0ldKfT^X*JV_6&cKRAvj=hP2ziI)*zs8j!*n*b>=%D_%CUnA>`@nI z4y<9yv12=aZqFpex!z1UcDOlKcgnHDt)vX!g^0)WDaVc}$ByA!7H_ow9vnM9r*hn% zvP6Dm+5KD#$Bw<`-e>&}k0~C?t@C*ud$!2-I}H8;YOG00xYvt3ttq3Cl<(AIAMC^gt|JAFU(iBJtvEQ)HOC1 z`^y&_ugjb)uuu5EsDr#?x)Pp(e|Y_rlZAS+DJKir0`|aiW=O0o^5FzeygW_wK8pL0 zNb~pZWO0qkNZDiB6}s8?hQP^Uas97nT&wi-3rkn5T)sT@PX(h$){ku5mN{AQ(MU*s zWy?ER@Ty^dMUuvclhQry1ZTp0UkW~H|78HaBgA{V_{g)&iGuilO|i@3dG+~kil^^t zcCsKRQBrh`P?&SF_;WN8GKrERk~vx25sgI2J(W9I{3VZ6{qhp^d#ZP``1e@AOtN|> zi~q<2=3h UWcfMqEV8L@al*_-h`ix~!pS4DD4;7XL2~7%7@Z%sW}!S%;K+_l9gN zau(mc(M)_(oERa^e?}vswkAXt?*FD^wQ`{`>d#S(lf{22@!A3S{#$(G1MuA?zHh>4=0N-zp4&Y$sEBqLwpzLt}Wk=;=6DF zzI%wTTi}avvbd-Cd{b)YWPyE#t$=UPb{Y^1n}w`JfpxEPEJUqvvcQ5fiM*4=&I6$! ziw%}@biGSC3Ui@8CkyP_$d`w^%*kTc7Fe{ckU~7gd1jZdoasT!Zn5IGSMt!ex2!^^UCkwjB6ry)laz{WuU@*uOq1S@# z9>~2X2kE8FJ6Y^g4oM^Ice0>&PeE8kb50fyR9GDQOEFRR3z0S$v z!7ZU`oGcz9s1+&+!=El4y%gB#m+>hRuB&_`>vDg9G1w;v3U-m|u*O z#mts`&vLO~~WC=ZK5K|{2AsHlBpd3Y2G`l>>q z9v-21)&{5tlR3u8;sEjSY;AmE7xh1<8YZ#iccAzfhhzERC+$JvJ0sxJrKmqYAMVRS zeg}(>^>Q%u=X4P|A$a*Fk|N(D#kcPOe20i{QOc)Fr_(Gy1(XnS9;(Dk6o;I~=gYTX zYYB_Ph3_yWJ}c$Zt)nbI(@z?ap7_@HaPbB0q55eL1L;IKSsc+Gu-?hy$Uy*E)j=I7x zkdKbd2mq+=3*^HT|5&A?$x{b3L+B74k5d?N%XGb5ht<*J6&9$j{u6XS>=Sf=JoPHS z2l|9OXtk{am{Rb)KaD8wWN}P8z-A|lWAlJ?tTj#+nV98H7RLz#Q1c-%SJ;BUfmX?L~=?~wN9H#ImDIJ426&rSOPgYo9?A59Q0IKWa z4pjWYSio!~_0s~ImbqN?k3JBuP8LrUAhvFEF=me^!?1RdWE0r3JXoA$RT>-3gT+Z! z1vVzINcB@lQ@fo*^)FB5I(6m7(e?8;tajr=)mkQvyrBMG!`vcNJWJAd`<1>W#{cbY zGdfr9=Y``ZL*Sp#!GIq7eZW<}G0&0(C%p9c|0-D)B%JMMLSC@vRlT1KS+mDW)X7dL z4V_8ev!wWwA%7k_Q)!BxCA$vvlOZTwYI9rXv%|SA9eqjvX*aQD{Wq2MYNZFO*H!7d zjEbHm*otWOAf6>5Z>(ntb^uYA9er~|eRP7K4Cxu0i|_yUJ)bsVQmA!{{ZBxk zAb+3zO(gl)O@Juf&O9;yYRinhy7b&Qw& zREPQ8%$oJ7+>fdJ>>gJKvz_k9IUDZnN^GS-uXnc}Q=$Ga{IrHfE;{KIkNU5*Z-3w8 zukLXD32JER`ycTB9k0LmT7@5=>jMcBi{r7fZMPb#^|?_Exf)0%?nc$n-Rs9xP;6L1 z|8dugU$#$Y^S)ntb@pQ_-@5Ch16Qho6#hku%bu8xj6 zgj_|@ArS7VJMze9es0V5>=0PiqI+|tsqEjv;&3f;Ev0*RD-Oda#Th+sbnTjztNS|Y zUO`+L+&^ECbOApNW=(h3iS1c0tP@d?_P=!V{A>Ru*IA!=@S~EuLrL2I(#`#Ueo1O< zR7-c{FW!%H;FTspd1zd%$r zs`QM@~N z{?>b+Dx9<&^U`oW%OZU-oct<102OEHEni?R)p3tB4t%3Uy0GxX0y!&R3n#s99d-2| zxyS>23qMHLbVpy-K@;$=iO*Tw`?)%Wg=Bnhl@52+&4UyPCM##eQ4gH0EMYiu%}C>T zuTqvi3=h*+=^WX?p=@EkVR(o`U6!Q}!^8CRg7h$2xu{EU>|7Qe;+TBJ^kI0I-tvvL znR`kW$jV{1N;q;74!+6BHB?Mbcv<>{#3Itiw2|#$!(WkX*l?^D>p%T%M&}YK3SE6! z2mIS~po5tH3%<>FO?k1Z2c7a_l`UWo^j{(Es2iT}7^_(PV@l3_NTk7T88>OK4BOn( zRzo6gFCEw?*Wl6L@^gxWhXf{V6%5kQA95cOX^@vb8cdU)_8*evOFGM!am?~9rl*hJ zN5=zoFg|eoRUMQ)rd=sn=ND>MGbKFO>l(aRzosCg-u!ckDb|so3^z z1;Pe|4w!rJ`g^6~_SYS0e7KL}zn`D@EB=Gc0pD2z@EsxEv&BcAWnQYpuTmV?W$}2i zo})PGvDu52oJ2{{_f%odi*b+Q> z7Ymq4R`10+o(H69^*-!*TF#3#6S3TjbzL5*x~!pSzS!Hg`m!epXIWzh(^#Jej1$yt5R%zSvohQEW z0r<`r-?;_87_ZV7h>u0+P|g^>3&h7GU0c2vwv>~Okb1aKe0Z^j`DGoaThUN#p5S|t z_%2XzTfVONE*yaG#p3H0_+q?RFA|?`O6|N@u}>Q?I{Ng1mGzelh=t8U;2GA%1f)qAb&e8SD%2AlR^m(yj*G9fP++|*@FK>ZG+X^YfL#|hpV=-6i z_hO~t7==KD0rtu^U`>*}svL|NPKg&QZPTbsv{$!6Ym)7fax`Wg1uxbR3Awy%nHTG8 z%8_{9E%RcfD}mA?Ixp7Owui_h@m{R2YY%~Ohf-YH9)dB+Ao$|(_2m!@byZ(}(M6^Z zy|a=#0`d)mL8b`37Hs!GzHxGpUfS#f*OLYLrgBIcVZRqEy?YA6ilOsjeY3)XDK8qU z@?xcvPcBn*H0a}?vnx~YLLh3cKq2E*;;;v3U- zm|u(+>)TrLkuiq!cJT$3M#om-#flcv`by79qLhw6c}ElqI;lf>XA}w=qTNFtEicQv zqEOIR6$C0dvqpNfgrCR`E zyjVZh4$ymEje^}V>&e_O4^!yJ1&HLRi`6v<$v+XB5dct~ix(MvQt4>&)B(*9Iz-2( z6h_=KT`$*Rb#%4D0@bmCS^ZOCfS8XTK%RP)-vj-09<O)PRX$RQs z#roMiARTLs7i%VFxfko_goe`fm-Ax%yaI?@rtr{Szo4*ar2~>z`d-&d+PUaRxILx+ zV;;0x=>Vn_D81i{^^1AH1|4On<6FV-*RL93O0g%WzI_hP-SJz%{T>sA3W7FT((ULTtw zKrvpdHz*y0I29XqabJ$j2mq+Ai#t&9Ux@|W>;N|>fHKWsDiRWXAb{Iq0kd(c8t`ZV zepP_jx}WR#`S92BnbbY@!D?g>cF&~v>+PVd*mgE3yjX9{L*i|h{j!%4Ww`6k?J(YB+wvC7$GYMRU%nR$FZjOgCsgTGZy-eODz7-E;Qk6j+ zC(LgPs$`LpXY772R;I8YY85ubx}-VD-*}O<=d? z!Rp-_4Gih5xS?b}$b-d6Rt5G$fd!M1CXJaqb`ItGQC_b4LNZp=ssEqyVD*J;0{iDY zSe#^48vAh`EKag2u%8GlQvDRt)Nbcc{kJKe>N{cdoHc9pHSh`JYu2vShR=0XN?Xs@ zf}d4_`*j_BPQWYoO3zZo8~N(T>Yjwbm34INC= zWA%8D|y<_ikY6 z-RQd48FG!W^SQZmj+57{JONw>PKW7@zdPkz+SxeeT)IYvffe;EsfEFb%@I9j&$pq< z$Ba39m*i8 z_A&e=kJzy@1n1J5l_hVkW3%1)F*~}YXjT;HED{|MZ9T?`ZNAd+K*n16Uv&Wn$2=W` z^W_p3#c=Y&LB_&Q^vT@HMp6jZt)olzpT|eT_o1E6q98o6K+eiHOpiQJR|j%|WBKZ` z_fwDG(sdh0&lgLFIC|pD111ly74hd;830{amHfA(z8~(O{+c5r!Or3TjtkOweV%P9m znwxF}bDs%eh`P$xu90(}#0C5C^g5GYz9Behy1Ynh_-Vc)@RCO1?wWA(e@N4(Y34}= zuamJcuJ@UMSD!^(BRSo5r?V&_44O6TjT7Ly8-+7R^Pf=gfT5M$lef;NZbD*t1Hv|` z5A3)|^gUpa7Jh7>cYB1>&S*=-heTRz8a&d`Z*U(HY3P^e|Z+W;g6@4>=Fs`mLd8>uYA++dQ{F#Q9Q8>Wv#;>&wM!cOgXiZ;`=kO7cs`lExwiXG z2cBPuhyEkXr-|p6;+ff!=U3uc*2vRIl*AFT{koEe&l9aYd7j^h=PV&uc|4kx+0H(c z|A*=Lt$5J4vh3*O=n(z?oo_n>+HfJh zR6Wo?ZNYOo=Ki6L#alLj*Jwaj4bgbBaQe;rJ%So$y zjPy(}8xUIiYb+yjTNz;de=&^oYsDPzjAaaSMDhQbXRND3`bHDhN(&qW)Zf}e0b`KB zKtTOhJQTgJL6k}L-|eBwq~g1;yYf)jL;v?)^z24OAVv$OSijN9dVXXNN6fSg&Jek# z2ik$|Nyo7YSf)!)z6W}OZl)=YG+7)ex+ADkpNY8H*}}!^M#r`LdHn}8fsG|*NVbrCt^187 zc2wN{iX@E>C#A`5XU~m%95~+GV*oyC*3{C%)k0K zmZ0Gng+PP>_J}rMO_Ci@4#rAL$;J}2O`|f=4s3Jp^NtK`@;@tQ>-&uIkyBE;5Da zot4}XkcSTjnIiOBu-yZB#N;5owE2xCjx2|y5%zB^LGPY|xRLx6rFxXYf+;T=tJ+wC zPCnI`*!{*5N3~s3!H$e?w$ksbkhXkt#J4ErqaA^l<)@nx zLe9D3TcSAfGd^EF+ZrIxXmXyQ^sK*|oTSR~>(>kMtgD_VzMwr+KkZ>4orsMk=Cuc` z-&kV)Ab?I-nT1{@GFeWLooc7Z3t|DW?U;=vo~U%BU8dBoFVmTfo)nuA05Ka&Jh>g9 zd%Ju5DA*MnODq&1lIzdCg(M}CKScpiRsjIS>N=Oay5;EwyN!ba#G$(IRnN%^3k0Zt)dPrsXM9@%kf&bd_bUFBJZQD81DH}WYFDn4$!{!iYCFK@ zjU}Fz2jt~x&BhX$nB^NwoF+7sPCr5)2BGw)D~!0Jy*@)>(Mks-uk`YbC7ziFtyVgK zDFsSjFqhuXOo`>BXXODKbd;f%Z!Ga_p`jymF{(qCZexk(=pxVsVwZ0$0YKfx691rh z(u@j$DI!D@J6&Nx2K5#Wh$$N&k>-(Iz5=0p>sk17^PttrW*GHUzp=y_?E&qz8;gP4 zRC`G3B|JjsGX=<4T(z;pqSy=pV&PYxN6ZZyJ!&C_p5`zeie zgb5=AM?jq&4>h*|YE?XxNrglvotMd*#5wU$CRG{Kal%|JsFFp>@)wOvVU3D_OpVtl z{%cBLQ(P~5;##{664v?+2fnr9`&Gb4T-l?I@o=WAdY<^m^B4(}?_oL}UQ&)Ljx<>u zoZS)fT&M6=y35Pzd!|fQ-!;NTd9jG~;?rNmW)|dNwFkGl)x@3j52Ou>=K(8fGYfiT z50afju#I`J`d6+^V9(Ek)$gWYU`S`h4JA7_4;Cj`71((K3&w=Hrj1-CkDWug&d$XCpzfl+9C`C>CDF4X-pOmJb3sin{VAA}np3nbdKcN1nH?%lnu0D1h%CDvG ze9INr=s4~NlA0zI`)R~X%|)(O`WZTUy_T-a=Q)D2h zi>Y5)zf0A!MVgq}48#4RJ)IMeQnvX8h7#V>`T6^)%`l`2=O3(dj~JNF;zy#Verdfs zGWARA-axFk9lkd?D`dT`J*IwXJ#B_84^REl`f#?8VDStKoBE~o+>c>j`<@qU*B`@X zoS|B#era9vx2a!RcMqjZ=!ddxjC+ceaZPQ8(Hl_iPQMvHwHZcQEjo2aw)bWjKav#p z*Ae>|eyLu73}G{je^QpbZI8|N0a{IEsfv{d9^w)m5N$oi(SN?u@o>n%^Y^kD#y_hp ztcJw?>iKJ>!>P?MybWOs*bxUd#XVlH=L{#G=?Xf}BQ|>caA#XMs8|3c?dz_ecVS>5&KO z>OfyV)`6|Y{<`_M^}@q8!@$nr|A`Lri0L!X<%N2mK-qccq*vr_nM_{*P3W4gM4v5W z*PW@&FebcCrZ&Ss4@P=n;_Q~Oigw9R`S-RN#%(H-TZxI>u;MzktC{MMXyZ+rVf<8S zX#eAD7B5|)a}`;C@j$)Mdbkqdg!*EX9}sPtDH9*tUZlAFbw?T>?&J7R8h`fx!RCPP zB?IvB#{FXPk!P8cDe*5=9N1;?d>ZyL#nE>)JE4-3C@H#*D$F^dzC0QUnM6quN&TL4 zLVZOv5+(Ok?u7cvJW}-+OQ^_Gy%XxIVgWPB>YY$uod?W+wv%&0%|tABLcJu9R9)6k zG^P}6_2A2%B%Ec9&I$E3dB8}~JYwDn^|f_Kxo?w@jTfNBZXymCO-*Zx!DKx@*g~NqiR$z<0U$x&=Ny<5rNUTu!~0 z?z~NWCEs^3j-NWZaddp$sDEraarN@W%SV^F0RlwqGi(K5y?sC|Y!(8K76sNj%CQi& z!U+`%&Lq-zl1lo{fl$QQ8!YGO`d#HHyz%dILdC9)e0jLboKQEnz@lx16yhP*yUVfM zS2JtYoPFxb6ao=2yvV1NI1$|YaP!FG1JWi<8gUMX>rMAT(4SZivdY-L~kM1R#wq(AytSnq^-{UCr&Seb=B0RU9zp>>$zzpivNdFp^>2pyv1 zMuicF>Xz%UI=V?=fdKU`dVrXV9zdRYmEQyXMjo`<)&Wc@8MQ0d$z=YJsOg*S0Gpjq zZ_WeKvDP@DW@45*p?*tfC>?vG4}(zpw-rVlx(e;}I|_?d`u}I|Ou#HDiah=tVL&`M z*A-Ea^}uW0MNvFfJOCAUb!Zip zb-fkQ^%f7j74Syc|F5#5DziGPUe=qDX7_vXb#+x`M*K4}GBYx(UPTokq0!?(s9z01 z>x~XzPM*=H2cg~+0`{>{i5d?={hH9Q5w;lBro$`<^=2J-wm|K85GnvoL8xC>K0KpB zV2KFPcfO%CuYl$r4u}~WAd%LQ(}Pg|Cj_lGHq)r1<{;E>wg+quLj9HinTzX!P`{m8 zAV4WWsNWGElQ``5gCzF_v2QGCSBDHq@RRHO%`JjXb`515HbSl)^w<;K2SeRhcd0u$h31hxi0aubSTp* z1~pHZKNnQwCMDO{)8BT>64s~+$kO;1%HK{IER7i>=cIXiutf7yNi)0cee?fC`FNNU&saY? zskc-&*AlN%v41f#8I^Zd(3-1>uc<@(fzWtdCwo+&HvF`dU*FrjbNjBYu6&gp`CGK% z`%)h_c=P4%5ur^T#Jb|JlVqg}kLc)EpHA~=cuU0_&qvb5>{ z3=0gy%KPv%tRIPoOO@0%`O=#=@0=>IVNh#kcg&i9Km2+UhF^Fee&K!NKOoLzHwoP5Q zJ3Vb4Ww&m6!!NwA9?h=13wv+UW-&KB3~J4L-tY_W<;bSX72R%tG0){EV}5L6&FaZz zqpLOU*RGkE%q*QU_T>`r3pvevQ0tGS36VOfm*JyVY?7eXpQuQFy-zLn7gxKWR>n5Y zqN@$!+z)E)k|^RwI6wX9EYo~p}klA$i#DWi^D46?U6`sp@7lE=?7F@8VY=dZIZ zZ2%6o^~?3seH_|8#_y;5{C>FzTD_RY!LfZT-N!Ngs{DSs&%e;a_xna&`WE7ctRB`^ zNk>o8!8biQhN}Fe$N0N2i{MWgBb#U3ZcKq^`jE~!?c?i%dxfmsjGy!ve-~yE{4sq< zN6>Koo@3{yDvGg_8hm@bo`&2^4S{ZqJLG?+4SS^cHst=Ir#EQ}ej^wL-(rL8%k|kb z>ApTc{1QD^f7~tSQitc1IQNOMNWW!H#ZUZy48Hxj>P6jC#+BGQBYK{BH;qkvPQT#W zUx)|){oEyIt<|oUz=B?@M_BgMp5WWRnuE-8oG)OR$3w<{Q{Em*hljE5$d-V%cd1~r zA$QjRat8w=$3vO1;9BzUrF^hs`2^q2Qa-+`fADR_*6DPsA+r+Bf^YAgjD$|2ZWYOb zZ#PRuqUMg`!MB@-NK7p8&%|RQN6o>vvr_>}&6i%Qhi;0 z)!ft_55B!m2$-mvLkxp&w`xKPp2=%p zoo190e0zV%;X&HUJwS331ITSHxw9*BDZ#hfNRF#kU(Xb|Z6!zWZCknRTIxv)(+&@m z9KpAKdF3^9=s?Am5pvs0?p&R4Boh0XmQoAp}(m(xCz_V%( z8W4*<3xUUo0_(wXEL5!tzNH738oA)xhYW;*7B*QPspE&nQCJI23%;da8@c*$RtDcb ztOXWh%O@WXy>^acaovnwVel;j$H)gF4X|C>fc4XC*Ekp}oJjC3W78<6+HS4T`sucN z91R^R!M8pVdO6+7;M+aoNL-i4f^TspP+r9>`1axLAxceL@a>-MA?Vz`7LRBT!JK3e zTsZC(hhVC!3%=^;M_h67YLNS8v9LRk(4$^5`K9_sEAoqDVtXCHVG`mU0wMM|z~>^k<|rT^^N$g1zccXop8DpL+wegX!!)*`5_&XyDF}J5+L9Tbms2CAQ2m zOmdO?2gxxHr^+GE_3dLMcbX@sLy;}#Z0}O}j~wMaR&w0qpgeTM7JhK5({HM)ZmIGp&*WVFnuBlWN$$*Cj`~4mdDHDeJ~2r1 zC8s|d5A|1jbdXL$@a;%@z~~e-#sPYl1fb{K@;M*g`2k&xmk7=Xb zC}@Gw^w;0E0Hg%p9@P%e1&ob?T@!qJv;ff@bJ?#4XudGDAON7I$g~5Mzes!xdD?(s z2<@-!7^RVi=~ig7HhR3$^k=4P4ow8aLK6XUR5X48`h*a)zOMtAQ`eb~GX_x@eEY<9 zfc=ASj|~BFtPR1prJC{J+b0PPqthSpVGu??PHE&}t1)fl)9O!Fn*P#^4oGP9c<}A< zA!xnP0nEuW`t;!26GFf~HY!o$!M7(04I5z#nwpVtfVQWErJ!~^_!fYs;MbLX@lJMq4h|T|oguk#9s6=_HixS|81_ub;WZYl zTsJwIb+Wn}B9vg3q|{F3Ypl;!J{LPl!LWEo2U6}cO#P$NjE7*&!GQh1R)t{Aaf$|p zc2-?qv(+J3nr3xiYXqi0TZ}XfGxRcjZ13x}Hq@)RlFSuN=6_BI)?CScU=tx&nr3wt zJ1YcB)2t3`QegT^F+Y_wv)kS`|2pN8WUbNDsYyJXtyWr<F{f+isoQYuw~<hS01W}o7O zE4SiA#|5#J90s0d<`@Q^$_!aQGH;umFwGZThlAo|fbPcKrXq@C_%&5o1L9We@N24@ zCR~$ycJ#2}*HnjJQ(dD8a+A6*o^Tlko_5av=tR)DX8O~eT+Pxf!@yG+0vZOMmaCMF zU9xcbSu9!p9|WHMR`nrDCG|4=JKx?Ufv2~rNPf9aEp}AzVbiUhEI1G!-qi*%)?>kH zq;t!PwJZFK-08GH(uH|CPcFd^FPo*~;vbZ!k$$u`v1NL6wKsm!jV{#zms^Ho>5IMe zt|hV;pwACJ)YFDuez`jB?4yl!&F$Lgj;R5r-;xc7UsJvN15E4s3|HY0eU&!1zDhdh zq+7qB4{!`s`ALuQcVQO6pE5@No_+WZ=|Epi4d~oWZ$!1PsnXAp|D87Kn&LCCFvJ(0T+ocjb1{g%0karyr-p!4^t7j;h=S7PgI zqZbJ8CWnO2S+#EUL1#UCoaBs1^XU&dVGdihZhX{FuO6G+O1-srPh}F&x!xRJ&diu* zG0TIi&sE+YI)lfhyFC8Gf^QMVd~skAJh^W0=4bP{!|NEXoff@CCW?kFD6d0vRb;v^o>iHRIF2XvmF z3Rr5^9MIVd0UPXJsu&OGydXrXudA;bR~>aNZYZ@2=%j!8qksoO|9L7? zd8CeC9Y7`I;73j4hvhJoLIOjuj8+WZ)S2K%@co+BRVQG<#hf zj1^8Kpp&s_6jSZ>tiV5+Noei0X$Llk?lX9VQsgF)s9#R#@@Am6-k zkWSk$pz|$p$ap{}-aQA&mfj~wrz@1EKU?x*vATdxoP2IEiMxQ#x3&{+3g~=WOQ?o` z&MO7AQZ-@vb4#$afX=t~krQMI9g-W0Of3pEVkeEfUa) z74r7V_uZ~IGXmw`lTffp6Uw`jP_Pi=9&%`*E>|U?V6Qq9+TlIQ=iUJAU^=G+biP;o zTw9wQ?j^R&GE8zQ?|qVE9!`}*p6lE9OYSsJPKP2}&e`6j@*g?MyIOMG)d}g?5U9Vo}=V z46Uj1f20D^w^IT-|5JSME*JNhHrkDXKB6@J^|vhmDFK}yZ3pOrklbx4>pf*e;(;o1 zg8-#!@IeD>#45HF}nCXUgfc*nHKN$kz zSQ`R5OEu#Gou3jKMyEgG!yt_QX{C{et;V#GPjzlon*P#^4oGP9ctGcWg`o9D2QVkk z=+gr_KNAA>u~CT{59s`Fp{(M+K za}Ni^j17<|>x@TlqJo0+utWTNcd9;LCsbKmfm%3Ruol^?(F)-Yh`+x?AhG_3+oj zLYgl75H&IgJ7-b+jdoC0ZQC0Z0iFL7LWQ@CgB!hcWR$Mn=mpi3M7eLaLNw{BZXkUt zL~61ai$H@gWrUCsP~T36VqMq-^__Gm(+Z6Y(&^;7#COx7Osg2wJYjxMP?4LI@qkX2 zutrrtmd4*#K0m~mQU_T1Mnj-@ZtZHPmqnbYs!O}FV1N(`<^k<8Teik$H+a8@D z^tv_FtGSZ+{3i4NGz4p|WIwQd?w?q zZoXok9lzq^>*Q~yxHqS5D!cCEXJ9s+cOQGnEy};VJ2rM%_nTWkURSM;7nXcS@g>mL zE^rGhA&B714)hPx^7$Xg{0{YE+3Zs9x{F)Kcr~Lx>wvDFTGwBzuGfkm{KC8FI7anB zl$|4T**P&e(wbzQf2@=2biS_T(=p1%p+o4}QRq5tAln{+txx{aS=awXsVrwx>;BCh zW_NB7KlZ|=Y@0mrk>@!4FE_4QcUE>zL$WMfwQe#yr&8|R@uQ48Uy|k9GIG_rrP(=S z%jGZ2&N=q^by~O~u&m?IS?Dy}fXp7TA6>Fcm$Z=ex2%8aUzS+>%jUb@W8QoNeLbh% z$oyOHJ)@tfq8eFT-Ne}F>J_F}p`H$UoZLR^d%4=K8n0h;-UiYg^+wMB*!(GunPed> zxqc#Sx%CsSrL5)b+*;1~t>xBFge|vz!nKsOoSj?C89(LI6h_>(prx`fuI#fss_7XD zxj+%W&CcC(&0cq2bjUSR^Jf*6-FDekb1uB;{0&Ny74<^1UBw;4~i(PrbLW0QW9 zQI6kaI_+ueoOs);psvrod)M2ogpeC)qVR`u2x%sG~cD<1k-}rzTt%x;A`vAPdE`D{;Bu{+RrBgH6 zxk`Vqw8@88{lUMzD)ixNE_h~_rm-=S`S6YK2ZdW?>Mc(2-o*(;6el_kd;m8H%?I#N z%iL=-0sAiC(Y>9oIJNVeLwpzT$GhJC$Y)%6{syJLPsi`4zX5-bXr+n9R;tdlNv*UI zGi_o10b9vDbvCCSLdGKC4oPYmda((#cE}C=IOU~b*^tn2|M@+8hO|M(p z@|&F}AG3Qt1JTiXBR73vX8kn7gnBH?-fD$Terup2X(hSY=4q#VEO2e7pEk3#xKj%9 zWP9o*$;~^??wq12in`)ymY;L_`bnN%jL|s@)@=8p!>Svcf7QmaF}2t;A3nQ-gE?HA zzSlRUt*fh7b%-e?+qvz-bgsBqiT+I+jkapt>C4t1bk_KC9mj~OLEl%Il!y0cIo8!i z9vED;lg7448|m=H(&2}}_!qjOaka4ERQibztdT zOJpy7EFFIIhkDwm$6eZRJgEU@Pu+8N7O1n6WYB>tRxqhMd#j6|PWd=T^0;!2@%!mM zf7jzru{moI@Tr@xkDu=2vj~gv`{_P^T_0HJ;Q(lMFz0RiSh|mIdRO`Vbf4eKg}=5h zdHT@Dj5c*&qHflQDPtdP*d2S&$5I2sE_lT3&H)<8jAi;K^7qn4y;J-MazEPJ-8rM& zPUb(@@78rbgk#(^ek7yoOP-F>@HG(pc1$|HC?oOPF*wEpUUA&jvG^eKVcGGNMt6?C zxU1uw$3MPY`Nnhk$lSSeB?H0ZXztusP3c+n{CshjHHW)<*OM$iv)_1R=lD-7V%+%z zA0%^T_NC3L1P^lTvAL}+byyI2EN>b2^iBGoEq8U85j>0|`T*k_pTK!crxYxSZW6s? zI#unETE7%K#q^Gq7vm$%2%S>Oi`kO)_6Zywc4N-mE_E zB=*M;slKkhYR>iD_z73{ZkIi-fM)np2$-mvLkxq&{@jEVJUf7HxaFb`9=B#<)spdS zn7E-hHNw*fe@RBfZ2b`VDf>?GtyaklTr2>k1d07s{A~6 zw$(r==wg%QkvhI_9EEknv>>r;H3)#n)rX@pNbG(suozoD`FQAc|2P(FPV@@D`p3XA z@_|SL>;Y}S`f0Xx9E=rCBuI?0X%tg!n^tK3blWzLhOH|>Vm=ajIo--2vF+kWto36- zVz?40uVNM?_Q3WKr6w*&Z2R^QbZ%dZ9oj=MCmF=Ubi896f~l@9NDLR5Llk?lX9VO< zgF)s9#R#@@ARn}GkWSk$NbJFJNCx5bum0iPbCAq4pCGP>D2>jSf9M*E)dh*+&B{!yHzr2(nvE5qA zQ8*oGcgcB;hGUBaiD8Ajz4CpxE6$8S*&_)Bn>3+3JP8F0G43IU7V5HR5(@UJL!liW zp?t2JX$R9eB}i;9$#HFMa=4e+GRrW@rM$f*$2^=WhdkG}`$+CIPfmxT_;oQk$Wh+D zlH-0o<)I_C@PnwFep6i~XJm5wNp2UVw3XXma*K00#u0dBc{+&@dLAITrOKl`lXLa6 zFrQG+^gK{aX_bAUtN*FG%d*_JGYnVuuU@$Sozz zrdx+BO1qq47OMQnR6zQ6N|4wb@xi-X++*5kHwv1YS`Yv!L1K?;2iQMI?9l>5bIg_L zpgo!&npzM5P*ViOfy(~}@iF9S1BM~AzqZFHjXX@ZLYuYGW0mH0OYY{?2Z;e94eQZ>s#)HI;6dE?d7Ngo22?uCf z5SD`4@gOk(nu5fRQa(I@vqXd#Vn>GsH1}{o%-8^lvd&ly5?dI8)*G8?)KPPg*rN7; z%|T+v2#~qBE=cV0sRaU*5+wEn@iB?hu$hSV*#C(-@j83GsQ`eQT-@HuKQFSMMP)$jcJFyj_Nmq3P=_w&nlf_sB8iXk$gp7bXDIJP+VH4C- z)1gc&G%`r1lj{;Er$d=mF{pXMe43ylHz~Qsp8nN8mas-uK$gZ&SN^yd{G~WEvXiL~ z5_^W^82$Zcm;@Yd*b?DAA&s07aEkzhdQ{&_197wtM!A=Rmnqz_bft?zH&CSL{ z-Tj+>V9yG{nnRuptlDB!l|Fu22$ojOIu(g=aCG1G@vfH4mF^k>d}B(c6E3J)*-*SHr4}%0bh&^W3yxPz`D!tcXYqNx>@_b zL_T^7|EVnutoy|YHwJ-qe4TK5VBOm`X<*%KRf0j7TGwM#*K5VkLwJ{BUwpu7#TLQcJrVNhPSw9I_E7o=PCr53$RtBHcRAv+Ap z8wTawy%Fy`yE6>RbAzxqGSfkMTgoBqAZ1c7Nyd-cBtd!iQL+5Gm|E;z&z#MrZ+4%G z*_NwMTp9N#*^^dHx9OI2Zf(Z+{dAwd>+%0z4Ei#=FxY(i`00LqxmOBbmETYI`4@To zT^*bKO`b)JU#_3-wDNHmX3|P+N|!@M&JNw>1IQ4V(I8nYg^?R&P>?$zPW8vgGEm~ zO+h@8;f^1&v<+V;q)(;z9^~G0`Y@1h7|7=?-P9clV%5!9;Rk8v5#}Tt!#XSoKKv-- zkTJ(N<=iKDSkAMjZ`#$N4htd=QuodJGvg4ly*qOl99Q`)pM7e1F}=a{3B9XKTZj?&0O?-km}=NXU*r76TEi63OJbxNYx#kv%ppV;2ZQsqN9|Sbsekr zxaNa!Q#fE3tgYo%c zA^7sTALYx&DXgNPs5WTG~2=-D0@oUu*FGv;iOT_Rm3@FVNTM@P?|toymYl)qX_i2JH!J{bEl;riqn%)JZX<;vSbnebRcqP*j`y*ooU zHew|%9zYIbULrZljK%ts{|e=S9m~f_U#dKBS`Gb6@GbyK5_PNYUTN980RA}{37tgU zDw4em;FZZp)Z9`0T>!5Nk?JQ7OysEfT>!661uQjdeiy)NLcj+5mnz2J1#nr2R9{zL zwav0h-}nhv_imTHdSmu3fY*kAiK;oo@Ld3}YeEVpF?7Rg7fX(scLBUU84?k$o#S7&YIu8`b$1IWEqa=nUN%DVvGCOJ2h+Pw>a z{%I3NCw~{fl>=hYXCd$m>+NwYRIPaz06nJ{ymPx(rNm;02nw%J`ibuy}J!qKh3U+gK?82 z@-6_zrcq3__q0Omr`vnuXskLa?*j0V(97voz6;=eaU^c1#oh&gD}nMVX72)ce|v~h z6ZbBFtJ_1+xqU6JX%E4iWDu-`uZ=@6)zw|L;v#d1VlVcLfc(H8n;z=z_H48rN}0>HcHAlVZ91aV!bG;hg^#p>P#fRoQHCUN&JfDgA5Z+aKNf3$>Z zco)Eb3TmZl!u02sU}^6H_(&f)K?a01m~KBRxiKC4<)yp}U_(ne3a2AoFFCK#aBPux z0bqr^z4CpxE6$8SnMy*zCQT?GOG3dyjC;tTg}Qt^2?cxAq0kPWP(HWbX$R9eMA)SleYBg1@PbE=hnID z34B@Jbi0txEz!?P&KnQ)S9^4jPQtqYKGzPbf|0^VI6&L?!%|Q? z{w@Fjn%)KQ1Lea5I7>u`zH>`hKywcV#EcD)DC>;=?@@sMFa)hPHq)r1=63=7s6C+l zV#dwD8`XMf>IU|~+W%O9%*A!@0{BU4fdFyiS8p?0;17Db3psd_1GU{MJ|=M*HWSev zQ~gvYUT3d26#!6^i`!fIKT8EHXHvH;uw_|RivFQFfIm+KEa$0uKz^BTn)MPOhfd*m92q7b&ZcB$^UDyP5dpeY9g+>PHbaGwdj&vx~Dh4%An7+HM=VWOVg|l41;-d zLO+X{KDPJux|g7m&CmSQWd2zpSaT)&f!#X zH~;KhucY7i8RQl7cYUxe+JND0~+h=#be^l)40MFn4J;i5t_0c1F?J4xt7QP+e_xpS#cssyxKb$u* zHn#AH%;OfH-Mu*ab^!FHmH5yaq$*^@-8b2`NZ(Ay)|$UK;ktR-iIG8=TGuhv^;+?R zQ}{g{$B0YZ!OLuj?)q zdisR#XVsqE_TF&;<+-x-F_md#GgFzd+0Iw#q&NS8Y6C7#QrqCfi)VL^mCTNkp&i&Z z>P-WG`|b_b2_x$$>{aj1Dm~a6eExSy<@3Kw!gzJ#M;Rv{evow4lFH|QmsCFgyTtKR zzUr0{SaeqQbYeO)R}n;{wf}nL;X8iwBNEQ3H?sS4zdxVm1R0`~nfaP*zwZ)WpXukW zx_YPG{Mrrfod3O%ufE{KE=N`kjKBV#_w`8Hk#@}o(8wSDy6q$G+;@vPr|*03qIz2& zanaQ~AJ*HT^s99|hw4crldJ6X9`|_#;-t3f`L#Bn8XQ0Rw5_@`SrJ@y!dp4?(bZz~qxUrpL%#jgDWz{R=jNPaI5Vx^ z#GlH>Q~5(kr#)>Q-_w!y+E3lHK9yZGS@Rd^tDY{Y$u`2%Wli??{vthf_uK5|yMFS4 zS?9lF4sK7!x+&fp+5GnX=5F(z-iCe8f5+8-xoy8|NTXe6a+t9s#b31h*z7YecxN!m zF4*gZGwLjODkyW_EkFJH^Gp63)ZRhUg<}iHHpvBrOy{qGbRIa6)KIHYZ zp%*ydi!Gyl^q)?@lMw{W*z(-U_0xSE+A_xPr~CX1J$?iYpEd)>_OWyy$Mmc6`{_Qvl?#7LpWzw^vU*rw zB^^CU2jBGM7^?D<9^>!AEP_8}jLbwIevlNW52t<>{xMg~?z~)v!dCQuILz zekffad*`M_g(#O=G+5Me?r|Z|8WI$jqO9gMAaN(7z(~a6H@SmAiCiKt4|2pQ0eGF2c9|H zF&PoF^+V(#u${!WS|u}Zu>h133jQGRuN7}wxd%&bVgR{^Nbc;4TuNy6LnX&ms;_5? z+`}ZdegL_hTk1&*(+;~xj!n3D|RVLEpKFBYo{1;@$f7L&LO1wXW%cvC3&KeU8u2nBzP zpjN6TOn+_(mKF;B*gkTC3<2c z-*>y>%m|cuNhsK)31xl~3KnAALk=y}Wh4m&d)1-P4qfGQtxP+Z&arq2%R?LFju1cB z)+UF0i7m6Laz{!|f5~#lbA7u&LZ^9hIuzM*&h{>q|Hz@|QIg|#0`x>jY~hDWJN>4* zO3ujSju!teN@**%P;!fNImQuqWqCS@5PB|>+*0LHp2@lT9rKBZNKwCI#D8WkNBy9( zyygaS%Xvd#Z>A?xH(pp~}am0@AlrLcyOT zK6sal8(&7dQP6Rz1p$x}3jXAFfc-L&2XeG>lGv#D_r`{TWIl4_o>D^_fabHaZ}o(c_`ur-Y#O zMh7q_&*;-b!A}hV``D;Njfa9iOK8{#Ta0RBBpjgaw6GM^j)#H+&=d-Oy7J)xoFyW} z5L+A;(A>iTF=GQH$~t2;6nsetT5oKoQAf?8;7i*BHiv>Q6CiVOT`2hS)B*uY2?ZY& zACou@>$|wI)Pewjnq1u8%3qNRSk9zwSzybutQ7sj2LiY<6|kJA>H!ZG;28p>ue-I5 zTMwTZ7SeRthp3T3*g1>hXSaj0YTMqRxGg&#LWQ@CgB!hcWR$Mn=mpi3M7dS15KX$O z8%V1|q$Z282s8*&MhF=JwI&^kbzu|K+H@$>3XKfX>Eyb^bJC$qs~FTgVNM7ta+8v4 z?CGzIW(jLl1!QS_mh#8Nz|xp8;&ivAZSiq|?D`xWFtGBZ_!<5E!>cL5EP`~W5?;Md z`T8rv44WDsFXuqYeTJ!jsI`6&u&P}E1njv2^QP{8dRZlH4-5p<*=_W~vo=-od4qt} zRq~wlN}`ul&h}Xisig4vX*~PMwjmeYGI?9THwWrM@#x{=>m8+|bKXWwf+od@J5 ze6IVt?h7?`rs&7o!hqbF_+0lcsw*8TwXT0qU9S~C_G%lDOS_1UVB1um&E8e|v%E^x z|CSqPcPXlFvweG9#8DtMpt!5X`!+63n`;63m+Oql}XeLxxtZs|2&I zs|2&IYYt|`C3F9q8)DhB!tJ8g9`oifYHj|l_ny(GgsDar?A07Oq+qXny2z%H-s=~g zw?UFQ^+wMB*!(F@{FbxNV5?VUEn%O@rn}QJc8+^+=dPu#<<|ebBZp7~|+eO+~S<(o9)B$O1U2R2ro<{mYFC7Nsw{(0*EZBtfuE&40&W$eB z0aLo+Tl!)zy=#f=h2!(1C)CqMIpBbA>HFxIIdl&tv?N+)+GW=S3k>{SV=o$We2^&OfFCmYOvO?7TPxbia~C z1Exw9;{iMW6e88v)mM#S$H$Fb-Md}(xB|MyOG3az)f{3NuybJ(Qt&%2y5Rz=zvJ3a z>F9?Lei?pgG9qT{hse*07m07RN@n0<0VpM4=VjtwE8ezpFPGfJ0CE>gj({D%yp+J3 zOC*P*Yb*B($q}&AR_@Z4deXwQ!#_)ofE~ZQ(s70kRBRa`_e#l~tFyLpuaew(1IWEv za=nUNO2E!*BLBJ0E+Q`+1voc`k4K1)3TR!=C==H`p7HhKU0XqyFBOiz~!2YET zSU=6)6bEC46A9R1Y#PN>``1=z{dD`cI2x;tO2CefgkDa!GGOQOI1+2&Silah1j?(J z1?;@JJw&OA3)p!}dk8wWuf-MZA()d4g6A{d8i!!2s|(n{MdlF2UhEkG`L@9zbA)09 z+c}U|ZXBf3HVoK#dmNHMI6Yto@1BEXOYalJ^$w+ZOI|Ei7qEkq&n+f#7qIircH)|m z7N~>_riAK@9Hz8)wS;O2*!g!strR5FpId_Ic>C4)^@cqa)$NL1Y z+*Ohr)3IM(O2E#0TFOx@9qGN2^BN7u775tF3b~QA3D~(-{9Id`oS;Ouys~|XNiOAmKyvy^mP045Z$BuZ z(>ysHimV*lyHx%oM|mHT9QUfx6CJUIAJF3JJk?clMkaTi_;*oCTe%NQZgDQhI0COM zPbU#V&;O9zQsq&e$+`M92kiW(_|MGcs2^08H{CAe^W6AHB3Bt{z|NHT;9V|md>QRVK_5#k2!ND;osYKz>>sf6 z2?3%x=Hf0NgyuJ-76bs)^fdc{%KxPJ81l3M!w}kE+ozO99;REN&D!YGO7prUck}84 zb^x((27nwDjbDJ?7=qUKbpUhnVn-N6VZhFRwFB%Qu=AM^5XagOuv4lT57_x{p<#6T zBR&km=$};@dDzPDub)#|ve5wvjUEr!`FsdkZ*%~2@{B$`VCM@VU>_TmsPTZEFA5DC zVT)01jD!QUeJLyjwc`Oh05k>cd|CPM0L~H-Vu*buETFlE17gMoNR)NPYQWA{L(qC- zGmScG4%oS=Jz#Ud&esIUTwE8hb8~8e0Hp-%d|iA@;xw%9;=Yku5CBk z&ZKTxV9Tr0KE`Q6qz}a~8$lX$NK1 zw!J}dTlTvlRCvocxY0{TM(OH}UQkU*l>1&QM3b)S2GaLKq$Z282s8*&MhF=J^@DUM z)`d+_x1>XvR%m39PAAtTewYqrTE(E|3G+vSirl2+8hd)c4og_0Dj-YaA1j})d9gHR zjG()JiGqw~Xl_ClgxpWW&+CNS%H1kC-p$)q?x&I)mj=EZD+i~PT|(o)9icb9;b)S= zOZ5*dq6BL>SL<$9f*FDIbLH!=43}u?q1Q$1$M(KnzX|nft|W6)llgxef;CsNAJ}anSej;a7P~zJ zOVg|l><)n?nx9IV*=_He|981wC!Vo>baK(U)!F<|cQ2DcUNL_$F!xpl&roE)?I%Qb zyi^QG7HNQeRaeGMYF)pix?U@Ou20%V zcF|WvN3i9xbF!4kzoySLrbdO)4 zU}nad30Ug)===4k*KtdVv=8wOKbI(bWsPYABs*cbMM8FhODRscR4h((ToAt)xKO~x zR;qqPEa{_`8}SjbLe~~mlA9@r=U90VKKlj=A43^ky+U6R%4`6iMgI*ymw2}ZF*5DY zEUn|nI>iMCO+5Tu;)=0s>SkEmw__PH?mUcr9)2#7F5@0+O$d6fdb;7~66Gs(RgqEQ zmhqv*30Ez}2`kFtgoEOwg)5g>Ml37a$1@E-msr?*lePxGP0$+5r}du~%vN*5&n0>t z|85#AHn|QzmzZBr;6i#M!_OsdQYXMuHRc3{pG&+)ef*K%M`@b>`=3kPUoMjf;M7}2 zn``B}2|ky2fQsdDj?`iwv)vZi?;bp9%OLA&gYd+E)W*Vy^rN*wq;q@L(igeYX%WK< z^K>rG;Rl1w(kU+%ElPS1qxRV0gq{%bN4HFp$`g#KHIRR4q_CUVpq3C*oC&s_C@rDn~M&`+BBCLf=Pn zlLN?YCAswj$lbT4p0qISa6icr3GLUf&Vh<8BjoNcxpQ^aR_+0kJ8uBFttHp1$fZO= zZzDN3l-fl?(?9)Dz=MO^4v0mcg}`G(fwf&63sq|(q3OY;MlKTifdiqSg-w=6>UjG& zibiG@I~zno)31$OeK;#4p?7G3#n|%6$3w3j<5);dkA!C682Lb?0k%^cuzs37C=SL7 zClU$G*fff%_TW}%{d9Xs9F1A85((`ip_kLGjD&t@9Er7XED{=50_9cABB3AF9-`F5 zMMCe~9)iy8Yq3jv2<9Y%;HlYN;}A@Bbx#lCB6EmhFZPUp+-)$(9HAJ&b`Iq38wcsM zEgzCTUXXjlA(a}5gvPt)AlVZ91aUoFY2K0xi`7L!ON5grrUiaH>P91yp%}jeOt;=HXUg{ z$$5>2V~a#WV};zv`M%o~XGWmxpM-)MA)S&XJodxm|SJR_;-fTb#==j=(F+(@BIV@6nQ5syxaw zIaj~tNa#Z)cV;d}{h+cuvyV%+{{-aygXFyNP=B>Y2hpRyUB$30umVu58jSat_JGZi z(2pGi(A}OYf?=h#Yj&#qxKu#;c1k4lVd8^#xw!FVv>OE-o>~w9DUs0g+5z^Dgq|-z zG{;>mkzbO?xJZHR;})r?0%FBBR^r$6GuAdJ39 zY2;xmzrP-%v}B_L5*j@o3H|sGwBG0d=HwZDdL;A{Lcl&YDpBK+&`%T^Ho_L%zhxvG zpzYYO6x5DKLIcng3H>DH!vi==M2H@KTv$MJ4+q4I4Uj17j8*6RSmyV3m)f>H_nvy7YN-IQ@uIdKTsUcF6#aILygefD0jDUJpIuz@|CaBZWp-d|@ zGDxSB>k_A@Lzz}FsCmL%EU3s$N~K03p;^KjRRLKVFH!!u82qI;GqRJZk1$>;IYxi~ z2xCexi@5gcb{)F2%rfP3(Ncu%H8nn7&ViJBA8dID)*MLM4{S69YYuTWu&R;Kj&3;? zf~9Fz2ev|B-lC$P#mxM+_bs+E)T_CY`1~gGpAmvJSF#`2nITx3W_1>Ob_kZHSsmE8 zz!J?*CC%)%H}lUCK93V*KXWGp1^=gh=6tbB8Q)fWHhcH4?oO$cLyiZ@6D}u+!C^< zq~WI`M>De&ZsG6eFj!0wgwQ&~clfDD&u#yGeE4`{jQ?hLefN6CijAA3j}YGT-o(Ia z&36Hh?(KZVsh!^(;(smnk9WQOkSvc+~nrh zuGC_e9ODAT7~{D1t~OM_R}ln58rvdmq{A0W&#pwpVEhX`egv!Obk+xHv-G2Le$u;@ zbe(2&ss3XcWWYCCtOHB$S|WRuYw7T#Kh)DkJszWkHUVK@m#yxQ+)moifvZO_&97Ts z{B+94MU%%>Y>eMe_xZaXe~Qid?FD@5#@_Vt(|vpvL@|Cp-RH0C0}DMI0Igheq_&Tx z`}n4JmETYI`K?^|Yx|O?4}HvNQ}-q6W__44_R)sjAFJ})1Z-{g1Oc|`z%xc>i8_5eQJ3zy(!-(^yI-a?ili0KF5cNiQ|+pCbrJI zHO7j7ttG1uI_ufvBxh7D?{Fnx$EA~#<4Y%2@*~D7%GQKr~WuLD6 zXXWjoGk9FO%i}*hZtwns&Bg<5uN*+`V9CBpa+Dbh$RhvM$^$!=Pr%k|lt*9bAFxG9 zqHZvbU#gDm@!!pWoKYnGic`Mk{h0AM0V z%>i4lPX#PBYYy0YLkNfqD1O6!N)WJBsu&O0dSi%GUsqo>=N{q#TmKRQCaUHT!+@f@n5`coKP&&6_*ScA2Cg~7lz^?v#lLm{ zxi?F0VgR|fNbc;4TuQ*!6_T4AK<=%QOGx+=$|%Wbn+mpe;*KwJ`351ny=$` z$FWegCSZ#mTx#S3wyqio1zl{iJW|K+iKDQNAjBsK*rHz>x%zNc25h~z1r}q=Cm#>J z-WSJ0YI?vH1INe*A`P(jw*l*?+0}6{RydJ>Eyku%OtouTq4m@4+Bh1kj!M9mkAz-M zw=!Vs192qQ!m)rYTnUs{F$>uGV0(yC6Bn@cq4p4TZeNS*+CwlW83a$~d^irlR96?U zg^SD~ioMt~0`flwgUk_%5p3r`{^!O)I&H&%t&hYZl^O}y!n@}n+0y$2aeY*2-jWxK z)dg(ftlW71Q`(4V7mRdRD zmzNT-^@)~p6i!FFL2_QB;n*SpTUa4)uYBL_iZdfnKAD7qO`1?Xm4t$Y826Av3w8N) z5(@UJL!ljRR6f_rw1erK60r4O;^*4h9P@Ch9P(V>{PqrA^bj(g{nhmP374`_1wO?8!=k;#2d{Ce=LwcO_=w>Xz$9D!Gsr;`Yw z=NBZmRC(xWa;|>O0b5@b|CzZQ^@GatrrU*l;s(AXId44FU+vLBc;u~Lz}A=B12zY2 zePs|pciX9m*^$<+*{SkZQvvDQDFItIi4Wf8;>MTJZWQ#j)Pev=3D~;19bo@}t*;9Z z%`q2u`5-j^MruI-KuysM2P*%6#K(}QYcdR>{k45lY2;x#Zk~~k0^d@a*Dbl5SO4is zKrEaEAV)>x7ogt`LF@ZEfH`@wLkyxYVCy^W0Q(1QeK!Qeu{H#3m1@QVw!SAcj81>V zhd~(q`${7ZTlxL<2TDseIv}CZ;{jW@grN0C2QVkk=+gtXei#Dwu~CT{57_#V(6AA< z7}dr|I6&Kv!%|Q?9vwtgCd)*G8? z)KPQ5*3a4lHV16|T!75QbpczyNG%Yclz^>YijPU0hV@Xrp8MSQ{s0{EL$z;d3d2P9zYw*sWEyS0v658oCR(sbE}sF6X~Ig8@k+d)~iZEsKn zY~2w;g}01@8@+U7l&;?B1=W;9x!<)yH0i2tApJf>YO)xMK!Y%4gpd(Xe@KU7UDyQm z$8;#u3XKfX>Eyb^pVFaBs~FTgVg6ZAk(-oCjRb75gf*%HvNZmS@;@U6md1<`r+YWM z9=Dm9yMzHspQzB4bL99fkslj>ZTrO7{-Inq!apfo&FoHAh7m7}{BNea$ux!O}FV1Dh={Z{gI>Vy2Jn zeZ95_^=hsp^IDVnw+z9WE7=e1J|S3|W_1?ZDg;Z@tPbqH0!uVMl{B;4-Z%gKa=ngS za@OcXzt3Lc94hAT`e65O1BREv0YEuu;T;&44-gm~>!{IHYu4&hC`V1KS-W<0B1@~g zQHvJ}6)e5uJZ12JNdDkLZ4jQxkL$sO3wCpFnq4JapPVIoBR^9GRx1ye4-c~B`JT_0 z;~1GW;(daSeVOTAuhboxwUWUuZDgJ!ncZ5-Oh^U~-&{_oE0&DV?W|fEZsHVPyqk+; zHkg#mnM$y7T%Oh0_9oHk9H_%}lEL08va?y9#RcAarICl;{#EsJmF5kU=4%c>9DT1# z0gkw;K9=A4vO>9#IXeWczvd_b&k0`nQw4lpDj-#Nbj|`-{ey4NXF!iqS~hgh8V%1G z1d!R3w%YzZiva6#1|Tbg=L?WN%X7fk*pX`^9)>wLEHGTY1`lI^B{@VFN<& zA5#Uzo4HK(2);N)5WiL}@t;x!Daovd;a?I8HnkzX(L}Abz(GJ=*d7WPg9HWw>ZR#W zcwd8vX?0P1sF+q<-@Gh@(pluX2G4F(1!A^%x$R}3+T;@D!BgfbQQizwzC!7&@RQa!6p|~D@12_iZoV?`BTFa8N6((DT|pG`k9f`& zo%^a}Du^sgkP&UT)zs%FS3WO2ieE7lYNTug%XncF|1VCsE{Nhk?uYZHNAW9~KNiK0 zzSP0R>fd#js*sUZXqjOxeKVa~M^t(9x?*HFrPlS`s_V7lXDTW#$8;Q{nU3OTDG6bl zP9%!I=xka3^nYK|y}1jOjC~+=yKEV$PTO^D(9>taKdbiSSNt6pP@XGGAMlt)WgoRH zIy|z~<+J76{$}ZMtWNkXl=kD95Zbeo{q%KtSEtYv|Bg_5vW7}+&)1!^Mdx*r*-*Xmy%ACSIOFx>!%vLM4B6~fb{Q9bH2lOkOSIm|&3FCe1GCP5$DGlNXK}1sD7}%* zZ{Kh3Ht*?e*!TQ*T>Y2Z_PfT0+)NHLmbdteWh>WBj%JOS;`N4~7%x_5n{-9TGbGt0 zH2lQ4EYTY|`Rg09KAHXNjlArnmrl*(V6n+{_=)j+&ZS+3pBNv_ZU7V>frH{?fXh0r z_{|9nKQTW1#JIXcw$$3BGtH5j=64Ws>Mf&{=Wdcuj4x2JJa(H}>>Do$-yE|@vMf+o zw){~C*o1ANHqyCj;Gmk$-Lu-acPP*JyE=yO^t=s)n>XYgtqmd_d`qWXh`Y}{ZI*8Q zN*egn<438SHgAsE?iKFMF}tWtbmk5wHo;cxt&V=W-Do0@pQB>@e!9S29@bo3-0eAAO- zsLD@zjK2%B2>z75%2WhdJD5JCgHO7z4|5n)X+hskbAq*wV!GfFKlrZ>1gp(krqetF`;mE%QX z;y7iDiLG;q##rhbZjKQ)c3iP!a?J$7HDr3;c3Js`o2?P_i1Do%JA1>;Hp<&WXYjam zm&bp2+}`~Mn~ey-Z3mD$ShCwmjxu9!up$3}$^$!=&!afoE04a?{|z^kBQP$u zhMOIdkbQZgxyYqUMg`Z@AehL}HM|-*AJ895uh;=0T}|rDn}qw$!_7lNr24x0syX)%f5Xi~L%>AU9Afx}n};xZs?yjVRZ60-0U|X7JU{1&#?B7W1(uz8*b>qrAF?-z5@nAK?|EKkJRyjaTL}O z)824HzczC9;mo}h1FVBuU@^9Q^6|hrIF7}dZ2B8+7&t~g5NUuN(gv)bW{-@6p+e*h zH;hfAm}+xcq4m>kZXAtON97GSJ`#F4-Du0+{KIwrs5la9;n*8)a3xS)#q13?k8Tf9 zYU18-b7*^rSrsk*p*;k1l2wG~9Ul{iV5+MNoWMoq5XD~X83Fm&!60*lVg%bckdNCq zNT;nE%)lP6?XWl`gYZe~&YFDElF4N&i|XOsbC7K5eS)|SSDLrv#bR}DxWUQi7L&Mp z!_B;Q;!SV3ncots;SDzr>m8nB*e&c*!vjr^-<-*SAlQ+-aVi4nFSUf=N{T~21 zDjL54Jv9Wa@9O~O=2`6k`@iAlv=9)-+VF;(QqA}qZcY~(MyEgG!yt^l zSZU;8E5E-kQChOm0SS#Bf5Xkv5VYRt0OsTw{g?&5(Ye#OEClRhqY^d#hMVO=!$#O* zR2w7V0FJ{_P&@vH8vvT#a5DzDHo#dTLJYALVFArO91t@$K%%TO`ca2~t_(rzjmyXS4^jxJYgW-l*0?Q#Y^=*8WTZG8fmq;pW+?1p>s4U&3AdK~Hxf2TyXKwsG+> ziPNyYi(8di5CBkSmyV3m)f>H_nvy6t*$UC5tGa=- zE<|dw7>huIFlB_05m4*Xp;#9-K|MDe%CtfwgLFE%E^&4`lxY=%nkUTX2`X}vl56Z^ z)=aEEa(u~IlSMPJgf*%HvNS$N`P(Ujr7>d!-Tg}xWHkD9m!~A;o-h9G2ar2gayt$n z_X5fBb{k($e<|+tbZ!w%IY-a)BsZ>OU(UQ4` zMOC~(Vi*yAch0dqV3axUmfxxW`6YkdAkmz9BX4@~OJ?*n82sj9!Jx}V)ww3tu9=v& zK+TprJMFO_x1OP%&7YT_w096d`JxkMwmQV{P@ORbN_~BFJriGW4Yw@DmvJ+>EK~pL_$;4&YI!leDc>jb~*P8nlj>s+TXW|87c*R4M2 ztY?ptoKdyBrzinCE?qZXGUdGf&g34ZpXv5g#;r2c%MtX5@y#U-PsCrWyghUVk4txX z{D;Tw-G8vzkh^36xq~J93dvDsEE1gjOO*$9ET88$|5w;%`Vs#BBW#dEV=d z;#;kf8Mr#lC?!(-U&Oz50J%3wZejqrf0Z1O;=Z0Kk>dX*Ic^HJmAhPW>j#i~b4xvO zgtWt3BuAvUuV?8vLkB9hjF7uRa_8!-t=wBBcisSUZBxP-+(`PXDwC zqmxI9zkNU~`YZ&VVZ9@cg{n1?;`HEBBNr+D&Vf+S!Y0cjb^NY43hRhzk>d1gBUc~J z%1H5lZ-K?w^2x_TuXo3>Sd&eU6ldTV`9P!rc2yg&eww`}4u%SmNO8udQB1Y>wnFQt z+xy~ZtU4-@;yx03Io--g@%P7(SPRD@#c?H2Ud1d@{Oa})r6w*?{F?R3+(JP8F0G43IU7V7eeBoypbheA8tpnR^CX$RBU55vfcFEnsx$bC}$Tw9wQ?j^R& zGE8!j`;_FEhg0Q{=lb^3k~__l)1k{6~)RZj>DN{wWU~vBmW8jj67ZGcvjV z5Ia2(y;y*K&qkd3X-gLW=Pi*1m zBiN9x49a5VYRt0OsTweR`z$_d>uvHY!o$k>cMM z8aBcfquLk=2Wb02SPE*#BgFw|iWI*^`S1YF5)opE{V*(`xrYN{#s)}~b;fF>_>V%+ zdSf$ir~)B*uYi4^~-_?X0LSl`9{EVUp2pe7f$xAK3U z3RuphZdouZgD?N#0|ER+DquNJ)dTXl-Y*46UpK$WO7>S_Ax)Qkh#DD$odfmjc2HJr z+Zz;-;=c)@!du3{jb1u3N>^|6f@(^l+;3YUnsik+kZuc+nk>d5&>&11A!G#9?dedg z3!9+sNQW}5(8wU2PVN%vcj-{3RSasLFn=$o$W2PFv8P9hvxGIO08x-#?O?63im5y}DfqW<-1aN%>r~6rqGojgOaeAm!dcIWzw`1ZxhM z?FaUk5Ue?r*TAYqMmwr`X9$+2SsmD41?DX(`dQ4(Z+qWje+%_$t|UIc$^3VPV9k~6 z2gc9n$sNPM>MVAz5G+lzIg{ijS|8znS9R zoVKYEEtcl2c$CniT)ldSWPb&{RV*Hz(T zl&v0>5xRCFpS^yX>dtaDweGL@-4>l2#LsmhT@_ny)F+}PpAjPxqM>+>W2wTbXh3&< zR(4LKx%0{FoJ#rpDC5q732ry{|6(fJUlOZ{%ISy^YaaJe-74 zEf&rias9Y!G;2gVw?;I6Gx(R9Y-QFIp_;FIsFO z9Cqs`+%U6YXXiHT*5~}_NmCeEFi;i+;58ZL_)Ye~ogVt;cRzfq_wD@LSy}I+8PEN| zE8h3TFP*bN>4)g}ki2PUw8@x@>4Brq8(q8RjMbA_J^hL(p_e5V|6JdD(Rc2f_eC;# zBk%m!|A}ue_wyFptlN8v3fU0aSZ`4bK_>m;#Ac^#a8g8(L)o$ZhKI-k&~g`nP^_7% zE@Ig|)6*{2EB(UK z&S$Sa`OD{QQ2JaQYt1$Dt{lCoP`hs|fAp3+g1PtSS6wut@jBlB9% z=u)j%U5`f_O10`~>-1aUL>nr9Hwb2NE1t^gI=?e&RrQUQlF_ZSt%@CclxsR2c0#( zT*on@YS4#OCgstU=}TR0T!w^+625FxaF3eJ0!Q0Hgw=FAehvh zz177}r+mgEdHh@wYd_8ko)L;x6JP7KSIaq?fKf~(kVOE9rmt{%XCN$FDjT$9i>X*LV~M!*LfK9KSnu>8>u0-yJ&~$K&*I$F5xCM;~|W^fVso z=#E{zjGy{iy%uM>pwHa7ubM&+jys*jUHpc7Gz44f5u@Wju_*JiS-$(Xd48-elJyz- zVU^$ki#`2_^#tcWk;g(2e8wAN$`+0~%m^NQ0~qve{1)dv!Gr%}Nw=*wmJFQx1P^0^ zxp4<=JLc!w6$B4{mT~=HZ4b%MwJQjohic=8O`f~iB|q1$Ab57wwwt!ywNWR|t9F79 zo1hDIsu7aSv?|*S2SVe43cBbBccuTjyT) z+cFDM1-oAm?CD~nu9Hh9R!^=QUxIv$z=C$)X3HW7_TF?NkMK<$`2`;K-AsAZ10I*| z^7s#r+q?f@vmv+n0CERQcDCdwGZy4Z{uasuJC^@wm184rTpIs{Bq%^`+Cu-h~t1|@IPJF9XG6Pqq8KnflK2ZE?2awxdauWl{?I5|cD{?78uscd_asauV zB)5J5xd*k>lNP2O9xOS6VEuL|9cSo3#g-9r50TutI%_NUP|2M)fZW3**Q>~7k7p>Y z)HgdR{&B~8XUVyt)Gi2?{^^ebuyz>`i#`j1$A|)J*Eklc)&#-QgG-HE5bSOPp`e9L zmPhJ%_c#h`oM}O@^lKwmAI{1k*gaZcF}8g2@zCqxaV*w6(}Q3cI7U7YX@Kq72CScE zkBEb@!ifaIGB%B3s_oSZt)Fgt$I)1IRDxiAB=mB+l|iuk#F3~?EC?1?0_9cAf?)S; z4^e93f?)S+4?*Ylwb;Ks1ap!>aA9yj9D=E?E(jJEnL`wNv1bJ2frCNj2*n7tb081e zI7p{$7zBH89FjpeJqQ->o`Ymd?-Rszh|;_zFBYo{g2l<_7L&LOf_-E=@uncyIW3_Y zf?($gYNcwz^yijfX+f}$>LVw}fUpMB?V}|(renXnlpxqcTgp*59qAt==QSFR?J3LF zOpHDySUzHfyuI>$w=2$!KzU3O3N~p%d2A927Gm5(4lUH>aY-oHs}6;BI86E6lb{_; z=aeAW!^O|FwaMXL%4JKr%rZ=JDQ}+Sn1@s4kmve#zT{5x@3s=y{~%mMV|(OwQG> zIS6)v_|MGcs2^08H{CAeb5H0f$$8_U{%Vg7q90Yd)re3YM<$0t0X(`rU~>@c!a)Gt zZKfg)vMa?34Hu;X(zjEBV2=?WyvxOnFQeTs#p6>80w5&__6h9(UEtOz*d6OVWfbRu zN`0aL(HwJeM-M{tV^a$P0HPNF!tGeDUby{Bm#0@y(38Z+kmsCX2<@-!IHi$?=~ig7 zUi4(8dEJsbrS(CufVlg>-|GV8sA&8G^!O08zOMtAlNXQ4AS%s=nNDa2*gpvN#1Ih2 z+7JX=su>T0eTvX9I{gtJ2JNryB&Csut^EG_RHY>w9gxuI@gUffL(qDo1DKO%^yxvc zPYVJ2*r-H}2f;pFXxIo_FjDBm2WWdnSPE*#gJ1z@3W9y6^5FrTB_c%MIVCKhxrYN{ z#s)}~b;hdmJv9WaH#XC#qvjykXSD}x4uU;RfXu~pL9nN%76?#E5bR>{F^SW#zKdIu zS`YwGlZ)G1`Abs)%bCd5&>&11 zA!G#9ndwlh3!9*xoepJMp^-s4om`g~PlqzCVo>vhxk^xxo0ME*PY;4+32RgZWNExw z`Qu_>Y0MaLy4%v$mhd=6M_^#(HR5OV_YZ=l1hWXz9ff#hJN*M`t@62ODZ=3NkV*S9L7lJigtRL7pAy`^9>&*ZB5G<{l zbztX)U}@E?1ABqM5<3PKvkqZ<>lllL&!ZCdXh2=?Fls7|q%*Bqtip zI)foOJT6P@)G+8c`!Pn=5cNi)%`}4{ZY(*95Vv8_an?#|reV;rn?5(zxpB4S1y9e( z?2BWazNXu4D$8`g9QTGn$K^b-Nv9irfuKc(LC0Bl>y1QXS!d8A6JJtz$Db&Hq38iQ|JGipyTDL9lbC0wnb;|mYX8zcvQt=%hX~&w7>-&Gq>Ox zyV__Me#7{qHqzJ@X(OGByI8tz6lStjesB=9^o8y;!-=J%2LV>be{{}Idbg6U(~K_F ze=ZM@0pDn`4lKQEiR`71rNd9Xpq@7B2ac7i!y=e-OpL6=-7n>?>ef)GEpWmwBtMdElKELTx?W-nl^)P+>^#5h=Ou+Ogs=ePt z)}R6kh#N!}0Rag_Z~-zs2_&GX;KFr5%rX-a2uYYMtilV5ETVwO>K4?Cf(nSh#f4-7 zsHmVQF1Xw)UKJNyP!`uK-~U(Dr@OkRyWe^Tu9N#cbDrtxs#E9u>(tuS%c(cSvHGgY zhx|}}MrJ4SjeR?)2l}4Tzp8H^sr>2N2fxU2u0K=X&^ZTen0!q4@%l>`7wFH|LAhh* z9;bKUxTCT@yBK#=rbCHr>A;zO#4}jt!jMQ~d^0C7-Wa3ALqdkJ1_pB(^Cj_+kYV0s z8OYlOzOy185;BYluBTkean2xFjPR>yWaw$H)~G(S+!G4q4OlB+d8 z@N2qKOXkdO|FzzuBt(B$x@5t!hRZUL4vX{G4lW#(PoWb9#N4FSfOAwnRcVw18PE4= z{71&0{eSG_;6v`tDD-xh?rG8^&pJnB(oa_!*mdbR1;1Ts^!x6P%H$+UtM0|(IY;Gp zL?dC7D6Jxyqw*QiNR-@Dy`%Cw%Sa6FdPild$Wyzc@|m%Kg=OuI%4d}U{ntUYj>?6J z^^VGCmyw#w8k**(%R6rKWlvMi>Wv9qJq-h?p?5O;%Hl)(`YuLuLTK#^_hDwq- zDxVvTNVRoCJX5dl-P>iGUdnCU^vc2k^Cq3>4deu8$ddFAvVjPt(klwOU z=)G5ZI4XyB#^iTlk9N|+w8Q(Phof?sUoml(Cs2twLhmB!ovc`|dKXLYlu_tiBE3#U zFUC>%QtA1j)SII+{WBZ|yx6#Glvwmx2s}m(e^e+~VHeA3 z3V)y;g>~BqM`il8kuMLi!cqByJzz1mLJIM)>qGTetSv`6Dl>45LLhj6eYh8}ZkDaA z2V;d(Uu~9;YdeiX7>!lExiww)F;IYmb}zhlcO?|d{$#p_m0Y+>P@}PQTfw7 zLbW(5Un8jbDhZcAzXXeORKB*0o*+v^ZE(50PI~hc4)cp~RQ^nldSp&Vx?XxgqcO47 zI4V;MS$k#YG?k;9l(r&N+0Q{{OvMempUp?>m8Nv5gK(wT`*D@3A^g}PB|CM zu6I-hpv_VFyGlm}aF&P=L+pFy4BC4*AXeD`iCkx_Ix2s^4BA}TTt+>$J1XDXJ7Bw` z@(%>awYbSq`G>I?0usLa{Xb&?iz}&L7EEyP#Xsgi z0RJl%u((b&1LCOs69LlK{aVMbhwm$A(stX2s*yohoJH|ZdxNrK+u5LSRQ~TWRQZu{ z=|L|Y8KbKYdOjRS%pOg z>22~|;+OGIW>p>3e!~2fplTjca*sXIQJE#IQ5BG-@voKsG$pV!W{hBac#DFLuF$Oa zazgJnlHYt3dJjl%%Teh4R(cC%L1-r{2X9ofL-p^Z$1K&|p_&}5<$S5r)T8?r{Jqk- zxys%5+Bzw-u?H#6A=n?vVC@d2-M}6!gSET58W`4DaYM`gSO$x;tO@K-0t*&D-D=G2 zv2$qGLuI?#3(2*qt@gS8j38`vXdusF+_YV6T6Se#`|V1E`^Wc5=>t9Cnw)&Ccz zGsC=Q!HU6UGnX%FFD0`|rT(*#>c`SwD`@S-WUgsKJ6Z{R4w8K;(B!wA>p%aM8zv8J zTqWGar!$>(}$K9hXDhSm$H=EQq#DYJTy!=(|o}#6SHQc5<+|+%`~e)MNIE zklN+q>57W(PLt%?>4vqZUHK*EOdeynC73h2{FAVAW>D<<_ zxedb^p!Z*5-s;UesR@iaeg8Q3p|#^D;ug-S`-wOi+QHbTUNL!?v!a;aIrf61SGlPB z*Xg_Mo=sAM^je5UuwPbI2g~B|zdYvk%Z<2VVdZyyvpBM$yrOv{5@r<8SU3a(KkG}| zVw$-;4Gw;ChbMjEReP@aQt?a77fk)m^}k(x$|~`%S6JiCFZ$52qS8N{FDhVp#CncP zVNS?X2;>oFwmf3P=?QU){`v7I~bdw%S2b=Ul|6yzmXT6`S{?YDYCC}8Xr|`8lUHoQ}8$un@;Qe9dKR-W~eJ^ja zp;mYN>a6#(#Su-mmdtvr&}gy|KQv9*!!~>PZ(rT>+mD^PJJX)R*V8_VU;DNVPF=;B zw6&qlxMib2bLTH#HmGp96pD7>7362Vb00k`c;M6Nd-8P`kLhHg`#)ETIX(W+bhR88 z+_@E>b^RvUq5jtNoyJt%mW8ZC}9CWvD|(B5>}@uU;+wO&M?XC!aUA zzng6noSWR5%Y*G59Rc}n)_2&wr8UCJE9Vc7! zH*WFvG3{sWW>TZxH4JO+*3$5EhGx0W9epTUD$T?X9y+GYVxz{D#?8##ibF$D63%N~ zarhv}twc2mG_{SZf2M$}Z8}+D^uF@o(iCvf+xA&2dKxoYW7CACaZR$emd2hb^u7Z` z^_jxz1Bb@6U5d3@?XQ{J&(3dhN%?2zw>Yo7R#R7XR9arIC2KXD`0}+{X*UQS5e3)N zzK14mHicqbx@ZF7&)UrJj~AC0*vO3K^(Sw%_Mf2NcV+oOP*kHmj{UBl$a^ANV2{`t zf@jrXo2{Qbc;gEm`^HsM@1C$)VYxhY`kuY$psO~x8iNJk`0r0NMT<(ThbZUk?OsGrpRGUjTX0ana^dNo7g4FlZE}9*>S%M|E)9p z@4{2RJm4BQ@vSSCtx%wjE}s6>WpCQ2dLVhM^j-T!7WII4j@*p`9F|#s(LqsoESKtl zn0-V30gjt_`zmjfH$L+88RO6NQCBs85g%+00XTMlZ25-#5Qny}lMnf!e3&nahELmoW9K@4h-3Cu*P~}Mab9L10O}hVN4l4(PL++@?q@6?sl=&SsNznsv)qAafkjg9n?q6D>(FC z_pb5XF2;AeP)Ep!am85SOh01W+n7?&5os)>nWLF^n2T&-t)L@hY_4DoF&`5T2^r>f zZX{U}aDPlZBxD#9T(4Q4up}lP5;EhvUHJJetQXpCTOHf!*ggv{*Zkm~Lqx89F4g=H zyW7PIVbdRm7SA4-v+!tz>PcdbZa%Nr?c#5AqJWs2w5o8sUHn~Xlmi*h_i6k`#-IIv zusQGs`o}2rc9-t|NRK@0cC#S;pGpI}E?w*UP?RK$FG!iBERKMHBgfbF?yMDI|s>oCOZWm9A1uQIU-|b@EG9Xh={sHi7mkbUL zxE_LOg^BgMU949|YA$PNnx8J~ce_}>3>ayeM=bAlu|XSB=_6=tV_MDY;8lxZ)-Oa;v(hDz*W>y%x)JGrMF}hdK*h`XcT%+mfrCdy_nr6 zo+3TodW7YR(R-@&xNYrKZ<8MFq;+YBO{K?f7h!(I#95v|CFTgd&7^m-V!i4;O?sz{ zLhtF)>s0h&cDvYIdVVPNw%Y~$(=HfEwnN1hqr{@mLN=m!@3>_>7N$1rc0ms=Eb_Zu zJY!TS*kTvUX$o&ukHWfb#BLY#Ya?GCV#RJ3&+GwZxj!_5% z53pzV0@ls4=hTC-!l~Kqg0X2-XWDanLhEMR*7azt6)L-3gh<%sZ7X)W*rpzdYj@pl z7fdBkRz$bk#iZUL3QPQM7tiY*g3cXUv2E`VT$2m}kDKl4A-L2v?RLQwnL*@di8}&v z`_VyW2>A%MIFLI$K1gqE;RthxAfI0k$sioL+Xb_G2I7|9he~Qk@q&daHP*D-1(SSM zV^a6KUF_7GdfRRnJNF3HvfITA1T|kJ;qvE~U~#)$?9xR~kR_rvxZLh4y?F|U`NiyZ zv0IONWKKtVq4a`AV`8h>?Sfj!+ABM!sU#hNvU?N?b<&11ISPduV%$R>t!&F4Q7F_` z6AJCHr_y;QK|7eup(~loKDWTf(3>JX?yXIa>7{O&WtgO*_afNy;yo%i_@##OQbg|(_1CnMgqur?6G&UmuVs^Xe?+vi~ZWq%8h~-q5 zy#>MY>9H9B0JXV-@22$qCC8AbYcdR>U345E9%)qFkvd4nfEnTi-I6Dz?tx4H+_~~Y z7@ECofxZLxW7dP%UH|}j${RliommEL?(0~UQLym>gQ&dQ#euy6cHiydpfVs6Ys+pI zg_-rcUA$aqR66~UISiuGUm+f8)K%DD4;C-F(g7(~di`z}uPlQ$S2}w~JSm z0lU;ufm*-Y#jAxz9Z?s9Iv5GN>NupF3uf2vb^$=!ZWo6t9T~t`B0}`=*OW78@8N)0 zWdkH~ow2&x#cRu;&6Uk%)KmLz7q9Cbuzk0S*9(wqano)Whs9T0rV=Q2CCH2b!Tb8+8^p80Zz&FJL7T2j}z`X_dW&zUIZQf)hdw4mM zw%a~bjSRx#K)t0mC@Z#|4T{IIN0gz;kBmzXdg;g*U476Csu_uKZ|w=uw5zs(G^>o% zR%0vz4Z@5Of+L`2$3w9$Y=fE;4`o(ikwJQ!{4LVlcqp@~4r)JP4hX8|Atm?NBX_%C z32RgZWNAF8bauN4m*U|q3Oc$%^AIv8^yW#A-7b37J5qY=cG0WeeCd5n7KD0Q47%qA zwu0cC8>s+xE|A{+fgb5$`G{9(cQKBV9(nE~Tf^lKvM^73Cs)cC z-Zm%+%55c%-Z9c!sBpQAR;K11Jr+rinYjCo9^_!X(_4|IQgp=FS*&z!AalR=wt>hM zCo4*R_E5gdFDZky?`Y5s?AS6``(_IUhILll(6XU2Se#`|U`quSEbzM3nAv0J(5_`= zyV?uM^|!71mzTlX3)u~9MHwv4vZfk4t_&7uSrgdt0*kDE3Tf4D=dk)u$n3J64BR!a z>3J;^S*7~(0nJc4QR(j8!|bJlLtVEAVXCR1rJ-pj^@PTxr}@NDhFY@iWTn$j_a8iF z@e=td>_4=4$rAn8S6km@QY%|%6H}5LrvxS2_ZnTd9NGN*4U^-a=Np49N6)5hxc)j0pgnph+%?j7i z|CKFA>THK++k|lMwyqAw5TCQ_q&{5Ua^&EAY$>&dzNdSWv&83i7UI(8u{vt=JJsf$ z{_Ly;&Xzo&$;Qnc(~vJy(cg{#mw8t!*qK@#N0x5q@5_#Z72#PhWzu8F%#M{Q{Z3J6 zn13g#Z&3EwzVWd7#?PfQzV(UR`^L9Ep$lmlI==PEpu1Wz+T6}1T<`M;*O@#*Adj$& z&Ld2>c|=3Fh$x&BZ@b*S4MVM))l@eDh}x`XEpaU4JK5Z^EZD7v%F)zgb1G|$j*juI zPgDna$NAsud0eh&mhr7m=yaXF@vTo5jlrxpzV*rY)+hhUt;Se9yWIlDw>}x)`s9EA z;yS+d$!e~yo;rQwTc13kHxE1!aFf~i)+cM*MlQVPr)kEwK5=8ec>2XtG>ALm6>G^I zs@rfvjpcUS8Q=QEwU7QaG}`#qC;8p^6FQrpq=zB&#Mo!Io8IWRKH(V(51R%?w++e3 z(&ziX*lh3on%{;K!lTQ&AAs^F+ zd5{cQJD5H2!G|B(L%)Ek^6=~Ao5l#`gRCD}zVN|;ALdIsRF#KcCqKhUd-;yShW|v2 z!BdnWV=#8xk~8nzFgaKS!v@AL`lsrkd@*w&dK=$8zHQ0)wk7Ha88JQ?bDZf%%pW#3 z6?8-zi(syo%wNn=wkTH65i&OCFs2z_#6v=c>jpQ0yz=EWHSv&;VN7s+AK$jbuQxQr z-I!+!7wXjJJoq8eZrkeEPRI6HxFaFzIc9#4Sn_Jk53$>poF;7g!_WfvH4W;uWOgq8 zPO)vt+bW%dxk;-Ww{6KON~0Xec)m~LKQjL8|AWneTi2(be_bEU9qm0DhuHUwV zD)Q96ZOJ=h0Sn98w=Frd49L`zf5~0mwxlqze%q3>%1F&+4NddYW&O4#XO{sZP4kH5 zZA;E+Ln?jEj%`em6#*+-Y312 z73)>+BI%tn3cZV^*Qw~mY+G`P^!!ljZQBz1r(H0TY}=AcM~OwBg}^hc%j&T(wPD*5 zdT?Qp-?rrPQK4XkT`Z?5{Qi0r)@>uUEumi<`SK7ewk`QU4_J(?kU~7{`d~el`*e8m z;-g=);K=#QvPw-7298k(1P`ze^#az-vJcmTvBIg@wuG^1RA<`Cp3u74c11lJtB%UH zB_R@adE1I@OFmMM#G1Zt+Y+V{C@Z4dw&bI|Lll~$o$xDqjZCk=5pVgSu{kA2a>`lFG+mcW92-UJ}$)^Q1UnSx4=a*n{+m>9@ zMNg0=qBgkPUMszM3Wxc{Y+G_&k9uTINBWHPf<|LvtJ$`MTFBZfJEy569f5Lv6bg0H zhVt1c6l#cZ4|%k*EjL7=P+v_bw8M=`=a~fUU^dtJ%vl=Npm&qxxwkewrkA>9R#opm zq{nqQRu6sdZ*P{~5rLk9B3sVc*>m}i9(I0CdOS}dKWwBfM*8Osr(!!Yz0XU2YjJwj z`-1dlWqOPw@QVBtsUhtAqV(n{jr>f{m#=->l3OHyRHjGypd!DK^+Gz{^Q)v6jECmC zJvxZ@TR3pKWq@H-&-vB81GaBlGCUeU9-(2KJU!&)k)*`1nj)`>1*C7sY+G`xAW&}XYwk5as2H1Vuk}nAm%c(AVn}X$Ej?D-FsLiK;H>H0?atwLefME#j zqT>$nNTceG)M0J(Rq=vu$&=FNZA$>LO&tL8lsA43`n57>b6*EAqhJRO22pw2lCSp$ z*nQiQJIjDftS#G?6lT_MTXL7ssC4=xa~MRWe?vUdsH?EQep9^YN_Qa6pX$EUS9<-n zC3lxWn=2i_jDkuZxoyd}%79(!s6egXw&dGFqmC%TpbkdDt~%~1=YrYw+m-;(wr$CG zl#UGGED<4w*muhrwD)j8tcL?6a-Fd{`F^hq+FaROMm@D}Tk`$h0o%7NxmSQ(i<`DB z`9W-k0L5%u@sLa{l~F@#g)`A3s{PT#2g6Vf5rk9*QsVe zwk`QD0n*o5i$JVoe^Sn*?Y0k9BZIIwQ1|r)WyQ9$L9uPgPs>o{N5-WGy>w)Zu0H4m z)r`cr|LzIVw5zs(^s_QjTaB>@Gzc?B2#$dIc{~*B!ZxU1#6y`?SY(jiCf_CQkB2g= z>Y(-$<}U?R^N^Bz?2+4+u!J?L0t9Cnw)&GdnX}+q*d|Q(;*2}G6<5jPk zm7wJ8m3!mH6S@A^^~!ypZM==_Jc0h(bufp-zP6wG@DsE1#9eoOs6|@X@2qru;R)S&;vFh0bsbyQ(^b|RB+qR_K4U3dM{E1e6V*OfEkpAz4O|bn zVRJOh|1(sNEYoA_anU0iCYwrUe3yptT^i^=(D*J5i^sxWd3=`!bv^puC;n|hw$63e z)6PeBa6kS_lE`0U$MT0{c^~6^;|6EX)yBk-X3!CvO}GU2&lh9nr|!y%1+&w4*=f6` zV_6KAClq6Rmj>S+R4%%}E z7sJftc`RLwRuk853_MwdI{I@Lp>tn;_3H6m8h8?r*Dkl(d4xb7;Q?D7iEAFa zxQ_4A;JTnHP&B?v!=QVhllP^^+spVE#wLMw zyXnyN{8_e@M0r&b%1Ylz5*=R4Bz;(0)A>t&dN8G#~!Go1G~Vnd=*S~(!orBmIQm* zrQz4ALw0H4u{)T&`XDdrgtL_~V$rd{y91*Ys{R1-VZiaf7f{j9mRF!{9z00yQNfN z)~9^Kl!ueV$vD2!(*_o#nKY9L!{XWXtP_SMvvkN9^Jb(bBZo%9DK>a{ANG7-7BBC^ z9>>dgdwkgEYx3CR!`@Dlp^QH4%VqME*UB}^*@8V&rd&9T9fXr)R?3CXf8$48>eb^R zx6NeE3TeG8qAue43}dEB$biL}e#AH<9ujG+JHTh0GnQ=~qM##WY-}=TG5-+{2^r>5 zZk9IF!IKl>At5uqn}M&9ZFJ%~YwfqC!qlm?Bm9tPw{3N7r(^pp{4NPm&oT3Z#FFQ3 zwo&wM2ImT!{&39fMavc}MZ2EN&i%I7$l1ki36EAf2Xm9ghuh8I&q|{l$aua_<3BR~ z?Eiz!fw#wBMxnR6bpI+n@~qpffb_p94eYw~y_EiUr7?E8?`A+wqO`gPfp~5=gMUOL zVUsAWB56LJicS9$jYP>k)$eBT&oUB&yM8wVs>oCOZU&FV0v49F?`FWlFRuOz6YF;~ zSf`BCT-MMuKV8=EW-y@)$gG%uds^OTAvDb+mUlCFQX5j~BUfx=TFoj`m@a%SKv>L_M6gY~7iWE6TENN;EqdK*gb_=;Z4ZU!4kk0<+K`C{}YN^iv| z^fvC%P9{Ry;mOitH-pg5V&W`Mpb~S0-czJ^vSPjJJym+Aj6!b{>2)f4?%Ou;3VU57 z|A&Ltrqc66skhw>=%04MNV44wHX9`teHH@Gu%1?rg{cj@8PJ0Zi~Mc|PahQuR@lXI zn!=mcqp)rpv6}(?+Q^rOSh1VI7Cm4wwn7T=uxrbDEY_CTRo=~jfnyW`!2|3Wy?}MI zY^!=ORyZ}g889}D>P&lPPiWn2dsaOfSG~$^1|br5dE1KJ44z$&#G1ZtHv^^;C@Z4d z&EPq`Lll3QxCzVu4y*|rpOE;KTF&ZkdsCSnIYsO z*y2Dw@9{x;YsARM`y0keAs;+EcrN@_dtf+ZI<*0h@elYCZVQun(VY~P!D z+inIs^a$0mo5Ax1HD4v+^5>Ueal0Ap*hNo}C89RC-0md3c?yU5#q4IVbB}stPDgry z^nylXVyoHBfLh4fD?6vDBprdWOB4!q(uT5Y6bd!OxQ9Gi*_Pd+P^hma6x!j1O6Qpb z?O-;?>}IgL^tiV+J*Jmp*-|XC43kvyn=C!9!?AkkbAP*s^o|Jh6ckxLcJ^HUqep&w zN{{yn^n&rAm@cMsXD>W#aN**)3znUbcLq90;(mp( zeK&)b^bXj*o54#*1IQyZs*T5x3Z%rS7K;3`SU~!A%x(tzNDkQnNi&zxZe+A?Y(@aY z>}IfEZ-CwdcM$BvdQahwzni#I1&HNTm%Vks^1j%N0D$xucq$+~j^*x!dZ)`%=ey}h zCC88_&M<^_(a|p+X;j^jI;@SRi5GNBo|HE4W&ntP4s4F~5-%D*2c2F9Rji?}1DH|Z zSkE9Ts*h^gzc)afV@{k-56Nga(G3`3ip>+N1ImC*tS!446lT`%W-vo&R66~UISiuG zXNpH!wZ9%HUUa1cQm*v+-3$&YgDTcg=>TRFRQkx>3|?La>{3SsYW;2ouMiq_L|rga z=)}9~IJlgPVhy_)0MNFZ!7G)H4B#vgA^Og%#EY(MK&-L>61mREup?r_=GA3T#TqJ` z%c!UJ-3$)t9k6{jgF^+#wYX_FgV)4n2vE#!2CtPI7jYUkoZ?;=n-Ks|+Z4B>(qA77 zSX@c{vVf&XNHivZhs6RG*QsW}y#@Gh0;I1qF+;3m-%!q^?Y0k9BZIIwP;cxF%8G4g zgJL&>HgO&Ruw{=uzWDioDL$LW} zuy#lJZeR<_VC^pa28MN3+|aV4%3yJpHGv&1u;7~9t;WnAJBM~HEZfyyNUl$9)qhMG zti6!kz!sIk;w)>bvBhPuILn&AmIy4e`YEJUyPd=8KUV4Par*3~gF`cyFKRC(qr6i8 zX^1w|6B_f4rT|A7YCg^xnM*5Z?UmNewq-q`wb}M=8LOub*{2NMcZs-6pE6uH$+rW$ zM4geu@#Cq^N?)1In|E=#_q%tL%>Ujl5!cN8>3-*_tV|KHW&MQ8dV}Pd-}6~n z;W}E|cZoPSA6IqOC&~A;)ILi|+_*zriTI>R*GIL}ooc6!cJOd#-N4*2jeh6H%#vwN ztn|;Wn+5aaSyw93nQC_IStON0W(RkP5O(0^{6yK|UiHh4^VJt9YiwV5--|a&z9Stz zxn;^*SI28!{p#0c#^pxR**iJ{a+T2u7z!2@L;)dgb>_@o^ujqu&T~_nk1us`CQKh+ z=HgU*D338dKHH_+t<#*@b6gyQefnG%CmhNvnop<5k{_7Z#shc0;o_Sv&0NkaW&Yso zfrV}dcQKr1)ubJ2+#<L8yuY|e7C2oq$ULLiSYHRchU$ej*jH&0PGCoXj~%lJ+g zR7t0Ae5Z@?oi5Z7Rt%LF8!LwV;=&di7PrNQ$td z(Z+YW=vzN|@WvNB_KmBi-aTQp!ur0c)A#H}2VJ$nC8w;~`>}8A{F`GA+IekgvkTNW z=!vn-c&$SkuMj!ItMct>4}89HsFM%*p?p)_(gxtzy{hFK@5N^L>eMN7F;vx~-L}=SosR9Z@Wm41Nm|VOAhG0H%@6FD0rtT1MK4@>^g`H< zs`*_a2K`~l^0`N6BDE*e`{o;p9XXb}iN6r1d@NCaqr6urjsAlSx}>#v*r0QqWM5v< zu_Z5OZ-ajuDzOBeAn;I zPxuNQT>6;4QwBw=-ZiQKJhAjcuT{X)VgV_-rxU09;_rTYl3cvMc--UX#XfyBfXsKa z)#lgC1S};+HSDhA?E<9F?yZhV9eeU^r2Dtz9pwxe4*7@I<*htG5~bC>S@@_6q%)$C zut$`FL>v20cb!drwEa8FNJ!T=QwF4Tb5T$*x#KoWB19$Zt>a8V&;ovN`oVZsITNlI zP2SN(;}sARcf`0pyEmu_nW~+$sGB0rDMOW;qx6|PWw-M9^RVklpi%gDm64e1vrp7s zy(m{?W@%|)Re`u#yie)Bl7P+p*dAUn zvog4jNSGPuBI%&FuNc)Ch>z|sRvI!znwXl+sLD&k$I{}Xz_vCfm&}6f?B_Y~E>(h( zlO_7j>G);cKZV`pjkmETg>n3b(zw(RT?tZl34G>?d)UN#(~%K<)hG} zHs3Ej@~qpni}VjD4eYvfX6X+qEx4|hCzvIJg9CXDl9MQ{&iCTEUA;aOjf732w2H*l z6q`OAjYP>k)$i)HvW$du{gs0%^3=Yo*A=mVg=Ou#dVQn}*i!$6iS@gBeYA{3f$GZ| znzpVh^c}bPvZpC$^+xBa`mr)#q-h?pysOv0w;`3TV%Wxz&et3byLw$2jYze1L&Trw zyy%3HVVB@NsmY0p`9`L zeY!_GnFwizYovE#CBLQ#RAP?MyHP5dc^5r4sHv$6dKYGAoY=so!fpv2|mRpgG*wu@HV-y0x1MG9XfOWI%^Yvgn zC8^ofi?L}`XWAEfLhEMR7wgejbyRls3X!nO+eTYU<4is*Lr zTGcy5VTs?>Yjy7s6Dn2=_YT1|$qK?!cuhS7m%66=R;I`dB0o#q5s@`SVM#xLv)z+C@*0C89RC+pkj`IUVUv z=>?6(#8$Jb7qyVJS9VTQNjd`Mt|%1hqz&a8Q7F_9;~w&8Wm~=(g+hHbq0kO@E1mZm zw1e4P=lX7GScBfTB+v7C(_?zkG&^GXQq}vm^tcYk>Y>m5?LE>vBG6M%G%`QW_hrG( z??{htD98^Rsf&?M7=}}^9g!b;-CI6Z`I(+C zpY6+3Rx~^Bl|0YR%}%6>{H%V;x;zv8f%Jm$pjgA*9vuXqS)Peffu1^j;WJSHf7m-< z`>tL;8V#U5x|ZiCi{%t+u^J1191BR_j@i}gKP89kfTWqrXg4zYuh@(Lh}qTaC%pms zooEKZZrIi9J^^Am)n#8&VEIpDGXemj7XX5%E_W}~J6)4H-%ZDVOO7E=oM8y@n&xNX zkw(>puW5cRUeGPuU(*2MU4+|r_4-8_RI!G>4q!&X22%{8@~&R@_XgN~SFc}|0hw4^ zcJ(UEtl!n^S3;xG>5t4|5S9LG@kp!o*WZX2UFm?7E4_YKuLsJYiZxU^fEfjqe&F=5 z(s`=)+cIF6Ix0}>clG+6(5NHof{{We-c`r%%eg4lu&WmUZM%B?LFvc<&Jqz~h&?D? zbY%l#l?{-{b;j!C`^Pem-st#&D;05Iyuk?_z{v{zxSfeT+OXDXA>1z_OC9bzU z&2Ke)4Ko82gxW*-pz3&st^=k_Mwy``-| zm=C@2#o3IZn`}55uxbqg2-rpfi|i=aWgW!Mz(7Dv?8PqT;I=|;JQ}d3LOwaZkl1B~ zv$HE-FaD*jb5{iRaMG(>x9PiXX9t_Dzsn)mL@#NcB(K3;2n?VRf+i)U|?^lKGJ z8F^`q{^dHrkNp7dSEt$@OegN2B%e?9in^ck&WCT3@4*y?lZHK*wmIY3(u4dSOdGFS zuKUP?;PoY)v!}E9ZPNM9bid?rf*P?Gr-ZPVGT=K3!Ba8Z!wXec&gaPv^<(sY2{8y` z%ergF@4-Y~`6xE9%DK7+Q=Qb*~{9B#2QF4dmx6rX}c0A$x4)KL%xbM)w^76hz1Ix?%4w*a# zv6vfJUfv2|V0n4pp@HS)eTPh5sy3ip;jFXJfp`i=1LAJh^UfOw{&?ejgsRrntN*&1 zUg}%a*W~{NXZm~o_RuQTK}MavB_}UP$FdyEz%Xv-TujAS_)liTq%0r#_DhTe`sGT2POX9gRdAK%l2Ra(nmyYRxVJ@a&*h8bKm${zxjBQ`Ach<`~S+gYcGVyPso%FYQpP#>KObcUUhQc&< zvb;2preDZ9oa> z+l9+#UAwI9lbDVEQEr`8z3`uqj_u8h4I9@q&0B$GmwUBYPJU{rE|)jh@Zd3BF5BI4 z&s%4`>his_s}3dX^nG>3xBJF&KKq~s2hTU6pNX8lQSxIAD#jGgPzT!f^SEQ$#P4sn zZ}pH?@*(LnW@EG6^+La&2X}y5Bu5YHNViDtS^dCcpXz(yvBQTac1}>dp3kC_M_3zaEPw0V6)#-6a6sWYqG-@Zl_&Y3!y~s;2gLfKZr=g;)C+kbKhsB@{$Iq0$1x-0 z>y%uo13mZ$=&-y~g+sogj?UMAs@-rrH%Vp%{M4A71!(di{!U8b9%-f08Jn?te>~%T zYJSNxtzrX@6S0{(;ta3KCx4z+!MDp~RX*g0@=sJ9@}vx+PO;P42tIN6R!`VT7^=#{ zuai#^79k(gH)so^(YEOoGK98^-Fsq}i?kJwbSV2uozee@4$2fW4$=GN#s2ZP)RHBO z+kMMFDk17)U}*M{ix(--Kwv?;T;hGppQEteG`ne1AJPmf%ymI;|BG;v46imB!c(S9 z$z*oT<>$>?KMzZt{UV% zaACjPJM;+qV26pU;b-~wp^J?8E)1WKhu~-Onaqq~)15bu@H2;z(c|%3WTy)!$*dF} zG-b+#!{EAz_>8~oQM&N-70w~I&7|E!S}%*x9yUJ0bi#~Vu#iQc@xy~%__Q_OkCPq} zvRp42SI9B%5Dy6%<^bjsaLJ!|NXRhnFrSkrOC;hUA;Xy9+JbFd+K7{PNThA4qgsY% zWc*O}@z`&D+wd%3%4v1CmBN;9Ri3(hrVf7k;MrODV-lk5F=JL@$(b5glT-otTW(UR zRO(rMx{vQlH&xoUiXr3qK8^p#__P0yogCvpFouT>&Z!!R=p&}bN-fFL?dC7D6JxC%sPL|Eu)brxu<%6%V(647&P@h zh*XiMc7MyQVgU=w+Wjq`Sq8+6{1cRN{TC+I`&&M%jMQA#&@?~I)cadLy9^jpI%x2>d~P%%)z%G>uRFGu+#==7z*W?dE)dy(Ef3r**?ri(jpUbz z(W~Ah=?#rS?|ITYzM>c7|G2I6mW@JhJL%zX8I~_5zwLXplZlXa*g<;uTZZ`+6K8Wf zJYRYzk3w%p>76nPy`7}jsp#3Fqp(*30rA9lXX)urJ-qZO6W7|;46Ya)S~}=&BMw+} zG03yZwJ<*uVb!3w)rPE&ZddKA_x zBm6Dt*G9fP#Jr0ZSTF1Wi?J0_hzHj0^;oROud{zrRQxSNB<%9G(U#ud@xOuOg_vP9Gdm+5}#%~LqcFUH?;T90~UPDh$9y`a&U*lPSO zsfDb)vU8eB(h(^8N1;$BZ72ssp-@ANd&r}eZJ7~;LVY!%&<-<|&iy;>U^dr%lx%5O zgWiFX=l<99m|ir^j#%zi^$wCA*Wp+_^tr!%x%7?*^b{10%+K?ES+MgJ(qnBze%MG| zg#L)$zTs4CN5s)PSn^vd+^gOzr8g_nV;q539JNH%DpYXL`PT?f#apmi$qf z9_53I{H%UF-~QwFbBOeU@z8v?M+f2i*lzxohxQKG?r-^;(E#$8h-%YgHWte%F{*_k zzcv<-z8&Ll`8vrVJ0NN1GTM!dULTtg05SfShxG>No_tOn1iQiC^4|oAz#uGt zLu^I>Kzbb7>Tmf*$uZ<<1BM}l>))HiBaNy%QirwCo5c&dB~KaM1DF1}bM-rpL$jAH z&_irLW<7|1p4#qjd3YJLxvyhYMuF=egQ)Cp`Ig=QyZc)nQ3hmUZSl7(%&hmfe5=r? zbowK67(}Jd5|6ZMf1NE}bfp7QuJn3;%Q#=6d;qlhTh0Sq2jDCbA%@tI+khAvgkRMLZPi!ZxVm;-SncEHX%MlfOkeJ|4=fs)O23m?sEIf7OSS++&a2l$9l{ zQ5BG-@rg=*ni5zVGe)pIyhTArS7}K>-DCdwD~pr;UPGInFE%IjrjNC((FDfB;l+DMA|JU>3T;UM)cnRC2Z7(gsPgvY)y>>|0A$7k#%L>$}1^SV=s; zr2Z6j^*3e8XNB`OwF7i_s{Lc98&*?+49h+jYQuW%!r6MaIK`pY{WI@ju09ZF+EvY& z`Wu+gd-&q%j0gHNyQa8P>7QLQ3+BTUuT-Qn^%LqF+%m=XjhB6KqvYq((eQM2Pn|vC z-ot!@7kUpbSzPuWUb49CJ#6yUfJ+vay@!`9E_)9zSzPuWHhGmLpLFP0HlVou<2(G` z{qCmrZO=52QK#?r9e&wIGg`Bf!@tsPnCYC7^yY56wv~cM70xeWaQ4tBKD%GribJD# zkGnP>A_=8BL~b;9TrmGvjBx8(%sxwo{6Nuwbu*jA>D*yDGe;QD2U4bQ_xz^Ml_8WT z9L5#R2NGefKDi@H_WQ2nfn5v-%A^k$-E{bi9Uqyh@Mo=@XI%D?)e`II5Ow<2``Fu7 zjr9<6t+lXAYYjVtdugqOmDbAQd240yytT4;-db5aZ>=nzw^kO6p>}?B|TNtvIYa^5$vs1J6tI$meciCJ_13e16`e zS={sHU%X)Bo@~!vX zIjSp#1$zyz9?Ri>mF8eR{*PU)AGT_vWQA@=n7Wz52ipAFnt!MIYU%T`F*e(EzgGCQ zP3*jWSVuasv&HZh$+dltp1MTmeH5?fGbM0=`=s(@VYFm%oL}2X%5z`IbMZny)dA6q zL*Jzorie~a$45WpAAqn39O{vaG5E#@r;ZO!$e-z>u1uld95^%&H=qQ-=9uB5&i7=i zjA!{G&rN1p;VbIseEp}n4aaknWLCgWjmcSnp*;9dM+bI&N(`=~vHo;_P+PoCI?tC5 zHn98yllJ5cugWKX7BcXuyE^%hAIdk?Eo}o1WeD>P`5_K%Tqhs$L-{aY6s=se4LEkL z^6=~AQ-npx*VzLqAlPIlvMT+PAD=&yf!X{B# zMdBp|HoZ3*iIRJ&_piLLjKqbm-oKJ6^3?8M`My}d!m@V%%8SZ?n2~>SQuePbOsw~> zyts_iT-MMuzm%x=ue_uT7-^bEEc;hp+J;p6>;~Id9_Mw?;9q%JG$Pg34Uw-oE|=UQ z<;=iU)KQFo<@+VSWE6TIklxTJ^gbxP<12bG{*E7#-m+2XeOP+7A@tuX-Pq-YKKd`A*MdMqRx{443fg+<=K@)M&%!4|t%PE+`*dK6ye zjPS3dUmN-I5G(vEukHbhu@zE?hh3kn$KpPIq<$y5SmMRfj^pXnW~>9B-(H;8NH05gk)x29cj7?g+>mM+cc9^QQ#i~o#=mk^k9uTIM_MhtpwXDvYWypy zg{-}@bDB!h5h%k^DAY+C%92El^J~(Zqcrj}Jzu_d|H`jR z{-{ik@Bu!f92hhLv}#Y%w@D2b^EQ@i~xx7ul#mzfZiu)5bOs3%6kNe-PVGx!6WAR9%uEPHM zpW;PVIw0jrulKL~uQF(Jr308zQ0XK6D}Pc3>{3SsYQ2BueL|y-s0&64BVkt^KP~5i z+4cUF0JQm6{zw*JJ5V46OR&Ar0e=H-l)fkIFgQ%;qKgC0_E^LE(C?3kJYAWEv z@la+}9n^lRt49Q-KYOaO^p&%hEEybfAFPb@uVe{pR0U*d{HW3wN`R#?W5id7Ep40q z7XK`HMt^s|MRF)ta+*rf5l#OWrE}Agd+)S0KC_%Px}80gA9;T*gSGo@bp!ib8ElFh z6HU)=x`F+@4A$x?~6uic}|;dtRE+@G$8s=qV3|%kCQNdoHwY>x%G(cU*|lc&w-`G zJv>8%x_H9<6#3>R^i!Nu`IXZ-m0vkEd5och&8hs#>72^1oX)BI%BjgqHSeqxj?QVA zbYAPY+*a`gfA1f@Uv%@9tEHS#r| zMqWW@)akqWkAGqoaaS$QG{TC7a+HT@?&pmE}>wT2<e#Gj(@o(w12ax8}vc2l6U$hPW{06rcEnPUra7M;gB%hIwSuilLa4_4~fIFqI%bot}v-bGq zWAEDY%jZn!Q}{EK@RrB^{F%!&C5wN(!h2+;9@8l~UtKS(Z77whqa*3I!l`Yj$8kUO zL|r;r;gs6xX(~+EPKtJPj9B6v{qWj#7j&bHruW4@w)p3x8zrZzQ&LtIh6AH>*uF{n zEJI?my>Wwy2@?@B8Fx*o4ou+6kHaFokWcpu`7;$qo@;EX!{m+6HLH#fK8hwk!$%vP zp|Ni(9VUN3CJ#TY@D+7*zW!5{=zwoDO9A7j#^fw}jE_9!f;u`VH#nBBg2_%g$p1ei z$O=8yNqW}}C%Pw8&yx?f#mBaE4`5_J$ zJ?yN?hx}09@9E8lzbo=CJa68W`k`3QpEvLRJS;JO zK-S4%mxcLQ*5vi6&QuFue%TMi_wp)N9@Y=DrY0jlD8i|*Rd(ck*z;Ob5#z;vpf!nBe-pg^n$=xK24C z!;h~ruI-0biHC#?KfcPlZ@%-|I*aR+6EfTAn55%*Iw%wIYCR!GonQ-PYN{i2vB~O) zcu3$t)%GABlC`7ZnY`t1_Eq(;aa$eR>DWFCe_le=bIkl8vE(IBndp9W7VM>6oUXqh zA<8Q3rAv-RyPnL>H*7Z1*~O3Au3u?*<|d5~_oKEOD2;L;~|H$~W{|`0?AEj?N z3ccN>yOH$Bv(BlS^odFXyDoh%rEjb>`h9n&YjP5$Raa^8oYVD_qmi&llva^6*E*-` zr$i%Ba!>V6*H0}YF}UlUuBjqV?M~O5!~zzUwL4vJS_Wk5$-hG@J6#th);nEqRz_+r zYiOFEF6*7HpH>EpG|eNHovxqWhE#I8#y0&GbPs6s5&?4o`z*W>y zjMMd&l3y|ky=O>oXcT%|N$>cIUW^m;Go`m|6nf8+-ilG^J-bIcnFwiz=SUBy>#!Y) ziL*R`O3V>@&z0WEiuJ0uwe(IIh2A#O>s0jIr!C?Y_PR*^kEiaFr00iHZ$D~F|FjE6 zqEBtWdfq6p=(7-bhP7=y7N#~hUDJaLi@ekIcB4YU3cFZNQ+WG&6xKK+oUZBDM!r16 z3a9HGdcb0Ag%sjp*YoSKSo4f@x@O=Qg+TBC+p!n0ZkFv-55@|o#_5`|X;f$0&OM=Z zv+V`-XskLaPS+t4c6r+hr|Vtnkyz8$IbAcAKv@x;)Ag>sLll;Hr|aE%hoEzZR=lux z2(C#6!HvQ0^$_AVI$bkGW)S&V;*NlvJUYk>As@jO2Xc?c2kEUXJ6-Qt56K`L>2%HP zo`JZf_o0%SB3`iMRjkqJnn^yZF{yi}>lgK=-sW_@SC3FFPS<-2YQ9Rs<wq?I46zZ!9g?5;#be>7j4rX(V({-QZxwkewrk7&bQY^C!lT`9c zrN?zRRu6sdZ~LWpM4+dj$nvqX=kgyt@|z|-o~Mu>Hc}UQR+ZgHo5#j*Dz+ojn=bjS z#pzXVf9cK2^cY9r75OPrL)dwM^yVmy{7lc6uifc-hUAaR^e7)xH1Xy#B!>OCwdT;zdAM}03baEZv9c)LnOzLrwtf}&@MU- z6^}Hk?noWhMz0Ys=$1SwZFaf_#9UGV@{~7z4*J?MXmei&Fr&c#mqAo^x_(`6fZd(0 zUtb1fVr_A{F3hZVx;{*3R66~UISiuG|4ls7sH?EQzCpa`N(ZD|>Ge+6Z!Cj0S2}H1A&z%F%Epw>HGzgcM15p}^xVI=IT3Xi@ zxQNrR;S@Izn-Ks|+Z4B>(g$M!iz}&L7TB`P<)VKyCV=x|0gLNYGvM9=JW_!4b=D#f zE7|$wOcZOp?L*bbAS@2lg5IF4*mgE3oUV^5LzN#Hmmc)ek+Ca(*xlfCeRNNV*hCSl zwo%N5Wh63h@@{1jXb^QZc1%1J>%umuMe$H(RZ{^M$3vM_bx`}MVwMQ1<{>5b*dv{; zS;87s0a+R!tMr8uU}?-4@zr5VTU)|2F?s@n1{;z*qrbb;H93?kIZdVL2&AP-=cXlh z@l(99@tNf?0kX4?d9#+4!P=cpyMZk)gSETE8d$ZGv5sP{D1*gW)&zE(z=G?XVy!i1 z)o*8Pg0SoOvR&HP;; zYjpir`X00Nzb)TbC*UkUS7%A!1k5XYoPbxW-niL|?IT~`Lr?Ie!*e|P8uj;tI|1_z zNazH-wBiK3wBiJ8@)*OCb7{p1cxlB6cxlB6*yN>}Phk{J<#ZLt<+J(MB<&Oa2e-VT zFZ_gmopVle_X<)Lb^12Fe#6y-tVytR#Tb6V&v3~<;m>+UU;q&Q`Qphjp@e&KuJP;#x*gdj93R^M|*& zg(7(B^u6cKpRA^Lj#W?N7N3Ij?wPdlTi#e|k{c%UrE5b;df&?6zNa6}%|=F@zH|27 zcz7&J!sw?>dh@3I+`H~Awa2p#-FHmegSX+7qE~OqwXGb(nxFWJHg-wzq$v}VXKOe! zt+8?*Xmilna{5!3{cxY^A+2PM^m)=9o9$uycn2M3CT7)C2PV*&{-OgO$4njYS@G2I zX|_~HRURA^jX%Rj9Znq|JNS^-f_xwy>xgrg>UMkSa1#k8OAYd(PB>c`Lq2w~Y#@ybU!8o&59QN9 zzOId`ZNVfCK4lK=3Hc#DZBQp4@V>`(+7t3ad@g>-Rpmo|C~x*u z`>N?%In17rAL3YjRpmo|C_f{!6Zyuz9n=GT&*)#(w{KJa^zB%On4R~Vn0!ok2l`7G z7wF%vgL22rJ?O2M`a5mLhwhZ!q7;V}h22s*3@78i-Z!jj;&sgUulG?A8S#Xbe#Lqdjmn7JEF`m@c;3g%?_B4_zB z2UxxuG9_Z}H^&;BXb68vLcDK`8CMcZ4$`=qrE~Y1Jb9seenHw0 z^%K%pB*c8_lZZ7Iar`^Q2poWYRRVSz#A9o4+Onv)OCb|2N#7 z5AZhASHShsobxdFIv|&qg{L`;LvEXCSTFHH?o9tn0h-?I`0X}(@lpp%vsXmx-hVK@lgA_7+R7Vf_$rWQWw!bkj@T} z+F!)bzHLb71W4^R(duO+v&h@@t^ldsCi+4f(zyXrcbohyH*$1SPwx(py4%!-^qv5z z-6ndiA=S0rdC^GpWshLzaxXYP8i}?mBbD3kf&i&|J+&ddH$ZByCv0NWKz8;q-=8iF zkhCut}?n{ViCIE z(82hLz3v?P%8710yRWa5;Ur1ZB$=h-9sPdufb$hjh8y^<9A5X1HC}F3I&uD+rWLwP zd|wCUe4iz~8G)|lJAxnNYceyYmGiCVGsjNQQOka=Qead|^`_~(O=kONES5`Oi$=u3nG81=t{QT_Eh;{z9wU~RduWUP*?Xm!+-C4`|v{_zM_AF$s13jj=kMY z{GzVV^KCRMO_Dd|x=nn`_inW@{cB)o&!~Q}$EznM_eqB~@@oc=>S>nP2kPJjgO_k) z(g(FId7?2-zXWH`j9Yh_C1wRjx<(#{a(qh%Z^UEgpo0#bn7mK&#XLeEhZu_-w=0g# zBl%oSt)GsRxm`Mp>8h^huivU`b3s+t_(i^d{pO~(KJ?*lt=atUpZ7my*6(HOR{hT! z-oL+zuWSRGH<#{D*F0s`?fvMRuEuvQf5Vb4^>Ohu@aSvORe84(uZbV#%YFLh(|n#= zqpLXeT+iouW>L?~Jr~#LHt|DU@UfXZoy|eMb^NMsXfy3dnX5K?e!I=4TeaEv)qF$S zOr}~EQ-&DI;rQk+ibd3n~fjlTeZz(n)qJ#+w0i8dtB7KyTxlJCd)MGFuxUJZ@Ax&Ie1~1 zxx>b%n@1Ek8SJWtLm9#$Sv(cr!jt-oe8Vs@mhVc*Sok{lS-xR-W%i6=Wtto^eI|1% zG{v79pYK#<&|{s$yvp-R!+Dm%5OL-&+MH)2grRCWhS z^n2Fv&!J+kM{5q7n0!h)ltVgQo+GW@&!N7fa!}VQN86=6zn}Q`H~8mJQginc-&G*H zpNP`G;*I`(Vtjn40!85%T3g4*_teHuldZ9RWJ7-190*T2HgYK2S&f+VhZp zrSAXu*Pb4SwdePBWNXi;{`#di`?aU+(7bryv?N(M?9QEIZcjRIJU~D3ew%*tbGrDc zkf$e0mL8A{pONudXJ!2Jk3GPpC5HrOwPwu<&c3~*r!*9*; zOZ-3{S!{Lk0e|?1wm#2j64_{8L1g*Mf}^L^uga_XgP=3g+W z|21cQV1Fl=|LgSKy~#ntI?}&x^3~Nk`b-bq$DViEn&8SpnzF=~+9^>-SOLpyl@$0^jUcT3iXub8M zxB1;~SaZ$Zf9OBs`?I3;xUT%+FBebSZRi!#l7~--*5jJG@c6H-S^u;j_uuvNjicLv zYv7q%ess+(KijJR*bjdB)=eJ%@Xgn6`rOqo{mES~`OuCp?|bu2zh6Cl=~w$EJ~FWC zh}}NEpS2&?>3fd&=$heOx1ILY6?dsGhSb~+TyJi>=lyHW?*B^vl(}D2KMtu`kL&)$ z8=bf6KOdPq?b1`8tv(%6vmR@Or`@t9UB7>yX$Nk0cC;RAhzEc9hiRL9{Vmge`m7tH z^;mbvQq}*Ge%*gW*9&WsKmP1vYxaEoi~0|o{n-9zPk#L;Hhb3K0nX^;yrH6*k#OI@s^3nJ2VIw2gl7_Ff@1JV7_)CJtUvL zbiN6UNMEpM>4GB{Ep1Bwp=_g_vwTA6QkXdaddqD8ZjU&+Khi-sR{yWkryrxUbW#6t zi-(Rj)7*7P?3{iqA#BU!a(*=c7WC3N{{1je)e$b|aD_ZL9 z=K{`bL(b)2_mBLcs{-55{e=$FWLuQ}dV}6JH_qqposR<`s%?7Q{JmP=Q!ku-;=s^? zT;wTL{rhDYWjk*E-umB6*bf~b+Xi&zUG>FGcma9rP9N`lFHzd%N<#)+$`Zbh4%A$b z+%J_ZdY0EO6<`iOZgAnk`2%}2zAZ8NpJuiZNB37cvO08mH2pLEx6SkQ?w?aGnXa{) zj!mcO%yFBK*Ymk{Q~vB3r(~DtsOo|-lFvG$tXs_&9m_w&TyopGCEfdmHB!^WJ@e(- zWpO+63?bx)`L0}}wW!i3>kMtGF!6dmYn;MnWH!}dx~5alFPGQysp{7A%k^yegu2*K z&o9^2#j4Ybr~7+?CDT-A(xZNw_+fdiKDnPj7oAI`-^8!#c80a1qx9Z6E$Lhl=+^N= zUDtlnBj0nS`;ps{&RNoL;)l8qs%(4%B)#OxD)$A_J6A^&Kh(XnUv^689nw8Z#}bwG z5FJhYI^D_Adx;J83j9%V!F! zi683Te5>C1=}6Kfxm$W)RQNg_^?dF}C+Nt=zI5)@agOxfql0g(=#O_a@I&2uhb5<@ zs@ud5btxb1Yr2+S6TeN@@~i3^Kh(WfWutr@<-e)&PZUlRZsLc!CTqIncdw2{eo)UQ zyF~I&4)Sf{hxuBYRO_mV-==GIQq?tnsB3Lv`C=<=*2E8W4X>)(#1D0^TciG~yr`=m zDnE4SZqaYzhq~DN2_2?uaXVM}q3(myyED`6r2ZYtB-MQrKh$NO+d&7{la)HI zmHk{-n)snE>jTy$D~FwRT4QW}$V%ng#INci>vhrl?X@3PKS8&SAL`P7i+l^+CVr@U z5;p6Am^ZYRd33SL(8LdQ$@3%~Roy0jNmqFyXS%1}_K%HRJvHz{-NR+))jB#Vx3^i_ z6iTn2UtVu)pgd{cs%|~Mth+&3u_BESLx1L{KPgZ5j=6Zg+uGLjl*YoRj>66%9&9}-A`=sHU zOf}yszfHGVSEg(HP}ka`D$~So)3x$eb&cPqYvrx#8b8!6c)p%Zr->ix7PgdioA{w_ zQGaFKCVr@E^Mlp1+1$hrb&+K(__^KB>vy=hww_QXN9 zt?D-MLtU_u^Sa6_%eS6ip0Do6Y{O#oxOQ?cUC&=%QWJFebvt_w0IZ6ZKugEqb=`F}?Je3S3c6^102i z@_KUV;^lRruw5^yPud>}!`9E>TmK+TSth9*5cNWtEKI#Z$XFPeb2EM@ulGJjzuW0@ z{^%#)d!yIAqhIkggnhbwH{s&OcjrugO@Jdlb0@?Ywlaoc-p`o~Va6Op8M&5M!&AjK z8NyaBD!8TCFuT62WheT7fC;O zSHf;6$Jk2=#!pDU7jR~qlMB8DY&YIM8oA}J(%=JFsJMG7oDLclk+)4QD+}#qrXUq{w+CU)t6#Kg5_kNc_#k zzthb}j6YwW4-U(dc$%Ujbe}4jr%wBO--W}{?}zJk*B5_%H&+$9XOTxBV{KEn4|ToXS+aRur(fg?ULD`JA9dx+nog_Q+{Cx? z{$m}RFXDXIp7{>lTS|w%6U+swqwe#?lqo;yN9)NG4!rfiLw@AKetZnqh1I4vtU=z_ zLmr;C{U`1+ei*)Wf|J!8t@{8UF4no!Gvkf(`Z_2-amd!fq=jpI*6_9#Lay8V_CM>` z{1!J(9yvqnKMF#f4Se~e4AZ6su%{xggDO>2UMi;vHjY$N73wv5fz9>{rs zn*WAOFuL#`|K4rdj%p*x|l zElU41=?AtA&2F*nNri35b+v6xU>myY7Pdv{Klkin%{FgYyI+FR!!_H8dR;HGU2=_f zlVEN37UjLa;(YgWncYxlnt~Gf?|v><+I5N{gRZ~Mr+VKH`E5{r*#GC=?ER8O&+=Md zfZQ+7TfT7FqNBTi_wxhUHXwQQ(cM4?`No!Q`8mE`{q^On;Ur1rH~WxmK0j4h=d*OK z=X1|aUg)kj{P6Ijr~Y2D+`B*2H?i~U;fWo5a_jk~yP@pmS}%K}uJt#{-s2_DTtz!l zUN9ztql0>gE&JfR{Cy{Ve*I(yx6H}jubj~T^!;xhCVbhF43^uk;hrn^VHuz5M3kKOa1ypYZbKXMFyBuk`%yPQ5wBE*YGWFXxk$C+)60quTw~%9DOZ-E_ashBCemlJo-ynEl@EasP&%YX~OpH z&C|hVvi3ey*xO6Y&--`uZ+`c;`*{{ny|=FC`#y@U(${d`Ue#^lW0_2K`62^8c|K*< z%6?nlH}T85WAprj=O+Fc3-_*&zn^L1BSCqeu7AvTYR9Pg?$c_Y`D(1V`3@VHYoP;g zm0C~FAvTw7|Bt?QBPzt#Qw$dcpS>MI84rjdxJA|~U!@5vylzHw^~a*$=v zxyd;1qsZL@AF92Fq-yW$VK3J;T#H2dXeaeB=;^@r&?YGdWtf(7>S=OWR)&#zRY#Z9 zXB4p0`#6e8t=sM!`yn&sLn0YwZXA?uJa@Rc)>(mTTtBjHSzpX!PejU0I5%BBhtJdI z%$en{rci6eI%mSnNmcI)_JZ!f$7W6<-x{P0=RT6Ygd5T#j*^ z?F@Aqm+zZ7;Pyx4y@GI)aGlF>ld>k)hU?rW;et-z7F&~Xt_?Js!6k=*N6|-HlJFSU z$Ma7_;fh`!D{)LRgEBOxxkNan|zYWob>)f8u+Y_>J{{d#f6?gAUIR4C>lxqC>0KR-PIBNWn`sGpT zi)m>aV)PLPrpKU6K^mB(SvM>ngPv{;_B0*dD`@*t(%U({Fw`KzoM3$5IfE|4cBQP` zBk`OZ22)PPWR5kI>yM0su_|Rhe`-Ok^Dpqo=NQ4dWghz=QYXe0eA6?fl^_<6c@)h|#_?Px0cfwGB5v9Tgu(qu|CysZ63tnO#L#OpAp z?6X;%C_hWrhIjrhT350CSvKaeA0qRfFf&~~xm%+-amK{xxht{=?Bh|wjGx8sBd0=D zEbI?}eu#WxxOo!P4Zv%myB_*=nVD- zCQe8-c6GWfdj3Ou$sd47o6_2SG4kO2rs_FXClz&e0PMvg^louD5B zF!*>E0*fKL9B0fo4Tt-YMaWVYP2-xfg+VWdb*jCv(3Jd-qSUIgZD{@g%O4%jBAP5?AWe8^@EmQYR)ij>oz5y#&v;BgtE4cF_6 zGD{HYw;RA=I5^~1;+1-J8S)AVT)}m{Y`-~(V-dNInd@T=fbGdR=lrOB$-57cx{8Rx zO~#YCbHQ7I=z7Qp_lCladI|9_QZY<30y*5aj6x{N8F$q?7SDmp<V=~OvK|hw?c+;(qBB(Gw-Ku zxLT(~_x8L-=FJ;Yi|p#bJszZI;fLevDt>}Ts+ZTa%s0&S0--b(r%VDxW_?0EHk+}u5(S>*bm6H;W}5hnfbH4wA+R& z?!g(khfDV?@Jy@+*Wm`CufxE+8M;GP6LgvB0mMTYraf25uuh6$n)j;md_G8HyknpY z$36z;@3}!z=?e2?`IaT5$rZhNI%o%Q81yvPu-Om~d^Jo{PRhmWl4jjX{tYG0H>y0X zdETR{^Z2_wl&C?>Aj)-O^1hF}1ElY(a6gFmV(NZ5+FRi|llMS;Cy4h=Jm-9i+k{|G zpW`d%vfhY&5O+tUJoPikz4QND`Os$3FZy_X2nwt2!3R^VHHckP@4>wqI4ti0IPzYF z{>gj}MWkHX`(11I*LanJ_3F}PlJZ~B|aMBQ^9snaUbQjT8tMenTq9*wf3 zX&nA@Wp)nVuZrDQ{sGq>KrWOaSNVnX1vy4)ct5xVvgC=b!(bcRQQZ$7xzqc>>tWkO z$dga*;fU0WI>4trh`vMa*Y5{c_+TI|$f+^yU>w&VCgbsWe=T^9r`C1kd#-wpmW;=_ zMRE~~;EV;=B_A;vk8|0FdqQ?D;!;H3i|&tT!_9RLb$y0d3yz2N;9S^1ZW3;CIc6+D z{0MQclH+UzkK80&=h9xv(1(^Ga=aRVXv1~xppaXHo#gicuRo#Df;{V}2)#0g z2J?gkkIlcnY9sPEk8zHWIfnU~xXztTE~2T|hU;AV9rOPLk$%B(qYd`kaGfjl$+}^> z!AE@~+HjpKe(ORP?KaD6;);7jM%EkYz7sGNoCh5({Tk_Y_{Y#OIo|bl|-dI|bZzyGWIehjabGpp`oI@FE5Gj|mMxYFN z`WhiAA6YlZ8bLi*ispUt&2@w9zv5DPePELt2m^P6T-rHf{X@0R92AVUaxUeZLqA|X zgAiHfw0Yh3NHnj{7+3wh1zfK>uMdW9))D0JX%DoI;T`C%$5D+@14~$8A-3n#TD6~# zCwPd-IO`JXEZnZhqaUKlRd{u-(~NB4yCzrRmE2?U%3k`Z3wsN$;wIsy%~Do!$!iO_ zl{kGagQ)6?*O@<$4f!68w?Z#<+i*Kq>1{$jac+c1+^qxO4&^Az@zM1Ub?&OO;V@UT zxi{>MY*zLbT(o&2F3&k5-zfU%>yQu13*Ac**+!LkWgA5@%I=QP8RrUK$?c8$eFnPt zy_Q>j#87V%u9uhjvz`V)myBU-qhy@@CWFZGZo8!`xGNx=b*WqQ+VHr|E1;8gnnhhv zzsw`ac(r;)9kaZl&3YXwT-UpG;C9HdPUgd2)>k9W8*?@s#VnWClvd(y zP$&3FdILP(kLZtV8`c$%Qdc%SvboZ48%nCKOn+8*yq-;&Ce#=8C*#Rn+N`&)a7|pd zndLhMkup-=rKoEgu5-x~-&JFd>I*j9m|1m*ZoS_7TB8ScP3RGv;Rt4@tTh7 zdPSz-g=L05DL0QMZgTay3Ur2glW?7DmWyK*$IE0qUS3m1^d{rNJu(wMXC9aC9lc4* zG55l;)Ov??!60>0kuIrg0bZ)%!R>!sa70pOd)mT49OgK(<{E+%u5Z$=3pPF(y*n@% zT$YV_3`Jz#Y4iETO7-qQa6i72@7YY)$@gp~%$i*FozA0R8^Lx$Ybm@s47tP4{- z;~w`^w5LJtw-CcRj4LzFMBnG&bDULkH-%=^y;b)!yqCQ;x8=+3?v^jdxI}F@b&`{>CpJ~9J0f@Zu3aoZ&+|uM(V9CTnv4@SLS;k zpSiV#J-sbo_Qx?9rySc%m6yE!)EDEb{3>zjzvOPa>_AWHAiLG2ty{i4*0tf3lDgV< z*?fFwX+AiuE^Us^XNP&lan_aCyqDMHzg2g<&-}>8cb=NJe7UvGhEq!C;vU}S4Xrag%D^j196t0b0(p_BYlK^Z7O+^`#wGru*uCj+~}Ts=xbl4D#lf z1vz}$gVe+0$a?_9Ky%0)fp{!psLP%Ku1Frcm(;sSs;}^Q1jjHrmgnn4oOMdw)XTPj z-KpNGIukmnk2cJj8GT0;r$K%^N*IZ}StpPaDDf!ec>#H|PE>iumau=C$L~eu9Ontd zr5>US%z`WZbd2oyT>PA`-Vq@$o5L7e!tcrA|0a`heJIjbGj2jgkoVEEV{c;KE7KQ8SwQ6qA-k%M=a0@}(8u)nF z#(wm(2}cbYG*0E1^hx^}Ho-RbBc7AnfXH-O{^id`KFaU&Pn|w>mMmbARV zivM`rwkhK-ky@)9cTSFMgIvs<*ooM-U9*kc??kqx;-CIptllP_J8RNRu?|_q!YPq$ zfn4mOb|SXTL*7zvAnf9!E?MxL$Q1`MV&{A0emHD$-*6;OC>~ z!%K1BGotqLoP*~zFRa;x!#jd{C;1*+n>_iK{-TA0as9a1wLjw83u`XLyUc&coqEw8 zEyClw$M@pe?Z}0BQzz#(^&cp$d9{84papX7gKQBPb*AOq582;?LtD~tc(3;WWN9De z8HhcIbL!WzWjJU4f}M&2@}6+U%t;exHVxV7bME_5$A^JTKDpmRWId#9qh4#2?{b~A zZ4a*Vvi?EEGjj(O&&$0zY44UdC-rWz;h+S%)EcXQ>7e2X;2sU`nYpfO_G-a1Nkkj2 zbMb_D;Jvx0zI^d1w2q5WwWaGA{tmqzM=`^--B8%P%qOpQO0Z7?-Y7&HuFr|fa(GuU zU&*!MI+yw5cb7DqdoFkvm<`vttmmO6awD6$hOpr}*DM$3KXPrj&Na&=TpO-)Sx;Bz zD{Z#nI=6_m$2(#B4$5^{@Y~Yv&i6djdm`Qu_1XbZ`4!hWZUQ$Mk8@pci;ONtPEBtz z9_MBa+iok-ZuAce9@+d>-Q?W*b1s11IfzSg+ip3fgmy03a1^y%Udp^x_v?VicT99{ z60UQ5v|Wk*cd;*e*Pk;I=ll6K+~f`|oC)p{=w1W+BW@C|bCvJ4`qCFvKMN4nfV99uV?<_8ZT^I1O$SWDwxl*n^YZsubtmp16wA+Tq+jltR zgFfSS^7`j`F4$61WwzmZdD;KyQ$>So!*#Co)1KfDf?kfVFCyA-og24J@%{p?4cEDG z+aj(F*SW*t8%OvoZ;!@BmIbU0UAU)T2Ug zgxmFsjHy>}UGImBABDYlA&$)Bu06lcq7g06{&@rLg_CieyQ6N8oa0PE?3dsE;$itu z9@!K2_HMD^I#=>1Pw7@%8?JNN_o!q0i@PYjL;9hvxK^>@QC+FB7QsC%Upr-ZexJSe z2)V3-BwXhXh5ua?@Hp?Yp76b8L>q4Bq7SsNu1#))N8H*edtr>(8}+mXb^Q_Isn9tR zb5b&{*Oe*5HQtW84?P>MbEAGb2s+2+p8fNu;T$Uc*Tf^6Wn5BY)r#DkoBE=x8_VOB ziO2P_4-NM}T+I88rMa$S_G@tp>r|*iqL3bsg!o;}O@i&2fH_-*M9Q z6*dcA&E`l(jn7h+2#@rdwnZ|^ucRyy9&t^ZYYUgVZ`FMZYrS~=3tr9UNG5J`ghzT! znD*?=;?(x8ZS{m*BbL(h4r@vEY$j_z!$yNlxlh z^xE-=Yubh@`E9pkD{L0Ln$3|++~x>J3K^*Tl(@~2j1AYhF3MXB>#B(7eBblfhh_X! zKB?mock93>agT61WQ*?lbH0On_A$6;KcdBkXJ9WQZSK+dsgL;pvFP%?z3Uj>xxClsJSgSj{XW*t7~7L^a>ZuKsPQ?z-mu}iUZyE0db!8& z=A;hLos4tMFM7G&*STsf+FG*V%u{@$)6mN?*VdMzHaZY`ySCVH>J+`qhkE(WCGDo( zqla!rUUod<7MiyXd<6YyZ?s8QpJi2c+we#)b&@N3g=@oUkFJ;JCRaUAOu}_;yj-6Q z=@@Gx$y3Lv_cVO)IR*B;Qa!8tF7~}VZ2YVDt&1opLwiXb&2)G8h{yzK)F(qRj~J%8 z#^=2lgPsm#!u+3xd^REdDfCMIOkV*x2HrzAA)0CS7m;ZQ_e6^>zmr9uW$334j_tVz zFZb7E$fK-0FPD6D89rNM9di#@ey179*n39*Pu{maJrll`AMgV*4t^<344We{l}5zKDDezX^F2-5_7e2G^*QIvB>{2wB=>%C9|TwL={yPTSko zL4E^#X89<@Qc$k8pR9Js!Jb77_ol9PcrB1;8AJIPuI012u-f4@XF2lUfc$BHuTf6n zp?asd5qb^0aZ|nH)s9wmrpZ&5*8=%glrzjH#D9>%H;GUK7f((89T3(ILybB(XQDk9 z;Dq1P<1;|PN3Z+6|LTjMx+{m?2wU|~s9U@12_B-meb?uj5$l9U?v8I?-zG zFxaREI}av1r=9wRf5ra2^Y5*>C^fGGcu)N8rd-SUo%8#ie{*VHNATW1eU!KHq@npG z>zY&ZI)S%Kk4~e8-9ImX)!y%?=5egZzj&`dZFsNz4ZB^v>eM5yf2`Zq>CM-i(00_< zK3_R<^GBaO-T3`kb)UXJwfUO6|2b0Xlh2l~`swBVt*f4MNBr<6_>CUy^~v$4eZEs# z;dRNsbKGI8bQYiY*xHX{*8KfW_WycvP5zLZuS(71IJeguXL@)3t=%2++vTfH-mk+W z557I;n2(Qr@3E<0URHO;{l|IxzV5m!A1O6ox9_uMf8p4;&vQTV7JdA7Zu0!~sr7N} zJiKL|KW|fW?yQzh=u>*ImygejmLApQ`_F%ryWxnvRxjv#=-`LPT-e;+eb}<=&bV@< z&0r z`Dvdt<(FJKB{h%F=QqtA)bi%rH|Nj#UV44K!K?f4Q7ungJGykk1rt}F_TRQg3k@@x zU+??Pqh8y4Uo-v}#Q*oR=!EsC73-O)KWzbVZY2}>R8XSaWBSaRj(k{=507kF5A4j^9{TMd%H_s zkH*d56>$C-?s=1Oor`qnSE84;wIf>bvflTI_)Ar#zwy5`?n8)~?e5W7RtG=^w7Bb=Z0Xcly1MOqj z1l<_;!hXEWV?X|I@xODmQ|Ql^mJo5Y;ZZwx88i@k&I7U6OW=(+nTucR z&Byg}otlit`_mqqP(Yst9IrEQSQnOqwlw^{i>0@owI5|7%q%b;HHjb8Z9&~LC8$a^Mb zvklklxw2fWllgfYUcJ1ETUlO(S1)gwYm`^;YUNcjmF2DE@;AsnT>M{@ad_CilwluC z#<{kR`jN=a!owqvVFP?+5>tvhkajht+=LFWK`R3hP`pFiGy0UnPWzmLB~KZ z#|+N)xY3+dChtb^RKA?O1+i! z9Op*$oTS&RPvIux)$7^hNDO@B_t zb-m~Z0XM2o@vCG!uJ;&l`Tb1OpOf)quGFXK6>c1l+iZR>k-prD=X=Sx&aG?<)s8ki znJaB!a^rZsyk=X7UnS$Z-pV$LbECFXcwDd4r?io9lksG(w1vryu zvcY_*ez$#A-iGr&KZD47Eb#Chv^BxK1Ls=d+HmeI2-nPi`-^?@-)Vx6d;n>bOuoW>Gm+vpA`_YDy;>h=kTX9aV4UhCH zoz#~N^(w9nkK5dUzR&&^=TdJn9@7in3iMgws`4scB~HJ}Agc13b)x!yWnG11LUk_e zpifui8Q^+7oBqRh9{KxEHoTf&3D@*1!41DM`q5s{yUsWDs^6ko=U4AXifif>uF;QT zeyeN?^d{nQ-|)&d^Il~y?^v`oLo#mG736}xuXAa060X;ky6y#iFyguxKbT(JQ<2-7^)!OXr zjJof~eRHb&{&8DzmyL?XwjKh<3kDfuD$=mOEK{oCW$iml^6d(igMrs!POwJi`Hyk3 z8;)u3=@;&ZzWc}h0G5q;oP)@`)8=#3XVGu|&zx5Mw+3;&>b^uHbaP(sus4-IY=^xU zL0CA^Mt?|Km-l=g`2*X5Wn&%_5Lw@8^BMg` z!CaHha$$VBF3~89`>gZxz6vE z2WG*e`!CfVd^dTOaPj`zA>`sb36FfqlmU-=5#!tlujDFw9fT}+*|OeBTyZC5WL!%3 zeax?Yss9&A(WRzPj~gTdz2cL!p`6aEx=#O{64@Nm z;kg`nCBl2*4C7k;`ZIhS|Jf28#SS?Sj_`L0Jw3<; z=juosRnYLdpq$#=^Yu`M_A>A~%fL3`SjIW2Ga}c04F7|RZ1c4Bxd~-k0(s`gwqV^b zkDnq^SK561Ow{I0msFpNrXg>(IppwZ4?$hv^4B`(ZSHu0T*UCmHEl3=hv#vebpdtG zbbPQ5p)*yRPl8UiIk~i#{Bsd$Q(C*%BM+{dl&=;&^kvs^Ue2laN90_NCa!eHxeK0F z{QZ&F{>V$XCa$2T;b{=A= z3#dI%hT)J-sy=x>erD{uvq8RrQ1~$ud8_$LR&V;%C@pzUN8YqgukSuUJ*6?>J($596U>o}aYzuO* zeMo(b=p4-jtV@=Sd7O_(nY8(=M?RbjKy!YwlV@kRUUf}!0Wx8mLJptyAZ6IEOSkfx z754IzamvwV(?&a&_e31COs>K? z$3)z-Aa_=tI`O>&=%ozx+VDy)e$xpyGQ_!+c*N~AbPn|*GO)ZwVFY(tp{u$#}#)s5m0G{+v9@%;34gwc(T!y^&0ttLwGlIv1M=Pvaf& z5yW)8c0AG>$;9>Aah+R_?=IDabrqEtd&(9(iEHW=u8Aw|g&8&XVQfw{_uYoEc_J3C zeS^B84>1IOC~4SFe-3axjdrB3F_0(yHt07Zugd@v`BtWp7lWRbenXr#unz@k$cj95 zNxGG3$T2Y8J(QGuQX`{C@1l;c>yJ}r9oM4Ex;oU3`C#I*v`4EpunIOqF#{BIAYFM>goO*+=X3fE^SBt1g;pR!uegH3qZ4+_i`P=yTIryQSCM9+*{M~zY(|#ASX%u_}v1cAf#ujy+jO+XV zO125|CYO0s;`AMuD&uXaN9U3w`r|l#N8{$Ae#!pXca-DZFbdp6yt9?-xyW^tQ#ioj z>bOlWWi~)J_%Xc^9@k4d|A@%ox&gPa54biwNpBYA!}w7+3N|-rdQDvC7NJYV09~&Q z*ST$8_&z1{a$J#fIa05V>s+;_!#f>53XISbvamf|>zR1GuE_0)C|t=a8ISvw=rOs; zc-)^wkItnX$#~o+=eJ;A8EwL`z6mi49_z=3>vbjdDO_?EfN#T1ZoyN}N3YI1g*!BE z60UQD_Jgg|I|tm~w>X8_;M;JW+m5nv{}Mc>JIZ|{cykbKxXxVwAHD;eE5V(O*o3l< zMYQ2b+(F*@o*}X^Vc~x`_1UYmk=> z*SRZ7_$4Sr$90^w;H^Y@8DcUn`-tJX6r6R4*MZ0P{j%WEA6qTBu6LaWIYg6d!*wpp z$MzMj=(FL~xT4SG3a)e4p=>N)0s1)yI7mB4+i;yLvcjdlb%<76n^Q!#3G&@Fy*6Ce zD{W%dl?|`Pl{zuGg6mvq6VXds*=9Ce=SqGi*M{rdWj_2Dx>#3#gFZQzV;qnBv)LBX zu2x)YqYV10S3-L-xcEhGq#s7K;kwQIeX;+9+yb~oq?-_JxX$egE_DO}T=rY?ZMe>* zy-N{=E9Y`Fah=-^-kOkGa51)`-m{1{T<3C}l3xM zLS8mp=N7$4u2tjOaGeWX!5WE2oomB&uGsdp;uiiydo`O)T;~S*Aj<%~K^>8sjCY1q z1~D9;TU2>XZfhbQ=W@NvbvEmUp{b?M*dp53hU!Jy~#_ zE527ixs}cMofzeu8dJkA|CO0}=pEZk%~zUDV&#O7qYI#=q-C0xOEuC#?IW5cU)rMxCr@M>HsugMi$=SG;SXW`gzog3K_=h|?c z8`WQ&Yr}P}j1N-JVzUib+)FVj@%bS3ky7oEo{oK>wOE{~JyOnh48fd<{$G&>R+d3p z##5PdD6gk!v&b-AgpVT>o*ad=tI~Hf9pX%Lt%4B9NSgTk5NBHUG92fs82ggv}*YZ(&qY1+r| zD0J83sMcn)urIK}C63?3!EbMU%kSj%^Kt)g!J|G{TUh9k2YK>x+b$c1^I6R{oU*i? zdOI{`d_-_AaLNCCaSeV$uS3p;8}~=f=Zp8uAsgqdx>It>UN?BgW5Y!+_E0=Tmt5+` z|ND6OZ7G~5zBp~y+;I;*?=gMiqtCmC zowh6L*>PTbuIIP=Kc?`J4?OSnn|tCD#NYhhuKpSKKkqXA%AcP1{s=zP`+fJuCt99V z_~Lt?cWVebpVq5mydUriahAUWqS^NVIhW%i`$1a&nRj6Hz7l!oV6mZ@{wnHa5*yji^j<1G1$6VUv{INyZ zRCEKo1`QtV6oU(AGh}mt zEUx`3gE#GgG>w~jZg9!+Q4`{iqh7N(VVlzNh%=tn`=u7|#ZB(yXJB6}RQ`U0@SxiH z=-;ok>^SM~xl^w^F*UCPc%A*{Tb|i?r@P3XnVLtl{$9J(Kj)AUxz|Ufx3eR7-SdBL zx${@oxEo)-Iki5{L1X^3%3pNh%ei0A`SvL4kAl5kIB#_u@N2(w&9>a8hVP&~^wg_yKbw`KV|fw!9VWs^mF$-{m>=<`-{3k zhYs-`y7sUUe;Ia7^Su{8Fhbgo^FrNy-+Fq@WlsL}zwW!bhf{d``yc$Wnbz*}{^Q|u zal8k%^o}PPg~z$|j*I@}KXCl^+>(P&t*3kx?B(kOp~Dt`;C1=VlH9(ZZ%NJL9DdvZ zC-^_=dZ4@LkiAp4AD^Yp{%DJL!(SiFZJl~|YJHslAA9^sZ)3NKrA1$X$7i-I-=dGl zmcB~))N|bQzn>!Q!1+gSKb$(lW?dGvUyo&1jTrdpao&LO_3kcH-g)YmZ{AyXB|0pB zcO}hO!M@$=kZ#UL=&Vd%xRd`K#PzD{kgJdh{S9*XvfXh*hjHyzoKc2cK;eH{AQ3#*;4uorkbDHPym5xgHFIv%2nHVX5M<8kig zs4JH3dDwe6xLtjIHw!B&3$E1_?e!MI<{WrGNA#d~uF{!=!>A0Rs%PHw1-<~@v4}-* zi!Rn97F_2dlfaKJ1@CG+BfJB)E&$JtXK+dB72ji>{2GxqIEXe}*USB4`X2+ zl5x&OkzVO9bHFPiK8Skby}Aw8xwMUP5zh91Ma&5TIWjU#r!FAQR!M@Ls zjAw8~)w8rGWwW&1Lv*8~iR*fop}fn$X+q@KA?I?8<8qIr^tM4y8}v{o<>XwBCa&uh z8R}evDCcrCah)4HO9<>n)FZ+_V$b-KaGlHjobsMesF&x- zczl18wn;nEX5l2`ontoBe{{XVO~xy^^hpNSjr>Y{(!}-h(q76j(5I=F{UI5T>%9i@ zOG54}9E1MjVRlW#t8&ag2(h$$b|XZaA?RN27XoGSk)Dg zf$v0w<+b23y$-*FIUCX7TJRXRB7d>jv?s)&qHJ?T{vu=ABe>2r+tG9JeiHm88ISeB ziuw$>7Cg>1%O%`oJjSgkuh?vsSK)E4_&oa(`>)IkHe9bOC4>KtK>aX14F1`GXu}nE zb|&1vPWfNN^RNybi$(eWz5Q$UZ3Z4$mlbJXWf`P7-ZMN7c?owSEjZIxpq>~gBWdCs zOBk4zy&Bn{R>%Lde;vK|%lp@B;S1d3NqbMS&(YET^;O{Vo`(L!e6B;R`3iX*a*W!) zCTGHV)%UM|jl6kZ2swP(1M^}yA9)YJF`Sz{tUp|wB4puTV-fKlo0IjDadn@jxXU0z zIR40jy7E920ZM6>s;!#;U-tNnf6kzX|uw4U)ljt+3Y}P(N*_6%;PZds5cpB zz1q1f@4<*BSK-`?iny#3-R6IRM>!j=bD2N6j8e~Hb0V(k729A;a4%1t!eu=$6p+8d zxu&PhbKq0l6N68sdXD!Je5yY<A+`UTJyFoPd z3SNzSD0tZfuHZU%uYB-q#~FYleWE?5&TY8P-5>Jwi$f9fi1a7&ZMe>DMZK&*WZ?79 zHV-0Rylw(laGm=a?E4F1JIcyB%jVSYFWT^G zT=wIG5lyb()wl)lrX+9$ug2|%vhIdx>J_{i_h9h$Pv8o!b6?Kkon1uM)nWOlu57r@ zspD2EN#xu)OtL_U2HZMe>D_2c6e?O%sz!>e%}@Z1Eh z;3k)K$}y7tp`jG|Gq5CF=l%;aw2wjO+Hjp~)(QRkz=XOIyc)MLhi^C{nt2MYbItnX zdL!t+D2F~@2(EKqh7Nt)ko;|UHLm!E$rZdBSL(#%3a)eML&VuWoI8&w!KYDH8*byW z{}+)*7J2Ag9k+3*m*YSClFrp}oy)N_uo*|T4SkYa8?JLbaF{Ox%S^q@!-nfz>Jfh? zXFkqFefYllO&{NN7TuDj{US5J zRKv>&_crRDDSmH5(HmjgZaAjBC+Klf^m`_}pJ3UT$4!XToi?9)kdNHg%-qRuTj6@u z`IRoTfbM!6)xG)x4|@?VP7$(bU#@xSTgiB5NI{*2OCEjNlF+I${IKJ*82rcbKA7j+BrW_v>ppZ37K7;3%~?M31LWPQy0VdPbg2Mzem z{$xDh<3ssMQ}BPZiXU;gj^O{)R^qBWA(uKK(-Ft9p3=+lCa|Rf=e`b#DS9af8S)rp z3=^)2>s+_Qvegz&aMiOhRbH$e5^)(PXtOGln>V>OoZ}rs$c4?b5z$tGZoQr>aa}KX zVSUEAHeA;m)hFwQVPu}|YsZt?NVv3_e5vO+E@Q!hjOx$u$5j3KZ203D;INIAZE~c( ziZrnDoP#v`y~uE^lC*9ceI>xl^Fc-dv3Ix$)gba3_o*c85hmCs9CLVNSy|6KUkC!n zh_wCh-($NuDSs9M)M$)Q z<7&|b?BTg8>N1OC7UxAAlW1IkcDj+Yo6}TD$*?Jouhp zP>&O<|9;2q$U7J}C#L)TjibM(>V$cdyEwFMdP@F0@af~qwxLyjTclXFZ73M_z`Ph< z4Q*3nYd>Gzt2TL9+qr6dWS>dKX%l@q&dnkZ1{oiP8^_rXA}+5{jz?Xu4cEE-a^Nu< zTpO;qcc7l=W78)NO*PgGKCPS64te%H)-m~iK>R&ojmig~_COhiGf!82Ppv^{Hv{XK z_E)4!s%!xsjzOc2m%Q}xg%ZSJPI(NXeZlxLF`X~m0ox{q`AnY}8yChgUp*`Vp!z_% zabd*w^>JYk%F6a;(A(RFo9#U)SIK32C*eAm`BR4D5QF%r4Nv0I-tNf5ZQFy~tbD$uMZJ2dR_CkvHpv?-nn|d%$PikZ)eJaAU5| z12=fc3PHVF{3x#7j5ErR%du|J!ZW$=iV*C-s$}>{?Tzl=q z{O&)D#vF3*N2FfVL8vA9Ao?BxpYxDv@6&Q>eZLaN-SX-?DnoI!;Yyd{a;-NzO#auZini=6xEXSywh(=dSheyELw{ znSD#jYr~Vce7{#OuW(IV=ep4ALhm~0?5LGD8Ry(bUwR-T{drib{`>)asy{g7vaiu6 zna6{OHNevP=IFEaac+FoKD`Wit3Ev*8tj4k8Lmg((Ky%BRX*N^dU5j6IA_DvI^iMc zRO8(ERQ2)>bh592=Fnd9A4XJlG9IWsh}~!ZSRd!Aud^RP-l|U0t+Vey-ZIYp31iZt zg$qY=59)d!?uag zLq55WBC2sNUD+0%qmOfqC0LwCU+|q^?c1J1AH=y0S8b-oIqnMw>rEV+z!7dTE_<(v zOCI%d-KukKxUQFDM5~{`O~iR`kU>;>SuXNTy*AwB(q@h|S0geXmRah`#8taQdd)Fd zxJkIlE!P$FnRU80!}WEGDcFb4cEEtu9E8uzHm2yn~d|jX7ocJ@Gr=eQGb#Wt2t^l~gq#_5w0H)-tWoS2O77U$x*u#0}rIgInpT35XX z;9789?`ggobKeDb8=`P+xXxvrP)_Dvy`GbBotrdIwo|{SY|!UV;yU*7(I@n)n{j>yVlp0Y-!@n2HMz-nrBBl4XAtSnfnOj^y-B!kGuQi+5jo-7aGfjl zNv^DM+L5;5iu+hb=G1h*sj(j8dJ!F|BO9vxT>_4$@?1(!Q$NRDhIaM-o%T$kpSlq2 zt1wxE2y=qI!t+1jg#JI}f^>7vLzC2;McX(RbIxM(TfhA3Heyw#(jf4=Ns#<8}P@Jod?xao&?bT_Shu z!1sf^Os?QqE|j@_*8U5!a}oJl3vc27%!fe#e)vC!WSn&_dQF)=Yuo)EjgR3!oa0=< zJ8N7dJvDE}_1bV4UcTbT#vdX$K)pC@pVQP+_7kr-ylAQ zbTOzmRgNTF*BdV{>xp#@D?Gg(G`w8T9UA-Q4k{iEonM5u7m&UwXTw>t45FGldxBFy zY!CTNFF>^6I@k4--p6v=ZmD6N)v5pNOvZa@dSCl;J;t~NPt%w2AA$HC`Zs;tANe*M z)UwT{Ol@Jk%ikTb;X3!j#kcvW8(;Ja*M?W)ip?fhaGi^^r?=xP3Em&GZY_mFP8b zU2j;{V4S1PqSuD&Tvf+oq300vqu}>zQQoeItm7m+ve_IDrH|WiU2kpS9Tz(A{F>uU zJ8V7`&vkFl*>Igp+qT`(i~Sb!3;Xa%CGm@7JhIv3GLNkTZ-5Q)JR>~LWt~KGS$v$V z#3L@pn?7ro1!d)!qkN<%>OC2!e(}jeoxAYgr0=-o)lTV$au;3htJ`q$gzGqsZYS?n z$nO?#J9+ovd=1WRc*OnW%RTETt8{)H|H*hCcn9ZfIMkN);=hDTY!kCiY`D(FJO(cB zT^aN_Eg6sByP7hbL)lKrxXx9!bw{7&I;F@M*kHrC=8o#w>@UIi1%5KlHMgD1{>NZ) z6|Qq@r!?Y!SGi_zLylTA*l^}5dMTsog=n*hU;y#mp1^MgG1gdaA#v)xfXMAGOp|0%bS?vJkRyUwp-2#xi^BF zj0^XPjJn6b`Zv|S-R?i>=CoqL%yx?IA6U+$dknUh++#2;?@6$3*!~PmxBDv1Pf4@h zM27V#Y3h-D&MIXBBCd@cb-YUB&EGIH)-6K~BCqj2UxLVRzn|+=%5r|^+L0LjpZ5j4 zMm~dZZ23M3CA=p}doQv3Ox(vHbK1rG5Vi&LScyoTY4aKPvuJO4!p!Q=d!9nxEEnYP zX%AB7dyw}4h^cjH5&rdXPO;b?ttG@f+b|iA`XjFUQD2C-Hk>+Os^}#b`idTLO|Jz{ z;!#`fE%Bdb{O0VqF9w?EM9f|#G7&R9Q1 zSAGA1^Bcz)jtP}G`zX{IzQX;TV-ZcRiJM&R1r?!}ayqvX=XZrOWxez*u}$YD<8nXG z0ZjQ>x;>uhsHfHXk06`D+kqQ(C+C`GtCZ%{(rgQvH9WalPvIEnYw-tTV{r(;lSG z#zA*I#CU!+xPL)pUrNh=1N`V+8R_HHo6SXi-iGV*<`pIO?;Uk5uHrtNSL-Glu5;Uc zH8$`!mdT$FF8MZG=Q4lJ?s<1vgJo@nKE%TBN2&ZO@y^hZK~!U_a9s}&0&Qj< zHeBbxsspBwc$Fq0lq(ueGYZZ zJ%+5W`lAikxhxks%Msa+t{tWNl?~Uq!YdkF8?JL{BXyWu8?JN3wmHxXeud2@u5&TQ z1mhFDQO1qnJQO|Meu`W1I#^d9pp|{LU#^YS6E0&ja zO}%L2pzhgDaXilDI1KsVoe#=!--_opTrV%je(Gl6m@ef_#^ZXWuNT1Y2`=;DIAX=M zdT#UZE`zK5pW}|4%P|W~$Cb@5X4IMobAGBd&pyBG=B$Ks><**K?W+6;z91OeCrC$g z6@T|Js6$?mx~xc-G#R8>XCfo%?s=3W#F^$?&A>F?K1^L&>Xfc`L7@{ue5D^=5^}c ziTgND(aD`}mtI(NVt(@EhCK7d09D6pPvhF;$@B8&wRdr?8P`gXB%itgVK3-sc!!Un z@;eITc#vI%tIRhIhr8@PWT}ht48%$}XI_H63ZvO4XHJ?t_1sA_FSczLiTrISe=Fo! z)|r#5e>WS~tKK`lhD_MMAcs$TDC_=pbni&JUq@u!rRDEAN56L*TEcH*h03>lHaAt2bPTMdbgj_A;0~UZ{&l$D(6HTSHXtmB^$1DF_J@e z5Xw3maVcUg_<2Md9@)I+vL=7cWn*D8-&Y)y-@faw5U;`V5~ z3eS7yAy9>`S}B{%<2D*Y2LtkK5gfbj!d9T9I1TNPe3|w=!;+%opE~8X>4$|3BemRajXBdjK zyw}2Y`5$r4K)VhVJKgC2nO=rW5s`t<^f}%$bmt=@2A9wDxrfCdYg<|C)&Qei2VM+= zE<+w=J0tRbHYp$dIX~CZJZI4J;rd!%OUpaFNpgHP%J#;z9<0kv8Rjo*aM8COg&>x8 z?)=4#-JCWQp5=KBT+Y4pE#~t#MAl2%yypEjT7yrRS^YWN-;p=h2#~|4Jy1WxM&vyJ zM>W^dHyZF>*zKKGxJQst8v9PlPkE% z9UAzRvX5o$il}61PaLntrT@?;O|Ib8xb%Ujt|GmH>)eTfeVx3U-A>+e_y+Bzj$}N( z2T0ovEb(2-I5!!u^huq|veG`2tMEA2v`x6lc-&_3-|`Vx_im5Ez;+SJ4)()#_`lz-bCIk6Xft|4?%t4^7+Vn0FJ7^ zu&!ChMGw)9jy7D?*}tGO*y|gg&IewCPU-{Ap}pj9LZnS;?H+x5^q$0onX%sz3i3r( z<$&w@UYAF`dUy+fTF1&;mipBwEp>J+bk_ssUSbOu_6RSmS%G?6lT&%C_r+G>+B3LD z8FJNqiR>ZDk!%%);jkLA1=VS}&wl#|2QgXosjzEUzyJE==?w}MMK;r0ZVmr6`kx0Ec<4}WV|}J9lSxv!{jPlxbI}-J}TXB z)osLFbXsS%=2CsdLFfrx>wKnA$6l1~S&C#>_bd+s$6&T?MOv3Z+Vhl5!BzFgGtSXG zX9(u&Fi+0~5T?uh2@va`;30v)wB$({u|ZE4+)N;g{)~G*j#CUWQ*&+3P=iQ0xlT-% zG1sd+XZX501n&fJPUjkp>l}GUK;OfZeM-tvAH&XcybGg(^>E6y#q_(nISY_E?RyJc zu1)9@%x4QC^`>2?j99AnDe+5HE!bBch4H+^XWK*Ge53w_`}P>E&btB|gxHwJfA_9- z=3c+L0v`lya{)MIA4NWzJn_N?QsU4(WJUe&09#RIibcwDWjRyVX12uX*9-+<9-@TL0ajU2()wM{PLf=XdRK$12{Or?xwrm(F<>Q)h{2k}yZl8hrJb=EV2fLl@Z|^?*iQBeeNdD)`CZy)^`NEVT zJ91;b_3vE6*G@^zV?Tdw?vlF33mS4OuA^`2!EPtVh)3qE%Kf2cOK!xX*H`JRYW@Nj zckZA1_uTJZ-I6=?;Hy&e=-c-l{$#G-T`P0n$_-4-hKjQHGvX}pkeyRt1 z`6xx+-!Hy0_f>ctBUgA=`y+mLM85s*zoMV(!LF}E$ougV6LMdL$FUXfJ=CkYtY2z< zy}{bH^o{)6$Lv{pq3cbn?{3&-_~yR9tUG!AuZKPR)bgP}XVfPVtcRJoX^V0_Rx(Dxiy36lA9r158 z_}-97Gp5lurry)dxwWGj%Vvz5QFYJoJrL-Jki(}v$ap#80ev5X>o1JGYMq>m_O)%e zzLpait{;ksaxO;`H@R#l%;y!{BwXkAgS}$2uGfa^TnG9Jh}28_XlqwQD;}&T)cvC= z(>1iiifde{6Vb~xd%%ZoDGTipT-p47M$Kht+f@7M3(>aRGX%|f4WBLYh8ALlQN zeiw4WdDXvH^8xY>_Jhtl((ZV;Lj4SnBkut?s``AOq}J7}lSagLU)_J%aJ?NxrX4)i zqscXKlRHRsk`FtW2lGtA756`xa7}(*y7zr|e@N|Vq8lSHZwBh3j*4_%lgZcc@>h7a z@gZyr)|V;Uq2}S}*#_H?Wn&&6AyPNmofcR_U>~mDhI}~IbKJggO7;C#T-Wy&10U5D zOdEH}#F{B%%%1^|qI= zM~lc%a8>`}-nI?bxgK~+L#_j^oXe4U>bTD3|I%j=gWzHnfqaUHHeBa+1MfeOWhl6c z*MxH$u5+oA_5}gl$B=#)(T3|>?(;Zk;{syOyt>aW60_l&Z!Ck%GVq!Z|Ic^BqVKA; zq7Bv|>h;V%xGt=#?x<&}UmLD-MONBKI96P1BkrLT5rr!p8?Ni6o-AyY?`W;_u%C%& z!>e(nPE4-gI#=|F-Yk5XWw7BoSMoEtHeBbjzut%FxN2{1CDO|flX2dcWDwPQpv_b3 z0j}d*M3(cKQPEzRiR;{HkmtBI3&-oQmvAe-KXVKEv<=s}3vy234sZv7I~k$4xX#Uj%W=Iy@%bI0!fbGDxXxug z7Z5K6_iEJD9pEj1%{JWRwz*0#^>aQEZW69@DLa2u#LYq{?X}@Lw=cN#-y-bB8(m|I z{?-Tiy?+~Sa_Jk2OAh&pn}qA!KqvGJf;Mt>m@fCudHWXujpePRN|eXB7>-WgZZ;w7+7B6CgX7~d6YN% zf(_U8vQ8sz*oTmp4cEE!J?apj6hBVJ<2JW>(Y;<1@{n^mW`XIru2=k)b>+Hh?Y$3d zw&6OL9NNsFb9tVOM{UIGqC@XTHeA;$GFjxo^ii<40nvsl?#EEhy=&a#q`KetagQ<$ zo1T4HoXF>(hkhhjISs7rmq^nO7wcwd()##^Ez;!DRo`mix18P4~~?9yszcs*AT+JGy5uo{%nTlyq-bq zz>_fOG8|jTrT=oQQ1|cnmn@_ic&k9^I1kU$(T7dKhBqQl$IkQc&iEckRS?d7Ux>z=5y7m=)Jn8ORD?B7s#9K4LN+;gS7Vx$a?_9RC_xfk}hI+WZw_Qi|{;- zvo4^{`4S&&Gw4j!W{0ef-m9a%fDa`?0dsgsS! zn{~qT&af>5K7Al9f5bET-qmamRocAmmfm?h=|*&MZ!_CPOvL3K1hz*f?;~&9W$!^2 z;|ciqtzoaWu-&!c!tDTK*&eVrReSsb_Fe>ej-{QQcps0+iCj+b&QY8lqVj#Lok-=a{;e+MA_(fY1`uPXR#+w9wPl9XiFTKPbWm`OPkl%TBGkA zHC}T{v(YI(J_DjOK%1D)=1DxytcwsCV33>#^=eIT}z#Ir854 zX~d!%v`@CrXvgDwFnO%R#f=1o}-;6;%5QlwGi(Kd@k{!z<4dhv%8LV zmJx5yscRwb_CUFabKTBsAzsA$Fo8Vpw|Gs%gZ#6=f@{hi$~Oi1;GEYq`LV?L?HJgCnmANeC{@~ZxU@tTGQ?X`kf9M7^H*|uCKhVmZTH^ABcth?~L z^q#-UVcDF=fj@{C?EB&Rx>b(1c9p{JjPUIGRZihW;KY6x;U4g|zW^t8V}v*U4f($S zoY*xH?g4LH1Dx0;5uW|~DkuAA;KU|Jcq8z(=YSJCHNuO)i><(k9U9?nz`bXH6Wf6L zk#cPS)`CcEPJ{>YsEYt=h;Zi5I&z5dUFk5NM!|_?BRnfOv8-E`XL*Bsh_y#J>nFg8 zHRK|B)Th!5Y)*u;{sWxY@(2&wi*^!Q6XD)#p?ovyfo&YxPuzKVRS%3SdpX!4zW9=9 z7$<(9=W;mTKw*rJ95iESvKmQUw`B98;0!m)Vd3E%W|(>R(JD` zf!-V6zk68S4+b{>^;elPF9Y73$G=f}{#P~mjnDtKe$(6IhWxVs;mx1*zu=MIFF3ZY z_vHD_`(#_|zW31OBOm$k^78vCFx#p7!Oi|Z&fDLe*nPkJ%NPIf(YwDfp!wHNUvboF zv+C()J0*SzZGh$aJoR*bz|t24*VCm;pda%$_Qq5?dheNa#W8|M_FaA7 z>+3jY;5B{Ui@wbB8bk(JbyJRkIQ7tX8G0eX^Oaz>#^U%_sM2 zw0AMSsroxAy^%M48*=!x2PyNl$a?_9l#jLgPOyHVj}={&<~k}Fr;o6H6qoBN?sJ&j zWSsBE+PPdSWf_e;1=qQzZ6agCb*|_To5^K)ZMfq0K^?PCp^j7asZFTk!)laYs=5R@ zSPusKLPlD22Qr~8l4hA0vgJKuWE%wWUHUx(aq(U07sPjm?eyWa{&B+V-JB~S51K>Y zV%eETUqtFin@^{8%7yZKdw6<^+_J7WF zM>*{ycGUd`|D8C)!@Y=W!>O10`$1>W=I5qs^XH(G`pBid!br); zd6lo`%SLdQAqqDck8{_8>mjZMPuH7_$GL1_S;N zICnv48wwHg$z(jvT@`YfFWZ;;SYOF_b#B&IeqwSJz7uXq`Beosz=gXv<^;9&Pxl{I zZ(vT?0Ow#Et9Ip4`m33y|Fi8G8cH=he1-SD`@=SlGnm)Nw1yyGT>apm(cUWOI+l%j z?1M;|wE0}$7Og`j44?Rd&+sP;t1D<>s;ndJto(N>)c@d3B7#B@K{9VGZxW?n_Rg+ z@It%!js>}u_)f+d=p>i@FE;)JxcGnaJVKkv<=9w+?qE&>rttXK$oiyxEN^`%a~h8p zT$OiU_(jm~hEGa$fAHOn>Nou|@ErOS`B}sooWlq4X%CcPnEIx+R-8Fp_v;G3-4A&O zemj%9WcDC=-;cZpKup!=8q^1Uujqz8i@IRl*>K$l=woXTO|A`(aj6$v`g-7dpvwl8O`iNW{CC^6CECNj{4TCNi)*boqYSx#5ZKT4qdMa!XP{Qd zk|(+j1c`eT7fzZsZOTOZzqg6}jj(MZoGTH3MYt}?gl)(=Xrf8))7n~cY~>X}Y4(A#}{hnB8eKM%Occ%0j1 zSzTE#cHmk%_U+t4o0IW47teLd+z#vhi1hqWZxSBoZrfu@nM<9tn|hP+IQNThEGTnX zR@PTg&xv@PyJO44Wv;5@mjiAxZg9Wpm$__PRc5qZA|B`Jb;Wx6{GiJNy~%i-tLIN% z?dCI;&6?f_*SRe*+akTmIN$%vAac&2PTij+e;clI`8FNKX+&A$3`Kf=-i}9l+5XD+ z$eok#(tfjlQ1O?(4cGN5Uf)pfoIH8lv$NqkmwiR~p3>WA>bO5!rknX zZ^Lyi`?r!)+zu;xmHLd`?A!1-_u+8dP+aIQkxyS%<3=3UxolhI^GZhf)X<>KlW?8u zIJf4ad7X3R87Mp3*M>*!tM(wSM7>fkxlKru%X`-(T<7vSpZ^MXZpgLaI+r{T^NDb| zj-Xx}u5-ydI2UpM6>@F3&Lyu&*D%(3A*mpbWx!WF$XT<6Be(r6w` z#`R|?(U?|rIo8QMXv1}GG^Q!8%-uFz=SE|i;znx*83W_E&W*-2B_s2%4cEERm?m7c z&avTfu8e7lD|2@=*2Qt18;x~JM%HFFT<4neoy_|-T<30m@ILtCazv$9e8Yz8&*nZ{ zybiyY!~djET=5MXu5)p(T%w$C#W!rY&Q&@&CMvz+8#Y|$axC5Qq^$ZHeBbDxBi@;l)2&?HeBbDw|&=J%3Sdc8?JN7Q*EirE52dFb#CMX9CLWT zpw@&o9Je{;wOQl?iYsd*8?JLBA5dIbBiV4B8~K3Z${NXr>)gl(gsav_HeBaMKA^a= zMzY~LH}V0+#TXx~k!-lmjeJ0HWsPLRb#CMXiYx198?JL5FIYc^{g?c4rC`lq!Q*Q) zjyLV0Ka%qgmUlJH2c>Zg&6%qccp*UP@9>y@$HhU;AR7o98Pvklj|YCMc= zmNC|b3-@4biV(r<{(Fa6Nr9;C3K-f3G` z&-!55BYb*&aIO4XOj&SNAmV%A1za=bgL_VXN4y>Rw?mFP+H#Kjt5xcLRPqm=>E)g5 zNvqX0v4=S9S&QHK<28rBKe-(Fal8ZG_LJ4Ywcr_qhI><22iF4mvmhJF$8b%azgNj? z&T{0x0r?kQyorV~Jyh=$H=!oI=kgveFO6RJd;irJKXq3Qy%A;5gZ;f)=DFkB z7y0$>_j4ys90uFj>Wa zr;qYBo|MfmS=XGJ$9}j=k4~e8-9ImX)!y%?=CSWy_0xO&gU-7t_w(huwBS?=QN8?Q z>$}G?N;~k`+EqWjJV%~J2$Oam$B4GW@9}3`ehql?eQwFY&f~Z{f4`IcyMA{CcnzzB zp^kPQpDP@H;rIO$A06ky-&dWyUx!B?e0$C@A0PYPV^hDptZwbDCwPc1%Z7K3%kL@k zozUa|b7pSQ$G7Ar&&T`vu@LFwd&)YGW8UE{tNnSKKF*!h(g}S{4|X2M$yfIBeE<26 zayJ~Y*Xjj*4;}pQm&wT3sdsNF4*G@0paKXgYr~S9>(L%$F=GXgv^QhN%JUVj5 z<;Qs=>W|0&9+jF;>HKWDKDjo7f3^hv`MZx(`zPlNc#Mm8mi!_;EONvmYX#aXN0MYeL|^HQlxMBZ?m9sZRe_ zd)ERaS5>C(bRLj6?DEhcPdgYCR~G{qdBhI4dnP1Nf*~OCNSyS{bY@z5dL}*H2}F=a zLGZyt#R!PlvbaL6l(7UWy0~;tLe;n>D`l;_NJ$y0)>jE`tOYHowcPJJ=l*@qJ@=mG zPRdeii&Jyvp8Mbb`~Ux(^PlH^bbB9;Q;0_tUi!gX3ZOaY;oQ{b0d59(#3(kTYwW48 zm;DXx?KRO8d$(o!WA7q*>Up4+4>1VYKxZti=UaGAOk~OPyC`}UNY5a`Bo*F{1lvT~ zvRpc^-x~!#@vH~tjWU)aQg&K7--R5ueZ977J%%#G+@0?(vraa_-#4L6yXf&c(KrYU zv5>>^qC5tXsj;WQ-k?r~)6~g=`MOS+M`BM8^E<4>JN`*MJOVt&DxOb__V)iXAe;UT zK8I9I7TGUC_A-!kS-!r58BQL3l#l&lM0pOzMc3~yM6n*~gTcnybQ8-tCv_;Cud!Ym zzUrX&!g|Cb4>nflCUyhlA8zQSPVyzwIc}hMrL3p}k%8sK{1VUdOQM^4Z62}BMK`gB zL;eOsuh^VS7n|P!!|Ai|i(W44^?`@s!Ug^6H$5{*)2E1EfynD=eXD#(fA?Ds)7AWV zacB5w2IZRJosdnxovs$aXI_b>#lD9in|{l4V$Te0ON(E0XxOG;TXnKFBE}8cww)E) zM!u*)#+lf*4zk5IV$Tk3ONIYR)V7JO#jb6!@$8(?Hu4$PM3Z9M&jQ&Es_u+EhA zA@Nx6aShlyun&FUj5=3hL2rEuv?Yj7brAEqzr=nVdDS(}Sq^~Cwy*~gywsug!KQHD z^40yQ?mBa-gKHtZyB?PHC;73ii>*HcdSsnRTa)Nqe+KkF)B1BI>WA;cZmmt%YZI#Q z694rD)cm4;ZyYB)XWhOFk!kpKs``C)vG!}u9c6t)(Ojp#_|04M2eVE+Df`ibSf~Em zUtpd3wm;iC^@e-LI+e4IDBO1B$M$VJ^_FkF=DCT-Zd$j0#iBnvy6TrN{O`YPxukyX z%l}<|?53~&wELcFuujGL_9OY+<)7KhdI>|gez4bZdY$^c&Yt!mg?Hb?T)Lo!5TDfBOET-<)~u6K@FDReGIzOy}<3|KcFl zsh{gywCkt-T-T`&teEO-DIHt5?Kf|Wty86xxJEVCsa$VnuueVa$YTq0S*LQ&$#v?f zf4rkGmvt(~V6Ic2*>^`_F6&gi-rU{6oC5o9Z%w@()9X#nM}V8dI!>=Q)34)l=$p8X zOVhVyz_;`@nE%h${n-fCGcw@fQfypX1=;jN^6|PWuy17e?%#%E?wg?OT;TDS8h^~; zy5H1uS&l`VKkm=#-=yMvlJ{+r>D(`&t|<0zz<(s7jg8Wiu^cm(Bih&~JsEoya5p4i zqx59#iLm#i1e>GuD3*S917gefJnCp7wh>+Qq_PtEC`6TKDQBCWgq3{RSeu@NmGZQ) zHa!U|^=M;ldJ=X&%IBAeHrA#mVI^PmPX;NgD4lz8ai5fY+1MyO87uj+u~B+5R_f8l zM(N2|DH9tTrAM*!y*m+aKpA6Bs*byncG1nUBG3JZ^yi-d!*EJ~jnm_LO&;Q!30R?< zdRc#;Lfn8jg?M`heE@7vrgLlv>zBB%AyQWhQLxGMWbEz0?LqY0kc0gc!A9w_p45Gv z*tSKmI5M3~k7B>p!3-5~Ir!-ZP3#*Sj&w3Tilxu{h%86?-)LgZdcF|2NbihTjq9++ohO}dG-ZDTti)R^+dp;drC-Gh0Y{E`#$z&e^#R zl;$k+B>44>6` zvFXV+du`p9aSw2lfwk$nUl>Fgt9}7xoTgtm;e>wm-5mP2-rwYrZR`N@7)!&311NJv z|9}52s?{h<)vi+d>-8t1E%fR66@8s`K^f;Ef{gd))A{`qZ_xJxHRjBoZE6i<>o#>} zsy6kytl6f-r)*zx(amv7e3(b}_ow67>V&=>rLzysAV%Ax@U-&!9dlczrqiE^U5mVG z-##;yZ*N0h9|rDK-`4)eGDH!ounr0B+v)sf^U~0_>2s_L%6K=T_-Pel|xBXv-pon~H6M`TdxnJ~?KF_124%3+=vRu%fxacB2l zpv+A;&N1+M1`%2429pQdoN7#5h$Hv?dA=UZ+K1BB&mWNAJ-|^1>z3t385bZ@|422R zoadKmAM(8G_970T-)XDw`L<8N?~5;bJnVx=&*E8B(3*=@$M{KWpR)SB(9e5X!;MR&qxum4Ft96Lpl`<@16{&DH`om)?A-(QpwG?jS&3xw63~qh&FTr{K zFH+;^XF6aV=g&i(n!&A)zKL}gd>``^|M=86wn3CQ#RnM^S%DAL=hPj$D!Pe{*W)$Rt$Z?C@0xDbFUN6>H*IF$?xKe_ z>%20bQLKxO>>Bx{9}(MZYdp(J>rJMcSi4MgzT#ySl!Kwy_S=_!@LJeVFSzKY&9?t& z>>&0_qJAaxUVbG!wqFU|^ebCFR=vt*7rl2o(pX!s$TZv0AoNTkJ`Mu z&2Qau{M7!ev7kBVrp>$k*FO0|J^`CZ=UiFJ894a(?zW9}(K+uGY&>7P(0({avh%Cy zfOfI*dS;>3C@w3H_Esek+Rdu zc^-0%_a*W=4{EKC^w;;|cbE`4E--I4-5jeq&U4Sw=5f(&EahW;qx6VgnLF5Y6KmU+ zg}qA>Y!#FB#BfMIOrGxg1%BA>Eu`=)5WWB0Mg- zIlqYWu$(AMj-pqen{$M?ZGy3F)^u}j5|)j~@0L+eW;Wd{E0#+Z(dKc{O|0kaqu1#y4+fS4^)XQ2&ZKlu?}`WME*89!CXRRpGfmml z!9d=fNonA^JV=Y2C3}_a3BQBN{*i&#+3&Hx;(iY4tW){~!zJ^izbc)kDarq(jIKVb z-+K-$8AO&Z@$X0E_2F7N8DBg*d}m~2Tkm(BE`@CF8-TBfgENSI&qDSxaPgej%L3cd z;&bPO?~F_qd)sz-U>o?VPQwCQc>P+)7TbuuBCstj{>Ks9Ce7Q*sy<8`Hg#>AOjWPP ztPE`$q63Vy&m)&uiK8AU|uPAliyoSu(pf9U-izqP5;d-}sLbh8ft zAO5?8DjQsW9J)h)Xt%@XZCI}CV>cnX=%GI>Xy4yP^tDD}H_Z_5qAvs^^E(22wLhf$ z4d48#xIaAc{mWout4-Zj8aA~2fIg%0JO_Umg>Bj&(v{_JVVn2^>w$Trj1nSsr>&D) z&ei@fpN6Y6|l`>T$@XFY_Hn@>!R=r()YTAbT08JSVm+wxz@$ zmXFw0pPm{O)0D4v6(aG$&^EA5o0lSKv28tMi*3YS8QPW#|6tU%Qng;HiE(zhRYKbo zU&J8eL~Q$&VH>d%p>3(~s|&i^_)M93KNEWhgL*u9ec-F2++w?$3+N~h;(Txkr zps8`Q18H%{DnnD_*1}#hxb@A~Y)y@0KF#391?@1v&8Eh&ztqnm_Rn}(Z?!t@{&VZo z_cIk1zsYxUY8>Y$I<$P$<6b$_N4Gvbm)?c)CywvKn!$}@I|o0?V{SO^b6~{PIRE(6 z`Z%xG{y8^&dM&_un;TBAlU|-PPT$X5f_j^qKJIULx4%{6=1?wtCV|g1Xnn=h<;gKb zf(^U*3VxNS4D$W_g!nH9i>|Dem4WzH==LiJ9gL~g%AG_ehK@$9~M*_ zQombm(ObvicdO4p{yFb4_{qy_N)Gop136u~tgm_GoOhPbjeuY6kqqi}XbUn2Ut@4R+deOHPx&cS{V~O!K}_e)FV#(2EG#{_hxc@;|%R%RUPJe~;72 z%WI;y{aVd$)2Y`#8uB5-KOXrD>=eDEP0@dZ9_T&%Evvoe$~c|8ye9mj*QSf!_KB;# z_UQrt6w2*o*s^lp!SCHy#vB~l0km? z{0r;WNjLlo&zge|(Z;&yCYJ9$7<##mqrJA?F5Sdh^1D1Py2ehS{c-HazSfRj3;RCs zFr2*(&%go0b7HpzY2p=wb(f|HOQk1*}U#cci(r#942%mFa=$)swG~T&BlRs*Z z-#EjsRIJ(K-+F$g!}LkN_ReXp)%2nKp7v2|&;AbSgSdXRzsG0#jql#m{{8uxJkyQF zjo-Ory{7+Y)gE8#+&L(^k0%p?Uf1X{r(duP<|8gZ4}Qv` zAFwW2K9utzMB0&7R_8+aE%Cw(M{~m0LwB)S+(DYc_-&_F1m?jxqz>$SK&ZQrbq8<9vARQ zSxGs&=(b+gr(mUiGn5Pto7 z2QSlZo6qc5C*~Z#*jlB-`vj2s>J#QLGo=dRzD)7&zdEQ#s#XuV+ zh+dwPz6<$L=@}&>q24l@q3dJvZVTy*Fwtw`Ur;waZ^nt8uX}&L$C)GX%p>vFBL;Po zO2&5~gLA&HZoV*(TsKK{yKcy1*8%G+iLS99fxSW9^t^#1dG5PZ*A0EyT{mHUgmpvy zNF5ePAx-K`bV%K39bx-|soi$>QJe&Ib-EJc_$M;I0lS;vVO=rL#NU9(>+s7|GRl{Q zbHefMkvU=P-L)GboBbE~@ZTN8zK0-t8QACthi&;*9_50F@2a1>7tfqM+!EactODqu4k-f<>7=-K}3kuY(?9fun7Rx|{{;qLYul z@iF)#+d2F()fl|!@_z490Ewk96Mqw8pO%6D?m!-fyEd8arT05CH$%2=FX`Tyc?Pnj zz3B2_d)bf3wXkMz`P{W!!@7H6Sk=+Hl(|;VVjC#LwbmXU8on-LiFx!bchhwX*FO#CMh`yg<9dpe)~-cZB-^L2v#L_ldPnmjM^j=tzZ)1gSVwpeMC;3%t zGuWI=r|)DCbss2oB3N1by66$CrC0RHQDo}#=w5@^C_Hj5$0$9zZnte?-j73c(M_9e z`C@A_J-Tiu4|TC_xo#JXi*D;Rv8LW6x{0L^aF0XuNV(v-!(>&#Cq4c;yf(p@ZgMJ8$8G~@^m zY29=|^=HQOU$Pd`&n@V_GXwSW5V<~1+Gk+Dsh_LxyibFX>m-&X4$h$T;_B*BxOdKa zApSFmyq;FZr?={UKH5&j2c%z+eA{%>e}rciWyC-%`&Jj-#0sxq1>>TdSk?#o-Bvr? z=MtYtqMKOh=WMKtZepcu1S@v9=)JI_&&CSf#8MCaSM;j9qRf-&(SDdX_F;mRa(2;s z=@or)?8;R3CHKR^BR0!1N>A>GyF5W2#CDr*+HA`gTa)R3J^e82L)x0;Q~5>$UFY|+ z^Sb?T&qbs39X~?5Zv*ou?uX%r478PHZKql8%o_vq)lGv}_(|h6#Y4KJaTFdY6V3Cd z?uYM~*X@UUZU{+PKJme@A7(ue|2f2i0w8WBJ@2M9k`5O`P>@$ybl0ZMf8E?_dS#8Y~z_2_T9i;j_3jF`5`t+k6@dJ zLg&$l40T|$9W|CX=nKJ>K~!^#7*DGW)xPJV_rwCn@A}5Dn$EdaSFd+d0pHX{WH4-Y z&?7d-cmkW9^j>GjlsWgUKlYOde(qE%~dyDvZf?Gcor8QgZx2iqmrX7x9r4t+2+j%yC!I{fC9 z*M2%Rj_m;LJFg?2`-}v)o%-2~0H?n1W&+(f{S177o5Q!jICki<@&Igo`{SlI_KB`< ztEv6CgZPFR*J=mz4KdEc59S+UoD1u3h@A|7Sv{CGf1Jy9zXhh=4Kb1Ka^bvPjRicY z_Q`~VSHjJ*?V%o?O>L*1f2MzTZuYNC@-ym?&O{^tfVIKxIiB6ds`$gng?TNET?J<({ z5rFVWBb-+edoLodjrZ)4H4pL6Y}fOuu#e|h0e|>2jUiuxy)uSOxQ7sxC)#_$j#tMJ zmO~iaZTr?zk|Rw&(McRK4iZeWS^Tn#PP`aBIkZ0hkY>v&*hmqwii9m(|xsho%1Tr zk>tK5uh}v<7vj9eC4+v)`2??j83uEGFk0I&)N5ma`D1wLL;c>@aKdw7jMoLciY_O` zrvBXr+008?+0R_7@8_}%iTxpz(7t~_4D_Y4@$3)lch!l(``o4NJ${?@e#oYcc%Pem zNF@i#Vz?f%m*L2BV!smDmKOgE@Ty*x)xYO0tFJ?h9=#`hulpM$P!bEf2L2H``FrlG ztJ}-9$?61Nh`xNXT8eRs%_m%^-w}!F3Urf?e%Yutrc0yVS0VoOI9bQ7CaBZ_!DNWTUtGP-8o>3e_ zYHHG(YK&Z&8*O;gQzay(8~AYb7!O-3rDATn=#7k*$Hq!ECa13~m0%f@waMbhI1|Ig z+E^(!(eNf36?MdSuWOSe4A&+{MkXs|rngV>V$mC`HL7(chU@jpaBWP{iuK8wqBSa& z+;GFI7xCrnMy1Gftvodajl)om8%9))1221=EBc_cT2Lw0!D8!SziYW3Xc zbgiBpse9*DiW8;j+}6s(G_S5H*NR)WmU3g|+E$*gE$%3m%enC#BjJMyclassToCreate) + { + case CameraShipClassID: + //======================================================================= + // Create Camera ship + //======================================================================= + { + CameraShip + *viewing_camera = + CameraShip::Make((CameraShip::MakeMessage*)message); + Check(viewing_camera); + + viewing_entity = viewing_camera; + //-------------------------------------------------- + // Create controls mapping object + //-------------------------------------------------- + CameraControlsMapper::SubsystemResource + control_subsystem_resource; + + Str_Copy( + control_subsystem_resource.subsystemName, + "ControlsMapper", + sizeof(control_subsystem_resource.subsystemName) + ); + control_subsystem_resource.classID = TrivialSubsystemClassID; + control_subsystem_resource.subsystemModelSize = + sizeof(control_subsystem_resource); + + CameraControlsMapper + *camera_mapper; + + switch (controls->primaryControlType) + { + case LBE4ControlsManager::PrimaryThrustMaster: + Tell("RPL4Application, CameraShip using ThrustMaster\n"); + camera_mapper = new CameraThrustmasterMapper( + viewing_camera, + CameraShip::ControlsMapperSubsystem, + &control_subsystem_resource + ); + primary_mapping_name = "Thrustmaster"; + break; + + case LBE4ControlsManager::PrimaryRIO: + Tell("RPL4Application, CameraShip using RIO\n"); + camera_mapper = new CameraRIOMapper( + viewing_camera, + CameraShip::ControlsMapperSubsystem, + &control_subsystem_resource + ); + primary_mapping_name = "L4"; + break; + + default: + Tell("RPL4Application, CameraShip using default mapper\n"); + camera_mapper = new CameraL4Mapper( + viewing_camera, + CameraShip::ControlsMapperSubsystem, + &control_subsystem_resource + ); + // primary mapping name is NULL + break; + } + + //------------------------------------------- + // Set mapping subsystem for this entity + //------------------------------------------- + Register_Object(camera_mapper); + viewing_camera->SetMappingSubsystem(camera_mapper); + } + break; + + case VTVClassID: + //======================================================================= + // Create VTV + //======================================================================= + { + VTV + *viewing_VTV = VTV::Make((VTV::MakeMessage*)message); + Check(viewing_VTV); + + viewing_entity = viewing_VTV; + //-------------------------------------------------- + // Set control deadbanding + //-------------------------------------------------- + controls->SetJoystickDeadBand(.1); + controls->SetThrottleDeadBand(.1); + controls->SetPedalsDeadBand(.1); + //-------------------------------------------------- + // Create controls mapping object + //-------------------------------------------------- + VTVControlsMapper::SubsystemResource + control_subsystem_resource; + Str_Copy( + control_subsystem_resource.subsystemName, + "ControlsMapper", + sizeof(control_subsystem_resource.subsystemName) + ); + control_subsystem_resource.classID = TrivialSubsystemClassID; + control_subsystem_resource.subsystemModelSize = + sizeof(control_subsystem_resource); + control_subsystem_resource.segmentIndex = -1; + control_subsystem_resource.subsystemFlags = 0; + + VTVControlsMapper + *vtv_mapper; + + switch (controls->primaryControlType) + { + case LBE4ControlsManager::PrimaryThrustMaster: + Tell("RPL4Application, VTV using ThrustMaster\n"); + vtv_mapper = new VTVThrustmasterMapper( + viewing_VTV, + VTV::ControlsMapperSubsystem, + &control_subsystem_resource + ); + primary_mapping_name = "Thrustmaster"; + break; + + case LBE4ControlsManager::PrimaryRIO: + Tell("RPL4Application, VTV using RIO\n"); + vtv_mapper = new VTVRIOMapper( + viewing_VTV, + VTV::ControlsMapperSubsystem, + &control_subsystem_resource + ); + primary_mapping_name = "L4"; + break; + + default: + DEBUG_STREAM << "*****VTV has no controls mapping!*****" << std::flush; + Fail("RPL4Application::MakeViewpointEntity"); + vtv_mapper = NULL; + // primary mapping name is NULL + break; + } + + //------------------------------------------- + // Set mapping subsystem for this entity + //------------------------------------------- + Register_Object(vtv_mapper); + viewing_VTV->SetMappingSubsystem(vtv_mapper); + //------------------------------------------- + // Enable collision detection for this entity + //------------------------------------------- + viewing_VTV->StartCollisionAssistant(); + } + break; + } + Check(viewing_entity); + + //------------------------------------------------------------------------ + // Load up the control mapping stream for the entity + //------------------------------------------------------------------------ + if (primary_mapping_name != NULL) + { + ResourceDescription + *resource_description = + application->GetResourceFile()->SearchList( + viewing_entity->GetResourceID(), + ResourceDescription::ControlMappingsListResourceType + ); + + if (resource_description != NULL) + { + Check(resource_description); + + Check(GetResourceFile()); + resource_description = + GetResourceFile()->SearchList( + resource_description->resourceID, + primary_mapping_name + ); + + if (resource_description != NULL) + { + Check(resource_description); + + resource_description->Lock(); + controls->CreateStreamedMappings( + viewing_entity, + (int*)resource_description->resourceAddress + ); + resource_description->Unlock(); + } + } + } + + //------------------------------------------------------------------------ + // Create gauges for this entity + //------------------------------------------------------------------------ + RPL4GaugeRenderer + *gauge_renderer = (RPL4GaugeRenderer *) GetGaugeRenderer(); + + if (gauge_renderer != NULL) + { + Check(gauge_renderer); + gauge_renderer->ConfigureForModel("Init", viewing_entity); + } + + Check_Fpu(); + return viewing_entity; +} diff --git a/RP_L4/RPL4APP.h b/RP_L4/RPL4APP.h new file mode 100644 index 0000000..a46e5f0 --- /dev/null +++ b/RP_L4/RPL4APP.h @@ -0,0 +1,29 @@ +#pragma once + +#include "..\munga_l4\l4app.h" + +//########################################################################## +//###################### RP4L4Application ############################ +//########################################################################## + +class RPL4Application : public L4Application +{ +public: + RPL4Application(HINSTANCE hInstance, HWND hWnd, ResourceFile *resource_file, ClassID class_ID=L4ApplicationClassID, SharedData &shared_data=DefaultData); + ~RPL4Application(); + +private: + Registry* MakeRegistry(); + + VideoRenderer* MakeVideoRenderer(); + + AudioRenderer* MakeAudioRenderer(); + + GaugeRenderer* MakeGaugeRenderer(int *secondaryIndex, int *aux1Index, int *aux2Index); + + ModeManager* MakeModeManager(); + + Mission* MakeMission(NotationFile *notation_file, ResourceFile *resources); + + Entity* MakeViewpointEntity(Entity__MakeMessage *); +}; diff --git a/RP_L4/RPL4ARND.cpp b/RP_L4/RPL4ARND.cpp new file mode 100644 index 0000000..9f36318 --- /dev/null +++ b/RP_L4/RPL4ARND.cpp @@ -0,0 +1,22 @@ +#include "rpl4.h" +#pragma hdrstop + +#include "rpl4arnd.h" + +// +//############################################################################# +// RPL4AudioRenderer +//############################################################################# +// +RPL4AudioRenderer::RPL4AudioRenderer(RendererRate render_rate, Logical mission_review_mode) : L4AudioRenderer(render_rate, mission_review_mode) +{ +} + +// +//############################################################################# +// ~RPL4AudioRenderer +//############################################################################# +// +RPL4AudioRenderer::~RPL4AudioRenderer() +{ +} diff --git a/RP_L4/RPL4ARND.h b/RP_L4/RPL4ARND.h new file mode 100644 index 0000000..3fa99f0 --- /dev/null +++ b/RP_L4/RPL4ARND.h @@ -0,0 +1,17 @@ +#pragma once + +#include "..\munga_l4\l4audrnd.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~ RPL4AudioRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class RPL4AudioRenderer : public L4AudioRenderer +{ +public: + // + //----------------------------------------------------------------------- + // Construction, Destruction, Testing + //----------------------------------------------------------------------- + // + RPL4AudioRenderer(RendererRate render_rate, Logical mission_review_mode); + ~RPL4AudioRenderer(); +}; diff --git a/RP_L4/RPL4GAUG.cpp b/RP_L4/RPL4GAUG.cpp new file mode 100644 index 0000000..3f6b8bc --- /dev/null +++ b/RP_L4/RPL4GAUG.cpp @@ -0,0 +1,3823 @@ +#include "rpl4.h" +#pragma hdrstop + +#define PRELOAD_ART + +# include "rpl4gaug.h" +# include "rpl4grnd.h" +# include "rpl4mode.h" +# include "rpl4mppr.h" +# include "..\munga_l4\l4gauge.h" +# include "..\munga_l4\l4gauima.h" +# include "..\munga_l4\l4vb8.h" +# include "..\munga_l4\l4ctrl.h" +# include "..\munga_l4\l4icom.h" +# include "..\rp\rpplayer.h" +# include "..\munga\terrain.h" +# include "..\munga\mission.h" +# include "..\rp\vtv.h" +# include "..\munga\nttmgr.h" +# include "..\munga\app.h" + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) std::cout << n +#else +# define Test_Tell(n) +#endif + +union quickCompare +{ + char ascii[4]; + long bytes4; +}; + +struct colorTable +{ + quickCompare name; + int colorValue; +}; + +static colorTable + colorLookUp[] = +{ + { {"Aqu"} , 1 }, + { {"Bla"} , 2 }, + { {"Blu"} , 3 }, + { {"Gre"} , 4 }, + { {"Pin"} , 5 }, + { {"Pur"} , 6 }, + { {"Red"} , 7 }, + { {"Whi"} , 8 }, + { {"Yel"} , 9 }, + { {"xxx"} , -1} +}; + +int + determineEntityColor(Entity *entity, Entity */*local_entity*/) +{ + + const char + *color_name; + quickCompare + compare; + colorTable + *colors; + + if (entity->IsDerivedFrom(*VTV::GetClassDerivations())) + { + color_name = ((VTV *) entity)->vehicleColor; + compare.ascii[0] = *color_name++; + compare.ascii[1] = *color_name++; + compare.ascii[2] = *color_name; + compare.ascii[3] = '\0'; + + for (colors=colorLookUp; colors->colorValue >0; ++colors) + { + if (colors->name.bytes4 == compare.bytes4) + { + Check_Fpu(); + return colors->colorValue; + } + } + } + Check_Fpu(); + return 255; +} + +Scalar + generateRelativeYaw(Scalar my_yaw, Vector3D &relative_position) +{ + Vector3D + delta = relative_position, + unit; + //--------------------------------------------------------- + // Generate unit vector pointing towards 'other' + //--------------------------------------------------------- + delta.y = 0.0; // this may induce an error if delta_y is large + // (but I think we can live with it) + + Scalar + length = delta.Length(); + + if (Small_Enough(length)) + { + unit.x = 0.0; + unit.y = 0.0; + unit.z = -1.0; + } + else + { + unit = delta; + unit /= length; + Check_Fpu(); + } + //--------------------------------------------------------- + // Generate angle in radians + //--------------------------------------------------------- + SinCosPair + sc_pair(unit.x, unit.z); + + Radian + angle; + + angle = sc_pair; + Check_Fpu(); + //--------------------------------------------------------- + // Get relative angle + //--------------------------------------------------------- + angle -= my_yaw; + angle.Normalize(); + Check_Fpu(); + + return angle; +} + +static char + *nameCopy(const char *old_name) +{ + Check_Pointer(old_name); + + char + *copy = new char[strlen(old_name)+1]; + Register_Pointer(copy); + strcpy(copy, old_name); + + return copy; +} + +//***************************************************************************** +// Compass +//***************************************************************************** +MethodDescription + Compass::methodDescription = + { + "compass", + Compass::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL },// mode mask + { ParameterDescription::typeInteger, NULL }, // NWES radius + { ParameterDescription::typeColor, NULL }, // bg color + { ParameterDescription::typeString, NULL }, // 'N' pixelmap + { ParameterDescription::typeString, NULL }, // 'W' pixelmap + { ParameterDescription::typeString, NULL }, // 'S' pixelmap + { ParameterDescription::typeString, NULL }, // 'E' pixelmap + { ParameterDescription::typeString, NULL }, // Bug pixelmap + PARAMETER_DESCRIPTION_END, + } + }; + +Logical + Compass::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer *gauge_renderer + ) +{ + Test_Tell("Compass::Make\n"); + Check(gauge_renderer); + + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeInteger); // radius + parameterList[3].CheckIt(ParameterDescription::typeColor); // bg color + parameterList[4].CheckIt(ParameterDescription::typeString); // 'N' pixmap + parameterList[5].CheckIt(ParameterDescription::typeString); // 'W' pixmap + parameterList[6].CheckIt(ParameterDescription::typeString); // 'S' pixmap + parameterList[7].CheckIt(ParameterDescription::typeString); // 'E' pixmap + parameterList[8].CheckIt(ParameterDescription::typeString); // Bug pixmap +# endif + +# if DEBUG_LEVEL > 0 + Compass + *compass = +# endif + new Compass( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, + position.y, + parameterList[2].data.integer,// NWES radius + parameterList[3].data.color, // bg color + parameterList[4].data.string, // 'N' pixelmap + parameterList[5].data.string, // 'W' pixelmap + parameterList[6].data.string, // 'S' pixelmap + parameterList[7].data.string, // 'E' pixelmap + parameterList[8].data.string // Bug pixelmap + ); + Register_Object(compass); + //---------------------------------------------------------- + // Make sure the icons were properly placed in the warehouse + //---------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + for(int i=4; i<=8; ++i) + { + if (warehouse->pixelMap8Bin.Get(parameterList[i].data.string) == NULL) + { + Test_Tell( + "Compass::Missing icon '" << parameterList[i].data.string << + "'\n" + ); + Check_Fpu(); + return False; + } + else + { + warehouse->pixelMap8Bin.Release(parameterList[i].data.string); + } + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("Compass::Make OK\n"); + Check_Fpu(); + return True; +} + +void + prepCompassMap( + L4Warehouse *warehouse, + const char *image_name, + Vector2DOf *offset + ) +{ + Check(warehouse); + + //------------------------------------------------------------- + // Get the images and mark them as permanent! + // Because we record the graphics operations, the indicated + // images must be permanently located at the same address + // in order for the recorder to play back properly! + //------------------------------------------------------------- + PixelMap8 + *image = warehouse->pixelMap8Bin.Get(image_name); + if (image != NULL) + { + Check(image); + + offset->x = image->Data.Size.x >> 1; + offset->y = image->Data.Size.y >> 1; + } + + Check_Fpu(); +} + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// *DANGER* HEAVY-DUTY WARNING *DANGER* +// +// This object records graphics operations for +// later playback! +// +// Any graphic entities (such as bitmaps or gaugeImages) +// that are used here MUST be locked at the SAME address +// at playback time or the playback will crash HARD. +// +// *DANGER CONSIDER YOURSELF WARNED *DANGER* +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +Compass::Compass( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *new_renderer, + unsigned int owner_ID, + int graphics_port_number, + + int center_x, int center_y, + int new_radius, + int background_color, + const char *north_map_name, + const char *west_map_name, + const char *south_map_name, + const char *east_map_name, + const char *bug_map_name, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + new_renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + + // graphics_port may be NULL! + + localView.SetOrigin(center_x, center_y); + + radius = new_radius; + backgroundColor = background_color; + renderer = new_renderer; + Check(renderer); + + //------------------------------------------------- + // Make local copies of image names + //------------------------------------------------- + imageName[northIndex]= nameCopy(north_map_name); + imageName[westIndex] = nameCopy(west_map_name); + imageName[southIndex]= nameCopy(south_map_name); + imageName[eastIndex] = nameCopy(east_map_name); + imageName[bugIndex] = nameCopy(bug_map_name); + + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + prepCompassMap(warehouse, north_map_name, &offset[northIndex]); + prepCompassMap(warehouse, west_map_name, &offset[westIndex]); + prepCompassMap(warehouse, south_map_name, &offset[southIndex]); + prepCompassMap(warehouse, east_map_name, &offset[eastIndex]); + prepCompassMap(warehouse, bug_map_name, &offset[bugIndex]); + + Check_Fpu(); +} + +Compass::~Compass() +{ + Check(this); + + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + //------------------------------------------------- + // Delete local copies of image names + //------------------------------------------------- + for(int i=0; ipixelMap8Bin.Release(imageName[i]); + + Unregister_Pointer(imageName[i]); + delete[] imageName[i]; + imageName[i] = NULL; + } + + Check_Fpu(); +} + +Logical + Compass::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + Compass::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "Compass:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + +// std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; +// std::cout << temp << "foregroundColor=" << foregroundColor << "\n"; +// std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n"; + GraphicGauge::ShowInstance(temp); + Check_Fpu(); +} + +void + Compass::BecameActive() +{ + Check(this); + + previousPosition.x = -999.0; + previousPosition.y = -999.0; +} + +void + Compass::Execute() +{ + Check(this); + + int + i; + + Logical + bug_is_blanked; + + Entity + *viewing_entity = renderer->GetLinkedEntity(); + if (viewing_entity != NULL) + { + Check(viewing_entity); + + YawPitchRoll + currentHeading; + currentHeading = viewing_entity->localOrigin.angularPosition; + + SinCosPair + sc_pair; + sc_pair = currentHeading.yaw.angle; + + Vector2DOf + north_vector; + north_vector.x = (int) (radius*sc_pair.sine + .5); + north_vector.y = (int) (radius*sc_pair.cosine + .5); + + if ( + (north_vector.x != previousPosition.x) || + (north_vector.y != previousPosition.y) + ) + { + previousPosition.x = north_vector.x; + previousPosition.y = north_vector.y; + + Vector2DOf + position[numberOfItems]; + //--------------------------------------------------------- + // Get new compass positions + //--------------------------------------------------------- + position[northIndex] = north_vector; + + position[eastIndex].x = north_vector.y; + position[eastIndex].y = -north_vector.x; + + position[southIndex].x = -north_vector.x; + position[southIndex].y = -north_vector.y; + + position[westIndex].x = -north_vector.y; + position[westIndex].y = north_vector.x; + //--------------------------------------------------------- + // Get new bug position + //--------------------------------------------------------- + bug_is_blanked = True; + + RPPlayer + *bugged_player = (RPPlayer *) viewing_entity->GetPlayerLink(); + + if (bugged_player != NULL) + { + Check(bugged_player); + Entity + *bug_entity = bugged_player->goalEntity; + + if (bug_entity != NULL) + { + Check(bug_entity); + + if (imageName[bugIndex] != NULL) + { + Vector3D + delta; + delta.Subtract( + bug_entity->localOrigin.linearPosition, + viewing_entity->localOrigin.linearPosition + ); + + Scalar + bug_yaw = generateRelativeYaw( + currentHeading.yaw.angle, + delta + ); + + sc_pair = bug_yaw; + + position[bugIndex].x = (int) (radius*sc_pair.sine + .5); + position[bugIndex].y = -(int) (radius*sc_pair.cosine + .5); + + bug_is_blanked = False; + } + } + } + //--------------------------------------------------------- + // Erase old compass + //--------------------------------------------------------- + previousDrawing.Draw(&localView,backgroundColor); + previousDrawing.Clear(); + //--------------------------------------------------------- + // Draw new compass + //--------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + localView.AttachRecorder(&previousDrawing); + for(i=0; ipixelMap8Bin.Get(imageName[i]); + //--------------------------------------------------- + // Draw the icon + //--------------------------------------------------- + if (icon != NULL) + { + if (bug_is_blanked && (i == bugIndex)) + { + continue; + } + + position[i].x -= offset[i].x; + position[i].y -= offset[i].y; + + localView.MoveToAbsolute( + position[i].x, + position[i].y + ); + + localView.DrawPixelMap8( + False, + 0, + icon + ); + } + //--------------------------------------------------- + // Release pixel map from warehouse + //--------------------------------------------------- + warehouse->pixelMap8Bin.Release(imageName[i]); + } + localView.DetachRecorder(); + } + } + Check_Fpu(); +} + +//***************************************************************************** +// ThreatIndicator +//***************************************************************************** +MethodDescription + ThreatIndicator::methodDescription = + { + "threat", + ThreatIndicator::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL },// mode mask + { ParameterDescription::typeInteger, NULL }, // inner radius + { ParameterDescription::typeInteger, NULL }, // outer radius + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // teamcolor + { ParameterDescription::typeColor, NULL }, // othercolor + { ParameterDescription::typeScalar, NULL }, // view radius + PARAMETER_DESCRIPTION_END + } + }; + +Logical + ThreatIndicator::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer *gauge_renderer + ) +{ + Test_Tell("ThreatIndicator::Make\n"); + Check(gauge_renderer); + + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeInteger);// inner radius + parameterList[3].CheckIt(ParameterDescription::typeInteger);// outer radius + parameterList[4].CheckIt(ParameterDescription::typeColor); // background + parameterList[5].CheckIt(ParameterDescription::typeColor); // team color + parameterList[6].CheckIt(ParameterDescription::typeColor); // other color + parameterList[7].CheckIt(ParameterDescription::typeScalar); // view radius +# endif + +# if DEBUG_LEVEL > 0 + ThreatIndicator + *threat_indicator = +# endif + new ThreatIndicator( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, position.y, + parameterList[2].data.integer, //inner radius + parameterList[3].data.integer, //outer radius + parameterList[4].data.color, //bg color + parameterList[5].data.color, //team color + parameterList[6].data.color, //other color + parameterList[7].data.scalar //view radius + ); + + Register_Object(threat_indicator); + + Test_Tell("ThreatIndicator::Make OK\n"); + Check_Fpu(); + return True; +} + +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! +// *DANGER* HEAVY-DUTY WARNING *DANGER* +// +// This object records graphics operations for +// later playback! +// +// Any graphic entities (such as bitmaps or gaugeImages) +// that are used here MUST be locked at the SAME address +// at playback time or the playback will crash HARD. +// +// *DANGER CONSIDER YOURSELF WARNED *DANGER* +//!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!! + +ThreatIndicator::ThreatIndicator( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int center_x, int center_y, + int inner_radius, + int outer_radius, + int bg_color, + int team_color, + int other_color, + Scalar sensing_radius, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Check_Pointer(this); + + // graphics_port may be NULL! + + localView.SetOrigin(center_x, center_y); + + viewRadius = sensing_radius; + topClosingVelocity = 75.0; // in KPH, arbitrary choice + + innerRadius = inner_radius; + outerRadius = outer_radius; + + backgroundColor = bg_color; + teamColor = team_color; + otherColor = other_color; + + operatingPhase = 0; + Check_Fpu(); +} + +ThreatIndicator::~ThreatIndicator() +{ + Check(this); + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + ThreatIndicator::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + ThreatIndicator::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "ThreatIndicator:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + +// std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; +// std::cout << temp << "foregroundColor=" << foregroundColor << "\n"; +// std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n"; + GraphicGauge::ShowInstance(temp); + Check_Fpu(); +} + +void + ThreatIndicator::BecameActive() +{ + Check(this); + // This empty method is required to override GaugeBase::BecameActive(), + // which immediately complains and deactivates the gauge. + Check_Fpu(); +} + +void + ThreatIndicator::Execute() +{ + Check(this); + + switch(operatingPhase++) + { + case 0: + Select(); + break; + + case 1: + //----------------------------------------------------------- + // Erase old threat display + //----------------------------------------------------------- + previousDrawing.Draw(&localView, backgroundColor); + previousDrawing.Clear(); + //----------------------------------------------------------- + // Draw new threat display + //----------------------------------------------------------- + localView.AttachRecorder(&previousDrawing); + Draw(); + localView.DetachRecorder(); + // deliberately falls through into default case + + default: + operatingPhase = 0; + break; + } + Check_Fpu(); +} + +void + ThreatIndicator::Select() +{ + Test_Tell("ThreatIndicator::Select\n"); + Check(this); + + Point3D + viewing_position; + + Entity + *viewing_entity = renderer->GetLinkedEntity(); + Check(viewing_entity); + + viewing_position = viewing_entity->localOrigin.linearPosition; + + movingEntityList.Clear(); + renderer->GetMovingEntitiesWithinBounds( + &movingEntityList, + viewing_position.x-viewRadius, -32768.0, viewing_position.z-viewRadius, + viewing_position.x+viewRadius, 32768.0, viewing_position.z+viewRadius + ); + Check_Fpu(); +} + +void + ThreatIndicator::Draw() +{ + Test_Tell("ThreatIndicator::Draw\n"); + Check(this); + + Entity + *entity, + *viewing_entity = renderer->GetLinkedEntity(); + Check(viewing_entity); + + YawPitchRoll + currentHeading; + + ChainIteratorOf + i(movingEntityList.GetInstanceList()); + + Vector3D + my_velocity = ((Mover *)viewing_entity)->worldLinearVelocity, + my_position = viewing_entity->localOrigin.linearPosition, + relative_position, + relative_velocity, + unit_position; + + Scalar + // HACK - calculate delta_radius at initialization instead! + delta_radius = innerRadius - outerRadius, + speed_factor, + distance, + distance_factor, + dot_product, + threat_yaw, + threat_assessment; + + int + color; + + //------------------------------------------------------- + // Get player (for team ID if martian football) + //------------------------------------------------------- + RPPlayer + *player = (RPPlayer *) viewing_entity->GetPlayerLink(); + Check(player); +# if DEBUG_LEVEL == 0 + if (player == NULL) + { + DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush; + DEBUG_STREAM << "player = NULL!\n" << std::flush; + return; + } +# endif + //------------------------------------------------------- + // Get current heading + //------------------------------------------------------- + currentHeading = viewing_entity->localOrigin.angularPosition; + + //------------------------------------------------------- + // Attempt to display all entities + //------------------------------------------------------- + while ((entity=i.ReadAndNext()) != NULL) + { + Check(entity); +# if DEBUG_LEVEL == 0 + if (entity == NULL) + { + DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush; + DEBUG_STREAM << "entity = NULL!\n" << std::flush; + break; + } +# endif + + //------------------------------------------------------- + // Make sure it's a VTV + //------------------------------------------------------- + if (! entity->IsDerivedFrom(*VTV::GetClassDerivations())) + { + continue; + } + + //------------------------------------------------------- + // Show all VTV's except us + //------------------------------------------------------- + if (entity != viewing_entity) + { + //----------------------------------------------------------- + // Generate relative position + //----------------------------------------------------------- + relative_position.Subtract( + entity->localOrigin.linearPosition, + viewing_entity->localOrigin.linearPosition + ); + //----------------------------------------------------------- + // Generate distance, discard if too distant + //----------------------------------------------------------- + distance = relative_position.Length(); + if (distance < viewRadius) + { + //----------------------------------------------------------- + // Generate threat assessment + //----------------------------------------------------------- + threat_assessment = 0.0; + //----------------------------------------- + // Assessment source #1: too close + // (anything too close is dangerous) + //----------------------------------------- +# define CLOSE_THREAT_RADIUS 200.0 + + if (distance <= CLOSE_THREAT_RADIUS) + { + threat_assessment += + (CLOSE_THREAT_RADIUS-distance)/CLOSE_THREAT_RADIUS; + } + //----------------------------------------- + // Assessment source #1: closing with us + // (anything closing with us is dangerous) + //----------------------------------------- + //-------------------------------- + // Normalize the position, but + // make sure that we handle a + // zero-length vector correctly. + //-------------------------------- + if (Small_Enough(distance)) + { + unit_position.x = 0.0; + unit_position.y = 0.0; + unit_position.z = -1.0; + } + else + { + unit_position = relative_position; + unit_position /= distance; + Check_Fpu(); + } + + //-------------------------------- + // Generate relative velocity + // (TOWARDS the threat) + //-------------------------------- + relative_velocity.Subtract( + ((Mover *) entity)->worldLinearVelocity, + my_velocity + ); + + dot_product = -(unit_position * relative_velocity); + if (dot_product > 0.0) + { + //---------------------------------- + // Faster is greather threat + // Closer is greater threat + // + // Note that the speed_factor + // is allowed to go above 1.0. + // This allows distant, very + // fast objects to be shown + // as serious threats. + // topClosingVelocity set in creator + //---------------------------------- +# if DEBUG_LEVEL == 0 + if (Small_Enough(topClosingVelocity)) + { + DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush; + DEBUG_STREAM << "topClosingVelocity = " << topClosingVelocity << "\n" << std::flush; + } +# endif + Verify(!Small_Enough(topClosingVelocity)); + speed_factor = dot_product/topClosingVelocity; + Check_Fpu(); + +# if DEBUG_LEVEL == 0 + if (Small_Enough(viewRadius)) + { + DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush; + DEBUG_STREAM << "viewRadius = " << viewRadius << "\n" << std::flush; + } +# endif + Verify(!Small_Enough(viewRadius)); + distance_factor = 1.0 - (distance/viewRadius); + Check_Fpu(); + + threat_assessment += + distance_factor * speed_factor; + } + + //----------------------------------------------------------- + // Display only if assessment > 0 + //----------------------------------------------------------- + if (threat_assessment > 0.0) + { + //----------------------------------------------------------- + // Draw the threat indicator + //----------------------------------------------------------- + threat_yaw = generateRelativeYaw( + currentHeading.yaw.angle, + relative_position + ); + + SinCosPair + sc_pair; + sc_pair = -threat_yaw; + // HACK - I don't know why the (-) is needed, but it is. + // cpb 8-21-95 + Check_Fpu(); + + if (threat_assessment > 1.0) + { + threat_assessment = 1.0; + } + Scalar + show_radius = outerRadius+(delta_radius*threat_assessment), + + orthogonal_x = sc_pair.cosine * 3.0, + orthogonal_y = -sc_pair.sine * 3.0, + + threat_outer_x = sc_pair.sine * -outerRadius, + threat_outer_y = sc_pair.cosine * -outerRadius, + + threat_inner_x = sc_pair.sine * -show_radius, + threat_inner_y = sc_pair.cosine * -show_radius; + Check_Fpu(); + + if (player->playerType == RPPlayer::GeneralPlayerType) + { + color = otherColor; // no friends in death race! + } + else + { + RPPlayer + *other_player = (RPPlayer *) entity->GetPlayerLink(); + + Check(other_player); +# if DEBUG_LEVEL == 0 + if (other_player == NULL) + { + DEBUG_STREAM << "ThreatIndicator has been SABOTAGED!\n" << std::flush; + DEBUG_STREAM << "other_player = NULL!\n" << std::flush; + break; + } +# endif + + if (other_player->teamID == player->teamID) + { + color = teamColor; + } + else + { + color = otherColor; + } + } + localView.SetColor(color); + + localView.MoveToAbsolute( + (int) (threat_outer_x + orthogonal_x + .5), + (int) (threat_outer_y + orthogonal_y + .5) + ); + localView.DrawLineToAbsolute( + (int) (threat_inner_x + .5), + (int) (threat_inner_y + .5) + ); + localView.DrawLineToAbsolute( + (int) (threat_outer_x - orthogonal_x + .5), + (int) (threat_outer_y - orthogonal_y + .5) + ); + } + } + } + } + Check_Fpu(); +} + +//***************************************************************************** +// NavName +//***************************************************************************** +//---------------------------------------------------------- +// A vector between each pair of objects is created, +// normalized, and then weighted according to the INVERSE +// of the vector length. This will cause closer pairs +// of objects to generate larger "repelling" vectors, and +// farther pairs of objects to generate smaller " repelling" +// vectors. +// +// These 'repelling" vectors are then summed for each object. +// The summed vectors then tend to point AWAY from +// 'nearer' objects. These summed vectors are +// again normalized and multiplied by a fixed distance to +// generate the center position for a name bitmap. +//---------------------------------------------------------- + +void + NavName::ExtractFromEntity(Entity *entity, AffineMatrix &worldToView) +{ + Check(this); + Check(entity); + + Player + *player; + //------------------------------------- + // Get pointer to bitmap + //------------------------------------- + player = entity->playerLink; + Check(application); + Mission *current_mission = application->GetCurrentMission(); + Check(current_mission); + + if (player == NULL) + { + nameBitmap = NULL; + } + else + { + nameBitmap = + current_mission->GetSmallNameBitmap(player->playerBitmapIndex); + Check(nameBitmap); + } + //------------------------------------- + // Generate screen position + //------------------------------------- + center.Multiply( + entity->localOrigin.linearPosition, + worldToView + ); + //------------------------------------- + // Get color + //------------------------------------- + color = determineEntityColor(entity); + //------------------------------------- + // Clear direction vector + //------------------------------------- + direction.x = 0.0; + direction.y = 0.0; + direction.z = 0.0; +} + +void + NavName::CalculatePositions(NavName *array, int count) +{ + Check_Pointer(array); + + int + i; + NavName + *this_nav_name; + Vector3D + delta; +#if 0 // QUICK PATCH TO REMOVE "FLOATING" NAMES + int + i; + NavName + *that_nav_name; + Scalar + distance; +#endif + //---------------------------------------------------------- + // Build NavName weighted direction vectors + //---------------------------------------------------------- + for( + i=0, this_nav_name=array; + icenter, that_nav_name->center); + + distance = delta.Length(); + //------------------------------------- + // Normalize the delta, and + // multiply by inverse distance + // (i.e., divide by distance squared) + //------------------------------------- + distance *= distance; + + if (!Small_Enough(distance)) + { + delta /= distance; + } + //------------------------------------- + // Sum the vectors for each navName + //------------------------------------- + this_nav_name->direction += delta; + that_nav_name->direction -= delta; + } +#else + this_nav_name->direction.x = -1.0; + this_nav_name->direction.y = 0.0; + this_nav_name->direction.z = 0.0; +#endif + } +#if 0 // QUICK PATCH TO REMOVE "FLOATING" NAMES + //---------------------------------------------------------- + // Normalize the directions + //---------------------------------------------------------- + for( + i=0, this_nav_name=array; + idirection.y = 0.0; // force to xz plane + distance = this_nav_name->direction.Length(); + + if (Small_Enough(distance)) + { + this_nav_name->direction.x = -1.0; + this_nav_name->direction.z = 0.0; + } + else + { + this_nav_name->direction /= distance; + } + } +#endif +} + +void + NavName::Draw(GraphicsView *graphics_view, Scalar radius_multiplier) +{ + Check(this); + Check(graphics_view); + + if (nameBitmap != NULL) + { + //---------------------------------------- + // Set 'radius' + //---------------------------------------- + direction *= (nameBitmap->Data.Size.x >> 1) * radius_multiplier; + //---------------------------------------- + // Change from screen to world coordinates + //---------------------------------------- + direction.y = -direction.z; + center.y = -center.z; + //---------------------------------------- + // Center the bitmap + //---------------------------------------- + direction.x -= nameBitmap->Data.Size.x >> 1; + direction.y -= nameBitmap->Data.Size.y >> 1; + //---------------------------------------- + // Finally, draw it! + //---------------------------------------- + graphics_view->MoveToAbsolute( + (int) (center.x + direction.x + .5), + (int) (center.y + direction.y + .5) + ); + + graphics_view->SetColor(color); + graphics_view->DrawBitMap(0, nameBitmap); + } +} + +//***************************************************************************** +// NavDisplay +//***************************************************************************** +MethodDescription + NavDisplay::methodDescription = + { + "nav", + NavDisplay::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // static + { ParameterDescription::typeAttribute, NULL }, // scale + { ParameterDescription::typeAttribute, NULL }, // lin pos + { ParameterDescription::typeAttribute, NULL }, // ang pos + PARAMETER_DESCRIPTION_END + } + }; + +Logical + NavDisplay::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer *gauge_renderer + ) +{ + Test_Tell("NavDisplay::Make\n"); + Check(gauge_renderer); + + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeColor); // bg + parameterList[4].CheckIt(ParameterDescription::typeColor); // bg + parameterList[5].CheckIt(ParameterDescription::typeAttribute); // scale + parameterList[6].CheckIt(ParameterDescription::typeAttribute); // lin pos + parameterList[7].CheckIt(ParameterDescription::typeAttribute); // ang pos +# endif + +# if DEBUG_LEVEL > 0 + NavDisplay + *nav_display = +# endif + new NavDisplay( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // owner_ID + display_port_index, // graphics_port_number + position.x, + position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.color, // bg + parameterList[4].data.color, // static objects + (Scalar *) parameterList[5].data.attributePointer, + (Point3D **) parameterList[6].data.attributePointer, + (Quaternion **) parameterList[7].data.attributePointer, + False + + // HACK!!!! The casts above are VERY dangerous! + ); + + Register_Object(nav_display); + + Test_Tell("NavDisplay::Make OK\n"); + Check_Fpu(); + return True; +} + +NavDisplay::NavDisplay( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int left, int bottom, + int right, int top, + int bg_color, + int static_color, + Scalar *scale_value_pointer, + Point3D **position_pointer, + Quaternion **angle_pointer, + Logical allow_rock_and_roll, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("NavDisplay::NavDisplay\n"); + Check_Pointer(this); + + // graphics_port may be NULL! + + // + //----------------------------------------------------------- + // Set position of graphicsView within the graphicsPort + // (which also specifies the clipping and origin) + //----------------------------------------------------------- + // + Verify(right > left); + Verify(top > bottom); + localView.SetPositionWithinPort(left, bottom, right, top); + localView.SetOrigin((right-left)>>1, (top-bottom)>>1); + // + //----------------------------------------------------------- + // Initialize internal values + //----------------------------------------------------------- + // + backgroundColor = bg_color; + staticColor = static_color; + + rockAndRoll = allow_rock_and_roll; + + halfWidth = (right-left)>>1; + halfHeight = (top-bottom)>>1; + + // + //----------------------------------------------------------- + // Build connections to values + //----------------------------------------------------------- + // + GaugeConnection + *connection; + + connection = new + GaugeConnectionDirectOf(0, ¤tScale, scale_value_pointer); + Register_Object(connection); + AddConnection(connection); + + connection = new + GaugeConnectionDirectOf( + 0, ¤tPositionPointer, position_pointer); + Register_Object(connection); + AddConnection(connection); + + connection = new + GaugeConnectionDirectOf( + 0, ¤tAngularPointer, angle_pointer); + Register_Object(connection); + AddConnection(connection); + + Check_Fpu(); +} + +NavDisplay::~NavDisplay() +{ + Test_Tell("NavDisplay::~NavDisplay\n"); + Check(this); + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + NavDisplay::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + NavDisplay::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "ThreatIndicator:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + +// std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; +// std::cout << temp << "foregroundColor=" << foregroundColor << "\n"; +// std::cout << temp << "numberOfDigits =" << numberOfDigits << "\n"; + GraphicGauge::ShowInstance(temp); + Check_Fpu(); +} + +void + NavDisplay::BecameActive() +{ + Check(this); + + operatingPhase = 0; +} + +void + NavDisplay::Execute() +{ + Test_Tell("NavDisplay::Execute\n"); + Check(this); + Check(renderer); + + Vector3D + scaling_vector; + Entity + *linked_entity; + LinearMatrix + temp; + + switch(operatingPhase++) + { + case 0: + CalculateBounds(); + break; + + case 1: + SelectStatic(); + break; + + case 2: + SelectMoving(); + break; + + case 3: + temp.BuildIdentity(); + //----------------------------------------------------------- + // Update worldToView transformation + //----------------------------------------------------------- + linked_entity = renderer->GetLinkedEntity(); + //------------------------------------ + // If pointer to position is null, + // use position of linked entity + //------------------------------------ + if (currentPositionPointer == NULL) + { + if (linked_entity != NULL) + { + currentPositionPointer = + &linked_entity->localOrigin.linearPosition; + } + } + //------------------------------------ + // Get inverse transform from viewer + //------------------------------------ + if (currentPositionPointer != NULL) + { + { + Point3D + point; + point = *currentPositionPointer; + temp = point; + } + if (currentAngularPointer != NULL) + { + if (rockAndRoll) + { + Quaternion + quaternion; + quaternion = *currentAngularPointer; + + temp = quaternion; + } + else + { + YawPitchRoll + currentHeading; + currentHeading = *currentAngularPointer; + + SinCosPair + sin_cos_pair; + sin_cos_pair = currentHeading.yaw.angle/2.0; + + Quaternion + quaternion(0.0, sin_cos_pair.sine, 0.0, sin_cos_pair.cosine); + + temp = quaternion; + } + } + } + worldToView.Invert(temp); + //------------------------------------ + // Scale the display + //------------------------------------ + Verify(pixelsPerMeter > 0.0); + scaling_vector.x = pixelsPerMeter; + scaling_vector.y = pixelsPerMeter; + scaling_vector.z = pixelsPerMeter; + + worldToView *= scaling_vector; + // + //----------------------------------------------------------- + // Update display + //----------------------------------------------------------- + // + previousDrawing.Draw(&localView, backgroundColor); + previousDrawing.Clear(); + localView.AttachRecorder(&previousDrawing); + DrawStatic(worldToView); + DrawMoving(worldToView); + DrawNames(worldToView); + localView.DetachRecorder(); + + // deliberately falls through into default case + + default: + operatingPhase = 0; + break; + } + Check_Fpu(); +} + +void + NavDisplay::CalculateBounds() +{ + Test_Tell("NavDisplay::CalculateBounds\n"); + Check(this); + + Test_Tell("currentScale = " << currentScale << "\n"); + + if (currentScale <= 0.0) + { + Fail("NavDisplay::CalculateBounds detected currentScale <= 0.0"); + currentScale = 1.0; + } + + pixelsPerMeter = (halfWidth<<1)/currentScale; + + Test_Tell("pixelsPerMeter = " << pixelsPerMeter << "\n"); + Verify(pixelsPerMeter > 0.0); + + metersPerPixel = 1.0 / pixelsPerMeter; + + //------------------------------------------------------------ + // Derivation of LODIndex: + // + // The LOD level for the gaugeImage is a very arbitrary value + // where 1.0 is the "normal" level of detail, with smaller + // numbers yielding "more" detail and larger numbers yielding + // "less" detail. If the LODIndex becomes greater than the + // largest value in the gaugeImage, the gaugeImage is not drawn. + // + // This code assumes that a "normal" level is N pixels per meter. + // Therefore, + // N pixel | meters + // LODIndex = ------------+---------- + // meter | pixel + //------------------------------------------------------------ + LODIndex = /*1.0* */ metersPerPixel; // N = 1.0 pixels/meter + + Scalar + halfViewWidth(halfWidth/pixelsPerMeter), + halfViewHeight(halfHeight/pixelsPerMeter); + Test_Tell("halfViewWidth = " << halfViewWidth << "\n"); + Test_Tell("halfViewHeight = " << halfViewHeight << "\n"); + + Point3D + viewing_position; + + Entity + *viewing_entity = renderer->GetLinkedEntity(); + Check(viewing_entity); + + viewing_position = viewing_entity->localOrigin.linearPosition; + + xMin = viewing_position.x - halfViewWidth; + xMax = viewing_position.x + halfViewWidth; + + yMin = -32768.0; + yMax = 32768.0; + + zMin = viewing_position.z - halfViewHeight; + zMax = viewing_position.z + halfViewHeight; + + Test_Tell("x= " << xMin << "..." << xMax << "\n"); + Test_Tell("y= " << yMin << "..." << yMax << "\n"); + Test_Tell("z= " << zMin << "..." << zMax << "\n"); + Check_Fpu(); +} + +void + NavDisplay::SelectStatic() +{ + Test_Tell("NavDisplay::SelectStatic\n"); + Check(this); + + staticEntityList.Clear(); + renderer->GetStaticEntitiesWithinBounds( + &staticEntityList, + xMin, yMin, zMin, + xMax, yMax, zMax + ); + Check_Fpu(); +} + +void + NavDisplay::SelectMoving() +{ + Test_Tell("NavDisplay::SelectMoving\n"); + Check(this); + + movingEntityList.Clear(); + renderer->GetMovingEntitiesWithinBounds( + &movingEntityList, + xMin, yMin, zMin, + xMax, yMax, zMax + ); + Check_Fpu(); +} + +void + NavDisplay::DrawStatic(AffineMatrix &worldToView) +{ + Test_Tell("NavDisplay::DrawStatic\n"); + Check(this); + + Entity + *entity; + Point3D + zero, + pos; + AffineMatrix + localToView; + ChainIteratorOf + i(staticEntityList.GetInstanceList()); + + zero.x = 0.0; + zero.y = 0.0; + zero.z = 0.0; + + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + L4GaugeImage + *gauge_image; + + while ((entity=i.ReadAndNext()) != NULL) + { + Check(entity); + + // + //----------------------------------------------------------- + // Draw new image + //----------------------------------------------------------- + // + gauge_image = warehouse-> + gaugeImageBin.GetIfAlreadyExists(entity->GetResourceID()); + if (gauge_image != NULL) + { + Check(gauge_image); + + localToView.Multiply(entity->localToWorld, worldToView); + + gauge_image->Draw( + LODIndex, + metersPerPixel, + &localView, + staticColor, + (AffineMatrix &) localToView + ); + + warehouse->gaugeImageBin.Release(entity->GetResourceID()); + } + } + Check_Fpu(); +} + +void + NavDisplay::DrawMoving(AffineMatrix &worldToView) +{ + Test_Tell("NavDisplay::DrawMoving\n"); + Check(this); + + Entity + *entity; + ChainIteratorOf + i(movingEntityList.GetInstanceList()); + L4GaugeImage + *gauge_image; + AffineMatrix + localToView; + //---------------------------------------------------------- + // Get warehouse + //---------------------------------------------------------- + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + //---------------------------------------------------------- + // Draw moving entities + //---------------------------------------------------------- + while ((entity=i.ReadAndNext()) != NULL) + { + Check(entity); + +// if (entity != renderer->GetLinkedEntity()) + { + // + //----------------------------------------------------------- + // Draw new image + //----------------------------------------------------------- + // + gauge_image = warehouse-> + gaugeImageBin.GetIfAlreadyExists(entity->GetResourceID()); + + if (gauge_image != NULL) + { + Check(gauge_image); + + localToView.Multiply(entity->localToWorld, worldToView); + + gauge_image->Draw( + LODIndex, + metersPerPixel, + &localView, + determineEntityColor(entity), + localToView, + 0 // bounding box color number: 0=no box + ); + + warehouse->gaugeImageBin.Release(entity->GetResourceID()); + } + } + } + Check_Fpu(); +} + +void + NavDisplay::DrawNames(AffineMatrix &worldToView) +{ + Test_Tell("NavDisplay::DrawNames\n"); + Check(this); + + ChainIteratorOf + iterator(movingEntityList.GetInstanceList()); + NavName + *nav_name; + int + i; + Entity + *entity; + + int + count = iterator.GetSize(); + + if (count < 1) + { + return; + } + + if (count > maximumNames) + { + count = maximumNames; + } + //---------------------------------------------------------- + // Build NavName entries + //---------------------------------------------------------- + for( + i=0, nav_name=nameArray; + iExtractFromEntity(entity, worldToView); + } + + //---------------------------------------------------------- + // Generate display positions + //---------------------------------------------------------- + NavName::CalculatePositions(nameArray, count); + + //---------------------------------------------------------- + // Draw names + //---------------------------------------------------------- + for( + i=0, nav_name=nameArray; + iDraw(&localView, 1.0); + } + Check_Fpu(); +} + +//***************************************************************************** +// GPS +//***************************************************************************** +MethodDescription + GPS::methodDescription = + { + "gps", + GPS::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeScalar, NULL }, // LOD index + PARAMETER_DESCRIPTION_END + } + }; + +Logical + GPS::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer *gauge_renderer + ) +{ + Test_Tell("GPS::Make\n"); + Check(gauge_renderer); + + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeScalar); // LOD index +# endif + +# if DEBUG_LEVEL > 0 + GPS + *gps = +# endif + new GPS( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, //unsigned int owner_ID + display_port_index, //int graphics_port_number + position.x, + position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.scalar + ); + + Register_Object(gps); + + Test_Tell("GPS::Make OK\n"); + Check_Fpu(); + return True; +} + +GPS::GPS( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + int right, int top, + Scalar LOD_index, + const char *identification_string +) : + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("GPS::GPS()\n"); + Check_Pointer(this); + + // graphics_port may be NULL! + + width = right-left, + height = top-bottom; + Verify(width > 0); + Verify(height > 0); + + LODIndex = LOD_index; + //----------------------------------------------------------- + // Set position of graphicsView within the graphicsPort + // (which also specifies the clipping and origin) + //----------------------------------------------------------- + localView.SetPositionWithinPort(left, bottom, right, top); + //----------------------------------------------------------- + // Create background pixelmap + //----------------------------------------------------------- + background = new Video8BitBuffered(width, height); + Register_Object(background); + needsStaticUpdate = True; + Check_Fpu(); +} + +GPS::~GPS() +{ + Check(this); + + Unregister_Object(background); + delete background; + background = NULL; + + Check_Fpu(); +} + +Logical + GPS::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + GPS::ShowInstance(char */*indent*/) +{ + Check_Fpu(); +} + +void + GPS::BecameActive() +{ + Check(this); + numberOfMovingEntities = 0; + needsScreenUpdate = True; + Check_Fpu(); +} + +void + GPS::NotifyOfNewInterestingEntity(Entity *entity) +{ + Check(this); + Check(entity); + if (entity->IsDerivedFrom(*Terrain::GetClassDerivations())) + { + needsStaticUpdate = True; + } + Check_Fpu(); +} + +void + GPS::UpdateStaticEntities() +{ + Check(this); + //----------------------------------------------------------- + // Calculate scale + //----------------------------------------------------------- + Scalar + minX, maxX, deltaX, + minY, maxY, + minZ, maxZ, deltaZ, + scaleX, scaleZ; + + //---------------------------------------- + // First, get bounds from staticEntityList + //---------------------------------------- + Check(renderer); + renderer->GetStaticBounds( + &minX, &minY, &minZ, + &maxX, &maxY, &maxZ + ); + //---------------------------------------- + // Calculate X, Z scales + //---------------------------------------- + deltaX = maxX - minX; + if (deltaX < 0) + { + deltaX = - deltaX; + } + if (deltaX != 0) + { + Verify(width > 0); + scaleX = deltaX/((Scalar) width); + } + else + { + scaleX = 1.0; + } + + deltaZ = maxZ - minZ; + if (deltaZ < 0) + { + deltaZ = - deltaZ; + } + if (deltaZ > 0) + { + Verify(height > 0); + scaleZ = deltaZ/((Scalar) height); + } + else + { + scaleZ = 1.0; + } + //---------------------------------------- + // Choose largest scaling value + // (such that entire map fits) + //---------------------------------------- + metersPerPixel = (scaleX > scaleZ)? scaleX : scaleZ; + metersPerPixel *= 1.2; // allow for large objects at edges of map + //---------------------------------------- + // Generate inverse as well + //---------------------------------------- + Verify(!Small_Enough(metersPerPixel)); + pixelsPerMeter = 1.0 / metersPerPixel; + +//DEBUG_STREAM << +// "GPS, dx=" << deltaX << +// ", dz=" << deltaZ << +// ", sx=" << scaleX << +// ", sz=" << scaleZ << +// ", metersPerPixel=" << metersPerPixel << +// ", pixelsPerMeter=" << pixelsPerMeter << +// "\n"; + //---------------------------------------- + // Generate centering offset + // (map is not necessarily symmetrical) + //---------------------------------------- + centeringOffset.x = -(deltaX/2 + minX); + centeringOffset.y = 0.0; + centeringOffset.z = -(deltaZ/2 + minZ); + //----------------------------------------------------------- + // Rebuild background + //----------------------------------------------------------- + Check(background); + L4BytePort + backgroundPort(background, "background", 0); + Check(&backgroundPort); + + GraphicsView + backgroundView(&backgroundPort); + Check(&backgroundView); + + backgroundView.MoveToAbsolute(0, 0); + backgroundView.SetColor(0); + backgroundView.DrawFilledRectangleToAbsolute(width,height); + + backgroundView.SetOrigin(width>>1, height>>1); + + GaugeEntityList + staticEntityList; + renderer->GetStaticEntities(&staticEntityList); + + ChainIteratorOf + i(staticEntityList.GetInstanceList()); + + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + Entity + *entity; + L4GaugeImage + *gauge_image; + + AffineMatrix + worldToView, + localToView; + + Vector3D + scaling_vector; + //------------------------------------ + // Scale the display + //------------------------------------ + + Verify(!Small_Enough(pixelsPerMeter)); + + scaling_vector.x = pixelsPerMeter; + scaling_vector.y = pixelsPerMeter; + scaling_vector.z = pixelsPerMeter; + + worldToView.BuildIdentity(); + worldToView *= centeringOffset; // translation + worldToView *= scaling_vector; + + while ((entity=i.ReadAndNext()) != NULL) + { + Check(entity); + //------------------------------------- + // Draw image + //------------------------------------- + gauge_image = warehouse-> + gaugeImageBin.GetIfAlreadyExists(entity->GetResourceID()); + if (gauge_image != NULL) + { + Check(gauge_image); + + localToView.Multiply(entity->localToWorld, worldToView); + + gauge_image->Draw( + LODIndex, // value set by creator + metersPerPixel, + &backgroundView, + 0, // default color + (AffineMatrix &) localToView + ); + + warehouse->gaugeImageBin.Release(entity->GetResourceID()); + } + } + //----------------------------------------------------------- + // Redraw new background, restart moving entity display + //----------------------------------------------------------- + BecameActive(); + Check_Fpu(); +} + + +void + GPS::Execute() +{ + Check(this); + + GaugeEntityList + movingEntityList; + GPSRecord + *gps_record; + int + size, + i; + + enum + { + my_size=3, + your_size=2 + }; + + //----------------------------------------------------------- + // Recreate background if it has changed + //----------------------------------------------------------- + if (needsStaticUpdate) + { + UpdateStaticEntities(); + needsStaticUpdate = False; + } + //----------------------------------------------------------- + // Redraw background if needed + //----------------------------------------------------------- + if (needsScreenUpdate) + { + Check(background); + Check(background->pixelBuffer); + + localView.MoveToAbsolute(0, 0); + localView.DrawPixelMap8( + True, // opaque + 0, // rotation + background->pixelBuffer + ); + + needsScreenUpdate = False; + } + //----------------------------------------------------------- + // Erase old positions + //----------------------------------------------------------- + for( + i=numberOfMovingEntities, gps_record=previousGPSRecord; + i>0; + --i, ++gps_record + ) + { + size = (gps_record->me)? my_size : your_size ; + + localView.MoveToAbsolute(gps_record->x, gps_record->y); + localView.DrawPixelMap8( + True, // opaque + 0, // rotation + background->pixelBuffer, + gps_record->x, // sx1 + gps_record->y, // sy1 + gps_record->x+size, // sx2 + gps_record->y+size // sy2 + ); + } + //----------------------------------------------------------- + // Get new entity list + //----------------------------------------------------------- + movingEntityList.Clear(); + renderer->GetMovingEntities(&movingEntityList); + //----------------------------------------------------------- + // Build new positions + //----------------------------------------------------------- + gps_record = previousGPSRecord; + numberOfMovingEntities = 0; + { + ChainIteratorOf + iterator(movingEntityList.GetInstanceList()); + Entity + *entity; + RPPlayer + *player; + int + half_width = width >> 1, + half_height = height >> 1; + + while((entity=iterator.ReadAndNext()) != NULL) + { + Check(entity); + //----------------------------------------------------------- + // Only show entities representing players + //----------------------------------------------------------- + player = (RPPlayer *)(entity->GetPlayerLink()); + if (player != NULL) + { + Check(player); + + gps_record->x = (int) + ( + ( + (entity->localOrigin.linearPosition.x+centeringOffset.x) + * pixelsPerMeter + ) + + .5 + half_width + ); + gps_record->y = (int) + ( + ( + -(entity->localOrigin.linearPosition.z+centeringOffset.z) + * pixelsPerMeter + ) + + .5 + half_height + ); + + gps_record->me = (entity == renderer->GetLinkedEntity()); + gps_record->color = determineEntityColor(entity); + + ++gps_record; + ++numberOfMovingEntities; + if (numberOfMovingEntities >= max_moving_entities) + { + break; + } + } + } + } + //----------------------------------------------------------- + // Draw new positions + //----------------------------------------------------------- + for( + i=numberOfMovingEntities, gps_record=previousGPSRecord; + i>0; + --i, ++gps_record + ) + { + if (gps_record->me) + { + size = my_size; + localView.SetColor(gps_record->color + 0xC0); // flashes color + } + else + { + size = your_size; + localView.SetColor(gps_record->color); + } + + localView.MoveToAbsolute(gps_record->x, gps_record->y); + localView.DrawFilledRectangleToRelative(size,size); + } + Check_Fpu(); +} + +//############################################################################ +// Ranking +//############################################################################ + +# define FORCE_CHANNEL_UPDATE -1 + +MethodDescription + Ranking::methodDescription = + { + "ranking", + Ranking::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL }, // mode mask + { ParameterDescription::typeString, NULL }, // font name + { ParameterDescription::typeInteger, NULL }, // spacing + { ParameterDescription::typeColor, NULL }, // score color + { ParameterDescription::typeInteger, NULL }, // options + PARAMETER_DESCRIPTION_END + } + }; + +Logical + Ranking::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeString); // font name + parameterList[3].CheckIt(ParameterDescription::typeInteger); // spacing + parameterList[4].CheckIt(ParameterDescription::typeColor); // color + parameterList[5].CheckIt(ParameterDescription::typeInteger); // options +# endif + + Test_Tell("Ranking::Make\n"); + +# if DEBUG_LEVEL > 0 + Ranking + *ranking = +# endif + new Ranking( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // unsigned int owner_ID + display_port_index, // int graphics_port_number + position.x, position.y, + parameterList[2].data.string, // font name + parameterList[3].data.integer, // vertical spacing + parameterList[4].data.color, // numeric color + parameterList[5].data.integer // options + ); + + Register_Object(ranking); + + //-------------------------------------------------------- + // Make sure the font was properly placed in the warehouse + //-------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + if (warehouse->bitMapBin.Get(parameterList[2].data.string) == NULL) + { + Test_Tell("Ranking::Missing font\n"); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[2].data.string); + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("Ranking::Make OK\n"); + Check_Fpu(); + return True; +} + +Ranking::Ranking( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int top, + const char *font_name, + int new_spacing, + int numeric_color, + int new_options, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("Ranking creator\n" << std::flush); + Check_Pointer(this); + // graphics_port may be NULL! + + spacing = new_spacing; + options = new_options; + x = left; + y = top - 32; + //----------------------------------------------------------- + // Get and lock font bitmap from warehouse + //----------------------------------------------------------- + Check(renderer); + + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + Check_Pointer(font_name); + BitMap + *font = warehouse->bitMapBin.Get(font_name); + + Check(font); + //----------------------------------------------------------- + // Size/offset definitions + //----------------------------------------------------------- +# define width_of_bitmap 128 +# define space_before_score 2 +# define number_of_score_digits 8 +# define space_before_channel 32 +# define space_at_end_of_box 4 + + int + char_width = (font->Data.Size.x/NumericDisplay::totalDigitsPerFont); + int + score_width = char_width * number_of_score_digits; + int + channel_width = char_width; + int + score_offset = width_of_bitmap + space_before_score; + int + channel_offset = score_offset + score_width + space_before_channel; + + //----------------------------------------------------------- + // Calculate box width + //----------------------------------------------------------- + width = width_of_bitmap + space_before_score + + score_width + space_at_end_of_box; + if (options & showIcomOption) + { + width += space_before_channel + channel_width; + } + //----------------------------------------------------------- + // Spawn off sub-instruments + //----------------------------------------------------------- + int + i, + bottom = y+3; + for(i=0; ibitMapBin.Release(font_name); + + Check_Fpu(); +} + +Ranking::~Ranking() +{ + Test_Tell("Ranking destructor\n" << std::flush); + Check(this); + + int + i; + // + //----------------------------------------------------------- + // Delete sub-gauges + //----------------------------------------------------------- + // + for(i=0; iForceUpdate(); + } + } +} + +void + Ranking::Execute() +{ + Test_Tell("Ranking::Execute\n" << std::flush); + Check(this); + + Check(application); + Check(application->GetEntityManager()); + + EntityGroup + *all_players = application->GetEntityManager()->FindGroup("Players"); + + if (all_players != NULL) + { + Check(all_players); + + Player + *player, + *currentArray[maximumDisplayedPlayers]; + int + i, + bottom, + currentRanking; + + Logical + intercomEnabled; + + //------------------------------------------- + // Get 'our' placement & intercom status + //------------------------------------------- + if (linkedEntity == NULL) + { + currentRanking = -1; + intercomEnabled = False; + } + else + { + Check(linkedEntity); + player = linkedEntity->GetPlayerLink(); + Check(player); + currentRanking = player->playerRanking; + + Icom + *intercom = player->GetIntercom(); + Check(intercom); + intercomEnabled = intercom->GetChannel() != Icom::undefinedChannel; + } + + //------------------------------------------- + // Clear the current array + //------------------------------------------- + for(i=0; i + iterator(all_players->groupMembers); + while((player=(Player *) iterator.ReadAndNext()) != NULL) + { + Check(player); + if (player->IsScoringPlayer()) + { + if (player->playerRanking < maximumDisplayedPlayers) + { + Verify(player->playerRanking >= 0); + +// HACK! Safety code for OPT version + if (player->playerRanking >= 0) + { + currentArray[player->playerRanking] = player; + } + } + } + } + //---------------------------------------------------------------------- + // Compare to previousArray, + // draw names if order has changed + //---------------------------------------------------------------------- + bottom = y; + for(i=0; iErase(&localView); + //------------------------------------------- + // Erase channel + //------------------------------------------- + if (channelDisplay[i] != NULL) + { + Check(channelDisplay[i]); + channelDisplay[i]->Erase(&localView); + } + } + else + { + Check(currentArray[i]); + //------------------------------------------- + // Draw name + //------------------------------------------- + Check(application); + Mission *current_mission = application->GetCurrentMission(); + Check(current_mission); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the nameBitmap out of the mission + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + BitMap *name_bitmap = + current_mission-> + GetLargeNameBitmap(currentArray[i]->playerBitmapIndex); + + if ( name_bitmap == NULL ) + { + localView.SetColor(0x00); + localView.DrawFilledRectangleToRelative(128,32); + } + else + { + int + color = 255; + + if (options & useTeamColorOption) + { + Entity + *entity = currentArray[i]->GetPlayerVehicle(); + + if (entity != NULL) + { + color = determineEntityColor(entity); + } + } + localView.SetColor(color); + + localView.DrawBitMapOpaque( + 0x00, // background + 0, // rotation + name_bitmap + ); + } + } + } + } + //---------------------------------------------------------------------- + // Draw scores if changed + //---------------------------------------------------------------------- + for(i=0; iErase(&localView); + } + else + { + //------------------------------------------- + // Get truncated score (no rounding) + //------------------------------------------- + int + integer_score = (int) rp_player->currentScore; + Scalar + new_score = (Scalar) integer_score; + + if (previousScore[i] != new_score) + { + previousScore[i] = new_score; + + Check(numericDisplay[i]); + //------------------------------------------- + // Display scores for general players, or + // only the runners in Martian Football + //------------------------------------------- + switch(rp_player->playerType) + { + case RPPlayer::GeneralPlayerType: + if (i > currentRanking && !(options & showAllScoresOption)) + { + numericDisplay[i]->Erase(&localView); + } + else + { + numericDisplay[i]->Draw(&localView, new_score); + } + break; + + case RPPlayer::RunnerPlayerType: + numericDisplay[i]->Draw(&localView, new_score); + break; + + default: + numericDisplay[i]->Erase(&localView); + break; + } + } + } + } + //---------------------------------------------------------------------- + // Draw channels if changed + //---------------------------------------------------------------------- + if (options & showIcomOption) + { + Player + *this_player; + L4Icom + *this_intercom; + int + new_channel; + + if (! intercomEnabled) + { + if (previousIntercomEnabled == True) + { + //-------------------------------------------- + // We now have no intercom, clear channels + //-------------------------------------------- + for(i=0; iErase(&localView); + previousChannel[i] = Icom::undefinedChannel; + } + } + } + else + { + for(i=0; iErase(&localView); + previousChannel[i] = Icom::undefinedChannel; + } + } + else + { + // HACK - eventually HIDE the channel if not the same team + + //------------------------------------------- + // Get the channel number for the pilot + //------------------------------------------- + Check(currentArray[i]); + this_player = currentArray[i]; + Check(this_player); + this_intercom = (L4Icom *) this_player->GetIntercom(); + Check(this_intercom); + new_channel = + this_intercom->GetChannel() - + this_intercom->GetChannelOffset(); + Verify(new_channel >= 0); + Verify(new_channel < 7); + //------------------------------------------- + // Update if changed + //------------------------------------------- + if (previousChannel[i] != new_channel) + { + previousChannel[i] = new_channel; + + if (new_channel == Icom::undefinedChannel) + { + //------------------------------------------- + // Not on the 'com, clear channel number + //------------------------------------------- + channelDisplay[i]->Erase(&localView); + } + else + { + //------------------------------------------- + // On the 'com, display channel number + // (channels are internally 0..N, add one + // to match labels on display) + //------------------------------------------- + channelDisplay[i]->Draw(&localView, new_channel+1); + } + } + } + } + } + //--------------------------------- + // Update 'previousIntercomEnabled' + //--------------------------------- + previousIntercomEnabled = intercomEnabled; + } + //---------------------------------------------------------------------- + // Draw boxes if changed + //---------------------------------------------------------------------- + if (previousRanking != currentRanking) + { + //--------------------------------- + // Erase old box + //--------------------------------- + if (previousRanking >= 0) + { + if (previousRanking < maximumDisplayedPlayers) + { + localView.SetColor(0x00); + localView.MoveToAbsolute(x,y-(previousRanking*spacing)-1); + localView.DrawRectangleToRelative(width,34); + } + } + //--------------------------------- + // Draw new box + //--------------------------------- + if (currentRanking >= 0) + { + if (currentRanking < maximumDisplayedPlayers) + { + localView.SetColor(255); + localView.MoveToAbsolute(x,y-(currentRanking*spacing)-1); + localView.DrawRectangleToRelative(width,34); + } + } + //--------------------------------- + // Update 'previousRanking' + //--------------------------------- + previousRanking = currentRanking; + } + } + + Check_Fpu(); +} + +//############################################################################ +// ConfigMap +//############################################################################ + +MethodDescription + ConfigMap::methodDescription = + { + "configMap", + ConfigMap::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL },// mode mask + { ParameterDescription::typeString, NULL }, // "unmapped" icon + { ParameterDescription::typeString, NULL }, // "other" icon + { ParameterDescription::typeString, NULL }, // "my" icon + { ParameterDescription::typeString, NULL }, // "both" icon + PARAMETER_DESCRIPTION_END + } + }; + +Logical + ConfigMap::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer * gauge_renderer + ) +{ + ParameterDescription + *parameterList = methodDescription.parameterList; + + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeString); // "unmapped" + parameterList[3].CheckIt(ParameterDescription::typeString); // "other" + parameterList[4].CheckIt(ParameterDescription::typeString); // "my" + parameterList[5].CheckIt(ParameterDescription::typeString); // "both" +# endif + + Test_Tell("ConfigMap::Make\n"); + +# if DEBUG_LEVEL > 0 + ConfigMap + *config_map = +# endif + new ConfigMap( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // unsigned int owner_ID + display_port_index, // int graphics_port_number + position.x, position.y, + parameterList[2].data.string, // "unmapped" icon + parameterList[3].data.string, // "mapped to other" icon + parameterList[4].data.string, // "mapped exclusively to us" icon + parameterList[5].data.string // "mapped to us and others" icon + ); + + Register_Object(config_map); + //---------------------------------------------------------- + // Make sure the icons were properly placed in the warehouse + //---------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + for(int i=2; i<=5; ++i) + { + if (warehouse->pixelMap8Bin.Get(parameterList[i].data.string) == NULL) + { + Test_Tell( + "ConfigMap::Missing icon'" << parameterList[i].data.string << "'\n" + ); + Check_Fpu(); + return False; + } + else + { + warehouse->pixelMap8Bin.Release(parameterList[i].data.string); + } + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("ConfigMap::Make OK\n"); + Check_Fpu(); + return True; +} + +ConfigMap::ConfigMap( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int left, int bottom, + const char *unmapped_icon, + const char *other_icon, + const char *my_icon, + const char *both_icon, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("ConfigMap creator\n" << std::flush); + Check_Pointer(this); + // graphics_port may be NULL! + + //------------------------------------------------- + // Make local copies of image names + //------------------------------------------------- + iconName[0] = nameCopy(unmapped_icon); + iconName[1] = nameCopy(other_icon); + iconName[2] = nameCopy(my_icon); + iconName[3] = nameCopy(both_icon); + //------------------------------------------------- + // Preload images from warehouse + //------------------------------------------------- +# if defined(PRELOAD_ART) + { + int + i; + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + for(i=0; i<4; ++i) + { + warehouse->pixelMap8Bin.Get(iconName[i]); + } + } +# endif + //----------------------------------------------------------- + // Initialize values + //----------------------------------------------------------- +# if DEBUG_LEVEL > 0 + { + int + i; + for(i=0; i<4; ++i) + { + Check_Pointer(iconName[i]); + } + } +# endif + + localView.SetOrigin(left, bottom); + + linkedEntity = NULL; + Check_Fpu(); +} + +ConfigMap::~ConfigMap() +{ + Test_Tell("ConfigMap destructor\n" << std::flush); + Check(this); + //------------------------------------------------- + // Unlock preloaded art + //------------------------------------------------- +# if defined(PRELOAD_ART) + { + int + i; + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + for(i=0; i<4; ++i) + { + warehouse->pixelMap8Bin.Release(iconName[i]); + } + } +# endif + //------------------------------------------------- + // Delete local copies of image names + //------------------------------------------------- + for(int i=0; i<4; ++i) + { + Unregister_Pointer(iconName[i]); + delete[] iconName[i]; + iconName[i] = NULL; + } + + Check_Fpu(); +} + + +Logical + ConfigMap::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + ConfigMap::ShowInstance(char */*indent*/) +{ + Check_Fpu(); +} + +void + ConfigMap::LinkToEntity(Entity *entity) +{ + Test_Tell("ConfigMap::LinkToEntity\n" << std::flush); + Check(this); + + linkedEntity = entity; + Check_Fpu(); +} + +void + ConfigMap::BecameActive() +{ + Check(this); + + int + i; + + for(i=0; i<4; ++i) + { + previousState[i] = -1; + } + Check_Fpu(); +} + +struct ConfigSet +{ + int yOffset; + int buttonNumber; +}; + +void + ConfigMap::Execute() +{ + static ConfigSet + configSet[4] = + { + { 0, LBE4ControlsManager::ButtonJoystickPinky }, + { 58, LBE4ControlsManager::ButtonJoystickThumbLow }, + { 118, LBE4ControlsManager::ButtonJoystickTrigger }, + { 178, LBE4ControlsManager::ButtonJoystickThumbHigh } + }; + + Test_Tell("ConfigMap::Execute\n" << std::flush); + Check(this); + + if (linkedEntity == NULL) + { + Check_Fpu(); + return; + } + + //----------------------------------------------------------- + // Get current preset mode mask + //----------------------------------------------------------- + L4VTVControlsMapper + *mapper = Cast_Object( + L4VTVControlsMapper*, + linkedEntity->GetSubsystem(VTV::ControlsMapperSubsystem) + ); + Check(mapper); + + ModeMask + preset_mode_mask = mapper->GetPresetModeMask(); + //----------------------------------------------------------- + // Get pointer to controls + //----------------------------------------------------------- + Check(application); + LBE4ControlsManager + *controls = (LBE4ControlsManager *) application->GetControlsManager(); + Check(controls); + //----------------------------------------------------------- + // Get warehouse pointer + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + //----------------------------------------------------------- + // Scan controls, searching for mapping changes + //----------------------------------------------------------- + int + i, + state; + + for(i=0; i<4; ++i) + { + if ( + (controls->activeDestination == NULL) + && + (controls->activeMessageID == 0) + ) + { + state = 0; + } + else + { + state = controls -> + buttonGroup[configSet[i].buttonNumber]. + GetMapState( + controls->activeDestination, + controls->activeReceiver, + controls->activeMessageID, + preset_mode_mask + ); + } + + Verify(state >= 0); + Verify(state <= 3); + + if (previousState[i] != state) + { + previousState[i] = state; + //-------------------------------------------------- + // Get, lock icon from warehouse + //-------------------------------------------------- + PixelMap8 + *pixelmap = warehouse->pixelMap8Bin.Get(iconName[state]); + + if (pixelmap != NULL) + { + //-------------------------------------------------- + // Draw it + //-------------------------------------------------- + localView.MoveToAbsolute(0, configSet[i].yOffset); + localView.DrawPixelMap8( + False, // opaque + 0, // rotation + pixelmap + ); + } + //-------------------------------------------------- + // Release icon from warehouse + //-------------------------------------------------- + Check(warehouse); + warehouse->pixelMap8Bin.Release(iconName[i]); + } + } + Check_Fpu(); +} + + +//***************************************************************************** +// MessageBoard +//***************************************************************************** +MethodDescription + MessageBoard::methodDescription = + { + "messageBoard", + MessageBoard::Make, + { + { ParameterDescription::typeRate, NULL }, // rate ID + { ParameterDescription::typeModeMask, NULL },// mode mask + { ParameterDescription::typeVector, NULL }, // size + { ParameterDescription::typeString, NULL }, // font + { ParameterDescription::typeString, NULL }, // message map + { ParameterDescription::typeColor, NULL }, // background + { ParameterDescription::typeColor, NULL }, // background + PARAMETER_DESCRIPTION_END + } + }; + +Logical + MessageBoard::Make( + int display_port_index, + Vector2DOf position, + Entity */*entity*/, + GaugeRenderer *gauge_renderer + ) +{ + Test_Tell("MessageBoard::Make\n"); + Check(gauge_renderer); + + ParameterDescription + *parameterList = methodDescription.parameterList; + +# if DEBUG_LEVEL > 0 + parameterList[0].CheckIt(ParameterDescription::typeRate); // group ID + parameterList[1].CheckIt(ParameterDescription::typeModeMask); // mode mask + parameterList[2].CheckIt(ParameterDescription::typeVector); // size + parameterList[3].CheckIt(ParameterDescription::typeString); // font + parameterList[4].CheckIt(ParameterDescription::typeString); // message map + parameterList[5].CheckIt(ParameterDescription::typeColor); // bg + parameterList[6].CheckIt(ParameterDescription::typeColor); // numeric +# endif + +# if DEBUG_LEVEL > 0 + MessageBoard + *annunciator = +# endif + new MessageBoard( + parameterList[0].data.rate, + parameterList[1].data.modeMask, + (L4GaugeRenderer *) gauge_renderer, + 0, // unsigned int owner_ID + display_port_index, // int graphics_port_number + position.x, position.y, + position.x + parameterList[2].data.vector.x, + position.y + parameterList[2].data.vector.y, + parameterList[3].data.string, // font + parameterList[4].data.string, // message map + parameterList[5].data.color, // bg color + parameterList[6].data.color // numeric color + ); + + Register_Object(annunciator); + //---------------------------------------------------------- + // Make sure the art was properly placed in the warehouse + //---------------------------------------------------------- + Check(gauge_renderer); + L4Warehouse + *warehouse = (L4Warehouse *) gauge_renderer->warehousePointer; + Check(warehouse); + + for(int i=3; i<=4; ++i) + { + if (warehouse->bitMapBin.Get(parameterList[i].data.string) == NULL) + { + Test_Tell( + "MessageBoard::Missing art '" << + parameterList[i].data.string << "'\n" + ); + Check_Fpu(); + return False; + } + else + { + warehouse->bitMapBin.Release(parameterList[i].data.string); + } + } + //-------------------------------------------------------- + // Everything's ok + //-------------------------------------------------------- + Test_Tell("MessageBoard::Make\n"); + Check_Fpu(); + return True; +} + +MessageBoard::MessageBoard( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int left, int bottom, + int right, int top, + const char *font_name, + const char *message_name, + int bg_color, + int numeric_color, + const char *identification_string +): + GraphicGauge( + rate, + mode_mask, + renderer, + owner_ID, + graphics_port_number, + identification_string + ) +{ + Test_Tell("MessageBoard::MessageBoard\n"); + Check_Pointer(this); + + // graphics_port may be NULL! + + Check_Pointer(font_name); + Check_Pointer(message_name); + + //----------------------------------------------------------- + // Make local copy of image name + //----------------------------------------------------------- + messageName = nameCopy(message_name); + Check_Pointer(messageName); + //----------------------------------------------------------- + // Create warehouse pointer + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + //----------------------------------------------------------- + // Preload message bitmap + //----------------------------------------------------------- +# if defined(PRELOAD_ART) + warehouse->bitMapBin.Get(messageName); +# endif + //----------------------------------------------------------- + // Set position of graphicsView within the graphicsPort + // (which also specifies the clipping and origin) + //----------------------------------------------------------- + Verify(right > left); + Verify(top > bottom); + localView.SetPositionWithinPort(left, bottom, right, top); + //----------------------------------------------------------- + // Initialize internal values + //----------------------------------------------------------- + backgroundColor = bg_color; + linkedEntity = NULL; + //-------------------------------- + // Get, lock font from warehouse + //-------------------------------- + BitMap + *font = warehouse->bitMapBin.Get(font_name); + + if (font == NULL) + { + fontHeight = 0; + } + else + { + fontHeight = font->Data.Size.y; + } + //----------------------------------------------------------- + // Create numeric display + //----------------------------------------------------------- + Check(renderer); + Check(renderer->warehousePointer); + numericDisplay = new NumericDisplay( + (L4Warehouse *) renderer->warehousePointer, + 14, 0, // position relative to local origin + font_name, + 8, + NumericDisplay::signedBlankedZerosFormat, + 0, + numeric_color + ); + Register_Object(numericDisplay); + + //----------------------------------------------------------- + // Release font from warehouse + //----------------------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(font_name); + + Check_Fpu(); +} + +MessageBoard::~MessageBoard() +{ + Test_Tell("MessageBoard::~MessageBoard\n"); + Check(this); + //------------------------------------------------- + // Unlock preloaded art + //------------------------------------------------- +# if defined(PRELOAD_ART) + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + warehouse->bitMapBin.Release(messageName); +# endif + //------------------------------------------------- + // Delete local copies of image name + //------------------------------------------------- + Unregister_Pointer(messageName); + delete[] messageName; + messageName = NULL; + //----------------------------------------------------------- + // Delete numeric display + //----------------------------------------------------------- + Unregister_Object(numericDisplay); + delete numericDisplay; + numericDisplay = NULL; + + // base class deletes all connections in Gauge::~Gauge + Check_Fpu(); +} + +Logical + MessageBoard::TestInstance() const +{ + return GraphicGauge::TestInstance(); +} + +void + MessageBoard::ShowInstance(char *indent) +{ + Check(this); + + std::cout << indent << "MessageBoard:\n"; + + char + temp[80]; + + Str_Copy(temp,indent, 80); + Str_Cat(temp,"...", 80); + + std::cout << temp << "backgroundColor=" << backgroundColor << "\n"; + std::cout << temp << "linkedEntity =" << linkedEntity << "\n"; + std::cout << temp << "numericDisplay =" << numericDisplay << "\n"; + GraphicGauge::ShowInstance(temp); + + Str_Cat(temp,"...", 80); + Check(numericDisplay); + numericDisplay->ShowInstance(temp); + + Check_Fpu(); +} + +void + MessageBoard::BecameActive() +{ + Test_Tell("MessageBoard::BecameActive\n" << std::flush); + Check(this); + + previousPlayerPointer = (Player *) deliberatelyBogusPointerValue; + previousMessageType = -2; + previousValue = (Scalar) 2e-22; + + Check_Fpu(); +} + +void + MessageBoard::LinkToEntity(Entity *entity) +{ + Test_Tell("MessageBoard::LinkToEntity\n" << std::flush); + Check(this); + + linkedEntity = entity; + Check_Fpu(); +} + +void + MessageBoard::Execute() +{ + Test_Tell("MessageBoard::Execute\n" << std::flush); + Check(this); + + if (linkedEntity == NULL) + { + return; + } + Check(linkedEntity); + + //-------------------------------------------------- + // Get a pointer to the local player object + // (or else return) + //-------------------------------------------------- + RPPlayer + *owner_player = (RPPlayer *) linkedEntity->GetPlayerLink(); + + if (owner_player == NULL) + { + return; + } + Check(owner_player); + //-------------------------------------------------- + // Get message data + //-------------------------------------------------- + Player + *message_player; + int + message_type; + Scalar + message_value; + + { + RPPlayer__StatusMessage + *message_pointer = (RPPlayer__StatusMessage *) + owner_player->statusMessagePointer; + + if (message_pointer == NULL) + { + message_player = NULL; + message_type = RPPlayer::RPStatusMessage::NoMessage; + message_value = 0.0; + } + else + { + Check_Pointer(message_pointer); + + message_player = message_pointer->playerInvolved; + message_type = message_pointer->messageType; + message_value = message_pointer->damageAmount; + } + } + + //-------------------------------------------------- + // Draw player name + // + // Warning - previousPlayerPointer is deliberately + // set to an illegal value in BecameActive() in order + // to force the next 'if' statement to execute. + // This is safe because we never directly use + // previousPlayerPointer without loading first + // loading it from message_player. + //-------------------------------------------------- + if (previousPlayerPointer != message_player) + { + localView.MoveToAbsolute(0,fontHeight+1); + + if (message_player == NULL) + { + //------------------------------ + // No player, erase area + //------------------------------ + localView.SetColor(backgroundColor); + + // Note: previousPlayerPointer cannot be null 'cuz message_player was + + if (previousPlayerPointer == (Player *) deliberatelyBogusPointerValue) + { + //---------------------------------- + // No previous name, clear rectangle + //---------------------------------- + localView.DrawFilledRectangleToRelative(128,32); + } + else + { + //---------------------------------------- + // Draw previous name in BG color to erase + //---------------------------------------- + Check(previousPlayerPointer); + + localView.DrawBitMap( + 0, // rotation + (application->GetCurrentMission())->GetLargeNameBitmap( + previousPlayerPointer->playerBitmapIndex + ) + ); + } + } + else + { + Check(message_player); + + //------------------------------ + // Get player vehicle color + //------------------------------ + Check(message_player->GetPlayerVehicle()); + localView.SetColor( + determineEntityColor(message_player->GetPlayerVehicle()) + ); + //------------------------------ + // Get Bitmap from Mission + //------------------------------ + Check(application); + Check(application->GetCurrentMission()); + + localView.DrawBitMapOpaque( + backgroundColor, + 0, // rotation + (application->GetCurrentMission())->GetLargeNameBitmap( + message_player->playerBitmapIndex + ) + ); + } + previousPlayerPointer = message_player; + } + //-------------------------------------------------- + // Draw message + //-------------------------------------------------- + if (previousMessageType != message_type) + { + previousMessageType = message_type; + + localView.MoveToAbsolute(0,fontHeight+(1+32)); + + if (previousMessageType < 0) + { + //-------------------------------------------------- + // Whoops, 'no message'. Erase it. + //-------------------------------------------------- + localView.SetColor(backgroundColor); + localView.DrawFilledRectangleToRelative(128,32); + } + else + { + //-------------------------------------------------- + // Choose sub-map from larger image + // + // The messageMap is a bitmap consisting of a + // group of 32 128x32 messages arranged as + // (4 across) by (8 high): + // + // +--------+--------+--------+--------+ + // | 28 | 29 | 30 | 31 | + // +--------+--------+--------+--------+ + // .... + // +--------+--------+--------+--------+ + // | 12 | 13 | 14 | 15 | + // +--------+--------+--------+--------+ + // | 8 | 9 | 10 | 11 | + // +--------+--------+--------+--------+ + // | 4 | 5 | 6 | 7 | + // +--------+--------+--------+--------+ + // | 0 | 1 | 2 | 3 | + // +--------+--------+--------+--------+ + // (origin (0,0) is lower left!) + //-------------------------------------------------- + Verify(previousMessageType < 32); + + int + sx = (previousMessageType & 3) << 7, // times 128 + sy = (previousMessageType >> 2) << 5; // times 32 + + //----------------------------------------------------------- + // Get player vehicle color + //----------------------------------------------------------- + Check(owner_player->GetPlayerVehicle()); + localView.SetColor( + determineEntityColor(owner_player->GetPlayerVehicle()) + ); + //----------------------------------------------------------- + // Get, lock image from warehouse + //----------------------------------------------------------- + Check(renderer); + L4Warehouse + *warehouse = (L4Warehouse *) renderer->warehousePointer; + Check(warehouse); + + BitMap + *message_map = warehouse->bitMapBin.Get(messageName); + //----------------------------------------------------------- + // Draw it + //----------------------------------------------------------- + if (message_map != NULL) + { + Check(message_map); + + localView.DrawBitMapOpaque( + backgroundColor, + 0, // rotation + message_map, + sx, sy, sx+127, sy+31 + ); + } + //----------------------------------------------------------- + // Release image from warehouse + //----------------------------------------------------------- + Check(warehouse); + warehouse->bitMapBin.Release(messageName); + } + } + //-------------------------------------------------- + // Draw numeric value + //-------------------------------------------------- + if (previousValue != message_value) + { + previousValue = message_value; + Check(numericDisplay); + + if ((previousValue > (Scalar) 1) || (previousValue < (Scalar) -1)) + { + numericDisplay->Draw(&localView, previousValue); + } + else + { + numericDisplay->Erase(&localView); + } + } + + Check_Fpu(); +} diff --git a/RP_L4/RPL4GAUG.h b/RP_L4/RPL4GAUG.h new file mode 100644 index 0000000..e4eee11 --- /dev/null +++ b/RP_L4/RPL4GAUG.h @@ -0,0 +1,571 @@ +#pragma once + +#include "..\munga_l4\l4grend.h" +#include "..\munga_l4\l4gauge.h" +#include "..\munga\rotation.h" +#include "..\munga\random.h" +#include "..\munga\point3d.h" + +//######################################################################### +//####################### Various gauge utilities ######################### +//######################################################################### +extern int + determineEntityColor(Entity *entity, Entity *local_entity=NULL); + +//######################################################################### +class Compass : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer *gauge_renderer + ); + + Compass( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int center_x, int center_y, + int radius, + int background_color, + const char *north_map_name, + const char *west_map_name, + const char *south_map_name, + const char *east_map_name, + const char *bug_map_name, + const char *identification_string = "Compass" + ); + + ~Compass(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + Execute(); +protected: + enum + { + northIndex = 0, + eastIndex, + southIndex, + westIndex, + bugIndex, + numberOfItems + }; + + char + *imageName[numberOfItems]; + + Vector2DOf + offset[numberOfItems], + previousPosition; + + int + radius, + backgroundColor; + L4GaugeRenderer + *renderer; + GraphicsViewRecord + previousDrawing; +}; + +class ThreatIndicator : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer *gauge_renderer + ); + + ThreatIndicator( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int center_x, int center_y, + int inner_radius, + int outer_radius, + int bg_color, + int team_color, + int other_color, + Scalar sensing_radius, + const char *identification_string = "ThreatIndicator" + ); + + ~ThreatIndicator(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); // virtual function in 'GaugeBase' + void + Execute(); +protected: + void + Select(); + void + Draw(); + + Scalar + viewRadius, + topClosingVelocity; + + int + innerRadius, + outerRadius, + backgroundColor, + teamColor, + otherColor, + operatingPhase; + + GaugeEntityList + movingEntityList; + + GraphicsViewRecord + previousDrawing; +}; + +class NavDisplay; + +class NavName SIGNATURED // Used exclusively by NavDisplay +{ + friend class NavDisplay; + + NavName() + {} + ~NavName() + {} + + Logical + TestInstance() const + { + return True; + } + +protected: + void + ExtractFromEntity(Entity *entity, AffineMatrix &worldToView); + static void + CalculatePositions(NavName *array, int count); + void + Draw(GraphicsView *graphics_view, Scalar radius_multiplier); + + Point3D + center; + Vector3D + direction; + BitMap + *nameBitmap; + int + color; +}; + +class NavDisplay : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer *gauge_renderer + ); + + NavDisplay( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int left, int bottom, + int right, int top, + int bg_color, + int static_color, + Scalar *scale_value_pointer, + Point3D **position_pointer, + Quaternion **angle_pointer, + Logical allow_rock_and_roll=False, + const char *identification_string = "NavDisplay" + ); + + ~NavDisplay(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); + void + Execute(); + +protected: + void + CalculateBounds(); + void + SelectStatic(); + void + SelectMoving(); + void + DrawStatic(AffineMatrix &worldToView); + void + DrawMoving(AffineMatrix &worldToView); + void + DrawNames(AffineMatrix &worldToView); + + enum + { + maximumNames = 16 + }; + + NavName + nameArray[maximumNames]; + + Scalar + currentScale; + Point3D * + currentPositionPointer; + Quaternion * + currentAngularPointer; + + Scalar + LODIndex, + pixelsPerMeter, + metersPerPixel, + xMin, + yMin, + zMin, + xMax, + yMax, + zMax; + + AffineMatrix + worldToView; + + int + operatingPhase, + backgroundColor, + staticColor, + halfWidth, + halfHeight; + + Logical + rockAndRoll; + + GaugeEntityList + staticEntityList, + movingEntityList; + + GraphicsViewRecord + previousDrawing; +}; + +class GPS : + public GraphicGauge +{ + struct GPSRecord + { + int x, y, color; + Logical me; + }; + +public: + static MethodDescription + methodDescription; + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer *gauge_renderer + ); + + GPS( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int left, int bottom, + int right, int top, + Scalar LOD_index, + const char *identification_string = "GPS" + ); + + ~GPS(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + BecameActive(); // virtual function in 'GaugeBase' + void + NotifyOfNewInterestingEntity(Entity *entity); + void + Execute(); + +protected: + void + UpdateStaticEntities(); + + enum + { + max_moving_entities=32 + }; + + Logical + needsStaticUpdate, + needsScreenUpdate; + Scalar + LODIndex, + metersPerPixel, + pixelsPerMeter; + Point3D + centeringOffset; + int + width, + height, + numberOfMovingEntities; + GPSRecord + previousGPSRecord[max_moving_entities]; + Video8BitBuffered + *background; +}; + +//####################################################################### +// Ranking +//####################################################################### +class Ranking : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + Ranking( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int top, int left, + const char *font_name, + int spacing, + int numeric_color, + int new_options, + const char *identification_string = "Ranking" + ); + + ~Ranking(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + LinkToEntity(Entity *entity); + void + BecameActive(); + void + Execute(); + + enum + { + useTeamColorOption=0x0001, + showAllScoresOption=0x0002, + showIcomOption=0x0004 + }; + +protected: + char + *messageName; + + enum + { + maximumDisplayedPlayers=8 + }; + + Entity + *linkedEntity; + int + previousRanking; + int + x, + y, + options, + spacing, + width; + + Player + *previousArray[maximumDisplayedPlayers]; + Scalar + previousScore[maximumDisplayedPlayers]; + NumericDisplay + *numericDisplay[maximumDisplayedPlayers]; + Logical + previousIntercomEnabled; + int + previousChannel[maximumDisplayedPlayers]; + NumericDisplay + *channelDisplay[maximumDisplayedPlayers]; +}; + +//####################################################################### +// ConfigMap +//####################################################################### +class ConfigMap : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + ConfigMap( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + int top, int bottom, + const char *unmapped_icon, + const char *other_icon, + const char *my_icon, + const char *both_icon, + const char *identification_string = "ConfigMap" + ); + + ~ConfigMap(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + LinkToEntity(Entity *entity); + void + BecameActive(); + void + Execute(); + +protected: + Entity + *linkedEntity; + char + *iconName[4]; + int + previousState[4]; +}; + +//####################################################################### +// MessageBoard +//####################################################################### +class MessageBoard : + public GraphicGauge +{ +public: + static MethodDescription + methodDescription; + + static Logical + Make( + int display_port_index, + Vector2DOf position, + Entity *entity, + GaugeRenderer * gauge_renderer + ); + + MessageBoard( + GaugeRate rate, + ModeMask mode_mask, + L4GaugeRenderer *renderer, + unsigned int owner_ID, + int graphics_port_number, + + int left, int bottom, + int right, int top, + const char *font_name, + const char *message_name, + int bg_color, + int numeric_color, + const char *identification_string = "MessageBoard" + ); + + ~MessageBoard(); + + Logical + TestInstance() const; + void + ShowInstance(char *indent); + void + LinkToEntity(Entity *entity); + void + BecameActive(); + void + Execute(); + +protected: + NumericDisplay + *numericDisplay; + Entity + *linkedEntity; + char + *messageName; + int + backgroundColor, + fontHeight; + enum + { + deliberatelyBogusPointerValue = -1 + }; + Player + *previousPlayerPointer; + int + previousMessageType; + Scalar + previousValue; +}; diff --git a/RP_L4/RPL4GRND.cpp b/RP_L4/RPL4GRND.cpp new file mode 100644 index 0000000..4523939 --- /dev/null +++ b/RP_L4/RPL4GRND.cpp @@ -0,0 +1,270 @@ +#include "rpl4.h" +#pragma hdrstop + +#include "rpl4grnd.h" +#include "..\munga_l4\l4lamp.h" +#include "..\munga\terrain.h" +#include "..\rp\demopack.h" +#include "rpl4gaug.h" +#include "rpl4mssn.h" +#include "..\munga\app.h" +#include + +// #define LOCAL_TEST + +#if defined(LOCAL_TEST) +# define Test_Tell(n) std::cout << n << std::flush +#else +# define Test_Tell(n) +#endif + +// +//############################################################################# +// RPL4MethodDescription list +//############################################################################# +// +//STUBBED: UNKNOWN RB 1/15/07 +extern + MethodDescription + *L4MethodDescription[]; + +MethodDescription + RPL4ChainToPrevious = METHOD_DESCRIPTION_CHAIN(L4MethodDescription); + +MethodDescription + *RPL4MethodDescription[] = + { + &Compass::methodDescription, + &ThreatIndicator::methodDescription, + &NavDisplay::methodDescription, + &GPS::methodDescription, + &Ranking::methodDescription, + &ConfigMap::methodDescription, + &MessageBoard::methodDescription, + &RPL4ChainToPrevious + }; + +// +//############################################################################# +// RPL4GaugeRenderer +//############################################################################# +// +RPL4GaugeRenderer::RPL4GaugeRenderer(bool windowed, int *secondaryIndex, int *aux1Gauge, int *aux2Gauge) +: + L4GaugeRenderer(windowed, secondaryIndex, aux1Gauge, aux2Gauge) +{ + Check_Pointer(this); + + static unsigned char + mask_list[] = + { 0xFF, 0xBF, 0x7F, 0x3F }; + + //---------------------------------------- + // Create lamp manager + //---------------------------------------- + Check(application); + LBE4ControlsManager + *controls_manager = (LBE4ControlsManager*) + (application->GetControlsManager()); + Check(controls_manager); + + lampManager = new L4LampManager(controls_manager); + Register_Object(lampManager); + //---------------------------------------- + // create warehouse + //---------------------------------------- + warehousePointer = new L4Warehouse(); + Register_Object(warehousePointer); + //---------------------------------------- + // Initialize interpreter + //---------------------------------------- + BuildConfigurationFile( + "gauge\\l4gauge.cfg", + RPL4MethodDescription + ); + //---------------------------------------- + // Enable secondary palette flashing + //---------------------------------------- + ((SVGA16 *) graphicsDisplay)->FlashPalette( + SVGA16::SecondaryPalette, + 2.0, // two cycles (8 changes) per second + mask_list + ); + + Check_Fpu(); +} + +// +//############################################################################# +// ~RPL4GaugeRenderer +//############################################################################# +// +RPL4GaugeRenderer::~RPL4GaugeRenderer() +{ + Check(this); + //---------------------------------------- + // Make sure all gauges removed BEFORE + // we destroy the warehouse!! + //---------------------------------------- + Remove(0); + //---------------------------------------- + // destroy warehouse + //---------------------------------------- + Check(warehousePointer); + Unregister_Object(warehousePointer); + delete warehousePointer; + warehousePointer = NULL; + + Check_Fpu(); +} + +// +//############################################################################# +// TestInstance +//############################################################################# +// +Logical + RPL4GaugeRenderer::TestInstance() const +{ + return GaugeRenderer::TestInstance(); +} + +// +//############################################################################# +// NotifyOfNewInterestingEntity +//############################################################################# +// +void + RPL4GaugeRenderer::NotifyOfNewInterestingEntity(Entity *entity) +{ + Test_Tell("RPL4GaugeRenderer::NotifyOfNewInterestingEntity\n"); + Check(this); + Check(entity); + + //------------------------------------------------------ + // If the entity has no gauge representation, discard it + //------------------------------------------------------ + Check(application); + Check(application->GetResourceFile()); + + ResourceDescription + *resource_description = + application->GetResourceFile()->SearchList( + entity->GetResourceID(), + ResourceDescription::GaugeImageStreamResourceType + ); + Test_Tell("resource_description = " << resource_description << "\n"); + + if (resource_description != NULL) + { + // + //--------------------------------------------------------- + // Place object in either moving list or static array + //--------------------------------------------------------- + // + if (entity->IsDerivedFrom(*Mover::GetClassDerivations())) + { + movingEntities.Add(entity); + } + else if (entity->IsDerivedFrom(*Terrain::GetClassDerivations())) + { + staticEntities.Add(entity); + } + } + + //------------------------------------------------------ + // Chain to "ancestor" method + //------------------------------------------------------ + L4GaugeRenderer::NotifyOfNewInterestingEntity(entity); + Check_Fpu(); +} + +// +//############################################################################# +// StartImplementation +//############################################################################# +// +void + RPL4GaugeRenderer::LoadMissionImplementation(Mission *mission) +{ + Check(this); +# if defined (LOCAL_TEST) + Tell("RPL4GaugeRenderer::LoadMissionImplementation()\n"); +# endif + + //------------------------------------------------------ + // Chain to "ancestor" method + //------------------------------------------------------ + L4GaugeRenderer::LoadMissionImplementation(mission); + Check_Fpu(); +} + +// +//############################################################################# +// StopImplementation +//############################################################################# +// +void + RPL4GaugeRenderer::ShutdownImplementation() +{ + Check(this); +# if defined (LOCAL_TEST) + Tell("RPL4GaugeRenderer::ShutdownImplementation()\n"); +# endif + //------------------------------------------------------ + // Chain to "ancestor" method + //------------------------------------------------------ + L4GaugeRenderer::ShutdownImplementation(); + Check_Fpu(); +} + +// +//############################################################################# +// NotifyOfNewUninterestingEntity +//############################################################################# +// +void + RPL4GaugeRenderer::NotifyOfBecomingUninterestingEntity(Entity *entity) +{ + Test_Tell("RPL4GaugeRenderer::NotifyOfBecomingUninterestingEntity\n"); + Check(this); + Check(entity); + //------------------------------------------------------ + // If the entity has no gauge representation, discard it + //------------------------------------------------------ + Check(application); + Check(application->GetResourceFile()); + + ResourceDescription + *resource_description = + application->GetResourceFile()->SearchList( + entity->GetResourceID(), + ResourceDescription::GaugeImageStreamResourceType + ); + Test_Tell("resource_description = " << resource_description << "\n"); + + if (resource_description != NULL) + { + //--------------------------------------------------------- + // Place entity from either moving list or static array + //--------------------------------------------------------- + if (entity->IsDerivedFrom(*Mover::GetClassDerivations())) + { + movingEntities.Remove(entity); + } + else if (entity->IsDerivedFrom(*DemolitionPack::GetClassDerivations())) + { + movingEntities.Remove(entity); + } + else if (entity->IsDerivedFrom(*Terrain::GetClassDerivations())) + { + staticEntities.Remove(entity); + } + } + + //------------------------------------------------------ + // Chain to "ancestor" method + //------------------------------------------------------ + L4GaugeRenderer::NotifyOfBecomingUninterestingEntity(entity); + Check_Fpu(); +} diff --git a/RP_L4/RPL4GRND.h b/RP_L4/RPL4GRND.h new file mode 100644 index 0000000..5633bc4 --- /dev/null +++ b/RP_L4/RPL4GRND.h @@ -0,0 +1,36 @@ +#pragma once + +#include "..\munga_l4\l4grend.h" + +//~~~~~~~~~~~~~~~~~~~~~~~~~~ RPL4GaugeRenderer ~~~~~~~~~~~~~~~~~~~~~~~~~~ + +class RPL4GaugeRenderer : public L4GaugeRenderer +{ +public: + + // + //-------------------------------------------------------------------- + // Construction, Destruction, Testing + //-------------------------------------------------------------------- + // + RPL4GaugeRenderer(bool windowed, int *secondaryIndex, int *aux1Gauge, int *aux2Gauge); + ~RPL4GaugeRenderer(); + + Logical TestInstance() const; + + void NotifyOfNewInterestingEntity(Entity *entity); + void NotifyOfBecomingUninterestingEntity(Entity *entity); + // + //-------------------------------------------------------------------- + // LoadMissionImplementation + // ShutdownImplementation + // SuspendImplementation + // ResumeImplementation + // + // These are virtual functions defined by the Renderer class. + // Derived classes must call these methods. + //-------------------------------------------------------------------- + // + void LoadMissionImplementation(Mission *mission); + void ShutdownImplementation(); +}; diff --git a/RP_L4/RPL4MODE.cpp b/RP_L4/RPL4MODE.cpp new file mode 100644 index 0000000..fad7ee5 --- /dev/null +++ b/RP_L4/RPL4MODE.cpp @@ -0,0 +1,60 @@ +#include "rpl4.h" +#pragma hdrstop + +#include "rpl4mode.h" + +#if defined(DEBUG) +# define Test_Tell(n) DEBUG_STREAM << n +#else +# define Test_Tell(n) +#endif + +struct ModeLookup +{ + const char *name; + ModeMask modeMask; +}; + +static ModeLookup mode_lookup[] = +{ + {"ModeNonConfig", RPL4ModeManager::ModeNonConfig}, + {"ModeConfigReady", RPL4ModeManager::ModeConfigReady}, + {"ModeConfigOn", RPL4ModeManager::ModeConfigOn}, + {"ModePreset1", RPL4ModeManager::ModePreset1}, + {"ModePreset2", RPL4ModeManager::ModePreset2}, + {"ModePreset3", RPL4ModeManager::ModePreset3}, + {"ModePreset4", RPL4ModeManager::ModePreset4}, + {"ModePreset5", RPL4ModeManager::ModePreset5}, + {"ModePreset6", RPL4ModeManager::ModePreset6}, + {"ModeBasic", RPL4ModeManager::ModeBasic}, + {"ModeStandard", RPL4ModeManager::ModeStandard}, + {"ModeIntercom", RPL4ModeManager::ModeIntercom}, + {"ModeConfiguring", RPL4ModeManager::ModeConfiguring}, + { NULL, (ModeMask)0} +}; + +Logical RPL4ModeManager::ModeStringLookup(const char *name, ModeMask *returned_value) +{ + Check(this); + Check_Pointer(name); + Check_Pointer(returned_value); + //---------------------------------------- + // Search table for match + //---------------------------------------- + ModeLookup *lookup; + + for(lookup=mode_lookup; lookup->name!=NULL; ++lookup) + { + if (stricmp(name, lookup->name) == 0) + { + *returned_value = lookup->modeMask; + Check_Fpu(); + return True; + } + } + //---------------------------------------- + // Not found here, check next level down. + //---------------------------------------- + Check_Fpu(); + return ModeManager::ModeStringLookup(name, returned_value); +} diff --git a/RP_L4/RPL4MODE.h b/RP_L4/RPL4MODE.h new file mode 100644 index 0000000..ff06a1a --- /dev/null +++ b/RP_L4/RPL4MODE.h @@ -0,0 +1,76 @@ +#pragma once + +#include "..\munga\mode.h" + +//######################################################################### +//########################## RPL4ControlsManager ########################## +//######################################################################### +class RPL4ModeManager : public ModeManager +{ +public: + enum + { + }; + //------------------------------------------------------------------- + // Construction/destruction/verification + //------------------------------------------------------------------- +public: + RPL4ModeManager(ModeMask initial_mask): + ModeManager(initial_mask) + {} + + //------------------------------------------------------------------- + // Mode control + //------------------------------------------------------------------- + enum + { + ModeNonConfigBit = ModeManager::nextModeBit, + ModeConfigReadyBit, + ModeConfigOnBit, + ModePreset1Bit, + ModePreset2Bit, + ModePreset3Bit, + ModePreset4Bit, + ModePreset5Bit, + ModePreset6Bit, + + ModeBasicBit, + ModeStandardBit, + + ModeIntercomBit + }; + enum + { + ModePreset1 = 1L<GetGaugeRenderer() == NULL) + { + return NULL; + } + else + { + Check(application->GetGaugeRenderer()); + + //------------------------------------------ + // Create the lamp + //------------------------------------------ + L4LampManager + *lamp_manager = (L4LampManager *) application-> + GetGaugeRenderer()->GetLampManager(); + Check(lamp_manager); + + L4Lamp + *lamp = new L4Lamp( + lamp_number, + mode_mask, + lamp_manager + ); + Register_Object(lamp); + + lamp->SetAutomaticOperation(False); + + Check_Fpu(); + return lamp; + } +} + +//----------------------------------------------------------------------- +void + MakeButtonLampEvent( + LBE4ControlsManager *controls, + int button_number, + Receiver *receiver, + Receiver::MessageID message_id, + Plug *dependant, + ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive + ) +{ + Check(controls); + Check(receiver); + Check(dependant); + + controls->buttonGroup[button_number].Add( + mode_mask, + receiver, + message_id, + dependant + ); + controls->MakeLinkedLamp(button_number, mode_mask); +} + +void + MakeButtonLampEventPair( + LBE4ControlsManager *controls, + int button_number1, + int button_number2, + Receiver *receiver, + Receiver::MessageID message_id, + Plug *dependant, + ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive + ) +{ + MakeButtonLampEvent( + controls, + button_number1, + receiver, + message_id, + dependant, + mode_mask + ); + MakeButtonLampEvent( + controls, + button_number2, + receiver, + message_id, + dependant, + mode_mask + ); +} + +//----------------------------------------------------------------------- +void + MakeButtonLampDirect( + LBE4ControlsManager *controls, + int button_number, + ControlsButton *direct_target, + Plug *dependent, + ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive + ) +{ + Check(controls); + + controls->buttonGroup[button_number].Add( + mode_mask, + direct_target, + dependent + ); + controls->MakeLinkedLamp(button_number, mode_mask); +} + +void + MakeButtonLampDirectPair( + LBE4ControlsManager *controls, + int button_number1, + int button_number2, + ControlsButton *direct_target, + Plug *dependent, + ModeMask mode_mask = RPL4ModeManager::ModeAlwaysActive + ) +{ + MakeButtonLampDirect( + controls, + button_number1, + direct_target, + dependent, + mode_mask + ); + MakeButtonLampDirect( + controls, + button_number2, + direct_target, + dependent, + mode_mask + ); +} + +//----------------------------------------------------------------------- +void + CreateDirectSystemMapping( + LBE4ControlsManager *controls, + int button_number, + ControlsButton *direct_target, + Receiver *receiver, + Receiver::MessageID configure_message_id + ) +{ + Check(controls); + Check(receiver); + + //------------------------------------------------- + // When not configuring, press button to activate + //------------------------------------------------- + MakeButtonLampDirect( + controls, + button_number, + direct_target, + receiver, + RPL4ModeManager::ModeNonConfig + ); + //------------------------------------------------- + // When configuring, the same button allows mapping + //------------------------------------------------- + MakeButtonLampEvent( + controls, + button_number, + receiver, + configure_message_id, + receiver, + RPL4ModeManager::ModeConfigReady + ); +} + +void + CreateDirectSystemMappingPair( + LBE4ControlsManager *controls, + int button_number1, + int button_number2, + ControlsButton *direct_target, + Receiver *receiver, + Receiver::MessageID configure_message_id + ) +{ + Check(controls); + Check(receiver); + + CreateDirectSystemMapping( + controls, + button_number1, + direct_target, + receiver, + configure_message_id + ); + CreateDirectSystemMapping( + controls, + button_number2, + direct_target, + receiver, + configure_message_id + ); +} + +//----------------------------------------------------------------------- +void + CreateEventSystemMapping( + LBE4ControlsManager *controls, + int button_number, + Receiver *receiver, + Receiver::MessageID active_message_id, + Receiver::MessageID configure_message_id + ) +{ + Check(controls); + Check(receiver); + + //------------------------------------------------- + // When not configuring, press button to activate + //------------------------------------------------- + MakeButtonLampEvent( + controls, + button_number, + receiver, + active_message_id, + receiver, + RPL4ModeManager::ModeNonConfig + ); + //------------------------------------------------- + // When configuring, the same button allows mapping + //------------------------------------------------- + MakeButtonLampEvent( + controls, + button_number, + receiver, + configure_message_id, + receiver, + RPL4ModeManager::ModeConfigReady + ); +} + +void + CreateEventSystemMappingPair( + LBE4ControlsManager *controls, + int button_number1, + int button_number2, + Receiver *receiver, + Receiver::MessageID active_message_id, + Receiver::MessageID configure_message_id + ) +{ + CreateEventSystemMapping( + controls, + button_number1, + receiver, + active_message_id, + configure_message_id + ); + CreateEventSystemMapping( + controls, + button_number2, + receiver, + active_message_id, + configure_message_id + ); +} + + +//############################################################################# +//########################### L4VTVControlsMapper ############################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +L4VTVControlsMapper::SharedData + L4VTVControlsMapper::DefaultData( + L4VTVControlsMapper::GetClassDerivations(), + L4VTVControlsMapper::GetMessageHandlers(), + L4VTVControlsMapper::GetAttributeIndex(), + L4VTVControlsMapper::StateCount + ); + +Derivation* L4VTVControlsMapper::GetClassDerivations() +{ static Derivation classDerivations(VTVControlsMapper::GetClassDerivations(), "L4VTVControlsMapper"); + return &classDerivations; +} + + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + L4VTVControlsMapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(L4VTVControlsMapper, Keypress) +}; + +Receiver::MessageHandlerSet& L4VTVControlsMapper::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(L4VTVControlsMapper::MessageHandlerEntries), L4VTVControlsMapper::MessageHandlerEntries, VTVControlsMapper::GetMessageHandlers()); + return messageHandlers; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4VTVControlsMapper::KeypressMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + + Check(message); + + switch (message->dataContents) + { + case PCK_F11: + { + Check(application); + + GaugeRenderer + *renderer = application->GetGaugeRenderer(); + if (renderer != NULL) + { + Check(renderer); + renderer->ProfileReport(); + } + } + break; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4VTVControlsMapper::SetControlsMode(int new_mode) +{ + Check(this); + + //------------------------------------------- + // Get mode manager + //------------------------------------------- + Check(application); + + RPL4ModeManager + *mode_manager = Cast_Object( + RPL4ModeManager*, + application->GetModeManager() + ); + Check(mode_manager); + + int + previous_mode = controlMode; + //------------------------------------------- + // Change modes + //------------------------------------------- + switch (new_mode) + { + case BasicMode: + //-------------------------------------- + // If we aren't already in basic mode, + // switch us there + //-------------------------------------- + if (controlMode != BasicMode) + { + controlMode = BasicMode; + mode_manager->AddModeMask(RPL4ModeManager::ModeBasic); + mode_manager->RemoveModeMask(RPL4ModeManager::ModeStandard); + //---------------------------------------- + // Ensure configuring is turned off + //---------------------------------------- + if (GetSimulationState() == ConfigurationState) + { + mode_manager->AddModeMask(RPL4ModeManager::ModeNonConfig); + mode_manager->RemoveModeMask(RPL4ModeManager::ModeConfiguring); + + SetSimulationState(DefaultState); + } + } + break; + + case StandardMode: + //--------------------------------------- + // If we aren't already in standard mode, + // switch us there + //--------------------------------------- + if (controlMode != StandardMode) + { + controlMode = StandardMode; + mode_manager->AddModeMask(RPL4ModeManager::ModeStandard); + mode_manager->RemoveModeMask(RPL4ModeManager::ModeBasic); + } + break; + + case VeteranMode: + //--------------------------------------- + // If we aren't already in veteran mode, + // switch us there + //--------------------------------------- + if (controlMode != VeteranMode) + { + controlMode = VeteranMode; + mode_manager->AddModeMask(RPL4ModeManager::ModeStandard); + mode_manager->RemoveModeMask(RPL4ModeManager::ModeBasic); + } + break; + + case MasterMode: + //--------------------------------------- + // If we aren't already in master mode, + // switch us there + //--------------------------------------- + if (controlMode != MasterMode) + { + controlMode = MasterMode; + mode_manager->AddModeMask(RPL4ModeManager::ModeStandard); + mode_manager->RemoveModeMask(RPL4ModeManager::ModeBasic); + } + break; + + default: + Tell( + "L4VTVControlsMapper::SetControlsMode(" << new_mode << + ")\n" + ); + Fail("out of range"); + break; + } + //---------------------------------------- + // Notify of mode change + //---------------------------------------- + if (previous_mode != controlMode) + { + L4VTVControlsMapper::NotifyOfControlModeChange(controlMode); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4VTVControlsMapper::SetConfigurationMode(Logical new_state) +{ + Check(this); + + //------------------------------------------- + // Call ancestral method + //------------------------------------------- + VTVControlsMapper::SetConfigurationState(new_state); + + //------------------------------------------- + // Get mode manager + //------------------------------------------- + Check(application); + + RPL4ModeManager + *mode_manager = Cast_Object( + RPL4ModeManager*, + application->GetModeManager() + ); + Check(mode_manager); + + //------------------------------------------- + // Modify mode + //------------------------------------------- + if (GetSimulationState() == ConfigurationState) + { + mode_manager->RemoveModeMask(RPL4ModeManager::ModeAllNonConfig); + // Note: this removes ALL presets as well + + mode_manager->AddModeMask(RPL4ModeManager::ModeConfigReady); + } + else + { + mode_manager->RemoveModeMask(RPL4ModeManager::ModeConfigReady); + + mode_manager->AddModeMask(RPL4ModeManager::ModeNonConfig); + mode_manager->AddModeMask(previousPresetModeMask); + } + Check_Fpu(); +} + + +//############################################################################# +// Platform-specific updates +// +void + L4VTVControlsMapper::NotifyOfControlModeChange(int new_mode) +{ + Check(this); + // The gauges are controlled directly by modes, so we do nothing here. + + //----------------------------------- + // Invoke ancestral method + //----------------------------------- + VTVControlsMapper::NotifyOfControlModeChange(new_mode); + + Check_Fpu(); +} + +void + L4VTVControlsMapper::NotifyOfConfigurationModeChange(Logical new_state) +{ + Check(this); + // The gauges are controlled directly by modes, so we do nothing here. + + //----------------------------------- + // Invoke ancestral method + //----------------------------------- + VTVControlsMapper::NotifyOfConfigurationModeChange(new_state); + + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4VTVControlsMapper::L4VTVControlsMapper( + VTV *player_vehicle, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data +): + VTVControlsMapper( + player_vehicle, + subsystem_ID, + subsystem_resource, + shared_data + ) +{ + Check(application); + + RPL4ModeManager + *mode_manager = Cast_Object( + RPL4ModeManager*, + application->GetModeManager() + ); + Check(mode_manager); + //------------------------------------------ + // Initialize presets + //------------------------------------------ + previousPresetModeMask = RPL4ModeManager::ModePreset1; + previousPresetNumber = 0; + + mode_manager->AddModeMask(previousPresetModeMask); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +L4VTVControlsMapper::~L4VTVControlsMapper() +{ + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + L4VTVControlsMapper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4VTVControlsMapper::CreateTemporaryEventMappings( + Receiver *receiver, + Receiver::MessageID config_message_id + ) +{ + Check(this); + Check(receiver); + + Check(application); + LBE4ControlsManager + *controls_mgr = Cast_Object( + LBE4ControlsManager *, + application->GetControlsManager() + ); + Check(controls_mgr); + + //------------------------------------------------ + // Create temporary mappings for configuration + //------------------------------------------------ + for( + int i=LBE4ControlsManager::FirstMappableButton; + i<=LBE4ControlsManager::LastMappableButton; + ++i + ) + { + //--------------------------------- + // Skip past hat switches + //--------------------------------- + if (i == LBE4ControlsManager::ButtonJoystickHatDown) + { + i = LBE4ControlsManager::ButtonJoystickPinky; + } + + controls_mgr->buttonGroup[i].Add( + RPL4ModeManager::ModeConfigReady, + receiver, + config_message_id, + receiver + ); + } + Check_Fpu(); +} + +void + L4VTVControlsMapper::RemoveTemporaryEventMappings() +{ + Check(this); + + Check(application); + LBE4ControlsManager + *controls_mgr = Cast_Object( + LBE4ControlsManager *, + application->GetControlsManager() + ); + Check(controls_mgr); + + //------------------------------------------------ + // Remove temporary mappings + //------------------------------------------------ + for( + int i=LBE4ControlsManager::FirstMappableButton; + i<=LBE4ControlsManager::LastMappableButton; + ++i + ) + { + //--------------------------------- + // Skip past hat switches + //--------------------------------- + if (i == LBE4ControlsManager::ButtonJoystickHatDown) + { + i = LBE4ControlsManager::ButtonJoystickPinky; + } + + controls_mgr->buttonGroup[i].Remove(RPL4ModeManager::ModeConfigReady); + } + Check_Fpu(); +} + +void + L4VTVControlsMapper::AddOrErase( + unsigned int /*button_ID*/, + Receiver */*target*/, + Receiver::MessageID /*message_ID*/ + ) +{ + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + L4VTVControlsMapper::AddOrErase( + unsigned int /*button_ID*/, + ControlsButton */*destination*/ + ) +{ + Check_Fpu(); +} + +void + L4VTVControlsMapper::PresetEnable(int preset_number) +{ + Check(this); + + static ModeMask + mode_table[presetCount] = + { + RPL4ModeManager::ModePreset1, + RPL4ModeManager::ModePreset2, + RPL4ModeManager::ModePreset3, + RPL4ModeManager::ModePreset4, + RPL4ModeManager::ModePreset5, + RPL4ModeManager::ModePreset6 + }; + + mustMatch = preset_number; // HACK - for backward watcher compatibility + + if (preset_number != previousPresetNumber) + { + Check(application); + + RPL4ModeManager + *mode_manager = Cast_Object( + RPL4ModeManager*, + application->GetModeManager() + ); + Check(mode_manager); + + //----------------------------------- + // Disable the old presets + //----------------------------------- + mode_manager->RemoveModeMask(previousPresetModeMask); + //----------------------------------- + // Enable the new presets + //----------------------------------- + if (preset_number >= 0) + { + Verify(preset_number < presetCount); + + previousPresetModeMask = mode_table[preset_number]; + mode_manager->AddModeMask(previousPresetModeMask); + } + //----------------------------------- + // Save the new preset number + //----------------------------------- + previousPresetNumber = preset_number; + } + + Check_Fpu(); +} + +//############################################################################# +//########################### ThrustmasterMapper ############################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +VTVThrustmasterMapper::SharedData + VTVThrustmasterMapper::DefaultData( + VTVThrustmasterMapper::GetClassDerivations(), + VTVThrustmasterMapper::MessageHandlers, + VTVThrustmasterMapper::GetAttributeIndex(), + VTVThrustmasterMapper::StateCount + ); + +Derivation* VTVThrustmasterMapper::GetClassDerivations() +{ static Derivation classDerivations(L4VTVControlsMapper::GetClassDerivations(), "VTVThrustmasterMapper"); + return &classDerivations; +} + + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + VTVThrustmasterMapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(VTVThrustmasterMapper, Keypress) +}; + +Receiver::MessageHandlerSet + VTVThrustmasterMapper::MessageHandlers( + ELEMENTS(VTVThrustmasterMapper::MessageHandlerEntries), + VTVThrustmasterMapper::MessageHandlerEntries, + L4VTVControlsMapper::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVThrustmasterMapper::KeypressMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + LBE4ControlsManager + *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + Check(controls); + + switch (message->dataContents) + { + //------------------------------------------------------- + // Joystick + //------------------------------------------------------- + case PCK_F1: + Tell("Aligning Joystick...\n"); + controls->BeginAlignJoystick(); + GetEntity()->SetSimulationState(VTV::StasisState); + break; + case PCK_F2: + Tell("Joystick Aligned...\n"); + controls->EndAlignJoystick(); + GetEntity()->SetSimulationState(VTV::DefaultState); + break; + + case PCK_F12: + //------------------------------------------------------- + // Exit + //------------------------------------------------------- + Check(application); + if ( + application->GetApplicationState() != Application::EndingMission + && application->GetApplicationState() != Application::StoppingMission + ) + { + DEBUG_STREAM << "Keystroke invoking mission stop...\n" << std::flush; + Exit_Code = 1; + Application::StopMissionMessage message(Exit_Code); + application->Dispatch(&message); + } + break; + + //------------------------------------------------------- + // Control eyepoint views + //------------------------------------------------------- + case PCK_UP: // look forward + lookLeft = -1; + lookRight = -1; + lookBehind = -1; + lookUp = -1; + break; + case PCK_LEFT: // look left + lookLeft = 1; + lookRight = -1; + lookBehind = -1; + lookUp = -1; + break; + case PCK_RIGHT: // look right + lookLeft = -1; + lookRight = 1; + lookBehind = -1; + lookUp = -1; + break; + case PCK_DOWN: // look behind + lookLeft = -1; + lookRight = -1; + lookBehind = 1; + lookUp = -1; + break; + case PCK_CTL_UP: // look up + lookLeft = -1; + lookRight = -1; + lookBehind = -1; + lookUp = 1; + break; + + //------------------------------------------------------- + // Set driving modes + //------------------------------------------------------- + case 'b': + case 'B': SetControlsMode(BasicMode); break; + + case 's': + case 'S': SetControlsMode(StandardMode); break; + + case 'v': + case 'V': SetControlsMode(VeteranMode); break; + + case 'm': + case 'M': SetControlsMode(MasterMode); break; + + //------------------------------------------------------- + // Configuration stuff + //------------------------------------------------------- + case 'c': + case 'C': + //------------------------------ + // Not allowed in 'basic' mode + //------------------------------ + if (controlMode != BasicMode) + { + static Logical + config_state = False; + //---------------------------- + // Invert configuration state + //---------------------------- + config_state ^= True; + //---------------------------- + // Send message to base class + //---------------------------- + SetConfigurationMode(config_state); + } + break; + + //------------------------------------------------------- + // Map scale stuff + //------------------------------------------------------- + case '<': + case ',': + { + ReceiverDataMessageOf + config_msg( + VTV::ZoomInMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + GetEntity()->Dispatch(&config_msg); + break; + } + + case '>': + case '.': + { + ReceiverDataMessageOf + config_msg( + VTV::ZoomOutMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + GetEntity()->Dispatch(&config_msg); + break; + } + + case 'h': + case 'H': + //------------------------------------------------------- + // Horn blast + //------------------------------------------------------- + { + static ControlsButton horn_state=1; + ReceiverDataMessageOf + config_msg( + ActivateHornMessageID, + sizeof(ReceiverDataMessageOf), + horn_state + ); + Dispatch(&config_msg); + horn_state = -horn_state; + break; + } + + case 'z': + case 'Z': + //--------------------------------------------------------- + // Chute + //--------------------------------------------------------- + { + ReceiverDataMessageOf + config_msg( + Chute::ActivateMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + for (int i=0; i < GetEntity()->GetSubsystemCount(); i++) + { + Subsystem *sub = GetEntity()->GetSubsystem(i); + if (sub && sub->GetClassID() == VTV::ChuteClassID) + { + sub->Dispatch(&config_msg); + break; + } + } + break; + } + + case 'w': + case 'W': + //--------------------------------------------------------- + // Booster + //--------------------------------------------------------- + { + ReceiverDataMessageOf + config_msg( + Booster::ActivateMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + for (int i=0; i < GetEntity()->GetSubsystemCount(); i++) + { + Subsystem *sub = GetEntity()->GetSubsystem(i); + if (sub && sub->GetClassID() == VTV::BoosterClassID) + { + sub->Dispatch(&config_msg); + break; + } + } + break; + } + + case 'd': + case 'D': + //--------------------------------------------------------- + // Demopack + //--------------------------------------------------------- + { + /*for (int i=0; i < GetEntity()->GetSubsystemCount(); i++) + { + Subsystem *sub = GetEntity()->GetSubsystem(i); + if (sub && sub->GetClassID() == VTV::DemolitionPackDropperClassID) + { + ((DemolitionPackDropper*)sub)->Fire(); + break; + } + }*/ + } + + case 'r': + case 'R': + //------------------------------------------------------- + // Toggle reticle + //------------------------------------------------------- + { + ReceiverDataMessageOf + config_msg( + ToggleReticleMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + Dispatch(&config_msg); + break; + } + //------------------------------------------------------- + // Trigger presets + //------------------------------------------------------- + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + PresetEnable(message->dataContents - '1'); + break; + + //------------------------------------------------------- + // Suspend/resume + //------------------------------------------------------- + case '[': + { + Check(application); + + Enumeration + state = application->GetApplicationState(); + + if ( + state != Application::EndingMission && + state != Application::StoppingMission && + state != Application::SuspendingMission + ) + { + DEBUG_STREAM << "Keystroke invoking mission suspend...\n" << std::flush; + Application::SuspendMissionMessage message; + application->Dispatch(&message); + } + } + break; + + case ']': + Check(application); + if ( + application->GetApplicationState() == Application::SuspendingMission + ) + { + DEBUG_STREAM << "Keystroke invoking mission resume...\n" << std::flush; + Application::ResumeMissionMessage message; + application->Dispatch(&message); + } + break; + + default: + L4VTVControlsMapper::KeypressMessageHandler(message); + break; + } + Check_Fpu(); +} + +//############################################################################# +// Model Support +// +void + VTVThrustmasterMapper::InterpretControls(Scalar time_slice) +{ + // + //---------------------------------------- + // Use the hat buttons to set the throttle + //---------------------------------------- + // + LBE4ControlsManager + *controls = Cast_Object( + LBE4ControlsManager*, + application->GetControlsManager() + ); + Check(controls); + + throttlePosition = controls->scalarGroup[LBE4ControlsManager::ScalarThrottle].previousValue; +/*if (throttleUp > 0) + { + throttlePosition = 1.0f; + reverseThrust = 0; + } + else if (throttleDown > 0) + { + throttlePosition = 1.0f; + reverseThrust = 1; + } + else + { + throttlePosition = 0.0f; + reverseThrust = 0; + }*/ + + // + //---------------------------------------- + // Sum the pedal inputs + //---------------------------------------- + // + pedalsPosition = leftPedal - rightPedal; + + + VTVControlsMapper::InterpretControls(time_slice); + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVThrustmasterMapper::VTVThrustmasterMapper( + VTV *player_vehicle, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + L4VTVControlsMapper( + player_vehicle, + subsystem_ID, + subsystem_resource, + DefaultData + ) +{ + SetPerformance(&VTVThrustmasterMapper::InterpretControls); + leftPedal = 0.0f; + rightPedal = 0.0f; + + LBE4ControlsManager + *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + Check(controls); + + controls + ->joystickGroup[LBE4ControlsManager::JoystickPhysical] + .Add(RPL4ModeManager::ModeAlwaysActive, &stickPosition, this); + + // + //-------------- + // Pedal mapping + //-------------- + // + controls + ->scalarGroup[LBE4ControlsManager::ScalarLeftPedal] + .Add(RPL4ModeManager::ModeAlwaysActive, &leftPedal, this); + + controls + ->scalarGroup[LBE4ControlsManager::ScalarRightPedal] + .Add(RPL4ModeManager::ModeAlwaysActive, &rightPedal, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookRight, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookLeft, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookUp, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookBehind, this); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonThrottle1] + .Add(RPL4ModeManager::ModeAlwaysActive, &reverseThrust, this); + + controls + ->keyboardGroup[LBE4ControlsManager::KeyboardPC] + .Add(RPL4ModeManager::ModeAlwaysActive, this, KeypressMessageID, this); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVThrustmasterMapper::~VTVThrustmasterMapper() +{ +} + + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + VTVThrustmasterMapper::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} + +//############################################################################# +//################################ RIOMapper ################################## +//############################################################################# + +//############################################################################# +// Shared Data Support +// +VTVRIOMapper::SharedData + VTVRIOMapper::DefaultData( + VTVRIOMapper::GetClassDerivations(), + VTVRIOMapper::MessageHandlers, + VTVRIOMapper::GetAttributeIndex(), + VTVRIOMapper::StateCount + ); + +Derivation* VTVRIOMapper::GetClassDerivations() +{ static Derivation classDerivations(L4VTVControlsMapper::GetClassDerivations(), "VTVRIOMapper"); + return &classDerivations; +} + + +//############################################################################# +// Messaging Support +// +const Receiver::HandlerEntry + VTVRIOMapper::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(VTVRIOMapper, Keypress), + MESSAGE_ENTRY(VTVRIOMapper, SwitchMode), + MESSAGE_ENTRY(VTVRIOMapper, SelectPreset), + MESSAGE_ENTRY(VTVRIOMapper, CenterJoystick), + MESSAGE_ENTRY(VTVRIOMapper, ConfigureControls) +}; + +Receiver::MessageHandlerSet + VTVRIOMapper::MessageHandlers( + ELEMENTS(VTVRIOMapper::MessageHandlerEntries), + VTVRIOMapper::MessageHandlerEntries, + L4VTVControlsMapper::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVRIOMapper::KeypressMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + Check(message); + + switch (message->dataContents) + { + case PCK_F1: + { + Check(application); + LBE4ControlsManager *controls = Cast_Object( + LBE4ControlsManager*, + application->GetControlsManager() + ); + Check(controls); + + Tell("Centered RIO Joystick\n"); + controls->CenterRIOJoystick(); + } + break; + + case PCK_F12: + Check(application); + if ( + application->GetApplicationState() != Application::EndingMission + && application->GetApplicationState() != Application::StoppingMission + ) + { + DEBUG_STREAM << "Keystroke invoking mission stop...\n" << std::flush; + Exit_Code = 1; + Application::StopMissionMessage message(Exit_Code); + application->Dispatch(&message); + } + break; + + case 'W': + case 'w': + { + ReceiverDataMessageOf + config_msg( + Booster::ActivateMessageID, + sizeof(ReceiverDataMessageOf), + 1 + ); + for (int i=0; i < GetEntity()->GetSubsystemCount(); i++) + { + Subsystem *sub = GetEntity()->GetSubsystem(i); + if (sub && sub->GetClassID() == VTV::BoosterClassID) + { + sub->Dispatch(&config_msg); + break; + } + } + break; + } + break; + + //------------------------------------------------------- + // Control eyepoint views + //------------------------------------------------------- + case PCK_UP: // look forward + lookLeft = -1; + lookRight = -1; + lookBehind = -1; + lookUp = -1; + break; + case PCK_LEFT: // look left + lookLeft = 1; + lookRight = -1; + lookBehind = -1; + lookUp = -1; + break; + case PCK_RIGHT: // look right + lookLeft = -1; + lookRight = 1; + lookBehind = -1; + lookUp = -1; + break; + case PCK_DOWN: // look behind + lookLeft = -1; + lookRight = -1; + lookBehind = 1; + lookUp = -1; + break; + case PCK_CTL_UP: // look up + lookLeft = -1; + lookRight = -1; + lookBehind = -1; + lookUp = 1; + break; + + default: + L4VTVControlsMapper::KeypressMessageHandler(message); + break; + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVRIOMapper::SwitchModeMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + + //------------------------------------------- + // Switch on 'press' only (ignore release) + //------------------------------------------- + if (message->dataContents > 0) + { + //---------------------------------- + // Pick the selected mode + //---------------------------------- + switch (message->dataContents - 1) + { + case LBE4ControlsManager::ButtonAuxUpperRight5: + SetControlsMode(BasicMode); + break; + + case LBE4ControlsManager::ButtonAuxUpperRight6: + SetControlsMode(StandardMode); + break; + + case LBE4ControlsManager::ButtonAuxUpperRight7: + SetControlsMode(VeteranMode); + break; + + case LBE4ControlsManager::ButtonAuxUpperRight8: + SetControlsMode(MasterMode); + break; + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVRIOMapper::SelectPresetMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + //------------------------------------------- + // Switch on 'press' only (ignore release) + //------------------------------------------- + if (message->dataContents > 0) + { + //----------------------------------- + // Choose a new preset + //----------------------------------- + int + current_preset_number = (message->dataContents - 1) + - LBE4ControlsManager::ButtonSecondary7; + + if (previousPresetNumber != current_preset_number) + { + //----------------------------------- + // Set the old preset lamp to 'dim' + //----------------------------------- + if (previousPresetNumber >= 0) + { + Verify(previousPresetNumber < presetCount); + + if (modeLamp[previousPresetNumber] != NULL) + { + Check(modeLamp[previousPresetNumber]); + modeLamp[previousPresetNumber]->SetState(L4Lamp::LampStateDim); + } + } + //----------------------------------- + // Set the new preset lamp to 'on' + //----------------------------------- + if (current_preset_number >= 0) + { + Verify(current_preset_number < presetCount); + + if (modeLamp[current_preset_number] != NULL) + { + Check(modeLamp[current_preset_number]); + modeLamp[current_preset_number]->SetState(L4Lamp::LampStateOn); + } + } + //----------------------------------- + // Change presets + //----------------------------------- + PresetEnable(current_preset_number); + } + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVRIOMapper::CenterJoystickMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + if (message->dataContents > 0) + { + Check(application); + LBE4ControlsManager + *controls = (LBE4ControlsManager *) application->GetControlsManager(); + Check(controls); + + controls->CenterRIOJoystick(); + } + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVRIOMapper::ConfigureControlsMessageHandler( + ReceiverDataMessageOf *message + ) +{ + Check(this); + + //------------------------------------------------------------- + // Allow the VTVControlsMapper to process the message + //------------------------------------------------------------- + +// OBSOLETE +// VTVControlsMapper::ConfigureControlsMessageHandler(message); + //------------------------------------------- + // Switch on 'press' only (ignore release) + //------------------------------------------- + if (message->dataContents > 0) + { + //------------------------------------------- + // Modify mode + //------------------------------------------- + if (GetSimulationState() == ConfigurationState) + { + SetConfigurationMode(False); + } + else + { + SetConfigurationMode(True); + } + } + Check_Fpu(); +} + +//############################################################################# +// Model Support +// +void + VTVRIOMapper::InterpretControls(Scalar time_slice) +{ + // + //---------------------------------------- + // Reverse if throttle button held in + //---------------------------------------- + // + if (throttleReverse > 0) + { + reverseThrust = 1; + throttleReverse = 0; + } + else if (throttleReverse < 0) + { + reverseThrust = 0; + throttleReverse = 0; + } + // + //---------------------------------------- + // Sum the pedal inputs + //---------------------------------------- + // + pedalsPosition = leftPedal - rightPedal; + + VTVControlsMapper::InterpretControls(time_slice); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVRIOMapper::AddOrErase( + unsigned int button_ID, + Receiver *target, + Receiver::MessageID message_ID + ) +{ + Check(this); + Check(target); + + Check(application); + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + Check(controls); + + controls->buttonGroup[button_ID-1] + .AddOrErase(previousPresetModeMask, target, message_ID, this); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + VTVRIOMapper::AddOrErase( + unsigned int button_ID, + ControlsButton *destination + ) +{ + Check(this); + Check_Pointer(destination); + + Check(application); + LBE4ControlsManager *controls = + Cast_Object(LBE4ControlsManager*,application->GetControlsManager()); + Check(controls); + + controls->buttonGroup[button_ID-1] + .AddOrErase(previousPresetModeMask, destination, this); + Check_Fpu(); +} + +//############################################################################# +// Platform-specific updates +// +void + VTVRIOMapper::NotifyOfControlModeChange(int new_mode) +{ + Check(this); + + int + lamp_number; + + //---------------------------------- + // Set the old mode button to 'dim' + //---------------------------------- + switch (previousControlMode) + { + case BasicMode: lamp_number = 0; break; + case StandardMode: lamp_number = 1; break; + case VeteranMode: lamp_number = 2; break; + case MasterMode: lamp_number = 3; break; + default: lamp_number = -1; break; + } + + if (lamp_number >= 0) + { + Verify(lamp_number < modeLampCount); + if (modeLamp[lamp_number] != NULL) + { + Check(modeLamp[lamp_number]); + modeLamp[lamp_number]->SetState(L4Lamp::LampStateDim); + } + } + + //---------------------------------- + // Pick the selected mode + //---------------------------------- + switch (controlMode) + { + case BasicMode: lamp_number = 0; break; + case StandardMode: lamp_number = 1; break; + case VeteranMode: lamp_number = 2; break; + case MasterMode: lamp_number = 3; break; + default: lamp_number = -1; break; + } + if (lamp_number >= 0) + { + Verify(lamp_number < modeLampCount); + if (modeLamp[lamp_number] != NULL) + { + Check(modeLamp[lamp_number]); + modeLamp[lamp_number]->SetState(L4Lamp::LampStateOn); + } + } + //----------------------------------- + // Invoke ancestral method + //----------------------------------- + L4VTVControlsMapper::NotifyOfControlModeChange(new_mode); + + Check_Fpu(); +} + +void + VTVRIOMapper::NotifyOfConfigurationModeChange(Logical new_state) +{ + Check(this); + + for(int i=0; iSetAlertState(new_state); + } + } + //----------------------------------- + // Invoke ancestral method + //----------------------------------- + L4VTVControlsMapper::NotifyOfConfigurationModeChange(new_state); + + Check_Fpu(); +} + +//############################################################################# +// Construction and Destruction Support +// + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVRIOMapper::VTVRIOMapper( + VTV *player_vehicle, + int subsystem_ID, + SubsystemResource *subsystem_resource +): + L4VTVControlsMapper( + player_vehicle, + subsystem_ID, + subsystem_resource, + DefaultData + ) +{ + SetPerformance(&VTVRIOMapper::InterpretControls); + throttleUp = 0; + throttleDown = 0; + throttleReverse = 0; + leftPedal = 0.0f; + rightPedal = 0.0f; + + Check(application); + LBE4ControlsManager + *controls = Cast_Object( + LBE4ControlsManager*, + application->GetControlsManager() + ); + Check(controls); + + VTV + *vtv = GetEntity(); + Check(vtv); + + // + //------------------ + // Throttle mappings + //------------------ + // + controls + ->scalarGroup[LBE4ControlsManager::ScalarThrottle] + .Add(RPL4ModeManager::ModeAlwaysActive, &throttlePosition, this); + controls + ->buttonGroup[LBE4ControlsManager::ButtonThrottle1] + .Add(RPL4ModeManager::ModeAlwaysActive, &reverseThrust, this); + + // + //------------------ + // Joystick mappings + //------------------ + // + controls + ->joystickGroup[LBE4ControlsManager::JoystickPhysical] + .Add(RPL4ModeManager::ModeAlwaysActive, &stickPosition, this); + // + //------------------ + // Eyepoint mappings + //------------------ + // + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatLeft] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookLeft, this); + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatRight] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookRight, this); + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatUp] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookUp, this); + controls + ->buttonGroup[LBE4ControlsManager::ButtonJoystickHatDown] + .Add(RPL4ModeManager::ModeAlwaysActive, &lookBehind, this); + // + //-------------- + // Pedal mapping + //-------------- + // + controls + ->scalarGroup[LBE4ControlsManager::ScalarLeftPedal] + .Add(RPL4ModeManager::ModeAlwaysActive, &leftPedal, this); + + controls + ->scalarGroup[LBE4ControlsManager::ScalarRightPedal] + .Add(RPL4ModeManager::ModeAlwaysActive, &rightPedal, this); + + // + //----------------- + // Keyboard mapping + //----------------- + // + controls + ->keyboardGroup[LBE4ControlsManager::KeyboardPC] + .Add(RPL4ModeManager::ModeAlwaysActive, this, KeypressMessageID, this); + + //---------------------------------------------------------------- + // Configuration mapping + //---------------------------------------------------------------- + + // Lamps explicitly controlled by ConfigureControlsMessageHandler + + configLamp[0] = CreateControlledLamp( + LBE4ControlsManager::ButtonAuxUpperRight1, + RPL4ModeManager::ModeStandard + ); + + configLamp[1] = CreateControlledLamp( + LBE4ControlsManager::ButtonAuxUpperRight2, + RPL4ModeManager::ModeStandard + ); + + + if (!getenv("NOMODES")) + { + int + i; + + for(i=0; iSetState(L4Lamp::LampStateDim); + } + } + + controls + ->buttonGroup[LBE4ControlsManager::ButtonAuxUpperRight1] + .Add( + RPL4ModeManager::ModeStandard, + this, + ConfigureControlsMessageID, this + ); + + controls + ->buttonGroup[LBE4ControlsManager::ButtonAuxUpperRight2] + .Add( + RPL4ModeManager::ModeStandard, + this, + ConfigureControlsMessageID, this + ); + } + + //---------------------------------------------------------------- + // Joystick centering + //---------------------------------------------------------------- + MakeButtonLampEventPair( + controls, + LBE4ControlsManager::ButtonAuxUpperRight3, + LBE4ControlsManager::ButtonAuxUpperRight4, + this, + CenterJoystickMessageID, + this + ); + + //---------------------------------------------------------------- + // Secondary mappings + //---------------------------------------------------------------- + MakeButtonLampEvent( + controls, + LBE4ControlsManager::ButtonSecondary1, + vtv, + VTV::ZoomInMessageID, + this + ); + + MakeButtonLampEvent( + controls, + LBE4ControlsManager::ButtonSecondary2, + vtv, + VTV::ZoomOutMessageID, + this + ); + + MakeButtonLampEvent( + controls, + LBE4ControlsManager::ButtonSecondary3, + this, + ToggleReticleMessageID, + this + ); + + MakeButtonLampEvent( + controls, + LBE4ControlsManager::ButtonSecondary4, + this, + ActivateHornMessageID, + this + ); + + //---------------------------------------------------------------- + // Mode mapping + //---------------------------------------------------------------- + previousControlMode = -1; + + if (!getenv("NOMODES")) + { + int + i; + + static int + button_number[modeLampCount] = + { + LBE4ControlsManager::ButtonAuxUpperRight5, + LBE4ControlsManager::ButtonAuxUpperRight6, + LBE4ControlsManager::ButtonAuxUpperRight7, + LBE4ControlsManager::ButtonAuxUpperRight8 + }; + + for(i=0; ibuttonGroup[button_number[i]].Add( + RPL4ModeManager::ModeAlwaysActive, + this, + SwitchModeMessageID, + this + ); + + //---------------------------------------------- + // These lamps are explicitly controlled by + // VTVRIOMapper::NotifyOfControlModeChange + //---------------------------------------------- + modeLamp[i] = CreateControlledLamp(button_number[i]); + + if (modeLamp[i] != NULL) + { + Check(modeLamp[i]); + } + } + } + + //---------------------------------------------------------------- + // Preset mapping + //---------------------------------------------------------------- + if (!getenv("NOMODES")) + { + int + i; + + static int + button_number[presetCount] = + { + LBE4ControlsManager::ButtonSecondary7, + LBE4ControlsManager::ButtonSecondary8, + LBE4ControlsManager::ButtonSecondary9, + LBE4ControlsManager::ButtonSecondary10, + LBE4ControlsManager::ButtonSecondary11, + LBE4ControlsManager::ButtonSecondary12 + }; + + for(i=0; ibuttonGroup[button_number[i]].Add( + RPL4ModeManager::ModeAlwaysActive, + this, + SelectPresetMessageID, + this + ); + + // These lamps are explicitly controlled by SelectPresetMessageHandler + modeLamp[i] = CreateControlledLamp(button_number[i]); + + if (modeLamp[i] != NULL) + { + Check(modeLamp[i]); + modeLamp[i]->SetState( + (i==0)? L4Lamp::LampStateOn : L4Lamp::LampStateDim + ); + } + } + NotifyOfControlModeChange(BasicMode); + } + + //---------------------------------------------------------------- + // liftcut mapping + //---------------------------------------------------------------- + CreateDirectSystemMappingPair( + controls, + LBE4ControlsManager::ButtonAuxUpperLeft1, + LBE4ControlsManager::ButtonAuxUpperLeft2, + &liftCut, + this, + ConfigureLiftCutMappablesMessageID + ); + //---------------------------------------------------------------- + // sideslip mapping + //---------------------------------------------------------------- + CreateDirectSystemMappingPair( + controls, + LBE4ControlsManager::ButtonAuxUpperLeft3, + LBE4ControlsManager::ButtonAuxUpperLeft4, + &sideSlip, + this, + ConfigureSideSlipMappablesMessageID + ); + //---------------------------------------------------------------- + // intercom PTT mapping + //---------------------------------------------------------------- + CreateEventSystemMappingPair( + controls, + LBE4ControlsManager::ButtonAuxUpperLeft5, + LBE4ControlsManager::ButtonAuxUpperLeft6, + this, + ActivatePTTMessageID, + ConfigurePTTMappablesMessageID + ); + //---------------------------------------------------------------- + // horn mapping + //---------------------------------------------------------------- + CreateEventSystemMappingPair( + controls, + LBE4ControlsManager::ButtonAuxUpperLeft7, + LBE4ControlsManager::ButtonAuxUpperLeft8, + this, + ActivateHornMessageID, + ConfigureHornMappablesMessageID + ); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +VTVRIOMapper::~VTVRIOMapper() +{ + Check(this); + +// HACK - gaugeRenderer::ShutdownImplementation() removes all lamps. +// When this destructor gets called, the lamps have (usually) already +// been deleted. The fix is to have all lamp operations go through +// the lamp manager, referring to the lamp by ID and modeMask...then, +// when a request is made for a nonexistent lamp, the request is ignored. + +#if 0 + + int + i; + + //----------------------------------------------- + // First check to see if the lamp manager exists. + // If it doesn't, then the lamps have either + // not been created or else have already + // been deleted. + //----------------------------------------------- + Check(application); + if (application->GetGaugeRenderer() != NULL) + { + Check(application->GetGaugeRenderer()); + + if (application->GetGaugeRenderer()->GetLampManager() != NULL) + { + Check(application->GetGaugeRenderer()->GetLampManager()); + //-------------------------------------------- + // Delete controlled lamp objects + //-------------------------------------------- + for(i=0; i *message); + +protected: + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (L4VTVControlsMapper::*Performance)(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + CreateTemporaryEventMappings( + Receiver *receiver, + Receiver::MessageID config_message_id + ), + RemoveTemporaryEventMappings(), + AddOrErase( + unsigned int button_ID, + Receiver *target, + Receiver::MessageID message_ID + ), + AddOrErase( + unsigned int button_ID, + ControlsButton *destination + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + L4VTVControlsMapper( + VTV *player_vehicle, + int subsystem_ID, + SubsystemResource *subsystem_resource, + SharedData &shared_data = DefaultData + ); + ~L4VTVControlsMapper(); + + Logical + TestInstance() const; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Controls mode switching +// +void + SetControlsMode(int new_mode), + SetConfigurationMode(Logical new_state); + +void + NotifyOfControlModeChange(int new_mode), + NotifyOfConfigurationModeChange(Logical new_state); + +ModeMask + GetPresetModeMask() + { + Check(this); + return previousPresetModeMask; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Preset controls switching +// +void + PresetEnable(int preset_number); +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Protected data +// +protected: + enum + { + presetCount = 6 // limited to number of switches! + }; + + ModeMask + previousPresetModeMask; + int + previousPresetNumber; +}; + +//########################################################################## +//#################### ThrustmasterMapper ############################ +//########################################################################## + +class VTVThrustmasterMapper: + public L4VTVControlsMapper +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging Support +// +public: + void + KeypressMessageHandler(ReceiverDataMessageOf *message); + +protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (VTVThrustmasterMapper::*Performance)(Scalar time_slice); + + void + InterpretControls(Scalar time_slice); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + VTVThrustmasterMapper( + VTV *player_vehicle, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~VTVThrustmasterMapper(); + + Logical + TestInstance() const; + +private: + ControlsScalar + leftPedal, + rightPedal; +}; + +//########################################################################## +//########################### RIOMapper ############################## +//########################################################################## + +class VTVRIOMapper : + public L4VTVControlsMapper +{ +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Messaging Support +// +public: + enum { + SwitchModeMessageID = L4VTVControlsMapper::NextMessageID, + SelectPresetMessageID, + CenterJoystickMessageID, + ConfigureControlsMessageID, // duplicate of VTVControlsMapper msg + NextMessageID + }; + + void + KeypressMessageHandler(ReceiverDataMessageOf *message); + void + SwitchModeMessageHandler( + ReceiverDataMessageOf *message + ); + void + SelectPresetMessageHandler( + ReceiverDataMessageOf *message + ); + void + CenterJoystickMessageHandler( + ReceiverDataMessageOf *message + ); + void + ConfigureControlsMessageHandler( + ReceiverDataMessageOf *message + ); + +protected: + static const HandlerEntry + MessageHandlerEntries[]; + static MessageHandlerSet + MessageHandlers; + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Model Support +// +public: + typedef void + (VTVRIOMapper::*Performance)(Scalar time_slice); + + void + InterpretControls(Scalar time_slice); + + void + NotifyOfControlModeChange(int new_mode); + + void + NotifyOfConfigurationModeChange(Logical new_state); + + void + SetPerformance(Performance performance) + { + Check(this); + activePerformance = (Simulation::Performance)performance; + } + + void + AddOrErase( + unsigned int button_ID, + Receiver *target, + Receiver::MessageID message_ID + ); + + void + AddOrErase( + unsigned int button_ID, + ControlsButton *destination + ); + void + AddOrErase( + unsigned int button_ID, + Scalar *destination + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Construction and Destruction Support +// +public: + VTVRIOMapper( + VTV *player_vehicle, + int subsystem_ID, + SubsystemResource *subsystem_resource + ); + ~VTVRIOMapper(); + + Logical + TestInstance() const; + +protected: + int + previousControlMode; + + enum + { + configLampCount=2, + modeLampCount=4 + }; + + L4Lamp + *configLamp[configLampCount], + *modeLamp[modeLampCount], + *presetLamp[presetCount]; + +private: + ControlsButton + throttleUp, + throttleDown, + throttleReverse; + + ControlsScalar + leftPedal, + rightPedal; +}; diff --git a/RP_L4/RPL4MSSN.cpp b/RP_L4/RPL4MSSN.cpp new file mode 100644 index 0000000..5834e88 --- /dev/null +++ b/RP_L4/RPL4MSSN.cpp @@ -0,0 +1,306 @@ +#include "rpl4.h" +#pragma hdrstop + +#include "rpl4mssn.h" +#include "..\munga_l4\l4grend.h" +#include "..\munga_l4\l4app.h" +#include "..\munga\notation.h" +#include "..\munga_l4\l4host.h" +#include "..\munga\hostmgr.h" +#include "..\munga\namelist.h" + +//########################################################################## +//########################### RPL4Mission ############################ +//########################################################################## + +// +//############################################################################# +//############################################################################# +// +RPL4Mission::RPL4Mission( + NotationFile *notation_file, + ResourceFile *resources +): + RPMission(notation_file, resources) +{ + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +RPL4Mission::~RPL4Mission() +{ + Check(this); + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +void + RPL4Mission::SetPlayerData(NotationFile *notation_file) +{ + Check(this); + // + //-------------------------------------------------------------- + // Figure out which page we should be using to create the player + //-------------------------------------------------------------- + // + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + L4Host *host = (L4Host*)host_manager->GetLocalHost(); + Check(host); + CString + player_node = host->GetSymbolicName(); + + // + //---------------------------------------------------------- + // Copy the game model and dropzone strings into the mission + //---------------------------------------------------------- + // + gameModel = NULL; + const char* player_model = NULL; + notation_file->GetEntry(player_node, "vehicle", &player_model); + if (!player_model) + { + DEBUG_STREAM << "Error: vehicle not specified!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + Check_Pointer(player_model); + gameModel = strdup(player_model); + Register_Pointer(gameModel); + + dropZoneName = NULL; + const char* drop_zone = NULL; + notation_file->GetEntry(player_node, "dropzone", &drop_zone); + if (!drop_zone) + { + DEBUG_STREAM << "Error: dropzone not specified!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + Check_Pointer(drop_zone); + dropZoneName = strdup(drop_zone); + Register_Pointer(dropZoneName); + + dropZoneHost = False; + notation_file->GetEntry(player_node, "loadzones", &dropZoneHost); + + colorName = NULL; + const char* color_name = NULL; + notation_file->GetEntry(player_node, "color", &color_name); + if (!color_name) + { + DEBUG_STREAM << "Error: color not specified!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + Check_Pointer(color_name); + colorName = strdup(color_name); + Register_Pointer(colorName); + + badgeName = NULL; + const char* badge_name = NULL; + notation_file->GetEntry(player_node, "badge", &badge_name); + if (!badge_name) + { + DEBUG_STREAM << "Error: badge not specified!\n" << std::flush; + PostQuitMessage(AbortExitCodeID); + } + Check_Pointer(badge_name); + badgeName = strdup(badge_name); + Register_Pointer(badgeName); + // + //~~~~~~~~~~~~~~~~~~~~~~ + // Get playerBitmapIndex + //~~~~~~~~~~~~~~~~~~~~~~ + // + if (!notation_file->GetEntry( + player_node, + "bitmapindex", + &playerBitmapIndex + ) + ) + { + DEBUG_STREAM<<"No bitmapindex in egg"< + GetGaugeRenderer(); + if (gauge_renderer != NULL) + { + Check(gauge_renderer); + GraphicsDisplay *graphics_display = + gauge_renderer->GetExternalDisplay(); + + if (graphics_display != NULL) + { + graphics_display->DrawBitMapOpaque( + 1, // foreground color + 0, // background color + 0xFF, // bitmask + GraphicsDisplay::Replace, // operation + 0, // rotation + 0,0, // position + bitmap, + 0, // sx1 + 0, // sy1 + bitmap->Data.Size.x-1, // sx2 + bitmap->Data.Size.y-1 // sy2 + ); + graphics_display->Update(True); + graphics_display->WaitForUpdate(); + } + } + } + } + + // + //---------------------------------------------------------- + // scoreCompression + //---------------------------------------------------------- + // + scoreCompression = False; + const char* score_compression = NULL; + notation_file->GetEntry("mission", "compression", &score_compression); + if (!score_compression) + { + scoreCompression = False; + } + else if (strcmp("1", score_compression) == 0) + { + scoreCompression = True; + } + else + { + scoreCompression = False; + } + + // + //----------------------------------------------- + // Get the position name "General" if not listed + //----------------------------------------------- + // + positionName = NULL; + const char* position_name = NULL; + notation_file->GetEntry(player_node, "position", &position_name); + if(!position_name) + { + position_name = strdup("General"); + } + Check_Pointer(position_name); + positionName = strdup(position_name); + Register_Pointer(positionName); + // + //--------------------------------------- + // Assign an integer value for the teamID + //--------------------------------------- + // + const char* team_name; + notation_file->GetEntry(player_node, "team", &team_name); + int team_count; + + NameList + *team_namelist = notation_file->MakeEntryList("teams"); + + teamID = -1; + if (team_namelist) + { + Register_Object(team_namelist); + team_count = team_namelist->EntryCount(); + if(team_count) + { + int current_id=0; + NameList::Entry *team_entry = team_namelist->GetFirstEntry(); + while(team_entry) + { + if (strcmp(team_name, team_entry->GetChar()) == 0) + { + teamID = current_id; + break; + } + current_id++; + team_entry = team_entry->GetNextEntry(); + } + } + Unregister_Object(team_namelist); + delete team_namelist; + } + Check_Fpu(); +} + +// +//############################################################################# +//############################################################################# +// +Logical + RPL4Mission::TestInstance() const +{ + RPMission::TestInstance(); + return True; +} + +#if 0 +// +//############################################################################# +//############################################################################# +// +void + RPL4Mission::CreatePlayerMessage( + NotationFile *notation_file, + StreamableResourceFile *resources + ) +{ + Check(this); + Check(notation_file); + Check(resources); + + Check(application); + HostManager *host_manager = application->GetHostManager(); + Check(host_manager); + L4Host *host = (L4Host*)host_manager->GetLocalHost(); + Check(host); + CString player_node = host->GetSymbolicName(); + + const char* player_model = NULL; + notation_file->GetEntry(player_node, "gamemodel", &player_model); + Check_Pointer(player_model); + + ResourceDescription *vtv = + resources->FindResourceDescription( + player_model, + ResourceDescription::ModelListResourceType + ); + Check(vtv); + + VTV::MakeMessage *create_player = + new VTV::MakeMessage( + VTV::MakeMessageID, + sizeof(VTV::MakeMessage), + EntityID(host_manager->GetLocalHostID()), + VTV::VTVClassID, + EntityID::Null, + vtv->resourceID, + VTV::DefaultFlags|VTV::InitialStasisFlag, + Origin(Point3D(0.0f, 10.0f, 0.0f), Quaternion::Identity), + Motion::Identity, + Motion::Identity + ); + Register_Object(create_player); + + AdoptCreatePlayerMessage(create_player); + Check_Fpu(); +} +#endif diff --git a/RP_L4/RPL4MSSN.h b/RP_L4/RPL4MSSN.h new file mode 100644 index 0000000..77a5e75 --- /dev/null +++ b/RP_L4/RPL4MSSN.h @@ -0,0 +1,18 @@ +#pragma once + +#include "..\rp\rpmssn.h" + +//########################################################################## +//########################### RPL4Mission ############################ +//########################################################################## + +class RPL4Mission : public RPMission +{ +public: + RPL4Mission(NotationFile *notation_file, ResourceFile *resources); + ~RPL4Mission(); + + Logical TestInstance() const; + + void SetPlayerData(NotationFile *notation_file); +}; diff --git a/RP_L4/RPL4PB.cpp b/RP_L4/RPL4PB.cpp new file mode 100644 index 0000000..4b9f8d5 --- /dev/null +++ b/RP_L4/RPL4PB.cpp @@ -0,0 +1,566 @@ +#include "rpl4.h" +#pragma hdrstop + +#include "rpl4pb.h" +#include "..\munga_l4\l4video.h" +#include "..\munga\mission.h" +#include "..\munga_l4\l4net.h" +#include "..\munga\update.h" +#include "..\munga\renderer.h" +#include "..\munga\cammppr.h" +#include "..\munga\icom.h" +#include "..\munga\nttmgr.h" +#include "..\rp\rpplayer.h" +#include "..\munga\dropzone.h" +#include "..\rp\vtv.h" +#include "..\munga\director.h" + +// RB 1/14/07 +//#include + +//############################################################################# +//########################## RPSpoolerTask ############################## +//############################################################################# + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPSpoolerTask::RPSpoolerTask() +{ +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPSpoolerTask::DispatchPacket(NetworkPacket *packet) +{ + RPL4PlaybackApplication *playback_app = + Cast_Object(RPL4PlaybackApplication*,application); + playback_app->DispatchPacket(packet); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +long + RPSpoolerTask::GetTimeBias() +{ + RPL4PlaybackApplication *playback_app = + Cast_Object(RPL4PlaybackApplication*,application); + Check_Fpu(); + return playback_app->GetTimeBias(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPSpoolerTask::~RPSpoolerTask() +{ + Check_Fpu(); +} + +RPL4IdleApplication::RPL4IdleApplication(HINSTANCE hInstance, HWND hWnd, ResourceFile *resource) +:RPL4Application(hInstance, hWnd, resource) +{ +} + +RPL4IdleApplication::~RPL4IdleApplication() +{ +} + +NetworkManager *RPL4IdleApplication::MakeNetworkManager() +{ + Check_Fpu(); + return new L4PlaybackNetworkManager; +} + +Registry *RPL4IdleApplication::MakeRegistry() +{ + return NULL; +} + +void RPL4IdleApplication::LoadBackgroundTasks() +{ + Check(this); + + ApplicationTask *application_task; + + application_task = new GaugeRendererTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); +} + +Logical RPL4IdleApplication::ExecuteForeground(Time start_of_frame, Scalar frame_duration) +{ + RPL4Application::ExecuteForeground(start_of_frame, frame_duration); + return 0; +} + +Logical RPL4IdleApplication::Shutdown(int remainingApps) +{ + if (remainingApps > 1) + { + return 1; + } else + { + RPL4Application::Shutdown(remainingApps); + + return 0; + } +} + +void + RPL4IdleApplication::Initialize() +{ + Check(this); + + L4Application::InitializeTillConsole(); +} + + +//############################################################################# +//####################### RPL4PlaybackApplication ####################### +//############################################################################# + +const Receiver::HandlerEntry + RPL4PlaybackApplication::MessageHandlerEntries[]= +{ + MESSAGE_ENTRY(RPL4PlaybackApplication, RunMission), + MESSAGE_ENTRY(RPL4PlaybackApplication, StopMission) +}; + +Receiver::MessageHandlerSet& RPL4PlaybackApplication::GetMessageHandlers() +{ + static Receiver::MessageHandlerSet messageHandlers(ELEMENTS(RPL4PlaybackApplication::MessageHandlerEntries), RPL4PlaybackApplication::MessageHandlerEntries, RPL4Application::GetMessageHandlers()); + return messageHandlers; +} + +Derivation* RPL4PlaybackApplication::GetClassDerivations() +{ + static Derivation classDerivations(RPL4Application::GetClassDerivations(), "RPL4PlaybackApplication"); + return &classDerivations; +} + +RPL4PlaybackApplication::SharedData + RPL4PlaybackApplication::DefaultData( + RPL4PlaybackApplication::GetClassDerivations(), + RPL4PlaybackApplication::GetMessageHandlers() + ); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPL4PlaybackApplication::RPL4PlaybackApplication( + HINSTANCE hInstance, + HWND hWnd, + ResourceFile *resource_file, + SpoolFile *spool_file +): + RPL4Application(hInstance, hWnd, resource_file, L4ApplicationClassID, DefaultData) +{ + Check(spool_file); + spoolFile = spool_file; + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +NetworkManager* + RPL4PlaybackApplication::MakeNetworkManager() +{ + Check_Fpu(); + return new L4PlaybackNetworkManager; +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPL4PlaybackApplication::Initialize() +{ + Check(this); + + L4Application::InitializeTillConsole(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPL4PlaybackApplication::LoadBackgroundTasks() +{ + Check(this); + + // + //-------------------------------------------------------------------------- + // Add background tasks + //-------------------------------------------------------------------------- + // + ApplicationTask *application_task; + + application_task = new RPSpoolerTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new ProcessEventTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new GaugeRendererTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new CompleteCyclesTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new FryDeathRowTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + application_task = new AudioRendererTask; + Register_Object(application_task); + backgroundTasks->AddTask(application_task); + + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RPL4PlaybackApplication::ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ) +{ + SET_FOREGROUND_PROCESSING(); + + Check(this); + Verify(application == this); + + if (!executeFrames || GetApplicationState() == WaitingForEgg) + { + videoRenderer->ExecuteIdle(); + CLEAR_FOREGROUND_PROCESSING(); + return executeFrames && !Exit_Code; + } + + Time + frame_ticks; + frame_ticks = frame_duration; + + if (RPL4Application::GetMissionReviewMode() == 2) + { + // + //-------------------------------------------------------------------------- + // Controls Manager + // + // Poll all devices, update all control variables. + // + // This is executed before the update manager so that the + // models have valid control values. It is not necessary for + // the controls to operate at the frame rate of this loop. If + // the controls manager can run run at a lower rate it can + // throttle itself internally. + //-------------------------------------------------------------------------- + // + Check(controlsManager); + controlsManager->Execute(); + } + + // + //-------------------------------------------------------------------------- + // Update Manager + // + // Execute replicants. + // Execute master entities if they are interesting here or + // elsewhere. + // Inform interest manager of possible interest zone change. + // If the master entity has provided and update message then + // send it to replicants. + // + // This is executed before the interest manager so that the + // interest manager can merge all interest zone changes before + // broadcasting interest arena deltas and building interesting + // entity lists. + // + // This is executed before the renderers so that the watchers + // have executed on the model and are ready for use by the + // renderers. + //-------------------------------------------------------------------------- + // + SET_UPDATE_MANAGER(); + + Check(updateManager); + updateManager->Execute(start_of_frame); + + CLEAR_UPDATE_MANAGER(); + + // + //-------------------------------------------------------------------------- + // Interest Manager + // + // Update the net interest arena. + // Calculate which interest zones should be released and which + // interest zones should be loaded + // Send a becoming uninteresting and becoming interesting + // message to the entity. + // Broadcast the interest arena change + // + // The renderer manager call, update interest origins will + // update only those interest origins required by the renderers + // executing this frame. + // + // This is executed before the renderer manager so that when + // the renderers execute they execute upon interest lists that + // are valid as of the end of a model/update frame. + // + // In theory the interest manager does not have to run every + // frame. If throttled less, this would cause fuzz at interest + // zone borders, which may or may not be acceptable depending + // on the size of the interest arena. + //-------------------------------------------------------------------------- + // + Check(rendererManager); + rendererManager->UpdateInterestOrigins(start_of_frame); + Check(interestManager); + interestManager->Execute(); + + // + //-------------------------------------------------------------------------- + // Renderer Manager + // + // Execute renderers. + // Get interest list from interest manager. + // Poll watchers. + // + // It is not necessary for all renderers to operate at the frame + // rate of this loop. If a renderer can run at a lower rate it + // does so via the renderer manager which will govern if a + // renderer executes this frame. + //-------------------------------------------------------------------------- + // + SET_RENDERER_MANAGER(); + + Check(rendererManager); + rendererManager->Execute(start_of_frame, frame_ticks, frame_ticks); + + CLEAR_RENDERER_MANAGER(); + + // + //-------------------------------------------------------------------------- + // Intercom Manager + //-------------------------------------------------------------------------- + // + Check(intercomManager); + intercomManager->Execute(); + + // + //-------------------------------------------------------------------------- + // Execution statistics + //-------------------------------------------------------------------------- + // + if (GetApplicationState() == RunningMission) + { + secondsRemainingInGame = + currentMission->GetGameLength() - (Now() - gameStarted); + } + + CLEAR_FOREGROUND_PROCESSING(); + Check_Fpu(); + return executeFrames && !Exit_Code; +} + +// +//############################################################################# +// ExecuteBackgroundTask +//############################################################################# +// +void + RPL4PlaybackApplication::ExecuteBackgroundTask() +{ + Check(this); + + // + // If there exists a high priority event, execute it + // + if (ProcessOneEvent(HighEventPriority)) + { + return; + } + + // + // Execute lower priority tasks + // + Check(backgroundTasks); + backgroundTasks->Execute(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +RPL4PlaybackApplication::~RPL4PlaybackApplication() +{ + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPL4PlaybackApplication::DispatchPacket(NetworkPacket *packet) +{ + Check(this); + NetworkManager *net_mgr = GetNetworkManager(); + Check(net_mgr); + NetworkClient *client = net_mgr->GetNetworkClientPointer(packet->clientID); + Check(client); + client->ReceiveNetworkPacket(packet, &packet->messageData); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +void + RPL4PlaybackApplication::RunMissionMessageHandler( + RunMissionMessage *message + ) +{ + Check(this); + // + //------------------------------------------------------------------------ + // If the application is waiting to launch, synchronize the clock stuff up + //------------------------------------------------------------------------ + // + if (GetApplicationState() == WaitingForLaunch) + { + SpoolFile *spool = GetSpoolFile(); + Check(spool); + NetworkPacket *packet = (NetworkPacket*)spool->GetPointer(); + Verify(packet->messageData.messageID == RunMissionMessageID); + timeBias = Now().ticks - packet->timeStamp.ticks; + spool->NextPacket(); + } + + RPL4Application::RunMissionMessageHandler(message); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +char winners_spot[]="win?"; + +void + RPL4PlaybackApplication::StopMissionMessageHandler( + StopMissionMessage *message + ) +{ + //STUBBED: DPL RB 1/14/07 + MissionReviewApplicationManager *app_mgr = GetApplicationManager(); + Check(app_mgr); + SpoolFile *spool = GetSpoolFile(); + if (spool) + { + Check(spool); + app_mgr->ReleaseSpoolFile(spool); + spoolFile = NULL; + + // + //------------------------ + // Find the dropzone group + //------------------------ + // + EntityManager *entity_manager = application->GetEntityManager(); + Check(entity_manager); + EntityGroup *dropzones = entity_manager->FindGroup("DropZones"); + Check(dropzones); + char *place = winners_spot+3; + + Player *p; + // + //---------------------------------------------------------------------- + // Move all the players into their final positions in the winners circle + //---------------------------------------------------------------------- + // + for ( + int rank=0; + (p = CameraDirector::FindPlayerByRank(rank)) != NULL; + ++rank + ) + { + // + //----------------------------------------------------------------- + // Now find the dropzone appropriate to the rank. If one cannot be + // found, ignore this vehicle + //----------------------------------------------------------------- + // + Verify(rank<10); + *place = (char)('1' + rank); + ChainIteratorOf iterator(dropzones->groupMembers); + DropZone *dropzone; + while ((dropzone = (DropZone*)iterator.ReadAndNext()) != NULL) + { + if (!strcmp(dropzone->GetDropZoneName(), winners_spot)) + { + break; + } + } + if (!dropzone) + { + continue; + } + + // + //--------------------------------------------------------------------- + // Get the location of this dropzone, and reset the vehicle to place it + // where specified + //--------------------------------------------------------------------- + // + VTV *vtv = (VTV*)p->GetPlayerVehicle(); + if (vtv->GetClassID() == VTVClassID) + { + vtv->Reset(dropzone->localOrigin, VTV::MissionReviewReset); + vtv->SetPerformance(&VTV::DoNothing); + vtv->FlushEvents(); + } + } + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Reload the NameBitmaps for the Winners Circle + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + DPLRenderer *dpl_renderer = GetVideoRenderer(); + Check(dpl_renderer); + dpl_renderer->SortAndReloadNameBitmaps(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Set the Viewing Angle to 45 Degrees for Winners Circle + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + dpl_renderer->SetViewAngle(Degree(45.0f)); + + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Set the Lighting Angle + //~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;iisceneLightCount;++ii) + { + //dpl_RotateDCS(dpl_renderer->sceneLightDCS[ii], 0.0, dpl_Z); + //dpl_RotateDCS(dpl_renderer->sceneLightDCS[ii], 150.0, dpl_Y); + //dpl_RotateDCS(dpl_renderer->sceneLightDCS[ii], -30.0, dpl_X); + //dpl_FlushDCS (dpl_renderer->sceneLightDCS[ii]); + } + } + + // + //--------------------------------------- + // Let the application stop regularly now + //--------------------------------------- + // + RPL4Application::StopMissionMessageHandler(message); + Check_Fpu(); +} + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// +Logical + RPL4PlaybackApplication::TestInstance() const +{ + return IsDerivedFrom(*GetClassDerivations()); +} diff --git a/RP_L4/RPL4PB.h b/RP_L4/RPL4PB.h new file mode 100644 index 0000000..3724626 --- /dev/null +++ b/RP_L4/RPL4PB.h @@ -0,0 +1,121 @@ +#pragma once + +#include "rpl4app.h" +#include "..\munga_l4\l4splr.h" + +//########################################################################## +//####################### RPSpoolerTask ############################## +//########################################################################## + +class RPSpoolerTask: + public SpoolerTask +{ +public: + RPSpoolerTask(); + ~RPSpoolerTask(); + + void + DispatchPacket(NetworkPacket *packet); + long + GetTimeBias(); +}; + +class RPL4IdleApplication : public RPL4Application +{ +public: + RPL4IdleApplication (HINSTANCE hInstance, HWND hWnd, ResourceFile *resource); + ~RPL4IdleApplication(); + + MissionReviewApplicationManager* + GetApplicationManager() + { + return + (MissionReviewApplicationManager*) + Application::GetApplicationManager(); + } + + Logical Shutdown(int remainingApps); + +protected: + Registry* MakeRegistry(); + NetworkManager* MakeNetworkManager(); + void LoadBackgroundTasks(); + Logical ExecuteForeground(Time start_of_frame, Scalar frame_duration); + void Initialize(); +}; + +//########################################################################## +//#################### RPPlaybackApplication ########################## +//########################################################################## + +class RPL4PlaybackApplication: + public RPL4Application +{ +public: + RPL4PlaybackApplication( + HINSTANCE hInstance, + HWND hWnd, + ResourceFile *resource, + SpoolFile *spool_file = NULL + ); + ~RPL4PlaybackApplication(); + + Logical + TestInstance() const; + + void + SetSpoolFile(SpoolFile *spool_file) + {spoolFile = spool_file;} + + MissionReviewApplicationManager* + GetApplicationManager() + { + return + (MissionReviewApplicationManager*) + Application::GetApplicationManager(); + } + + long + GetTimeBias() + {return timeBias;} + + void + DispatchPacket(NetworkPacket *packet); + +protected: + NetworkManager* + MakeNetworkManager(); + + long + timeBias; + + void + Initialize(); + void + LoadBackgroundTasks(); + Logical + ExecuteForeground( + Time start_of_frame, + Scalar frame_duration + ); + void + ExecuteBackgroundTask(); + + static const HandlerEntry + MessageHandlerEntries[]; + //static MessageHandlerSet MessageHandlers; + static MessageHandlerSet& GetMessageHandlers(); + +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// Shared Data Support +// +public: + //static Derivation *GetClassDerivations(); + static Derivation *GetClassDerivations(); + static SharedData DefaultData; + + void + RunMissionMessageHandler(RunMissionMessage *message); + void + StopMissionMessageHandler(StopMissionMessage *message); +}; diff --git a/RP_L4/RPL4TOOL VS2008.vcproj b/RP_L4/RPL4TOOL VS2008.vcproj new file mode 100644 index 0000000..6709af3 --- /dev/null +++ b/RP_L4/RPL4TOOL VS2008.vcproj @@ -0,0 +1,363 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RP_L4/RPL4TOOL.cpp b/RP_L4/RPL4TOOL.cpp new file mode 100644 index 0000000..7e1046e --- /dev/null +++ b/RP_L4/RPL4TOOL.cpp @@ -0,0 +1,78 @@ +#include "rpl4.h" +#pragma hdrstop + +#include +#include "..\rp\rptool.h" +#include "rpl4mode.h" +#include "..\munga_l4\l4tool.h" +#include "rpl4ver.h" + +class RPL4Tool : + public L4Tool +{ +public: + RPL4Tool() : L4Tool() + { + modeManager = new RPL4ModeManager(RPL4ModeManager::ModeInitial); + } + + ~RPL4Tool() + { + delete modeManager; + modeManager = NULL; + } + + Logical ConvertStringToModeMask(const char *name, ModeMask *returned_value_ptr) + { + return modeManager->ModeStringLookup(name, returned_value_ptr); + } + +protected: + RPL4ModeManager *modeManager; +}; + +//########################################################################## +//################## RP4L4Application Globals ######################## +//########################################################################## + +extern const char* const ProgName; +const char* const ProgName = "rpl4tool"; + +// +//############################################################################# +// main +//############################################################################# +// +int main(int argc, char *argv[]) +{ + int status; + if (argc < 3) + { +Usage: + DEBUG_STREAM << "Building Usage: rpl4tool -b rpl4.bld [res2.bld]\n" << " Listing Usage: rpl4tool -l rpl4.res [res2.res ...]\n" << std::flush; + status = 1; + } + else + { + RPL4Tool rpl4_tool; + RPTool rp_l4_tool(&rpl4_tool); + L4AudioCreateSymbols create_symbols; + + if (!strcmp(argv[1], "-b")) + { + status = rp_l4_tool.BuildResources(argc-1, &argv[1], create_symbols, MINOR_DATA_VERSION); + } + else if (!strcmp(argv[1], "-l")) + { + status = rp_l4_tool.ListResources(argc-1, &argv[1]); + } + else + { + DEBUG_STREAM << "Error: Unknown tool switch!\n" << std::flush; + goto Usage; + } + } + + _getch(); + return status; +} diff --git a/RP_L4/RPL4TOOL.vcproj b/RP_L4/RPL4TOOL.vcproj new file mode 100644 index 0000000..8b710c5 --- /dev/null +++ b/RP_L4/RPL4TOOL.vcproj @@ -0,0 +1,372 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RP_L4/RPL4VER.h b/RP_L4/RPL4VER.h new file mode 100644 index 0000000..0db5943 --- /dev/null +++ b/RP_L4/RPL4VER.h @@ -0,0 +1,5 @@ +#pragma once + +#define MAJOR_DATA_VERSION 3 +#define RELEASE_VERSION 0 +#define MINOR_DATA_VERSION 2 diff --git a/RP_L4/RPL4VID.cpp b/RP_L4/RPL4VID.cpp new file mode 100644 index 0000000..69944c8 --- /dev/null +++ b/RP_L4/RPL4VID.cpp @@ -0,0 +1,1713 @@ +#include "rpl4.h" +#pragma hdrstop + +#include "rpl4vid.h" +#include "..\rp\chute.h" +#include "..\munga\door.h" +#include "..\munga\doorfram.h" +#include "..\munga_l4\l4vidrnd.h" +#include "..\munga\mission.h" +#include "..\rp\rpplayer.h" +#include "..\rp\weapsys.h" +#include "..\munga\notation.h" +#include "..\munga\namelist.h" +#include "..\rp\vtv.h" +#include "..\munga\app.h" + +// RB 1/14/07 +//#include +//#include +//#include + +extern Entity + *Entity_Being_Created; // !!! temp, till callback handlers become a class +// HACK, this code makes sure the left and right engine geometry is loaded +// one time and re-used. A more generic solution using the connection +// manager will be created once we are sure it is safe to apply this +// optimization to all cases. +d3d_OBJECT + *left_engine, + *right_engine; +// +//############################################################################# +// Constructor for the video renderer +//############################################################################# +// +RPL4VideoRenderer::RPL4VideoRenderer( + HWND hWnd, + unsigned int screenWidth, + unsigned int screenHeight, + bool fullscreen, + InterestType interest_type, + InterestDepth depth_calibration +) : DPLRenderer(hWnd, screenWidth, screenHeight, fullscreen, interest_type, depth_calibration) +{ +//STUBBED: DPL RB 1/14/07 + vtvCount = 0; + vtvsExpected = 999; +//// +//// Preload a couple of things for DPL +//// +// dpl_LoadObject ( "chg", dpl_load_normal ); +// dpl_LoadObject ( "rivet", dpl_load_normal ); +// dpl_LoadObject ( "lsaber", dpl_load_normal ); +// dpl_LoadObject ( "bst", dpl_load_normal ); +// dpl_LoadObject ( "tsphere", dpl_load_normal ); +} + +// +//############################################################################# +// Destructor for the video renderer +//############################################################################# +// +RPL4VideoRenderer::~RPL4VideoRenderer() +{ +} +#if 0 +void + RPL4VideoRenderer::MakeJointedMoverRenderables( + Entity *entity + ViewFrom view_type +) +{ + bool inDeathZone + dpl_ISECT_MODE + intersect_mode; + uint32 + intersect_mask; + char + my_filename[40]; + dpl_LOAD_MODE + cache_mode; + + JointedMover + *jointed_mover; + + Verify(entity->IsDerivedFrom(JointedMover::GetClassDerivations()); + jointed_mover = Cast_Object( + JointedMover*, + entity + ); + + cache_mode = dpl_load_nocache; + // + //~~~~~~~~~~~~~~~~~~~~~~~ + // Outside or Inside View + //~~~~~~~~~~~~~~~~~~~~~~~ + // + if (type == inside_entity) + { + inDepthZone = true; + //buildInZone = dplDeathZone; + intersect_mode = dpl_isect_mode_obj; + intersect_mask = NULL; + skl_type = EntitySegment::SkeletonType_A; + } + else + { + inDepthZone = true; + //buildInZone = dplDeathZone; + intersect_mode = dpl_isect_mode_geometry; + intersect_mask = INTERSECT_ALL; + skl_type = EntitySegment::SkeletonType_N; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Create the root renderable and tie it to the entity + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + RootRenderable *this_root = + new RootRenderable( + entity, // Entity to attach the renderable to + RootRenderable::Dynamic, // How/when to execute the renderable + NULL, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + Register_Object(this_root); + if(eyeRelative && (entity == GetLinkedEntity())) + { + dpl_DCS* aDCS=this_root->GetDCS(); + Check_Pointer(aDCS); + Check_Pointer(dplTestEyeDCS); + dpl_AddDCSToDCS( aDCS, dplTestEyeDCS ); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // create an array for the parent DCS' sizeof(segmentTable) + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + dpl_DCS **dcs_array = new (dpl_DCS(*[jointed_mover->segmentCount])); + Register_Pointer(dcs_array); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~ + // Get The Joint Subsystem + //~~~~~~~~~~~~~~~~~~~~~~~~ + // + CString *object_file_name; + JointSubsystem* joint_subsystem = jointed_mover->GetJointSubsystem(); + Check(joint_subsystem); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the Segment table for this jointed Mover + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + EntitySegment::SegmentTableIterator segment_iterator(jointed_mover->segmentTable); + EntitySegment *current_segment; + while ((current_segment = segment_iterator.ReadAndNext()) != NULL) + { + Check(current_segment); + // + //~~~~~~~~~~~~~~~~~~~~~~ + // Get the offset matrix + //~~~~~~~~~~~~~~~~~~~~~~ + // + LinearMatrix offset_matrix; + offset_matrix = current_segment->GetBaseOffset(); + + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the parent DCS of the DCS we will be creating + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + dpl_DCS *parent_DCS; + if(!current_segment->GetParent()) + { + parent_DCS = this_root->GetDCS(); + } + else + { + int parent_index; + parent_index = current_segment->GetParentIndex(); + Verify( + (parent_index >= 0) && + (parent_index < jointed_mover->segmentCount) + ); + parent_DCS = dcs_array[parent_index]; + } + Check_Pointer(parent_DCS); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // See if this segment is a Site + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(current_segment->IsSiteSegment()) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If this is an eye site build the eye renderable + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if(type == insideEntity && + strcmp(current_segment->GetName(), "siteeyepoint") == 0) + { + EulerAngles* eyepoint_rotation = + (EulerAngles*)entity->GetAttributePointer("EyepointRotation"); + #if 0 //DEBUG_LEVEL > 0 + DPLEyeRenderable* this_eye = + #endif + mCamera = + new DPLEyeRenderable( + entity, + false, + offset_matrix, + parent_DCS, + dplMainView, + eyepoint_rotation + ); + Register_Object(this_eye); + } + continue; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the dpl object and load it + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + object_file_name = current_segment->GetVideoObjectName(skl_type); + if(object_file_name) + { + Dump(*object_file_name); + //cout<<"normal object "<<*object_file_name<<"\n"; + strcpy(my_filename,*object_file_name); + *(my_filename + (strlen(my_filename) - 4)) = '\0'; + this_object = dpl_LoadObject ( my_filename,cache_mode ); + } + else + { + this_object = NULL; + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the segment index + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int this_segment_index; + this_segment_index = current_segment->GetIndex(); + Verify( + (this_segment_index >= 0) && + (this_segment_index < jointed_mover->segmentCount) + ); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // If this segment has a joint Get it + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + int joint_index; + joint_index = current_segment->GetJointIndex(); + Joint::JointType joint_type; + Joint *this_joint = NULL; + if(joint_index == -1) + { + joint_type = Joint::StaticJointType; + } + else + { + Verify(joint_index < joint_subsystem->GetJointCount()); + this_joint = joint_subsystem->GetJoint(joint_index); + Check(this_joint); + joint_type = this_joint->GetJointType(); + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Make the appropriate renderable + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + switch(joint_type) + { + case Joint::HingeXJointType: + case Joint::HingeYJointType: + case Joint::HingeZJointType: + { + HingeRenderable *this_child = + new HingeRenderable( + entity, // Entity to attach the renderable to + HingeRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + &offset_matrix, // offset matrix to be applied prior to joint DCS + this_joint->GetHingePtr()); // Hinge attribute we will use to control the joint + Register_Object(this_child); + dcs_array[this_segment_index] = this_child->GetDCS(); + } + break; + } + case Joint::BallJointType: + { + BallJointRenderable *this_child = + new BallJointRenderable( + entity, // Entity to attach the renderable to + BallJointRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + &offset_matrix, // offset matrix to be applied prior to joint DCS + this_joint->GetEulerAnglesPtr());// Euler angles to control rotation of the ball joint + Register_Object(this_child); + dcs_array[this_segment_index] = this_child->GetDCS(); + break; + } + case Joint::BallTranslationJointType: + { + BallTranslateJointRenderable *this_child = + new BallTranslateJointRenderable( + entity, // Entity to attach the renderable to + BallTranslateJointRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent_DCS, // the parent DCS we will be offsetting from + &offset_matrix, // offset matrix to be applied prior to joint DCS + this_joint->GetEulerAnglesPtr(), // Euler angles to control rotation of the ball joint + this_joint->GetTranslationPtr() // offset for the translation part of the joint + ); + Register_Object(this_child); + dcs_array[this_segment_index] = this_child->GetDCS(); + break; + } + case Joint::StaticJointType: + default: + { + DPLStaticChildRenderable *this_child = + new DPLStaticChildRenderable( + entity, + false, + this_object, + intersect_mode, + intersect_mask, + offset_matrix, + parent_DCS + ); + Register_Object(this_child); + dcs_array[this_segment_index] = this_child->GetDCS(); + break; + } + } + } + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Cycle through the VTV's subsystems and create the site renderables + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + for(int ii=0;iiGetSubsystemCount();++ii) + { + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Controls Mapper is not propagated across + // the network so we must ignore it here for replicants + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + if (ii == VTV::ControlsMapperSubsystem) + { + continue; + } + Subsystem *current_subsystem = entity->GetSubsystem(ii); + Check(current_subsystem); + int site_index = current_subsystem->GetSegmentIndex(); + if (site_index != -1) + { + EntitySegment *site_segment = entity->GetSegment(site_index); + Check(site_segment); + // + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // Get the parentDCS for this site + //~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ + // + dpl_DCS *parent_DCS; + if(!site_segment->GetParent()) + { + parent_DCS = this_root->GetDCS(); + } + else + { + int parent_index; + parent_index = site_segment->GetParentIndex(); + Verify( + (parent_index >= 0) && + (parent_index < jointed_mover->segmentCount) + ); + parent_DCS = dcs_array[parent_index]; + } + Check_Pointer(parent_DCS); + + // + //~~~~~~~~~~~~~~~~~~~~ + // Get the base offset + //~~~~~~~~~~~~~~~~~~~~ + // + LinearMatrix base_offset = site_segment->GetBaseOffset(); + switch(current_subsystem->GetClassID()) + { + class LaserDrillClassID: + this_object = dpl_LoadObject ( "lsaber", dpl_load_normal ); + Check_Pointer(this_object); + Vector3D* laser_scale = + (Vector3D*)current_subsystem->GetAttributePointer("LaserScale"); + Logical* laser_on = + (Logical*)current_subsystem->GetAttributePointer("LaserOn"); + DPLScaleRenderable *this_scaler = + new DPLScaleRenderable( + entity, + buildInZone, + this_object, + dpl_isect_mode, + NULL, + base_offset, + parent_DCS, + laser_scale, + laser_on + ); + Register_Object(this_scaler); + break; + } + } + } + Unregister_Pointer(dcs_array); + delete[] dcs_array; + + Check_Fpu(); +} +#endif +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// RPL4VideoRenderer::RecurseSKLFile This routine is called recursively to +// to descend the hiearchy of a notation file and create all the renderables +// needed to get an object visible. +// +void + RPL4VideoRenderer::RecurseSKLFile( + Entity *entity, + HierarchicalDrawComponent *parent, + NotationFile *mech_skeleton, + const char *page_name, + int recursion_depth, + ViewFrom type, + int *joint_counter, + dpl_LOAD_MODE cache_mode + ) +{ +//STUBBED: DPL RB 1/14/07 + NameList + *joint_pages, + *site_pages; + + NameList::Entry + *entry; + + const char + *site_page_name, + *next_joint_page_name; // The next joint name (argument to a recursive call) + + const char + *object_file_name, + *my_joint_type; + + char + *gun_name, + *gun_attribute_name, + my_filename[40]; + + int + gun_site; + + + +#ifdef NOISY_RENDERER + int + i; // loop counter +#endif + + Point3D + translation(0,0,0); + + EulerAngles + rotation(0,0,0); + + HierarchicalDrawComponent + *next_parent; + + d3d_OBJECT *this_object = NULL; + + dpl_ISECT_MODE + intersect_mode; + uint32 + intersect_mask; + bool inDeathZone; + // + // get the intersect mode hooked up properly + // + if(type == insideEntity) + { + inDeathZone = true; + //buildInZone = dplDeathZone; +// intersect_mode = dpl_isect_mode_obj; + intersect_mask = NULL; + } + else + { + inDeathZone = false; + //buildInZone = dplMainZone; +// intersect_mode = dpl_isect_mode_geometry; + intersect_mask = INTERSECT_ALL; + } + // + // indent by the recursion depth and print out the current page name + // +#ifdef NOISY_RENDERER + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Tell(page_name << "\n"); +#endif + // + // suck the brains out of this page to create the renderable from + // + mech_skeleton->GetEntry(page_name, "tranx" ,&translation.x); + mech_skeleton->GetEntry(page_name, "trany" ,&translation.y); + mech_skeleton->GetEntry(page_name, "tranz" ,&translation.z); + mech_skeleton->GetEntry(page_name, "pitch" ,&rotation.pitch.angle); + mech_skeleton->GetEntry(page_name, "yaw" ,&rotation.yaw.angle); + mech_skeleton->GetEntry(page_name, "roll" ,&rotation.roll.angle); + + if(mech_skeleton->GetEntry(page_name, "Object" ,&object_file_name)) + { + strcpy(my_filename,object_file_name); + *(my_filename + (strlen(my_filename) - 4)) = '\0'; +#ifdef NOISY_RENDERER + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Tell("BGF file: " << my_filename << "\n"); +#endif +// // HACK, this code makes sure the left and right engine geometry is loaded +// // one time and re-used. A more generic solution using the connection +// // manager will be created once we are sure it is safe to apply this +// // optimization to all cases. +// if( (strcmp("vra",my_filename) == 0) || +// (strcmp("vrc",my_filename) == 0) || +// (strcmp("vrn",my_filename) == 0) || +// (strcmp("vrt",my_filename) == 0)) +// { +// if(right_engine == 0) +// { +// char *file = new char[strlen(my_filename) + 5]; +// strcpy_s(file,strlen(my_filename)+5,my_filename); +// strcat_s(file,strlen(my_filename)+5,".bgf"); +// this_object = d3d_OBJECT::LoadObject ( GetDevice(), file ); +// right_engine = this_object; +//// cout<<"Load right engine\n"; +// } +// else +// { +// this_object = right_engine; +//// cout<<"re-use right engine\n"; +// } +// } +// else if( (strcmp("vla",my_filename) == 0) || +// (strcmp("vlc",my_filename) == 0) || +// (strcmp("vln",my_filename) == 0) || +// (strcmp("vlt",my_filename) == 0)) +// { +// if(left_engine == 0) +// { +// char *file = new char[strlen(my_filename) + 5]; +// strcpy_s(file,strlen(my_filename)+5,my_filename); +// strcat_s(file,strlen(my_filename)+5,".bgf"); +// this_object = d3d_OBJECT::LoadObject ( GetDevice(), file ); +// left_engine = this_object; +//// cout<<"Load left engine\n"; +// } +// else +// { +// this_object = left_engine; +//// cout<<"re-use left engine\n"; +// } +// } +// else + { + char *file = new char[strlen(my_filename) + 5]; + strcpy_s(file,strlen(my_filename)+5,my_filename); + strcat_s(file,strlen(my_filename)+5,".bgf"); + this_object = d3d_OBJECT::LoadObject ( GetDevice(), file ); + } + } + else + { + this_object = NULL; + } + // + // dump out the data for me to look at + // +#ifdef NOISY_RENDERER + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Dump(translation); + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Dump(rotation); +#endif + // + // Construct the renderable to display this part of the thing + // + LinearMatrix Offset_Matrix; + Offset_Matrix = translation; + Offset_Matrix = rotation; + my_joint_type = "none"; + mech_skeleton->GetEntry(page_name, "Type" ,&my_joint_type); + if(recursion_depth>1) + (*joint_counter)++; + if(strncmp(my_joint_type,"hinge",5) == 0) + { + Tell("Hinge Joint " << (*joint_counter) << "\n"); + + VTV *vtv = (VTV*) entity; + JointSubsystem *joint_subsystem = vtv->GetJointSubsystem(); + Verify( + (joint_subsystem->GetJoint(*joint_counter)->GetJointType() == + Joint::HingeXJointType) || + (joint_subsystem->GetJoint(*joint_counter)->GetJointType() == + Joint::HingeYJointType) || + (joint_subsystem->GetJoint(*joint_counter)->GetJointType() == + Joint::HingeZJointType) + ); + const Hinge *hinge_joint = + &joint_subsystem->GetJoint(*joint_counter)->GetHinge(); + HingeRenderable *this_child = + new HingeRenderable( + entity, // Entity to attach the renderable to + HingeRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + inDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + &Offset_Matrix, // offset matrix to be applied prior to joint DCS + hinge_joint); // Hinge attribute we will use to control the joint + Register_Object(this_child); + next_parent = this_child; + } + else if(strcmp(my_joint_type,"ball") == 0) + { + Tell("Ball Joint " << (*joint_counter) << "\n"); + VTV *vtv = (VTV*) entity; + JointSubsystem *joint_subsystem = vtv->GetJointSubsystem(); + const EulerAngles *euler_angles = + &joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles(); + Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() == + Joint::BallJointType); + BallJointRenderable *this_child = + new BallJointRenderable( + entity, // Entity to attach the renderable to + BallJointRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + &Offset_Matrix, // offset matrix to be applied prior to joint DCS + euler_angles); // Euler angles to control rotation of the ball joint + Register_Object(this_child); + next_parent = this_child; + } + else if(strcmp(my_joint_type,"balltranslate") == 0) + { + Tell("Ball Translation Joint " << (*joint_counter) << "\n"); + VTV *vtv = (VTV*) entity; + JointSubsystem *joint_subsystem = vtv->GetJointSubsystem(); + const EulerAngles *euler_angles = + &joint_subsystem->GetJoint(*joint_counter)->GetEulerAngles(); + const Point3D *point_3D = + &joint_subsystem->GetJoint(*joint_counter)->GetTranslation(); + + Verify(joint_subsystem->GetJoint(*joint_counter)->GetJointType() == + Joint::BallTranslationJointType); + BallTranslateJointRenderable *this_child = + new BallTranslateJointRenderable( + entity, // Entity to attach the renderable to + BallTranslateJointRenderable::Dynamic, // How/when to execute the renderable + this_object, // object to hang on the DCS, may be a list later + false, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask, // intersection mask for the object + parent, // the parent DCS we will be offsetting from + &Offset_Matrix, // offset matrix to be applied prior to joint DCS + euler_angles, // Euler angles to control rotation of the ball joint + point_3D); // offset for the translation part of the joint + Register_Object(this_child); + next_parent = this_child; + } + else + { + // Tell("Static Joint" << (*joint_counter) << "\n"); + DPLStaticChildRenderable *this_child = + new DPLStaticChildRenderable( + entity, + inDeathZone, + this_object, + intersect_mode, + intersect_mask, + Offset_Matrix, + parent + ); + Register_Object(this_child); + next_parent = this_child; + } + // + // Get a the list of joint pages from the current page + // + if(type == insideEntity) + { +// dpl_SetDCSNearField ( next_parent_dcs, True ); +// dpl_FlushDCS(next_parent_dcs); + } + joint_pages = mech_skeleton->MakeEntryList(page_name,"joint"); + Register_Object(joint_pages); + recursion_depth++; + // + // Recursively process all the joint pages on the current page + // + for( entry = joint_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + // Get the name of the next joint page + next_joint_page_name = (char *)entry->dataReference; + // Process the next page recursively through this routine + RecurseSKLFile( + entity, + next_parent, + mech_skeleton, + next_joint_page_name, + recursion_depth, + type, + joint_counter, + cache_mode); + } + // + // now check the list of sites for stuff to hook up + // + site_pages = mech_skeleton->MakeEntryList(page_name,"site"); + Register_Object(site_pages); + // + // process all the site pages on the current page + // + for( entry = site_pages->GetFirstEntry(); + entry; + entry = entry->GetNextEntry()) + { + // Get the name of the next joint page + site_page_name = (char *)entry->dataReference; + // + // Setup a eyepoint site, connect it to a rotation attribute so we can move it + // arround. + // + if(type == insideEntity && + strcmp(site_page_name, "siteeyepoint") == 0) + { + mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x); + mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y); + mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z); + mech_skeleton->GetEntry(site_page_name, "pitch" ,&rotation.pitch.angle); + mech_skeleton->GetEntry(site_page_name, "yaw" ,&rotation.yaw.angle); + mech_skeleton->GetEntry(site_page_name, "roll" ,&rotation.roll.angle); +#ifdef NOISY_RENDERER + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Tell(site_page_name << "\n"); + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Dump(translation); + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Dump(rotation); +#endif + EulerAngles* eyepoint_rotation = (EulerAngles*)entity->GetAttributePointer("EyepointRotation"); + Offset_Matrix = translation; + Offset_Matrix = rotation; + #if 0 //DEBUG_LEVEL > 0 + DPLEyeRenderable* this_eye = + #endif + mCamera = + new DPLEyeRenderable( + entity, +// buildInZone, + Offset_Matrix, + next_parent, + eyepoint_rotation + ); + Register_Object(this_eye); + } + // + // Setup a gunport site, this works for all the sites + // this is kind of funky but will be replaced as the VID file goes on line. + // !!! Hack + // + gun_site = False; + gun_name = ""; + gun_attribute_name = ""; + if(strcmp(site_page_name,"sitefrontrightport") == 0) + { + gun_site = True; + gun_name = "LaserGun1"; + gun_attribute_name = "FrontLaserOn"; + } + else if(strcmp(site_page_name,"sitefrontleftport") == 0) + { + gun_site = True; + gun_name = "LaserGun2"; + gun_attribute_name = "FrontLaserOn"; + } + else if(strcmp(site_page_name,"sitefrontcenterport") == 0) + { + gun_site = True; + gun_name = "LaserGun"; + gun_attribute_name = "FrontLaserOn"; + } + else if(strcmp(site_page_name,"sitebackrightport") == 0) + { + gun_site = True; + gun_name = "LaserGun1"; + gun_attribute_name = "RearLaserOn"; + } + else if(strcmp(site_page_name,"sitebackleftport") == 0) + { + gun_site = True; + gun_name = "LaserGun2"; + gun_attribute_name = "RearLaserOn"; + } + else if(strcmp(site_page_name,"sitebackcenterport") == 0) + { + gun_site = True; + gun_name = "LaserGun"; + gun_attribute_name = "RearLaserOn"; + } + if(gun_site) + { + LaserGun* laser_subsystem= + (LaserGun*)entity->FindSubsystem(gun_name); + if(laser_subsystem) + { + mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x); + mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y); + mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z); + mech_skeleton->GetEntry(site_page_name, "pitch" ,&rotation.pitch.angle); + mech_skeleton->GetEntry(site_page_name, "yaw" ,&rotation.yaw.angle); + mech_skeleton->GetEntry(site_page_name, "roll" ,&rotation.roll.angle); + Vector3D* laser_scale = + (Vector3D*)laser_subsystem->GetAttributePointer("LaserScale"); + Logical* laser_on = + (Logical*)laser_subsystem->GetAttributePointer(gun_attribute_name); + this_object = d3d_OBJECT::LoadObject ( GetDevice(), "lsaber.bgf" ); + + if( laser_subsystem && laser_scale && laser_on && this_object) + { + Tell("Hooked "< 0 + DPLScaleRenderable *this_scaler = + #endif + new DPLScaleRenderable( + entity, + inDeathZone, + this_object, + intersect_mode, + intersect_mask, + Offset_Matrix, + next_parent, + laser_scale, + laser_on); + Register_Object(this_scaler); + } + } + } + // + // Setup a chute site, get the position and attributes to control it and bind + // them all up for use. + // + if(strcmp(site_page_name, "sitechute") == 0) + { + mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x); + mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y); + mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z); + Chute* chute_subsystem= + (Chute*)entity->FindSubsystem("Chute"); + if (chute_subsystem) + { + Check(chute_subsystem); + Quaternion* chute_rotation = + (Quaternion*)chute_subsystem->GetAttributePointer("ChuteDirection"); + Vector3D* chute_scale = + (Vector3D*)chute_subsystem->GetAttributePointer("ScaleFactor"); + Logical* chute_open = + (Logical*)chute_subsystem->GetAttributePointer("ChuteOn"); + this_object = d3d_OBJECT::LoadObject ( GetDevice(), "cht.bgf" ); + if(chute_rotation && chute_scale && chute_open && this_object) + { + Check(chute_rotation); + Check(chute_scale); + Check_Pointer(chute_open); + Check_Pointer(this_object); + Offset_Matrix.BuildIdentity(); + Offset_Matrix = translation; + #if DEBUG_LEVEL > 0 + DPLScaleQuatRenderable *this_scaler = + #endif + new DPLScaleQuatRenderable( + entity, + inDeathZone, + this_object, + intersect_mode, + intersect_mask, + Offset_Matrix, + next_parent, + chute_rotation, + chute_scale, + chute_open); + Register_Object(this_scaler); + } + else + { + if(!chute_rotation) + DEBUG_STREAM<<"ChuteSite couldn't find ChuteDirection attribute\n" << std::flush; + if(!chute_scale) + DEBUG_STREAM<<"ChuteSite couldn't find ChuteScale attribute\n" << std::flush; + if(!chute_open) + DEBUG_STREAM<<"ChuteSite couldn't find ChuteOn attribute\n" << std::flush; + if(!this_object) + DEBUG_STREAM<<"ChuteSite couldn't find chute DPL object\n" << std::flush; + } + } + } + // + // Setup a booster site, get the site position and the attribute(s) that will + // control the booster. Setup origin matrix and renderables to control the + // appearance of the booster. + // + if(strcmp(site_page_name, "sitebooster") == 0) + { +#ifdef NOISY_RENDERER + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Tell(site_page_name << "\n"); + Tell(recursion_depth); + for (i = 0; i < recursion_depth; i++) + Tell(".."); + Dump(translation); +#endif + mech_skeleton->GetEntry(site_page_name, "tranx" ,&translation.x); + mech_skeleton->GetEntry(site_page_name, "trany" ,&translation.y); + mech_skeleton->GetEntry(site_page_name, "tranz" ,&translation.z); + Vector3D* booster_scale = + (Vector3D*)entity->GetAttributePointer("BoosterScale"); + Logical* booster_on = + (Logical*)entity->GetAttributePointer("BoosterOn"); + this_object = d3d_OBJECT::LoadObject ( GetDevice(), "bst.bgf" ); + if( booster_scale && booster_on && this_object) + { + Check(booster_scale); + Check_Pointer(booster_on); + Offset_Matrix.BuildIdentity(); + Offset_Matrix = translation; + #if DEBUG_LEVEL > 0 + DPLScaleRenderable* this_scaler = + #endif + /*new DPLScaleRenderable( + entity, + inDeathZone, + this_object, + intersect_mode, + intersect_mask, + Offset_Matrix, + next_parent, + booster_scale, + booster_on);*/ + } + else + { + if(!booster_scale) + DEBUG_STREAM<<"BoosterSite couldn't find BoosterScale attribute\n" << std::flush; + if(!booster_on) + DEBUG_STREAM<<"BoosterSite couldn't find BoosterOn attribute\n" << std::flush; + if(!this_object) + DEBUG_STREAM<<"BoosterSite couldn't find booster DPL object\n" << std::flush; + } + Scalar* booster_smoke_density = + (Scalar*)entity->GetAttributePointer("BoosterSmokeDensity"); + if( booster_smoke_density ) + { + translation.z +=3.0; + #if 1 + #if DEBUG_LEVEL > 0 + DPLRepeatSFXRenderable* this_effect = + #endif + new DPLRepeatSFXRenderable( + entity, + inDeathZone, + translation, + next_parent, // offset is relative to this + 0, // type code for the effect + booster_smoke_density); + Register_Object(this_effect); + #else + DPLPSFXRenderable* this_effect = + new DPLPSFXRenderable( + entity, // Entity to attach the renderable to + DPLPSFXRenderable::Dynamic, // How/when to execute the renderable + booster_on, // address containing the trigger + myPSFXDescriptons[4], // Pointer to the psfx description in memory + next_parent_dcs, // DCS the effect is relative to (may be NULL) + &translation); // Offset (or world coordinants if DCS is NULL) + Register_Object(this_effect); + #endif + } + else + { + if(!booster_smoke_density) + DEBUG_STREAM<<"BoosterSite couldn't find BoosterSmokeDensity attribute\n" << std::flush; + } + } + } +// +// Unregister the namelist objects we created in this subroutine +// + Check(joint_pages); + Unregister_Object(joint_pages); + delete joint_pages; + Check(site_pages); + Unregister_Object(site_pages); + delete site_pages; +} + + +// +//############################################################################# +// This starts the process for of reading in a .skl file for a vtv. +//############################################################################# +// +HierarchicalDrawComponent* + RPL4VideoRenderer::ReadSKLFile( + Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom type, // type of reference to create + char skeleton_type) // TEMPORARY!!!! to handle color substitutions +{ +//STUBBED: DPL RB 1/14/07 + //dpl_ZONE + // *buildInZone; + bool inDeathZone; + int + joint_counter; + char + *skl_filename, + TempFileName[256]; + NotationFile + *object_skeleton; + dpl_ISECT_MODE + intersect_mode; + uint32 + intersect_mask; + // test code for load size reduction + left_engine = 0; + right_engine = 0; + // + // Currently, the name of the .skl file to read in is in the video resource + // After reading in the .skl file we die if the page count was zero, + // indicating an empty file. + // + strcpy(TempFileName,"video\\"); +//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv +// HACK to test video resource format changes + skl_filename = (char *)model_resource->resourceAddress; + skl_filename += sizeof(int); + strcat(TempFileName, skl_filename); + //strcat(TempFileName, ".skl"); +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ +//vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv + // !!! Temporary hack to get proper vtv skl file to load + TempFileName[8] = skeleton_type; +//^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + #ifdef NOISY_RENDERER + Tell("RPL4VID.cpp loading .skl file "<PageCount() == 0) + { + DEBUG_STREAM << "RPL4VID.cpp couldn't load .skl file "< + inDeathZone, // DPL Zone this stuff will live in (for culling) + intersect_mode, // type of intersections to do on this object + intersect_mask); // intersection mask for the object + Register_Object(this_root); + + if(eyeRelative && entity == GetLinkedEntity()) + { + dpl_DCS* aDCS=this_root->GetDCS(); + Check_Pointer(aDCS); + Check_Pointer(dplTestEyeDCS); +// dpl_AddDCSToDCS( aDCS, dplTestEyeDCS ); + } + + // + // Process all the interesting notation file pages + // + Check(object_skeleton); + joint_counter = -1; + LinearMatrix starting_matrix(True); + dpl_LOAD_MODE dpl_load_nocache; + RecurseSKLFile( + entity, + this_root, + object_skeleton, + "ROOT", + 1, + type, + &joint_counter, + dpl_load_nocache); + // + // Close the notation file + // + Unregister_Object(object_skeleton); + delete object_skeleton; + return this_root; +} + +// +//############################################################################# +// This is the routine that will eventually process the script to create all +// the renderables necessary to get an object on the screen. For the moment it +// is just executing a hardwired script. +//############################################################################# +// +void + RPL4VideoRenderer::MakeEntityRenderables( + Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom view_type) // Type of reference (inside/outside...etc.) + +{ +#define MAX_DOS_FILENAME 15 + HierarchicalDrawComponent + *root; + // + // Make sure the callback system knows what entity is being created + // !!!! This global will be replaced later. + // + Entity_Being_Created = entity; + // + // Examine the class id of the entity and call the appropriate creation script. + // If we don't recognize the entity ID here we fall through to the inhereted + // level and let it take care of it. + // + switch(entity->GetClassID()) + { + case VTVClassID: + { + vtvCount++; + Tell("-------Creating VTV #"<GetAttributePointer("TargetReticle"); + if(vehicleReticle) + { + Tell("RPL4VideoRenderer::vehicleReticle should be hooked up\n"); + mReticle = new ReticleRenderable( + entity, // Entity to attach the renderable to + ReticleRenderable::Dynamic, // How/when to execute the renderable + &vehicleReticle, // Pointer to the reticle structure in the entity + dplMainView); // the view associated with our eye + + Register_Object(this_reticle); + } + else + { + Tell("RPL4VideoRenderer::vehicleReticle NOT hooked up\n"); + } + StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState"); + if(simulation_state) + { + Tell("RPL4VideoRenderer::translocate effect hooked up\n"); + #if DEBUG_LEVEL > 0 + POVTranslocateRenderable* translocate = + #endif + new POVTranslocateRenderable( + entity, // Entity to attach the renderable to + POVTranslocateRenderable::Watcher, // How/when to execute the renderable + true, // DPL zone the world is in + dplDeathZone, // DPL zone the player's VTV and death effect are in + root, // the parent DCS we will be offsetting from + simulation_state, // State dial we use to control the translocation + VTV::BurningState); // State that controls start/end of the effect + Register_Object(translocate); + } + else + { + Tell("RPL4VideoRenderer::translocate effect NOT hooked up\n"); + } + } + else + { + // + // Script for renderables needed for outside view of the vehicle + // + Point3D my_offset_point(0.0, 0.0, 0.0); + StateIndicator* simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState"); + if(simulation_state) + { + Tell("RPL4VideoRenderer::death effect hooked up\n"); +#if 1 + #if DEBUG_LEVEL > 0 + DPLSFXRenderable* my_death_effect = + #endif + new DPLSFXRenderable( + entity, // Entity to attach the effect to + false, // DPL zone everything will be in + my_offset_point, // Point offset from the parent DCS + root, // Parent DCS (can be NULL for world) + simulation_state, // Trigger effect when this attribute changes + VTV::BurningState, // Trigger effect when in this state + 6, // Type of effect to trigger + 0.1); // Effect repeat speed. +#else + #if DEBUG_LEVEL > 0 + DPLPSFXStateRenderable* my_death_effect = + #endif + new DPLPSFXStateRenderable( + entity, // Entity to attach the renderable to + DPLPSFXStateRenderable::Watcher, // How/when to execute the renderable + simulation_state, // Trigger effect when this state changes + VTV::BurningState, // The state to edge trigger on + myPSFXDescriptons[2], // name of file with the PFX description in it + root_DCS, // DCS the effect is relative to (may be NULL) + &my_offset_point); // Offset (or world coordinants if DCS is NULL) +#endif + Register_Object(my_death_effect); + } + else + { + Tell("RPL4VideoRenderer::death effect NOT hooked up\n"); + } + StateIndicator* collision_state = (StateIndicator *)entity->GetAttributePointer("CollisionState"); + if(simulation_state) + { + Tell("RPL4VideoRenderer::collision effects hooked up\n"); + #if DEBUG_LEVEL > 0 + DPLSFXRenderable* initial_collision_effect = + #endif + new DPLSFXRenderable( + entity, // Entity to attach the effect to + false, // DPL zone everything will be in + my_offset_point, // Point offset from the parent DCS + root, // Parent DCS (can be NULL for world) + collision_state, // Trigger effect when this attribute changes + VTV::InitialHitState, // Trigger effect when in this state + 1, // Type of effect to trigger + 0.1); // Effect repeat speed. + Register_Object(initial_collision_effect); + #if DEBUG_LEVEL > 0 + DPLSFXRenderable* scrape_collision_effect = + #endif + new DPLSFXRenderable( + entity, // Entity to attach the effect to + false, // DPL zone everything will be in + my_offset_point, // Point offset from the parent DCS + root, // Parent DCS (can be NULL for world) + collision_state, // Trigger effect when this attribute changes + VTV::SlideState, // Trigger effect when in this state + 1, // Type of effect to trigger + 0.1); // Effect repeat speed. + Register_Object(scrape_collision_effect); + } + else + { + Tell("RPL4VideoRenderer::collision effects NOT hooked up\n"); + } + } + // + // Teardown the vtv materal substitution namelists and disconnect DPL substitution handler + // + TearDownMaterialSubstitutionList(); +#if 0 + // + // Check for all players loaded + // + if((vtvCount >= vtvsExpected) && + (GetRendererStatus() == LoadingRendererStatus)) + { + Tell("Renderer Status set to running in RPL4VideoRenderer::MakeEntityRenderables\n"); + SetRendererStatusToRunning(); + } +#endif + break; + } + // + // This constructs the renderables needed for the player class + // + case CrusherClassID: + case BlockerClassID: + case RunnerClassID: + case PlayerClassID: + case RPPlayerClassID: + { + // + // We need to construct the translocate effect but only if this is a + // player on another computer. We check this by asking if this is + // a replicant instance. + // + StateIndicator* player_simulation_state = (StateIndicator *)entity->GetAttributePointer("SimulationState"); + if(entity->GetInstance() == Player::ReplicantInstance) + { + // + // Setup the translocation effect for third party view + // + Point3D* drop_zone_position = (Point3D *)entity->GetAttributePointer("DropZoneLocation"); + if(player_simulation_state && drop_zone_position) + { + Tell("third party translocate effect is hooked up\n"); + #if DEBUG_LEVEL > 0 + TranslocationRenderable *my_translocate= + #endif + new TranslocationRenderable( + entity, // Entity to attach the renderable to + TranslocationRenderable::Watcher, // How/when to execute the renderable + false, // DPL zone everything will be in + player_simulation_state, // Trigger effects off of this state dial + drop_zone_position, // Attribute that holds where the new drop will be + RPPlayer::DropZoneAcquiredState); // State that indicates drop zone is valid (starts effect) + Register_Object(my_translocate); + } + else + { + Tell("third party translocate effect NOT hooked up\n"); + } + } + else + { + if(player_simulation_state) + { + Tell("Start/end effect hooked up\n"); + #if DEBUG_LEVEL > 0 + POVStartEndRenderable* start_end = + #endif + new POVStartEndRenderable( + entity, // Entity to attach the renderable to + POVStartEndRenderable::Watcher, // How/when to execute the renderable + true, // DPL zone the world is in + dplDeathZone, // DPL zone the player's VTV and death effect are in + dplMainView, // The view containing our eye + player_simulation_state, // State dial we use to control the translocation + fogRed, // Fog color + fogGreen, + fogBlue, + fogNear, // The near fog plane + fogFar, // The far fog plane + RPPlayer::MissionStartingState, // State that signals start of mission + RPPlayer::MissionEndingState); // State that signals end of mission + Register_Object(start_end); + } + else + { + Tell("Start/end effect NOT hooked up\n"); + } + } + break; + } + // + // At the RP level we have no default method for creating objects so we call the + // next level down (l4) and let it have a try at creating the renderables. + // + default: + { + DPLRenderer::MakeEntityRenderables( + entity, // The entity we are dealing with + model_resource, // video resource for this entity + view_type); // type of reference to create !!! should be enum + break; + } + } + // + // Make sure the callback system knows what entity is being created + // !!!! This global will be replaced later. + // + Entity_Being_Created = NULL; +} +//~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ +// LoadMissionImplementation For the moment it doesn't do much, just determines +// how many players we should be expecting and sets a variable in the renderer +// about it. +// +void + RPL4VideoRenderer::LoadMissionImplementation(Mission* mission) +{ + Tell("RPL4VideoRenderer::LoadMissionImplementation has been called\n"); + // + // First call our inhereted method to make sure the division card is initialized right + // + DPLRenderer::LoadMissionImplementation(mission); +#if 0 +// +// This is a !!! HACK to figure out in advance how many VTV's to expect so we can +// setup the game state properly. +// + Mission::HostAddressIterator mission_iterator(mission); + vtvsExpected = mission_iterator.GetSize(); + // + // Check for all players loaded + // + if((vtvCount >= vtvsExpected) && + (GetRendererStatus() == LoadingRendererStatus)) + { + Tell("Renderer Status set to running in RPL4VideoRenderer::LoadMissionImplementation\n"); + SetRendererStatusToRunning(); + } +#endif +} +// +//############################################################################# +// SetupMaterialSubstitutionList This routine sets up the material substitution +// prior to loading a vehicle. +//############################################################################# +// +char + RPL4VideoRenderer::SetupMaterialSubstitutionList( + Entity* entity, + ViewFrom view_type) // The entity we will be substituting for. +{ + //STUBBED: DPL RB 1/14/07 + extern NameList + *materialSubstitutionList; + static const char + * const color_parameter = "%color%", + * const badge_parameter = "%badge%"; + static int + color_parm_len = strlen(color_parameter), + badge_parm_len = strlen(badge_parameter); + NotationFile + *veh_tbl; // vehicle table from resource file + NameList::Entry + *entry; // used to loop through namelists + const char + *egg_color, // color name in egg file (from entity) + *egg_badge, // badge name in egg file (from entity) + *veh_color, // color code from vehicle table + *veh_badge; // badge code from vehicle table + const char + *source, // tracks progress in source string + *pc; // jumps ahead of source pointer + char + *destination, // tracks progress in destination string + buffer[80]; // holds result while being constructed + int + len; // misc. length + char + *vehicleTableResource; + long + vehicleTableResourceLength; + char geometry_substitution = 'n'; + + Verify(materialSubstitutionList == NULL); + // + // Get the vehicle table out of resources. + // + ResourceDescription *res = + application->GetResourceFile()->FindResourceDescription( + "vehicletable", + ResourceDescription::VehicleTableResourceType + ); + + if (!res) + { + return(geometry_substitution); + } + Check(res); + res->Lock(); + + vehicleTableResource = (char *)res->resourceAddress; + vehicleTableResourceLength = (long)res->resourceSize; + + char + *vehicle_table = new char[vehicleTableResourceLength]; + Register_Pointer(vehicle_table); + memcpy(vehicle_table, vehicleTableResource, vehicleTableResourceLength); + + veh_tbl = new NotationFile; + Register_Object(veh_tbl); + veh_tbl->ReadText(vehicle_table, vehicleTableResourceLength); + + Unregister_Pointer(vehicle_table); + delete vehicle_table; + + res->Unlock(); + + // + // Fetch the color and badge pointers out of the entity and into our local stuff + // + egg_color = ((VTV *)entity)->vehicleColor; + egg_badge = ((VTV *)entity)->vehicleBadge; + Check_Pointer(egg_color); + Check_Pointer(egg_badge); + if (!veh_tbl->GetEntry("color", egg_color, &veh_color)) + { + veh_color = NULL; + } + + if (!veh_tbl->GetEntry("badge", egg_badge, &veh_badge)) + { + veh_badge = NULL; + } + else + { + if(view_type == insideEntity) + { + geometry_substitution = *(veh_badge + strlen(veh_badge) - 2); //ourself + } + else + { + geometry_substitution = *(veh_badge + strlen(veh_badge) - 1); //someone else + } + } + //-------------------------------------------------- + // get generic substitution list from vehicle table + //-------------------------------------------------- + materialSubstitutionList = veh_tbl->MakeEntryList("substitute"); + Register_Object(materialSubstitutionList); + //------------------------------------------------------------- + // fill in % place holders with specifics for vtv being loaded + //------------------------------------------------------------- + entry = materialSubstitutionList->GetFirstEntry(); + while (entry) + { + source = entry->GetChar(); + *(destination = buffer) = '\0'; + while ((pc = strchr(source, '%')) != NULL) + { + if ((len = pc-source) != 0) + { + strncpy(destination, source, len); + source = pc; + destination += len; + } + if (!strncmp(pc, color_parameter, color_parm_len)) + { + if (veh_color) + { + Str_Copy( + destination, + veh_color, + sizeof(buffer)-(destination-buffer) + ); + destination += strlen(veh_color); + } + source += color_parm_len; + } + else if (!strncmp(pc, badge_parameter, badge_parm_len)) + { + if (veh_badge) + { + const char + *qc = veh_badge; + + while (isgraph(*qc)) + { + ++qc; + } + if ((len = qc - veh_badge) != 0) + { + strncpy(destination, veh_badge, len); + destination += len; + } + } + source += badge_parm_len; + } + else + { + //------------------------------------- + // % was not from recognized parameter + //------------------------------------- + *destination++ = *source++; + } + } + if (*source) + { + Str_Copy( + destination, + source, + sizeof(buffer)-(destination-buffer) + ); + } + else + { + *destination = '\0'; + } + + //--------------------------------------- + // make copy of result and store in list + //--------------------------------------- + destination = new char[strlen(buffer)+1]; + Register_Pointer(destination); + strcpy(destination, buffer); + + entry->dataReference = (void *)destination; + + entry = entry->GetNextEntry(); + } + Unregister_Object(veh_tbl); + delete veh_tbl; + //dpl_SetMaterialNameCallback(substituteMaterial); + return geometry_substitution; +} +// +//############################################################################# +// TearDownMaterialSubstitutionList This routine destroys and disconnects the +// material substitution stuff after a vehicle has been loaded. +//############################################################################# +// +void + RPL4VideoRenderer::TearDownMaterialSubstitutionList() +{ + //STUBBED: DPL RB 1/14/07 + NameList::Entry + *entry; + char + *p; + + extern NameList + *materialSubstitutionList; + + if (materialSubstitutionList) + { + entry = materialSubstitutionList->GetFirstEntry(); + while (entry) + { + if ((p = entry->GetChar()) != NULL) + { + Unregister_Pointer(p); + delete p; + entry->dataReference = NULL; + } + entry = entry->GetNextEntry(); + } + Unregister_Object(materialSubstitutionList); + delete materialSubstitutionList; + materialSubstitutionList = NULL; + } + //dpl_SetMaterialNameCallback(NULL); +} +//===========================================================================// diff --git a/RP_L4/RPL4VID.h b/RP_L4/RPL4VID.h new file mode 100644 index 0000000..400a9c0 --- /dev/null +++ b/RP_L4/RPL4VID.h @@ -0,0 +1,67 @@ +#pragma once + +#include "..\munga_l4\l4video.h" + + +// RB 1/14/07 +//#include +//#include + +//########################################################################## +//########################################################################## + +class RPL4VideoRenderer: + public DPLRenderer +{ +public: + RPL4VideoRenderer( + HWND hWnd, + unsigned int screenWidth, + unsigned int screenHeight, + bool fullscreen, + InterestType interest_type, + InterestDepth depth_calibration + ); + ~RPL4VideoRenderer(); +char + SetupMaterialSubstitutionList( + Entity* entity, + ViewFrom view_type); // The entity we will be substituting for. +void + TearDownMaterialSubstitutionList(); + +protected: + int + vtvsExpected, + vtvCount; + + void + LoadMissionImplementation(Mission *mission); + + void + MakeEntityRenderables( + Entity *this_entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom type); // Type of reference (inside/outside...etc.) + + HierarchicalDrawComponent* + ReadSKLFile( + Entity *entity, // The entity we are dealing with + ResourceDescription *model_resource, // Pointer to the video resource + ViewFrom type, // type of reference to create + char skeleton_type // TEMPORARY!!!! to handle color substitutions + ); + + void + RecurseSKLFile( + Entity *entity, + HierarchicalDrawComponent *parent, + NotationFile *mech_skeleton, + const char *page_name, + int recursion_depth, + ViewFrom type, // type of reference to create !!! should be enum + int *joint_counter, + dpl_LOAD_MODE cache_mode + ); + +}; diff --git a/RP_L4/RP_L4 VS2008.vcproj b/RP_L4/RP_L4 VS2008.vcproj new file mode 100644 index 0000000..faabb9a --- /dev/null +++ b/RP_L4/RP_L4 VS2008.vcproj @@ -0,0 +1,579 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RP_L4/RP_L4.vcproj b/RP_L4/RP_L4.vcproj new file mode 100644 index 0000000..5956915 --- /dev/null +++ b/RP_L4/RP_L4.vcproj @@ -0,0 +1,589 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + diff --git a/RP_L4/TEST.EGG b/RP_L4/TEST.EGG new file mode 100644 index 0000000..d049e77 --- /dev/null +++ b/RP_L4/TEST.EGG @@ -0,0 +1,243 @@ +[mission] +adventure=Red Planet +map=burnt +scenario=race +time=day +weather=clear +temperature=0 +compression=0 +//length=600 + +[pilots] +pilot=200.0.0.117 + +[200.0.0.117] +hostType=0 +dropzone=one +name=Firestorm +bitmapindex=1 +loadzones=1 +vehicle=blkspk +; uncomment one color and one badge +//color=Aqua +color=Black +//color=Blue +//color=Green +//color=Pink +//color=Purple +//color=Red +//color=White +//color=Yellow +//badge=None +//badge=Celtic +//badge=Desert +//badge=Flames +//badge=Giraffe +//badge=Hawaii +//badge=Korean +badge=Lightning +//badge=Razzle Dazzle +//badge=Rising Sun +//badge=Tiger Stripe + +[ordinals] +bitmap=Ordinal::BitMap::1 +bitmap=Ordinal::BitMap::2 +bitmap=Ordinal::BitMap::3 +bitmap=Ordinal::BitMap::4 +[Ordinal::BitMap::1] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=000038000003C000001FF00000000F00 +bitmap=0000F8000003C000003FF80000000F00 +bitmap=0001F8000003C00000707C0000000F00 +bitmap=0001F8000003C00000603C0000000F00 +bitmap=00007801FC0FF00000003C3DF807FF00 +bitmap=00007803FE0FF00000003C3FFC0FFF00 +bitmap=00007803C703C00000003C3E3C1F0F00 +bitmap=000078078303C0000000783C1E1E0F00 +bitmap=000078078003C0000000783C1E1E0F00 +bitmap=00007807C003C0000000F03C1E1E0F00 +bitmap=00007807F003C0000001E03C1E1E0F00 +bitmap=00007803FC03C0000003C03C1E1E0F00 +bitmap=00007801FE03C0000007803C1E1E0F00 +bitmap=000078007F03C000000F003C1E1E0F00 +bitmap=000078001F03C000001E003C1E1E0F00 +bitmap=000078000F03C000003C003C1E1E0F00 +bitmap=000078060F03C0000078003C1E1E0F00 +bitmap=000078071E03E0000078003C1E1F1F00 +bitmap=00007803FE01F000007FFC3C1E0FFF00 +bitmap=00007801FC00F000007FFC3C1E07EF00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[Ordinal::BitMap::2] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=001FFF0000003C0000003C03C0780000 +bitmap=001FFF0000003C0000007C03C0780000 +bitmap=00000E0000003C000000FC03C0780000 +bitmap=00003C0000003C000001BC03C0780000 +bitmap=0000700F3E1FFC000003BC0FF07BF000 +bitmap=0001E00F7E3FFC0000073C0FF07FF800 +bitmap=0003800FFE7C3C0000063C03C07C7800 +bitmap=0007F80FFE783C00000C3C03C0783C00 +bitmap=0007FE0F80783C0000183C03C0783C00 +bitmap=00001E0F00783C0000383C03C0783C00 +bitmap=00000F0F00783C0000703C03C0783C00 +bitmap=00000F0F00783C00007FFF03C0783C00 +bitmap=00000F0F00783C00007FFF03C0783C00 +bitmap=00000F0F00783C0000003C03C0783C00 +bitmap=00000F0F00783C0000003C03C0783C00 +bitmap=00000F0F00783C0000003C03C0783C00 +bitmap=00180F0F00783C0000003C03C0783C00 +bitmap=001C1F0F007C7C0000003C03E0783C00 +bitmap=000FFE0F003FFC0000003C01F0783C00 +bitmap=0007FC0F001FBC0000003C00F0783C00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[Ordinal::BitMap::3] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=001FFF03C07800000000FC03C0780000 +bitmap=001FFF03C07800000003FC03C0780000 +bitmap=001E0003C07800000007C003C0780000 +bitmap=001E0003C0780000000F0003C0780000 +bitmap=001E000FF07BF000000F000FF07BF000 +bitmap=001E000FF07FF800001E000FF07FF800 +bitmap=001E0003C07C7800001E0003C07C7800 +bitmap=001FFC03C0783C00001EFC03C0783C00 +bitmap=001FFE03C0783C00001FFE03C0783C00 +bitmap=00001F03C0783C00001F1F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00180F03C0783C00001E0F03C0783C00 +bitmap=001C1F03E0783C00001F1F03E0783C00 +bitmap=000FFE01F0783C00000FFE01F0783C00 +bitmap=0007FC00F0783C000007FC00F0783C00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[Ordinal::BitMap::4] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=001FFF03C07800000007FC03C0780000 +bitmap=001FFF03C0780000000FFE03C0780000 +bitmap=00000F03C0780000001F1F03C0780000 +bitmap=00000F03C0780000001E0F03C0780000 +bitmap=00000F0FF07BF000001E0F0FF07BF000 +bitmap=00001F0FF07FF800001E0F0FF07FF800 +bitmap=00001E03C07C7800001E0F03C07C7800 +bitmap=00003E03C0783C00001E0F03C0783C00 +bitmap=00003C03C0783C00000F1E03C0783C00 +bitmap=00003C03C0783C000007FC03C0783C00 +bitmap=00007803C0783C000007FC03C0783C00 +bitmap=00007803C0783C00000F1E03C0783C00 +bitmap=00007803C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003E0783C00000F1E03E0783C00 +bitmap=0000F001F0783C00000FFE01F0783C00 +bitmap=0000F000F0783C000007FC00F0783C00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[largebitmap] +bitmap=BitMap::Large::Slag +[BitMap::Large::Slag] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=0000000001FC0F000000000000000000 +bitmap=0000000003FE0F000000000000000000 +bitmap=0000000007C70F000000000000000000 +bitmap=0000000007830F000000000000000000 +bitmap=0000000007800F01FF00FFE000000000 +bitmap=0000000007800F03FF81FFE000000000 +bitmap=0000000007C00F0707C3E1E000000000 +bitmap=0000000007E00F0603C3C1E000000000 +bitmap=0000000003F00F0003C3C1E000000000 +bitmap=0000000001F80F0003C3C1E000000000 +bitmap=0000000000FC0F0003C3C1E000000000 +bitmap=00000000007E0F01FFC3C1E000000000 +bitmap=00000000003F0F03FFC3C1E000000000 +bitmap=00000000001F0F07C3C3C1E000000000 +bitmap=00000000000F0F0783C3C1E000000000 +bitmap=00000000000F0F0783C3C1E000000000 +bitmap=00000000060F0F0783C3C1E000000000 +bitmap=00000000071F0F03C7C3E3E000000000 +bitmap=0000000003FE0F03FFC1FFE000000000 +bitmap=0000000001FC0F00FBC0FDE000000000 +bitmap=0000000000000000000001E000000000 +bitmap=0000000000000000000001E000000000 +bitmap=0000000000000000000301E000000000 +bitmap=0000000000000000000383E000000000 +bitmap=00000000000000000001FFC000000000 +bitmap=00000000000000000000FF8000000000 +x=128 +y=32 +width=8 +[smallbitmap] +bitmap=BitMap::Small::Slag +[BitMap::Small::Slag] +bitmap=00000000000000000000000000000000 +bitmap=000000000000000000001E3000000000 +bitmap=000031300000000000003031F0FC0000 +bitmap=00003832198C000000001C30198C0000 +bitmap=00000E31F98C000000000733198C0000 +bitmap=00000333198C000000002333198C0000 +bitmap=00001E31F8FC000000000000000C0000 +bitmap=00000000010C00000000000000F80000 +x=64 +y=16 +width=4 diff --git a/RP_L4/WTPresets.cpp b/RP_L4/WTPresets.cpp new file mode 100644 index 0000000..d5e01ae --- /dev/null +++ b/RP_L4/WTPresets.cpp @@ -0,0 +1,2812 @@ +#include "..\munga_l4\L4AUDLVL.h" + +#pragma warning ( disable : 4482) + +PRESETINFO allPresets[2][100] = +{ + //BANK 1 + { + //EngineDroneInt01 + //BANK 1 PRESET 0 + { + 2, + { + {-1, 1, "EngineDroneInt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "EngineDroneInt01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //EngineThrustInt01 + //BANK 1 PRESET 1 + { + 1, + { + {-1, 1, "EngineThrustInt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //EngineDroneInt02 + //BANK 1 PRESET 2 + { + 2, + { + {-1, 1, "EngineDroneInt02.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::LoopAtWill}, + {-1, 1, "EngineDroneInt02a.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //EngineThrustInt02 + //BANK 1 PRESET 3 + { + 3, + { + {-1, 1, "EngineThrustInt02.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::LoopAtWill}, + {-1, 1, "EngineThrustInt02a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::LoopAtWill}, + {-1, 1, "EngineThrustInt02b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //EngineDroneExt01 + //BANK 1 PRESET 4 + { + 2, + { + {-1, 1, "EngineDroneExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "EngineDroneExt01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //EngineThrustExt01 + //BANK 1 PRESET 5 + { + 1, + { + {-1, 1, "EngineThrustExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //EngineComboExt01 + //BANK 1 PRESET 6 + { + 3, + { + {-1, 1, "EngineComboExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "EngineComboExt01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "EngineComboExt01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CockpitWindDrone01 + //BANK 1 PRESET 7 + { + 1, + { + {-1, 1, "CockpitWindDrone01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CockpitWindRush01 + //BANK 1 PRESET 8 + { + 1, + { + {-1, 1, "CockpitWindRush01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //BoosterInt01 + //BANK 1 PRESET 9 + { + 3, + { + {-1, 1, "BoosterInt01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //BoosterInt02 + //BANK 1 PRESET 10 + { + 3, + { + {-1, 1, "BoosterInt02.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt02a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt02b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //BoosterInt03 + //BANK 1 PRESET 11 + { + 3, + { + {-1, 1, "BoosterInt03.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt03a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt03b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //BoosterInt04 + //BANK 1 PRESET 12 + { + 3, + { + {-1, 1, "BoosterInt04.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt04a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 1, "BoosterInt04b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //BoosterExt01 + //BANK 1 PRESET 13 + { + 1, + { + {-1, 1, "BoosterExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt01 + //BANK 1 PRESET 14 + { + 1, + { + {-1, 1, "CollisionInt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt02 + //BANK 1 PRESET 15 + { + 1, + { + {-1, 1, "CollisionInt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt03 + //BANK 1 PRESET 16 + { + 1, + { + {-1, 1, "CollisionInt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt04 + //BANK 1 PRESET 17 + { + 1, + { + {-1, 1, "CollisionInt04.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt05 + //BANK 1 PRESET 18 + { + 1, + { + {-1, 1, "CollisionInt05.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt06 + //BANK 1 PRESET 19 + { + 1, + { + {-1, 1, "CollisionInt06.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt07 + //BANK 1 PRESET 20 + { + 1, + { + {-1, 1, "CollisionInt07.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt08 + //BANK 1 PRESET 21 + { + 1, + { + {-1, 1, "CollisionInt08.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt09 + //BANK 1 PRESET 22 + { + 1, + { + {-1, 1, "CollisionInt09.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt10 + //BANK 1 PRESET 23 + { + 1, + { + {-1, 1, "CollisionInt10.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt11 + //BANK 1 PRESET 24 + { + 1, + { + {-1, 1, "CollisionInt11.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt12 + //BANK 1 PRESET 25 + { + 1, + { + {-1, 1, "CollisionInt12.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt13 + //BANK 1 PRESET 26 + { + 1, + { + {-1, 1, "CollisionInt13.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt14 + //BANK 1 PRESET 27 + { + 1, + { + {-1, 1, "CollisionInt14.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt15 + //BANK 1 PRESET 28 + { + 1, + { + {-1, 1, "CollisionInt15.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt16 + //BANK 1 PRESET 29 + { + 1, + { + {-1, 1, "CollisionInt16.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt17 + //BANK 1 PRESET 30 + { + 1, + { + {-1, 1, "CollisionInt17.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt18 + //BANK 1 PRESET 31 + { + 1, + { + {-1, 1, "CollisionInt18.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt19 + //BANK 1 PRESET 32 + { + 1, + { + {-1, 1, "CollisionInt19.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionInt20 + //BANK 1 PRESET 33 + { + 1, + { + {-1, 1, "CollisionInt20.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt01 + //BANK 1 PRESET 34 + { + 1, + { + {-1, 1, "CollisionExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt02 + //BANK 1 PRESET 35 + { + 1, + { + {-1, 1, "CollisionExt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt03 + //BANK 1 PRESET 36 + { + 1, + { + {-1, 1, "CollisionExt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt04 + //BANK 1 PRESET 37 + { + 1, + { + {-1, 1, "CollisionExt04.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt05 + //BANK 1 PRESET 38 + { + 1, + { + {-1, 1, "CollisionExt05.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt06 + //BANK 1 PRESET 39 + { + 1, + { + {-1, 1, "CollisionExt06.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt07 + //BANK 1 PRESET 40 + { + 1, + { + {-1, 1, "CollisionExt07.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt08 + //BANK 1 PRESET 41 + { + 1, + { + {-1, 1, "CollisionExt08.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt09 + //BANK 1 PRESET 42 + { + 1, + { + {-1, 1, "CollisionExt09.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //CollisionExt10 + //BANK 1 PRESET 43 + { + 1, + { + {-1, 1, "CollisionExt10.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ScrapeInt01 + //BANK 1 PRESET 44 + { + 1, + { + {-1, 1, "ScrapeInt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DeathInt01 + //BANK 1 PRESET 45 + { + 3, + { + {-1, 1, "DeathInt01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::LoopAtWill}, + {-1, 1, "DeathInt01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::LoopAtWill}, + {-1, 1, "DeathInt01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DeathInt02 + //BANK 1 PRESET 46 + { + 1, + { + {-1, 1, "DeathInt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DeathExt01 + //BANK 1 PRESET 47 + { + 1, + { + {-1, 1, "DeathExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 48 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 49 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Horn01 + //BANK 1 PRESET 50 + { + 2, + { + {-1, 1, "Horn01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 1, "Horn01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAlways}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Chute01 + //BANK 1 PRESET 51 + { + 1, + { + {-1, 1, "Chute01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ReverseThrust01 + //BANK 1 PRESET 52 + { + 2, + { + {-1, 1, "ReverseThrust01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "ReverseThrust01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ReverseThrust02 + //BANK 1 PRESET 53 + { + 2, + { + {-1, 1, "ReverseThrust02.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "ReverseThrust02a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LiftCut01 + //BANK 1 PRESET 54 + { + 3, + { + {-1, 1, "LiftCut01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "LiftCut01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 1, "LiftCut01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ViewSwitchLeft01 + //BANK 1 PRESET 55 + { + 1, + { + {-1, 1, "ViewSwitchLeft01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ViewSwitchRight01 + //BANK 1 PRESET 56 + { + 1, + { + {-1, 1, "ViewSwitchRight01.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ViewSwitchCenter01 + //BANK 1 PRESET 57 + { + 1, + { + {-1, 1, "ViewSwitchCenter01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ModeSwitch01 + //BANK 1 PRESET 58 + { + 1, + { + {-1, 1, "ModeSwitch01.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ConfigSwitch01 + //BANK 1 PRESET 59 + { + 1, + { + {-1, 1, "ConfigSwitch01.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //PresetSwitch + //BANK 1 PRESET 60 + { + 2, + { + {-1, 1, "PresetSwitch01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "PresetSwitch01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //HVAC01 + //BANK 1 PRESET 61 + { + 2, + { + {-1, 1, "HVAC01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "HVAC01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //HVAC02 + //BANK 1 PRESET 62 + { + 2, + { + {-1, 1, "HVAC02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "HVAC02a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //BoosterLoopInt01 + //BANK 1 PRESET 63 + { + 2, + { + {-1, 1, "BoosterLoopInt01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::LoopAtWill}, + {-1, 1, "BoosterLoopInt01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //BoosterLoopExt01 + //BANK 1 PRESET 64 + { + 2, + { + {-1, 1, "BoosterLoopExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "BoosterLoopExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //HVAC03 + //BANK 1 PRESET 65 + { + 3, + { + {-1, 1, "HVAC03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "HVAC03a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "HVAC03b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ScoreKill01 + //BANK 1 PRESET 66 + { + 2, + { + {-1, 1, "ScoreKill06.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "ScoreKill06a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //ScoreZone01 + //BANK 1 PRESET 67 + { + 2, + { + {-1, 1, "ScoreZone15.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "ScoreZone15a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RadarButton01 + //BANK 1 PRESET 68 + { + 3, + { + {-1, 1, "RadarButton01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "RadarButton01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 1, "RadarButton01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 69 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 70 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 71 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 72 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 73 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 74 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 75 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 76 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 77 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 78 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 79 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 80 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 81 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 82 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 83 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 84 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 85 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 86 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 87 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 88 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 89 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 90 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 91 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 92 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 93 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 94 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 95 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 96 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 97 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 98 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 1 PRESET 99 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + } + }, + + //BANK 2 + { + //DoorOpen01 + //BANK 2 PRESET 0 + { + 1, + { + {-1, 1, "DoorOpen01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DoorOpen02 + //BANK 2 PRESET 1 + { + 1, + { + {-1, 1, "DoorOpen02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DoorClose01 + //BANK 2 PRESET 2 + { + 1, + { + {-1, 1, "DoorClose01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DoorClose02 + //BANK 2 PRESET 3 + { + 1, + { + {-1, 1, "DoorClose02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DoorMove01 + //BANK 2 PRESET 4 + { + 1, + { + {-1, 1, "DoorMove01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //DoorMove02 + //BANK 2 PRESET 5 + { + 1, + { + {-1, 1, "DoorMove02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //WellheadDrill01 + //BANK 2 PRESET 6 + { + 4, + { + {-1, 1, "WellheadDrill01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "WellheadDrill01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "WellheadDrill01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "WellheadDrill01c.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //WellheadDrill02 + //BANK 2 PRESET 7 + { + 3, + { + {-1, 1, "WellheadDrill02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "WellheadDrill02a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "WellheadDrill02b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //OreDrop01 + //BANK 2 PRESET 8 + { + 1, + { + {-1, 1, "OreDrop01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //OreDrop02 + //BANK 2 PRESET 9 + { + 1, + { + {-1, 1, "OreDrop02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //OreDrop03 + //BANK 2 PRESET 10 + { + 1, + { + {-1, 1, "OreDrop03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //MaintPulse01 + //BANK 2 PRESET 11 + { + 2, + { + {-1, 1, "MaintPulse01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "MaintPulse01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //MaintDrone01 + //BANK 2 PRESET 12 + { + 1, + { + {-1, 1, "MaintDrone01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //GeneratorSpin01 + //BANK 2 PRESET 13 + { + 2, + { + {-1, 1, "GeneratorSpin01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "GeneratorSpin01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //GeneratorDrone01 + //BANK 2 PRESET 14 + { + 1, + { + {-1, 1, "GeneratorDrone01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Generator01 + //BANK 2 PRESET 15 + { + 2, + { + {-1, 1, "Generator01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Generator01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Generator02 + //BANK 2 PRESET 16 + { + 1, + { + {-1, 1, "Generator02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //FuelTank01 + //BANK 2 PRESET 17 + { + 1, + { + {-1, 1, "FuelTank01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //FuelTank02 + //BANK 2 PRESET 18 + { + 1, + { + {-1, 1, "FuelTank02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //PipeMachine01 + //BANK 2 PRESET 19 + { + 2, + { + {-1, 1, "PipeMachine01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "PipeMachine01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //FlameMachine01 + //BANK 2 PRESET 20 + { + 2, + { + {-1, 1, "FlameMachine01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "FlameMachine01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Refinery01 + //BANK 2 PRESET 21 + { + 3, + { + {-1, 1, "Refinery01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Refinery02 + //BANK 2 PRESET 22 + { + 1, + { + {-1, 1, "Refinery02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery02a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "Refinery02b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Refinery03 + //BANK 2 PRESET 23 + { + 1, + { + {-1, 1, "Refinery03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery03a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery03b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Refinery04 + //BANK 2 PRESET 24 + { + 2, + { + {-1, 1, "Refinery04.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery04a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Refinery05 + //BANK 2 PRESET 25 + { + 2, + { + {-1, 1, "Refinery05.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery05a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Refinery06 + //BANK 2 PRESET 26 + { + 3, + { + {-1, 1, "Refinery06.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery06a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery06b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Refinery07 + //BANK 2 PRESET 27 + { + 3, + { + {-1, 1, "Refinery07.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery07a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "Refinery07b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //PipeMachine02 + //BANK 2 PRESET 28 + { + 4, + { + {-1, 1, "PipeMachine02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "PipeMachine02a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "PipeMachine02b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "PipeMachine02c.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //TRANSLOCATION01 + //BANK 2 PRESET 29 + { + 2, + { + {-1, 1, "Translocation01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "Translocation01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //Translocation02 + //BANK 2 PRESET 30 + { + 2, + { + {-1, 1, "Translocation02.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "Translocation02a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //TranslocationExt01 + //BANK 2 PRESET 31 + { + 2, + { + {-1, 1, "TranslocationExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 1, "TranslocationExt01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //WellheadDevice01 + //BANK 2 PRESET 32 + { + 3, + { + {-1, 1, "WellheadDevice01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "WellheadDevice01a.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 1, "WellheadDevice01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 33 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 34 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 35 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 36 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 37 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 38 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 39 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 40 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 41 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 42 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 43 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 44 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //MineRelease01 + //BANK 2 PRESET 45 + { + 3, + { + {-1, 1, "MineRelease01.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 1, "MineRelease01a.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 1, "MineRelease01b.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //MineCoast01 + //BANK 2 PRESET 46 + { + 1, + { + {-1, 1, "MineCoast01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //MineExplode01 + //BANK 2 PRESET 47 + { + 1, + { + {-1, 1, "MineExplode01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetEmpty01 + //BANK 2 PRESET 48 + { + 1, + { + {-1, 1, "RivetEmpty01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetFireLeft + //BANK 2 PRESET 49 + { + 1, + { + {-1, 1, "RivetFireLeft.wav", SampleChannel::CHANNEL_LEFT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetFireRight + //BANK 2 PRESET 50 + { + 1, + { + {-1, 1, "RivetFireRight.wav", SampleChannel::CHANNEL_RIGHT, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetFireCenter + //BANK 2 PRESET 51 + { + 1, + { + {-1, 1, "RivetFireCenter.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetTravel01 + //BANK 2 PRESET 52 + { + 1, + { + {-1, 1, "RivetTravel01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitInt01 + //BANK 2 PRESET 53 + { + 1, + { + {-1, 1, "RivetHitInt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitInt02 + //BANK 2 PRESET 54 + { + 1, + { + {-1, 1, "RivetHitInt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitInt03 + //BANK 2 PRESET 55 + { + 1, + { + {-1, 1, "RivetHitInt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitCraft01 + //BANK 2 PRESET 56 + { + 1, + { + {-1, 1, "RivetHitCraft01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitCraft02 + //BANK 2 PRESET 57 + { + 1, + { + {-1, 1, "RivetHitCraft02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitCraft03 + //BANK 2 PRESET 58 + { + 1, + { + {-1, 1, "RivetHitCraft03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitExt01 + //BANK 2 PRESET 59 + { + 1, + { + {-1, 1, "RivetHitExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitExt02 + //BANK 2 PRESET 60 + { + 1, + { + {-1, 1, "RivetHitExt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitExt03 + //BANK 2 PRESET 61 + { + 1, + { + {-1, 1, "RivetHitExt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitExt04 + //BANK 2 PRESET 62 + { + 1, + { + {-1, 1, "RivetHitExt04.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //RivetHitExt05 + //BANK 2 PRESET 63 + { + 1, + { + {-1, 1, "RivetHitExt05.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt01 + //BANK 2 PRESET 64 + { + 1, + { + {-1, 1, "LaserFireInt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt02 + //BANK 2 PRESET 65 + { + 1, + { + {-1, 1, "LaserFireInt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt03 + //BANK 2 PRESET 66 + { + 1, + { + {-1, 1, "LaserFireInt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt04 + //BANK 2 PRESET 67 + { + 1, + { + {-1, 1, "LaserFireInt04.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt05 + //BANK 2 PRESET 68 + { + 1, + { + {-1, 1, "LaserFireInt05.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt06 + //BANK 2 PRESET 69 + { + 1, + { + {-1, 1, "LaserFireInt06.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt07 + //BANK 2 PRESET 70 + { + 1, + { + {-1, 1, "LaserFireInt07.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt08 + //BANK 2 PRESET 71 + { + 1, + { + {-1, 1, "LaserFireInt08.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt09 + //BANK 2 PRESET 72 + { + 1, + { + {-1, 1, "LaserFireInt09.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt10 + //BANK 2 PRESET 73 + { + 1, + { + {-1, 1, "LaserFireInt10.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt11 + //BANK 2 PRESET 74 + { + 1, + { + {-1, 1, "LaserFireInt11.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt12 + //BANK 2 PRESET 75 + { + 1, + { + {-1, 1, "LaserFireInt12.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt13 + //BANK 2 PRESET 76 + { + 1, + { + {-1, 1, "LaserFireInt13.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireInt14 + //BANK 2 PRESET 77 + { + 1, + { + {-1, 1, "LaserFireInt14.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireIntEmpty + //BANK 2 PRESET 78 + { + 1, + { + {-1, 1, "LaserFireIntEmpty.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt01 + //BANK 2 PRESET 79 + { + 1, + { + {-1, 1, "LaserFireExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt02 + //BANK 2 PRESET 80 + { + 1, + { + {-1, 1, "LaserFireExt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt03 + //BANK 2 PRESET 81 + { + 1, + { + {-1, 1, "LaserFireExt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt04 + //BANK 2 PRESET 82 + { + 1, + { + {-1, 1, "LaserFireExt04.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt05 + //BANK 2 PRESET 83 + { + 1, + { + {-1, 1, "LaserFireExt05.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt06 + //BANK 2 PRESET 84 + { + 1, + { + {-1, 1, "LaserFireExt06.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt07 + //BANK 2 PRESET 85 + { + 1, + { + {-1, 1, "LaserFireExt07.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt08 + //BANK 2 PRESET 86 + { + 1, + { + {-1, 1, "LaserFireExt08.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt09 + //BANK 2 PRESET 87 + { + 1, + { + {-1, 1, "LaserFireExt09.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserFireExt10 + //BANK 2 PRESET 88 + { + 1, + { + {-1, 1, "LaserFireExt10.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitExt01 + //BANK 2 PRESET 89 + { + 1, + { + {-1, 1, "LaserHitExt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitExt02 + //BANK 2 PRESET 90 + { + 1, + { + {-1, 1, "LaserHitExt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitExt03 + //BANK 2 PRESET 91 + { + 1, + { + {-1, 1, "LaserHitExt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitExt04 + //BANK 2 PRESET 92 + { + 1, + { + {-1, 1, "LaserHitExt04.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitInt01 + //BANK 2 PRESET 93 + { + 1, + { + {-1, 1, "LaserHitInt01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitInt02 + //BANK 2 PRESET 94 + { + 1, + { + {-1, 1, "LaserHitInt02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitInt03 + //BANK 2 PRESET 95 + { + 1, + { + {-1, 1, "LaserHitInt03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitCraft01 + //BANK 2 PRESET 96 + { + 1, + { + {-1, 1, "LaserHitCraft01.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitCraft02 + //BANK 2 PRESET 97 + { + 1, + { + {-1, 1, "LaserHitCraft02.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //LaserHitCraft03 + //BANK 2 PRESET 98 + { + 1, + { + {-1, 1, "LaserHitCraft03.wav", SampleChannel::CHANNEL_CENTER, SampleLoop::ForceStatic}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + }, + + //UNIMPLEMENTED + //BANK 2 PRESET 99 + { + 0, + { + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + {-1, 0, "", SampleChannel::CHANNEL_CENTER, SampleLoop::LoopAtWill}, + }, + 0 + } + } + }; \ No newline at end of file diff --git a/RP_L4/WTPresets.h b/RP_L4/WTPresets.h new file mode 100644 index 0000000..96daa8f --- /dev/null +++ b/RP_L4/WTPresets.h @@ -0,0 +1 @@ +void setupPresets(); \ No newline at end of file diff --git a/RP_L4/last.egg b/RP_L4/last.egg new file mode 100644 index 0000000..011c766 --- /dev/null +++ b/RP_L4/last.egg @@ -0,0 +1,224 @@ +[mission] +adventure=Red Planet +map=wise +scenario=race +time=day +weather=clear +temperature=0 +compression=0 +length=600 + +[pilots] +pilot=127.0.0.1 + +[127.0.0.1] +hostType=0 +dropzone=one +name=Test +bitmapindex=1 +loadzones=1 +vehicle=puck +color=Aqua +badge=Celtic + +[ordinals] +bitmap=Ordinal::BitMap::1 +bitmap=Ordinal::BitMap::2 +bitmap=Ordinal::BitMap::3 +bitmap=Ordinal::BitMap::4 +[Ordinal::BitMap::1] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=000038000003C000001FF00000000F00 +bitmap=0000F8000003C000003FF80000000F00 +bitmap=0001F8000003C00000707C0000000F00 +bitmap=0001F8000003C00000603C0000000F00 +bitmap=00007801FC0FF00000003C3DF807FF00 +bitmap=00007803FE0FF00000003C3FFC0FFF00 +bitmap=00007803C703C00000003C3E3C1F0F00 +bitmap=000078078303C0000000783C1E1E0F00 +bitmap=000078078003C0000000783C1E1E0F00 +bitmap=00007807C003C0000000F03C1E1E0F00 +bitmap=00007807F003C0000001E03C1E1E0F00 +bitmap=00007803FC03C0000003C03C1E1E0F00 +bitmap=00007801FE03C0000007803C1E1E0F00 +bitmap=000078007F03C000000F003C1E1E0F00 +bitmap=000078001F03C000001E003C1E1E0F00 +bitmap=000078000F03C000003C003C1E1E0F00 +bitmap=000078060F03C0000078003C1E1E0F00 +bitmap=000078071E03E0000078003C1E1F1F00 +bitmap=00007803FE01F000007FFC3C1E0FFF00 +bitmap=00007801FC00F000007FFC3C1E07EF00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[Ordinal::BitMap::2] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=001FFF0000003C0000003C03C0780000 +bitmap=001FFF0000003C0000007C03C0780000 +bitmap=00000E0000003C000000FC03C0780000 +bitmap=00003C0000003C000001BC03C0780000 +bitmap=0000700F3E1FFC000003BC0FF07BF000 +bitmap=0001E00F7E3FFC0000073C0FF07FF800 +bitmap=0003800FFE7C3C0000063C03C07C7800 +bitmap=0007F80FFE783C00000C3C03C0783C00 +bitmap=0007FE0F80783C0000183C03C0783C00 +bitmap=00001E0F00783C0000383C03C0783C00 +bitmap=00000F0F00783C0000703C03C0783C00 +bitmap=00000F0F00783C00007FFF03C0783C00 +bitmap=00000F0F00783C00007FFF03C0783C00 +bitmap=00000F0F00783C0000003C03C0783C00 +bitmap=00000F0F00783C0000003C03C0783C00 +bitmap=00000F0F00783C0000003C03C0783C00 +bitmap=00180F0F00783C0000003C03C0783C00 +bitmap=001C1F0F007C7C0000003C03E0783C00 +bitmap=000FFE0F003FFC0000003C01F0783C00 +bitmap=0007FC0F001FBC0000003C00F0783C00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[Ordinal::BitMap::3] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=001FFF03C07800000000FC03C0780000 +bitmap=001FFF03C07800000003FC03C0780000 +bitmap=001E0003C07800000007C003C0780000 +bitmap=001E0003C0780000000F0003C0780000 +bitmap=001E000FF07BF000000F000FF07BF000 +bitmap=001E000FF07FF800001E000FF07FF800 +bitmap=001E0003C07C7800001E0003C07C7800 +bitmap=001FFC03C0783C00001EFC03C0783C00 +bitmap=001FFE03C0783C00001FFE03C0783C00 +bitmap=00001F03C0783C00001F1F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00000F03C0783C00001E0F03C0783C00 +bitmap=00180F03C0783C00001E0F03C0783C00 +bitmap=001C1F03E0783C00001F1F03E0783C00 +bitmap=000FFE01F0783C00000FFE01F0783C00 +bitmap=0007FC00F0783C000007FC00F0783C00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[Ordinal::BitMap::4] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=001FFF03C07800000007FC03C0780000 +bitmap=001FFF03C0780000000FFE03C0780000 +bitmap=00000F03C0780000001F1F03C0780000 +bitmap=00000F03C0780000001E0F03C0780000 +bitmap=00000F0FF07BF000001E0F0FF07BF000 +bitmap=00001F0FF07FF800001E0F0FF07FF800 +bitmap=00001E03C07C7800001E0F03C07C7800 +bitmap=00003E03C0783C00001E0F03C0783C00 +bitmap=00003C03C0783C00000F1E03C0783C00 +bitmap=00003C03C0783C000007FC03C0783C00 +bitmap=00007803C0783C000007FC03C0783C00 +bitmap=00007803C0783C00000F1E03C0783C00 +bitmap=00007803C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003C0783C00001E0F03C0783C00 +bitmap=0000F003E0783C00000F1E03E0783C00 +bitmap=0000F001F0783C00000FFE01F0783C00 +bitmap=0000F000F0783C000007FC00F0783C00 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[largebitmap] +bitmap=BitMap::Large::Test +[BitMap::Large::Test] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=000000000001FF000000000000000000 +bitmap=000000000001FF00000E000000000000 +bitmap=000000000001FF00000E000000000000 +bitmap=0000000000003800000E000000000000 +bitmap=000000000000381F0FBF800000000000 +bitmap=000000000000383F9FBF800000000000 +bitmap=000000000000387F9FBF800000000000 +bitmap=000000000000387B9C0E000000000000 +bitmap=00000000000038770F0E000000000000 +bitmap=000000000000387E078E000000000000 +bitmap=000000000000383F9F8E000000000000 +bitmap=000000000000381F1F0E000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=128 +y=32 +width=8 +[smallbitmap] +bitmap=BitMap::Small::Test +[BitMap::Small::Test] +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +bitmap=000007F0008000000000008000800000 +bitmap=000000871DC0000000000088A0800000 +bitmap=00000089108000000000008E08800000 +bitmap=00000088848000000000008738800000 +bitmap=00000000000000000000000000000000 +bitmap=00000000000000000000000000000000 +x=64 +y=16 +width=4 diff --git a/Setup1/Setup1.vdproj b/Setup1/Setup1.vdproj new file mode 100644 index 0000000..e22269b --- /dev/null +++ b/Setup1/Setup1.vdproj @@ -0,0 +1,16493 @@ +"DeployProject" +{ +"VSVersion" = "3:800" +"ProjectType" = "8:{978C614F-708E-4E1A-B201-565925725DBA}" +"IsWebType" = "8:FALSE" +"ProjectName" = "8:Setup1" +"LanguageId" = "3:1033" +"CodePage" = "3:1252" +"UILanguageId" = "3:1033" +"SccProjectName" = "8:" +"SccLocalPath" = "8:" +"SccAuxPath" = "8:" +"SccProvider" = "8:" + "Hierarchy" + { + "Entry" + { + "MsmKey" = "8:_006D0CB7C44B43B798CA2772E2D2ACCB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_00AFABA3E51149F89AED555CB335E2CE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_00C248D38C8D484FB89622FE13931E8F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_00CA668011F147C58782B627CCCC2AC8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_00FDBE51B26446EFAB7D3183AF3327A5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_01C5A6F0978A4D9B8D2185E2E475D506" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_02870A86502F4D9EB068899650070458" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_02EDCCC9584546B583846D9F5ED0E5BB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0345D734DDBD415EA3076FB739003255" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_036C8E0FCE354F389BC9AB2ECC872E74" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_03A9A4FA04A24D418047148EE3B74049" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_03E4CA8894E941579A748A4A4715E699" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_043979313DF14D52866537FD44923E8B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_04C5C478AA8044229D001AD638515589" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_06459C02D35F43B9A29BBAEEC6EE2EFC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_06E128E1518040A99BC839FC7B7433E3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_072FFBD40A8965475CB7060B4105091E" + "OwnerKey" = "8:_F416462836FD4AC3AA39054F791C8C0F" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0792B0B236A84AA8A2D56CDE810B350F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_07EDCC32C132464295B014760030CD84" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_080480B007DE475CBB728032FAE640D2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_092F0B45BA26494E92837A7C562DA87F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_094AE63D45C84E88A1CE3C99152AB251" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0A7E2D812CD3467B99F4F0EA94FDF3AB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0B4A14142A2C47C2A5B44A9980004C6F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0BB9BC33DE4A4A3ABEFF1FF51F3EA299" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0D781C62646A461EA9C3FA55EAC488A6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0DBA1B6BCC064FEAB341925D1183A61C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0E001D162572440C9B5C5DA850C08EB2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0E4B15B9CBAE45B1B68155818D854A0E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0E689AE216DD40758597D0611B062C7A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0F3C0F2D95374BC1A33332EA2B57F9CB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0F40BC85ACD247C2970EE8D5B5AD08FD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0FA9870A7E9446CBB43229A6EF00647C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0FB4B38CE93243EF8E30001AC222048D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_0FF9B67FB5314C57A903F7A99C2392CD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_10A8931C6AD7417594655B3977C9C8C2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_116A12105DF1493ABC28469B9D3A773E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1171F8E1A69D45C1810935B43D085724" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_11A19D284C8A4BA59C4E859EA6BB3B1B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_11B93AEFB9D44251B41C9C9C11AD0556" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_11E0A799554F438197382DF84807F631" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_126BA75870A24007A092DA073A408CCE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_128922AB01D44A73A1F22C4314A4F3FF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1392BE3CEE7041799D64408A4AD1C1D3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_143C153D96DA4CB0A5578C7AFF8211FF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_143DA4188BBE4EB09130F42B99B7CD1E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_143F2B995BB449E0874B8F4C2217AB58" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_15439D0009DA4EBAAB1C805C371895A0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_15B83B0F1E2146D7AF7E7375246C34A2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_16B6EF840C8E43EC8800AD1FF9DB57C4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_178A813081464D1C9284C8CF7194CD9E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_19268E74339E4757825B1C63C32FA33F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1987C7D6CB3040B6B5A401925CA37C54" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_19B55F1CA06A40EC917B552669F441C0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1A0FA2D099924E8A8F9C9AFA8FB47D86" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1A2A4B2451074200ABDFD3048AE2401F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1C525205D5B943588870B82F7961B2CF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1C733072D2F24B3094BD457F14674F5B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1C84C74BC18549118D74405F6E4C119B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1C99C21D9F9A4937A3CB8BBDB58251C2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1DA0F136251F4096B33EC8DEC56C78D7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1E365D6C2FF24597AD10F59BB6EB7DCF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1EBE36BC5BF5488BB8F69B28FB8741C8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1F015CD0D057499D972F7E960D8212BE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1F52E572D32F4622822CF87C9C8E84A0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1F9CB773A6D94A748CD1AD751E8CBE1D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_1FB9EB0096494166AD3D017764675DB3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2019F4F23B2247CD85822D2186795829" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_201BFDF7D7964B9C8E7BBAE836E51424" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_209E78F0C95B4DD68225C8F204C66F63" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_217105B95549461C8DABF8B3F3C80743" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_21AA256F588A46D9874DCB5C87EA79D9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_21BDB5950F5346779F5C2E2940C31BAC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_22984E40249D4F22A813BE8417ED63CB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_22A730FC69FC4D49BEC9315EC6CB68BE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_22CA4E62EDA641A6897035CA69482BAF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_23D38693F008456DB52B852FD7836817" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_24498092FB2A4922B6055DCA3D526AF4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_249348076F7B44F4BA6DB529D4DB49EA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_25162A21B2984F22B6140750F559F1F2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_26E2087DDCF64F3B806F3748EBE86FBD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_271567CA5E9348CBA04629311EDBDF0A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_285D7B3EE3AC4F738F31F51EBE9F026E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_28FED9DC78954D50A0342D8DEFA3F64F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_290356E6DECB4F779D8481737AB7CD66" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_29061B419EF243E0B7AC31F44274CCCF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2948255E740D4E719A528D98C8EFCD99" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_296D55BC12174FF5B97A9E8D18618A5E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_29796736028948E8A9298DAAF308858E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_29C063D1011E45D9AB825AF328C53BD0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_29D30C0540B841168886069C96567B09" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_29E9901A650C4FD1BB43CAFEE5B2B076" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2A4C99FAACEC4920AEA5B40FCD9B2B10" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2A6EC34FE4F246BB9C52BA975E51FE52" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2AD83F6CECD74D02BA5346E3FE7FC003" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2AEC7A12575C4D67882A40F90E1F980A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2B59BF040DCE41939321C1D427B79A61" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2B935410B1A54514813A79E7CE71F46D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2C04F060B6324D29BD0D34D68F97D298" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2C1F1CBF0C8E48CA93654FD0B2BB8F2E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2C3EBC784EEF40D2916538C700E8547D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2C7E1E2B8F2C4421B95444CFD6CFD932" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2C8F6F91FF1743DC8C83A332A7D70513" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2CFD94DFFC8E4E5A955C649AE2875ACD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2D601A6EAAE340C5B6F4B1B0C8D2EB6E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2D6EB0D9015E4873BEFF10FBB6354D1D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2DBCE7E0F46840A3BE99BCC9869D8653" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2E939C1B263E4DCEB8799364D4A6F00F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2F1D500F25BF4498AC303F95EA03EAE9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2F1FE157916C4781B69267D241AA03CB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_2F4F66331E4545C5A7B326310ABB4973" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_303909735C104EE5B01EBEDBCBE8F2DB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3040C877B1B846CE9F718D2BFDDC8D40" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_308185542B5A40A495D83ECFCAAC5965" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_31DC0BC9F57042E9AB2920884BCB798F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_31DE26777AAE4F38B360C949C3FE5443" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_333F431A29C2428282D6DD0FF26A06D9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_33B0A36FA4BB44FCAEC8B987EBB172B1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_34021C57D1FF40778712AD45A10A29BA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3422379FACC1485DB4C9B689EB6FAD7C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_342E65E4F2D749178DF5C1ED6DFABAF1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_34538B8814974577A1F2304C0338A974" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_35F51E5D2EF24A88A386A9984DF29A63" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_361D1DB44378456D8FC8774F1693AEF2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_364707B4C4A24C0E8BB64A207AF1CC69" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_369E37FEE35D406A8FFC035A87CFD747" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_36B7CA1D6217460BA9FE102004C6516E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_36DB8DEF07A3491FAD929B4101AC6C36" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_37C26A3A698246CAABF6E240F41E2FFA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3802BE7A611045068B7BB90FA2055124" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3830B1418F2E45318DE8638EF323B3A8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_38A695B9531D4688BBADD6F78F3D28E7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3924AEA054C04B9789D89AE92C937CB8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3953C4B1EC0740DD894183182B39AA50" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3964C8969A2A40BD9056BA2304BF7DF6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3991C8DA9B7846C79943472002CDFA0D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3A81CAACC0414FE693DC4DDF53481CDE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3B02CA36C18B4ECFA52ED2F8D659218A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3B4E54D791AA412DA276E543D308F7E7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3C7D1EE834094C438633E0C59434926E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3CB51B7C98B049299FB08F1504222254" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3D64408421F74AF6926FD43B08CB1AB8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3D77A77CF8EA49198DE885DBF64BE011" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3E0D8E1F214E4351A12DD3D1B4EDAD7A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3E47D7A07910456E9C81FFE77D0519C2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_3F33027A44D24E6E87C6CBEA70EDB58C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_40089F4F21A146CA8121EDBF0D5D86BD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_401B438C1B0E4DEB94B756E4E7FA53F2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4051DFAE405943B6A4E099E87B0FCE03" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4070925303D2484597BEC1D92F3DE151" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_407AA920D9154131A187FD4863FB18CE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4095A3EB0FFD47CF9E6B0E1ED714F6B1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_40BE2DC9DD854E3DA563C308BCB41A5E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_40DC87C3155846CB8D8E2208D05FC13B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_41920D2CD8BD4F05962B5C6DF0DE8C42" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_41E0E95306C3461C8D2AB3AA0A93FFF0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_41F65B75E782470CBCB011DDF5B89059" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4275950A329C48C6BB994B0863ACCD20" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_43D580329AC94D1C8BFA8EA1DB348296" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_456EF4972E8D4687B9C37B7AA9B230B5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_45ED74B95F00498CB470EF774501E559" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_46164D90CCCE49A3A8575B9AE0EC6631" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_46826FB1D4894F4DA755B95EB43B567F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_46C62A5E15E1421BA046024B48C5A2A0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_47004C74102D42CDBAF5018F2757A4A2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_47175F7A914D4B98919EE56B73E7F60F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4775937211774A8097C609D1C332F615" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_47A8734FB4CE44C39206131A3BD33EE9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_47C1A901825A4365B99DDF86B2ADE927" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_48E075CDCF7A401A82A1BBBCC2996F2C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_49160EBCD21D49FA818F088AA93DE3B0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_49232690870F42F1A3166477F3BCA9B6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4A8E3CD0523543C4BA72DB9D63141847" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4A9B3C68ECA2465BAF16F764CFCA7A5A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4ACE24129D7F40BAB126BDD80AC3AF03" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4ADA0429849141F3811BA82FF0911E20" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4ADAA323612A44AC9AA3C78113349B2D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4B9AA6D7B068452A9855B8668E68536A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4BD611EDF2B1419088D24C67FAAA91B2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4C5ED2FE7E7A45669C2578C317BE842C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4C8ECB894E194A3ABAAD492C78370F3C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4CAA21A7D8034CE49C208F2EFB0433C0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4CCF446D3E40438392B7C528B2EB1D8B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4D23C121926D4AE98F426D8AF979640B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4D2C9EE538534BB3B251B0D891D5E768" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4D2DF60C28724CB98894E9060EB4CDD7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4D62929DB0AA4353840EAA9EBE63E7BE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4D633343B87E4F6A8FABF0DE87B7A838" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4E069B7C235D4008A31232875EB31F29" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4E4A86B1EFC240139BCFDBE926CEA509" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4F04DC56C05E4B2D92A0FFB539375F67" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4F5C8391D1504DCDB16398AF7261F88C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4F9B75043D30449CBDA916764882EB29" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4FBC935682E846478E4EA776C658C0B7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_4FC2851FAF354399AF1BAA963F269598" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_509FCFAB6F31424D998D7B090BDB99F3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5157220481B74800A1168D77B95DFAF4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_51A35DD1D5A545E883760504BA741DDB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_535318D023B841F198AE7CF47F8B6396" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_53F8E3D086724275A084A1E5F4CB43F0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_541E55D804394B7D9214E18307EDD93F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_542C4AC1A34B4A08BC0AAEFE5D60C9DC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_546B8435FDB24BF5B097DF7E07C57F74" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_54ABD31BD149480AB618CC4C3A0BDA51" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_559449392BBF4D219DF6C8EF48699835" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_55C0058E6ABF464DAB925A5B15DF2296" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_55F27B88F8CF49D2AD61B7840CB8C0E1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_55F43589D0934583AD2E5BC4AC489A69" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_56DA33BB18844334BF0377716A800D59" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_56F869100F304713BAD0311A03840C13" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_574C4AFBB73444DF9F5C1217066357A8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_574D7A8BD5AB45868BF8DC06F030C371" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_57C0CF903D7D4C888A34BBD8F06A2E22" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_588858D923FB475D8F7B5E4A761C355F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_58A4D240B09C466085E10123D05D106B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_58A66E7B7B114367B1E696495112C826" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_58A9F70C44B0493FBED8B96DA08CEEE9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_58CDF0E23C61482482D365502B4416BB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_593D64FDFA84403D86ACA6098429989C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5A522BC189854848BFABDFBD71F0A67C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5B3B11EFB5314EA496E9BCD91839EF39" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5B5E3647A7954ED0926FA15DBDFBA039" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5B7793B9762B46D98C38438B94A0EE5D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5B8B183D0462454294727A068FBF708A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5C2AC87D42B94901922807907E384033" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5C3568CFD3B84B34AFFC5D6B8CCF9882" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5C5A84733CDC4B368612AC1BBB09A0BC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5C5B922BC16940DEA2675413F645FC2C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5CCD195A09B14F67AFF2CF937DD814D2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5EBE0AB1C56542A3A25AFE8D25352A73" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5F5526CCE5B041A7816503D1019E237F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_5FE4BF2BD66E4F89B7905A832430FDCB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_601C8190E84B414B888205AEDC32C687" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6078A9EA852745AB924CA061033827C5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_61A8C1CDF6A542CAA1677EBCE252897E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_61DB2269F4A244C4B47B250465C41E6D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_61E845324BE44FBEB6F320258769569D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6202339998B046FD8105FD5D1914C87E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_62362B339209465CB1EFDC4CC03991C8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_628BEB5C6B7D4019A9AF5F9C86065F1B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_635DD6C10A984A52859BBE2701B3129A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_64543F2BDD094739BAB2D6E7E4BAB7BF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_64657C3E6EBB42FF8D508E1F4B39BA05" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_649AD1F594ED44BDABA7601BA6DA0C9B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_655F379A9A1C4324881C8F7BAB3B5C03" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_65E804474D6048829F02C7E078B3D628" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_65FD3035E25848DDA8942C8AEA6CC334" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_662CE563A28A4DF98E0654C19483E201" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_669B48D145DD4126BB2BCEDE35031F00" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_66DCA3126F7C45828CA03DEA62AADD03" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_66DCE3D20AC24C7886780BA071A92C83" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_67116D5D859B42A0844BB419EA7AB645" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_676E4FD03F694EEE8C7FD29DBD351114" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_69527D6A172B473DBB34DB812E9F9CEC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6971E053929C4EAEB089D2C70A3F0D9A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6A123C2CF3394C35B968F081D411F1DD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6A29ABF537B840A583BE487707A61D6D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6A42913E1A9B405CB6B46938998BD02C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6BAAC628B45E4F899D9F9C62D6FA2C74" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6BDDBC9AA63940BD9F576A2D199BF5DE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6BE3C280BF2F45D882A7772AE197948A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6C3E46E7DDF843E8ADE028424ADF11F8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6D7BA92A22C74284B437DAA3F362F41D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6D9DAF26D0074D92AD0D0A32EA4A6AED" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6E3196E5E20E491D9ED0C43A3EB45B21" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6F73842C3A4840AA814178FCDA4E68DD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6F7ADEEA4317497D9E00D0E99C658367" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_6FC35F9D64AC43938FCF40A89D6B429A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7007A8AEF8644163A26AF5EFDA8315F4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_704C22C1F2C0412E86766E0D88F53DBA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_707EEE4837AB47609AE1192B59F37CCA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7096B7259E274A1A94A143B450D00D91" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_70A5D4A0573B44EAAE0453EE443379C8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_70F1E09D77A742948F239221D85EB631" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_71230B4F0EF74198B0781C286469E5DA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7128E161694446C49902E18D813DD83A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_72C7D9DED4194D308AB817BF91340809" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_72D69E85A4F54D518C1ACDEA8D27ACBB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_733C57D6ABA24828B9BFEB2CF0E583F0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_74A904F3F6114528B5903E738F69A0D9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_74DE6F4A96894296B124F27E4FFF7738" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_75DECD23CA754B27A7E43B392A938D1D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_765DC462B638482CAB3542C19539968F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_76706575F9CA47ADB8E4F9C1F5B47820" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_767776CAE6794F4F808DD65BB60626EB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_76CB2D03CC85408BB96278381FDB6674" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_76FAF7920E19410E9955C0E5EEEA427A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7713EA24E0C747169ABFA06661161A31" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_77B39A26E82D416ABA48C98A1A070C84" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_784FB82409D347A483C863A9640AEEFF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_78DE276F3366461183FB7B2EC53C1413" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_794241C50BFD42B4A1A43B6A6E00BB88" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_79DF83F17B63454DBE3FAD99A242C852" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_79E7D5CA6F32455499E9FC6FA7106793" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7A4DA999016643C191E9E1D96E28A8FE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7A54E9C9DFE24822ACDB4919D0BDC89B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7A9616B456964166A043ABB9FC7D193D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7B0A698BDB0A4DC6918C77B5391597B0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7B974691977D4316B33641AA9D695B1F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7C3ADC756F184FDC81A12DC180394CC1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7C5B474CAC974521AB38CF1C9553F2E4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7CBB75EB2085440AB9430D81A85E98BE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7D8E17F3FB48475281B3DE82AC8C2946" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7DB6C05F77144714B18F077A782F6DEC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7DB95B3CCFA7405FB55AC236FD2397D5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7E221AF8A7B24F47BD0E945271F27F1B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7E9AA57CFC9C4C96AC619E49B2AE68BB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7EB18046FF51494FA2B0ED027C61EC33" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7EEAE2BC1F8C4C568AF0DF2C9ACD9750" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7F51E28CD57746659CE55C6E2F17657B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7FE0771341C8413EA1327DFF7CFE83AA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_7FEC578B37B04965A7998A1B17D0D0DA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_800EAC2975CF453EAFD22FCD372F3A5B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_806B853DFD9A48D2828AA43393205C29" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_81136CBCE0CA4555B295D53DFE8EB12D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_816063DFB0794169BED294B6750BBB74" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_816092952B87443C81ADD0AB0C88594B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8197298C7A5F49878165430B60DB3C8C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_81D4A937BA6C489D80CF66F55466F8E8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_824BBD8320564C2899D54394A4645E66" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_82BB9B7DA0F446F29FE8CF3B1D4A03A8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_82D0C47D5A0C4CDFA11826968542C889" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_834C4F4EE03D4C41AD978ACE2DAF03FA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_839324D3B7AC4B85A89496BD83B71577" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_83B7B90885DA4340A50905AC9F13F2AD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_846104FF50A84EE1892CE4B7866ED04B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_855B0948A1DA45E997A8A4E90354B985" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8586A310DD5C43B3AB8620F6E85403FC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_858CF8BA47B04FBC8E1463D95B7CF835" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_85A90E7C6702488B9E6DC6E51939FA96" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_85B49CE782CD45F181FBE8A28B460BE5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_86215EF08DFF4C9B8EF1F1A5F652689C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_86745BA7D727464DAFDD7CFDEE3C7833" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_86DBD25DAB91430EBF9760DEF3A70221" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_871C6181986D4B689F8437AE6653F736" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_87519A8BCC3F4F4BB072A8F3E45DBC6F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_87D23EC11F3A4FE08BD85CB76B502FAE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_88C02CDA20734E338A8AF267C37BC1DA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_893D4C0AE0124EDF987439A8399CFBEB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_899DD448CCF4429787AA1BCC19A93394" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8A20CE81285442139AD39BE0C9097698" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8A3745B45B694B9EA9DF656F6A01C08D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8A8A889C984440778AC56862DC1C2D24" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8AA079A72E07418987AF2B80C5D9E139" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8ACE3E918F3D444A91923FA5DBA18ED0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8C4C93FD223A456AA66C9750AA73C33C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8D4AD3B4DC0A4876914A4CD7260A7F55" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8D767AA1CAE84567A062F1AD1BFD4FF8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8E8A2105C6094997ACD176DC037C7DB7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8EC0C662F73A445ABEDDBF3D1B4D2C7A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8EE9DC96393D4E8C9C4D75C4C7E3ECFF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_8F894C8004264ACF8F624A680724BA62" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_915DCBA3B2A44B0EB7AE59C5675F5081" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_91840158FD984BBBA4D0B5C1E81E0DDA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9192BA80F9C34D128348A9B6453CF96C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_92CCF1C3663440A98FF87EFD29B5FFFD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_93D082CB52CB43A78E2F6A7FFA694472" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_93F4CED32CF547C78A25477C7562DF1B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_940B6C02C3004711AFE9F8E627FDEC9D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_956D2DAAA2F548EDBA45BC768B843D7B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_95BD547E1CB44726BF661E332A70E7E0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_964E7CB77ECD4D2C82D9DF44B243CB91" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_98236B2E08EA43E28B00F88C7FADB74B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_982686BCAD3140B888049A9C903EF254" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_98326B986BAE43238328DC0E8C65551D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_98346740D9A64A849FD702022A3BA319" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_98BF17F8ACED41CEB8039AB76A876B67" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_98D0392830E64D419D6F26FF2524EE46" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9932333F26AB477DAC558CF91689D2AB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_99B5422E6CFD439DBD501650B5A3ACC8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_99E8818FD556473FA5EC9B22338CECD8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9A2B42458215440D976FD8B3959B3F40" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9AAB6F70632C4B81A1AB8766426E4761" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9ADE9F6AF52F49469139861E010229D0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9B50B625BAAE4ABEA0B6A704B2A18C0C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9BF0C1F4EFD04347AA9ED9F03FDDD6BD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9CD33EB2B23447A9AA87A40C42585926" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9E9A5B189EA74A1AAB71F70A6C8F540E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9EA06672F2503924A09793056DF7EA70" + "OwnerKey" = "8:_F416462836FD4AC3AA39054F791C8C0F" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9F08FD93B139474D904B6C727262609F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9F44C5F8DC3446B9A5738D140BA86553" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9F6BB8CB467842AFB543F7AA80AE9C8D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9FAAFE7B42FB4DE6874998CA968814CB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_9FEB7C7D606549ED83EC352ADB0E9263" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A01A00C2B48B413EA8F75E79D2D7FB41" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A05FDFED8F824FF5A5B3B486568A5AEB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A0BB741F77E24DF6BEAB99D2A9C23BD3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A0E75FACF5B0481FB71F93079FC81DA6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A1394037A535467A83F935D776C4BC97" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A17BB4216E6C4C0791CD8D0144CEDC1A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A18DDE22A53B46958C8A724B9CA16F57" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A1B5B6053891454D891630A99A8F4EC0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A1BE3311CF934116823B10F06FEADD56" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A23B8A6701214753BF781C0ACE1421A9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A26E7FD32AF94C1AB26938D16702D7FA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A43AC737BFBB4313AC9B1BF70A25F167" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A462A036B5BC4211AB8E4A4C3F4F5170" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A590A3A6826D4B149C1BD0C8040EFFE1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A61C5D96537C4327B8FB1B1FFA09B952" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A6B268C4F2BD40C0BFB08758E92A9221" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A6B6DD87A90642259063A8EB75064260" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A703E553EABE4219BC476557B4A81A0A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A72B3F8FB6CD469691414B1E19990EFC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A7AB9D0C1DA74866B0916861AC10D868" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A823D68E199B426E98D9C631F8524EF0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A86B2A50B9DE43039F0A67031E1DA4BF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A89D502E134B4EFCB8843E719EA1E093" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A8E0F5EA7DA2443793BF4188335E0F4A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A9107D25ED2C47C2BFADCA3EEE5116B3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A9900978E7D54EF2BFDE5A3F844D1CE4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_A9B3F73D4DA4484383D0C6807CDDAFEF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AA711F1131EF44118F316155463D6F71" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AABDBC7E0DC94B21938D60956A0A8E8F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AAD7D5E9A527470F812C8556036DA67A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AADA87793CBE4C59A1DE256457B307AB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AB2F56AE86E146D2A1B424B05DD68426" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ABC3D490BB264CB0824DF148501EE84B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ABD46A949A494DE7AB61B3F069B3F832" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ABED536639A54955BF834CDAA79D2FE3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AC7DA4E6417743C792C9DCF5A050126A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ACAD52699F4945C0973D6B583F896A09" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ACB3A85A971349BE9BDC019849DBEB3A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AD5A9DD370A7492EAE52EA10E6176CD5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ADDE147893CD47778EF548A116C2D402" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AE1163E7B39C4B53AA50A84CA3E22109" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AE19D3DE3B4145FFA8CC3D5E29492DE7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AE8F8A8C376B42958A052A945D7129B6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AE91494676254C44877C5B7FEC52E864" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AEFF7E503315473EAAA2A683F629A1D6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AF11DDD8E30A4B8E8DD8AA6F86E30D30" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_AF348362A33A41AB930013690C5212D8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B03BAA5575424943933E54B5EFE2851B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B071CA65CEF143D9AD061DCA589F2B9B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B0759DA28A5646F6865486B794049973" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B171969183564D47A9987C6B7829A33A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B27DABBED93B4E40BD16B954DD99E2CA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B321287E898F4A2EBE647CA883764DF1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B380834BF5E44984869FA545CD86B1CE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B3966FA2BCBB414292487D2E8C92C413" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B43ED801E6884338833C213DDC6F45DD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B478AEEFA5F547C29D919199CFC9A7B1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B4EC427F8AFF40B7A10E9E2070D270FA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B5950BCC2B904E61AA95D3F379AF7580" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B5C266502FD64711B048F1C0D8AEB202" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B62CD104FDE045F290B855BF4E9BF514" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B7038776CF974FFA9845C1E9C4339098" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B706E7F4F96249A8959A7B9ADBC03512" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B70D9CC6F6694962A4EC847A34D5EE11" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B8B195763460402CA0195A22EE4D7A61" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B8DFC81368274017BD88042182170735" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B90D976B8E204DA18EE325E2E8BFD12F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B922AF7E3FF943BD93E0FF0BEA63E162" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B93F80AA91984937974B581C7A429AD0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B952B5BB4930493C8C6A1B5C6CF89C82" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B994F7FA427F4B3DB3F7DDE0E458EBF6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_B995049EDF294EE19958B6D9A44768EE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BAC2AFAB06364837A53E782F3A406759" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BB17F6A6CA3B485F88C9ED9D6CBD3FE5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BB5BDE36E7554E959AACBB732B14714B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BBFBD95853E6448A953FC476C9BA209B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BC8079A4AAE94C63A633D4C7039E24B3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BCBECAFAA0644F93B58A9170B7F38050" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BDB3E818B9F73D1C6A5BFEFFF8B70912" + "OwnerKey" = "8:_F416462836FD4AC3AA39054F791C8C0F" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_BDF2AF4805374D53A15E77D11C9F3C67" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C00FA694A6384FBDBDA91A1F54BD0301" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C2190773C36F42169C12DFEB251DEC59" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C367B64F8DAC44888907A119784A71EB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C369D964974A45759FD353DAFFEEEDA4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C3D03C578F88469C871312C0F933D280" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C3DAC7C45CBD4DF7A6CD3478C7750714" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C3F762C2BFFE43C695223C813AEDAB86" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C414AA643336457EA6711056B254AE5C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C4E1B1441FC80FE779D04EDF089D8DC3" + "OwnerKey" = "8:_F416462836FD4AC3AA39054F791C8C0F" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C516E1EDF0394BEFBDA86880B2A57BA8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C7D755867627491AB30C877CFA743E9F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C80470302D9B43BEBAF5F63B78B7B672" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C87BEA81A2D54168BBAEE6946D43ED0D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C9926302F73943EABB67D9F69F38BBED" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_C9E5DF4709C54AADAFBF3370919AB2C6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CAB47663EC994744AF473C21C314674C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CAE514C732AC4575AE5006369FE026C6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CBEC3A60157942B1AA5E42E883AC6BE0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CBF936AC750A4176881CE75B2A80CFBE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CC31B03F6CA1446DA9AEB464CEEDB4C6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CC476CE5007D447AB80FD7F9DC335EBA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CCB73795DE4849C09596DF8A5257AA3C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CCF4E0ECF4CD4A89A231EC1BF9402D00" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CD9A527D0EC9464FB058B30D5A8EB6AA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CE3A71F8135D4ECB9C41BA84CE65BC72" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CEB37922D72B40E1900864B8E50F4135" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CEE14DCF7A2543C09AA6536BF01C0115" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CF2E8C057F9A4FD484ECA7F76BF56FAF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CF371FFE46F44F03A3718A03E31B5CBA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CF3D4D2183AF4508B39A73F339280F13" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CFA0056EEE3A40ABBDB6E439AE588781" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_CFEE6AC9A962489F81556B0D427C782C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D083C18D8C7144CD951E244B2C946D2D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D0A7CFC6B2C94CCAABDA85AE147F8E0B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D0BE6EECF08641F6A074A7190C3A9AC1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D12262ADD74541CD9D829AF2022835EC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D1259B60EB1D4988AECA3913786AB522" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D1570E9AFD8D42CD894FC961AC5EA947" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D1C6D397DBAC463CAB2F5014305A31E6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D2360210FB5E49DD8433868A9FA91642" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D26D86A965B945599250B7EC28D0C33F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D2EDD1255850445095E375ABDC16C35A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D339C82002C545D5ACB12FC254F4AE1A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D351E08D7E8744B7987CB9588B2DB49B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D36F42FA834E4DA4A3E33A4868C56A58" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D431DC980F7F4ED3BDB29AC735D98BDC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D510C71F91F54973A196D41181FC5E9A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D52C3635BDE34B0EB82E8CE9C54F7B13" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D53367CBD47F4D63AA488641D3133102" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D5972918583045B69AE2B6B0B3616AB6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D5C0254D502543A081B5F1100D59CB76" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D6DBC86D78B742E4AC0E4A7583944EFB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D777C2ADD68B40A2BACA358D9F61DEBB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D8871C8E22C74699B0BDCAE7DAE3E6DE" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D8CE594650CF5AF84377188D03CC3689" + "OwnerKey" = "8:_F416462836FD4AC3AA39054F791C8C0F" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D8CE7F54A3E34564A72D44E31C3027AF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D90020ABC89E40F795FD564263F11C13" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_D930F8355F704FFDBED150BDFD7B9822" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DA1B972A4D594602A197A27C85E0F12C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DA1C22D901FF4A1A898B93DC2EBC22B8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DA3BA11DCF0341ECB20CB36A7EAAB6F4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DAC9C7B9FF374A1787C57BE20B612374" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DAF5EA8366CA4ECF9C42F8883E78575A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DB1850DD1C254191A7927468026621C7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DC6320EAABE742ACB727727053F37286" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DCED0953BF384856B9A0CFDDA0BC3CF1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DD47D84330F7480AB3888C924FEB6DA7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DDAED51D890E42CE9694521BB2566863" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DDC2C1F1FEC348068F4D814EC3E4A837" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DDD4C7E5D8BC473BB9EDA4F350D25B8E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DDE4217E8AC040D4B13863F2ADEC5DF3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DE6F47C33944413AA4AE9FAA15C89C47" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DE79ABB414D747459945C99E52D98EE8" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DEC8F7F34C9A4AC1B27554BEEE472AD6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DF3CAACF253441E7B0D939FE870D5CEA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DF49BEE3849B42A5B65317D56EC52604" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DF7D953122A54A1E93E32D4469B91DC1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DF82B6FC5E4E40AC8E86BC92661C812B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_DFDD4383FDA5406891A567923C7B7F2A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E03025BAC06B49B9860A5213C36233E2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E28E8D1F1B0B411581164F6A67A2F02E" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E292B767DF3A4EA2AE88686510DA1C61" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E3A41390879A42DAAA440C02C85BECCF" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E3C9633B5FB94F39B718237C7FFDE1F3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E43763E59150433C860C42E39A41EA3D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E4A252D4AA2A457C8B7AC6FF5DBEFEAC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E4DEF65130E8495A8D8A6B6A4D9EF85C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E4E47EFE352F4EDF8F20E48B638D5DBD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E578208A56304B1AA57121B2398AF048" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E58A394B88D24093A8F7CC888914FF3F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E73992158C294F90978497B9C0B1A723" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E7451E63031A4FC7B7524D2149E78308" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E7C217F79900404CA0F61323C1B06C1D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E87D21FC3A3B4BF982016C3434257169" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E8A5E4D4FF4E40BF9B78C7AA8C0AFD96" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E92105A519B64C2F8B1148553B809ADD" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_E991EC30E5B74E14AA495D2DA1E138E9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EB1FC9E499F543AE9B723D1D5A27FD79" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EB49D5345A924F828EF9906A28E7C08C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EB7B998D65A940C8BC66A6DEC081DA25" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EBBEAF74D9D14D2C8570074AB20634D4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EBEE2F68CA7D46B1B51885C3C62E3435" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EC6C0A74B89E42CD81CA9C3AF4E5677F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ECD51689A68D40DE9188FB9EE4E79B03" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_ED395EB6FEE94B179683F0A0A2A6D6B3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EDECCFE9E7FA4F53A731F9BC8794D276" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EE011A0037D64B109CC800636F0A4296" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EE09AD72A82C46FE827C35020371C0B3" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EE3757B3C62347BE8ED5B52660207B1A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EEE1343E6B01403E9958E31483DCE2D1" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_EF7927456E4E424897700228BBAA2A9D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F084600A9FB346C1AADB8F0668E62053" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F09D3596F4384B4BAE1460A2C45042B6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F171D77A5E3849B9908677A1016C9C6D" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F1D5AA741D0C4A8BB0012FA2F5360140" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F1ECE56D42B1414985701C916564DBB5" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F30440A183284FE4BDA60DB19F7437D2" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F3B9D8442F2A4F56A93985F23ADB8AE0" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F416462836FD4AC3AA39054F791C8C0F" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F4AF284D31C048DFA09BA933B8AAB270" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F4E4309C13194E87AF016BD175C9E310" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F65495C03E72422DBD26B22B86AE52D4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F6CBE149B1CB4C00AC0B42649C13FD3A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F7B95AA4A2894E83899444A3D7454E76" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F7D8A92F1A8E4F06BBCA302E36AC7BC9" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F84D1CFDF41F480E9163F15357ED2FE7" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F8DA3C2EF9B247ABB7D07AA199845AB4" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F926D0607B5D4A189B6198998CED1EBB" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_F96B3082953C49AD87D657A2321B635C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FA5C605D11754B49AD87B2FFC01B84F6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FB51195D57C5449CA8277F406EECF984" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FBE64D8962D640358518E50A6B77F196" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FCA9918729DA4830B4FA9BE6F0BC4890" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FCC52C47EF184AECAFCD5B5636951D7B" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FD684DD604C341D882C66DE42E84C14A" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FDE5FBF5615B48049D2D0FEC6005FF08" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FDF073796BAB484088F07504BD9842CC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FE857ADC4D0A4E378C6530917BBFECE6" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FF3E6DE321BE47CC981F9D69D6285CDA" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FF80CB9E723C4C93B2271F566529094C" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FFDC038020294FABB8378023ACE30952" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + "Entry" + { + "MsmKey" = "8:_FFE912EF33CF4293A5F0FFB1FC70FDFC" + "OwnerKey" = "8:_UNDEFINED" + "MsmSig" = "8:_UNDEFINED" + } + } + "Configurations" + { + "Debug" + { + "DisplayName" = "8:Debug" + "IsDebugOnly" = "11:TRUE" + "IsReleaseOnly" = "11:FALSE" + "OutputFilename" = "8:Debug\\Setup1.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:2" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" + { + "Enabled" = "11:TRUE" + "PromptEnabled" = "11:TRUE" + "PrerequisitesLocation" = "2:1" + "Url" = "8:" + "ComponentsUrl" = "8:" + "Items" + { + } + } + } + "Release" + { + "DisplayName" = "8:Release" + "IsDebugOnly" = "11:FALSE" + "IsReleaseOnly" = "11:TRUE" + "OutputFilename" = "8:Release\\RPSetup.msi" + "PackageFilesAs" = "3:2" + "PackageFileSize" = "3:-2147483648" + "CabType" = "3:1" + "Compression" = "3:3" + "SignOutput" = "11:FALSE" + "CertificateFile" = "8:" + "PrivateKeyFile" = "8:" + "TimeStampServer" = "8:" + "InstallerBootstrapper" = "3:2" + "BootstrapperCfg:{63ACBE69-63AA-4F98-B2B6-99F9E24495F2}" + { + "Enabled" = "11:TRUE" + "PromptEnabled" = "11:TRUE" + "PrerequisitesLocation" = "2:1" + "Url" = "8:" + "ComponentsUrl" = "8:" + "Items" + { + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Net.Framework.2.0" + { + "Name" = "8:.NET Framework 2.0" + "ProductCode" = "8:Microsoft.Net.Framework.2.0" + } + "{EDC2488A-8267-493A-A98E-7D9C3B36CDF3}:Microsoft.Windows.Installer.3.1" + { + "Name" = "8:Windows Installer 3.1" + "ProductCode" = "8:Microsoft.Windows.Installer.3.1" + } + } + } + } + } + "Deployable" + { + "CustomAction" + { + } + "DefaultFeature" + { + "Name" = "8:DefaultFeature" + "Title" = "8:" + "Description" = "8:" + } + "ExternalPersistence" + { + "LaunchCondition" + { + } + } + "File" + { + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_006D0CB7C44B43B798CA2772E2D2ACCB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\ME4.BGF" + "TargetName" = "8:ME4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_00AFABA3E51149F89AED555CB335E2CE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAB.SKL" + "TargetName" = "8:SAB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_00C248D38C8D484FB89622FE13931E8F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUB.SKL" + "TargetName" = "8:MUB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_00CA668011F147C58782B627CCCC2AC8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CC1.BGF" + "TargetName" = "8:CC1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_00FDBE51B26446EFAB7D3183AF3327A5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PP2.BGF" + "TargetName" = "8:PP2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_01C5A6F0978A4D9B8D2185E2E475D506" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUA.BGF" + "TargetName" = "8:DUA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_02870A86502F4D9EB068899650070458" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VM1.BGF" + "TargetName" = "8:VM1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_02EDCCC9584546B583846D9F5ED0E5BB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt02a.wav" + "TargetName" = "8:BoosterInt02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0345D734DDBD415EA3076FB739003255" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POA.SKL" + "TargetName" = "8:POA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_036C8E0FCE354F389BC9AB2ECC872E74" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\environ.ini" + "TargetName" = "8:environ.ini" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_03A9A4FA04A24D418047148EE3B74049" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUA.SKL" + "TargetName" = "8:BUA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_03E4CA8894E941579A748A4A4715E699" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RIVET.BGF" + "TargetName" = "8:RIVET.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_043979313DF14D52866537FD44923E8B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt04.wav" + "TargetName" = "8:CollisionExt04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_04C5C478AA8044229D001AD638515589" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAS.BGF" + "TargetName" = "8:SAS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_06459C02D35F43B9A29BBAEEC6EE2EFC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WINBOX.BGF" + "TargetName" = "8:WINBOX.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_06E128E1518040A99BC839FC7B7433E3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUC.SKL" + "TargetName" = "8:SUC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_072FFBD40A8965475CB7060B4105091E" + { + "SourcePath" = "8:OpenAL32.dll" + "TargetName" = "8:OpenAL32.dll" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0792B0B236A84AA8A2D56CDE810B350F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUS.BGF" + "TargetName" = "8:BUS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_07EDCC32C132464295B014760030CD84" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\GR2L.BGF" + "TargetName" = "8:GR2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_080480B007DE475CBB728032FAE640D2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RadarButton01a.wav" + "TargetName" = "8:RadarButton01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_092F0B45BA26494E92837A7C562DA87F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt10.wav" + "TargetName" = "8:CollisionExt10.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_094AE63D45C84E88A1CE3C99152AB251" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineThrustInt02.wav" + "TargetName" = "8:EngineThrustInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0A7E2D812CD3467B99F4F0EA94FDF3AB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RP1L.BGF" + "TargetName" = "8:RP1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0B4A14142A2C47C2A5B44A9980004C6F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitInt02.wav" + "TargetName" = "8:LaserHitInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0BB9BC33DE4A4A3ABEFF1FF51F3EA299" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUT.SKL" + "TargetName" = "8:BUT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0D781C62646A461EA9C3FA55EAC488A6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUC.BGF" + "TargetName" = "8:MUC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0DBA1B6BCC064FEAB341925D1183A61C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RL2L.BGF" + "TargetName" = "8:RL2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0E001D162572440C9B5C5DA850C08EB2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetFireLeft.wav" + "TargetName" = "8:RivetFireLeft.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0E4B15B9CBAE45B1B68155818D854A0E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CAMPOS.BGF" + "TargetName" = "8:CAMPOS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0E689AE216DD40758597D0611B062C7A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\HVAC03b.wav" + "TargetName" = "8:HVAC03b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0F3C0F2D95374BC1A33332EA2B57F9CB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POB.BGF" + "TargetName" = "8:POB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0F40BC85ACD247C2970EE8D5B5AD08FD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DR2L.BGF" + "TargetName" = "8:DR2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0FA9870A7E9446CBB43229A6EF00647C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DR2.BG_" + "TargetName" = "8:DR2.BG_" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0FB4B38CE93243EF8E30001AC222048D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAN.SKL" + "TargetName" = "8:LAN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_0FF9B67FB5314C57A903F7A99C2392CD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUS.BGF" + "TargetName" = "8:DUS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_10A8931C6AD7417594655B3977C9C8C2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterLoopExt01.wav" + "TargetName" = "8:BoosterLoopExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_116A12105DF1493ABC28469B9D3A773E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt13.wav" + "TargetName" = "8:CollisionInt13.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1171F8E1A69D45C1810935B43D085724" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BR1L.BGF" + "TargetName" = "8:BR1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_11A19D284C8A4BA59C4E859EA6BB3B1B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDrill01.wav" + "TargetName" = "8:WellheadDrill01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_11B93AEFB9D44251B41C9C9C11AD0556" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POS.BGF" + "TargetName" = "8:POS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_11E0A799554F438197382DF84807F631" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt06.wav" + "TargetName" = "8:CollisionExt06.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_126BA75870A24007A092DA073A408CCE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAS.SKL" + "TargetName" = "8:MAS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_128922AB01D44A73A1F22C4314A4F3FF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HV1L.BGF" + "TargetName" = "8:HV1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1392BE3CEE7041799D64408A4AD1C1D3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAB.SKL" + "TargetName" = "8:MAB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_143C153D96DA4CB0A5578C7AFF8211FF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CQ2.BGF" + "TargetName" = "8:CQ2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_143DA4188BBE4EB09130F42B99B7CD1E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE6.BGF" + "TargetName" = "8:PLACE6.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_143F2B995BB449E0874B8F4C2217AB58" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LSABER.BGF" + "TargetName" = "8:LSABER.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_15439D0009DA4EBAAB1C805C371895A0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE4.BGF" + "TargetName" = "8:PLACE4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_15B83B0F1E2146D7AF7E7375246C34A2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HVB.BGF" + "TargetName" = "8:HVB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_16B6EF840C8E43EC8800AD1FF9DB57C4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt08.wav" + "TargetName" = "8:LaserFireExt08.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_178A813081464D1C9284C8CF7194CD9E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ViewSwitchCenter01.wav" + "TargetName" = "8:ViewSwitchCenter01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_19268E74339E4757825B1C63C32FA33F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HVE.BGF" + "TargetName" = "8:HVE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1987C7D6CB3040B6B5A401925CA37C54" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR7L.BGF" + "TargetName" = "8:CR7L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_19B55F1CA06A40EC917B552669F441C0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PM1L.BGF" + "TargetName" = "8:PM1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1A0FA2D099924E8A8F9C9AFA8FB47D86" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MineCoast01.wav" + "TargetName" = "8:MineCoast01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1A2A4B2451074200ABDFD3048AE2401F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt14.wav" + "TargetName" = "8:CollisionInt14.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1C525205D5B943588870B82F7961B2CF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PRT.BGF" + "TargetName" = "8:PRT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1C733072D2F24B3094BD457F14674F5B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Generator01.wav" + "TargetName" = "8:Generator01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1C84C74BC18549118D74405F6E4C119B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAS.SKL" + "TargetName" = "8:BAS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1C99C21D9F9A4937A3CB8BBDB58251C2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WCIRCLE.BGF" + "TargetName" = "8:WCIRCLE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1DA0F136251F4096B33EC8DEC56C78D7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAA.BGF" + "TargetName" = "8:BAA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1E365D6C2FF24597AD10F59BB6EB7DCF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\INTB.VTX" + "TargetName" = "8:INTB.VTX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1EBE36BC5BF5488BB8F69B28FB8741C8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MaintPulse01a.wav" + "TargetName" = "8:MaintPulse01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1F015CD0D057499D972F7E960D8212BE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt04a.wav" + "TargetName" = "8:BoosterInt04a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1F52E572D32F4622822CF87C9C8E84A0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\INTD.VTX" + "TargetName" = "8:INTD.VTX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1F9CB773A6D94A748CD1AD751E8CBE1D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery06a.wav" + "TargetName" = "8:Refinery06a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_1FB9EB0096494166AD3D017764675DB3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAA.SKL" + "TargetName" = "8:BAA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2019F4F23B2247CD85822D2186795829" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAB.BGF" + "TargetName" = "8:BAB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_201BFDF7D7964B9C8E7BBAE836E51424" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt08.wav" + "TargetName" = "8:CollisionExt08.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_209E78F0C95B4DD68225C8F204C66F63" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt02.wav" + "TargetName" = "8:LaserFireInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_217105B95549461C8DABF8B3F3C80743" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNACRANE.BGF" + "TargetName" = "8:SNACRANE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_21AA256F588A46D9874DCB5C87EA79D9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LiftCut01a.wav" + "TargetName" = "8:LiftCut01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_21BDB5950F5346779F5C2E2940C31BAC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PON.BGF" + "TargetName" = "8:PON.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_22984E40249D4F22A813BE8417ED63CB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt01.wav" + "TargetName" = "8:BoosterInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_22A730FC69FC4D49BEC9315EC6CB68BE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt12.wav" + "TargetName" = "8:CollisionInt12.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_22CA4E62EDA641A6897035CA69482BAF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt10.wav" + "TargetName" = "8:CollisionInt10.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_23D38693F008456DB52B852FD7836817" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CHT.BGF" + "TargetName" = "8:CHT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_24498092FB2A4922B6055DCA3D526AF4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\TRS.BGF" + "TargetName" = "8:TRS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_249348076F7B44F4BA6DB529D4DB49EA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAA.SKL" + "TargetName" = "8:LAA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_25162A21B2984F22B6140750F559F1F2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RP3.BGF" + "TargetName" = "8:RP3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_26E2087DDCF64F3B806F3748EBE86FBD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\OreDrop01.wav" + "TargetName" = "8:OreDrop01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_271567CA5E9348CBA04629311EDBDF0A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WT2.BGF" + "TargetName" = "8:WT2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_285D7B3EE3AC4F738F31F51EBE9F026E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POC.BGF" + "TargetName" = "8:POC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_28FED9DC78954D50A0342D8DEFA3F64F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery01.wav" + "TargetName" = "8:Refinery01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_290356E6DECB4F779D8481737AB7CD66" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitInt03.wav" + "TargetName" = "8:RivetHitInt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_29061B419EF243E0B7AC31F44274CCCF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PZ1.BGF" + "TargetName" = "8:PZ1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2948255E740D4E719A528D98C8EFCD99" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MaintDrone01.wav" + "TargetName" = "8:MaintDrone01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_296D55BC12174FF5B97A9E8D18618A5E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAN.SKL" + "TargetName" = "8:MAN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_29796736028948E8A9298DAAF308858E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DoorOpen01.wav" + "TargetName" = "8:DoorOpen01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_29C063D1011E45D9AB825AF328C53BD0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE3.BGF" + "TargetName" = "8:PLACE3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_29D30C0540B841168886069C96567B09" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\HVAC02.wav" + "TargetName" = "8:HVAC02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_29E9901A650C4FD1BB43CAFEE5B2B076" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAA.BGF" + "TargetName" = "8:SAA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2A4C99FAACEC4920AEA5B40FCD9B2B10" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAA.BGF" + "TargetName" = "8:MAA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2A6EC34FE4F246BB9C52BA975E51FE52" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAB.BGF" + "TargetName" = "8:SAB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2AD83F6CECD74D02BA5346E3FE7FC003" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery07.wav" + "TargetName" = "8:Refinery07.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2AEC7A12575C4D67882A40F90E1F980A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SINC.BSL" + "TargetName" = "8:SINC.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2B59BF040DCE41939321C1D427B79A61" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PipeMachine01a.wav" + "TargetName" = "8:PipeMachine01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2B935410B1A54514813A79E7CE71F46D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\FuelTank02.wav" + "TargetName" = "8:FuelTank02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2C04F060B6324D29BD0D34D68F97D298" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAA.SKL" + "TargetName" = "8:SAA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2C1F1CBF0C8E48CA93654FD0B2BB8F2E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\C8EL.BGF" + "TargetName" = "8:C8EL.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2C3EBC784EEF40D2916538C700E8547D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAT.SKL" + "TargetName" = "8:BAT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2C7E1E2B8F2C4421B95444CFD6CFD932" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAT.SKL" + "TargetName" = "8:SAT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2C8F6F91FF1743DC8C83A332A7D70513" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetTravel01.wav" + "TargetName" = "8:RivetTravel01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2CFD94DFFC8E4E5A955C649AE2875ACD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN2L.BGF" + "TargetName" = "8:CN2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2D601A6EAAE340C5B6F4B1B0C8D2EB6E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAN.SKL" + "TargetName" = "8:BAN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2D6EB0D9015E4873BEFF10FBB6354D1D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt11.wav" + "TargetName" = "8:CollisionInt11.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2DBCE7E0F46840A3BE99BCC9869D8653" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNANORC.BGF" + "TargetName" = "8:SNANORC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2E939C1B263E4DCEB8799364D4A6F00F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNATSPD.BGF" + "TargetName" = "8:SNATSPD.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2F1D500F25BF4498AC303F95EA03EAE9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUT.BGF" + "TargetName" = "8:DUT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2F1FE157916C4781B69267D241AA03CB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Generator02.wav" + "TargetName" = "8:Generator02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_2F4F66331E4545C5A7B326310ABB4973" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HVC.BGF" + "TargetName" = "8:HVC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_303909735C104EE5B01EBEDBCBE8F2DB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CH2.BGF" + "TargetName" = "8:CH2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3040C877B1B846CE9F718D2BFDDC8D40" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SIGNA.BMF" + "TargetName" = "8:SIGNA.BMF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_308185542B5A40A495D83ECFCAAC5965" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt02b.wav" + "TargetName" = "8:BoosterInt02b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_31DC0BC9F57042E9AB2920884BCB798F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt20.wav" + "TargetName" = "8:CollisionInt20.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_31DE26777AAE4F38B360C949C3FE5443" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDrill02b.wav" + "TargetName" = "8:WellheadDrill02b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_333F431A29C2428282D6DD0FF26A06D9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAN.BGF" + "TargetName" = "8:LAN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_33B0A36FA4BB44FCAEC8B987EBB172B1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MineRelease01b.wav" + "TargetName" = "8:MineRelease01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_34021C57D1FF40778712AD45A10A29BA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ViewSwitchRight01.wav" + "TargetName" = "8:ViewSwitchRight01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3422379FACC1485DB4C9B689EB6FAD7C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUC.SKL" + "TargetName" = "8:LUC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_342E65E4F2D749178DF5C1ED6DFABAF1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SINB.BSL" + "TargetName" = "8:SINB.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_34538B8814974577A1F2304C0338A974" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAMFAC.BGF" + "TargetName" = "8:SNAMFAC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_35F51E5D2EF24A88A386A9984DF29A63" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery03.wav" + "TargetName" = "8:Refinery03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_361D1DB44378456D8FC8774F1693AEF2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUS.BGF" + "TargetName" = "8:SUS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_364707B4C4A24C0E8BB64A207AF1CC69" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineThrustInt01.wav" + "TargetName" = "8:EngineThrustInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_369E37FEE35D406A8FFC035A87CFD747" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OA1.BGF" + "TargetName" = "8:OA1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_36B7CA1D6217460BA9FE102004C6516E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ScoreZone15a.wav" + "TargetName" = "8:ScoreZone15a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_36DB8DEF07A3491FAD929B4101AC6C36" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAT.BGF" + "TargetName" = "8:SAT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_37C26A3A698246CAABF6E240F41E2FFA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDrill01a.wav" + "TargetName" = "8:WellheadDrill01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3802BE7A611045068B7BB90FA2055124" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAWELC.BGF" + "TargetName" = "8:SNAWELC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3830B1418F2E45318DE8638EF323B3A8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt03.wav" + "TargetName" = "8:BoosterInt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_38A695B9531D4688BBADD6F78F3D28E7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DR1.BGF" + "TargetName" = "8:DR1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3924AEA054C04B9789D89AE92C937CB8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CRE.BGF" + "TargetName" = "8:CRE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3953C4B1EC0740DD894183182B39AA50" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VRA.BGF" + "TargetName" = "8:VRA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3964C8969A2A40BD9056BA2304BF7DF6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUB.BGF" + "TargetName" = "8:MUB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3991C8DA9B7846C79943472002CDFA0D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BR2.BGF" + "TargetName" = "8:BR2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3A81CAACC0414FE693DC4DDF53481CDE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNALIMIT.BGF" + "TargetName" = "8:SNALIMIT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3B02CA36C18B4ECFA52ED2F8D659218A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RP0.BGF" + "TargetName" = "8:RP0.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3B4E54D791AA412DA276E543D308F7E7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUN.SKL" + "TargetName" = "8:BUN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3C7D1EE834094C438633E0C59434926E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BR3.BGF" + "TargetName" = "8:BR3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3CB51B7C98B049299FB08F1504222254" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MineExplode01.wav" + "TargetName" = "8:MineExplode01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3D64408421F74AF6926FD43B08CB1AB8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR3.BGF" + "TargetName" = "8:CR3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3D77A77CF8EA49198DE885DBF64BE011" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt03.wav" + "TargetName" = "8:CollisionExt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3E0D8E1F214E4351A12DD3D1B4EDAD7A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt01.wav" + "TargetName" = "8:LaserFireInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3E47D7A07910456E9C81FFE77D0519C2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PipeMachine01.wav" + "TargetName" = "8:PipeMachine01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_3F33027A44D24E6E87C6CBEA70EDB58C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUC.BGF" + "TargetName" = "8:DUC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_40089F4F21A146CA8121EDBF0D5D86BD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CENTER.BGF" + "TargetName" = "8:CENTER.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_401B438C1B0E4DEB94B756E4E7FA53F2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LiftCut01b.wav" + "TargetName" = "8:LiftCut01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4051DFAE405943B6A4E099E87B0FCE03" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\GR1.BGF" + "TargetName" = "8:GR1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4070925303D2484597BEC1D92F3DE151" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DRWL.BGF" + "TargetName" = "8:DRWL.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_407AA920D9154131A187FD4863FB18CE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetFireRight.wav" + "TargetName" = "8:RivetFireRight.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4095A3EB0FFD47CF9E6B0E1ED714F6B1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\TEST.EGG" + "TargetName" = "8:TEST.EGG" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_40BE2DC9DD854E3DA563C308BCB41A5E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterLoopInt01.wav" + "TargetName" = "8:BoosterLoopInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_40DC87C3155846CB8D8E2208D05FC13B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUA.BGF" + "TargetName" = "8:LUA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_41920D2CD8BD4F05962B5C6DF0DE8C42" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH4.BGF" + "TargetName" = "8:WH4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_41E0E95306C3461C8D2AB3AA0A93FFF0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitExt01.wav" + "TargetName" = "8:RivetHitExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_41F65B75E782470CBCB011DDF5B89059" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAS.SKL" + "TargetName" = "8:LAS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4275950A329C48C6BB994B0863ACCD20" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUB.BGF" + "TargetName" = "8:SUB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_43D580329AC94D1C8BFA8EA1DB348296" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN5U.BGF" + "TargetName" = "8:CN5U.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_456EF4972E8D4687B9C37B7AA9B230B5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WINSIGNS.BGF" + "TargetName" = "8:WINSIGNS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_45ED74B95F00498CB470EF774501E559" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUS.BGF" + "TargetName" = "8:MUS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_46164D90CCCE49A3A8575B9AE0EC6631" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt02.wav" + "TargetName" = "8:CollisionExt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_46826FB1D4894F4DA755B95EB43B567F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ScoreKill06.wav" + "TargetName" = "8:ScoreKill06.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_46C62A5E15E1421BA046024B48C5A2A0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDevice01.wav" + "TargetName" = "8:WellheadDevice01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_47004C74102D42CDBAF5018F2757A4A2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PipeMachine02c.wav" + "TargetName" = "8:PipeMachine02c.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_47175F7A914D4B98919EE56B73E7F60F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN7.BGF" + "TargetName" = "8:CN7.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4775937211774A8097C609D1C332F615" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt08.wav" + "TargetName" = "8:LaserFireInt08.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_47A8734FB4CE44C39206131A3BD33EE9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt06.wav" + "TargetName" = "8:LaserFireInt06.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_47C1A901825A4365B99DDF86B2ADE927" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\FT1.BGF" + "TargetName" = "8:FT1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_48E075CDCF7A401A82A1BBBCC2996F2C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHItExt02.wav" + "TargetName" = "8:RivetHItExt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_49160EBCD21D49FA818F088AA93DE3B0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAN.BGF" + "TargetName" = "8:SAN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_49232690870F42F1A3166477F3BCA9B6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAB.BGF" + "TargetName" = "8:MAB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4A8E3CD0523543C4BA72DB9D63141847" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery03b.wav" + "TargetName" = "8:Refinery03b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4A9B3C68ECA2465BAF16F764CFCA7A5A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAT.BGF" + "TargetName" = "8:BAT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4ACE24129D7F40BAB126BDD80AC3AF03" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\ME3.BGF" + "TargetName" = "8:ME3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4ADA0429849141F3811BA82FF0911E20" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt02.wav" + "TargetName" = "8:BoosterInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4ADAA323612A44AC9AA3C78113349B2D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUA.BGF" + "TargetName" = "8:MUA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4B9AA6D7B068452A9855B8668E68536A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\TSPHERE.BGF" + "TargetName" = "8:TSPHERE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4BD611EDF2B1419088D24C67FAAA91B2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterLoopInt01a.wav" + "TargetName" = "8:BoosterLoopInt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4C5ED2FE7E7A45669C2578C317BE842C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VLTNG.BSL" + "TargetName" = "8:VLTNG.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4C8ECB894E194A3ABAAD492C78370F3C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\INTE.VTX" + "TargetName" = "8:INTE.VTX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4CAA21A7D8034CE49C208F2EFB0433C0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MINE.BGF" + "TargetName" = "8:MINE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4CCF446D3E40438392B7C528B2EB1D8B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNARADS.BGF" + "TargetName" = "8:SNARADS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4D23C121926D4AE98F426D8AF979640B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DeathInt02.wav" + "TargetName" = "8:DeathInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4D2C9EE538534BB3B251B0D891D5E768" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Translocation01a.wav" + "TargetName" = "8:Translocation01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4D2DF60C28724CB98894E9060EB4CDD7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt07.wav" + "TargetName" = "8:CollisionExt07.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4D62929DB0AA4353840EAA9EBE63E7BE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SINA.BSL" + "TargetName" = "8:SINA.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4D633343B87E4F6A8FABF0DE87B7A838" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAC.SKL" + "TargetName" = "8:BAC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4E069B7C235D4008A31232875EB31F29" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HV6.BGF" + "TargetName" = "8:HV6.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4E4A86B1EFC240139BCFDBE926CEA509" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt09.wav" + "TargetName" = "8:LaserFireInt09.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4F04DC56C05E4B2D92A0FFB539375F67" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POA.BGF" + "TargetName" = "8:POA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4F5C8391D1504DCDB16398AF7261F88C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\GeneratorSpin01a.wav" + "TargetName" = "8:GeneratorSpin01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4F9B75043D30449CBDA916764882EB29" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery02.wav" + "TargetName" = "8:Refinery02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4FBC935682E846478E4EA776C658C0B7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery02b.wav" + "TargetName" = "8:Refinery02b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_4FC2851FAF354399AF1BAA963F269598" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VLA.BGF" + "TargetName" = "8:VLA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_509FCFAB6F31424D998D7B090BDB99F3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VRC.BGF" + "TargetName" = "8:VRC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5157220481B74800A1168D77B95DFAF4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUT.BGF" + "TargetName" = "8:SUT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_51A35DD1D5A545E883760504BA741DDB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt03.wav" + "TargetName" = "8:LaserFireExt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_535318D023B841F198AE7CF47F8B6396" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ScoreKill06a.wav" + "TargetName" = "8:ScoreKill06a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_53F8E3D086724275A084A1E5F4CB43F0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUB.BGF" + "TargetName" = "8:BUB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_541E55D804394B7D9214E18307EDD93F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireIntEmpty.wav" + "TargetName" = "8:LaserFireIntEmpty.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_542C4AC1A34B4A08BC0AAEFE5D60C9DC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitInt01.wav" + "TargetName" = "8:RivetHitInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_546B8435FDB24BF5B097DF7E07C57F74" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RL2.BGF" + "TargetName" = "8:RL2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_54ABD31BD149480AB618CC4C3A0BDA51" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\TranslocationExt01a.wav" + "TargetName" = "8:TranslocationExt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_559449392BBF4D219DF6C8EF48699835" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\FuelTank01.wav" + "TargetName" = "8:FuelTank01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_55C0058E6ABF464DAB925A5B15DF2296" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineComboExt01a.wav" + "TargetName" = "8:EngineComboExt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_55F27B88F8CF49D2AD61B7840CB8C0E1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BP1.BGF" + "TargetName" = "8:BP1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_55F43589D0934583AD2E5BC4AC489A69" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH1L.BGF" + "TargetName" = "8:WH1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_56DA33BB18844334BF0377716A800D59" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BST.BGF" + "TargetName" = "8:BST.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_56F869100F304713BAD0311A03840C13" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAHEADM.BGF" + "TargetName" = "8:SNAHEADM.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_574C4AFBB73444DF9F5C1217066357A8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery06.wav" + "TargetName" = "8:Refinery06.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_574D7A8BD5AB45868BF8DC06F030C371" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PipeMachine02b.wav" + "TargetName" = "8:PipeMachine02b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_57C0CF903D7D4C888A34BBD8F06A2E22" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DeathInt01.wav" + "TargetName" = "8:DeathInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_588858D923FB475D8F7B5E4A761C355F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUC.BGF" + "TargetName" = "8:BUC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_58A4D240B09C466085E10123D05D106B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\ME2.BGF" + "TargetName" = "8:ME2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_58A66E7B7B114367B1E696495112C826" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUT.SKL" + "TargetName" = "8:MUT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_58A9F70C44B0493FBED8B96DA08CEEE9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CH1.BGF" + "TargetName" = "8:CH1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_58CDF0E23C61482482D365502B4416BB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OA3L.BGF" + "TargetName" = "8:OA3L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_593D64FDFA84403D86ACA6098429989C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAC.SKL" + "TargetName" = "8:LAC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5A522BC189854848BFABDFBD71F0A67C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAZDRIL.BGF" + "TargetName" = "8:LAZDRIL.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5B3B11EFB5314EA496E9BCD91839EF39" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\C8E.BGF" + "TargetName" = "8:C8E.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5B5E3647A7954ED0926FA15DBDFBA039" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MD5.BGF" + "TargetName" = "8:MD5.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5B7793B9762B46D98C38438B94A0EE5D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitCraft02.wav" + "TargetName" = "8:LaserHitCraft02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5B8B183D0462454294727A068FBF708A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RL3.BGF" + "TargetName" = "8:RL3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5C2AC87D42B94901922807907E384033" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt19.wav" + "TargetName" = "8:CollisionInt19.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5C3568CFD3B84B34AFFC5D6B8CCF9882" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDrill02a.wav" + "TargetName" = "8:WellheadDrill02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5C5A84733CDC4B368612AC1BBB09A0BC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME6.BGF" + "TargetName" = "8:PNAME6.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5C5B922BC16940DEA2675413F645FC2C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DEMOBOOM.PFX" + "TargetName" = "8:DEMOBOOM.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5CCD195A09B14F67AFF2CF937DD814D2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BR2L.BGF" + "TargetName" = "8:BR2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5EBE0AB1C56542A3A25AFE8D25352A73" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MD4.BGF" + "TargetName" = "8:MD4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5F5526CCE5B041A7816503D1019E237F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR4.BGF" + "TargetName" = "8:CR4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_5FE4BF2BD66E4F89B7905A832430FDCB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery03a.wav" + "TargetName" = "8:Refinery03a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_601C8190E84B414B888205AEDC32C687" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\RPDPL.INI" + "TargetName" = "8:RPDPL.INI" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6078A9EA852745AB924CA061033827C5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAC.SKL" + "TargetName" = "8:SAC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_61A8C1CDF6A542CAA1677EBCE252897E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PL1L.BGF" + "TargetName" = "8:PL1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_61DB2269F4A244C4B47B250465C41E6D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetFireCenter.wav" + "TargetName" = "8:RivetFireCenter.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_61E845324BE44FBEB6F320258769569D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CL3.BGF" + "TargetName" = "8:CL3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6202339998B046FD8105FD5D1914C87E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ViewSwitchLeft01.wav" + "TargetName" = "8:ViewSwitchLeft01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_62362B339209465CB1EFDC4CC03991C8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DoorMove02.wav" + "TargetName" = "8:DoorMove02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_628BEB5C6B7D4019A9AF5F9C86065F1B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POB.SKL" + "TargetName" = "8:POB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_635DD6C10A984A52859BBE2701B3129A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\GENB.BSL" + "TargetName" = "8:GENB.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_64543F2BDD094739BAB2D6E7E4BAB7BF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\AUDIO\\AUDIO.INI" + "TargetName" = "8:AUDIO.INI" + "Tag" = "8:" + "Folder" = "8:_30A8831869F24F1198873FCC45365678" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_64657C3E6EBB42FF8D508E1F4B39BA05" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ReverseThrust02a.wav" + "TargetName" = "8:ReverseThrust02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_649AD1F594ED44BDABA7601BA6DA0C9B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery07a.wav" + "TargetName" = "8:Refinery07a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_655F379A9A1C4324881C8F7BAB3B5C03" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUC.SKL" + "TargetName" = "8:MUC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_65E804474D6048829F02C7E078B3D628" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VTGRS.BSL" + "TargetName" = "8:VTGRS.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_65FD3035E25848DDA8942C8AEA6CC334" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt04.wav" + "TargetName" = "8:LaserFireExt04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_662CE563A28A4DF98E0654C19483E201" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt03.wav" + "TargetName" = "8:LaserFireInt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_669B48D145DD4126BB2BCEDE35031F00" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\ME1.BGF" + "TargetName" = "8:ME1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_66DCA3126F7C45828CA03DEA62AADD03" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DEMOFUSE.PFX" + "TargetName" = "8:DEMOFUSE.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_66DCE3D20AC24C7886780BA071A92C83" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR7.BGF" + "TargetName" = "8:CR7.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_67116D5D859B42A0844BB419EA7AB645" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt02.wav" + "TargetName" = "8:LaserFireExt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_676E4FD03F694EEE8C7FD29DBD351114" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VCELT.BSL" + "TargetName" = "8:VCELT.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_69527D6A172B473DBB34DB812E9F9CEC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PP1.BGF" + "TargetName" = "8:PP1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6971E053929C4EAEB089D2C70A3F0D9A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PresetSwitch01a.wav" + "TargetName" = "8:PresetSwitch01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6A123C2CF3394C35B968F081D411F1DD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\TEST.PFX" + "TargetName" = "8:TEST.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6A29ABF537B840A583BE487707A61D6D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery06b.wav" + "TargetName" = "8:Refinery06b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6A42913E1A9B405CB6B46938998BD02C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VRSUN.BSL" + "TargetName" = "8:VRSUN.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6BAAC628B45E4F899D9F9C62D6FA2C74" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BR1.BGF" + "TargetName" = "8:BR1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6BDDBC9AA63940BD9F576A2D199BF5DE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery04.wav" + "TargetName" = "8:Refinery04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6BE3C280BF2F45D882A7772AE197948A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNA.BSL" + "TargetName" = "8:SNA.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6C3E46E7DDF843E8ADE028424ADF11F8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CTF.BGF" + "TargetName" = "8:CTF.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6D7BA92A22C74284B437DAA3F362F41D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\GR1L.BGF" + "TargetName" = "8:GR1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6D9DAF26D0074D92AD0D0A32EA4A6AED" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MD1.BGF" + "TargetName" = "8:MD1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6E3196E5E20E491D9ED0C43A3EB45B21" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery05a.wav" + "TargetName" = "8:Refinery05a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6F73842C3A4840AA814178FCDA4E68DD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitExt01.wav" + "TargetName" = "8:LaserHitExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6F7ADEEA4317497D9E00D0E99C658367" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUN.BGF" + "TargetName" = "8:SUN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_6FC35F9D64AC43938FCF40A89D6B429A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt10.wav" + "TargetName" = "8:LaserFireExt10.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7007A8AEF8644163A26AF5EFDA8315F4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CT1.BGF" + "TargetName" = "8:CT1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_704C22C1F2C0412E86766E0D88F53DBA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ScoreZone15.wav" + "TargetName" = "8:ScoreZone15.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_707EEE4837AB47609AE1192B59F37CCA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH8.BGF" + "TargetName" = "8:WH8.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7096B7259E274A1A94A143B450D00D91" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PresetSwitch01.wav" + "TargetName" = "8:PresetSwitch01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_70A5D4A0573B44EAAE0453EE443379C8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAN.SKL" + "TargetName" = "8:SAN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_70F1E09D77A742948F239221D85EB631" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAC.BGF" + "TargetName" = "8:MAC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_71230B4F0EF74198B0781C286469E5DA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HV1.BGF" + "TargetName" = "8:HV1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7128E161694446C49902E18D813DD83A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RL1L.BGF" + "TargetName" = "8:RL1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_72C7D9DED4194D308AB817BF91340809" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitExt03.wav" + "TargetName" = "8:RivetHitExt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_72D69E85A4F54D518C1ACDEA8D27ACBB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAENTER.BGF" + "TargetName" = "8:SNAENTER.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_733C57D6ABA24828B9BFEB2CF0E583F0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt03a.wav" + "TargetName" = "8:BoosterInt03a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_74A904F3F6114528B5903E738F69A0D9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUN.BGF" + "TargetName" = "8:LUN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_74DE6F4A96894296B124F27E4FFF7738" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\GENC.BSL" + "TargetName" = "8:GENC.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_75DECD23CA754B27A7E43B392A938D1D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\OreDrop02.wav" + "TargetName" = "8:OreDrop02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_765DC462B638482CAB3542C19539968F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CL1.BGF" + "TargetName" = "8:CL1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_76706575F9CA47ADB8E4F9C1F5B47820" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUA.SKL" + "TargetName" = "8:MUA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_767776CAE6794F4F808DD65BB60626EB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HV2.BGF" + "TargetName" = "8:HV2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_76CB2D03CC85408BB96278381FDB6674" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CREL.BGF" + "TargetName" = "8:CREL.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_76FAF7920E19410E9955C0E5EEEA427A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUS.SKL" + "TargetName" = "8:DUS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7713EA24E0C747169ABFA06661161A31" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN4.BGF" + "TargetName" = "8:CN4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_77B39A26E82D416ABA48C98A1A070C84" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\RPL4.RES" + "TargetName" = "8:RPL4.RES" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_784FB82409D347A483C863A9640AEEFF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CL2.BGF" + "TargetName" = "8:CL2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_78DE276F3366461183FB7B2EC53C1413" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUC.BGF" + "TargetName" = "8:SUC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_794241C50BFD42B4A1A43B6A6E00BB88" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUB.SKL" + "TargetName" = "8:BUB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_79DF83F17B63454DBE3FAD99A242C852" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ReverseThrust01.wav" + "TargetName" = "8:ReverseThrust01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_79E7D5CA6F32455499E9FC6FA7106793" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAT.BGF" + "TargetName" = "8:MAT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7A4DA999016643C191E9E1D96E28A8FE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MineRelease01a.wav" + "TargetName" = "8:MineRelease01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7A54E9C9DFE24822ACDB4919D0BDC89B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WT2L.BGF" + "TargetName" = "8:WT2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7A9616B456964166A043ABB9FC7D193D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt04.wav" + "TargetName" = "8:CollisionInt04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7B0A698BDB0A4DC6918C77B5391597B0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ConfigSwitch01.wav" + "TargetName" = "8:ConfigSwitch01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7B974691977D4316B33641AA9D695B1F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ScrapeInt01.wav" + "TargetName" = "8:ScrapeInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7C3ADC756F184FDC81A12DC180394CC1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\FlameMachine01a.wav" + "TargetName" = "8:FlameMachine01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7C5B474CAC974521AB38CF1C9553F2E4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HVA.BGF" + "TargetName" = "8:HVA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7CBB75EB2085440AB9430D81A85E98BE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DeathInt01a.wav" + "TargetName" = "8:DeathInt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7D8E17F3FB48475281B3DE82AC8C2946" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt09.wav" + "TargetName" = "8:LaserFireExt09.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7DB6C05F77144714B18F077A782F6DEC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DeathExt01.wav" + "TargetName" = "8:DeathExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7DB95B3CCFA7405FB55AC236FD2397D5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR3L.BGF" + "TargetName" = "8:CR3L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7E221AF8A7B24F47BD0E945271F27F1B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt03.wav" + "TargetName" = "8:CollisionInt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7E9AA57CFC9C4C96AC619E49B2AE68BB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDevice01b.wav" + "TargetName" = "8:WellheadDevice01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7EB18046FF51494FA2B0ED027C61EC33" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUN.SKL" + "TargetName" = "8:SUN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7EEAE2BC1F8C4C568AF0DF2C9ACD9750" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\GeneratorDrone01.wav" + "TargetName" = "8:GeneratorDrone01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7F51E28CD57746659CE55C6E2F17657B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAS.BGF" + "TargetName" = "8:LAS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7FE0771341C8413EA1327DFF7CFE83AA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAC.BGF" + "TargetName" = "8:LAC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_7FEC578B37B04965A7998A1B17D0D0DA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt02.wav" + "TargetName" = "8:CollisionInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_800EAC2975CF453EAFD22FCD372F3A5B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PON.SKL" + "TargetName" = "8:PON.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_806B853DFD9A48D2828AA43393205C29" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME7.BGF" + "TargetName" = "8:PNAME7.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_81136CBCE0CA4555B295D53DFE8EB12D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAB.SKL" + "TargetName" = "8:LAB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_816063DFB0794169BED294B6750BBB74" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Preparing-To-Translocate.png" + "TargetName" = "8:Preparing-To-Translocate.png" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_816092952B87443C81ADD0AB0C88594B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PZ4.BGF" + "TargetName" = "8:PZ4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8197298C7A5F49878165430B60DB3C8C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt12.wav" + "TargetName" = "8:LaserFireInt12.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_81D4A937BA6C489D80CF66F55466F8E8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\TranslocationExt01.wav" + "TargetName" = "8:TranslocationExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_824BBD8320564C2899D54394A4645E66" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH2L.BGF" + "TargetName" = "8:WH2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_82BB9B7DA0F446F29FE8CF3B1D4A03A8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUS.SKL" + "TargetName" = "8:LUS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_82D0C47D5A0C4CDFA11826968542C889" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt04.wav" + "TargetName" = "8:LaserFireInt04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_834C4F4EE03D4C41AD978ACE2DAF03FA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Horn01a.wav" + "TargetName" = "8:Horn01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_839324D3B7AC4B85A89496BD83B71577" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CRC.BGF" + "TargetName" = "8:CRC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_83B7B90885DA4340A50905AC9F13F2AD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineThrustInt02a.wav" + "TargetName" = "8:EngineThrustInt02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_846104FF50A84EE1892CE4B7866ED04B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CQ1.BGF" + "TargetName" = "8:CQ1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_855B0948A1DA45E997A8A4E90354B985" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Translocation01.wav" + "TargetName" = "8:Translocation01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8586A310DD5C43B3AB8620F6E85403FC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Generator01a.wav" + "TargetName" = "8:Generator01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_858CF8BA47B04FBC8E1463D95B7CF835" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OA3.BGF" + "TargetName" = "8:OA3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_85A90E7C6702488B9E6DC6E51939FA96" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\TEST.TXT" + "TargetName" = "8:TEST.TXT" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_85B49CE782CD45F181FBE8A28B460BE5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ReverseThrust01a.wav" + "TargetName" = "8:ReverseThrust01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_86215EF08DFF4C9B8EF1F1A5F652689C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RadarButton01.wav" + "TargetName" = "8:RadarButton01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_86745BA7D727464DAFDD7CFDEE3C7833" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUT.BGF" + "TargetName" = "8:BUT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_86DBD25DAB91430EBF9760DEF3A70221" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAT.SKL" + "TargetName" = "8:MAT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_871C6181986D4B689F8437AE6653F736" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RP2L.BGF" + "TargetName" = "8:RP2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_87519A8BCC3F4F4BB072A8F3E45DBC6F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt01.wav" + "TargetName" = "8:CollisionInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_87D23EC11F3A4FE08BD85CB76B502FAE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitInt01.wav" + "TargetName" = "8:LaserHitInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_88C02CDA20734E338A8AF267C37BC1DA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt17.wav" + "TargetName" = "8:CollisionInt17.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_893D4C0AE0124EDF987439A8399CFBEB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RL1.BGF" + "TargetName" = "8:RL1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_899DD448CCF4429787AA1BCC19A93394" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Translocation02.wav" + "TargetName" = "8:Translocation02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8A20CE81285442139AD39BE0C9097698" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SC500L.BGF" + "TargetName" = "8:SC500L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8A3745B45B694B9EA9DF656F6A01C08D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUS.SKL" + "TargetName" = "8:MUS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8A8A889C984440778AC56862DC1C2D24" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\vgcorps.png" + "TargetName" = "8:vgcorps.png" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8AA079A72E07418987AF2B80C5D9E139" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUC.SKL" + "TargetName" = "8:BUC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8ACE3E918F3D444A91923FA5DBA18ED0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DEMOBURN.PFX" + "TargetName" = "8:DEMOBURN.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8C4C93FD223A456AA66C9750AA73C33C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RF1.BGF" + "TargetName" = "8:RF1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8D4AD3B4DC0A4876914A4CD7260A7F55" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MaintPulse01.wav" + "TargetName" = "8:MaintPulse01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8D767AA1CAE84567A062F1AD1BFD4FF8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAS.SKL" + "TargetName" = "8:SAS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8E8A2105C6094997ACD176DC037C7DB7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ModeSwitch01.wav" + "TargetName" = "8:ModeSwitch01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8EC0C662F73A445ABEDDBF3D1B4D2C7A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN5.BGF" + "TargetName" = "8:CN5.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8EE9DC96393D4E8C9C4D75C4C7E3ECFF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POT.BGF" + "TargetName" = "8:POT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_8F894C8004264ACF8F624A680724BA62" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BN1.BGF" + "TargetName" = "8:BN1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_915DCBA3B2A44B0EB7AE59C5675F5081" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Horn01.wav" + "TargetName" = "8:Horn01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_91840158FD984BBBA4D0B5C1E81E0DDA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Chute01.wav" + "TargetName" = "8:Chute01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9192BA80F9C34D128348A9B6453CF96C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MED.BGF" + "TargetName" = "8:MED.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_92CCF1C3663440A98FF87EFD29B5FFFD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BMAP.BSL" + "TargetName" = "8:BMAP.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_93D082CB52CB43A78E2F6A7FFA694472" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BR4.BGF" + "TargetName" = "8:BR4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_93F4CED32CF547C78A25477C7562DF1B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME2.BGF" + "TargetName" = "8:PNAME2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_940B6C02C3004711AFE9F8E627FDEC9D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ReverseThrust02.wav" + "TargetName" = "8:ReverseThrust02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_956D2DAAA2F548EDBA45BC768B843D7B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Loading-Stick.png" + "TargetName" = "8:Loading-Stick.png" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_95BD547E1CB44726BF661E332A70E7E0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MB1.BGF" + "TargetName" = "8:MB1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_964E7CB77ECD4D2C82D9DF44B243CB91" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterLoopExt01a.wav" + "TargetName" = "8:BoosterLoopExt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_98236B2E08EA43E28B00F88C7FADB74B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE8.BGF" + "TargetName" = "8:PLACE8.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_982686BCAD3140B888049A9C903EF254" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt05.wav" + "TargetName" = "8:CollisionExt05.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_98326B986BAE43238328DC0E8C65551D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUA.SKL" + "TargetName" = "8:SUA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_98346740D9A64A849FD702022A3BA319" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\ODC.BGF" + "TargetName" = "8:ODC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_98BF17F8ACED41CEB8039AB76A876B67" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUB.BGF" + "TargetName" = "8:DUB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_98D0392830E64D419D6F26FF2524EE46" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN1.BGF" + "TargetName" = "8:CN1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9932333F26AB477DAC558CF91689D2AB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitExt02.wav" + "TargetName" = "8:LaserHitExt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_99B5422E6CFD439DBD501650B5A3ACC8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH5.BGF" + "TargetName" = "8:WH5.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_99E8818FD556473FA5EC9B22338CECD8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLT.BGF" + "TargetName" = "8:PLT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9A2B42458215440D976FD8B3959B3F40" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE1.BGF" + "TargetName" = "8:PLACE1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9AAB6F70632C4B81A1AB8766426E4761" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHItExt05.wav" + "TargetName" = "8:RivetHItExt05.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9ADE9F6AF52F49469139861E010229D0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VM1L.BGF" + "TargetName" = "8:VM1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9B50B625BAAE4ABEA0B6A704B2A18C0C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt14.wav" + "TargetName" = "8:LaserFireInt14.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9BF0C1F4EFD04347AA9ED9F03FDDD6BD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUN.BGF" + "TargetName" = "8:MUN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9CD33EB2B23447A9AA87A40C42585926" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNALOXM.BGF" + "TargetName" = "8:SNALOXM.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9E9A5B189EA74A1AAB71F70A6C8F540E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE2.BGF" + "TargetName" = "8:PLACE2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9EA06672F2503924A09793056DF7EA70" + { + "SourcePath" = "8:libsndfile-1.dll" + "TargetName" = "8:libsndfile-1.dll" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9F08FD93B139474D904B6C727262609F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt09.wav" + "TargetName" = "8:CollisionInt09.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9F44C5F8DC3446B9A5738D140BA86553" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery05.wav" + "TargetName" = "8:Refinery05.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9F6BB8CB467842AFB543F7AA80AE9C8D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDrill02.wav" + "TargetName" = "8:WellheadDrill02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9FAAFE7B42FB4DE6874998CA968814CB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH9L.BGF" + "TargetName" = "8:WH9L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_9FEB7C7D606549ED83EC352ADB0E9263" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUMMY.BMF" + "TargetName" = "8:DUMMY.BMF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A01A00C2B48B413EA8F75E79D2D7FB41" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH5L.BGF" + "TargetName" = "8:WH5L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A05FDFED8F824FF5A5B3B486568A5AEB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OD1L.BGF" + "TargetName" = "8:OD1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A0BB741F77E24DF6BEAB99D2A9C23BD3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RP2.BGF" + "TargetName" = "8:RP2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A0E75FACF5B0481FB71F93079FC81DA6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAN.BGF" + "TargetName" = "8:BAN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A1394037A535467A83F935D776C4BC97" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PM1.BGF" + "TargetName" = "8:PM1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A17BB4216E6C4C0791CD8D0144CEDC1A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DoorOpen02.wav" + "TargetName" = "8:DoorOpen02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A18DDE22A53B46958C8A724B9CA16F57" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MD3.BGF" + "TargetName" = "8:MD3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A1B5B6053891454D891630A99A8F4EC0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\GR2.BGF" + "TargetName" = "8:GR2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A1BE3311CF934116823B10F06FEADD56" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DRW.BGF" + "TargetName" = "8:DRW.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A23B8A6701214753BF781C0ACE1421A9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DR1L.BGF" + "TargetName" = "8:DR1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A26E7FD32AF94C1AB26938D16702D7FA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DoorClose01.wav" + "TargetName" = "8:DoorClose01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A43AC737BFBB4313AC9B1BF70A25F167" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt07.wav" + "TargetName" = "8:CollisionInt07.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A462A036B5BC4211AB8E4A4C3F4F5170" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt15.wav" + "TargetName" = "8:CollisionInt15.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A590A3A6826D4B149C1BD0C8040EFFE1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAB.BGF" + "TargetName" = "8:LAB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A61C5D96537C4327B8FB1B1FFA09B952" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAN.BGF" + "TargetName" = "8:MAN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A6B268C4F2BD40C0BFB08758E92A9221" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RF1L.BGF" + "TargetName" = "8:RF1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A6B6DD87A90642259063A8EB75064260" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME8.BGF" + "TargetName" = "8:PNAME8.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A703E553EABE4219BC476557B4A81A0A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SPARKS.PFX" + "TargetName" = "8:SPARKS.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A72B3F8FB6CD469691414B1E19990EFC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUC.BGF" + "TargetName" = "8:LUC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A7AB9D0C1DA74866B0916861AC10D868" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineDroneExt01a.wav" + "TargetName" = "8:EngineDroneExt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A823D68E199B426E98D9C631F8524EF0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt05.wav" + "TargetName" = "8:LaserFireExt05.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A86B2A50B9DE43039F0A67031E1DA4BF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POT.SKL" + "TargetName" = "8:POT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A89D502E134B4EFCB8843E719EA1E093" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDrill01b.wav" + "TargetName" = "8:WellheadDrill01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A8E0F5EA7DA2443793BF4188335E0F4A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAB.SKL" + "TargetName" = "8:BAB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A9107D25ED2C47C2BFADCA3EEE5116B3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WCIRCLSH.BGF" + "TargetName" = "8:WCIRCLSH.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A9900978E7D54EF2BFDE5A3F844D1CE4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PZ3.BGF" + "TargetName" = "8:PZ3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_A9B3F73D4DA4484383D0C6807CDDAFEF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineThrustInt02b.wav" + "TargetName" = "8:EngineThrustInt02b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AA711F1131EF44118F316155463D6F71" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitExt04.wav" + "TargetName" = "8:RivetHitExt04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AABDBC7E0DC94B21938D60956A0A8E8F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitCraft01.wav" + "TargetName" = "8:RivetHitCraft01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AAD7D5E9A527470F812C8556036DA67A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR2L.BGF" + "TargetName" = "8:CR2L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AADA87793CBE4C59A1DE256457B307AB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\FT2.BGF" + "TargetName" = "8:FT2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AB2F56AE86E146D2A1B424B05DD68426" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VRAZZ.BSL" + "TargetName" = "8:VRAZZ.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ABC3D490BB264CB0824DF148501EE84B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POC.SKL" + "TargetName" = "8:POC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ABD46A949A494DE7AB61B3F069B3F832" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUC.SKL" + "TargetName" = "8:DUC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ABED536639A54955BF834CDAA79D2FE3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAA.SKL" + "TargetName" = "8:MAA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AC7DA4E6417743C792C9DCF5A050126A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt04b.wav" + "TargetName" = "8:BoosterInt04b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ACAD52699F4945C0973D6B583F896A09" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUB.SKL" + "TargetName" = "8:DUB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ACB3A85A971349BE9BDC019849DBEB3A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CP1.BGF" + "TargetName" = "8:CP1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AD5A9DD370A7492EAE52EA10E6176CD5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HV5.BGF" + "TargetName" = "8:HV5.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ADDE147893CD47778EF548A116C2D402" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HV4.BGF" + "TargetName" = "8:HV4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AE1163E7B39C4B53AA50A84CA3E22109" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME5.BGF" + "TargetName" = "8:PNAME5.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AE19D3DE3B4145FFA8CC3D5E29492DE7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VDSRT.BSL" + "TargetName" = "8:VDSRT.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AE8F8A8C376B42958A052A945D7129B6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DeathInt01b.wav" + "TargetName" = "8:DeathInt01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AE91494676254C44877C5B7FEC52E864" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MISSILE.BGF" + "TargetName" = "8:MISSILE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AEFF7E503315473EAAA2A683F629A1D6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt06.wav" + "TargetName" = "8:CollisionInt06.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AF11DDD8E30A4B8E8DD8AA6F86E30D30" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt18.wav" + "TargetName" = "8:CollisionInt18.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_AF348362A33A41AB930013690C5212D8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VKRON.BSL" + "TargetName" = "8:VKRON.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B03BAA5575424943933E54B5EFE2851B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RPFX.BMF" + "TargetName" = "8:RPFX.BMF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B071CA65CEF143D9AD061DCA589F2B9B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt05.wav" + "TargetName" = "8:LaserFireInt05.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B0759DA28A5646F6865486B794049973" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt07.wav" + "TargetName" = "8:LaserFireExt07.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B171969183564D47A9987C6B7829A33A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VFLMS.BSL" + "TargetName" = "8:VFLMS.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B27DABBED93B4E40BD16B954DD99E2CA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\HVAC03a.wav" + "TargetName" = "8:HVAC03a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B321287E898F4A2EBE647CA883764DF1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\FT1L.BGF" + "TargetName" = "8:FT1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B380834BF5E44984869FA545CD86B1CE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OD2.BGF" + "TargetName" = "8:OD2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B3966FA2BCBB414292487D2E8C92C413" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt08.wav" + "TargetName" = "8:CollisionInt08.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B43ED801E6884338833C213DDC6F45DD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUN.BGF" + "TargetName" = "8:DUN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B478AEEFA5F547C29D919199CFC9A7B1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUS.SKL" + "TargetName" = "8:BUS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B4EC427F8AFF40B7A10E9E2070D270FA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUT.SKL" + "TargetName" = "8:SUT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B5950BCC2B904E61AA95D3F379AF7580" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH9.BGF" + "TargetName" = "8:WH9.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B5C266502FD64711B048F1C0D8AEB202" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\INTA.VTX" + "TargetName" = "8:INTA.VTX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B62CD104FDE045F290B855BF4E9BF514" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineThrustExt01.wav" + "TargetName" = "8:EngineThrustExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B7038776CF974FFA9845C1E9C4339098" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR1A.BGF" + "TargetName" = "8:CR1A.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B706E7F4F96249A8959A7B9ADBC03512" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt05.wav" + "TargetName" = "8:CollisionInt05.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B70D9CC6F6694962A4EC847A34D5EE11" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VRT.BGF" + "TargetName" = "8:VRT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B8B195763460402CA0195A22EE4D7A61" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CT1L.BGF" + "TargetName" = "8:CT1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B8DFC81368274017BD88042182170735" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterExt01.wav" + "TargetName" = "8:BoosterExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B90D976B8E204DA18EE325E2E8BFD12F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WCPTEMP.BGF" + "TargetName" = "8:WCPTEMP.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B922AF7E3FF943BD93E0FF0BEA63E162" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RP3L.BGF" + "TargetName" = "8:RP3L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B93F80AA91984937974B581C7A429AD0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDevice01a.wav" + "TargetName" = "8:WellheadDevice01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B952B5BB4930493C8C6A1B5C6CF89C82" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitInt02.wav" + "TargetName" = "8:RivetHitInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B994F7FA427F4B3DB3F7DDE0E458EBF6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUA.BGF" + "TargetName" = "8:SUA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_B995049EDF294EE19958B6D9A44768EE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE5.BGF" + "TargetName" = "8:PLACE5.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BAC2AFAB06364837A53E782F3A406759" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DR2.BGF" + "TargetName" = "8:DR2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BB17F6A6CA3B485F88C9ED9D6CBD3FE5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt10.wav" + "TargetName" = "8:LaserFireInt10.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BB5BDE36E7554E959AACBB732B14714B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt01a.wav" + "TargetName" = "8:BoosterInt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BBFBD95853E6448A953FC476C9BA209B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt09.wav" + "TargetName" = "8:CollisionExt09.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BC8079A4AAE94C63A633D4C7039E24B3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUN.BGF" + "TargetName" = "8:BUN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BCBECAFAA0644F93B58A9170B7F38050" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUN.SKL" + "TargetName" = "8:LUN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BDB3E818B9F73D1C6A5BFEFFF8B70912" + { + "SourcePath" = "8:d3dx9_37.dll" + "TargetName" = "8:d3dx9_37.dll" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_BDF2AF4805374D53A15E77D11C9F3C67" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CLD.BGF" + "TargetName" = "8:CLD.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C00FA694A6384FBDBDA91A1F54BD0301" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN3.BGF" + "TargetName" = "8:CN3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C2190773C36F42169C12DFEB251DEC59" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt13.wav" + "TargetName" = "8:LaserFireInt13.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C367B64F8DAC44888907A119784A71EB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNADOS.BGF" + "TargetName" = "8:SNADOS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C369D964974A45759FD353DAFFEEEDA4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VLN.BGF" + "TargetName" = "8:VLN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C3D03C578F88469C871312C0F933D280" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MD2.BGF" + "TargetName" = "8:MD2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C3DAC7C45CBD4DF7A6CD3478C7750714" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAHAZ.BGF" + "TargetName" = "8:SNAHAZ.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C3F762C2BFFE43C695223C813AEDAB86" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery02a.wav" + "TargetName" = "8:Refinery02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C414AA643336457EA6711056B254AE5C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OD3L.BGF" + "TargetName" = "8:OD3L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C4E1B1441FC80FE779D04EDF089D8DC3" + { + "SourcePath" = "8:DINPUT8.dll" + "TargetName" = "8:DINPUT8.dll" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C516E1EDF0394BEFBDA86880B2A57BA8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUS.SKL" + "TargetName" = "8:SUS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C7D755867627491AB30C877CFA743E9F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VLT.BGF" + "TargetName" = "8:VLT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C80470302D9B43BEBAF5F63B78B7B672" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt01b.wav" + "TargetName" = "8:BoosterInt01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C87BEA81A2D54168BBAEE6946D43ED0D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME3.BGF" + "TargetName" = "8:PNAME3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C9926302F73943EABB67D9F69F38BBED" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WHC.BGF" + "TargetName" = "8:WHC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_C9E5DF4709C54AADAFBF3370919AB2C6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery01a.wav" + "TargetName" = "8:Refinery01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CAB47663EC994744AF473C21C314674C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitInt03.wav" + "TargetName" = "8:LaserHitInt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CAE514C732AC4575AE5006369FE026C6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VLC.BGF" + "TargetName" = "8:VLC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CBEC3A60157942B1AA5E42E883AC6BE0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\HVAC01.wav" + "TargetName" = "8:HVAC01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CBF936AC750A4176881CE75B2A80CFBE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAS.BGF" + "TargetName" = "8:BAS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CC31B03F6CA1446DA9AEB464CEEDB4C6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH4L.BGF" + "TargetName" = "8:WH4L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CC476CE5007D447AB80FD7F9DC335EBA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HV7.BGF" + "TargetName" = "8:HV7.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CCB73795DE4849C09596DF8A5257AA3C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitCraft02.wav" + "TargetName" = "8:RivetHitCraft02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CCF4E0ECF4CD4A89A231EC1BF9402D00" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BUA.BGF" + "TargetName" = "8:BUA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CD9A527D0EC9464FB058B30D5A8EB6AA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUN.SKL" + "TargetName" = "8:MUN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CE3A71F8135D4ECB9C41BA84CE65BC72" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\HVAC02a.wav" + "TargetName" = "8:HVAC02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CEB37922D72B40E1900864B8E50F4135" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt03b.wav" + "TargetName" = "8:BoosterInt03b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CEE14DCF7A2543C09AA6536BF01C0115" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\ReleaseMine01a.wav" + "TargetName" = "8:ReleaseMine01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CF2E8C057F9A4FD484ECA7F76BF56FAF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BMAP.BMF" + "TargetName" = "8:BMAP.BMF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CF371FFE46F44F03A3718A03E31B5CBA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\temp-old1.wav" + "TargetName" = "8:temp-old1.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CF3D4D2183AF4508B39A73F339280F13" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery04a.wav" + "TargetName" = "8:Refinery04a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CFA0056EEE3A40ABBDB6E439AE588781" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OD3.BGF" + "TargetName" = "8:OD3.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_CFEE6AC9A962489F81556B0D427C782C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DoorMove01.wav" + "TargetName" = "8:DoorMove01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D083C18D8C7144CD951E244B2C946D2D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BAC.BGF" + "TargetName" = "8:BAC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D0A7CFC6B2C94CCAABDA85AE147F8E0B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WT1L.BGF" + "TargetName" = "8:WT1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D0BE6EECF08641F6A074A7190C3A9AC1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt11.wav" + "TargetName" = "8:LaserFireInt11.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D12262ADD74541CD9D829AF2022835EC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CockpitWindRush01.wav" + "TargetName" = "8:CockpitWindRush01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D1259B60EB1D4988AECA3913786AB522" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME1.BGF" + "TargetName" = "8:PNAME1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D1570E9AFD8D42CD894FC961AC5EA947" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MUT.BGF" + "TargetName" = "8:MUT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D1C6D397DBAC463CAB2F5014305A31E6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Translocation02a.wav" + "TargetName" = "8:Translocation02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D2360210FB5E49DD8433868A9FA91642" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAALE.BGF" + "TargetName" = "8:SNAALE.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D26D86A965B945599250B7EC28D0C33F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUN.SKL" + "TargetName" = "8:DUN.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D2EDD1255850445095E375ABDC16C35A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionExt01.wav" + "TargetName" = "8:CollisionExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D339C82002C545D5ACB12FC254F4AE1A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt06.wav" + "TargetName" = "8:LaserFireExt06.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D351E08D7E8744B7987CB9588B2DB49B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RadarButton01b.wav" + "TargetName" = "8:RadarButton01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D36F42FA834E4DA4A3E33A4868C56A58" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN3U.BGF" + "TargetName" = "8:CN3U.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D431DC980F7F4ED3BDB29AC735D98BDC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR6.BGF" + "TargetName" = "8:CR6.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D510C71F91F54973A196D41181FC5E9A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNASPDS.BGF" + "TargetName" = "8:SNASPDS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D52C3635BDE34B0EB82E8CE9C54F7B13" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CockpitWindDrone01.wav" + "TargetName" = "8:CockpitWindDrone01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D53367CBD47F4D63AA488641D3133102" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH6.BGF" + "TargetName" = "8:WH6.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D5972918583045B69AE2B6B0B3616AB6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SAC.BGF" + "TargetName" = "8:SAC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D5C0254D502543A081B5F1100D59CB76" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUT.BGF" + "TargetName" = "8:LUT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D6DBC86D78B742E4AC0E4A7583944EFB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR8.BGF" + "TargetName" = "8:CR8.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D777C2ADD68B40A2BACA358D9F61DEBB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OAO.BGF" + "TargetName" = "8:OAO.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D8871C8E22C74699B0BDCAE7DAE3E6DE" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\DoorClose02.wav" + "TargetName" = "8:DoorClose02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D8CE594650CF5AF84377188D03CC3689" + { + "SourcePath" = "8:d3d9.dll" + "TargetName" = "8:d3d9.dll" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:TRUE" + "IsDependency" = "11:TRUE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D8CE7F54A3E34564A72D44E31C3027AF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN7U.BGF" + "TargetName" = "8:CN7U.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D90020ABC89E40F795FD564263F11C13" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VHWII.BSL" + "TargetName" = "8:VHWII.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_D930F8355F704FFDBED150BDFD7B9822" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery07b.wav" + "TargetName" = "8:Refinery07b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DA1B972A4D594602A197A27C85E0F12C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PL1.BGF" + "TargetName" = "8:PL1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DA1C22D901FF4A1A898B93DC2EBC22B8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BN1L.BGF" + "TargetName" = "8:BN1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DA3BA11DCF0341ECB20CB36A7EAAB6F4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\HVAC03.wav" + "TargetName" = "8:HVAC03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DAC9C7B9FF374A1787C57BE20B612374" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR2.BGF" + "TargetName" = "8:CR2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DAF5EA8366CA4ECF9C42F8883E78575A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUMMYENG.BGF" + "TargetName" = "8:DUMMYENG.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DB1850DD1C254191A7927468026621C7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH2.BGF" + "TargetName" = "8:WH2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DC6320EAABE742ACB727727053F37286" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VGIRF.BSL" + "TargetName" = "8:VGIRF.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DCED0953BF384856B9A0CFDDA0BC3CF1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\BoosterInt04.wav" + "TargetName" = "8:BoosterInt04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DD47D84330F7480AB3888C924FEB6DA7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\CollisionInt16.wav" + "TargetName" = "8:CollisionInt16.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DDAED51D890E42CE9694521BB2566863" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineDroneInt02a.wav" + "TargetName" = "8:EngineDroneInt02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DDC2C1F1FEC348068F4D814EC3E4A837" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VRN.BGF" + "TargetName" = "8:VRN.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DDD4C7E5D8BC473BB9EDA4F350D25B8E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitCraft01.wav" + "TargetName" = "8:LaserHitCraft01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DDE4217E8AC040D4B13863F2ADEC5DF3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineComboExt01b.wav" + "TargetName" = "8:EngineComboExt01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DE6F47C33944413AA4AE9FAA15C89C47" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitCraft03.wav" + "TargetName" = "8:LaserHitCraft03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DE79ABB414D747459945C99E52D98EE8" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\Refinery01b.wav" + "TargetName" = "8:Refinery01b.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DEC8F7F34C9A4AC1B27554BEEE472AD6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUT.SKL" + "TargetName" = "8:LUT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DF3CAACF253441E7B0D939FE870D5CEA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PNAME4.BGF" + "TargetName" = "8:PNAME4.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DF49BEE3849B42A5B65317D56EC52604" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUT.SKL" + "TargetName" = "8:DUT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DF7D953122A54A1E93E32D4469B91DC1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineComboExt01.wav" + "TargetName" = "8:EngineComboExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DF82B6FC5E4E40AC8E86BC92661C812B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAC.SKL" + "TargetName" = "8:MAC.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_DFDD4383FDA5406891A567923C7B7F2A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\INTG.VTX" + "TargetName" = "8:INTG.VTX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E03025BAC06B49B9860A5213C36233E2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAA.BGF" + "TargetName" = "8:LAA.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E28E8D1F1B0B411581164F6A67A2F02E" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RPCULT.BMF" + "TargetName" = "8:RPCULT.BMF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E292B767DF3A4EA2AE88686510DA1C61" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OD1.BGF" + "TargetName" = "8:OD1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E3A41390879A42DAAA440C02C85BECCF" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PZ2.BGF" + "TargetName" = "8:PZ2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E3C9633B5FB94F39B718237C7FFDE1F3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\PLACE7.BGF" + "TargetName" = "8:PLACE7.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E43763E59150433C860C42E39A41EA3D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\FlameMachine01.wav" + "TargetName" = "8:FlameMachine01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E4A252D4AA2A457C8B7AC6FF5DBEFEAC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAWORK.BGF" + "TargetName" = "8:SNAWORK.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E4DEF65130E8495A8D8A6B6A4D9EF85C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUA.SKL" + "TargetName" = "8:LUA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E4E47EFE352F4EDF8F20E48B638D5DBD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR1L.BGF" + "TargetName" = "8:CR1L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E578208A56304B1AA57121B2398AF048" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CRP.BGF" + "TargetName" = "8:CRP.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E58A394B88D24093A8F7CC888914FF3F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SMOKE.PFX" + "TargetName" = "8:SMOKE.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E73992158C294F90978497B9C0B1A723" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineDroneInt01a.wav" + "TargetName" = "8:EngineDroneInt01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E7451E63031A4FC7B7524D2149E78308" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUS.BGF" + "TargetName" = "8:LUS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E7C217F79900404CA0F61323C1B06C1D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetEmpty01.wav" + "TargetName" = "8:RivetEmpty01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E87D21FC3A3B4BF982016C3434257169" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\POS.SKL" + "TargetName" = "8:POS.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E8A5E4D4FF4E40BF9B78C7AA8C0AFD96" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\JOYSTICK.INI" + "TargetName" = "8:JOYSTICK.INI" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E92105A519B64C2F8B1148553B809ADD" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR1.BGF" + "TargetName" = "8:CR1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_E991EC30E5B74E14AA495D2DA1E138E9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAT.BGF" + "TargetName" = "8:LAT.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EB1FC9E499F543AE9B723D1D5A27FD79" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN6.BGF" + "TargetName" = "8:CN6.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EB49D5345A924F828EF9906A28E7C08C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WH1.BGF" + "TargetName" = "8:WH1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EB7B998D65A940C8BC66A6DEC081DA25" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUB.SKL" + "TargetName" = "8:LUB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EBBEAF74D9D14D2C8570074AB20634D4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RL3L.BGF" + "TargetName" = "8:RL3L.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EBEE2F68CA7D46B1B51885C3C62E3435" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitExt03.wav" + "TargetName" = "8:LaserHitExt03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EC6C0A74B89E42CD81CA9C3AF4E5677F" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\OS1.BGF" + "TargetName" = "8:OS1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ECD51689A68D40DE9188FB9EE4E79B03" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SNAEVAC.BGF" + "TargetName" = "8:SNAEVAC.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_ED395EB6FEE94B179683F0A0A2A6D6B3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\OreDrop03.wav" + "TargetName" = "8:OreDrop03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EDECCFE9E7FA4F53A731F9BC8794D276" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VTVBURN.PFX" + "TargetName" = "8:VTVBURN.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EE011A0037D64B109CC800636F0A4296" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PipeMachine02a.wav" + "TargetName" = "8:PipeMachine02a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EE09AD72A82C46FE827C35020371C0B3" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineDroneExt01.wav" + "TargetName" = "8:EngineDroneExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EE3757B3C62347BE8ED5B52660207B1A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\DUA.SKL" + "TargetName" = "8:DUA.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EEE1343E6B01403E9958E31483DCE2D1" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\BOOST.PFX" + "TargetName" = "8:BOOST.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_EF7927456E4E424897700228BBAA2A9D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\WT1.BGF" + "TargetName" = "8:WT1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F084600A9FB346C1AADB8F0668E62053" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireExt01.wav" + "TargetName" = "8:LaserFireExt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F09D3596F4384B4BAE1460A2C45042B6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\RP1.BGF" + "TargetName" = "8:RP1.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F171D77A5E3849B9908677A1016C9C6D" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\GENA.BSL" + "TargetName" = "8:GENA.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F1D5AA741D0C4A8BB0012FA2F5360140" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CR5.BGF" + "TargetName" = "8:CR5.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F1ECE56D42B1414985701C916564DBB5" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserFireInt07.wav" + "TargetName" = "8:LaserFireInt07.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F30440A183284FE4BDA60DB19F7437D2" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VTVSKIN.BMF" + "TargetName" = "8:VTVSKIN.BMF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F3B9D8442F2A4F56A93985F23ADB8AE0" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\HVAC01a.wav" + "TargetName" = "8:HVAC01a.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F4AF284D31C048DFA09BA933B8AAB270" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LaserHitExt04.wav" + "TargetName" = "8:LaserHitExt04.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F4E4309C13194E87AF016BD175C9E310" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CN2.BGF" + "TargetName" = "8:CN2.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F65495C03E72422DBD26B22B86AE52D4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LUB.BGF" + "TargetName" = "8:LUB.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F6CBE149B1CB4C00AC0B42649C13FD3A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LiftCut01c.wav" + "TargetName" = "8:LiftCut01c.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F7B95AA4A2894E83899444A3D7454E76" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\INTC.VTX" + "TargetName" = "8:INTC.VTX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F7D8A92F1A8E4F06BBCA302E36AC7BC9" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\SUB.SKL" + "TargetName" = "8:SUB.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F84D1CFDF41F480E9163F15357ED2FE7" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\tdloadtext.png" + "TargetName" = "8:tdloadtext.png" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F8DA3C2EF9B247ABB7D07AA199845AB4" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\WellheadDrill01c.wav" + "TargetName" = "8:WellheadDrill01c.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F926D0607B5D4A189B6198998CED1EBB" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\VTV.BSL" + "TargetName" = "8:VTV.BSL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_F96B3082953C49AD87D657A2321B635C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\LiftCut01.wav" + "TargetName" = "8:LiftCut01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FA5C605D11754B49AD87B2FFC01B84F6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\MAS.BGF" + "TargetName" = "8:MAS.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FB51195D57C5449CA8277F406EECF984" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\PipeMachine02.wav" + "TargetName" = "8:PipeMachine02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FBE64D8962D640358518E50A6B77F196" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\GeneratorSpin01.wav" + "TargetName" = "8:GeneratorSpin01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FCA9918729DA4830B4FA9BE6F0BC4890" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\MineRelease01.wav" + "TargetName" = "8:MineRelease01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FCC52C47EF184AECAFCD5B5636951D7B" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\RivetHitCraft03.wav" + "TargetName" = "8:RivetHitCraft03.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FD684DD604C341D882C66DE42E84C14A" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LASER.PFX" + "TargetName" = "8:LASER.PFX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FDE5FBF5615B48049D2D0FEC6005FF08" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\HVEL.BGF" + "TargetName" = "8:HVEL.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FDF073796BAB484088F07504BD9842CC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\CHG.BGF" + "TargetName" = "8:CHG.BGF" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FE857ADC4D0A4E378C6530917BBFECE6" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\INTF.VTX" + "TargetName" = "8:INTF.VTX" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FF3E6DE321BE47CC981F9D69D6285CDA" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineDroneInt02.wav" + "TargetName" = "8:EngineDroneInt02.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FF80CB9E723C4C93B2271F566529094C" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\VIDEO\\LAT.SKL" + "TargetName" = "8:LAT.SKL" + "Tag" = "8:" + "Folder" = "8:_096E8846C2144E0DA9A191FE426FF455" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FFDC038020294FABB8378023ACE30952" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\EngineDroneInt01.wav" + "TargetName" = "8:EngineDroneInt01.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + "{1FB2D0AE-D3B9-43D4-B9DD-F88EC61E35DE}:_FFE912EF33CF4293A5F0FFB1FC70FDFC" + { + "SourcePath" = "8:..\\..\\..\\Rel410\\CONTENT\\RP\\tempassets\\temp.wav" + "TargetName" = "8:temp.wav" + "Tag" = "8:" + "Folder" = "8:_82B713999EA64B03B4780C17BB493C0E" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + } + } + "FileType" + { + } + "Folder" + { + "{3C67513D-01DD-4637-8A68-80971EB9504F}:_0181B1C10F094264966B753C5E8BF50F" + { + "DefaultLocation" = "8:[ProgramFilesFolder][Manufacturer]\\[ProductName]" + "Name" = "8:#1925" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:TARGETDIR" + "Folders" + { + "{9EF0B969-E518-4E46-987F-47570745A589}:_096E8846C2144E0DA9A191FE426FF455" + { + "Name" = "8:VIDEO" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_433EF519CB034FBEBCF45870DC1D7E1C" + "Folders" + { + } + } + "{9EF0B969-E518-4E46-987F-47570745A589}:_30A8831869F24F1198873FCC45365678" + { + "Name" = "8:AUDIO" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_4E74D2BD5DE94709BFD58940023C8C18" + "Folders" + { + } + } + "{9EF0B969-E518-4E46-987F-47570745A589}:_82B713999EA64B03B4780C17BB493C0E" + { + "Name" = "8:tempassets" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:_360CDF03C38F4FCAB5BD20D9C0A28886" + "Folders" + { + } + } + } + } + "{1525181F-901A-416C-8A58-119130FE478E}:_53ABCEC108954FC7A70E5E13ED07B58A" + { + "Name" = "8:#1916" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:DesktopFolder" + "Folders" + { + } + } + "{1525181F-901A-416C-8A58-119130FE478E}:_9D5F466A8BFF442AA818918C699B41EB" + { + "Name" = "8:#1919" + "AlwaysCreate" = "11:FALSE" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Property" = "8:ProgramMenuFolder" + "Folders" + { + } + } + } + "LaunchCondition" + { + } + "Locator" + { + } + "MsiBootstrapper" + { + "LangId" = "3:1033" + } + "Product" + { + "Name" = "8:Microsoft Visual Studio" + "ProductName" = "8:Red Planet 4.11" + "ProductCode" = "8:{22D0294D-E386-4714-9529-E2124576B0CC}" + "PackageCode" = "8:{79B35514-3BAC-4F25-BDC1-DF0AEAC4D9FB}" + "UpgradeCode" = "8:{5CC4A7B9-A8A4-460D-A317-5B961E7468FE}" + "RestartWWWService" = "11:FALSE" + "RemovePreviousVersions" = "11:TRUE" + "DetectNewerInstalledVersion" = "11:TRUE" + "InstallAllUsers" = "11:TRUE" + "ProductVersion" = "8:4.11.0" + "Manufacturer" = "8:VGCorps" + "ARPHELPTELEPHONE" = "8:" + "ARPHELPLINK" = "8:" + "Title" = "8:Red Planet 4.11" + "Subject" = "8:" + "ARPCONTACT" = "8:VGCorps" + "Keywords" = "8:" + "ARPCOMMENTS" = "8:" + "ARPURLINFOABOUT" = "8:" + "ARPPRODUCTICON" = "8:" + "ARPIconIndex" = "3:0" + "SearchPath" = "8:" + "UseSystemSearchPath" = "11:TRUE" + "TargetPlatform" = "3:0" + "PreBuildEvent" = "8:" + "PostBuildEvent" = "8:" + "RunPostBuildEvent" = "3:0" + } + "Registry" + { + "HKLM" + { + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_B9D160E4A0F84DB49876B7D43B827B7C" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_BEFB38BF648B499085250DE3E904BE31" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCU" + { + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_5540CF868CE4444EBB403EE8C7533C80" + { + "Name" = "8:Software" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + "{60EA8692-D2D5-43EB-80DC-7906BF13D6EF}:_04A78617B8AD4683ADE1C67E79F7913A" + { + "Name" = "8:[Manufacturer]" + "Condition" = "8:" + "AlwaysCreate" = "11:FALSE" + "DeleteAtUninstall" = "11:FALSE" + "Transitive" = "11:FALSE" + "Keys" + { + } + "Values" + { + } + } + } + "Values" + { + } + } + } + } + "HKCR" + { + "Keys" + { + } + } + "HKU" + { + "Keys" + { + } + } + "HKPU" + { + "Keys" + { + } + } + } + "Sequences" + { + } + "Shortcut" + { + "{970C0BB2-C7D0-45D7-ABFA-7EC378858BC0}:_063667569A8F42488C150E3B66319BD2" + { + "Name" = "8:Red Planet" + "Arguments" = "8:-net 0 -egg test.egg -windowed" + "Description" = "8:" + "ShowCmd" = "3:1" + "IconIndex" = "3:0" + "Transitive" = "11:FALSE" + "Target" = "8:_F416462836FD4AC3AA39054F791C8C0F" + "Folder" = "8:_53ABCEC108954FC7A70E5E13ED07B58A" + "WorkingFolder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Icon" = "8:" + "Feature" = "8:" + } + } + "UserInterface" + { + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_2BDCBDB0B6A1484C99C0C2C91270A2F2" + { + "Name" = "8:#1900" + "Sequence" = "3:2" + "Attributes" = "3:1" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_09D8163FF585436594BBE5CAC774CD38" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1203" + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7BC0C02DDDEB4D669A43AE9AB5E5703C" + { + "Sequence" = "3:300" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_F85682342E1E49FE9CAC6A883952487F" + { + "Sequence" = "3:200" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminFolderDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_4F0F556265F048B58948C938F6F163F5" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdUserInterface.wim" + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_50BE52A8576A46FE987412C9A75221A3" + { + "Name" = "8:#1902" + "Sequence" = "3:2" + "Attributes" = "3:3" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_7F45B4C3A57142C29150277A825412C1" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_6BA8E6E9BFD14E7CAD149C245389D114" + { + "Name" = "8:#1901" + "Sequence" = "3:2" + "Attributes" = "3:2" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_DD719B92E600402183ECD5DECE7F3522" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdAdminProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{2479F3F5-0309-486D-8047-8187E2CE5BA0}:_84CF21974A5C44CDB4565D971E8CB379" + { + "UseDynamicProperties" = "11:FALSE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdBasicDialogs.wim" + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_93746E03100A40A2B303AF6204D1528F" + { + "Name" = "8:#1901" + "Sequence" = "3:1" + "Attributes" = "3:2" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_8664BD95778148ECA867F9C1A2BD6CF1" + { + "Sequence" = "3:100" + "DisplayName" = "8:Progress" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdProgressDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "ShowProgress" + { + "Name" = "8:ShowProgress" + "DisplayName" = "8:#1009" + "Description" = "8:#1109" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_C5D9EA9F017F42CB80B332DDE08A6207" + { + "Name" = "8:#1902" + "Sequence" = "3:1" + "Attributes" = "3:3" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_48CA5F70C9B04DF2976F78330F9B2354" + { + "Sequence" = "3:100" + "DisplayName" = "8:Finished" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdFinishedDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "UpdateText" + { + "Name" = "8:UpdateText" + "DisplayName" = "8:#1058" + "Description" = "8:#1158" + "Type" = "3:15" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1258" + "DefaultValue" = "8:#1258" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + "{DF760B10-853B-4699-99F2-AFF7185B4A62}:_CF7C066C43BB467B86E1408B46166E65" + { + "Name" = "8:#1900" + "Sequence" = "3:1" + "Attributes" = "3:1" + "Dialogs" + { + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C16860D90DAE471BB69030D35FA26FDE" + { + "Sequence" = "3:200" + "DisplayName" = "8:Installation Folder" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdFolderDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "InstallAllUsersVisible" + { + "Name" = "8:InstallAllUsersVisible" + "DisplayName" = "8:#1059" + "Description" = "8:#1159" + "Type" = "3:5" + "ContextData" = "8:1;True=1;False=0" + "Attributes" = "3:0" + "Setting" = "3:0" + "Value" = "3:1" + "DefaultValue" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_C9993879384442FDB7623A33CF64DF99" + { + "Sequence" = "3:300" + "DisplayName" = "8:Confirm Installation" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdConfirmDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + } + } + "{688940B3-5CA9-4162-8DEE-2993FA9D8CBC}:_E7E3F00A7F7E4570B08D50D3489ECC5D" + { + "Sequence" = "3:100" + "DisplayName" = "8:Welcome" + "UseDynamicProperties" = "11:TRUE" + "IsDependency" = "11:FALSE" + "SourcePath" = "8:\\VsdWelcomeDlg.wid" + "Properties" + { + "BannerBitmap" + { + "Name" = "8:BannerBitmap" + "DisplayName" = "8:#1001" + "Description" = "8:#1101" + "Type" = "3:8" + "ContextData" = "8:Bitmap" + "Attributes" = "3:4" + "Setting" = "3:1" + "UsePlugInResources" = "11:TRUE" + } + "CopyrightWarning" + { + "Name" = "8:CopyrightWarning" + "DisplayName" = "8:#1002" + "Description" = "8:#1102" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1202" + "DefaultValue" = "8:#1202" + "UsePlugInResources" = "11:TRUE" + } + "Welcome" + { + "Name" = "8:Welcome" + "DisplayName" = "8:#1003" + "Description" = "8:#1103" + "Type" = "3:3" + "ContextData" = "8:" + "Attributes" = "3:0" + "Setting" = "3:1" + "Value" = "8:#1203" + "DefaultValue" = "8:#1203" + "UsePlugInResources" = "11:TRUE" + } + } + } + } + } + } + "MergeModule" + { + } + "ProjectOutput" + { + "{5259A561-127C-4D43-A0A1-72F10C7B3BF8}:_F416462836FD4AC3AA39054F791C8C0F" + { + "SourcePath" = "8:..\\release\\rpl4opt.exe" + "TargetName" = "8:" + "Tag" = "8:" + "Folder" = "8:_0181B1C10F094264966B753C5E8BF50F" + "Condition" = "8:" + "Transitive" = "11:FALSE" + "Vital" = "11:TRUE" + "ReadOnly" = "11:FALSE" + "Hidden" = "11:FALSE" + "System" = "11:FALSE" + "Permanent" = "11:FALSE" + "SharedLegacy" = "11:FALSE" + "PackageAs" = "3:1" + "Register" = "3:1" + "Exclude" = "11:FALSE" + "IsDependency" = "11:FALSE" + "IsolateTo" = "8:" + "ProjectOutputGroupRegister" = "3:1" + "OutputConfiguration" = "8:Release|Win32" + "OutputGroupCanonicalName" = "8:Built" + "OutputProjectGuid" = "8:{01B740F7-5D4E-4E42-893F-CE018E5EE785}" + "ShowKeyOutput" = "11:TRUE" + "ExcludeFilters" + { + } + } + } + "VJSharpPlugin" + { + } + } +} diff --git a/WinTesla.sln b/WinTesla.sln new file mode 100644 index 0000000..a4c06f2 --- /dev/null +++ b/WinTesla.sln @@ -0,0 +1,141 @@ +Microsoft Visual Studio Solution File, Format Version 9.00 +# Visual Studio 2005 +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RP_L4", "RP_L4\RP_L4.vcproj", "{01B740F7-5D4E-4E42-893F-CE018E5EE785}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {F988B198-A386-40DD-A50E-9A5CE17A92A5} = {F988B198-A386-40DD-A50E-9A5CE17A92A5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "BT410_L4", "BT410_L4\BT410_L4.vcproj", "{3D11EC2A-78C8-4138-AABC-5597846A30F9}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {F988B198-A386-40DD-A50E-9A5CE17A92A5} = {F988B198-A386-40DD-A50E-9A5CE17A92A5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Munga_L4", "MUNGA_L4\Munga_L4.vcproj", "{F988B198-A386-40DD-A50E-9A5CE17A92A5}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "RPL4TOOL", "RP_L4\RPL4TOOL.vcproj", "{11BDE691-E0D7-443E-A5AF-87B35B8EEAEE}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection + ProjectSection(ProjectDependencies) = postProject + {F988B198-A386-40DD-A50E-9A5CE17A92A5} = {F988B198-A386-40DD-A50E-9A5CE17A92A5} + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TextureExp", "TextureExp\TextureExp.vcproj", "{E5595E6E-4D04-4114-91A2-0E839698262C}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MeshExp", "MeshExp\MeshExp.vcproj", "{17BBD54E-1011-45B4-B53D-CDB0588CEF23}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DivLoader", "DivLoader\DivLoader.vcproj", "{2742FFCF-E94C-4202-BB0E-36D86CD04A09}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "SphereExp", "SphereExp\SphereExp.vcproj", "{8FFCD624-4B77-4FE7-9226-642389E31420}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "DetailExp", "DetailExp\DetailExp.vcproj", "{E22A8051-BD1E-44C9-ACDB-AC813C034EE1}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "MatReplaceExp", "MatReplaceExp\MatReplaceExp.vcproj", "{F6DC05B7-882E-4C10-8462-314EC9BC7759}" + ProjectSection(WebsiteProperties) = preProject + Debug.AspNetCompiler.Debug = "True" + Release.AspNetCompiler.Debug = "False" + EndProjectSection +EndProject +Global + GlobalSection(SolutionConfigurationPlatforms) = preSolution + Debug|Win32 = Debug|Win32 + Release|Win32 = Release|Win32 + Remote Debug|Win32 = Remote Debug|Win32 + EndGlobalSection + GlobalSection(ProjectConfigurationPlatforms) = postSolution + {01B740F7-5D4E-4E42-893F-CE018E5EE785}.Debug|Win32.ActiveCfg = Debug|Win32 + {01B740F7-5D4E-4E42-893F-CE018E5EE785}.Debug|Win32.Build.0 = Debug|Win32 + {01B740F7-5D4E-4E42-893F-CE018E5EE785}.Release|Win32.ActiveCfg = Release|Win32 + {01B740F7-5D4E-4E42-893F-CE018E5EE785}.Release|Win32.Build.0 = Release|Win32 + {01B740F7-5D4E-4E42-893F-CE018E5EE785}.Remote Debug|Win32.ActiveCfg = Remote Debug|Win32 + {01B740F7-5D4E-4E42-893F-CE018E5EE785}.Remote Debug|Win32.Build.0 = Remote Debug|Win32 + {3D11EC2A-78C8-4138-AABC-5597846A30F9}.Debug|Win32.ActiveCfg = Debug|Win32 + {3D11EC2A-78C8-4138-AABC-5597846A30F9}.Debug|Win32.Build.0 = Debug|Win32 + {3D11EC2A-78C8-4138-AABC-5597846A30F9}.Release|Win32.ActiveCfg = Release|Win32 + {3D11EC2A-78C8-4138-AABC-5597846A30F9}.Release|Win32.Build.0 = Release|Win32 + {3D11EC2A-78C8-4138-AABC-5597846A30F9}.Remote Debug|Win32.ActiveCfg = Debug|Win32 + {F988B198-A386-40DD-A50E-9A5CE17A92A5}.Debug|Win32.ActiveCfg = Debug|Win32 + {F988B198-A386-40DD-A50E-9A5CE17A92A5}.Debug|Win32.Build.0 = Debug|Win32 + {F988B198-A386-40DD-A50E-9A5CE17A92A5}.Release|Win32.ActiveCfg = Release|Win32 + {F988B198-A386-40DD-A50E-9A5CE17A92A5}.Release|Win32.Build.0 = Release|Win32 + {F988B198-A386-40DD-A50E-9A5CE17A92A5}.Remote Debug|Win32.ActiveCfg = Remote Debug|Win32 + {F988B198-A386-40DD-A50E-9A5CE17A92A5}.Remote Debug|Win32.Build.0 = Remote Debug|Win32 + {11BDE691-E0D7-443E-A5AF-87B35B8EEAEE}.Debug|Win32.ActiveCfg = Debug|Win32 + {11BDE691-E0D7-443E-A5AF-87B35B8EEAEE}.Debug|Win32.Build.0 = Debug|Win32 + {11BDE691-E0D7-443E-A5AF-87B35B8EEAEE}.Release|Win32.ActiveCfg = Release|Win32 + {11BDE691-E0D7-443E-A5AF-87B35B8EEAEE}.Release|Win32.Build.0 = Release|Win32 + {11BDE691-E0D7-443E-A5AF-87B35B8EEAEE}.Remote Debug|Win32.ActiveCfg = Remote Debug|Win32 + {E5595E6E-4D04-4114-91A2-0E839698262C}.Debug|Win32.ActiveCfg = Debug|Win32 + {E5595E6E-4D04-4114-91A2-0E839698262C}.Debug|Win32.Build.0 = Debug|Win32 + {E5595E6E-4D04-4114-91A2-0E839698262C}.Release|Win32.ActiveCfg = Release|Win32 + {E5595E6E-4D04-4114-91A2-0E839698262C}.Release|Win32.Build.0 = Release|Win32 + {E5595E6E-4D04-4114-91A2-0E839698262C}.Remote Debug|Win32.ActiveCfg = Debug|Win32 + {E5595E6E-4D04-4114-91A2-0E839698262C}.Remote Debug|Win32.Build.0 = Debug|Win32 + {17BBD54E-1011-45B4-B53D-CDB0588CEF23}.Debug|Win32.ActiveCfg = Debug|Win32 + {17BBD54E-1011-45B4-B53D-CDB0588CEF23}.Debug|Win32.Build.0 = Debug|Win32 + {17BBD54E-1011-45B4-B53D-CDB0588CEF23}.Release|Win32.ActiveCfg = Release|Win32 + {17BBD54E-1011-45B4-B53D-CDB0588CEF23}.Release|Win32.Build.0 = Release|Win32 + {17BBD54E-1011-45B4-B53D-CDB0588CEF23}.Remote Debug|Win32.ActiveCfg = Debug|Win32 + {17BBD54E-1011-45B4-B53D-CDB0588CEF23}.Remote Debug|Win32.Build.0 = Debug|Win32 + {2742FFCF-E94C-4202-BB0E-36D86CD04A09}.Debug|Win32.ActiveCfg = Debug|Win32 + {2742FFCF-E94C-4202-BB0E-36D86CD04A09}.Debug|Win32.Build.0 = Debug|Win32 + {2742FFCF-E94C-4202-BB0E-36D86CD04A09}.Release|Win32.ActiveCfg = Release|Win32 + {2742FFCF-E94C-4202-BB0E-36D86CD04A09}.Release|Win32.Build.0 = Release|Win32 + {2742FFCF-E94C-4202-BB0E-36D86CD04A09}.Remote Debug|Win32.ActiveCfg = Debug|Win32 + {2742FFCF-E94C-4202-BB0E-36D86CD04A09}.Remote Debug|Win32.Build.0 = Debug|Win32 + {8FFCD624-4B77-4FE7-9226-642389E31420}.Debug|Win32.ActiveCfg = Debug|Win32 + {8FFCD624-4B77-4FE7-9226-642389E31420}.Debug|Win32.Build.0 = Debug|Win32 + {8FFCD624-4B77-4FE7-9226-642389E31420}.Release|Win32.ActiveCfg = Release|Win32 + {8FFCD624-4B77-4FE7-9226-642389E31420}.Release|Win32.Build.0 = Release|Win32 + {8FFCD624-4B77-4FE7-9226-642389E31420}.Remote Debug|Win32.ActiveCfg = Debug|Win32 + {8FFCD624-4B77-4FE7-9226-642389E31420}.Remote Debug|Win32.Build.0 = Debug|Win32 + {E22A8051-BD1E-44C9-ACDB-AC813C034EE1}.Debug|Win32.ActiveCfg = Debug|Win32 + {E22A8051-BD1E-44C9-ACDB-AC813C034EE1}.Debug|Win32.Build.0 = Debug|Win32 + {E22A8051-BD1E-44C9-ACDB-AC813C034EE1}.Release|Win32.ActiveCfg = Release|Win32 + {E22A8051-BD1E-44C9-ACDB-AC813C034EE1}.Release|Win32.Build.0 = Release|Win32 + {E22A8051-BD1E-44C9-ACDB-AC813C034EE1}.Remote Debug|Win32.ActiveCfg = Debug|Win32 + {E22A8051-BD1E-44C9-ACDB-AC813C034EE1}.Remote Debug|Win32.Build.0 = Debug|Win32 + {F6DC05B7-882E-4C10-8462-314EC9BC7759}.Debug|Win32.ActiveCfg = Debug|Win32 + {F6DC05B7-882E-4C10-8462-314EC9BC7759}.Debug|Win32.Build.0 = Debug|Win32 + {F6DC05B7-882E-4C10-8462-314EC9BC7759}.Release|Win32.ActiveCfg = Release|Win32 + {F6DC05B7-882E-4C10-8462-314EC9BC7759}.Release|Win32.Build.0 = Release|Win32 + {F6DC05B7-882E-4C10-8462-314EC9BC7759}.Remote Debug|Win32.ActiveCfg = Debug|Win32 + {F6DC05B7-882E-4C10-8462-314EC9BC7759}.Remote Debug|Win32.Build.0 = Debug|Win32 + EndGlobalSection + GlobalSection(SolutionProperties) = preSolution + HideSolutionNode = FALSE + EndGlobalSection +EndGlobal diff --git a/docs/audionotes.rtf b/docs/audionotes.rtf new file mode 100644 index 0000000..a9cc8d6 --- /dev/null +++ b/docs/audionotes.rtf @@ -0,0 +1,94 @@ +{\rtf1\ansi\ansicpg1252\uc1\deff0\stshfdbch0\stshfloch0\stshfhich0\stshfbi0\deflang1033\deflangfe1033{\fonttbl{\f0\froman\fcharset0\fprq2{\*\panose 02020603050405020304}Times New Roman;}{\f1\fswiss\fcharset0\fprq2{\*\panose 020b0604020202020204}Arial;} +{\f37\froman\fcharset238\fprq2 Times New Roman CE;}{\f38\froman\fcharset204\fprq2 Times New Roman Cyr;}{\f40\froman\fcharset161\fprq2 Times New Roman Greek;}{\f41\froman\fcharset162\fprq2 Times New Roman Tur;} +{\f42\froman\fcharset177\fprq2 Times New Roman (Hebrew);}{\f43\froman\fcharset178\fprq2 Times New Roman (Arabic);}{\f44\froman\fcharset186\fprq2 Times New Roman Baltic;}{\f45\froman\fcharset163\fprq2 Times New Roman (Vietnamese);} +{\f47\fswiss\fcharset238\fprq2 Arial CE;}{\f48\fswiss\fcharset204\fprq2 Arial Cyr;}{\f50\fswiss\fcharset161\fprq2 Arial Greek;}{\f51\fswiss\fcharset162\fprq2 Arial Tur;}{\f52\fswiss\fcharset177\fprq2 Arial (Hebrew);} +{\f53\fswiss\fcharset178\fprq2 Arial (Arabic);}{\f54\fswiss\fcharset186\fprq2 Arial Baltic;}{\f55\fswiss\fcharset163\fprq2 Arial (Vietnamese);}}{\colortbl;\red0\green0\blue0;\red0\green0\blue255;\red0\green255\blue255;\red0\green255\blue0; +\red255\green0\blue255;\red255\green0\blue0;\red255\green255\blue0;\red255\green255\blue255;\red0\green0\blue128;\red0\green128\blue128;\red0\green128\blue0;\red128\green0\blue128;\red128\green0\blue0;\red128\green128\blue0;\red128\green128\blue128; +\red192\green192\blue192;}{\stylesheet{\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 \snext0 Normal;}{\*\cs10 \additive \ssemihidden Default Paragraph Font;}{\* +\ts11\tsrowd\trftsWidthB3\trpaddl108\trpaddr108\trpaddfl3\trpaddft3\trpaddfb3\trpaddfr3\tscellwidthfts0\tsvertalt\tsbrdrt\tsbrdrl\tsbrdrb\tsbrdrr\tsbrdrdgl\tsbrdrdgr\tsbrdrh\tsbrdrv +\ql \li0\ri0\widctlpar\aspalpha\aspnum\faauto\adjustright\rin0\lin0\itap0 \fs20\lang1024\langfe1024\cgrid\langnp1024\langfenp1024 \snext11 \ssemihidden Normal Table;}}{\*\rsidtbl \rsid928474\rsid1311826\rsid5056432\rsid5572268\rsid6828841\rsid8667063 +\rsid8728605\rsid11619772\rsid12661939\rsid14093336}{\*\generator Microsoft Word 10.0.6775;}{\info{\author Stephen Baynham}{\operator GameWyze}{\creatim\yr2007\mo1\dy22\hr11\min18}{\revtim\yr2007\mo1\dy22\hr21\min18}{\version5}{\edmins130}{\nofpages2} +{\nofwords901}{\nofchars5142}{\*\company GameWyze}{\nofcharsws6031}{\vern16391}}\widowctrl\ftnbj\aenddoc\noxlattoyen\expshrtn\noultrlspc\dntblnsbdb\nospaceforul\hyphcaps0\horzdoc\dghspace120\dgvspace120\dghorigin1701\dgvorigin1984\dghshow0\dgvshow3 +\jcompress\viewkind4\viewscale100\nolnhtadjtbl\rsidroot8667063 \fet0\sectd \linex0\sectdefaultcl\sftnbj {\*\pnseclvl1\pnucrm\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl2\pnucltr\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl3 +\pndec\pnstart1\pnindent720\pnhang {\pntxta .}}{\*\pnseclvl4\pnlcltr\pnstart1\pnindent720\pnhang {\pntxta )}}{\*\pnseclvl5\pndec\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl6\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}} +{\*\pnseclvl7\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl8\pnlcltr\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}{\*\pnseclvl9\pnlcrm\pnstart1\pnindent720\pnhang {\pntxtb (}{\pntxta )}}\pard\plain +\ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 \fs24\lang1033\langfe1033\cgrid\langnp1033\langfenp1033 {\f1\fs20\insrsid11619772 BTL4 Has its own AudioRenderer (BTL4AudioRenderer) which just establishes a new AudioHead (BTL4AudioHead). +\par +\par MungaL4 has its own AudioRenderer (L4AudioRenderer) which implements the Initialize() function to load world sound info from a file.}{\f1\fs20\insrsid6828841 It also initializes the AudioHardware. Finally, it refers to L4 +AudioResourceManager::PreloadResources.}{\f1\fs20\insrsid11619772 +\par }{\f1\fs20\insrsid6828841 +\par L4AudioRenderer also! Will create entity audio objects when it is notified of new interesting things. An audio representation of the object is obtained from entity::GetAudioRepresentation and used to create the necessary entity audio objects in L4AudioRe +sourceManager::CreateEntityAudioObjects. L4AudioResourceManager::DestroyEntityAudioObjects is used to get rid of it when it\rquote s over. +\par +\par }{\f1\fs20\insrsid8728605 L4AudioRenderer::StartRequest(L4AudioSource) is called to start an audiosource rendering. It requests the necessary resources with RequestAudioResources. If they don\rquote +t exist, it will put sustained audio sources in line to play later on when the resources are available. Otherwise, it will set necessary values and call L4AudioSource::StartImplementation(), which probably check +s the type of the audio source and plays it accordingly. It also adds the source to the running socket and if it isn\rquote t mixed manually, adds it to the mix socket.}{\f1\fs20\insrsid11619772 +\par }{\f1\fs20\insrsid928474 +\par L4AudioRenderer::RequestAudioResources(source, channel_set_result) ensures that}{\f1\fs20\insrsid5572268 the source ought to be played (isn\rquote t clipped) and then sends a list of possible channels and number of channels the source will use. + If not enough channels remain, then the list of desired channels is searched for playing audio that has lower importance than the requesting source. If room can be found, returns true, otherwise false.}{\f1\fs20\insrsid928474 +\par }{\f1\fs20\insrsid8728605 +\par L4AudioRenderer::StopRequest(L4AudioSource) checks if the source is suspended or dormant (or otherwise not running) and if so, removes it from the dormant plug (waiting list) and sets it to stop. For currently-playing sounds, +AudioSourceStopMaintenance(source) is called. +\par }{\f1\fs20\insrsid12661939 +\par L4AudioRenderer::AudioSourceStopMaintenance}{\f1\fs20\insrsid928474 (source) calls source::StopImplementation(), releases channels, and removes the source from the mix & running sockets.}{\f1\fs20\insrsid12661939 +\par }{\f1\fs20\insrsid928474 +\par L4AudioRenderer::AudioSourceSuspendMaintenance(source) calls source::SuspendImplementation(), removes it from the sockets and adds it to the dormant socket. +\par }{\f1\fs20\insrsid8728605 +\par }{\f1\fs20\insrsid12661939 L4AudioRenderer::ExecuteImplementation() is the renderer-specific code that is called each frame. It extends AudioRenderer\rquote s implementation. It mixes stuff in the mix plug, plays stuff in the running plug, + and processes stuff in the dormant plug to see if it should activate. +\par }{\f1\fs20\insrsid5572268 +\par }{\f1\fs20\insrsid12661939 CalculateMix(), RunningSourceCheckup(), and DormantSourceCheckup() perform these activities. +\par }{\f1\fs20\insrsid1311826 +\par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0\pararsid1311826 {\f1\fs20\insrsid1311826 AudioRenderer links its AudioHead when it is linked to a guy. In ExecuteImplementation (called each frame), AudioRenderer calls Execute() on its AudioHead. + +\par +\par What does AudioRenderer::PostAudioRequestMessage do? +\par }{\f1\fs20\insrsid5056432 +\par AudioRenderer::ProcessAudioRequestMessage seems to do something with these requests. Just calls the Process() function on them if there\rquote s one on the stack. +\par +\par AudioRenderer::FlushAudioMessages(source) gets rid of any pending audio events for a particular source, only processing messages saying to stop the sound. +\par +\par AudioRenderer::StartEntityEffectImplementation starts a new sound on a portion of an entity? AudioEntity::Make is used. +\par +\par AudioEntity/AudioSource for implementing buffers & sources? +\par AudioHead for implementing listener controls. +\par }\pard \ql \li0\ri0\nowidctlpar\faauto\rin0\lin0\itap0 {\f1\fs20\insrsid1311826 +\par }{\f1\fs20\insrsid8728605 +\par }{\f1\fs20\insrsid8667063 Stuff is held in audio\\static.scp! This is read as a NotationFile +\par +\par AudioControlSequence seems to be the primary audio/midi file class. BuildFromPage is used to load the information. Actually, AudioControlSequence is descended from AudioComponent which seems to be a sort of generic audio class. I might be able to chang +e the way it loads, stores, and plays its data and have that do most of the work. +\par +\par AudioControlSequence::BuildFromPage makes use of the CreateAudioControlEventStream class to parse midi files and DynamicMemoryStream objects to hold most information. +\par +\par What's a NameList, is it like a string/string dictionary? +\par +\par In BuildFromPage, we pull the midi_file value from the passed-in NameLIst, open up a file stream, and write it into a DynamicMemoryStream object. We also pull the tempo from the NameList. Then we run + the file through the midi parser, getting a new DynamicMemoryStream out. +\par +\par The new DynamicMemoryStream has information on what are apparently called control events- presumably the whole what happens in this midi file info. We write that as well as a ton of other options into a PlugStream that got passed in as an argument. + +\par +\par Actually, there are a ton of different audio object types, and all of their BuildFromPage things are called from AudioObjectStream::BuildFromPageImplementation. This seems to be called +from a generic ObjectStream::ParseNotationFile(), which may be called fro ObjectStream::BuildFromNotationFile() and ObjectStream::ReadIncludedFiles(). ReadIncludedFiles() is run because a notation file may reference other notation files within it and cau +se those to be read as well. +\par +\par BuildFromNotationFile is called from: +\par \tab -L4AudioResourceManager::CreateStaticAudioStreamResource(ResourceFile) +\par \tab -L4AudioResourceManager::CreateModelAudioStreamResource(ResourceFile, model_name, model_File, ResourceDirectorie) +\par \tab -Registry::CreateStaticObjectStreamResource(NotationFile, ResourceFile) +\par +\par ApplicationTool::BuildResources calls each of these when necessary. CreateStaticAudioStreamResource may only be called once? +\par +\par +\par +\par Called from main of BTL4Tool/RPL4Tool. Where the fuck in the game app? +\par +\par In WinMain, we open a StreamableResourceFile (btl4.res in BT410). Also, we make a new BTL4Application object and send in the StreamableResourceFile. +\par +\par Passes to L4Application to Application. +\par +\par Saves resourcefile to Application::resourceFile. Retrievable with GetResourceFile(). Sent to Application::MakeMission() which is picked up by BTL4Application/RPL4Application and used to Create a new BTL4Mission/RPL4Mission. +\par +\par The mission constructors seem to have the relevant info within. +\par }} \ No newline at end of file diff --git a/lib/OpenAL32.lib b/lib/OpenAL32.lib new file mode 100644 index 0000000000000000000000000000000000000000..d635de97efe4265f914eadb751dd7b34451c6f52 GIT binary patch literal 20552 zcmdU0OKe<47QJ?WfC&&F{6YXH;L0BoJc30x5Iq`)<{HU3B|7BTY-!@7-Is z>eRh;>-)-^59iBs7mqgWYj%I_?H!$MZSCD{`(1gPW^tKbFw zqNwdUnJ}9?d(czy^4^YpiiaOsX5_I%KMMu6Q5_Amul3vFXbo8L2 zW8Z@Z?Qc}ny`4zV{zXmS;0fx6{epT%743tI1nq&Z1P!z(Ix-JD(BNf7y{N08L6jkA zXjoD24ah-5*A*QEzMuoU6df#r7xcBF184(5hlUg#2ezaFo}fO|S<>5hf(B4mLH($& zB>1Nvbo?ttgUBzab&sMwS6~O|@SBSEp-e#?Unt7G27iOP#ue>DIf6R773ID|I;aa6 zf)0JGXfO07!PdQ?6B`xn`4)JfVfb0l2=oLE3mNDHVnNbxc!EY}6-@wB(nUN$V;?CR zMT`kL^@gJH4Mc**dK8`d8FJ7`_*c@qc!EwfDH;c!Bw&q$Ms5h2nHd?IoR~U2GcY*a zKQ%IWdSYs3VlgWAjdpg>%*^Vpp40KX|8X69{M^OT?x}1EG}ONHq)R5+%q+F&bW+8L^2p#+!2BJtMWz#sw*QHsXw)5Txjt zs55HJK91_E@t(x=RCn?OF=}zTv|OHx%xGjeqoD>LE6x`@fzeYM)0NVqh!D;hjgciK zRdH$FO{(Ih!|kh^rrfL&dDLii*`D#cn^*cuB{Fa7vRESbp;l+*dQqambdRu{L59mU zfC;0RP3YLz(8aisp@gQvEte?8jz$`Z*=lQJ<3Sh0kd$PykbgC9L&X`SScADms3c3t zFE7c#LT6E|SB?87M4tseKlzq&1F7mC}T`I+W2^>REY9L9g~)08Uv+e z4Gnd}u=JrqDKF;^BAxh}#@z*L!KB<*2%O;N1 zq`=qfFO-&|f#~wWoD5Z??TGz6Vg;Pc!lgC`0>Lh5=3>UCPcJW_u=)NHV(yBnuP?H? zVkLuB4A=EVRu@olXb51#ag8{l@&%z2^IWTcxm?Cli^D?Km)aa@%P|z6CboG{p0`XB z)p0~z*IB4ZuO?S&bN%HgUx|3FJ&7%GAX=)FORsWOUu1QK<*KcgSOla_w_LIJeBkLYdCHIy^jkNSYVf?OOJ?18OUfbk~k zSpeP_sQ+uI_jng{z;~nG-+})W{KqJBd@pc88&42@i+qd2kd5FS&#RFA2AUm3-U*_M zppVAjGw^SmBHDoSfFAHa<9*jjqIW?}c)tqyZ=f3}2gg*jfgYj;YLw5rXdSJkJE@88 zrhDji+CjZEPN!&;j?rzj9VQOZee?j`OY7-=dXW0*1U*I%(*O;_yb;<=TdA40(9^Vy z9;J55Q5$toCw0+Dx`X=Y5!y+Q)04E3HqjIG6z!%~>Y)SFP5bEx9iqe3LI>$6?V>%j z7Y#B-Q#4Hz^bAeXd3u@7(F{FLFVSgwj$Wi^=>?jlJe{R8^#5D)HStc??p;@MZlZTV zW*@Bju`N-boT$w|U-@eZTjd7NIn3~&PZ8LHLrD_l@b!L`LzpVNp~TXy${b(oqQg|( zUoG;}B%=eFTCift5X<6~VN%9Cfzeuf6`K~WDbK9<_Q-0cDSA8Ggnw;j?qUd2)}v{w zLpI5=I_kv)lO)%#)t8cvxyjicl{5Qs9)euV;)jV{_n0y~2N`jC5uTG$=YAlnR`+VB zg>J!0=+;cj+*nY;w9HrDmWXwD(V%8a1N=|N@ z_8%)uOISW7nG9`ljS*T^Zn2XxRz0N{+H?NS9@i~h9n2(U3B+nUR#l&b8+aTmm4sg$ zZ>H{u>fTrwJ4{BqMM@-8Qa3iPH=O069rXM~vMsuv^{>r@?pbwLfV7kWO|IS5c`q*| zIWh&e1Ae~@?=@;(c-tCP-DLSYHS-NZ^j`apSTXPJmkOq&PR8sEV)R8+nZrnxD0j%- zd@MKD>^#NWcvm?Chm zS5+C0L^EGXOgmGm?*s9^Px0*Afu0wo+{}oQ(a|Mbi_+s*ldKsrRTCoJ3QX;cz?for z*;p)xpTQdB%xw}?dD&uW))b&vgQq!zrdU_iBAK4SKc2}CCe9IC>Ngctu5gkuP*u-z z64G$8a+Z;GGn}KRYNpCo<>_~+rQY=%V-DCQD@)YLiKAPV=*}gk2s4YgJj^aCEouT24%hkVFi=xEW z?$-H2L7bWV-Yt^-9i93<$!ybT!x~!q!H>s(Y#{8&vF9ghxVzyFyaj&ik=97qt5^T6 zkx5V#y5f&~+DG+_|AUm)`RM%eD_f@x6pl`)0Q>o`m)0L|U6{v5`K>rTQ9oQ&pua-z zA6i$~*h_7nX+50qsNcPK{D=mHA`KKsYm6i(bRZzB(-ljEe6#qYf1-38kZDdl8gaxz*v+lvAfkGA zXyPW<(jPjy^s!;H=nsvuKm1KrPgIf`(&A-aCdGePyx??A{Y1R{#W4CQ;^h{_K`m|j z1gcT>PE6f?>uFDnBmV|~YUp&oy_N8X?PoZRR6h}p|1^w#vVMk>OZ5|a|1ykzuCjk? z@#&L*Ud3q48K)u|F$|!Sjy8x9`XOoIo%S4$w-(hM^C6T5%mm`zi@4L05v5B9h-b@V zu%%I;m^}hkQMV3hjf1q170KSsblc}~*mN65lKZ5LR^`(D_b9M#=UATmIBG2;U@p*3 zcQ`ngvwAOJk@zNHBf@K@)wJkN2PdmVUFLGG7vo}BxJx0qC(_&$$D6gZR0yq!qp4;5 zk^|r{wV>q!t#!9X)3+dQnN{m74m%RKWoY+kH0Qh_8=6^Mc=6GU__)_Wvxga(@N#Bx z@8LZHy!#ZMJ}Gfv>YqUZOmjN z8>l#PO?^3lwIRkb$6vho`p1m`)Q0aOjfnY;7E2$OW{bjr2Osy4JfrIO;DL0j#D;5=#fp!c9K-5I3#`|k zh|%OZ@~uO9(juu->WoN%xOmD%@*0cd)-)0Z;-c9inFDrS`U>`0fe~Y~kCoA`(Asc| z#WE+_{+5f|S&J7#Xiq26ydkPyv|ONnZB3wM9p^)~ZA+qMY`2hY+Y@M>BkLYJLbmNl zqGhzLtIBD{Qy3RpEE@lo#3N&M``b>7r&fwtdq6JGw|DtiUbAs4Yw2ydz?ik$!^#@{ zA-neYSQ+CZWY=B~%X4Afksq?F)yK+eS70{V7h|cb?mQUkUuy@}0&NP(Uh#2&>i1v3 zrgnp5{_nwo;!G{k-c`k>r!i`DSS0_8FGpFy$WaAToKhiEM_pd;Fbh}vI5XD=rmiP#b8v8vYuOrv*!GKjgE|%xO)wJq>hm_f>K(rrJ zSm~2w{r(Fe9deL7_tlRSn2!&0By~4~H;>b!Yl^_Ydh|#FD|2fFdht;QO~dO z9r~U);^1VqDA1cvY9xMhjayRx*wIyGEwB}FcuJv}3vm2ioCC_4T6`HABS&3KQMCSl zK8~^iI|JXW##~HurOyH6OieZhzM+nLc=Em=2XN-QTF^r0EfYQ(E+aZ%_4m0zgiabX z_V2sd&_d@e&loi4B4tLrK%`7*Jnx#O1IU?L+Ah=^rZryj4k$-iL2sxsK8xMxX@=?E zFwKY==n-dP%qkxgICd>w%~cuK#5b9<3@!OVp>Cu=Z+JFFvNvye`73C-Ky*GAqg6eA z>Achcsu`#w;zzHNGz%IK$B!bK@31B`lriqY-^?vY@wb$BR2ci^_ zP(*=JQc+PNr9sq|LPbS^lp+#Hw2`Q&5EbO!_nY@-W(S5fS?T)Cz3+S*TUjRKjf!>#r25tdNy*DL| z90Hj7ijoGO0ZjczB=tQeIZ^+8Nkg{*rj3sjU8I(1__?BM)H1D+G(^};8WruC-e0vZcT^Rp#eNehf#xmKUgH@(7KsUXMa3XER8lrMVq z{8cejpKuSByESW{LI9J0g8+}M989`7_k6LND<5og{(ZV(Ly!g)oNIg}u+5HGX>jVn34$iVQKvR9dK7k`L$&7p zROB0z?sH0uU>OnkkXa=4a#`jV!}+gURhN?le6ygJQ(oEcWXY$E9w&4Bl0&R?)p%A3*du-z$(JidMuwr>Om*9LzH3o*AtxP4)ph|rVjon|9G(5ANHND z6za7`t=vrQnEo;~b>hq^(Hs0j8CJZ>UjU^wP|~7oOG%BNf><;h$`Fe*?(GkM#hW)8 zmEYqZ5400{`jdbd`ka=CiSjtRv?R+qB!JP$`4X0Y&VSU8zfQ?taolv`BK>{;L>O<3 ziR~woQ{_vF?Wa@N&tGDgJlJUaDT*%tk7Yl5wUq7WPtB;7?dJp9#k=e?RYa{%rAd7+ zbKskh?>!{|x#`hs7vp<5yJTQoQ2n76B8rGMQX0rc!uIM-2U#x*ypzf$sD)a$BXfGJ~WD% z={w-|(PF$|heDHQe05>aK4OfmY|ZDb=fw;ny~R&2kqo@jPVS{HLI#Gx7wd&%&PJ! V!a|HR)WoYAGefSOEW8$B`#&~_1m*w$ literal 0 HcmV?d00001