Advertisement
Guest User

blizzard.cpp

a guest
Aug 7th, 2011
387
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 321.55 KB | None | 0 0
  1. /**********************************************************************
  2.  *<                            
  3.  
  4.    FILE: Blizzard.CPP
  5.    DESCRIPTION: SuperSpray and Blizzard main code
  6.  
  7.    CREATED BY: Audrey Peterson  
  8.  
  9.    HISTORY: created November 1996
  10.    Instancing Geometry 1/97
  11.    IPC 8/98
  12.  
  13.  *>   Copyright (c) 1996, All Rights Reserved.
  14.  **********************************************************************/
  15. #include <io.h>
  16. #include "SuprPrts.h"
  17. #include "iparamm.h"
  18. #include "interpik.h"
  19. #include "texutil.h"
  20. #include "stdmat.h"
  21. #include "macrorec.h"
  22.  
  23. #include "3dsmaxport.h"
  24.  
  25. // russom - 10/11/01
  26. #if !defined(NO_PARTICLES_BLIZZARD) && !defined(NO_PARTICLES_SUPERSPRAY)
  27.  
  28. #define EPSILON            0.0001f
  29. #define MAX_PATH_LENGTH    257
  30. #define MAX_STRING_LENGTH  256
  31. #define PARTICLE_SEED      0x8d6a65bc
  32.  
  33. #define PBLK         0
  34. #define CUSTNODE     1
  35.  
  36. #define BASER 2
  37.  
  38. typedef struct
  39. {
  40.    float Vsz,Ts,Ts0,LamTs,A,LamA,To;
  41.    float M,Dis,Fo,Mltvar,pvar;
  42.    int themtl,gennum,SpVar;
  43.    TimeValue L,showframe,DL,persist;
  44.    Point3   V,W,RV;
  45. }  CSavePt;
  46.  
  47. typedef struct
  48. {
  49.    float Size,VSz,VSpin,Phase,VPhase,Speed,VSpeed;
  50.    float width,bstr,bstrvar,ToAmp,VToAmp,axisvar;
  51.    float ToPhase,VToPhase,VToPeriod,Av180,Ah180,VAv,VAh,pvar;
  52.    int axisentered;
  53.    Point3 Ve,Axis;
  54.    TimeValue Spin,ToPeriod,Life,Vl,persist;
  55.    BirthPositionSpeed bps;
  56. }  VelDir;
  57.  
  58. static Class_ID SUPRSPRAY_CLASS_ID(0x74f811e3, 0x21fb7b57);
  59. static Class_ID BLIZZARD_CLASS_ID(0x5835054d, 0x564b40ed);
  60.  
  61. class CPickOperand;
  62. class CommonParticle;
  63.  
  64. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  65. //        WARNING - a copy of this class description is in maxscrpt\maxnode.cpp
  66. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  67. class CommonParticleDraw : public CustomParticleDisplay {
  68.    public:
  69.       float tumble,scale;
  70.       BOOL firstpart;
  71.       CommonParticle *obj;
  72.       int disptype,ptype,bb,anifr,anioff;
  73.       boxlst *bboxpt;
  74.       TimeValue t;
  75.       InDirInfo indir;
  76.  
  77.       CommonParticleDraw() {obj=NULL;}
  78.       BOOL DrawParticle(GraphicsWindow *gw,ParticleSys &parts,int i);
  79.    };
  80.  
  81. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  82. //       WARNING - a copy of this class description is in maxscrpt\maxnode.cpp
  83. // !!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!
  84. class CommonParticle : public SimpleParticle, IParamArray {
  85.    public:
  86.       CommonParticleDraw theSuprSprayDraw;
  87.       static IParamMap *pmapParam;
  88.       static IParamMap *pmapPGen;
  89.       static IParamMap *pmapPType;
  90.       static IParamMap *pmapPSpin;
  91.       static IParamMap *pmapEmitV;
  92.       static IParamMap *pmapSpawn;
  93.       int stepSize,size;
  94.       static int custsettings;
  95.       ULONG dflags;
  96.       Mesh *cmesh, *dispmesh;
  97.       INode *custnode, *cnode;
  98.       TSTR custname;
  99.       DWORD flags;
  100.       BOOL cancelled,wasmulti;
  101.       static BOOL creating;
  102.       static CPickOperand pickCB;
  103.       Mtl *origmtl;
  104.  
  105.       Point3 boxcenter;
  106.       int CustMtls;
  107.       TimeLst times;
  108.       void GetTimes(TimeLst &times,TimeValue t,int anifr,int ltype);
  109.       void TreeDoGroup(INode *node,Matrix3 tspace,Mesh *cmesh,int *numV,int *numF,int *tvnum,int *ismapped,TimeValue t,int subtree,int custmtl);
  110.       void CheckTree(INode *node,Matrix3 tspace,Mesh *cmesh,int *numV,int *numF,int *tvnum,int *ismapped,TimeValue t,int subtree,int custmtl);
  111.       void GetMesh(TimeValue t,int subtree,int custmtl);
  112.       void GetNextBB(INode *node,int subtree,int *count,int *tabmax,Point3 boxcenter,TimeValue t,int tcount,INode *onode);
  113.       void DoGroupBB(INode *node,int subtree,int *count,int *tabmax,Point3 boxcenter,TimeValue t,int tcount,INode *onode);
  114.       void GetallBB(INode *custnode,int subtree,TimeValue t);
  115.  
  116.       Tab<int> nmtls;
  117.       void DoSpawn(int j,int spmult,SpawnVars spvars,TimeValue lvar,BOOL emit);
  118.       void SetUpList();
  119.       void AddToList(INode *newnode,int i,BOOL add);
  120.       void DeleteFromList(int nnum,BOOL all);
  121.       Tab<INode*> nlist;
  122.       Tab<int> llist;
  123.       int deftime;
  124.       int maincount,rseed;
  125.       int NumRefs() {return BASER+nlist.Count();}
  126.       RefTargetHandle GetReference(int i);
  127.       void SetReference(int i, RefTargetHandle rtarg);      
  128.       RefResult NotifyRefChanged( Interval changeInt,RefTargetHandle hTarget,
  129.          PartID& partID, RefMessage message);
  130.       void SetUpLifeList();
  131.       void AddToLifeList(int newlife);
  132.       void DeleteFromLifeList(int nnum);
  133.       void ShowName();
  134.       static AName *NameLst;
  135.       static HWND hParams2,hptype,hgen,hparam,hrot,spawn;
  136.       static ICustEdit *custCtrlEdit;
  137.       void ResetSystem(TimeValue t,BOOL full=TRUE);
  138.  
  139.       void GetWorldBoundBox(TimeValue t, INode *inode, ViewExp* vpt, Box3& box);
  140.       int CountLive();
  141.       int rcounter,vcounter;
  142.       oldipc lc;
  143.       static IObjParam *ip;
  144.       // Animatable methods      
  145.       void DeleteThis() {delete this;}
  146.       void MapKeys(TimeMap *map,DWORD flags);
  147.       int RenderBegin(TimeValue t, ULONG flags);      
  148.       int RenderEnd(TimeValue t);
  149.  
  150.       // From SimpleParticle
  151.       Interval GetValidity(TimeValue t);    
  152.       BOOL EmitterVisible();    
  153.       MarkerType GetMarkerType();  
  154.       CSavePt *sdata;
  155.  
  156.       // From BaseObject
  157.       int IsInstanceDependent() {return 1;}
  158.       Matrix3 TumbleMat(int index,float amount, float scale);
  159.       void GetFilename(TCHAR *filename);
  160.       void SetupTargetList();
  161.       int SaveSettings(int overwrite,TCHAR *newname);
  162.       int GetSettings(int setnum,TCHAR *newname);
  163.       int RemSettings(int setnum,TCHAR *newname);
  164.       IOResult Load(ILoad *iload);
  165.       IOResult Save(ISave *isave);
  166.       void AssignMtl(INode *node,INode *topnode,int subtree,TimeValue t);
  167.       void DoGroupMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t);
  168.       void RetrieveMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t);
  169.       void GetSubs(INode *node,INode *topnode,int subtree,TimeValue t);
  170.       void CntDoGroupMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t);
  171.       void CntRetrieveMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t);
  172.       BOOL backpatch;
  173.       Mtllst mttab;
  174.       TimeValue ParticleLife(TimeValue t, int i);
  175.       int Display(TimeValue t, INode* inode, ViewExp *vpt, int flags);
  176.       int HitTest(TimeValue t, INode *inode, int type, int crossing, int flags,
  177.       IPoint2 *p, ViewExp *vpt);
  178.       TimeValue dispt;
  179.    };
  180.  
  181. class SuprSprayParticle : public CommonParticle {
  182.    public:
  183.       SuprSprayParticle();
  184.       ~SuprSprayParticle();
  185.       static IParamMap *pmapBubl;
  186.       static HWND hbubl;
  187.       CreateMouseCallBack* GetCreateMouseCallBack();
  188.  
  189.       TCHAR *GetObjectName();
  190.       void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev);    
  191.       void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next);    
  192.       void BuildEmitter(TimeValue t, Mesh& amesh);
  193.       void BirthParticle(INode *node,TimeValue bt,int num,VelDir* ptvel,Matrix3 tmlast);
  194.       BOOL ComputeParticleStart(TimeValue t0,int c);
  195.       // From GeomObject
  196.       Mesh* GetRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete);
  197.       // Animatable methods      
  198.       Class_ID ClassID() {return SUPRSPRAY_CLASS_ID;}
  199.       // From ref
  200.       RefTargetHandle Clone(RemapDir& remap);      
  201.  
  202.       // From Simple Particle
  203.       void UpdateParticles(TimeValue t,INode *node);
  204.       ParamDimension *GetParameterDim(int pbIndex);
  205.       TSTR GetParameterName(int pbIndex);
  206.       void InvalidateUI();
  207.       float ParticleSize(TimeValue t,int i);
  208.       int ParticleCenter(TimeValue t,int i);
  209.       Point3 ParticlePosition(TimeValue t,int i);
  210.       Point3 ParticleVelocity(TimeValue t,int i);    
  211.       void MovePart(int j,TimeValue dt,BOOL fullframe,int tpf);
  212.    };
  213. //--- ClassDescriptor and class vars ---------------------------------
  214.  
  215. class SuprSprayClassDesc:public ClassDesc {
  216.    public:
  217.    int         IsPublic() {return 1;}
  218.    void *         Create(BOOL loading = FALSE) {return new SuprSprayParticle;}
  219.    const TCHAR *  ClassName();
  220.    SClass_ID      SuperClassID() {return GEOMOBJECT_CLASS_ID;}
  221.    Class_ID    ClassID() {return SUPRSPRAY_CLASS_ID;}
  222.    const TCHAR*   Category();
  223.    int         BeginCreate(Interface *i);
  224.    int         EndCreate(Interface *i);
  225.    };
  226.  
  227. static SuprSprayClassDesc SuprSprayDesc;
  228. ClassDesc* GetSuprSprayDesc() {return &SuprSprayDesc;}
  229.  
  230. class CPickOperand :
  231.       public PickModeCallback,
  232.       public PickNodeCallback {
  233.    public:    
  234.       CommonParticle *po;
  235.       int dodist,repi;
  236.  
  237.       CPickOperand() {po=NULL;}
  238.  
  239.       BOOL HitTest(IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags);
  240.       BOOL Pick(IObjParam *ip,ViewExp *vpt);
  241.  
  242.       void EnterMode(IObjParam *ip);
  243.       void ExitMode(IObjParam *ip);
  244.  
  245.       BOOL RightClick(IObjParam *ip, ViewExp *vpt) { return TRUE; }
  246.       BOOL Filter(INode *node);
  247.      
  248.       PickNodeCallback *GetFilter() {return this;}
  249.    };
  250. //--- ClassDescriptor and class vars ---------------------------------
  251. IParamMap *CommonParticle::pmapParam;
  252. IParamMap *CommonParticle::pmapPGen;
  253. IParamMap *CommonParticle::pmapPType;
  254. IParamMap *CommonParticle::pmapPSpin;
  255. IParamMap *CommonParticle::pmapEmitV;
  256. IParamMap *CommonParticle::pmapSpawn;
  257. IObjParam *CommonParticle::ip    = NULL;
  258. BOOL CommonParticle::creating    = FALSE;
  259. CPickOperand CommonParticle::pickCB;
  260. ICustEdit *CommonParticle::custCtrlEdit=NULL;
  261. int CommonParticle::custsettings=0;
  262. AName *CommonParticle::NameLst=NULL;
  263. HWND CommonParticle::hParams2;
  264. HWND CommonParticle::hgen;
  265. HWND CommonParticle::hptype;
  266. HWND CommonParticle::hparam;
  267. HWND CommonParticle::hrot;
  268. HWND CommonParticle::spawn;
  269.  
  270. IParamMap *SuprSprayParticle::pmapBubl;
  271. HWND SuprSprayParticle::hbubl;
  272.  
  273. class BlizzardParticle : public CommonParticle {
  274.    public:
  275.       BlizzardParticle();
  276.       ~BlizzardParticle();
  277.       CreateMouseCallBack* GetCreateMouseCallBack();
  278.  
  279.       TCHAR *GetObjectName();
  280.       void BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev);    
  281.       void EndEditParams( IObjParam *ip, ULONG flags,Animatable *next);    
  282.       void BuildEmitter(TimeValue t, Mesh& amesh);
  283.       void BirthParticle(INode *node,TimeValue bt,int num,VelDir* ptvel,Matrix3 tmlast);
  284.       BOOL ComputeParticleStart(TimeValue t0,int c);
  285.       // From GeomObject
  286.       Mesh* GetRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete);
  287.       // Animatable methods      
  288.       Class_ID ClassID() {return BLIZZARD_CLASS_ID;}
  289.       // From ref
  290.       RefTargetHandle Clone(RemapDir& remap);      
  291.  
  292.       // From Simple Particle
  293.       void UpdateParticles(TimeValue t,INode *node);
  294.       ParamDimension *GetParameterDim(int pbIndex);
  295.       TSTR GetParameterName(int pbIndex);
  296.       void InvalidateUI();
  297.       float ParticleSize(TimeValue t,int i);
  298.       int ParticleCenter(TimeValue t,int i);
  299.       Point3 ParticlePosition(TimeValue t,int i);
  300.       Point3 ParticleVelocity(TimeValue t,int i);    
  301.    };
  302. //--- ClassDescriptor and class vars ---------------------------------
  303.  
  304. class BlizzardClassDesc:public ClassDesc {
  305.    public:
  306.    int         IsPublic() {return 1;}
  307.    void *         Create(BOOL loading = FALSE) {return new BlizzardParticle();}
  308.    const TCHAR *  ClassName();
  309.    SClass_ID      SuperClassID() {return GEOMOBJECT_CLASS_ID;}
  310.    Class_ID    ClassID() {return BLIZZARD_CLASS_ID;}
  311.    const TCHAR*   Category();
  312.    int         BeginCreate(Interface *i);
  313.    int         EndCreate(Interface *i);
  314.    };
  315.  
  316. static BlizzardClassDesc BlizzardDesc;
  317. ClassDesc* GetBlizzardDesc() {return &BlizzardDesc;}
  318.  
  319. #define SIZEFACTOR (float(TIME_TICKSPERSEC)/120.0f)
  320.  
  321. //--- Parameter map/block descriptors -------------------------------
  322.  
  323. #define PB_OFFAXIS            0
  324. #define PB_AXISSPREAD         1
  325. #define PB_OFFPLANE           2
  326. #define PB_PLANESPREAD        3
  327. #define PB_SPEED           4
  328. #define PB_SPEEDVAR           5
  329.  
  330. #define PB_BIRTHMETHOD        6
  331. #define PB_PBIRTHRATE         7
  332. #define PB_PTOTALNUMBER       8
  333. #define PB_EMITSTART       9
  334. #define PB_EMITSTOP           10
  335. #define PB_DISPUNTIL       11
  336. #define PB_LIFE               12
  337. #define PB_LIFEVAR            13
  338. #define PB_SUBFRAMEMOVE       14
  339. #define PB_SUBFRAMETIME       15
  340. #define PB_SIZE               16
  341. #define PB_SIZEVAR            17
  342. #define PB_GROWTIME           18
  343. #define PB_FADETIME           19
  344. #define PB_RNDSEED            20
  345. #define PB_EMITRWID           21
  346. #define PB_EMITRHID           22
  347.  
  348. #define PB_PARTICLECLASS      23
  349. #define PB_PARTICLETYPE       24
  350. #define PB_METATENSION        25
  351. #define PB_METATENSIONVAR     26
  352. #define PB_METACOURSE         27
  353. #define PB_METAAUTOCOARSE     28
  354. #define PB_USESUBTREE         29
  355. #define PB_ANIMATIONOFFSET    30
  356. #define PB_OFFSETAMOUNT       31
  357. #define PB_VIEWPORTSHOWS      32
  358. #define PB_DISPLAYPORTION     33
  359. #define PB_MAPPINGTYPE        34
  360. #define PB_MAPPINGTIME        35
  361. #define PB_MAPPINGDIST        36
  362.                  
  363. #define PB_SPINTIME           37
  364. #define PB_SPINTIMEVAR        38
  365. #define PB_SPINPHASE       39
  366. #define PB_SPINPHASEVAR       40
  367. #define PB_SPINAXISTYPE       41
  368. #define PB_SPINAXISX       42
  369. #define PB_SPINAXISY       43
  370. #define PB_SPINAXISZ       44
  371. #define PB_SPINAXISVAR        45
  372.  
  373. #define PB_EMITVINFL       46
  374. #define PB_EMITVMULT       47
  375. #define PB_EMITVMULTVAR       48
  376.  
  377. #define PB_SPAWNTYPE       49
  378. #define PB_SPAWNGENS       50
  379. #define PB_SPAWNCOUNT         51
  380. #define PB_SPAWNDIRCHAOS      52
  381. #define PB_SPAWNSPEEDCHAOS    53
  382. #define PB_SPAWNSPEEDSIGN     54
  383. #define PB_SPAWNINHERITV      55
  384. #define PB_SPAWNSCALECHAOS    56
  385. #define PB_SPAWNSCALESIGN     57
  386. #define PB_SPAWNLIFEVLUE      58
  387. #define PB_SPAWNSPEEDFIXED    59
  388. #define PB_SPAWNSCALEFIXED    60
  389.  
  390. #define PB_BUBLAMP            61
  391. #define PB_BUBLAMPVAR         62
  392. #define PB_BUBLPER            63
  393. #define PB_BUBLPERVAR         64
  394. #define PB_BUBLPHAS           65
  395. #define PB_BUBLPHASVAR        66
  396.  
  397. #define PB_STRETCH            67
  398. #define PB_CUSTOMMTL       68
  399. #define PB_METACOURSEV        69
  400. #define PB_SUBFRAMEROT        70
  401. #define PB_SPAWNPERCENT       71
  402. #define PB_SPAWNMULTVAR       72
  403. #define PB_SSNOTDRAFT         73
  404. #define PB_SSSPAWNDIEAFTER    74
  405. #define PB_SSSPAWNDIEAFTERVAR 75
  406.  
  407. #define PB_IPCOLLIDE_ON       76
  408. #define PB_IPCOLLIDE_STEPS    77
  409. #define PB_IPCOLLIDE_BOUNCE      78
  410. #define PB_IPCOLLIDE_BOUNCEVAR   79
  411.  
  412. // render types
  413. #define RENDMETA    8
  414. #define RENDGEOM  9
  415.  
  416. // Parameters
  417. #define ISSTD 0
  418. #define METABALLS 1
  419. #define INSTGEOM 2
  420.  
  421. static int countIDs[] = {IDC_SP_GENUSERATE,IDC_SP_GENUSETTL};
  422.  
  423. static int particleclassIDs[] = {IDC_SP_TYPESTD,IDC_SP_TYPEMET,IDC_SP_TYPEINSTANCE};
  424.  
  425. static int particletypeIDs[] = {IDC_SP_TYPETRI,IDC_SP_TYPECUB,IDC_SP_TYPESPC,IDC_SP_TYPEFAC,
  426.                         IDC_SP_TYPEPIX,IDC_SP_TYPETET,IDC_SP_TYPE6PNT,IDC_SP_TYPESPHERE};
  427.  
  428. static int viewportoptionIDs[] = {IDC_SP_VIEWDISPDOT,IDC_SP_VIEWDISPTIK,IDC_SP_VIEWDISPMESH,IDC_SP_VIEWDISPBOX};
  429.  
  430. static int mappingIDs[] = {IDC_SP_MAPTIME,IDC_SP_MAPDIST};
  431.  
  432. static int spindirectionIDs[] = {IDC_AP_PARTICLEDIRRND,IDC_AP_PARTICLEDIRTRAVL,IDC_AP_PARTICLEDIRUSER};
  433. static int bspindirectionIDs[] = {IDC_AP_PARTICLEDIRRND,IDC_AP_PARTICLEDIRUSER};
  434.  
  435. #define DIRTRAVEL 1
  436.  
  437. static int animateoffsetIDs[] = {IDC_AP_NOANIOFF,IDC_AP_ANIOFFBIRTH,IDC_AP_ANIOFFRND};
  438. static int custmtlIDs[] = {IDC_SP_MAPCUSTOMEMIT,IDC_SP_MAPCUSTOMINST};
  439.  
  440. // Dialog Unique to SuperSpray
  441. static ParamUIDesc descParamSuprSpray[] = {
  442.  
  443.    // Particle Off Axis
  444.    ParamUIDesc(
  445.       PB_OFFAXIS,
  446.       EDITTYPE_FLOAT,
  447.       IDC_SP_OFFAXIS,IDC_SP_OFFAXISSPIN,
  448.       -180.0f,180.0f,
  449.       1.0f,
  450.       stdAngleDim),
  451.  
  452.    // Particle Off Axis Spread
  453.    ParamUIDesc(
  454.       PB_AXISSPREAD,
  455.       EDITTYPE_FLOAT,
  456.       IDC_SP_OFFAXISVAR,IDC_SP_OFFAXISVARSPIN,
  457.       0.0f,180.0f,
  458.       1.0f,
  459.       stdAngleDim),
  460.  
  461.    // Particle Off Plane
  462.    ParamUIDesc(
  463.       PB_OFFPLANE,
  464.       EDITTYPE_FLOAT,
  465.       IDC_SP_OFFPLANE,IDC_SP_OFFPLANESPIN,
  466.       -180.0f,180.0f,
  467.       1.0f,
  468.       stdAngleDim),
  469.  
  470.    // Particle Off Plane Spread
  471.    ParamUIDesc(
  472.       PB_PLANESPREAD,
  473.       EDITTYPE_FLOAT,
  474.       IDC_SP_OFFPLANEVAR,IDC_SP_OFFPLANEVARSPIN,
  475.       0.0f,180.0f,
  476.       1.0f,
  477.       stdAngleDim),
  478.  
  479.    // Emitter Width
  480.    ParamUIDesc(
  481.       PB_EMITRWID,
  482.       EDITTYPE_UNIVERSE,
  483.       IDC_SP_EMITWID,IDC_SP_EMITWIDSPIN,
  484.       0.0f,999999999.0f,
  485.       SPIN_AUTOSCALE),  
  486.  
  487.    // Hide Emitter
  488.    ParamUIDesc(PB_EMITRHID,TYPE_SINGLECHEKBOX,IDC_SP_EMITHID),
  489.  
  490.    // Viewport Shows
  491.    ParamUIDesc(PB_VIEWPORTSHOWS,TYPE_RADIO,viewportoptionIDs,4),
  492.  
  493.    // Particle Display Portion
  494.    ParamUIDesc(
  495.       PB_DISPLAYPORTION,
  496.       EDITTYPE_FLOAT,
  497.       IDC_SP_GENDISP,IDC_SP_GENDISPSPIN,
  498.       0.0f,100.0f,
  499.       0.1f,
  500.       stdPercentDim),
  501. };
  502.  
  503. #define PARAMSuprSpray_LENGTH 8
  504.  
  505. // Common Dialog for Particle Generation
  506. static ParamUIDesc descParamPGen[] = {
  507.  
  508.    // Distribution Method
  509.    ParamUIDesc(PB_BIRTHMETHOD,TYPE_RADIO,countIDs,2),
  510.  
  511.    // Particle Birth Rate
  512.    ParamUIDesc(
  513.       PB_PBIRTHRATE,
  514.       EDITTYPE_INT,
  515.       IDC_SP_GENRATE,IDC_SP_GENRATESPIN,
  516.       0.0f,65000.0f,
  517.       1.0f),
  518.  
  519.    // Particle Total Count
  520.    ParamUIDesc(
  521.       PB_PTOTALNUMBER,
  522.       EDITTYPE_INT,
  523.       IDC_SP_GENTTL,IDC_SP_GENTTLSPIN,
  524.       0.0f,65000.0f,
  525.       1.0f),
  526.  
  527.    // Particle Speed
  528.    ParamUIDesc(
  529.       PB_SPEED,
  530.       EDITTYPE_UNIVERSE,
  531.       IDC_SP_SPEED,IDC_SP_SPEEDSPIN,
  532.       0.0f,999999999.0f,
  533.       SPIN_AUTOSCALE),
  534.  
  535.    // Particle Speed Var
  536.    ParamUIDesc(
  537.       PB_SPEEDVAR,
  538.       EDITTYPE_FLOAT,
  539.       IDC_SP_SPEEDVAR2,IDC_SP_SPEEDVARSPIN2,
  540.       0.0f,100.0f,
  541.       SPIN_AUTOSCALE,stdPercentDim),
  542.  
  543.    // Emitter Start Time
  544.    ParamUIDesc(
  545.       PB_EMITSTART,
  546.       EDITTYPE_TIME,
  547.       IDC_SP_GENEMIT1,IDC_SP_GENEMIT1SPIN,
  548.       -999999999.0f,999999999.0f,
  549.       10.0f),
  550.  
  551.    // Emitter Stop Time
  552.    ParamUIDesc(
  553.       PB_EMITSTOP,
  554.       EDITTYPE_TIME,
  555.       IDC_SP_GENEMIT2,IDC_SP_GENEMIT2SPIN,
  556.       -999999999.0f,999999999.0f,
  557.       10.0f),
  558.  
  559.    // Particle Time Limit
  560.    ParamUIDesc(
  561.       PB_DISPUNTIL,
  562.       EDITTYPE_TIME,
  563.       IDC_SP_DISPUNTIL,IDC_SP_DISPUNTILSPIN,
  564.       -999999999.0f,999999999.0f,
  565.       10.0f),
  566.  
  567.    // Particle Life
  568.    ParamUIDesc(
  569.       PB_LIFE,
  570.       EDITTYPE_TIME,
  571.       IDC_SP_GENLIFE,IDC_SP_GENLIFESPIN,
  572.       0.0f,999999999.0f,
  573.       10.0f),
  574.  
  575.    // Particle Life Var
  576.    ParamUIDesc(
  577.       PB_LIFEVAR,
  578.       EDITTYPE_TIME,
  579.       IDC_SP_GENLIFEVAR,IDC_SP_GENLIFEVARSPIN,
  580.       0.0f,999999999.0f,
  581.       10.0f),
  582.  
  583.    // Subframe Time and Motion Sampling
  584.    ParamUIDesc(PB_SUBFRAMEMOVE,TYPE_SINGLECHEKBOX,IDC_SP_GENSMPLMOVE),
  585.    ParamUIDesc(PB_SUBFRAMETIME,TYPE_SINGLECHEKBOX,IDC_SP_GENSMPLTIME),
  586.    ParamUIDesc(PB_SUBFRAMEROT,TYPE_SINGLECHEKBOX,IDC_SP_GENSMPLROT),
  587.  
  588.    // Particle Size
  589.    ParamUIDesc(
  590.       PB_SIZE,
  591.       EDITTYPE_UNIVERSE,
  592.       IDC_SP_GENSIZE,IDC_SP_GENSIZESPIN,
  593.       0.0f,999999999.0f,
  594.       SPIN_AUTOSCALE),
  595.  
  596.    // Particle Size Var
  597.    ParamUIDesc(
  598.       PB_SIZEVAR,
  599.       EDITTYPE_FLOAT,
  600.       IDC_SP_GENSIZEVAR,IDC_SP_GENSIZEVARSPIN,
  601.       0.0f,100.0f,
  602.       SPIN_AUTOSCALE,stdPercentDim),
  603.  
  604.    // Particle Grow Time
  605.    ParamUIDesc(
  606.       PB_GROWTIME,
  607.       EDITTYPE_TIME,
  608.       IDC_SP_GENGRO,IDC_SP_GENGROSPIN,
  609.       0.0f,999999999.0f,
  610.       10.0f),
  611.  
  612.    // Particle Fade Time
  613.    ParamUIDesc(
  614.       PB_FADETIME,
  615.       EDITTYPE_TIME,
  616.       IDC_SP_GENFAD,IDC_SP_GENFADSPIN,
  617.       0.0f,999999999.0f,
  618.       10.0f),
  619.  
  620.    // Random Number Seed
  621.    ParamUIDesc(
  622.       PB_RNDSEED,
  623.       EDITTYPE_INT,
  624.       IDC_SP_GENSEED,IDC_SP_GENSEEDSPIN,
  625.       0.0f,25000.0f,
  626.       1.0f),
  627. };
  628.  
  629. #define PARAMPGEN_LENGTH 18
  630.  
  631. // Particle Type for SuprSpray
  632. static ParamUIDesc descParamPType[] = {
  633.  
  634.    // Particle Class
  635.    ParamUIDesc(PB_PARTICLECLASS,TYPE_RADIO,particleclassIDs,3),
  636.  
  637.    // Particle Type
  638.    ParamUIDesc(PB_PARTICLETYPE,TYPE_RADIO,particletypeIDs,8),
  639.  
  640.    // Metaball Tension
  641.    ParamUIDesc(
  642.       PB_METATENSION,
  643.       EDITTYPE_FLOAT,
  644.       IDC_SP_METTENS,IDC_SP_METTENSSPIN,
  645.       0.1f,10.0f,
  646.       SPIN_AUTOSCALE),
  647.  
  648.    // Metaball Tension Variation
  649.    ParamUIDesc(
  650.       PB_METATENSIONVAR,
  651.       EDITTYPE_FLOAT,
  652.       IDC_SP_METTENSVAR,IDC_SP_METTENSVARSPIN,
  653.       0.0f,100.0f,
  654.       SPIN_AUTOSCALE,stdPercentDim),
  655.  
  656.    // Metaball Courseness
  657.    ParamUIDesc(
  658.       PB_METACOURSE,
  659.       EDITTYPE_UNIVERSE,
  660.       IDC_SP_METCOURSE,IDC_SP_METCOURSESPIN,
  661.       0.0f,999999999.0f,
  662.       SPIN_AUTOSCALE),
  663.  
  664.    // Metaball Courseness ViewPort
  665.    ParamUIDesc(
  666.       PB_METACOURSEV,
  667.       EDITTYPE_UNIVERSE,
  668.       IDC_SP_METCOURSEV,IDC_SP_METCOURSEVSPIN,
  669.       0.0f,999999999.0f,
  670.       SPIN_AUTOSCALE),
  671.  
  672.    // Metaball Auto Coarseness
  673.    ParamUIDesc(PB_METAAUTOCOARSE,TYPE_SINGLECHEKBOX,IDC_SP_AUTOCOARSE),
  674.  
  675.    // Display type
  676.    ParamUIDesc(PB_SSNOTDRAFT,TYPE_SINGLECHEKBOX,IDC_SP_DRAFTMODE),
  677.  
  678.    // Use Subtree Checkbox
  679.    ParamUIDesc(PB_USESUBTREE,TYPE_SINGLECHEKBOX,IDC_AP_USESUBTREE),
  680.  
  681.    // Display type
  682.    ParamUIDesc(PB_ANIMATIONOFFSET,TYPE_RADIO,animateoffsetIDs,3),
  683.  
  684.    // Animation Offset Amount
  685.    ParamUIDesc(
  686.       PB_OFFSETAMOUNT,
  687.       EDITTYPE_TIME,
  688.       IDC_AP_ANIRNDFR,IDC_AP_ANIRNDFRSPIN,
  689.       1.0f,999999999.0f,
  690.       10.0f),
  691.  
  692.    // Mapping Across
  693.    ParamUIDesc(PB_MAPPINGTYPE,TYPE_RADIO,mappingIDs,2),
  694.  
  695.    // Time Mapping Option
  696.    ParamUIDesc(
  697.       PB_MAPPINGTIME,
  698.       EDITTYPE_TIME,
  699.       IDC_SP_MAPTIMEVAL,IDC_SP_MAPTIMEVALSPIN,
  700.       1.0f,999999999.0f,
  701.       10.0f),
  702.  
  703.    // Distance Mapping Option
  704.    ParamUIDesc(
  705.       PB_MAPPINGDIST,
  706.       EDITTYPE_UNIVERSE,
  707.       IDC_SP_MAPDISTVAL,IDC_SP_MAPDISTVALSPIN,
  708.       0.1f,999999999.0f,
  709.       SPIN_AUTOSCALE),
  710.  
  711.    // Use Custom Mtl
  712.    ParamUIDesc(PB_CUSTOMMTL,TYPE_RADIO,custmtlIDs,2),
  713. };
  714.  
  715. #define PARAMPTYPE_LENGTH 15
  716.  
  717. // SS Dialog for Particle Spin
  718. static ParamUIDesc descParamPSpin[] = {
  719.  
  720.    // Spin Time
  721.    ParamUIDesc(
  722.       PB_SPINTIME,
  723.       EDITTYPE_TIME,
  724.       IDC_SP_SPIN,IDC_SP_SPINSPIN,
  725.       0.0f,999999999.0f,
  726.       10.0f),
  727.  
  728.    // Spin Time Var
  729.    ParamUIDesc(
  730.       PB_SPINTIMEVAR,
  731.       EDITTYPE_FLOAT,
  732.       IDC_SP_SPINVAR,IDC_SP_SPINVARSPIN,
  733.       0.0f,100.0f,
  734.       0.01f,
  735.       stdPercentDim),
  736.  
  737.    // Spin Phase
  738.    ParamUIDesc(
  739.       PB_SPINPHASE,
  740.       EDITTYPE_FLOAT,
  741.       IDC_SP_SPINPHA,IDC_SP_SPINPHASPIN,
  742.       -360.0f,360.0f,
  743.       0.01f,
  744.       stdAngleDim),
  745.  
  746.    // Spin Phase Variation
  747.    ParamUIDesc(
  748.       PB_SPINPHASEVAR,
  749.       EDITTYPE_FLOAT,
  750.       IDC_SP_SPINPHAVAR,IDC_SP_SPINPHAVARSPIN,
  751.       0.0f,100.0f,
  752.       0.01f,
  753.       stdPercentDim),
  754.  
  755.    // Enter Axis Control
  756.    ParamUIDesc(PB_SPINAXISTYPE,TYPE_RADIO,spindirectionIDs,3),
  757.  
  758.    // X-Axis
  759.    ParamUIDesc(
  760.       PB_SPINAXISX,
  761.       EDITTYPE_FLOAT,
  762.       IDC_SP_SPINAXISX,IDC_SP_SPINAXISXSPIN,
  763.       -999999999.0f,999999999.0f,
  764.       SPIN_AUTOSCALE),
  765.  
  766.    // Y-Axis
  767.    ParamUIDesc(
  768.       PB_SPINAXISY,
  769.       EDITTYPE_FLOAT,
  770.       IDC_SP_SPINAXISY,IDC_SP_SPINAXISYSPIN,
  771.       -999999999.0f,999999999.0f,
  772.       SPIN_AUTOSCALE),
  773.  
  774.    // Z-Axis
  775.    ParamUIDesc(
  776.       PB_SPINAXISZ,
  777.       EDITTYPE_FLOAT,
  778.       IDC_SP_SPINAXISZ,IDC_SP_SPINAXISZSPIN,
  779.       -999999999.0f,999999999.0f,
  780.       SPIN_AUTOSCALE),
  781.  
  782.    // Spin Direction Variation
  783.    ParamUIDesc(
  784.       PB_SPINAXISVAR,
  785.       EDITTYPE_FLOAT,
  786.       IDC_SP_SPINAXISVAR,IDC_SP_SPINAXISVARSPIN,
  787.       -180.0f,180.0f,
  788.       0.01f,
  789.       stdAngleDim),
  790.  
  791.    // Stretch
  792.    ParamUIDesc(
  793.       PB_STRETCH,
  794.       EDITTYPE_INT,
  795.       IDC_AP_STRETCH,IDC_AP_STRETCHSPIN,
  796.       -1000.0f,1000.0f,
  797.       1.0f),
  798.  
  799.    // IPC Enable
  800.    ParamUIDesc(PB_IPCOLLIDE_ON,TYPE_SINGLECHEKBOX,IDC_INTERP_BOUNCEON),
  801.  
  802.    // IPC Steps
  803.    ParamUIDesc(
  804.       PB_IPCOLLIDE_STEPS,
  805.       EDITTYPE_INT,
  806.       IDC_INTERP_NSTEPS,IDC_INTERP_NSTEPSSPIN,
  807.       1.0f,1000.0f,
  808.       1.0f),
  809.  
  810.    // IPC Bounce
  811.    ParamUIDesc(
  812.       PB_IPCOLLIDE_BOUNCE,
  813.       EDITTYPE_FLOAT,
  814.       IDC_INTERP_BOUNCE,IDC_INTERP_BOUNCESPIN,
  815.       0.0f,10000.0f,
  816.       1.0f,
  817.       stdPercentDim),
  818.  
  819.    // IPC Bounce
  820.    ParamUIDesc(
  821.       PB_IPCOLLIDE_BOUNCEVAR,
  822.       EDITTYPE_FLOAT,
  823.       IDC_INTERP_BOUNCEVAR,IDC_INTERP_BOUNCEVARSPIN,
  824.       0.0f,100.0f,
  825.       1.0f,
  826.       stdPercentDim),
  827.  
  828. };
  829.  
  830. #define PARAMPSPIN_LENGTH 14
  831.  
  832. // Common Dialog for Secondary Motion Data
  833. static ParamUIDesc descParamEmitV[] = {
  834.  
  835.    // Emitter Velocity Inheritance Influence Portion
  836.    ParamUIDesc(
  837.       PB_EMITVINFL,
  838.       EDITTYPE_FLOAT,
  839.       IDC_SP_EMVI,IDC_SP_EMVISPIN,
  840.       0.0f,100.0f,
  841.       0.01f),
  842.  
  843.    // Secondary Motion Multiplier
  844.    ParamUIDesc(
  845.       PB_EMITVMULT,
  846.       EDITTYPE_FLOAT,
  847.       IDC_SP_EMVIMULT,IDC_SP_EMVIMULTSPIN,
  848.       -999999999.0f,999999999.0f,
  849.       SPIN_AUTOSCALE),
  850.  
  851.    // Multiplier Variation
  852.    ParamUIDesc(
  853.       PB_EMITVMULTVAR,
  854.       EDITTYPE_FLOAT,
  855.       IDC_SP_EMVIMULTVAR,IDC_SP_EMVIMULTVARSPIN,
  856.       0.0f,100.0f,
  857.       0.01f,
  858.       stdPercentDim),
  859.    };
  860. #define PARAMEMITV_LENGTH 3
  861.  
  862. // Common Dialog for Bubble Motion
  863. static ParamUIDesc descParamBubl[] = {
  864.  
  865.    // Bubble Amplitude
  866.    ParamUIDesc(
  867.       PB_BUBLAMP,
  868.       EDITTYPE_UNIVERSE,
  869.       IDC_SP_BUBL_AMP,IDC_SP_BUBL_AMPSPIN,
  870.       -.0f,999999999.0f,
  871.       SPIN_AUTOSCALE),
  872.  
  873.    // Bubble Amp Var
  874.    ParamUIDesc(
  875.       PB_BUBLAMPVAR,
  876.       EDITTYPE_FLOAT,
  877.       IDC_SP_BUBL_AMPVAR,IDC_SP_BUBL_AMPVARSPIN,
  878.       0.0f,100.0f,
  879.       0.01f,
  880.       stdPercentDim),
  881.  
  882.    // Bubble Period
  883.    ParamUIDesc(
  884.       PB_BUBLPER,
  885.       EDITTYPE_TIME,
  886.       IDC_SP_BUBL_PER,IDC_SP_BUBL_PERSPIN,
  887.       0.0f,999999999.0f,
  888.       10.0f),
  889.  
  890.    // Bubble Period Var
  891.    ParamUIDesc(
  892.       PB_BUBLPERVAR,
  893.       EDITTYPE_FLOAT,
  894.       IDC_SP_BUBL_PERVAR,IDC_SP_BUBL_PERVARSPIN,
  895.       0.0f,100.0f,
  896.       0.01f,
  897.       stdPercentDim),
  898.  
  899.    // Bubble Phase
  900.    ParamUIDesc(
  901.       PB_BUBLPHAS,
  902.       EDITTYPE_FLOAT,
  903.       IDC_SP_BUBL_PERPHA,IDC_SP_BUBL_PERPHASPIN,
  904.       -360.0f,360.0f,
  905.       0.01f,
  906.       stdAngleDim),
  907.  
  908.    // Bubble Phase Var
  909.    ParamUIDesc(
  910.       PB_BUBLPHASVAR,
  911.       EDITTYPE_FLOAT,
  912.       IDC_SP_BUBL_PERPHAVAR,IDC_SP_BUBL_PERPHAVARSPIN,
  913.       0.0f,100.0f,
  914.       0.01f,
  915.       stdPercentDim),
  916. };
  917. #define PARAMBUBL_LENGTH 6
  918.  
  919.  
  920. static int SpawnTypeIDs[] = {IDC_AP_NOSPAWN,IDC_AP_COLLIDEDIE,IDC_AP_COLLIDESPAWN,IDC_AP_DEATHSPAWN,IDC_AP_SPAWNTRAILS};
  921. static int SpeedChaosIDs[] = {IDC_AP_SPEEDLESS,IDC_AP_SPEEDMORE,IDC_AP_SPEEDBOTH};
  922. static int ScaleChaosIDs[] = {IDC_AP_SCALEDOWN,IDC_AP_SCALEUP,IDC_AP_SCALEBOTH};
  923.  
  924. // Dialog for Particle Spawning
  925. static ParamUIDesc descPSpawning[] = {
  926.    
  927.    // Spawing Effects Type
  928.    ParamUIDesc(PB_SPAWNTYPE,TYPE_RADIO,SpawnTypeIDs,5),
  929.  
  930.    // Die after X
  931.    ParamUIDesc(
  932.       PB_SSSPAWNDIEAFTER,
  933.       EDITTYPE_TIME,
  934.       IDC_AP_MAXSPAWNDIEAFTER,IDC_AP_MAXSPAWNDIEAFTERSPIN,
  935.       0.0f,999999999.0f,
  936.       10.0f),
  937.  
  938.    ParamUIDesc(
  939.       PB_SSSPAWNDIEAFTERVAR,
  940.       EDITTYPE_FLOAT,
  941.       IDC_AP_MAXSPAWNDIEAFTERVAR,IDC_AP_MAXSPAWNDIEAFTERVARSPIN,
  942.       0.0f,100.0f,
  943.       0.01f,
  944.       stdPercentDim),
  945.  
  946.    // Spawn Generations
  947.    ParamUIDesc(
  948.       PB_SPAWNGENS,
  949.       EDITTYPE_INT,
  950.       IDC_AP_MAXSPAWNGENS,IDC_AP_MAXSPAWNGENSSPIN,
  951.       1.0f,65000.0f,
  952.       1.0f),
  953.  
  954.    // Spawn Generations
  955.    ParamUIDesc(
  956.       PB_SPAWNPERCENT,
  957.       EDITTYPE_INT,
  958.       IDC_AP_PARENTPERCENT,IDC_AP_PARENTPERCENTSPIN,
  959.       1.0f,100.0f,
  960.       1.0f),
  961.  
  962.    // Spawn Spawncount
  963.    ParamUIDesc(
  964.       PB_SPAWNCOUNT,
  965.       EDITTYPE_INT,
  966.       IDC_AP_NUMBERVAR,IDC_AP_NUMBERVARSPIN,
  967.       1.0f,65000.0f,
  968.       1.0f),
  969.  
  970.    // Spawn Mult Percent
  971.    ParamUIDesc(
  972.       PB_SPAWNMULTVAR,
  973.       EDITTYPE_FLOAT,
  974.       IDC_AP_NUMBERVARVAR,IDC_AP_NUMBERVARVARSPIN,
  975.       0.0f,100.0f,
  976.       0.1f,stdPercentDim),
  977.  
  978.    // Spawn Direction Chaos
  979.    ParamUIDesc(
  980.       PB_SPAWNDIRCHAOS,
  981.       EDITTYPE_FLOAT,
  982.       IDC_AP_CHAOSANGLE,IDC_AP_CHAOSANGLESPIN,
  983.       0.0f,100.0f,
  984.       0.1f,stdPercentDim),
  985.  
  986.    // Spawn Speed Chaos
  987.    ParamUIDesc(
  988.       PB_SPAWNSPEEDCHAOS,
  989.       EDITTYPE_FLOAT,
  990.       IDC_AP_CHAOSSPEED,IDC_AP_CHAOSSPEEDSPIN,
  991.       0.0f,100.0f,
  992.       0.1f),
  993.  
  994.    // Spawing Speed Sign
  995.    ParamUIDesc(PB_SPAWNSPEEDSIGN,TYPE_RADIO,SpeedChaosIDs,3),
  996.  
  997.    // Spawning Inherit Parent V
  998.    ParamUIDesc(PB_SPAWNINHERITV,TYPE_SINGLECHEKBOX,IDC_AP_SPAWNSUMV),
  999.  
  1000.    // Spawning Speed Fixed
  1001.    ParamUIDesc(PB_SPAWNSPEEDFIXED,TYPE_SINGLECHEKBOX,IDC_AP_SPAWNSPEEDFIXED),
  1002.  
  1003.    // Spawn Scale Chaos
  1004.    ParamUIDesc(
  1005.       PB_SPAWNSCALECHAOS,
  1006.       EDITTYPE_FLOAT,
  1007.       IDC_AP_CHAOSSCALE,IDC_AP_CHAOSSCALESPIN,
  1008.       0.0f,100.0f,
  1009.       0.1f),
  1010.  
  1011.    // Spawning Scale Sign
  1012.    ParamUIDesc(PB_SPAWNSCALESIGN,TYPE_RADIO,ScaleChaosIDs,3),
  1013.  
  1014.    // Spawning Speed Fixed
  1015.    ParamUIDesc(PB_SPAWNSCALEFIXED,TYPE_SINGLECHEKBOX,IDC_AP_SPAWNSCALEFIXED),
  1016.  
  1017.    // Spawn Lifespan Entry Field
  1018.    ParamUIDesc(
  1019.       PB_SPAWNLIFEVLUE,
  1020.       EDITTYPE_INT,
  1021.       IDC_AP_QUEUELIFESPAN,IDC_AP_QUEUELIFESPANSPIN,
  1022.       0.0f,65000.0f,
  1023.       1.0f),
  1024. };
  1025. #define PSPAWNINGPARAMS_LENGTH 16
  1026.  
  1027. static ParamBlockDescID spdescVer0[] = {
  1028.    { TYPE_FLOAT, NULL, TRUE, 0 },    // off axis
  1029.    { TYPE_FLOAT, NULL, TRUE, 1 },    // axis apread
  1030.    { TYPE_FLOAT, NULL, TRUE, 2 },    // off plane
  1031.    { TYPE_FLOAT, NULL, TRUE, 3 },    // plane spread
  1032.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  1033.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  1034.  
  1035.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  1036.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  1037.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  1038.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  1039.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  1040.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  1041.    { TYPE_INT, NULL, TRUE, 12 },  // life
  1042.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  1043.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  1044.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  1045.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  1046.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  1047.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  1048.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  1049.    { TYPE_INT, NULL, FALSE, 20 }, // rnd seed
  1050.    { TYPE_FLOAT, NULL, FALSE, 21 },  // emitter width
  1051.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  1052.  
  1053.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  1054.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  1055.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  1056.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  1057.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  1058.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  1059.     { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  1060.     { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  1061.     { TYPE_INT, NULL, FALSE, 31 }, // offset amount
  1062.  
  1063.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  1064.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  1065.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  1066.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  1067.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  1068.  
  1069.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  1070.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  1071.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  1072.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  1073.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choice
  1074.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  1075.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  1076.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  1077.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  1078.  
  1079.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  1080.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  1081.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  1082.  
  1083.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  1084.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  1085.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  1086.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  1087.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  1088.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  1089.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  1090.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  1091.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  1092.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  1093.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  1094.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  1095.  
  1096.    { TYPE_FLOAT, NULL, TRUE, 61 },  // bubble amp61
  1097.    { TYPE_FLOAT, NULL, TRUE, 62 },  // bubble amp var
  1098.    { TYPE_INT, NULL, TRUE, 63 },  // bubble period
  1099.    { TYPE_FLOAT, NULL, TRUE, 64 },  // bubble period var
  1100.    { TYPE_FLOAT, NULL, TRUE, 65 },  // bubble phase
  1101.    { TYPE_FLOAT, NULL, TRUE, 66 },  // bubble phase var
  1102.  
  1103.    { TYPE_INT, NULL, TRUE, 67 },  // Stretch
  1104.    { TYPE_INT, NULL, FALSE, 68 },  // Custom Mtl
  1105. };
  1106.  
  1107. static ParamBlockDescID spdescVer1[] = {
  1108.    { TYPE_FLOAT, NULL, TRUE, 0 },    // off axis
  1109.    { TYPE_FLOAT, NULL, TRUE, 1 },    // axis apread
  1110.    { TYPE_FLOAT, NULL, TRUE, 2 },    // off plane
  1111.    { TYPE_FLOAT, NULL, TRUE, 3 },    // plane spread
  1112.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  1113.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  1114.  
  1115.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  1116.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  1117.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  1118.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  1119.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  1120.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  1121.    { TYPE_INT, NULL, TRUE, 12 },  // life
  1122.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  1123.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  1124.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  1125.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  1126.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  1127.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  1128.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  1129.    { TYPE_INT, NULL, FALSE, 20 }, // rnd seed
  1130.    { TYPE_FLOAT, NULL, FALSE, 21 },  // emitter width
  1131.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  1132.  
  1133.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  1134.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  1135.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  1136.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  1137.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  1138.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  1139.     { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  1140.     { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  1141.     { TYPE_INT, NULL, FALSE, 31 }, // offset amount
  1142.  
  1143.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  1144.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  1145.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  1146.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  1147.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  1148.  
  1149.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  1150.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  1151.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  1152.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  1153.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choice
  1154.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  1155.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  1156.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  1157.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  1158.  
  1159.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  1160.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  1161.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  1162.  
  1163.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  1164.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  1165.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  1166.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  1167.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  1168.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  1169.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  1170.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  1171.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  1172.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  1173.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  1174.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  1175.  
  1176.    { TYPE_FLOAT, NULL, TRUE, 61 },  // bubble amp61
  1177.    { TYPE_FLOAT, NULL, TRUE, 62 },  // bubble amp var
  1178.    { TYPE_INT, NULL, TRUE, 63 },  // bubble period
  1179.    { TYPE_FLOAT, NULL, TRUE, 64 },  // bubble period var
  1180.    { TYPE_FLOAT, NULL, TRUE, 65 },  // bubble phase
  1181.    { TYPE_FLOAT, NULL, TRUE, 66 },  // bubble phase var
  1182.  
  1183.    { TYPE_INT, NULL, TRUE, 67 },  // Stretch
  1184.    { TYPE_INT, NULL, FALSE, 68 },  // Custom Mtl
  1185.    { TYPE_FLOAT, NULL, FALSE, 69 },  // ViewPort Courseness
  1186. };
  1187.  
  1188. static ParamBlockDescID spdescVer2[] = {
  1189.    { TYPE_FLOAT, NULL, TRUE, 0 },    // off axis
  1190.    { TYPE_FLOAT, NULL, TRUE, 1 },    // axis apread
  1191.    { TYPE_FLOAT, NULL, TRUE, 2 },    // off plane
  1192.    { TYPE_FLOAT, NULL, TRUE, 3 },    // plane spread
  1193.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  1194.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  1195.  
  1196.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  1197.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  1198.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  1199.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  1200.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  1201.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  1202.    { TYPE_INT, NULL, TRUE, 12 },  // life
  1203.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  1204.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  1205.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  1206.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  1207.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  1208.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  1209.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  1210.    { TYPE_INT, NULL, FALSE, 20 }, // rnd seed
  1211.    { TYPE_FLOAT, NULL, FALSE, 21 },  // emitter width
  1212.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  1213.  
  1214.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  1215.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  1216.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  1217.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  1218.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  1219.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  1220.     { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  1221.     { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  1222.     { TYPE_INT, NULL, FALSE, 31 }, // offset amount
  1223.  
  1224.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  1225.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  1226.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  1227.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  1228.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  1229.  
  1230.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  1231.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  1232.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  1233.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  1234.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choice
  1235.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  1236.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  1237.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  1238.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  1239.  
  1240.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  1241.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  1242.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  1243.  
  1244.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  1245.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  1246.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  1247.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  1248.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  1249.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  1250.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  1251.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  1252.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  1253.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  1254.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  1255.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  1256.  
  1257.    { TYPE_FLOAT, NULL, TRUE, 61 },  // bubble amp61
  1258.    { TYPE_FLOAT, NULL, TRUE, 62 },  // bubble amp var
  1259.    { TYPE_INT, NULL, TRUE, 63 },  // bubble period
  1260.    { TYPE_FLOAT, NULL, TRUE, 64 },  // bubble period var
  1261.    { TYPE_FLOAT, NULL, TRUE, 65 },  // bubble phase
  1262.    { TYPE_FLOAT, NULL, TRUE, 66 },  // bubble phase var
  1263.  
  1264.    { TYPE_INT, NULL, TRUE, 67 },  // Stretch
  1265.    { TYPE_INT, NULL, FALSE, 68 },  // Custom Mtl
  1266.    { TYPE_FLOAT, NULL, FALSE, 69 },  // ViewPort Courseness
  1267.    { TYPE_INT, NULL, FALSE, 70 },  // Subframe rot
  1268. };
  1269.  
  1270. static ParamBlockDescID spdescVer3[] = {
  1271.    { TYPE_FLOAT, NULL, TRUE, 0 },    // off axis
  1272.    { TYPE_FLOAT, NULL, TRUE, 1 },    // axis apread
  1273.    { TYPE_FLOAT, NULL, TRUE, 2 },    // off plane
  1274.    { TYPE_FLOAT, NULL, TRUE, 3 },    // plane spread
  1275.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  1276.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  1277.  
  1278.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  1279.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  1280.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  1281.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  1282.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  1283.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  1284.    { TYPE_INT, NULL, TRUE, 12 },  // life
  1285.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  1286.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  1287.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  1288.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  1289.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  1290.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  1291.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  1292.    { TYPE_INT, NULL, FALSE, 20 }, // rnd seed
  1293.    { TYPE_FLOAT, NULL, FALSE, 21 },  // emitter width
  1294.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  1295.  
  1296.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  1297.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  1298.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  1299.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  1300.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  1301.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  1302.     { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  1303.     { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  1304.     { TYPE_INT, NULL, FALSE, 31 }, // offset amount
  1305.  
  1306.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  1307.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  1308.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  1309.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  1310.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  1311.  
  1312.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  1313.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  1314.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  1315.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  1316.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choice
  1317.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  1318.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  1319.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  1320.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  1321.  
  1322.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  1323.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  1324.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  1325.  
  1326.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  1327.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  1328.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  1329.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  1330.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  1331.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  1332.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  1333.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  1334.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  1335.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  1336.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  1337.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  1338.  
  1339.    { TYPE_FLOAT, NULL, TRUE, 61 },  // bubble amp61
  1340.    { TYPE_FLOAT, NULL, TRUE, 62 },  // bubble amp var
  1341.    { TYPE_INT, NULL, TRUE, 63 },  // bubble period
  1342.    { TYPE_FLOAT, NULL, TRUE, 64 },  // bubble period var
  1343.    { TYPE_FLOAT, NULL, TRUE, 65 },  // bubble phase
  1344.    { TYPE_FLOAT, NULL, TRUE, 66 },  // bubble phase var
  1345.  
  1346.    { TYPE_INT, NULL, TRUE, 67 },  // Stretch
  1347.    { TYPE_INT, NULL, FALSE, 68 },  // Custom Mtl
  1348.    { TYPE_FLOAT, NULL, FALSE, 69 },  // ViewPort Courseness
  1349.    { TYPE_INT, NULL, FALSE, 70 },  // Subframe rot
  1350.    { TYPE_INT, NULL, FALSE, 71 },  // Spawn Percent
  1351.    { TYPE_FLOAT, NULL, FALSE, 72 },  // Spawn Mult var
  1352. };
  1353.  
  1354. static ParamBlockDescID spdescVer4[] = {
  1355.    { TYPE_FLOAT, NULL, TRUE, 0 },    // off axis
  1356.    { TYPE_FLOAT, NULL, TRUE, 1 },    // axis apread
  1357.    { TYPE_FLOAT, NULL, TRUE, 2 },    // off plane
  1358.    { TYPE_FLOAT, NULL, TRUE, 3 },    // plane spread
  1359.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  1360.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  1361.  
  1362.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  1363.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  1364.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  1365.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  1366.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  1367.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  1368.    { TYPE_INT, NULL, TRUE, 12 },  // life
  1369.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  1370.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  1371.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  1372.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  1373.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  1374.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  1375.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  1376.    { TYPE_INT, NULL, FALSE, 20 }, // rnd seed
  1377.    { TYPE_FLOAT, NULL, FALSE, 21 },  // emitter width
  1378.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  1379.  
  1380.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  1381.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  1382.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  1383.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  1384.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  1385.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  1386.     { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  1387.     { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  1388.     { TYPE_INT, NULL, FALSE, 31 }, // offset amount
  1389.  
  1390.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  1391.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  1392.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  1393.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  1394.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  1395.  
  1396.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  1397.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  1398.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  1399.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  1400.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choice
  1401.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  1402.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  1403.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  1404.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  1405.  
  1406.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  1407.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  1408.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  1409.  
  1410.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  1411.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  1412.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  1413.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  1414.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  1415.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  1416.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  1417.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  1418.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  1419.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  1420.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  1421.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  1422.  
  1423.    { TYPE_FLOAT, NULL, TRUE, 61 },  // bubble amp61
  1424.    { TYPE_FLOAT, NULL, TRUE, 62 },  // bubble amp var
  1425.    { TYPE_INT, NULL, TRUE, 63 },  // bubble period
  1426.    { TYPE_FLOAT, NULL, TRUE, 64 },  // bubble period var
  1427.    { TYPE_FLOAT, NULL, TRUE, 65 },  // bubble phase
  1428.    { TYPE_FLOAT, NULL, TRUE, 66 },  // bubble phase var
  1429.  
  1430.    { TYPE_INT, NULL, TRUE, 67 },  // Stretch
  1431.    { TYPE_INT, NULL, FALSE, 68 },  // Custom Mtl
  1432.    { TYPE_FLOAT, NULL, FALSE, 69 },  // ViewPort Courseness
  1433.    { TYPE_INT, NULL, FALSE, 70 },  // Subframe rot
  1434.    { TYPE_INT, NULL, FALSE, 71 },  // Spawn Percent
  1435.    { TYPE_FLOAT, NULL, FALSE, 72 },  // Spawn Mult var
  1436.    { TYPE_INT, NULL, FALSE, 73 },  // Surface Tracking
  1437. };
  1438.  
  1439. static ParamBlockDescID spdescVer5[] = {
  1440.    { TYPE_FLOAT, NULL, TRUE, 0 },    // off axis
  1441.    { TYPE_FLOAT, NULL, TRUE, 1 },    // axis apread
  1442.    { TYPE_FLOAT, NULL, TRUE, 2 },    // off plane
  1443.    { TYPE_FLOAT, NULL, TRUE, 3 },    // plane spread
  1444.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  1445.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  1446.  
  1447.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  1448.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  1449.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  1450.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  1451.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  1452.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  1453.    { TYPE_INT, NULL, TRUE, 12 },  // life
  1454.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  1455.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  1456.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  1457.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  1458.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  1459.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  1460.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  1461.    { TYPE_INT, NULL, FALSE, 20 }, // rnd seed
  1462.    { TYPE_FLOAT, NULL, FALSE, 21 },  // emitter width
  1463.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  1464.  
  1465.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  1466.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  1467.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  1468.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  1469.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  1470.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  1471.     { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  1472.     { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  1473.     { TYPE_INT, NULL, FALSE, 31 }, // offset amount
  1474.  
  1475.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  1476.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  1477.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  1478.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  1479.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  1480.  
  1481.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  1482.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  1483.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  1484.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  1485.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choice
  1486.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  1487.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  1488.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  1489.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  1490.  
  1491.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  1492.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  1493.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  1494.  
  1495.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  1496.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  1497.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  1498.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  1499.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  1500.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  1501.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  1502.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  1503.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  1504.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  1505.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  1506.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  1507.  
  1508.    { TYPE_FLOAT, NULL, TRUE, 61 },  // bubble amp61
  1509.    { TYPE_FLOAT, NULL, TRUE, 62 },  // bubble amp var
  1510.    { TYPE_INT, NULL, TRUE, 63 },  // bubble period
  1511.    { TYPE_FLOAT, NULL, TRUE, 64 },  // bubble period var
  1512.    { TYPE_FLOAT, NULL, TRUE, 65 },  // bubble phase
  1513.    { TYPE_FLOAT, NULL, TRUE, 66 },  // bubble phase var
  1514.  
  1515.    { TYPE_INT, NULL, TRUE, 67 },  // Stretch
  1516.    { TYPE_INT, NULL, FALSE, 68 },  // Custom Mtl
  1517.    { TYPE_FLOAT, NULL, FALSE, 69 },  // ViewPort Courseness
  1518.    { TYPE_INT, NULL, FALSE, 70 },  // Subframe rot
  1519.    { TYPE_INT, NULL, FALSE, 71 },  // Spawn Percent
  1520.    { TYPE_FLOAT, NULL, FALSE, 72 },  // Spawn Mult var
  1521.    { TYPE_INT, NULL, FALSE, 73 },  // Surface Tracking
  1522.    { TYPE_INT, NULL, TRUE, 74 },  // dies after X
  1523.    { TYPE_FLOAT, NULL, TRUE, 75 },  // dies after X var
  1524. };
  1525.  
  1526. static ParamBlockDescID spdescVer6[] = {
  1527.    { TYPE_FLOAT, NULL, TRUE, 0 },    // off axis
  1528.    { TYPE_FLOAT, NULL, TRUE, 1 },    // axis apread
  1529.    { TYPE_FLOAT, NULL, TRUE, 2 },    // off plane
  1530.    { TYPE_FLOAT, NULL, TRUE, 3 },    // plane spread
  1531.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  1532.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  1533.  
  1534.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  1535.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  1536.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  1537.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  1538.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  1539.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  1540.    { TYPE_INT, NULL, TRUE, 12 },  // life
  1541.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  1542.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  1543.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  1544.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  1545.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  1546.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  1547.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  1548.    { TYPE_INT, NULL, FALSE, 20 }, // rnd seed
  1549.    { TYPE_FLOAT, NULL, FALSE, 21 },  // emitter width
  1550.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  1551.  
  1552.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  1553.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  1554.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  1555.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  1556.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  1557.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  1558.     { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  1559.     { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  1560.     { TYPE_INT, NULL, FALSE, 31 }, // offset amount
  1561.  
  1562.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  1563.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  1564.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  1565.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  1566.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  1567.  
  1568.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  1569.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  1570.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  1571.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  1572.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choice
  1573.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  1574.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  1575.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  1576.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  1577.  
  1578.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  1579.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  1580.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  1581.  
  1582.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  1583.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  1584.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  1585.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  1586.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  1587.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  1588.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  1589.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  1590.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  1591.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  1592.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  1593.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  1594.  
  1595.    { TYPE_FLOAT, NULL, TRUE, 61 },  // bubble amp61
  1596.    { TYPE_FLOAT, NULL, TRUE, 62 },  // bubble amp var
  1597.    { TYPE_INT, NULL, TRUE, 63 },  // bubble period
  1598.    { TYPE_FLOAT, NULL, TRUE, 64 },  // bubble period var
  1599.    { TYPE_FLOAT, NULL, TRUE, 65 },  // bubble phase
  1600.    { TYPE_FLOAT, NULL, TRUE, 66 },  // bubble phase var
  1601.  
  1602.    { TYPE_INT, NULL, TRUE, 67 },  // Stretch
  1603.    { TYPE_INT, NULL, FALSE, 68 },  // Custom Mtl
  1604.    { TYPE_FLOAT, NULL, FALSE, 69 },  // ViewPort Courseness
  1605.    { TYPE_INT, NULL, FALSE, 70 },  // Subframe rot
  1606.    { TYPE_INT, NULL, FALSE, 71 },  // Spawn Percent
  1607.    { TYPE_FLOAT, NULL, FALSE, 72 },  // Spawn Mult var
  1608.    { TYPE_INT, NULL, FALSE, 73 },  // Surface Tracking
  1609.    { TYPE_INT, NULL, TRUE, 74 },  // dies after X
  1610.    { TYPE_FLOAT, NULL, TRUE, 75 },  // dies after X var
  1611.  
  1612.    { TYPE_INT, NULL, FALSE, 76 },  // IPC Enable
  1613.    { TYPE_INT, NULL, FALSE, 77 },  // IPC Steps
  1614.    { TYPE_FLOAT, NULL, TRUE, 78 },  // IPC Bounce
  1615.    { TYPE_FLOAT, NULL, TRUE, 79 },  // IPC Bounce Var
  1616. };
  1617.  
  1618. #define PBLOCK_LENGTH_SUPRSPRAY 80
  1619.  
  1620. static ParamVersionDesc spversions[] = {
  1621.    ParamVersionDesc(spdescVer0,69,0),
  1622.    ParamVersionDesc(spdescVer1,70,1),
  1623.    ParamVersionDesc(spdescVer2,71,2),
  1624.    ParamVersionDesc(spdescVer3,73,3),
  1625.    ParamVersionDesc(spdescVer4,74,4),
  1626.    ParamVersionDesc(spdescVer5,76,5),
  1627.    };
  1628. #define NUM_OLDVERSIONS 6
  1629.  
  1630. // Current version
  1631. #define CURRENT_VERSION 6
  1632.  
  1633. #define PB_TUMBLE             0
  1634. #define PB_TUMBLERATE            1
  1635. #define PB_EMITMAP               2
  1636. #define PB_EMITRLENGTH           3
  1637. #define PB_CUSTOMMTL2            61
  1638. #define PB_METACOURSEVB          62
  1639. #define PB_SUBFRAMEROT2          63
  1640. #define PB_SPAWNPERCENT2         64
  1641. #define PB_SPAWNMULTVAR2         65
  1642. #define PB_BLNOTDRAFT            66
  1643. #define PB_BLSPAWNDIEAFTER       67
  1644. #define PB_BLSPAWNDIEAFTERVAR    68
  1645. #define PB_BLIPCOLLIDE_ON        69
  1646. #define PB_BLIPCOLLIDE_STEPS     70
  1647. #define PB_BLIPCOLLIDE_BOUNCE    71
  1648. #define PB_BLIPCOLLIDE_BOUNCEVAR 72
  1649.  
  1650. static int bmappingIDs[] = {IDC_SP_MAPTIME,IDC_SP_MAPDIST,IDC_SP_MAPPLANAR};
  1651.  
  1652. // Spin Dialog for Blizzard
  1653. static ParamUIDesc descBParamPSpin[] = {
  1654.  
  1655.    // Spin Time
  1656.    ParamUIDesc(
  1657.       PB_SPINTIME,
  1658.       EDITTYPE_TIME,
  1659.       IDC_SP_SPIN,IDC_SP_SPINSPIN,
  1660.       0.0f,999999999.0f,
  1661.       10.0f),
  1662.  
  1663.    // Spin Time Var
  1664.    ParamUIDesc(
  1665.       PB_SPINTIMEVAR,
  1666.       EDITTYPE_FLOAT,
  1667.       IDC_SP_SPINVAR,IDC_SP_SPINVARSPIN,
  1668.       0.0f,100.0f,
  1669.       0.01f,
  1670.       stdPercentDim),
  1671.  
  1672.    // Spin Phase
  1673.    ParamUIDesc(
  1674.       PB_SPINPHASE,
  1675.       EDITTYPE_FLOAT,
  1676.       IDC_SP_SPINPHA,IDC_SP_SPINPHASPIN,
  1677.       -360.0f,360.0f,
  1678.       0.01f,
  1679.       stdAngleDim),
  1680.  
  1681.    // Spin Phase Variation
  1682.    ParamUIDesc(
  1683.       PB_SPINPHASEVAR,
  1684.       EDITTYPE_FLOAT,
  1685.       IDC_SP_SPINPHAVAR,IDC_SP_SPINPHAVARSPIN,
  1686.       0.0f,100.0f,
  1687.       0.01f,
  1688.       stdPercentDim),
  1689.  
  1690.    // Enter Axis Control
  1691.    ParamUIDesc(PB_SPINAXISTYPE,TYPE_RADIO,bspindirectionIDs,2),
  1692.  
  1693.    // X-Axis
  1694.    ParamUIDesc(
  1695.       PB_SPINAXISX,
  1696.       EDITTYPE_FLOAT,
  1697.       IDC_SP_SPINAXISX,IDC_SP_SPINAXISXSPIN,
  1698.       -999999999.0f,999999999.0f,
  1699.       SPIN_AUTOSCALE),
  1700.  
  1701.    // Y-Axis
  1702.    ParamUIDesc(
  1703.       PB_SPINAXISY,
  1704.       EDITTYPE_FLOAT,
  1705.       IDC_SP_SPINAXISY,IDC_SP_SPINAXISYSPIN,
  1706.       -999999999.0f,999999999.0f,
  1707.       SPIN_AUTOSCALE),
  1708.  
  1709.    // Z-Axis
  1710.    ParamUIDesc(
  1711.       PB_SPINAXISZ,
  1712.       EDITTYPE_FLOAT,
  1713.       IDC_SP_SPINAXISZ,IDC_SP_SPINAXISZSPIN,
  1714.       -999999999.0f,999999999.0f,
  1715.       SPIN_AUTOSCALE),
  1716.  
  1717.    // Spin Direction Variation
  1718.    ParamUIDesc(
  1719.       PB_SPINAXISVAR,
  1720.       EDITTYPE_FLOAT,
  1721.       IDC_SP_SPINAXISVAR,IDC_SP_SPINAXISVARSPIN,
  1722.       -180.0f,180.0f,
  1723.       0.01f,
  1724.       stdAngleDim),
  1725.  
  1726.    // IPC Enable
  1727.    ParamUIDesc(PB_BLIPCOLLIDE_ON,TYPE_SINGLECHEKBOX,IDC_INTERP_BOUNCEON),
  1728.  
  1729.    // IPC Steps
  1730.    ParamUIDesc(
  1731.       PB_BLIPCOLLIDE_STEPS,
  1732.       EDITTYPE_INT,
  1733.       IDC_INTERP_NSTEPS,IDC_INTERP_NSTEPSSPIN,
  1734.       1.0f,1000.0f,
  1735.       1.0f),
  1736.  
  1737.    // IPC Bounce
  1738.    ParamUIDesc(
  1739.       PB_BLIPCOLLIDE_BOUNCE,
  1740.       EDITTYPE_FLOAT,
  1741.       IDC_INTERP_BOUNCE,IDC_INTERP_BOUNCESPIN,
  1742.       0.0f,10000.0f,
  1743.       1.0f,
  1744.       stdPercentDim),
  1745.  
  1746.    // IPC Bounce
  1747.    ParamUIDesc(
  1748.       PB_BLIPCOLLIDE_BOUNCEVAR,
  1749.       EDITTYPE_FLOAT,
  1750.       IDC_INTERP_BOUNCEVAR,IDC_INTERP_BOUNCEVARSPIN,
  1751.       0.0f,100.0f,
  1752.       1.0f,
  1753.       stdPercentDim),
  1754. };
  1755.  
  1756. #define BPARAMPSPIN_LENGTH 13
  1757.  
  1758. static ParamUIDesc BdescParamPType[] = {
  1759.  
  1760.    // Particle Class
  1761.    ParamUIDesc(PB_PARTICLECLASS,TYPE_RADIO,particleclassIDs,3),
  1762.  
  1763.    // Particle Type
  1764.    ParamUIDesc(PB_PARTICLETYPE,TYPE_RADIO,particletypeIDs,8),
  1765.  
  1766.    // Metaball Tension
  1767.    ParamUIDesc(
  1768.       PB_METATENSION,
  1769.       EDITTYPE_UNIVERSE,
  1770.       IDC_SP_METTENS,IDC_SP_METTENSSPIN,
  1771.       0.1f,10.0f,
  1772.       SPIN_AUTOSCALE),
  1773.  
  1774.    // Metaball Tension Variation
  1775.    ParamUIDesc(
  1776.       PB_METATENSIONVAR,
  1777.       EDITTYPE_FLOAT,
  1778.       IDC_SP_METTENSVAR,IDC_SP_METTENSVARSPIN,
  1779.       0.0f,100.0f,
  1780.       SPIN_AUTOSCALE,stdPercentDim),
  1781.  
  1782.    // Metaball Courseness
  1783.    ParamUIDesc(
  1784.       PB_METACOURSE,
  1785.       EDITTYPE_UNIVERSE,
  1786.       IDC_SP_METCOURSE,IDC_SP_METCOURSESPIN,
  1787.       0.0f,999999999.0f,
  1788.       SPIN_AUTOSCALE),
  1789.  
  1790.    // Metaball Courseness ViewPort
  1791.    ParamUIDesc(
  1792.       PB_METACOURSEVB,
  1793.       EDITTYPE_UNIVERSE,
  1794.       IDC_SP_METCOURSEV,IDC_SP_METCOURSEVSPIN,
  1795.       0.0f,999999999.0f,
  1796.       SPIN_AUTOSCALE),
  1797.  
  1798.    // Metaball Auto Coarseness
  1799.    ParamUIDesc(PB_METAAUTOCOARSE,TYPE_SINGLECHEKBOX,IDC_SP_AUTOCOARSE),
  1800.      
  1801.    // Display type
  1802.    ParamUIDesc(PB_BLNOTDRAFT,TYPE_SINGLECHEKBOX,IDC_SP_DRAFTMODE),
  1803.  
  1804.    // Use Subtree Checkbox
  1805.    ParamUIDesc(PB_USESUBTREE,TYPE_SINGLECHEKBOX,IDC_AP_USESUBTREE),
  1806.  
  1807.    // Display type
  1808.    ParamUIDesc(PB_ANIMATIONOFFSET,TYPE_RADIO,animateoffsetIDs,3),
  1809.  
  1810.    // Animation Offset Amount
  1811.    ParamUIDesc(
  1812.       PB_OFFSETAMOUNT,
  1813.       EDITTYPE_TIME,
  1814.       IDC_AP_ANIRNDFR,IDC_AP_ANIRNDFRSPIN,
  1815.       1.0f,999999999.0f,
  1816.       10.0f),
  1817.  
  1818.    // Mapping Across
  1819.    ParamUIDesc(PB_MAPPINGTYPE,TYPE_RADIO,bmappingIDs,3),
  1820.  
  1821.    // Time Mapping Option
  1822.    ParamUIDesc(
  1823.       PB_MAPPINGTIME,
  1824.       EDITTYPE_TIME,
  1825.       IDC_SP_MAPTIMEVAL,IDC_SP_MAPTIMEVALSPIN,
  1826.       1.0f,999999999.0f,
  1827.       10.0f),
  1828.  
  1829.    // Distance Mapping Option
  1830.    ParamUIDesc(
  1831.       PB_MAPPINGDIST,
  1832.       EDITTYPE_UNIVERSE,
  1833.       IDC_SP_MAPDISTVAL,IDC_SP_MAPDISTVALSPIN,
  1834.       0.1f,999999999.0f,
  1835.       SPIN_AUTOSCALE),
  1836.  
  1837.    // Use Custom Mtl
  1838.    ParamUIDesc(PB_CUSTOMMTL2,TYPE_RADIO,custmtlIDs,2),
  1839. };
  1840. #define BPARAMPTYPE_LENGTH 15
  1841.  
  1842. // Dialog Unique to Particle Array
  1843. static ParamUIDesc BdescParam[] = {
  1844.  
  1845.    // Emitter Width
  1846.    ParamUIDesc(
  1847.       PB_EMITRWID,
  1848.       EDITTYPE_UNIVERSE,
  1849.       IDC_SP_EMITWID,IDC_SP_EMITWIDSPIN,
  1850.       0.0f,999999999.0f,
  1851.       SPIN_AUTOSCALE),  
  1852.  
  1853.    // Emitter Length
  1854.    ParamUIDesc(
  1855.       PB_EMITRLENGTH,
  1856.       EDITTYPE_UNIVERSE,
  1857.       IDC_SP_EMITLEN,IDC_SP_EMITLENSPIN,
  1858.       0.0f,999999999.0f,
  1859.       SPIN_AUTOSCALE),  
  1860.  
  1861.    // Hide Emitter
  1862.    ParamUIDesc(PB_EMITRHID,TYPE_SINGLECHEKBOX,IDC_SP_EMITHID),
  1863.  
  1864.    // Animation Offset Type
  1865.    ParamUIDesc(PB_VIEWPORTSHOWS,TYPE_RADIO,viewportoptionIDs,4),
  1866.  
  1867.    // Particle Display Portion
  1868.    ParamUIDesc(
  1869.       PB_DISPLAYPORTION,
  1870.       EDITTYPE_FLOAT,
  1871.       IDC_SP_GENDISP,IDC_SP_GENDISPSPIN,
  1872.       0.0f,100.0f,
  1873.       0.1f,
  1874.       stdPercentDim),
  1875. };
  1876. #define PARAMBLIZZARD_LENGTH 5
  1877.  
  1878. // Common Dialog for Particle Generation
  1879. static ParamUIDesc BdescParamPGen[] = {
  1880.  
  1881.    // Distribution Method
  1882.    ParamUIDesc(PB_BIRTHMETHOD,TYPE_RADIO,countIDs,2),
  1883.  
  1884.    // Particle Birth Rate
  1885.    ParamUIDesc(
  1886.       PB_PBIRTHRATE,
  1887.       EDITTYPE_INT,
  1888.       IDC_SP_GENRATE,IDC_SP_GENRATESPIN,
  1889.       0.0f,65000.0f,
  1890.       1.0f),
  1891.  
  1892.    // Particle Total Count
  1893.    ParamUIDesc(
  1894.       PB_PTOTALNUMBER,
  1895.       EDITTYPE_INT,
  1896.       IDC_SP_GENTTL,IDC_SP_GENTTLSPIN,
  1897.       0.0f,65000.0f,
  1898.       1.0f),
  1899.  
  1900.    // Particle Speed
  1901.    ParamUIDesc(
  1902.       PB_SPEED,
  1903.       EDITTYPE_UNIVERSE,
  1904.       IDC_SP_BLIZSPEED,IDC_SP_BLIZSPEEDSPIN,
  1905.       0.0f,999999999.0f,
  1906.       SPIN_AUTOSCALE),
  1907.  
  1908.    // Particle Speed Var
  1909.    ParamUIDesc(
  1910.       PB_SPEEDVAR,
  1911.       EDITTYPE_FLOAT,
  1912.       IDC_SP_BLIZSPEEDVAR,IDC_SP_BLIZSPEEDVARSPIN,
  1913.       0.0f,100.0f,
  1914.       SPIN_AUTOSCALE,stdPercentDim),
  1915.  
  1916.    // Particle Tumble
  1917.    ParamUIDesc(
  1918.       PB_TUMBLE,
  1919.       EDITTYPE_FLOAT,
  1920.       IDC_SP_BLIZTUMBL,IDC_SP_BLIZTUMBLSPIN,
  1921.       0.0f,1.0f,
  1922.       0.005f),
  1923.  
  1924.    // Particle Tumble Rate
  1925.    ParamUIDesc(
  1926.       PB_TUMBLERATE,
  1927.       EDITTYPE_FLOAT,
  1928.       IDC_SP_BLIZTUMBLRATE,IDC_SP_BLIZTUMBLRATESPIN,
  1929.       0.0f,999999999.0f,
  1930.       0.01f),
  1931.  
  1932.    // Emitter Start Time
  1933.    ParamUIDesc(
  1934.       PB_EMITSTART,
  1935.       EDITTYPE_TIME,
  1936.       IDC_SP_GENEMIT1,IDC_SP_GENEMIT1SPIN,
  1937.       -999999999.0f,999999999.0f,
  1938.       10.0f),
  1939.  
  1940.    // Emitter Stop Time
  1941.    ParamUIDesc(
  1942.       PB_EMITSTOP,
  1943.       EDITTYPE_TIME,
  1944.       IDC_SP_GENEMIT2,IDC_SP_GENEMIT2SPIN,
  1945.       -999999999.0f,999999999.0f,
  1946.       10.0f),
  1947.  
  1948.    // Particle Time Limit
  1949.    ParamUIDesc(
  1950.       PB_DISPUNTIL,
  1951.       EDITTYPE_TIME,
  1952.       IDC_SP_DISPUNTIL,IDC_SP_DISPUNTILSPIN,
  1953.       -999999999.0f,999999999.0f,
  1954.       10.0f),
  1955.  
  1956.    // Particle Life
  1957.    ParamUIDesc(
  1958.       PB_LIFE,
  1959.       EDITTYPE_TIME,
  1960.       IDC_SP_GENLIFE,IDC_SP_GENLIFESPIN,
  1961.       0.0f,999999999.0f,
  1962.       10.0f),
  1963.  
  1964.    // Particle Life Var
  1965.    ParamUIDesc(
  1966.       PB_LIFEVAR,
  1967.       EDITTYPE_TIME,
  1968.       IDC_SP_GENLIFEVAR,IDC_SP_GENLIFEVARSPIN,
  1969.       0.0f,999999999.0f,
  1970.       10.0f),
  1971.  
  1972.    // Subframe Time and Motion Sampling
  1973.    ParamUIDesc(PB_SUBFRAMEMOVE,TYPE_SINGLECHEKBOX,IDC_SP_GENSMPLMOVE),
  1974.    ParamUIDesc(PB_SUBFRAMETIME,TYPE_SINGLECHEKBOX,IDC_SP_GENSMPLTIME),
  1975.    ParamUIDesc(PB_SUBFRAMEROT2,TYPE_SINGLECHEKBOX,IDC_SP_GENSMPLROT),
  1976.  
  1977.    // Particle Size
  1978.    ParamUIDesc(
  1979.       PB_SIZE,
  1980.       EDITTYPE_UNIVERSE,
  1981.       IDC_SP_GENSIZE,IDC_SP_GENSIZESPIN,
  1982.       0.0f,999999999.0f,
  1983.       SPIN_AUTOSCALE),
  1984.  
  1985.    // Particle Size Var
  1986.    ParamUIDesc(
  1987.       PB_SIZEVAR,
  1988.       EDITTYPE_FLOAT,
  1989.       IDC_SP_GENSIZEVAR,IDC_SP_GENSIZEVARSPIN,
  1990.       0.0f,100.0f,
  1991.       SPIN_AUTOSCALE,stdPercentDim),
  1992.  
  1993.    // Particle Grow Time
  1994.    ParamUIDesc(
  1995.       PB_GROWTIME,
  1996.       EDITTYPE_TIME,
  1997.       IDC_SP_GENGRO,IDC_SP_GENGROSPIN,
  1998.       0.0f,999999999.0f,
  1999.       10.0f),
  2000.  
  2001.    // Particle Fade Time
  2002.    ParamUIDesc(
  2003.       PB_FADETIME,
  2004.       EDITTYPE_TIME,
  2005.       IDC_SP_GENFAD,IDC_SP_GENFADSPIN,
  2006.       0.0f,999999999.0f,
  2007.       10.0f),
  2008.  
  2009.    // Random Number Seed
  2010.    ParamUIDesc(
  2011.       PB_RNDSEED,
  2012.       EDITTYPE_INT,
  2013.       IDC_SP_GENSEED,IDC_SP_GENSEEDSPIN,
  2014.       0.0f,25000.0f,
  2015.       1.0f),
  2016.    };
  2017.  
  2018. #define BPARAMPGEN_LENGTH 20
  2019.  
  2020. static ParamUIDesc descBPSpawning[] = {
  2021.    
  2022.    // Spawing Effects Type
  2023.    ParamUIDesc(PB_SPAWNTYPE,TYPE_RADIO,SpawnTypeIDs,5),
  2024.  
  2025.    // Die after X
  2026.    ParamUIDesc(
  2027.       PB_BLSPAWNDIEAFTER,
  2028.       EDITTYPE_TIME,
  2029.       IDC_AP_MAXSPAWNDIEAFTER,IDC_AP_MAXSPAWNDIEAFTERSPIN,
  2030.       0.0f,999999999.0f,
  2031.       10.0f),
  2032.  
  2033.    ParamUIDesc(
  2034.       PB_BLSPAWNDIEAFTERVAR,
  2035.       EDITTYPE_FLOAT,
  2036.       IDC_AP_MAXSPAWNDIEAFTERVAR,IDC_AP_MAXSPAWNDIEAFTERVARSPIN,
  2037.       0.0f,100.0f,
  2038.       0.01f,
  2039.       stdPercentDim),
  2040.  
  2041.    // Spawn Generations
  2042.    ParamUIDesc(
  2043.       PB_SPAWNGENS,
  2044.       EDITTYPE_INT,
  2045.       IDC_AP_MAXSPAWNGENS,IDC_AP_MAXSPAWNGENSSPIN,
  2046.       1.0f,65000.0f,
  2047.       1.0f),
  2048.  
  2049.    // Spawn Generations
  2050.    ParamUIDesc(
  2051.       PB_SPAWNPERCENT2,
  2052.       EDITTYPE_INT,
  2053.       IDC_AP_PARENTPERCENT,IDC_AP_PARENTPERCENTSPIN,
  2054.       1.0f,100.0f,
  2055.       1.0f),
  2056.  
  2057.    // Spawn Spawncount
  2058.    ParamUIDesc(
  2059.       PB_SPAWNCOUNT,
  2060.       EDITTYPE_INT,
  2061.       IDC_AP_NUMBERVAR,IDC_AP_NUMBERVARSPIN,
  2062.       1.0f,65000.0f,
  2063.       1.0f),
  2064.  
  2065.    // Spawn Mult Percent
  2066.    ParamUIDesc(
  2067.       PB_SPAWNMULTVAR2,
  2068.       EDITTYPE_FLOAT,
  2069.       IDC_AP_NUMBERVARVAR,IDC_AP_NUMBERVARVARSPIN,
  2070.       0.0f,100.0f,
  2071.       0.1f,stdPercentDim),
  2072.  
  2073.    // Spawn Direction Chaos
  2074.    ParamUIDesc(
  2075.       PB_SPAWNDIRCHAOS,
  2076.       EDITTYPE_FLOAT,
  2077.       IDC_AP_CHAOSANGLE,IDC_AP_CHAOSANGLESPIN,
  2078.       0.0f,100.0f,
  2079.       0.1f,stdPercentDim),
  2080.  
  2081.    // Spawn Speed Chaos
  2082.    ParamUIDesc(
  2083.       PB_SPAWNSPEEDCHAOS,
  2084.       EDITTYPE_FLOAT,
  2085.       IDC_AP_CHAOSSPEED,IDC_AP_CHAOSSPEEDSPIN,
  2086.       0.0f,100.0f,
  2087.       0.1f),
  2088.  
  2089.    // Spawing Speed Sign
  2090.    ParamUIDesc(PB_SPAWNSPEEDSIGN,TYPE_RADIO,SpeedChaosIDs,3),
  2091.  
  2092.    // Spawning Inherit Parent V
  2093.    ParamUIDesc(PB_SPAWNINHERITV,TYPE_SINGLECHEKBOX,IDC_AP_SPAWNSUMV),
  2094.  
  2095.    // Spawning Speed Fixed
  2096.    ParamUIDesc(PB_SPAWNSPEEDFIXED,TYPE_SINGLECHEKBOX,IDC_AP_SPAWNSPEEDFIXED),
  2097.  
  2098.    // Spawn Scale Chaos
  2099.    ParamUIDesc(
  2100.       PB_SPAWNSCALECHAOS,
  2101.       EDITTYPE_FLOAT,
  2102.       IDC_AP_CHAOSSCALE,IDC_AP_CHAOSSCALESPIN,
  2103.       0.0f,100.0f,
  2104.       0.1f),
  2105.  
  2106.    // Spawning Scale Sign
  2107.    ParamUIDesc(PB_SPAWNSCALESIGN,TYPE_RADIO,ScaleChaosIDs,3),
  2108.  
  2109.    // Spawning Speed Fixed
  2110.    ParamUIDesc(PB_SPAWNSCALEFIXED,TYPE_SINGLECHEKBOX,IDC_AP_SPAWNSCALEFIXED),
  2111.  
  2112.    // Spawn Lifespan Entry Field
  2113.    ParamUIDesc(
  2114.       PB_SPAWNLIFEVLUE,
  2115.       EDITTYPE_INT,
  2116.       IDC_AP_QUEUELIFESPAN,IDC_AP_QUEUELIFESPANSPIN,
  2117.       0.0f,65000.0f,
  2118.       0.1f),
  2119. };
  2120.  
  2121. #define PBSPAWNINGPARAMS_LENGTH 16
  2122.  
  2123. // Particle Type for Blizzard
  2124.  
  2125. static ParamBlockDescID BdescVer0[] = {
  2126.    { TYPE_FLOAT, NULL, TRUE, 0 },    // tumble
  2127.    { TYPE_FLOAT, NULL, TRUE, 1 },    // tumblerate
  2128.    { TYPE_FLOAT, NULL, FALSE, 2 },   // emit map
  2129.    { TYPE_FLOAT, NULL, TRUE, 3 },    // emitter length
  2130.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  2131.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  2132.  
  2133.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  2134.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  2135.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  2136.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  2137.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  2138.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  2139.    { TYPE_INT, NULL, TRUE, 12 },  // life
  2140.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  2141.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  2142.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  2143.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  2144.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  2145.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  2146.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  2147.    { TYPE_INT, NULL, FALSE, 20 },    // rnd seed
  2148.    { TYPE_FLOAT, NULL, TRUE, 21 },  // emitter width
  2149.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  2150.  
  2151.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  2152.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  2153.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  2154.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  2155.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  2156.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  2157.    { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  2158.    { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  2159.    { TYPE_INT, NULL, FALSE, 31 }, // animation offset time
  2160.  
  2161.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  2162.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  2163.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  2164.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  2165.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  2166.  
  2167.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  2168.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  2169.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  2170.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  2171.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choose
  2172.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  2173.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  2174.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  2175.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  2176.  
  2177.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  2178.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  2179.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  2180.  
  2181.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  2182.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  2183.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  2184.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  2185.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  2186.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  2187.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  2188.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  2189.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  2190.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  2191.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  2192.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  2193.  
  2194.    { TYPE_INT, NULL, FALSE, 61 },  // custmlt
  2195. };
  2196.  
  2197. static ParamBlockDescID BdescVer1[] = {
  2198.    { TYPE_FLOAT, NULL, TRUE, 0 },    // tumble
  2199.    { TYPE_FLOAT, NULL, TRUE, 1 },    // tumblerate
  2200.    { TYPE_FLOAT, NULL, FALSE, 2 },   // emit map
  2201.    { TYPE_FLOAT, NULL, TRUE, 3 },    // emitter length
  2202.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  2203.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  2204.  
  2205.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  2206.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  2207.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  2208.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  2209.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  2210.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  2211.    { TYPE_INT, NULL, TRUE, 12 },  // life
  2212.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  2213.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  2214.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  2215.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  2216.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  2217.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  2218.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  2219.    { TYPE_INT, NULL, FALSE, 20 },    // rnd seed
  2220.    { TYPE_FLOAT, NULL, TRUE, 21 },  // emitter width
  2221.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  2222.  
  2223.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  2224.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  2225.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  2226.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  2227.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  2228.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  2229.    { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  2230.    { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  2231.    { TYPE_INT, NULL, FALSE, 31 }, // animation offset time
  2232.  
  2233.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  2234.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  2235.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  2236.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  2237.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  2238.  
  2239.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  2240.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  2241.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  2242.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  2243.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choose
  2244.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  2245.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  2246.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  2247.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  2248.  
  2249.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  2250.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  2251.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  2252.  
  2253.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  2254.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  2255.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  2256.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  2257.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  2258.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  2259.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  2260.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  2261.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  2262.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  2263.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  2264.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  2265.  
  2266.    { TYPE_INT, NULL, FALSE, 61 },  // custmlt
  2267.    { TYPE_FLOAT, NULL, FALSE, 62 }, // meta course Viewport
  2268. };
  2269. static ParamBlockDescID BdescVer2[] = {
  2270.    { TYPE_FLOAT, NULL, TRUE, 0 },    // tumble
  2271.    { TYPE_FLOAT, NULL, TRUE, 1 },    // tumblerate
  2272.    { TYPE_FLOAT, NULL, FALSE, 2 },   // emit map
  2273.    { TYPE_FLOAT, NULL, TRUE, 3 },    // emitter length
  2274.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  2275.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  2276.  
  2277.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  2278.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  2279.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  2280.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  2281.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  2282.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  2283.    { TYPE_INT, NULL, TRUE, 12 },  // life
  2284.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  2285.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  2286.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  2287.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  2288.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  2289.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  2290.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  2291.    { TYPE_INT, NULL, FALSE, 20 },    // rnd seed
  2292.    { TYPE_FLOAT, NULL, TRUE, 21 },  // emitter width
  2293.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  2294.  
  2295.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  2296.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  2297.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  2298.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  2299.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  2300.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  2301.    { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  2302.    { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  2303.    { TYPE_INT, NULL, FALSE, 31 }, // animation offset time
  2304.  
  2305.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  2306.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  2307.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  2308.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  2309.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  2310.  
  2311.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  2312.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  2313.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  2314.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  2315.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choose
  2316.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  2317.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  2318.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  2319.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  2320.  
  2321.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  2322.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  2323.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  2324.  
  2325.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  2326.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  2327.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  2328.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  2329.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  2330.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  2331.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  2332.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  2333.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  2334.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  2335.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  2336.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  2337.  
  2338.    { TYPE_INT, NULL, FALSE, 61 },  // custmlt
  2339.    { TYPE_FLOAT, NULL, FALSE, 62 }, // meta course Viewport
  2340.    { TYPE_INT, NULL, FALSE, 63},  // subframe rot
  2341. };
  2342. static ParamBlockDescID BdescVer3[] = {
  2343.    { TYPE_FLOAT, NULL, TRUE, 0 },    // tumble
  2344.    { TYPE_FLOAT, NULL, TRUE, 1 },    // tumblerate
  2345.    { TYPE_FLOAT, NULL, FALSE, 2 },   // emit map
  2346.    { TYPE_FLOAT, NULL, TRUE, 3 },    // emitter length
  2347.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  2348.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  2349.  
  2350.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  2351.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  2352.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  2353.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  2354.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  2355.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  2356.    { TYPE_INT, NULL, TRUE, 12 },  // life
  2357.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  2358.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  2359.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  2360.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  2361.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  2362.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  2363.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  2364.    { TYPE_INT, NULL, FALSE, 20 },    // rnd seed
  2365.    { TYPE_FLOAT, NULL, TRUE, 21 },  // emitter width
  2366.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  2367.  
  2368.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  2369.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  2370.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  2371.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  2372.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  2373.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  2374.    { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  2375.    { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  2376.    { TYPE_INT, NULL, FALSE, 31 }, // animation offset time
  2377.  
  2378.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  2379.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  2380.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  2381.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  2382.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  2383.  
  2384.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  2385.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  2386.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  2387.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  2388.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choose
  2389.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  2390.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  2391.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  2392.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  2393.  
  2394.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  2395.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  2396.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  2397.  
  2398.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  2399.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  2400.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  2401.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  2402.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  2403.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  2404.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  2405.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  2406.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  2407.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  2408.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  2409.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  2410.  
  2411.    { TYPE_INT, NULL, FALSE, 61 },  // custmlt
  2412.    { TYPE_FLOAT, NULL, FALSE, 62 }, // meta course Viewport
  2413.    { TYPE_INT, NULL, FALSE, 63},  // subframe rot
  2414.    { TYPE_INT, NULL, FALSE, 64 }, // Spawn PErcent
  2415.    { TYPE_FLOAT, NULL, FALSE, 65},  // spawn mult var
  2416. };
  2417. static ParamBlockDescID BdescVer4[] = {
  2418.    { TYPE_FLOAT, NULL, TRUE, 0 },    // tumble
  2419.    { TYPE_FLOAT, NULL, TRUE, 1 },    // tumblerate
  2420.    { TYPE_FLOAT, NULL, FALSE, 2 },   // emit map
  2421.    { TYPE_FLOAT, NULL, TRUE, 3 },    // emitter length
  2422.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  2423.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  2424.  
  2425.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  2426.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  2427.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  2428.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  2429.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  2430.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  2431.    { TYPE_INT, NULL, TRUE, 12 },  // life
  2432.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  2433.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  2434.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  2435.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  2436.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  2437.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  2438.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  2439.    { TYPE_INT, NULL, FALSE, 20 },    // rnd seed
  2440.    { TYPE_FLOAT, NULL, TRUE, 21 },  // emitter width
  2441.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  2442.  
  2443.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  2444.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  2445.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  2446.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  2447.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  2448.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  2449.    { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  2450.    { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  2451.    { TYPE_INT, NULL, FALSE, 31 }, // animation offset time
  2452.  
  2453.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  2454.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  2455.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  2456.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  2457.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  2458.  
  2459.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  2460.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  2461.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  2462.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  2463.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choose
  2464.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  2465.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  2466.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  2467.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  2468.  
  2469.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  2470.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  2471.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  2472.  
  2473.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  2474.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  2475.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  2476.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  2477.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  2478.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  2479.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  2480.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  2481.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  2482.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  2483.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  2484.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  2485.  
  2486.    { TYPE_INT, NULL, FALSE, 61 },  // custmlt
  2487.    { TYPE_FLOAT, NULL, FALSE, 62 }, // meta course Viewport
  2488.    { TYPE_INT, NULL, FALSE, 63},  // subframe rot
  2489.    { TYPE_INT, NULL, FALSE, 64 }, // Spawn PErcent
  2490.    { TYPE_FLOAT, NULL, FALSE, 65},  // spawn mult var
  2491.    { TYPE_INT, NULL, TRUE, 66 }, // Draft
  2492. };
  2493.  
  2494. static ParamBlockDescID BdescVer5[] = {
  2495.    { TYPE_FLOAT, NULL, TRUE, 0 },    // tumble
  2496.    { TYPE_FLOAT, NULL, TRUE, 1 },    // tumblerate
  2497.    { TYPE_FLOAT, NULL, FALSE, 2 },   // emit map
  2498.    { TYPE_FLOAT, NULL, TRUE, 3 },    // emitter length
  2499.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  2500.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  2501.  
  2502.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  2503.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  2504.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  2505.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  2506.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  2507.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  2508.    { TYPE_INT, NULL, TRUE, 12 },  // life
  2509.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  2510.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  2511.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  2512.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  2513.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  2514.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  2515.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  2516.    { TYPE_INT, NULL, FALSE, 20 },    // rnd seed
  2517.    { TYPE_FLOAT, NULL, TRUE, 21 },  // emitter width
  2518.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  2519.  
  2520.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  2521.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  2522.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  2523.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  2524.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  2525.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  2526.    { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  2527.    { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  2528.    { TYPE_INT, NULL, FALSE, 31 }, // animation offset time
  2529.  
  2530.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  2531.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  2532.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  2533.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  2534.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  2535.  
  2536.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  2537.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  2538.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  2539.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  2540.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choose
  2541.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  2542.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  2543.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  2544.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  2545.  
  2546.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  2547.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  2548.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  2549.  
  2550.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  2551.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  2552.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  2553.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  2554.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  2555.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  2556.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  2557.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  2558.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  2559.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  2560.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  2561.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  2562.  
  2563.    { TYPE_INT, NULL, FALSE, 61 },  // custmlt
  2564.    { TYPE_FLOAT, NULL, FALSE, 62 }, // meta course Viewport
  2565.    { TYPE_INT, NULL, FALSE, 63},  // subframe rot
  2566.    { TYPE_INT, NULL, FALSE, 64 }, // Spawn PErcent
  2567.    { TYPE_FLOAT, NULL, FALSE, 65},  // spawn mult var
  2568.    { TYPE_INT, NULL, TRUE, 66 }, // Draft
  2569.    { TYPE_INT, NULL, TRUE, 67 }, // Dies after X
  2570.    { TYPE_FLOAT, NULL, TRUE, 68 }, // Dies after X var
  2571. };
  2572.  
  2573. static ParamBlockDescID BdescVer6[] = {
  2574.    { TYPE_FLOAT, NULL, TRUE, 0 },    // tumble
  2575.    { TYPE_FLOAT, NULL, TRUE, 1 },    // tumblerate
  2576.    { TYPE_FLOAT, NULL, FALSE, 2 },   // emit map
  2577.    { TYPE_FLOAT, NULL, TRUE, 3 },    // emitter length
  2578.    { TYPE_FLOAT, NULL, TRUE, 4 },    // speed
  2579.    { TYPE_FLOAT, NULL, TRUE, 5 },    // speed var
  2580.  
  2581.    { TYPE_INT, NULL, FALSE, 6 },  // Birth method
  2582.    { TYPE_INT, NULL, TRUE, 7 },   // Birth rate
  2583.    { TYPE_INT, NULL, FALSE, 8 },    // total number
  2584.    { TYPE_INT, NULL, FALSE, 9 },  // emit start
  2585.    { TYPE_INT, NULL, FALSE, 10 },   // emit stop
  2586.    { TYPE_INT, NULL, FALSE, 11 },   // display until
  2587.    { TYPE_INT, NULL, TRUE, 12 },  // life
  2588.    { TYPE_INT, NULL, TRUE, 13 },  // life var
  2589.    { TYPE_INT, NULL, FALSE, 14 },    // sub frame move
  2590.    { TYPE_INT, NULL, FALSE, 15 },    // sub frame time
  2591.    { TYPE_FLOAT, NULL, TRUE, 16 },   // size
  2592.    { TYPE_FLOAT, NULL, TRUE, 17 },   // size var
  2593.    { TYPE_INT, NULL, FALSE, 18 },    // grow time
  2594.    { TYPE_INT, NULL, FALSE, 19 },    // fade time
  2595.    { TYPE_INT, NULL, FALSE, 20 },    // rnd seed
  2596.    { TYPE_FLOAT, NULL, TRUE, 21 },  // emitter width
  2597.    { TYPE_INT, NULL, FALSE, 22 },    // emitter hidden
  2598.  
  2599.    { TYPE_INT, NULL, FALSE, 23 },  // particle class
  2600.    { TYPE_INT, NULL, FALSE, 24 },  // particle type
  2601.    { TYPE_FLOAT, NULL, TRUE, 25 },  // meta tension
  2602.    { TYPE_FLOAT, NULL, TRUE, 26 },  // metatension var
  2603.    { TYPE_FLOAT, NULL, FALSE, 27 }, // meta course
  2604.    { TYPE_INT, NULL, FALSE, 28 }, // auto coarseness
  2605.    { TYPE_INT, NULL, FALSE, 29 }, // use subtree
  2606.    { TYPE_INT, NULL, FALSE, 30 }, // animation offset
  2607.    { TYPE_INT, NULL, FALSE, 31 }, // animation offset time
  2608.  
  2609.    { TYPE_INT, NULL, FALSE, 32 },     // viewport shows
  2610.    { TYPE_FLOAT, NULL, FALSE, 33 }, // display portion
  2611.    { TYPE_INT, NULL, FALSE, 34 },     // mapping type
  2612.    { TYPE_INT, NULL, TRUE, 35 },   // mapping time
  2613.    { TYPE_FLOAT, NULL, TRUE, 36 },    // mapping dist
  2614.  
  2615.    { TYPE_INT, NULL, TRUE, 37 }, // spin time
  2616.    { TYPE_FLOAT, NULL, TRUE, 38 },  // spin time var
  2617.    { TYPE_FLOAT, NULL, TRUE, 39 },  // spin phase
  2618.    { TYPE_FLOAT, NULL, TRUE, 40 },  // spin phase var
  2619.    { TYPE_INT, NULL, FALSE, 41 },  // spin axis choose
  2620.    { TYPE_FLOAT, NULL, TRUE, 42 }, // spin axis x
  2621.    { TYPE_FLOAT, NULL, TRUE, 43 }, // spin axis y
  2622.    { TYPE_FLOAT, NULL, TRUE, 44 }, // spin axis z
  2623.    { TYPE_FLOAT, NULL, TRUE, 45 }, // spin axis var
  2624.  
  2625.    { TYPE_FLOAT, NULL, TRUE, 46 },  // emit influence
  2626.    { TYPE_FLOAT, NULL, TRUE, 47 },  // emit multiplier
  2627.    { TYPE_FLOAT, NULL, TRUE, 48 },  // emit mult var
  2628.  
  2629.    { TYPE_INT, NULL, FALSE, 49 }, // spawn type
  2630.    { TYPE_INT, NULL, FALSE, 50 }, // number of gens
  2631.    { TYPE_INT, NULL, FALSE, 51 }, // number of spawns
  2632.    { TYPE_FLOAT, NULL, TRUE, 52 }, // direction chaos
  2633.    { TYPE_FLOAT, NULL, TRUE, 53 }, // speed chaos
  2634.    { TYPE_INT, NULL, FALSE, 54 }, // speed chaos sign
  2635.    { TYPE_INT, NULL, FALSE, 55 }, // inherit old particle velocity
  2636.    { TYPE_FLOAT, NULL, TRUE, 56 }, // scale chaos
  2637.    { TYPE_INT, NULL, FALSE, 57 }, // scale chaos sign
  2638.    { TYPE_INT, NULL, FALSE, 58 }, // lifespan entry field
  2639.    { TYPE_INT, NULL, FALSE, 59 }, // constant spawn speed
  2640.    { TYPE_INT, NULL, FALSE, 60 }, // constant spawn scale
  2641.  
  2642.    { TYPE_INT, NULL, FALSE, 61 },  // custmlt
  2643.    { TYPE_FLOAT, NULL, FALSE, 62 }, // meta course Viewport
  2644.    { TYPE_INT, NULL, FALSE, 63},  // subframe rot
  2645.    { TYPE_INT, NULL, FALSE, 64 }, // Spawn PErcent
  2646.    { TYPE_FLOAT, NULL, FALSE, 65},  // spawn mult var
  2647.    { TYPE_INT, NULL, TRUE, 66 }, // Draft
  2648.    { TYPE_INT, NULL, TRUE, 67 }, // Dies after X
  2649.    { TYPE_FLOAT, NULL, TRUE, 68 }, // Dies after X var
  2650.  
  2651.    { TYPE_INT, NULL, FALSE, 69 }, // IPC Enable
  2652.    { TYPE_INT, NULL, FALSE, 70 }, // IPC Steps
  2653.    { TYPE_FLOAT, NULL, TRUE, 71 }, // IPC Bounce
  2654.    { TYPE_FLOAT, NULL, TRUE, 72 }, // IPC Bounce Var
  2655. };
  2656.  
  2657. static ParamVersionDesc Bversions[] = {
  2658.    ParamVersionDesc(BdescVer0,62,0),
  2659.    ParamVersionDesc(BdescVer1,63,1),
  2660.    ParamVersionDesc(BdescVer2,64,2),
  2661.    ParamVersionDesc(BdescVer3,66,3),
  2662.    ParamVersionDesc(BdescVer4,67,4),
  2663.    ParamVersionDesc(BdescVer5,69,5),
  2664.    };
  2665. #define PBLOCK_LENGTH_BLIZZARD 73
  2666.  
  2667. static ParamVersionDesc curVersionBL(BdescVer6,PBLOCK_LENGTH_BLIZZARD,CURRENT_VERSION);
  2668. static ParamVersionDesc curVersionSp(spdescVer6,PBLOCK_LENGTH_SUPRSPRAY,CURRENT_VERSION);
  2669.  
  2670. //-- ParticleDlgProc ------------------------------------------------
  2671.  
  2672. class CreateSSBlizProc : public MouseCallBack,ReferenceMaker {
  2673.    private:
  2674.       IObjParam *ip;
  2675.       void Init(IObjParam *i) {ip=i;}
  2676.       CreateMouseCallBack *createCB;  
  2677.       INode *CloudNode;
  2678.       CommonParticle *SSBlizObject;
  2679.       int attachedToNode;
  2680.       IObjCreate *createInterface;
  2681.       ClassDesc *cDesc;
  2682.       Matrix3 mat;  // the nodes TM relative to the CP
  2683.       Point3 p0,p1;
  2684.       IPoint2 sp0, sp1;
  2685.       BOOL square;
  2686.  
  2687.       int ignoreSelectionChange;
  2688.  
  2689.       int lastPutCount;
  2690.       void CreateNewObject();
  2691.  
  2692.       int NumRefs() { return 1; }
  2693.       RefTargetHandle GetReference(int i) { return (RefTargetHandle)CloudNode; }
  2694.       void SetReference(int i, RefTargetHandle rtarg) { CloudNode = (INode *)rtarg; }
  2695.  
  2696.       // StdNotifyRefChanged calls this, which can change the partID to new value
  2697.       // If it doesnt depend on the particular message& partID, it should return
  2698.       // REF_DONTCARE
  2699.       BOOL SupportAutoGrid(){return TRUE;}
  2700.        RefResult NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
  2701.          PartID& partID,  RefMessage message);
  2702.    public:
  2703.       void Begin( IObjCreate *ioc, ClassDesc *desc );
  2704.       void End();
  2705.      
  2706.       CreateSSBlizProc()
  2707.          {
  2708.          ignoreSelectionChange = FALSE;
  2709.          }
  2710. //    int createmethod(ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat);
  2711.       int proc( HWND hwnd, int msg, int point, int flag, IPoint2 m );
  2712.    };
  2713. class ComObjectListRestore : public RestoreObj {
  2714.    public:        
  2715.       CommonParticle *po;
  2716.       Tab<INode*> unodes;
  2717.       Tab<INode*> rnodes;
  2718.       int lnum,lnum2;
  2719.       ComObjectListRestore(CommonParticle *p)
  2720.       {  po=p;
  2721.          unodes=p->nlist;
  2722.       }
  2723.       void Restore(int isUndo)
  2724.       {  if (isUndo) {
  2725.             rnodes = po->nlist;
  2726.             }
  2727.          po->nlist = unodes;
  2728.          po->NotifyDependents(FOREVER,0,REFMSG_CHANGE);
  2729.       }
  2730.       void Redo()
  2731.       {  po->nlist = rnodes;
  2732.          po->NotifyDependents(FOREVER,0,REFMSG_CHANGE);
  2733.       }
  2734.    };
  2735.  
  2736. class LifeListRestore : public RestoreObj {
  2737.    public:        
  2738.       CommonParticle *po;
  2739.       Tab<int> utimes;
  2740.       Tab<int> rtimes;
  2741.       LifeListRestore(CommonParticle *p)
  2742.       { po=p;
  2743.         utimes=p->llist;
  2744.       }
  2745.       void Restore(int isUndo)
  2746.       { if (isUndo) { rtimes = po->llist; }
  2747.         po->llist=utimes;
  2748.         if (po->ip) po->SetUpLifeList();
  2749.       }
  2750.       void Redo()
  2751.       { po->llist = rtimes;
  2752.         if (po->ip) po->SetUpLifeList();
  2753.       }
  2754.    };
  2755.  
  2756. class CreateCPartPickNode : public RestoreObj {
  2757.    public:        
  2758.       CommonParticle *obj;
  2759.       TSTR name,name2;
  2760.       CreateCPartPickNode(CommonParticle *o, TSTR n,TSTR n1) {
  2761.          obj = o; name=TSTR(n);name2=TSTR(n1);
  2762.          }
  2763.       void Restore(int isUndo) {
  2764.          if (obj->custnode)
  2765.           obj->custname = name;
  2766.          else
  2767.            obj->custname=TSTR(_T(""));
  2768.          obj->ShowName();
  2769.          }
  2770.       void Redo()
  2771.       { obj->custname = name2;
  2772.       if (obj->hptype)
  2773.    {TSTR name=TSTR(GetString(IDS_AP_OBJECTSTR)) + (_tcslen(name2)>0? obj->custname : TSTR(GetString(IDS_AP_NONE)));
  2774.    SetWindowText(GetDlgItem(obj->hptype, IDC_AP_INSTANCESRCNAME), name);}
  2775.          }
  2776.       TSTR Description() {return GetString(IDS_AP_COMPICK);}
  2777.    };
  2778. class CreateCPartDelNode : public RestoreObj {
  2779.    public:        
  2780.       CommonParticle *obj;
  2781.       TSTR name;
  2782.       CreateCPartDelNode(CommonParticle *o, TSTR n) {
  2783.          obj = o; name=TSTR(n);
  2784.          }
  2785.       void Restore(int isUndo)
  2786.       {obj->custname = name;
  2787.        obj->ShowName();
  2788.          }
  2789.       void Redo()
  2790.          {  obj->custname=TSTR(_T(""));
  2791.       if (obj->hptype)
  2792.    {TSTR name=TSTR(GetString(IDS_AP_OBJECTSTR)) + TSTR(GetString(IDS_AP_NONE));
  2793.    SetWindowText(GetDlgItem(obj->hptype, IDC_AP_INSTANCESRCNAME), name);}
  2794.          }
  2795.       TSTR Description() {return GetString(IDS_AP_COMPICK);}
  2796.    };
  2797.  
  2798. #define CID_CREATESSBlizMODE  CID_USER +15
  2799.  
  2800. class CreateSSBlizMode : public CommandMode {      
  2801.    public:    
  2802.       CreateSSBlizProc proc;
  2803.       IObjParam *ip;
  2804.       CommonParticle *obj;
  2805.       void Begin( IObjCreate *ioc, ClassDesc *desc ) { proc.Begin( ioc, desc ); }
  2806.       void End() { proc.End(); }
  2807.       void JumpStart(IObjParam *i,CommonParticle*o);
  2808.  
  2809.       int Class() {return CREATE_COMMAND;}
  2810.       int ID() { return CID_CREATESSBlizMODE; }
  2811.       MouseCallBack *MouseProc(int *numPoints) {*numPoints = 10000; return &proc;}
  2812.       ChangeForegroundCallback *ChangeFGProc() {return CHANGE_FG_SELECTED;}
  2813.       BOOL ChangeFG( CommandMode *oldMode ) { return (oldMode->ChangeFGProc() != CHANGE_FG_SELECTED); }
  2814.       void EnterMode()
  2815.       { GetCOREInterface()->PushPrompt(GetString(IDS_AP_CREATEMODE));
  2816.         SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CROSS_HAIR)));
  2817.       }
  2818.       void ExitMode() {GetCOREInterface()->PopPrompt();SetCursor(LoadCursor(NULL, IDC_ARROW));}
  2819.    };
  2820. static CreateSSBlizMode theCreateSSBlizMode;
  2821.  
  2822. RefResult CreateSSBlizProc::NotifyRefChanged(
  2823.    Interval changeInt,
  2824.    RefTargetHandle hTarget,
  2825.    PartID& partID,  
  2826.    RefMessage message)
  2827.    {
  2828.    switch (message) {
  2829.       case REFMSG_PRENOTIFY_PASTE:
  2830.       case REFMSG_TARGET_SELECTIONCHANGE:
  2831.          if ( ignoreSelectionChange ) {
  2832.             break;
  2833.             }
  2834.          if ( SSBlizObject && CloudNode==hTarget ) {
  2835.             // this will set camNode== NULL;
  2836.             theHold.Suspend();
  2837.             DeleteReference(0);
  2838.             theHold.Resume();
  2839.             goto endEdit;
  2840.             }
  2841.          // fall through
  2842.  
  2843.       case REFMSG_TARGET_DELETED:      
  2844.          if (SSBlizObject && CloudNode==hTarget ) {
  2845.             endEdit:
  2846.             if (createInterface->GetCommandMode()->ID() == CID_STDPICK)
  2847.             { if (SSBlizObject->creating)
  2848.                   {  theCreateSSBlizMode.JumpStart(SSBlizObject->ip,SSBlizObject);
  2849.                      createInterface->SetCommandMode(&theCreateSSBlizMode);
  2850.                    }
  2851.               else {createInterface->SetStdCommandMode(CID_OBJMOVE);}
  2852.             }
  2853. #ifdef _OSNAP
  2854.             SSBlizObject->ClearAFlag(A_OBJ_LONG_CREATE);
  2855. #endif
  2856.             SSBlizObject->EndEditParams( (IObjParam*)createInterface, 0, NULL);
  2857.             SSBlizObject  = NULL;            
  2858.             CloudNode    = NULL;
  2859. /*          if (theHold.GetGlobalPutCount()!=lastPutCount)
  2860.                GetSystemSetting(SYSSET_CLEAR_UNDO);*/
  2861.             CreateNewObject();  
  2862.             attachedToNode = FALSE;
  2863.             }
  2864.          else if (CloudNode==hTarget )
  2865.              CloudNode    = NULL;
  2866.          break;
  2867.       }
  2868.    return REF_SUCCEED;
  2869.    }
  2870.  
  2871. void CreateSSBlizProc::Begin( IObjCreate *ioc, ClassDesc *desc )
  2872.    {
  2873.    createInterface = ioc;
  2874.    cDesc           = desc;
  2875.    attachedToNode  = FALSE;
  2876.    createCB        = NULL;
  2877.    CloudNode         = NULL;
  2878.    SSBlizObject       = NULL;
  2879.    CreateNewObject();
  2880.    }
  2881. void CreateSSBlizProc::CreateNewObject()
  2882. {
  2883.    SuspendSetKeyMode();
  2884.    createInterface->GetMacroRecorder()->BeginCreate(cDesc);
  2885.    SSBlizObject = (CommonParticle*)cDesc->Create();
  2886.    lastPutCount  = theHold.GetGlobalPutCount();
  2887.    
  2888.    // Start the edit params process
  2889.    if ( SSBlizObject ) {
  2890.       SSBlizObject->BeginEditParams( (IObjParam*)createInterface, BEGIN_EDIT_CREATE, NULL );
  2891. #ifdef _OSNAP
  2892.       SSBlizObject->SetAFlag(A_OBJ_LONG_CREATE);
  2893. #endif
  2894.       }  
  2895.    ResumeSetKeyMode();
  2896.    }
  2897.  
  2898. //LACamCreationManager::~LACamCreationManager
  2899. void CreateSSBlizProc::End()
  2900. { if ( SSBlizObject )
  2901.    {
  2902. #ifdef _OSNAP
  2903.       SSBlizObject->ClearAFlag(A_OBJ_LONG_CREATE);
  2904. #endif
  2905.    
  2906.    SSBlizObject->EndEditParams( (IObjParam*)createInterface,
  2907.                                   END_EDIT_REMOVEUI, NULL);
  2908.       if ( !attachedToNode )
  2909.       {  // RB 4-9-96: Normally the hold isn't holding when this
  2910.          // happens, but it can be in certain situations (like a track view paste)
  2911.          // Things get confused if it ends up with undo...
  2912.          createInterface->GetMacroRecorder()->Cancel();
  2913.          theHold.Suspend();
  2914.          SSBlizObject->DeleteAllRefsFromMe();
  2915.          SSBlizObject->DeleteAllRefsToMe();
  2916.          SSBlizObject->DeleteThis();
  2917.          SSBlizObject = NULL;
  2918.          theHold.Resume();
  2919.          if (theHold.GetGlobalPutCount()!=lastPutCount)
  2920.             GetSystemSetting(SYSSET_CLEAR_UNDO);
  2921.       }  else if ( CloudNode )
  2922.       {  theHold.Suspend();
  2923.          DeleteReference(0);  // sets cloudNode = NULL
  2924.          theHold.Resume();}
  2925.    }
  2926. }
  2927.  
  2928. void CreateSSBlizMode::JumpStart(IObjParam *i,CommonParticle *o)
  2929.    {
  2930.    ip  = i;
  2931.    obj = o;
  2932.    obj->BeginEditParams(i,BEGIN_EDIT_CREATE,NULL);
  2933.    }
  2934.  
  2935. int BlizzardClassDesc::BeginCreate(Interface *i)
  2936.    {  
  2937.    SuspendSetKeyMode();
  2938.    IObjCreate *iob = i->GetIObjCreate();
  2939.    theCreateSSBlizMode.Begin(iob,this);
  2940.    iob->PushCommandMode(&theCreateSSBlizMode);
  2941.    return TRUE;
  2942.    }
  2943.  
  2944. int BlizzardClassDesc::EndCreate(Interface *i)
  2945.    {
  2946.    ResumeSetKeyMode();
  2947.    theCreateSSBlizMode.End();
  2948.    i->RemoveMode(&theCreateSSBlizMode);
  2949.    macroRec->EmitScript();  // 10/00
  2950.    return TRUE;
  2951.    }
  2952. int SuprSprayClassDesc::BeginCreate(Interface *i)
  2953.    {  
  2954.    SuspendSetKeyMode();
  2955.    IObjCreate *iob = i->GetIObjCreate();
  2956.    theCreateSSBlizMode.Begin(iob,this);
  2957.    iob->PushCommandMode(&theCreateSSBlizMode);
  2958.    return TRUE;
  2959.    }
  2960.  
  2961. int SuprSprayClassDesc::EndCreate(Interface *i)
  2962.    {
  2963.    ResumeSetKeyMode();
  2964.    theCreateSSBlizMode.End();
  2965.    i->RemoveMode(&theCreateSSBlizMode);
  2966.    return TRUE;
  2967.    }
  2968.  
  2969. int CreateSSBlizProc::proc(HWND hwnd,int msg,int point,int flag,
  2970.             IPoint2 m )
  2971. {  int res=TRUE;  
  2972.    ViewExp *vpx = createInterface->GetViewport(hwnd);
  2973.    assert( vpx );
  2974.  
  2975.    INode *l_CloudNode = NULL;
  2976.  
  2977. #ifdef _3D_CREATE
  2978.    DWORD snapdim = SNAP_IN_3D;
  2979. #else
  2980.    DWORD snapdim = SNAP_IN_PLANE;
  2981. #endif
  2982.  
  2983.    switch ( msg ) {
  2984.       case MOUSE_POINT:
  2985.          switch ( point ) {
  2986.             case 0:
  2987.                assert( SSBlizObject );            
  2988.                vpx->CommitImplicitGrid(m, flag );
  2989.                if ( createInterface->SetActiveViewport(hwnd) ) {
  2990.                   return FALSE;
  2991.                   }
  2992.  
  2993.                if (createInterface->IsCPEdgeOnInView()) {
  2994.                   res = FALSE;
  2995.                   goto done;
  2996.                   }
  2997.  
  2998.                if ( attachedToNode ) {
  2999.                      // send this one on its way
  3000. #ifdef _OSNAP
  3001.                   SSBlizObject->ClearAFlag(A_OBJ_LONG_CREATE);
  3002. #endif
  3003.                      SSBlizObject->EndEditParams( (IObjParam*)createInterface, 0, NULL);
  3004.               createInterface->GetMacroRecorder()->EmitScript();
  3005.                   // Get rid of the reference.
  3006.                   if (CloudNode) {
  3007.                      theHold.Suspend();
  3008.                      DeleteReference(0);
  3009.                      theHold.Resume();
  3010.                      }
  3011.                   // new object
  3012.                   CreateNewObject();   // creates SSBlizObject
  3013.                   }
  3014.  
  3015.                   theHold.Begin();   // begin hold for undo
  3016.                mat.IdentityMatrix();
  3017.  
  3018.                // link it up
  3019.                l_CloudNode = createInterface->CreateObjectNode( SSBlizObject);
  3020.                attachedToNode = TRUE;
  3021.                assert( l_CloudNode );            
  3022.                createCB = SSBlizObject->GetCreateMouseCallBack();
  3023.                createInterface->SelectNode( l_CloudNode );
  3024.                
  3025.                // Reference the new node so we'll get notifications.
  3026.                theHold.Suspend();
  3027.                ReplaceReference( 0, l_CloudNode);
  3028.                theHold.Resume();
  3029.                mat.IdentityMatrix();
  3030.             default:          
  3031.                if (createCB) {                  
  3032.                   res = createCB->proc(vpx,msg,point,flag,m,mat);
  3033. //                macroRec->Disable();   // 10/00
  3034.                   createInterface->SetNodeTMRelConstPlane(CloudNode,mat);
  3035. //                macroRec->Enable();
  3036.  
  3037.                   if (res==CREATE_ABORT)
  3038.                      goto abort;
  3039.                   if (res==CREATE_STOP)
  3040.                   {
  3041. #ifdef _OSNAP
  3042.                          SSBlizObject->ClearAFlag(A_OBJ_LONG_CREATE);
  3043. #endif
  3044.                    theHold.Accept(GetString(IDS_DS_CREATE));  
  3045.                   }
  3046.                  
  3047.                   createInterface->RedrawViews(createInterface->GetTime());   //DS
  3048.                   }
  3049.  
  3050.                break;
  3051.                
  3052.             }        
  3053.          break;
  3054.  
  3055.       case MOUSE_MOVE:
  3056.          if (createCB) {            
  3057.             res = createCB->proc(vpx,msg,point,flag,m,mat);
  3058. //          macroRec->Disable();   // 10/00
  3059.             createInterface->SetNodeTMRelConstPlane(CloudNode,mat);
  3060. //          macroRec->Enable();
  3061.             if (res==CREATE_ABORT)
  3062.                goto abort;
  3063.             if (res==CREATE_STOP){
  3064. #ifdef _OSNAP
  3065.          SSBlizObject->ClearAFlag(A_OBJ_LONG_CREATE);
  3066. #endif
  3067.                theHold.Accept(GetString(IDS_DS_CREATE)); // TH
  3068.             }
  3069.             createInterface->RedrawViews(createInterface->GetTime(),REDRAW_INTERACTIVE);     //DS    
  3070.             }
  3071.          break;
  3072.  
  3073.    case MOUSE_PROPCLICK:
  3074.       createInterface->SetStdCommandMode(CID_OBJMOVE);
  3075.       break;
  3076.       case MOUSE_ABORT:
  3077.    if (createCB)
  3078.    { res = createCB->proc(vpx,msg,point,flag,m,mat);
  3079.      createInterface->SetNodeTMRelConstPlane(CloudNode, mat);
  3080.      if (res==CREATE_ABORT)
  3081.          goto abort;
  3082.      if (res==CREATE_STOP)
  3083.      {
  3084. #ifdef _OSNAP
  3085.          SSBlizObject->ClearAFlag(A_OBJ_LONG_CREATE);
  3086. #endif
  3087.        theHold.Accept(GetString(IDS_DS_CREATE));  
  3088.      }
  3089.       break;
  3090.    }
  3091.    abort:
  3092.       assert( SSBlizObject );
  3093. #ifdef _OSNAP
  3094.       SSBlizObject->ClearAFlag(A_OBJ_LONG_CREATE);
  3095. #endif
  3096.       SSBlizObject->EndEditParams( (IObjParam*)createInterface,0,NULL);
  3097.       theHold.Cancel();  // deletes both the Cloudera and target.
  3098.       if (theHold.GetGlobalPutCount()!=lastPutCount)
  3099.                GetSystemSetting(SYSSET_CLEAR_UNDO);
  3100.       SSBlizObject=NULL;
  3101.       createInterface->RedrawViews(createInterface->GetTime());
  3102.       CreateNewObject();  
  3103.       attachedToNode = FALSE;
  3104.       res = FALSE;
  3105.       break;
  3106.    
  3107.       case MOUSE_FREEMOVE:
  3108.          SetCursor(LoadCursor(hInstance, MAKEINTRESOURCE(IDC_CROSS_HAIR)));
  3109. #ifdef _OSNAP  //PREVIEW SNAP
  3110.          if (createCB) res =createCB->proc(vpx,msg,point,flag,m,mat);
  3111. #endif
  3112.       vpx->TrackImplicitGrid(m);
  3113.          break;
  3114.    }
  3115.  
  3116.    done:
  3117.    if ((res == CREATE_STOP)||(res==CREATE_ABORT))
  3118.       vpx->ReleaseImplicitGrid();
  3119.    createInterface->ReleaseViewport(vpx);
  3120.    return res;
  3121. }
  3122.  
  3123. void CheckInstButtons(IParamBlock *pblock,HWND hptype)
  3124. { int isinst;
  3125.   pblock->GetValue(PB_PARTICLECLASS,0,isinst,FOREVER);
  3126.   if (isinst==INSTGEOM)
  3127.   { TurnButton(hptype,IDC_AP_OBJECTPICK,TRUE);
  3128.   }
  3129. }
  3130. void CheckLifeButtons(int stype,HWND spawn)
  3131. { int rep;
  3132.   rep = SendMessage(GetDlgItem(spawn,IDC_AP_LIFEQUEUE),LB_GETCURSEL,0,0);
  3133.   TurnButton(spawn,IDC_AP_LIFEQUEUEADD,(stype>1));
  3134.   TurnButton(spawn,IDC_AP_LIFEQUEUEREPL,(stype>1)&&(rep>-1));
  3135.   TurnButton(spawn,IDC_AP_LIFEQUEUEDEL,(stype>1)&&(rep>-1));
  3136. }
  3137.  
  3138. void CheckSpawnButtons(IParamBlock *pblock,HWND spawn,int repi)
  3139. { int stype;
  3140.   pblock->GetValue(PB_SPAWNTYPE,0,stype,FOREVER);
  3141.   EnableWindow(GetDlgItem(spawn,IDC_AP_OBJECTQUEUE),(stype>1));
  3142.   TurnButton(spawn,IDC_AP_OBJECTQUEUEPICK,(stype>1));
  3143.   TurnButton(spawn,IDC_AP_OBJQUEUEREPLACE,(stype>1)&&(repi>-1));
  3144.   TurnButton(spawn,IDC_AP_OBJQUEUEDELETE,(stype>1)&&(repi>-1));
  3145.   CheckLifeButtons(stype,spawn);
  3146. }
  3147.  
  3148. void CheckPickButtons(IParamBlock *pblock,HWND hptype,HWND spawn,int repi)
  3149. { CheckInstButtons(pblock,hptype);
  3150.   CheckSpawnButtons(pblock,spawn,repi);
  3151. }
  3152.  
  3153. class EmitterCreateCallback : public CreateMouseCallBack {
  3154.    public:
  3155.       SuprSprayParticle *po;
  3156.       Point3 p0,p1;
  3157.       IPoint2 sp0, sp1;
  3158.       int proc( ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat);
  3159.    };
  3160.  
  3161. int EmitterCreateCallback::proc(
  3162.       ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat)
  3163. {
  3164. #ifdef _3D_CREATE
  3165.    DWORD snapdim = SNAP_IN_3D;
  3166. #else
  3167.    DWORD snapdim = SNAP_IN_PLANE;
  3168. #endif
  3169.  
  3170. #ifdef _OSNAP
  3171.    if (msg == MOUSE_FREEMOVE)
  3172.    { vpt->SnapPreview(m,m,NULL, snapdim);
  3173.    }
  3174. #endif
  3175.    if (msg==MOUSE_POINT||msg==MOUSE_MOVE) {
  3176.       switch(point)  {
  3177.          case 0:
  3178.             // if hidden by category, re-display particles and objects
  3179.             GetCOREInterface()->SetHideByCategoryFlags(
  3180.                   GetCOREInterface()->GetHideByCategoryFlags() & ~(HIDE_OBJECTS|HIDE_PARTICLES));
  3181.             sp0 = m;
  3182.             p0 = vpt->SnapPoint(m,m,NULL,snapdim);
  3183.             mat.SetTrans(p0);
  3184.             po->pblock->SetValue(PB_EMITRWID,0,0.01f);
  3185.             po->pmapParam->Invalidate();
  3186.             break;
  3187.  
  3188.          case 1: {
  3189. //          mat.IdentityMatrix();
  3190.             sp1 = m;
  3191.             p1 = vpt->SnapPoint(m,m,NULL,snapdim);
  3192.             po->pblock->SetValue(PB_EMITRWID,0,Length(p1-p0));
  3193.             po->pmapParam->Invalidate();
  3194.  
  3195.             if (msg==MOUSE_POINT) {
  3196.                if (Length(m-sp0)<3 || Length(p1-p0)<0.1f) {                
  3197.                   return CREATE_ABORT;
  3198.                } else { CheckPickButtons(po->pblock,po->hptype,po->spawn,po->pickCB.repi);
  3199.                   return CREATE_STOP;
  3200.                   }
  3201.                }
  3202.             break;
  3203.             }
  3204.  
  3205.          }
  3206.    } else {
  3207.       if (msg == MOUSE_ABORT)
  3208.          return CREATE_ABORT;
  3209.       }
  3210.    return 1;
  3211.    }
  3212.  
  3213. static EmitterCreateCallback emitterCallback;
  3214.  
  3215. CreateMouseCallBack* SuprSprayParticle::GetCreateMouseCallBack()
  3216.    {
  3217.    emitterCallback.po = this;
  3218.    return &emitterCallback;
  3219.    }
  3220.  
  3221. class SSParticleGenDlgProc : public ParamMapUserDlgProc {
  3222.    public:
  3223.       CommonParticle *po;
  3224.  
  3225.       SSParticleGenDlgProc(CommonParticle *p) {po=p;}
  3226.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  3227.       void Update(TimeValue t);
  3228.       void DeleteThis() {delete this;}
  3229.    };
  3230. void SSParticleGenDlgProc::Update(TimeValue t)
  3231. { if (!po->editOb) return;
  3232.   int birthmeth;
  3233.   po->pblock->GetValue(PB_BIRTHMETHOD,0,birthmeth,FOREVER);
  3234.   if (birthmeth)
  3235.   { SpinnerOff(po->hgen,IDC_SP_GENRATESPIN,IDC_SP_GENRATE);
  3236.     SpinnerOn(po->hgen,IDC_SP_GENTTLSPIN,IDC_SP_GENTTL);
  3237.   }else
  3238.   { SpinnerOn(po->hgen,IDC_SP_GENRATESPIN,IDC_SP_GENRATE);
  3239.     SpinnerOff(po->hgen,IDC_SP_GENTTLSPIN,IDC_SP_GENTTL);
  3240.   }
  3241. }
  3242.  
  3243. INT_PTR SSParticleGenDlgProc::DlgProc(
  3244.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  3245.    {  int acourse;
  3246.        float size;
  3247.       switch (msg)
  3248.      { case WM_INITDIALOG: {
  3249.           Update(t);
  3250.          break;
  3251.          }
  3252.       case WM_COMMAND:
  3253.          switch (LOWORD(wParam))
  3254.          { case IDC_SP_GENUSERATE:
  3255.             { SpinnerOn(hWnd,IDC_SP_GENRATESPIN,IDC_SP_GENRATE);
  3256.               SpinnerOff(hWnd,IDC_SP_GENTTLSPIN,IDC_SP_GENTTL);
  3257.              return TRUE;
  3258.             }
  3259.            case IDC_SP_GENUSETTL:
  3260.             { SpinnerOff(hWnd,IDC_SP_GENRATESPIN,IDC_SP_GENRATE);
  3261.               SpinnerOn(hWnd,IDC_SP_GENTTLSPIN,IDC_SP_GENTTL);
  3262.              return TRUE;
  3263.             }
  3264.          }
  3265.          case CC_SPINNER_CHANGE:
  3266.          switch ( LOWORD(wParam) )
  3267.          { case IDC_SP_GENSIZESPIN:
  3268.                { po->pblock->GetValue(PB_METAAUTOCOARSE,t,acourse,FOREVER);
  3269.                int mpart;
  3270.                 po->pblock->GetValue(PB_PARTICLECLASS,t,mpart,FOREVER);
  3271.                 if ((mpart==METABALLS)&&(acourse) )
  3272.                 { po->pblock->GetValue(PB_SIZE,t,size,FOREVER);
  3273.                   po->pblock->SetValue(PB_METACOURSE,t,size/coursedivider);
  3274.                   BOOL bliz=(po->ClassID()==BLIZZARD_CLASS_ID);
  3275.                   if (bliz) po->pblock->SetValue(PB_METACOURSEVB,t,size/3.0f);
  3276.                   else po->pblock->SetValue(PB_METACOURSEV,t,size/3.0f);
  3277.                   po->pmapPType->Invalidate();
  3278.                 }
  3279.                break;
  3280.                }
  3281.             case IDC_AP_NEWSEED:
  3282.                { srand( (unsigned)time( NULL ) );
  3283.                  int newseed=rand() % 25001;
  3284.                  po->pblock->SetValue(PB_RNDSEED,0,newseed);
  3285.                  po->pmapPGen->Invalidate();
  3286.                }
  3287.                  return TRUE;
  3288.             case IDC_SP_GENEMIT1SPIN:
  3289.             case IDC_SP_GENEMIT2SPIN:
  3290.                { int sstop,sstart;
  3291.                  po->pblock->GetValue(PB_EMITSTOP,t,sstop,FOREVER);
  3292.                  po->pblock->GetValue(PB_EMITSTART,t,sstart,FOREVER);
  3293.                  if (sstop<sstart)
  3294.                     po->pblock->SetValue(PB_EMITSTOP,t,sstart);
  3295.                  return TRUE;
  3296.                }
  3297.          }
  3298.      }
  3299.    return FALSE;
  3300.    }
  3301. void CourseCheck(CommonParticle *po,HWND hWnd,TimeValue t)
  3302. { int acourse;
  3303.   float size;
  3304.   po->pblock->GetValue(PB_METAAUTOCOARSE,t,acourse,FOREVER);
  3305.   BOOL bliz=(po->ClassID()==BLIZZARD_CLASS_ID);
  3306.   if (acourse)
  3307.   { float mc1,mc2,mc,mcv;
  3308.    po->pblock->GetValue(PB_SIZE,t,size,FOREVER);mc=size/coursedivider;mcv=size/3.0f;
  3309.    po->pblock->GetValue(PB_METACOURSE,t,mc1,FOREVER);
  3310.    if (bliz) po->pblock->GetValue(PB_METACOURSEVB,t,mc2,FOREVER);
  3311.    else po->pblock->GetValue(PB_METACOURSEV,t,mc2,FOREVER);
  3312.    if ((mc1!=mc)||(mc2!=mcv))
  3313.    { po->pblock->SetValue(PB_METACOURSE,t,mc);
  3314.      if (bliz) po->pblock->SetValue(PB_METACOURSEVB,t,mcv);
  3315.      else po->pblock->SetValue(PB_METACOURSEV,t,mcv);
  3316.      po->pmapPType->Invalidate();
  3317.    }
  3318.    SpinnerOff(hWnd,IDC_SP_METCOURSESPIN,IDC_SP_METCOURSE);
  3319.    SpinnerOff(hWnd,IDC_SP_METCOURSEVSPIN,IDC_SP_METCOURSEV);
  3320.    EnableWindow(GetDlgItem(hWnd,IDC_SP_COARSENESS_TXT),FALSE);
  3321.    EnableWindow(GetDlgItem(hWnd,IDC_SP_METCOURSE_TXT),FALSE);
  3322.    EnableWindow(GetDlgItem(hWnd,IDC_SP_METCOURSEV_TXT),FALSE);
  3323.   }
  3324.   else
  3325.   { SpinnerOn(hWnd,IDC_SP_METCOURSESPIN,IDC_SP_METCOURSE);
  3326.    SpinnerOn(hWnd,IDC_SP_METCOURSEVSPIN,IDC_SP_METCOURSEV);
  3327.    EnableWindow(GetDlgItem(hWnd,IDC_SP_COARSENESS_TXT),TRUE);
  3328.    EnableWindow(GetDlgItem(hWnd,IDC_SP_METCOURSE_TXT),TRUE);
  3329.    EnableWindow(GetDlgItem(hWnd,IDC_SP_METCOURSEV_TXT),TRUE);
  3330.    }
  3331. };
  3332. void SetMapVals(IParamBlock *pblock,HWND hWnd,TimeValue t)
  3333. { int type,maptype;
  3334.   pblock->GetValue(PB_PARTICLETYPE,t,type,FOREVER);
  3335.   if (type==RENDTET)
  3336.   { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3337.    SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3338.    EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),FALSE);
  3339.    EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),FALSE);
  3340.   }
  3341.   else
  3342.   { pblock->GetValue(PB_MAPPINGTYPE,t,maptype,FOREVER);
  3343.     if (maptype==2)
  3344.    { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3345.      SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3346.    }
  3347.     else if (maptype)
  3348.    { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3349.      SpinnerOn(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3350.    }
  3351.    else
  3352.    { SpinnerOn(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3353.      SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3354.    }
  3355.    EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),TRUE);
  3356.    EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),TRUE);
  3357.   }
  3358. }
  3359.  
  3360. void MappingStuff(IParamBlock *pblock,HWND hWnd,TimeValue t,BOOL isbliz)
  3361. { int maptype;
  3362.   pblock->GetValue((isbliz?PB_CUSTOMMTL2:PB_CUSTOMMTL),t,maptype,FOREVER);
  3363.   if (isbliz)
  3364.   EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPPLANAR),!maptype);
  3365.   if (maptype)
  3366.   { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3367.     SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3368.     EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),FALSE);
  3369.     EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),FALSE);
  3370.   }
  3371.   else SetMapVals(pblock,hWnd,t);
  3372. }
  3373. void CheckStretchBox(HWND hWnd,CommonParticle *po)
  3374. { int enon=0;
  3375.   if (IsStdMtl(po->cnode))
  3376.   { EnableWindow(GetDlgItem(hWnd,IDC_AP_PBLURON),TRUE);
  3377.   } else EnableWindow(GetDlgItem(hWnd,IDC_AP_PBLURON),FALSE);
  3378.   SpinnerOn(hWnd,IDC_AP_STRETCHSPIN,IDC_AP_STRETCH);
  3379.   EnableWindow(GetDlgItem(hWnd,IDC_AP_STRETCH_TXT),TRUE);
  3380.   po->pmapPSpin->Invalidate();
  3381. }
  3382.  
  3383. void StretchStuff(int dir,int isphase,HWND hWnd,CommonParticle *po)
  3384. { if (dir==0)
  3385.   { EnableWindow(GetDlgItem(hWnd,IDC_AP_PBLURON),FALSE);
  3386.    SpinnerOff(hWnd,IDC_AP_STRETCHSPIN,IDC_AP_STRETCH);
  3387.    EnableWindow(GetDlgItem(hWnd,IDC_AP_STRETCH_TXT),FALSE);
  3388.    SpinStuff(hWnd,FALSE,isphase);
  3389.   }
  3390.   else if (dir==1)
  3391.   {   CheckStretchBox(hWnd,po);
  3392.    SpinStuff(hWnd,FALSE,isphase);
  3393.   }  
  3394.   else if (dir==2)
  3395.   {   EnableWindow(GetDlgItem(hWnd,IDC_AP_PBLURON),FALSE);
  3396.    SpinnerOff(hWnd,IDC_AP_STRETCHSPIN,IDC_AP_STRETCH);
  3397.    EnableWindow(GetDlgItem(hWnd,IDC_AP_STRETCH_TXT),FALSE);
  3398.    SpinStuff(hWnd,TRUE,isphase);
  3399.   }
  3400. }
  3401.  
  3402. void AniFr(HWND hWnd,IParamBlock *pblock)
  3403. { int anitype;
  3404.   pblock->GetValue(PB_ANIMATIONOFFSET,0,anitype,FOREVER);
  3405.   if (anitype>1)
  3406.      SpinnerOn(hWnd,IDC_AP_ANIRNDFRSPIN,IDC_AP_ANIRNDFR);
  3407.   else   SpinnerOff(hWnd,IDC_AP_ANIRNDFRSPIN,IDC_AP_ANIRNDFR);
  3408.   EnableWindow(GetDlgItem(hWnd,IDC_AP_ANIRNDFR_TXT),anitype>1);
  3409. }
  3410. void InstIn(CommonParticle *po,HWND hWnd, TimeValue t)
  3411. { int ison;
  3412.   BOOL isbliz;
  3413.   MetaOff(hWnd);
  3414.   StdStuff(hWnd,FALSE);
  3415.   InstStuff(hWnd,TRUE,po->spawn,po->hparam);
  3416.   AniFr(hWnd,po->pblock);
  3417.   TurnButton(hWnd,IDC_AP_OBJECTPICK,TRUE);
  3418.   isbliz=(po->ClassID()==BLIZZARD_CLASS_ID);
  3419.   po->pblock->GetValue(PB_SPINAXISTYPE,0,ison,FOREVER);
  3420.   if (isbliz) SpinStuff(po->hrot,ison,TRUE);
  3421.   else StretchStuff(ison,TRUE,po->hrot,po);
  3422.   SpinMainStuff(po->hrot,TRUE);
  3423.   EnableWindow(GetDlgItem(hWnd,IDC_SP_AUTOCOARSE),FALSE);
  3424.   EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPBOX),TRUE);
  3425.   EnableWindow(GetDlgItem(hWnd,IDC_SP_DRAFTMODE),FALSE);
  3426.   MappingStuff(po->pblock,hWnd,t,isbliz);
  3427.   int stype;po->pblock->GetValue(PB_SPAWNTYPE,0,stype,FOREVER);
  3428.   ObjectMutQueOn(stype,po->spawn,po->pickCB.repi);
  3429.   if (!isbliz)
  3430.     EnableWindow(GetDlgItem(po->hrot,IDC_AP_PARTICLEDIRTRAVL),TRUE);
  3431.   po->pmapPSpin->Invalidate();
  3432. }
  3433.  
  3434. void MetaIn(CommonParticle *po,HWND hWnd,TimeValue t)
  3435. { BOOL isbliz;
  3436.   isbliz=(po->ClassID()==BLIZZARD_CLASS_ID);
  3437.   int mon,pname=(isbliz?PB_CUSTOMMTL2:PB_CUSTOMMTL);
  3438.   po->pblock->GetValue(pname,t,mon,FOREVER);
  3439.   if (mon>0) po->pblock->SetValue(pname,t,0);
  3440.   SpinnerOn(hWnd,IDC_SP_METTENSSPIN,IDC_SP_METTENS);
  3441.   SpinnerOn(hWnd,IDC_SP_METTENSVARSPIN,IDC_SP_METTENSVAR);
  3442.   EnableWindow(GetDlgItem(hWnd,IDC_SP_METTENS_TXT),TRUE);
  3443.   EnableWindow(GetDlgItem(hWnd,IDC_SP_METTENSVAR_TXT),TRUE);
  3444.   EnableWindow(GetDlgItem(hWnd,IDC_SP_METTENSVAR_PCNT),TRUE);
  3445.   EnableWindow(GetDlgItem(hWnd,IDC_SP_AUTOCOARSE),TRUE);
  3446.   CourseCheck(po,hWnd,t);
  3447.   if (isbliz) SpinStuff(po->hrot,FALSE,FALSE);
  3448.   else StretchStuff(0,FALSE,po->hrot,po);
  3449.   SpinMainStuff(po->hrot,FALSE);
  3450.   EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),TRUE);
  3451.   int showtype;
  3452.   po->pblock->GetValue(PB_VIEWPORTSHOWS,0,showtype,FOREVER);
  3453.   if (showtype==3) po->pblock->SetValue(PB_VIEWPORTSHOWS,0,0);
  3454.   EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPBOX),FALSE);
  3455.   TurnButton(hWnd,IDC_AP_OBJECTPICK,FALSE);
  3456.   StdStuff(hWnd,FALSE);
  3457.   InstStuff(hWnd,FALSE,po->spawn,po->hparam);
  3458.   isbliz=(po->ClassID()==BLIZZARD_CLASS_ID);
  3459.   MappingStuff(po->pblock,hWnd,t,isbliz);
  3460.   ObjectMutQueOff(po->spawn);
  3461.   if (!isbliz) EnableWindow(GetDlgItem(po->hrot,IDC_AP_PARTICLEDIRTRAVL),FALSE);
  3462.   EnableWindow(GetDlgItem(hWnd,IDC_SP_DRAFTMODE),TRUE);
  3463.   int stype;
  3464.   po->pblock->GetValue(PB_SPAWNTYPE,0,stype,FOREVER);
  3465. //  if (stype>1) po->pblock->SetValue(PB_SPAWNTYPE,0,0);  AllSpawnBad(po->spawn,0,FALSE);
  3466.   int ison; po->pblock->GetValue((isbliz?PB_BLIPCOLLIDE_ON:PB_IPCOLLIDE_ON),t,ison,FOREVER);
  3467.   if (ison) stype=0;
  3468.   SpawnStuff(po->spawn,stype);
  3469.   po->pmapPSpin->Invalidate();
  3470. }
  3471.  
  3472. void StdOn(CommonParticle *po,HWND hWnd,TimeValue t)
  3473. { int ison,mon;
  3474.   BOOL isbliz;
  3475.   StdStuff(hWnd,TRUE);
  3476.   isbliz=(po->ClassID()==BLIZZARD_CLASS_ID);
  3477.   int pname=(isbliz?PB_CUSTOMMTL2:PB_CUSTOMMTL);
  3478.   po->pblock->GetValue(pname,t,mon,FOREVER);
  3479.   if (mon>0) po->pblock->SetValue(pname,t,0);
  3480.   po->pblock->GetValue(PB_SPINAXISTYPE,0,ison,FOREVER);
  3481.   if (isbliz) SpinStuff(po->hrot,ison,TRUE);
  3482.   else StretchStuff(ison,TRUE,po->hrot,po);
  3483.   SpinMainStuff(po->hrot,TRUE);
  3484.   int facing;
  3485.   po->pblock->GetValue(PB_PARTICLETYPE,t,facing,FOREVER);
  3486. /*
  3487.    if ((facing==RENDTYPE5)||(facing==RENDTYPE6))
  3488.    {    
  3489.       po->pblock->GetValue(PB_VIEWPORTSHOWS,t,facing,FOREVER);
  3490.       if (facing==2)
  3491.          po->pblock->SetValue(PB_VIEWPORTSHOWS,t,1);
  3492.       EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),FALSE);
  3493.    }
  3494.    else  
  3495.    */
  3496.       EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),TRUE);
  3497.   TurnButton(hWnd,IDC_AP_OBJECTPICK,FALSE);
  3498.   int showtype;
  3499.   po->pblock->GetValue(PB_VIEWPORTSHOWS,0,showtype,FOREVER);
  3500.   if (showtype==3) po->pblock->SetValue(PB_VIEWPORTSHOWS,0,0);
  3501.   EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPBOX),FALSE);
  3502.  // SpinnerOn(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3503.   MetaOff(hWnd);
  3504.   InstStuff(hWnd,FALSE,po->spawn,po->hparam);
  3505.   MappingStuff(po->pblock,hWnd,t,isbliz);
  3506.   ObjectMutQueOff(po->spawn);
  3507.   if (!isbliz)
  3508.     EnableWindow(GetDlgItem(po->hrot,IDC_AP_PARTICLEDIRTRAVL),TRUE);
  3509.   po->pmapPSpin->Invalidate();
  3510. }
  3511.  
  3512. class BLParticleDlgProc : public ParamMapUserDlgProc {
  3513.    public:
  3514.       BlizzardParticle *po;
  3515.  
  3516.       BLParticleDlgProc(BlizzardParticle *p) {po=p;}
  3517.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  3518.       void DeleteThis() {delete this;}
  3519.    };
  3520.  
  3521. INT_PTR BLParticleDlgProc::DlgProc(
  3522.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  3523. {  switch (msg) {
  3524.       case WM_INITDIALOG: {
  3525.          break;
  3526.          }
  3527.       case WM_COMMAND:
  3528.          switch (LOWORD(wParam))
  3529.          { case IDC_SP_VIEWDISPMESH:
  3530.               {po->valid=FALSE;
  3531.                int subtree,custmtl;
  3532.                po->pblock->GetValue(PB_CUSTOMMTL2,0,custmtl,FOREVER);
  3533.                po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3534.                int anioff;
  3535.                po->pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  3536.                po->theSuprSprayDraw.t=t;
  3537.                po->theSuprSprayDraw.anioff=anioff;
  3538.                TimeValue aniend=GetAnimEnd();
  3539.                int anifr;
  3540.                anifr=aniend+GetTicksPerFrame();
  3541.                po->theSuprSprayDraw.anifr=anifr;
  3542.                po->GetTimes(po->times,t,anifr,anioff);
  3543.                 po->GetMesh(t,subtree,custmtl);
  3544.                break;
  3545.               }
  3546.            case IDC_SP_VIEWDISPBOX:        
  3547.               { po->valid=FALSE;
  3548.                int subtree;
  3549.                po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3550.                int anioff;
  3551.                po->pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  3552.                po->theSuprSprayDraw.t=t;
  3553.                po->theSuprSprayDraw.anioff=anioff;
  3554.                TimeValue aniend=GetAnimEnd();
  3555.                int anifr;
  3556.                anifr=aniend+GetTicksPerFrame();
  3557.                po->theSuprSprayDraw.anifr=anifr;
  3558.                po->GetTimes(po->times,t,anifr,anioff);
  3559.                po->GetallBB(po->custnode,subtree,t);
  3560.               break;
  3561.               }
  3562.          }
  3563.          break;  
  3564.       default:
  3565.          return FALSE;
  3566.       }
  3567.    return TRUE;
  3568.    }
  3569. class SSParticleDlgProc : public ParamMapUserDlgProc {
  3570.    public:
  3571.       SuprSprayParticle *po;
  3572.  
  3573.       SSParticleDlgProc(SuprSprayParticle *p) {po=p;}
  3574.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  3575.       void DeleteThis() {delete this;}
  3576.    };
  3577.  
  3578. INT_PTR SSParticleDlgProc::DlgProc(
  3579.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  3580. {  switch (msg) {
  3581.       case WM_INITDIALOG: {
  3582.          break;
  3583.          }
  3584.       case WM_COMMAND:
  3585.          switch (LOWORD(wParam))
  3586.          { case IDC_SP_VIEWDISPMESH:
  3587.               {po->valid=FALSE;
  3588.                int subtree,custmtl;
  3589.                po->pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  3590.                po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3591.                int anioff;
  3592.                po->pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  3593.                po->theSuprSprayDraw.t=t;
  3594.                po->theSuprSprayDraw.anioff=anioff;
  3595.                TimeValue aniend=GetAnimEnd();
  3596.                int anifr;
  3597.                anifr=aniend+GetTicksPerFrame();
  3598.                po->theSuprSprayDraw.anifr=anifr;
  3599.                po->GetTimes(po->times,t,anifr,anioff);
  3600.                 po->GetMesh(t,subtree,custmtl);
  3601.                break;
  3602.               }
  3603.            case IDC_SP_VIEWDISPBOX:        
  3604.               { po->valid=FALSE;
  3605.                int subtree;
  3606.                po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3607.                int anioff;
  3608.                po->pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  3609.                po->theSuprSprayDraw.t=t;
  3610.                po->theSuprSprayDraw.anioff=anioff;
  3611.                TimeValue aniend=GetAnimEnd();
  3612.                int anifr;
  3613.                anifr=aniend+GetTicksPerFrame();
  3614.                po->theSuprSprayDraw.anifr=anifr;
  3615.                po->GetTimes(po->times,t,anifr,anioff);
  3616.                po->GetallBB(po->custnode,subtree,t);
  3617.               break;
  3618.               }
  3619.          }
  3620.          break;  
  3621.       default:
  3622.          return FALSE;
  3623.       }
  3624.    return TRUE;
  3625.    }
  3626. void AddMtl(CommonParticle *po,TimeValue t,int custmtl)
  3627. { if (po->cnode)
  3628.    { int subtree,frag,submtl=0;
  3629.     po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3630.     po->pblock->GetValue(PB_PARTICLECLASS,0,frag,FOREVER);
  3631.    if ((po->custnode)&&(frag==INSTGEOM)&& custmtl)
  3632.       po->AssignMtl(po->cnode,po->custnode,subtree,t);
  3633.    po->valid=FALSE;
  3634.    po->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  3635.    }
  3636.  }
  3637.  
  3638.  
  3639. class SSParticleDisableDlgProc : public ParamMapUserDlgProc {
  3640.    public:
  3641.       SuprSprayParticle *po;
  3642.       ICustButton *iBut;
  3643.  
  3644.       SSParticleDisableDlgProc(SuprSprayParticle *p) {po=p;}
  3645.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  3646.       void Update(TimeValue t);
  3647.       void DeleteThis() {delete this;}
  3648.    };
  3649. void SSParticleDisableDlgProc::Update(TimeValue t)
  3650. { if (!po->editOb) return;
  3651.   SetMapVals(po->pblock,po->hptype,t);
  3652.   float width;
  3653.   po->pblock->GetValue(PB_EMITRWID,0,width,FOREVER);
  3654.   if (width<0.01f) iBut->Disable();
  3655.   po->ShowName();
  3656.   int chunky;
  3657.   po->pblock->GetValue(PB_PARTICLECLASS,0,chunky,FOREVER);
  3658.   if (chunky==METABALLS) MetaIn(po,po->hptype,t);
  3659.   else if (chunky==ISSTD) StdOn(po,po->hptype,t);
  3660.   else InstIn(po,po->hptype,t);
  3661. }
  3662.  
  3663. INT_PTR SSParticleDisableDlgProc::DlgProc(
  3664.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  3665. {  switch (msg) {
  3666.       case WM_INITDIALOG: {
  3667.          iBut = GetICustButton(GetDlgItem(hWnd,IDC_AP_OBJECTPICK));
  3668.          iBut->SetType(CBT_CHECK);
  3669.          iBut->SetHighlightColor(GREEN_WASH);
  3670.          Update(t);
  3671.          break;
  3672.          }
  3673.       case WM_DESTROY:
  3674.          // Release all our Custom Controls
  3675.          ReleaseICustButton(iBut);
  3676.          return FALSE;
  3677.       case WM_COMMAND:
  3678.          switch (LOWORD(wParam))
  3679.          { case IDC_AP_OBJECTPICK:
  3680.                { po->flags=0;
  3681.                if (po->ip->GetCommandMode()->ID() == CID_STDPICK)
  3682.                { if (po->creating)
  3683.                   {  theCreateSSBlizMode.JumpStart(po->ip,po);
  3684.                      po->ip->SetCommandMode(&theCreateSSBlizMode);
  3685.                   } else {po->ip->SetStdCommandMode(CID_OBJMOVE);}
  3686.                } else
  3687.                   { po->pickCB.po = po;  
  3688.                     po->pickCB.dodist=0;
  3689.                     po->ip->SetPickMode(&po->pickCB);
  3690.                   }
  3691.                break;
  3692.             }
  3693.          case IDC_AP_UPDATEMTL:
  3694.             { int custmtl;
  3695.               po->pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  3696.               AddMtl(po,t,custmtl);
  3697.               if ((custmtl) &&(po->cnode))
  3698.               { EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPCUSTOMEMIT),FALSE);
  3699.                 po->origmtl=po->cnode->GetMtl();
  3700.               }
  3701.               break;
  3702.             }
  3703.             case IDC_SP_TYPESTD:
  3704.             { StdOn(po,hWnd,t);
  3705.               po->valid=FALSE;
  3706.               if (po->ip->GetCommandMode()->ID() == CID_STDPICK)
  3707.               { if (po->creating)
  3708.                {  theCreateSSBlizMode.JumpStart(po->ip,po);
  3709.                   po->ip->SetCommandMode(&theCreateSSBlizMode);
  3710.                } else {po->ip->SetStdCommandMode(CID_OBJMOVE);}
  3711.               }
  3712.              break;
  3713.             }
  3714.            case IDC_AP_NOANIOFF:
  3715.            case IDC_AP_ANIOFFBIRTH:
  3716.                SpinnerOff(hWnd,IDC_AP_ANIRNDFRSPIN,IDC_AP_ANIRNDFR);
  3717.                EnableWindow(GetDlgItem(hWnd,IDC_AP_ANIRNDFR_TXT),FALSE);
  3718.               break;
  3719.            case IDC_AP_ANIOFFRND:
  3720.               SpinnerOn(hWnd,IDC_AP_ANIRNDFRSPIN,IDC_AP_ANIRNDFR);
  3721.               EnableWindow(GetDlgItem(hWnd,IDC_AP_ANIRNDFR_TXT),TRUE);
  3722.               break;
  3723.            case IDC_SP_TYPEFAC:
  3724.            case IDC_SP_TYPEPIX:
  3725.             { SetMapVals(po->pblock,hWnd,t);
  3726. //            int facing;
  3727. //            po->pblock->GetValue(PB_VIEWPORTSHOWS,t,facing,FOREVER);
  3728. //            if (facing==2) po->pblock->SetValue(PB_VIEWPORTSHOWS,t,1);
  3729. //            EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),FALSE);
  3730.               po->pmapParam->Invalidate();
  3731.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),TRUE);
  3732.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),TRUE);
  3733.              break;
  3734.             }
  3735.            case IDC_SP_TYPETRI:
  3736.            case IDC_SP_TYPECUB:
  3737.            case IDC_SP_TYPESPC:
  3738.            case IDC_SP_TYPE6PNT:
  3739.            case IDC_SP_TYPESPHERE:
  3740.             { SetMapVals(po->pblock,hWnd,t);
  3741.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),TRUE);
  3742.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),TRUE);
  3743.               EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),TRUE);
  3744.              break;
  3745.             }
  3746.            case IDC_SP_TYPETET:
  3747.             { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3748.               SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3749.               EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),TRUE);
  3750.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),FALSE);
  3751.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),FALSE);
  3752.              break;
  3753.             }
  3754.            case IDC_SP_MAPTIME:
  3755.             { SpinnerOn(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3756.               SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3757.              break;
  3758.             }
  3759.            case IDC_SP_MAPDIST:
  3760.             { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3761.               SpinnerOn(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3762.              break;
  3763.             }
  3764.            case IDC_SP_TYPEMET:
  3765.               { MetaIn(po,hWnd,t);
  3766.                 po->valid=FALSE;
  3767.               if (po->ip->GetCommandMode()->ID() == CID_STDPICK)
  3768.               { if (po->creating)
  3769.                {  theCreateSSBlizMode.JumpStart(po->ip,po);
  3770.                   po->ip->SetCommandMode(&theCreateSSBlizMode);
  3771.                } else {po->ip->SetStdCommandMode(CID_OBJMOVE);}
  3772.               }
  3773.               break;
  3774.               }
  3775.            case IDC_SP_MAPCUSTOMEMIT:
  3776.            case IDC_SP_MAPCUSTOMINST:
  3777.             { MappingStuff(po->pblock,hWnd,t,FALSE);
  3778.               int dir;
  3779.               po->pblock->GetValue(PB_SPINAXISTYPE,0,dir,FOREVER);
  3780.               if (dir==1)
  3781.               { int subtree,frag,custmtl=0;
  3782.                 po->pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  3783.                 po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3784.                 po->pblock->GetValue(PB_PARTICLECLASS,0,frag,FOREVER);
  3785.                 CheckStretchBox(po->hrot,po);
  3786.               }
  3787.               break;}
  3788.            case IDC_SP_TYPEINSTANCE:
  3789.               { int custmtl,vshow,anioff;
  3790.                po->pblock->GetValue(PB_VIEWPORTSHOWS,0,vshow,FOREVER);
  3791.                 po->pblock->SetValue(PB_CUSTOMMTL,0,1);
  3792.                InstIn(po,hWnd,t);
  3793.                if (vshow>1)
  3794.                {int subtree;
  3795.                 po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3796.                 po->pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  3797.                 po->theSuprSprayDraw.t=t;
  3798.                 po->theSuprSprayDraw.anioff=anioff;
  3799.                 TimeValue aniend=GetAnimEnd();
  3800.                 int anifr;
  3801.                 anifr=aniend+GetTicksPerFrame();
  3802.                 po->theSuprSprayDraw.anifr=anifr;
  3803.                 po->GetTimes(po->times,t,anifr,anioff);
  3804.                 if (vshow==2)
  3805.                 { po->pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  3806.                    po->GetMesh(t,subtree,custmtl);
  3807.                 }
  3808.                else po->GetallBB(po->custnode,subtree,t);
  3809.                }
  3810.                 po->valid=FALSE;
  3811.               break;
  3812.               }
  3813.            case IDC_SP_AUTOCOARSE:
  3814.             { int chunky;
  3815.               po->pblock->GetValue(PB_PARTICLECLASS,0,chunky,FOREVER);
  3816.               if (chunky==METABALLS)
  3817.                 CourseCheck(po,hWnd,t);
  3818.               break;
  3819.             }
  3820.          }
  3821.          break;  
  3822.       default:
  3823.          return FALSE;
  3824.       }
  3825.    return TRUE;
  3826.    }
  3827. class BLParticleDisableDlgProc : public ParamMapUserDlgProc {
  3828.    public:
  3829.       BlizzardParticle *po;
  3830.       ICustButton *iBut;
  3831.  
  3832.       BLParticleDisableDlgProc(BlizzardParticle *p) {po=p;}
  3833.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  3834.       void Update(TimeValue t);
  3835.       void DeleteThis() {delete this;}
  3836.    };
  3837. void BLParticleDisableDlgProc::Update(TimeValue t)
  3838. {  if (!po->editOb) return;
  3839.    float width;
  3840.    po->pblock->GetValue(PB_EMITRWID,0,width,FOREVER);
  3841.    int chunky;
  3842.    po->pblock->GetValue(PB_PARTICLECLASS,0,chunky,FOREVER);
  3843.    if (chunky==METABALLS) MetaIn(po,po->hptype,t);
  3844.    else if (chunky==ISSTD) StdOn(po,po->hptype,t);
  3845.    else InstIn(po,po->hptype,t);
  3846.    if (width<0.01f)
  3847.    { iBut->Disable();
  3848.    }
  3849.    po->ShowName();
  3850. }
  3851.  
  3852. INT_PTR BLParticleDisableDlgProc::DlgProc(
  3853.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  3854. {  switch (msg) {
  3855.       case WM_INITDIALOG: {
  3856.          iBut = GetICustButton(GetDlgItem(hWnd,IDC_AP_OBJECTPICK));
  3857.          iBut->SetType(CBT_CHECK);
  3858.          iBut->SetHighlightColor(GREEN_WASH);
  3859.          Update(t);
  3860.          break;
  3861.          }
  3862.       case WM_DESTROY:
  3863.          // Release all our Custom Controls
  3864.          ReleaseICustButton(iBut);
  3865.          return FALSE;
  3866.       case WM_COMMAND:
  3867.          switch (LOWORD(wParam))
  3868.          {  case IDC_AP_OBJECTPICK:
  3869.                { po->flags=0;
  3870.                if (po->ip->GetCommandMode()->ID() == CID_STDPICK)
  3871.                { if (po->creating)
  3872.                   {  theCreateSSBlizMode.JumpStart(po->ip,po);
  3873.                      po->ip->SetCommandMode(&theCreateSSBlizMode);
  3874.                   } else {po->ip->SetStdCommandMode(CID_OBJMOVE);}
  3875.                } else
  3876.                   { po->pickCB.po = po;  
  3877.                      po->pickCB.dodist = 0;
  3878.                     po->ip->SetPickMode(&po->pickCB);
  3879.                   }
  3880.                break;
  3881.             }
  3882.          case IDC_AP_UPDATEMTL:
  3883.             { int custmtl;
  3884.               po->pblock->GetValue(PB_CUSTOMMTL2,0,custmtl,FOREVER);
  3885.               AddMtl(po,t,custmtl);
  3886.               if ((po->cnode)&&(custmtl))
  3887.               { EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPCUSTOMEMIT),FALSE);
  3888.                po->origmtl=po->cnode->GetMtl();
  3889.               }
  3890.               break;
  3891.             }
  3892.            case IDC_AP_NOANIOFF:
  3893.            case IDC_AP_ANIOFFBIRTH:
  3894.                SpinnerOff(hWnd,IDC_AP_ANIRNDFRSPIN,IDC_AP_ANIRNDFR);
  3895.                EnableWindow(GetDlgItem(hWnd,IDC_AP_ANIRNDFR_TXT),FALSE);
  3896.               break;
  3897.            case IDC_AP_ANIOFFRND:
  3898.               SpinnerOn(hWnd,IDC_AP_ANIRNDFRSPIN,IDC_AP_ANIRNDFR);
  3899.               EnableWindow(GetDlgItem(hWnd,IDC_AP_ANIRNDFR_TXT),TRUE);
  3900.               break;
  3901.            case IDC_SP_TYPEFAC:
  3902.            case IDC_SP_TYPEPIX:
  3903.             { SetMapVals(po->pblock,hWnd,t);
  3904. //            int facing;
  3905. //            po->pblock->GetValue(PB_VIEWPORTSHOWS,t,facing,FOREVER);
  3906. //            if (facing==2) po->pblock->SetValue(PB_VIEWPORTSHOWS,t,1);
  3907. //            EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),FALSE);
  3908.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),TRUE);
  3909.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),TRUE);
  3910.               po->pmapParam->Invalidate();
  3911.              break;
  3912.             }
  3913.            case IDC_SP_TYPETRI:
  3914.            case IDC_SP_TYPECUB:
  3915.            case IDC_SP_TYPESPC:
  3916.            case IDC_SP_TYPE6PNT:
  3917.            case IDC_SP_TYPESPHERE:
  3918.             { SetMapVals(po->pblock,hWnd,t);
  3919.               EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),TRUE);
  3920.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),TRUE);
  3921.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),TRUE);
  3922.              break;
  3923.             }
  3924.            case IDC_SP_TYPETET:
  3925.             { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3926.               SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3927.               EnableWindow(GetDlgItem(po->hparam,IDC_SP_VIEWDISPMESH),TRUE);
  3928.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPDIST),FALSE);
  3929.               EnableWindow(GetDlgItem(hWnd,IDC_SP_MAPTIME),FALSE);
  3930.              break;
  3931.             }
  3932.            case IDC_SP_MAPTIME:
  3933.             { SpinnerOn(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3934.               SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3935.              break;
  3936.             }
  3937.            case IDC_SP_MAPDIST:
  3938.             { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3939.               SpinnerOn(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3940.              break;
  3941.             }
  3942.            case IDC_SP_MAPPLANAR:
  3943.             { SpinnerOff(hWnd,IDC_SP_MAPTIMEVALSPIN,IDC_SP_MAPTIMEVAL);
  3944.               SpinnerOff(hWnd,IDC_SP_MAPDISTVALSPIN,IDC_SP_MAPDISTVAL);
  3945.              break;
  3946.             }
  3947.             case IDC_SP_TYPESTD:
  3948.             { StdOn(po,hWnd,t);
  3949.               po->valid=FALSE;
  3950.               if (po->ip->GetCommandMode()->ID() == CID_STDPICK)
  3951.               { if (po->creating)
  3952.                {  theCreateSSBlizMode.JumpStart(po->ip,po);
  3953.                   po->ip->SetCommandMode(&theCreateSSBlizMode);
  3954.                } else {po->ip->SetStdCommandMode(CID_OBJMOVE);}
  3955.               }
  3956.              break;
  3957.             }
  3958.            case IDC_SP_TYPEMET:
  3959.               { MetaIn(po,hWnd,t);
  3960.                 po->valid=FALSE;
  3961.               if (po->ip->GetCommandMode()->ID() == CID_STDPICK)
  3962.               { if (po->creating)
  3963.                {  theCreateSSBlizMode.JumpStart(po->ip,po);
  3964.                   po->ip->SetCommandMode(&theCreateSSBlizMode);
  3965.                } else {po->ip->SetStdCommandMode(CID_OBJMOVE);}
  3966.               }
  3967.               break;
  3968.               }
  3969.            case IDC_SP_MAPCUSTOMEMIT:
  3970.            case IDC_SP_MAPCUSTOMINST:
  3971.               MappingStuff(po->pblock,hWnd,t,TRUE);
  3972.               break;
  3973.            case IDC_SP_TYPEINSTANCE:
  3974.               { int custmtl,vshow;
  3975.                  po->pblock->SetValue(PB_CUSTOMMTL2,0,1);
  3976.                 InstIn(po,hWnd,t);
  3977.                po->pblock->GetValue(PB_VIEWPORTSHOWS,0,vshow,FOREVER);
  3978.                if (vshow>1)
  3979.                {int subtree,anioff;
  3980.                 po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  3981.                 po->pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  3982.                 po->theSuprSprayDraw.t=t;
  3983.                 po->theSuprSprayDraw.anioff=anioff;
  3984.                 TimeValue aniend=GetAnimEnd();
  3985.                 int anifr;
  3986.                 anifr=aniend+GetTicksPerFrame();
  3987.                 po->theSuprSprayDraw.anifr=anifr;
  3988.                 po->GetTimes(po->times,t,anifr,anioff);
  3989.                 if (vshow==2)
  3990.                 { po->pblock->GetValue(PB_CUSTOMMTL2,0,custmtl,FOREVER);
  3991.                    po->GetMesh(t,subtree,custmtl);
  3992.                 }
  3993.                else po->GetallBB(po->custnode,subtree,t);
  3994.                }
  3995.                 po->valid=FALSE;
  3996.               break;
  3997.               }
  3998.            case IDC_SP_AUTOCOARSE:
  3999.             { int chunky;
  4000.               po->pblock->GetValue(PB_PARTICLECLASS,0,chunky,FOREVER);
  4001.               if (chunky==METABALLS)
  4002.                 CourseCheck(po,hWnd,t);
  4003.               break;
  4004.             }
  4005.          }
  4006.          break;  
  4007.       default:
  4008.          return FALSE;
  4009.       }
  4010.    return TRUE;
  4011.    }
  4012.  
  4013. void CommonParticle::GetFilename(TCHAR *filename)
  4014. {   _tcscpy(filename,ip->GetDir(APP_PLUGCFG_DIR));
  4015.   int len= static_cast<int>(_tcslen(filename)); // SR DCAST64: Downcast to 2G limit.
  4016.   if (len)
  4017.   {  if (filename[len-1]!=_T('\\'))
  4018.         _tcscat(filename,_T("\\"));
  4019.   }
  4020.   if (ClassID()==BLIZZARD_CLASS_ID)
  4021.     _tcscat(filename,GetString(IDS_AP_BLIZZARDCST));
  4022.   else  _tcscat(filename,GetString(IDS_AP_SSPRAYCST));
  4023. }
  4024.  
  4025. void CommonParticle::SetupTargetList()    
  4026.    {TCHAR filename[MAX_PATH];
  4027.      FILE *f;
  4028.     int vers,i,Namelen,osize;
  4029.    custsettings=i=0; // LAM - 6/9/02 - initialize i so if fileok == false, will display error in onerr.
  4030.     GetFilename(filename);
  4031.    BOOL fileok=TRUE;
  4032.    if ((f = _tfopen(filename, _T("rb"))) == NULL) return;
  4033.    if((ReadInt(&custsettings,f))&&(ReadInt(&vers,f))&&(ReadInt(&osize,f))&&(ReadInt(&Namelen,f)))
  4034.    {if ( ((Namelen!=NLEN)&& (fileok=GenNewNameLen(size,custsettings,f,filename,CURRENT_VERSION)) == TRUE)||
  4035.       ((vers!=CURRENT_VERSION)&&(fileok=GenNewSaveFile(osize,size,custsettings,f,filename,CURRENT_VERSION)) == TRUE))
  4036.       { fileok=((ReadInt(&custsettings,f))&&(ReadInt(&vers,f))&&(ReadInt(&osize,f))&&(ReadInt(&Namelen,f)));
  4037.       }
  4038.    if (fileok&&(vers==CURRENT_VERSION))
  4039.    { NameLst=new AName[custsettings];
  4040.      for (i=0;i<custsettings;i++)
  4041.      if (fread(NameLst[i],NLEN,1,f)==1)
  4042.        fseek(f,size,SEEK_CUR);
  4043.      else goto onerr;
  4044.    }
  4045.    }
  4046.    onerr:if (i<custsettings)
  4047.    { custsettings=0;
  4048.    MessageBox (NULL,GetString(IDS_RB_BADFILE),
  4049.             "", MB_ICONINFORMATION);
  4050.    }
  4051.    if (fileok) fclose(f);
  4052.    UpdatePresetListBox(GetDlgItem(hParams2, IDC_SP_SETLIST), custsettings, NameLst);
  4053.    }
  4054. int CommonParticle::RemSettings(int overwrite,TCHAR *newname)
  4055. { TCHAR filename[MAX_PATH];
  4056.   FILE *f;
  4057.   long startpt;
  4058.   int vers,newsets,baselen=size+NLEN;
  4059.   GetFilename(filename);
  4060.   vers=CURRENT_VERSION;
  4061.   newsets=custsettings-1;
  4062.   if ((f = _tfopen(filename,_T("r+b"))) == NULL)
  4063.   { MessageBox(NULL,GetString(IDS_AP_WRITEPRO),"", MB_ICONINFORMATION);
  4064.    return 0;
  4065.   }
  4066.   if (custsettings==1)
  4067.   {fclose(f);remove(filename);custsettings=0;
  4068.     delete[] NameLst;NameLst=NULL;
  4069.     SendMessage(GetDlgItem(hParams2,IDC_SP_SETLIST),LB_RESETCONTENT,0,0);
  4070.    return (1);}
  4071.  if (!WriteInt(&newsets,f)) {fclose(f);return 0;}
  4072.   startpt=overwrite*(baselen)+HLEN;
  4073.   fseek(f,startpt,SEEK_SET);
  4074.   int i;
  4075.   BYTE *buf;
  4076.   buf=new BYTE[baselen];
  4077.   assert(buf);
  4078.   long cpos=startpt;
  4079.   for (i=overwrite+1;i<custsettings;i++)
  4080.   {   fseek(f,cpos+baselen,SEEK_SET);
  4081.    if (fread(buf,baselen,1,f)!=1) {delete[] buf;fclose(f);return 0;}
  4082.    fseek(f,cpos,SEEK_SET);
  4083.    if (fwrite(buf,baselen,1,f)!=1) {delete[] buf;fclose(f);return 0;}
  4084.    cpos+=baselen;
  4085.   }
  4086.   delete[] buf;
  4087.   _chsize(_fileno(f),ftell(f));
  4088.   fclose(f);                          
  4089.   AName *Tmp=new AName[custsettings-1];
  4090.   int newi=0;
  4091.   for (i=0;i<custsettings;i++)
  4092.   { if (i!=overwrite)
  4093.       _tcscpy(Tmp[newi++],NameLst[i]);}
  4094.   delete []NameLst;NameLst=Tmp;
  4095.   custsettings--;
  4096.   UpdatePresetListBox(GetDlgItem(hParams2, IDC_SP_SETLIST), custsettings, NameLst);
  4097.   return(1);
  4098. }
  4099. int CommonParticle::SaveSettings(int overwrite,TCHAR *newname)
  4100. { TCHAR filename[MAX_PATH];
  4101.   FILE *f;
  4102.   int vers,newsets,Namelen=NLEN;
  4103.  
  4104.   if ((overwrite>-1)&&(MessageBox (NULL,GetString(IDS_AP_SETEXISTS),GetString(IDS_AP_WARNING), MB_ICONQUESTION | MB_YESNO ) == IDNO))
  4105.     return 0;
  4106.   GetFilename(filename);
  4107.   vers=CURRENT_VERSION;
  4108.   newsets=custsettings+1;
  4109.   if ((f = _tfopen(filename,(custsettings==0?_T("wb"):_T("r+b")))) == NULL)
  4110.   { MessageBox(NULL,GetString(IDS_AP_WRITEPRO),"", MB_ICONINFORMATION);
  4111.    return 0;
  4112.   }
  4113.  // longest one
  4114.   ParamBlockDescID *descVer=((ClassID()==BLIZZARD_CLASS_ID)?BdescVer6:spdescVer6);
  4115.   int plength=((ClassID()==BLIZZARD_CLASS_ID)?PBLOCK_LENGTH_BLIZZARD:PBLOCK_LENGTH_SUPRSPRAY);
  4116.   if (custsettings==0)
  4117.   { if (!(WriteInt(&newsets,f)&&WriteInt(&vers,f)&&WriteInt(&size,f)&&WriteInt(&Namelen,f))) goto errend;
  4118.   }
  4119.   else
  4120.   { if (overwrite>=0)
  4121.     { overwrite=overwrite*(size+NLEN)+HLEN;
  4122.       fseek(f,overwrite,SEEK_SET); }
  4123.     else
  4124.    { if (!WriteInt(&newsets,f)) goto errend;
  4125.      fseek(f,0,SEEK_END);
  4126.    }
  4127.   }    
  4128.   int ival,i;
  4129.   float fval;
  4130.   if (fwrite(newname,1,NLEN,f)!=NLEN) goto errend;
  4131.   for (i=0;i<plength;i++)
  4132.   {   if (descVer[i].type==TYPE_INT)
  4133.     { pblock->GetValue(i,0,ival,FOREVER);
  4134.       if (fwrite(&ival,isize,1,f)!=1) goto errend;
  4135.    }
  4136.     else
  4137.     { pblock->GetValue(i,0,fval,FOREVER);
  4138.       if (fwrite(&fval,fsize,1,f)!=1) goto errend;
  4139.    }
  4140.   }
  4141.   fclose(f);
  4142.   if (overwrite<0)
  4143.   { AName *Tmp=new AName[custsettings+1];
  4144.     memcpy(Tmp,NameLst,sizeof(AName)*custsettings);
  4145.    delete []NameLst;NameLst=Tmp;
  4146.     _tcscpy(NameLst[custsettings],newname);
  4147.    custsettings++;
  4148.    UpdatePresetListBox(GetDlgItem(hParams2, IDC_SP_SETLIST), custsettings, NameLst);
  4149.   }  
  4150.   return(1);
  4151. errend: fclose(f);return(0);
  4152. }
  4153. int CommonParticle::GetSettings(int setnum,TCHAR *newname)
  4154. { TCHAR filename[MAX_PATH];
  4155.   FILE *f;
  4156.   GetFilename(filename);
  4157.   if ((f = _tfopen(filename,_T("rb"))) == NULL) return 0;
  4158.   { setnum=setnum*(size+NLEN)+HLEN;
  4159.     fseek(f,setnum,SEEK_SET);
  4160.   }    
  4161.   int ival,i;
  4162.   float fval;
  4163.   // longest one
  4164.   ParamBlockDescID *descVer=((ClassID()==BLIZZARD_CLASS_ID)?BdescVer6:spdescVer6);
  4165.  int plength=((ClassID()==BLIZZARD_CLASS_ID)?PBLOCK_LENGTH_BLIZZARD:PBLOCK_LENGTH_SUPRSPRAY);
  4166.   if (fread(newname,1,NLEN,f)!=NLEN) goto errend;
  4167.   for (i=0;i<plength;i++)
  4168.   {   if (descVer[i].type==TYPE_INT)
  4169.     { if (fread(&ival,isize,1,f)!=1) goto errend;
  4170.      pblock->SetValue(i,0,ival);
  4171.    }
  4172.     else
  4173.     { if (fread(&fval,fsize,1,f)!=1) goto errend;
  4174. //   if (i!=PB_EMITRWID)
  4175.         pblock->SetValue(i,0,fval);
  4176.    }
  4177.   }
  4178.   fclose(f);
  4179.   InvalidateUI();                  
  4180.   return(1);
  4181.   errend: fclose(f);return(0);
  4182. }
  4183. static INT_PTR CALLBACK CustomSettingParamDlgProc(
  4184.       HWND hWnd, UINT message, WPARAM wParam, LPARAM lParam)
  4185. { TCHAR newname[NLEN];
  4186.   int i = 0, save = 0;
  4187.   CommonParticle *po = DLGetWindowLongPtr<CommonParticle*>(hWnd);
  4188.   if (!po && message!=WM_INITDIALOG) return FALSE;
  4189.  
  4190.   switch (message) {
  4191.       case WM_INITDIALOG: {
  4192.          po = (SuprSprayParticle*)lParam;
  4193.          DLSetWindowLongPtr(hWnd, lParam);
  4194.          po->custCtrlEdit = GetICustEdit(GetDlgItem(hWnd,IDC_SP_SETEDIT));
  4195.          po->custCtrlEdit->SetText(_T(""));
  4196.          po->hParams2 = hWnd;
  4197.          po->SetupTargetList();
  4198.          break;
  4199.          }
  4200.       case WM_COMMAND:
  4201.          { switch(LOWORD(wParam)) {
  4202.             case IDC_SP_SETLIST:  
  4203.                if (HIWORD(wParam)==LBN_DBLCLK)
  4204.                  goto doload;
  4205.                break;
  4206.             case IDC_SP_DELETE:  
  4207.                i = SendMessage(GetDlgItem(po->hParams2,IDC_SP_SETLIST),
  4208.                      LB_GETCURSEL,0,0);
  4209.                   if ((i>-1)&&(po->custsettings>0))
  4210.                   { po->custCtrlEdit->GetText(newname,NLEN);
  4211.                    if (_tcscmp(newname,po->NameLst[i])==0)
  4212.                      po->custCtrlEdit->SetText(_T(""));
  4213.                     po->RemSettings(i,po->NameLst[i]);
  4214.                   }
  4215.                break;
  4216.             case IDC_SP_SAVE:
  4217.                save=1;
  4218.             case IDC_SP_LOAD:
  4219.                doload:
  4220.                if (!save)
  4221.                { i = SendMessage(GetDlgItem(po->hParams2,IDC_SP_SETLIST),
  4222.                      LB_GETCURSEL,0,0);
  4223.                   if ((i>-1)&&(po->custsettings>0))
  4224.                     po->custCtrlEdit->SetText(po->NameLst[i]);
  4225.                }
  4226.                 po->custCtrlEdit->GetText(newname,NLEN);
  4227.                if (save)
  4228.                {int tstblk=0,tstlen=static_cast<int>(_tcslen(newname)); // SR DCAST64: Downcast to 2G limit.
  4229.                  while ((tstblk<tstlen)&&(newname[tstblk]==' ')) tstblk++;
  4230.                  if (tstblk>=tstlen)
  4231.                   MessageBox (NULL,GetString(IDS_RB_NONAME),
  4232.             "", MB_ICONINFORMATION);
  4233.                  else
  4234.                  { i=0;
  4235.                    while ((i<po->custsettings)&&(_tcscmp(newname,po->NameLst[i])))
  4236.                     i++;
  4237.                   if (i>=po->custsettings) i=-1;
  4238.                    po->SaveSettings(i,newname);
  4239.                  }
  4240.                }
  4241.                else if ((i>-1)&&(i<po->custsettings))
  4242.                { po->GetSettings(i,newname);
  4243.                  int stype;
  4244.                  po->pblock->GetValue(PB_SPAWNTYPE,0,stype,FOREVER);
  4245.                  int chunky;
  4246.                    po->pblock->GetValue(PB_PARTICLECLASS,0,chunky,FOREVER);
  4247.                  if (chunky==METABALLS) MetaIn(po,po->hptype,po->ip->GetTime());
  4248.                   else
  4249.                  {// AllSpawnBad(po->spawn,stype,TRUE);
  4250.                   int ison; po->pblock->GetValue((po->ClassID()==BLIZZARD_CLASS_ID?PB_BLIPCOLLIDE_ON:PB_IPCOLLIDE_ON),0,ison,FOREVER);
  4251.                   if (ison) stype=0;
  4252.                   SpawnStuff(po->spawn,stype);
  4253.                   if (chunky==ISSTD) StdOn(po,po->hptype,po->ip->GetTime());
  4254.                    else InstIn(po,po->hptype,po->ip->GetTime());
  4255.                  }
  4256.              if (chunky==INSTGEOM)
  4257.              { CheckSpawnButtons(po->pblock,po->spawn,po->pickCB.repi);
  4258.                int onscreen;
  4259.                po->pblock->GetValue(PB_VIEWPORTSHOWS,0,onscreen,FOREVER);
  4260.                if (onscreen>1)
  4261.                {int subtree,anioff;
  4262.                 po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  4263.                 po->pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  4264.                TimeValue t=po->ip->GetTime();
  4265.                 po->theSuprSprayDraw.t=t;
  4266.                 po->theSuprSprayDraw.anioff=anioff;
  4267.                 TimeValue aniend=GetAnimEnd();
  4268.                 int anifr,custmtl;
  4269.                 anifr=aniend+GetTicksPerFrame();
  4270.                 po->theSuprSprayDraw.anifr=anifr;
  4271.                 po->GetTimes(po->times,t,anifr,anioff);
  4272.                 po->pblock->GetValue((po->ClassID()==BLIZZARD_CLASS_ID?PB_CUSTOMMTL2:PB_CUSTOMMTL),0,custmtl,FOREVER);
  4273.                 if (onscreen==2)
  4274.                    po->GetMesh(po->ip->GetTime(),subtree,custmtl);
  4275.                   else po->GetallBB(po->custnode,subtree,po->ip->GetTime());
  4276.                }
  4277.              }
  4278.              else ObjectMutQueOff(po->spawn);
  4279.                  if (stype==EMIT)
  4280.                  {   SpinnerOff(po->spawn,IDC_AP_MAXSPAWNGENSSPIN,IDC_AP_MAXSPAWNGENS);
  4281.                   EnableWindow(GetDlgItem(hWnd,IDC_AP_MAXSPAWNDIEAFTER_TXT),FALSE);
  4282.                  }
  4283.                  po->pmapParam->Invalidate();
  4284.                  po->ip->RedrawViews(po->ip->GetTime());
  4285.                }
  4286.                else MessageBox (NULL,GetString(IDS_RB_BADNAME),
  4287.             "", MB_ICONINFORMATION);
  4288.                break;
  4289.             }
  4290.          break;
  4291.          }
  4292.  
  4293.       case WM_DESTROY:
  4294.          // Release all our Custom Controls
  4295.          ReleaseICustEdit(po->custCtrlEdit);
  4296.          if (po->NameLst) {delete []po->NameLst;po->NameLst=NULL;}
  4297.          return FALSE;
  4298.       case WM_LBUTTONDOWN:
  4299.       case WM_LBUTTONUP:
  4300.       case WM_MOUSEMOVE:
  4301.          po->ip->RollupMouseMessage(hWnd,message,wParam,lParam);
  4302.          return FALSE;
  4303.      
  4304.       default: return FALSE;    
  4305.       }
  4306.    return TRUE;
  4307.    }  
  4308.  
  4309. class ComParticleSpawnDlgProc : public ParamMapUserDlgProc {
  4310.    public:
  4311.       CommonParticle *po;
  4312.       ICustButton *iBut,*iButrep;
  4313.  
  4314.       ComParticleSpawnDlgProc(CommonParticle *p) {po=p;}
  4315.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  4316.       void Update(TimeValue t);
  4317.       void DeleteThis() {delete this;}
  4318.    };
  4319.  
  4320. void ComParticleSpawnDlgProc::Update(TimeValue t)
  4321. { if (!po->editOb) return;
  4322.    po->SetUpList();
  4323.    float width;
  4324.    po->pblock->GetValue(PB_EMITRWID,0,width,FOREVER);
  4325.    if (width<0.01f) iBut->Disable();
  4326.    po->SetUpLifeList();
  4327.    po->pickCB.repi= SendMessage(GetDlgItem(po->spawn,IDC_AP_OBJECTQUEUE),
  4328.                LB_GETCURSEL,0,0);
  4329.    if (width<0.01f) iButrep->Disable();
  4330.    else
  4331.    { if (po->pickCB.repi<0) iButrep->Disable(); else iButrep->Enable();
  4332.    }
  4333.    int chunky,stype;
  4334.    po->pblock->GetValue(PB_PARTICLECLASS,0,chunky,FOREVER);
  4335.    po->pblock->GetValue(PB_SPAWNTYPE,0,stype,FOREVER);
  4336. // AllSpawnBad(po->spawn,stype,chunky!=METABALLS);
  4337.    int ison; po->pblock->GetValue((po->ClassID()==BLIZZARD_CLASS_ID?PB_BLIPCOLLIDE_ON:PB_IPCOLLIDE_ON),t,ison,FOREVER);
  4338.    if (ison) stype=0;
  4339.     SpawnStuff(po->spawn,stype);
  4340.    if (chunky==INSTGEOM)
  4341.           CheckSpawnButtons(po->pblock,po->spawn,po->pickCB.repi);
  4342.    else
  4343.    { ObjectMutQueOff(po->spawn);
  4344.      CheckLifeButtons(stype,po->spawn);
  4345.    }
  4346.    if (stype==EMIT)
  4347.    {  SpinnerOff(po->spawn,IDC_AP_MAXSPAWNGENSSPIN,IDC_AP_MAXSPAWNGENS);
  4348.       EnableWindow(GetDlgItem(po->spawn,IDC_AP_MAXSPAWNDIEAFTER_TXT),FALSE);
  4349.    }
  4350. }
  4351.  
  4352. INT_PTR ComParticleSpawnDlgProc::DlgProc(
  4353.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  4354. { int dtype=2,stype,rep;  
  4355.    switch (msg) {
  4356.       case WM_INITDIALOG:
  4357.       { iBut = GetICustButton(GetDlgItem(hWnd,IDC_AP_OBJECTQUEUEPICK));
  4358.         iBut->SetType(CBT_CHECK);
  4359.         iBut->SetHighlightColor(GREEN_WASH);
  4360.         iButrep = GetICustButton(GetDlgItem(hWnd,IDC_AP_OBJQUEUEREPLACE));
  4361.         iButrep->SetType(CBT_CHECK);
  4362.         iButrep->SetHighlightColor(GREEN_WASH);
  4363.         Update(t);
  4364.         break;
  4365.       }
  4366.       case WM_DESTROY:
  4367.          // Release all our Custom Controls
  4368.          ReleaseICustButton(iBut);
  4369.          ReleaseICustButton(iButrep);
  4370.          return FALSE;
  4371.       case WM_COMMAND:
  4372.          switch (LOWORD(wParam))
  4373.          { case IDC_AP_NOSPAWN:stype=0;goto spawnradio;
  4374.            case IDC_AP_COLLIDEDIE:
  4375.               stype=1;goto spawnradio;
  4376.            case IDC_AP_SPAWNTRAILS:stype=EMIT;goto spawnradio;
  4377.            case IDC_AP_COLLIDESPAWN:
  4378.            case IDC_AP_DEATHSPAWN: stype=2;
  4379.          spawnradio:
  4380.             int chunky;
  4381.          po->pblock->GetValue(PB_PARTICLECLASS,0,chunky,FOREVER);
  4382. //          AllSpawnBad(po->spawn,stype,chunky!=METABALLS);
  4383.             int ison; po->pblock->GetValue((po->ClassID()==BLIZZARD_CLASS_ID?PB_BLIPCOLLIDE_ON:PB_IPCOLLIDE_ON),t,ison,FOREVER);
  4384.             if (ison) stype=0;
  4385.             SpawnStuff(po->spawn,stype);
  4386.              if (chunky==INSTGEOM)
  4387.                 CheckSpawnButtons(po->pblock,hWnd,po->pickCB.repi);
  4388.              else
  4389.              { ObjectMutQueOff(po->spawn);
  4390.                CheckLifeButtons(stype,po->spawn);
  4391.              }
  4392.              if (stype==EMIT)
  4393.              { SpinnerOff(po->spawn,IDC_AP_MAXSPAWNGENSSPIN,IDC_AP_MAXSPAWNGENS);
  4394.                EnableWindow(GetDlgItem(hWnd,IDC_AP_MAXSPAWNDIEAFTER_TXT),FALSE);
  4395.              }
  4396.             break;
  4397.            case IDC_AP_OBJECTQUEUE:
  4398.             { po->pickCB.repi= SendMessage(GetDlgItem(hWnd,IDC_AP_OBJECTQUEUE),
  4399.                      LB_GETCURSEL,0,0);
  4400.              TurnButton(hWnd,IDC_AP_OBJQUEUEREPLACE,po->pickCB.repi>-1);
  4401.              TurnButton(hWnd,IDC_AP_OBJQUEUEDELETE,po->pickCB.repi>-1);
  4402.             break;
  4403.             }
  4404.             case IDC_AP_OBJECTQUEUEPICK:
  4405.                dtype=1;goto dopick;
  4406.             case IDC_AP_OBJQUEUEREPLACE:
  4407.               dtype=2;
  4408.               dopick:
  4409.                {if (po->ip->GetCommandMode()->ID() == CID_STDPICK)
  4410.                { if (po->creating)
  4411.                   {  theCreateSSBlizMode.JumpStart(po->ip,po);
  4412.                      po->ip->SetCommandMode(&theCreateSSBlizMode);
  4413.                   } else {po->ip->SetStdCommandMode(CID_OBJMOVE);}
  4414.                } else
  4415.                   { po->pickCB.po = po;
  4416.                      po->pickCB.dodist=dtype;
  4417.                     po->ip->SetPickMode(&po->pickCB);
  4418.                   }
  4419.                break;
  4420.             }
  4421.             case IDC_AP_OBJQUEUEDELETE:
  4422.             {  int i = SendMessage(GetDlgItem(hWnd,IDC_AP_OBJECTQUEUE),
  4423.                      LB_GETCURSEL,0,0);
  4424.                   TurnButton(hWnd,IDC_AP_OBJQUEUEREPLACE,0);
  4425.                   TurnButton(hWnd,IDC_AP_OBJQUEUEDELETE,0);
  4426.                if ((po->nlist.Count()>0)&&(i>-1))
  4427.                {  theHold.Begin();
  4428.                   po->DeleteFromList(i,0);
  4429.                   theHold.Accept(GetString(IDS_AP_OBJDEL));
  4430.                }
  4431.                po->valid=FALSE;
  4432.                po->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  4433.             break;
  4434.             }
  4435.             case IDC_AP_LIFEQUEUEDEL:
  4436.             {  int i = SendMessage(GetDlgItem(hWnd,IDC_AP_LIFEQUEUE),
  4437.                      LB_GETCURSEL,0,0);
  4438.                int Lcnt=po->llist.Count();
  4439.                if ((Lcnt>0)&&(i>-1)&&(i<Lcnt))
  4440.                {  theHold.Begin();
  4441.                   theHold.Put(new LifeListRestore(po));
  4442.                   po->DeleteFromLifeList(i);
  4443.                   TurnButton(hWnd,IDC_AP_LIFEQUEUEREPL,0);
  4444.                   TurnButton(hWnd,IDC_AP_LIFEQUEUEDEL,0);
  4445.                   theHold.Accept(GetString(IDS_AP_LIFEDEL));
  4446.                }
  4447.                po->valid=FALSE;
  4448.                po->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  4449.                break;
  4450.             }
  4451.             case IDC_AP_LIFEQUEUEADD:
  4452.             {   int i;
  4453.                po->pblock->GetValue(PB_SPAWNLIFEVLUE,t,i,FOREVER);
  4454.                theHold.Begin();
  4455.                theHold.Put(new LifeListRestore(po));
  4456.                po->AddToLifeList(i);
  4457.                TurnButton(hWnd,IDC_AP_LIFEQUEUEREPL,0);
  4458.                TurnButton(hWnd,IDC_AP_LIFEQUEUEDEL,0);
  4459.                theHold.Accept(GetString(IDS_AP_LIFEADD));
  4460.                po->valid=FALSE;
  4461.                po->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  4462.                break;
  4463.             }
  4464.             case IDC_AP_LIFEQUEUE:
  4465.             { rep = SendMessage(GetDlgItem(hWnd,IDC_AP_LIFEQUEUE),LB_GETCURSEL,0,0);
  4466.               TurnButton(hWnd,IDC_AP_LIFEQUEUEREPL,rep>-1);
  4467.               TurnButton(hWnd,IDC_AP_LIFEQUEUEDEL,rep>-1);
  4468.                po->valid=FALSE;
  4469.                po->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  4470.               break;
  4471.             }
  4472.             case IDC_AP_LIFEQUEUEREPL:
  4473.             { int i;
  4474.              rep = SendMessage(GetDlgItem(hWnd,IDC_AP_LIFEQUEUE),
  4475.                      LB_GETCURSEL,0,0);
  4476.               if (rep>-1)
  4477.               {   po->pblock->GetValue(PB_SPAWNLIFEVLUE,t,i,FOREVER);
  4478.                theHold.Begin();
  4479.                theHold.Put(new LifeListRestore(po));
  4480.                po->llist[rep]=i;
  4481.                po->SetUpLifeList();
  4482.                TurnButton(hWnd,IDC_AP_LIFEQUEUEREPL,0);
  4483.                TurnButton(hWnd,IDC_AP_LIFEQUEUEDEL,0);
  4484.                theHold.Accept(GetString(IDS_AP_LIFEREP));
  4485.                po->valid=FALSE;
  4486.                po->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  4487.               }
  4488.                break;
  4489.             }
  4490.       }
  4491.       default:
  4492.          return FALSE;
  4493.    }
  4494.    return TRUE;
  4495. }
  4496. class BParticleSpinDlgProc : public ParamMapUserDlgProc {
  4497.    public:
  4498.       CommonParticle *po;
  4499.  
  4500.       BParticleSpinDlgProc(CommonParticle *p) {po=p;}
  4501.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  4502.       void Update(TimeValue t);
  4503.       void DeleteThis() {delete this;}
  4504.    };
  4505.  
  4506. void BParticleSpinDlgProc::Update(TimeValue t)
  4507. {   int axis;
  4508.    po->pblock->GetValue(PB_SPINAXISTYPE,t,axis,FOREVER);
  4509.    SpinStuff(po->hrot,axis==1,TRUE);
  4510.    int ison; po->pblock->GetValue(PB_BLIPCOLLIDE_ON,t,ison,FOREVER);
  4511.    int stype; po->pblock->GetValue(PB_SPAWNTYPE,t,stype,FOREVER);
  4512.    IPCControls(po->hrot,po->spawn,stype,ison);
  4513. }
  4514.  
  4515. INT_PTR BParticleSpinDlgProc::DlgProc(
  4516.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  4517. {  switch (msg) {
  4518.       case WM_INITDIALOG:
  4519.       { Update(t);
  4520.         break;
  4521.       }
  4522.       case WM_COMMAND:
  4523.          switch (LOWORD(wParam))
  4524.          { case IDC_AP_PARTICLEDIRRND:
  4525.            { SpinStuff(hWnd,FALSE,TRUE);
  4526.            }
  4527.            break;
  4528.            case IDC_AP_PARTICLEDIRUSER:
  4529.                SpinStuff(hWnd,TRUE,TRUE);
  4530.             break;
  4531.            case IDC_INTERP_BOUNCEON:
  4532.             {  int ison; po->pblock->GetValue(PB_BLIPCOLLIDE_ON,t,ison,FOREVER);
  4533.                int stype; po->pblock->GetValue(PB_SPAWNTYPE,t,stype,FOREVER);
  4534.                IPCControls(hWnd,po->spawn,stype,ison);
  4535.             }
  4536.             break;
  4537.          }
  4538.       default:
  4539.          return FALSE;
  4540.    }
  4541.    return TRUE;
  4542. }
  4543. class SSParticleSpinDlgProc : public ParamMapUserDlgProc {
  4544.    public:
  4545.       CommonParticle *po;
  4546.  
  4547.       SSParticleSpinDlgProc(CommonParticle *p) {po=p;}
  4548.       INT_PTR DlgProc(TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
  4549.       void Update(TimeValue t);
  4550.       void DeleteThis() {delete this;}
  4551.    };
  4552.  
  4553. void SSParticleSpinDlgProc::Update(TimeValue t)
  4554. {   int axis;
  4555.    po->pblock->GetValue(PB_SPINAXISTYPE,t,axis,FOREVER);
  4556.    StretchStuff(axis,TRUE,po->hrot,po);
  4557.    int ison; po->pblock->GetValue(PB_IPCOLLIDE_ON,t,ison,FOREVER);
  4558.    int stype; po->pblock->GetValue(PB_SPAWNTYPE,t,stype,FOREVER);
  4559.    IPCControls(po->hrot,po->spawn,stype,ison);
  4560. }
  4561.  
  4562. INT_PTR SSParticleSpinDlgProc::DlgProc(
  4563.       TimeValue t,IParamMap *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
  4564. {  switch (msg) {
  4565.       case WM_INITDIALOG:
  4566.       { Update(t);
  4567.          break;
  4568.       }
  4569.       case WM_COMMAND:
  4570.          switch (LOWORD(wParam))
  4571.          { case IDC_AP_PARTICLEDIRTRAVL:
  4572.              StretchStuff(1,TRUE,hWnd,po);
  4573.            break;
  4574.            case IDC_AP_PARTICLEDIRRND:
  4575.             StretchStuff(0,TRUE,hWnd,po);
  4576.            break;
  4577.            case IDC_AP_PARTICLEDIRUSER:
  4578.             StretchStuff(2,TRUE,hWnd,po);
  4579.             break;
  4580.            case IDC_INTERP_BOUNCEON:
  4581.             {  int ison; po->pblock->GetValue(PB_IPCOLLIDE_ON,t,ison,FOREVER);
  4582.                int stype; po->pblock->GetValue(PB_SPAWNTYPE,t,stype,FOREVER);
  4583.                IPCControls(hWnd,po->spawn,stype,ison);
  4584.             }
  4585.             break;
  4586.          }
  4587.       default:
  4588.          return FALSE;
  4589.    }
  4590.    return TRUE;
  4591. }
  4592.  
  4593. void CommonParticle::ResetSystem(TimeValue t,BOOL full)
  4594. {  lc.lastmin=-1;lc.lastcollide=-1;
  4595.    rcounter=0;
  4596.    vcounter=0;
  4597.    if (full)
  4598.    { tvalid = t;
  4599.      valid  = TRUE;
  4600.    }
  4601. }
  4602.  
  4603. //--- SuprSprayParticle Methods--------------------------------------------
  4604.  
  4605. SuprSprayParticle::SuprSprayParticle()
  4606. {int FToTick=(int)((float)TIME_TICKSPERSEC/(float)GetFrameRate());
  4607.      int tpf=GetTicksPerFrame();
  4608.  
  4609.    sdata=NULL;
  4610.    cnode=NULL;
  4611.    custnode=NULL;
  4612.    cmesh=NULL;
  4613.    dispmesh=NULL;
  4614.    origmtl=NULL;
  4615.  
  4616.    ReplaceReference(PBLK, CreateParameterBlock(spdescVer6, PBLOCK_LENGTH_SUPRSPRAY, CURRENT_VERSION));
  4617.    pblock->SetValue(PB_SPEED,0,10.0f);
  4618.    pblock->SetValue(PB_SPEEDVAR,0,0.0f);
  4619.    pblock->SetValue(PB_OFFAXIS,0,0.0f);
  4620.    pblock->SetValue(PB_AXISSPREAD,0,0.0f);
  4621.    pblock->SetValue(PB_OFFPLANE,0,0.0f);
  4622.    pblock->SetValue(PB_PLANESPREAD,0,0.0f);
  4623.    pblock->SetValue(PB_PBIRTHRATE,0,10);
  4624.    pblock->SetValue(PB_PTOTALNUMBER,0,100);
  4625.    pblock->SetValue(PB_BIRTHMETHOD,0,0);
  4626.    pblock->SetValue(PB_DISPLAYPORTION,0,0.1f);
  4627.    pblock->SetValue(PB_EMITSTART,0,TimeValue(0));
  4628.    pblock->SetValue(PB_EMITSTOP,0,(TimeValue)30*FToTick);// correct constant?
  4629.    pblock->SetValue(PB_DISPUNTIL,0,100*FToTick);// correct constant?
  4630.    pblock->SetValue(PB_LIFE,0,30*FToTick);// correct constant?
  4631.    pblock->SetValue(PB_LIFEVAR,0,0.0f);
  4632.    pblock->SetValue(PB_SUBFRAMEMOVE,0,1);
  4633.    pblock->SetValue(PB_SUBFRAMETIME,0,1);
  4634.    pblock->SetValue(PB_SUBFRAMEROT,0,0);
  4635.    pblock->SetValue(PB_SIZE,0,1.0f);
  4636.    pblock->SetValue(PB_SIZEVAR,0,0.0f);
  4637.    pblock->SetValue(PB_GROWTIME,0,10*FToTick);
  4638.    pblock->SetValue(PB_FADETIME,0,10*FToTick);
  4639.    pblock->SetValue(PB_RNDSEED,0,12345);
  4640.  
  4641.    pblock->SetValue(PB_PARTICLETYPE,0,0);
  4642.    pblock->SetValue(PB_METATENSION,0,1.0f);
  4643.    pblock->SetValue(PB_METATENSIONVAR,0,0.0f);
  4644.    pblock->SetValue(PB_METAAUTOCOARSE,0,1);
  4645.    pblock->SetValue(PB_METACOURSE,0,0.5f);
  4646.    pblock->SetValue(PB_VIEWPORTSHOWS,0,1);
  4647.    pblock->SetValue(PB_MAPPINGTYPE,0,0);
  4648.    pblock->SetValue(PB_MAPPINGTIME,0,30*FToTick);
  4649.    pblock->SetValue(PB_MAPPINGDIST,0,100.0f);
  4650.  
  4651.    pblock->SetValue(PB_SPINTIME,0,30*FToTick);
  4652.    pblock->SetValue(PB_SPINTIMEVAR,0,0.0f);
  4653.    pblock->SetValue(PB_SPINPHASE,0,0.0f);
  4654.    pblock->SetValue(PB_SPINPHASEVAR,0,0.0f);
  4655.    pblock->SetValue(PB_SPINAXISTYPE,0,0);
  4656.    pblock->SetValue(PB_SPINAXISX,0,1.0f);
  4657.    pblock->SetValue(PB_SPINAXISY,0,0.0f);
  4658.    pblock->SetValue(PB_SPINAXISZ,0,0.0f);
  4659.    pblock->SetValue(PB_SPINAXISVAR,0,0.0f);
  4660.  
  4661.    pblock->SetValue(PB_EMITVINFL,0,100.0f);
  4662.    pblock->SetValue(PB_EMITVMULT,0,1.0f);
  4663.    pblock->SetValue(PB_EMITVMULTVAR,0,0.0f);
  4664.  
  4665.    pblock->SetValue(PB_BUBLAMP,0,0.0f);
  4666.    pblock->SetValue(PB_BUBLAMPVAR,0,0.0f);
  4667.    pblock->SetValue(PB_BUBLPER,0,100000*FToTick);
  4668.    pblock->SetValue(PB_BUBLPERVAR,0,0.0f);
  4669.    pblock->SetValue(PB_BUBLPHAS,0,0.0f);
  4670.    pblock->SetValue(PB_BUBLPHASVAR,0,0.0f);
  4671.  
  4672.    pblock->SetValue(PB_EMITRWID,0,0.0f);
  4673.    pblock->SetValue(PB_EMITRHID,0,0);
  4674.    pblock->SetValue(PB_SPAWNGENS,0,1);
  4675.    pblock->SetValue(PB_SPAWNCOUNT,0,1);
  4676.    pblock->SetValue(PB_METACOURSEV,0,1.0f);
  4677.    pblock->SetValue(PB_SPAWNPERCENT,0,100);
  4678.    pblock->SetValue(PB_SPAWNMULTVAR,0,0.0f);
  4679.    pblock->SetValue(PB_SSNOTDRAFT,0,0);
  4680.    pblock->SetValue(PB_SSSPAWNDIEAFTER,0,0);
  4681.    pblock->SetValue(PB_IPCOLLIDE_ON,0,0);
  4682.    pblock->SetValue(PB_IPCOLLIDE_STEPS,0,2);
  4683.    pblock->SetValue(PB_IPCOLLIDE_BOUNCE,0,1.0f);
  4684.    pblock->SetValue(PB_IPCOLLIDE_BOUNCEVAR,0,0.0f);
  4685.  
  4686.    custname=TSTR(_T(" "));
  4687.    ResetSystem(0,FALSE);
  4688.    size=43*isize+fsize*37;
  4689.    times.tl.SetCount(0);
  4690.    dispt=-99999;
  4691.    theSuprSprayDraw.bboxpt=NULL;
  4692.    nmtls.ZeroCount();
  4693.    deftime=0;
  4694.    parts.points.ZeroCount();
  4695.    maincount=0;
  4696.    cancelled=FALSE;
  4697.    wasmulti=FALSE;
  4698.    nlist.ZeroCount();
  4699.    llist.ZeroCount();
  4700.    dflags=APRTS_ROLLUP_FLAGS;
  4701.    backpatch=TRUE;
  4702.    ClearAFlag(A_NOTREND);
  4703.     stepSize=GetTicksPerFrame();
  4704. }
  4705.  
  4706. SuprSprayParticle::~SuprSprayParticle()
  4707. {  if (sdata) {delete[] sdata;sdata=NULL;}
  4708. // SetFlag(dflags,STDMTL_ROLLUP1_OPEN,ip->IsRollupPanelOpen(hPanelBasic));
  4709.    DeleteAllRefsFromMe();
  4710.    pblock=NULL;
  4711.    parts.FreeAll();
  4712.    times.tl.SetCount(0);
  4713.    times.tl.Shrink();
  4714.    nmtls.ZeroCount();nmtls.Shrink();
  4715.    llist.ZeroCount();llist.Shrink();
  4716.    nlist.ZeroCount();nlist.Shrink();
  4717.    if (cmesh) delete[] cmesh;
  4718.    if (theSuprSprayDraw.bboxpt) delete[] theSuprSprayDraw.bboxpt;
  4719.    if (dispmesh) delete dispmesh;
  4720. }
  4721.  
  4722. Matrix3 CommonParticle::TumbleMat(int index,float amount, float scale)
  4723.    {
  4724.    Matrix3 mat;
  4725.    Quat q;
  4726.    float ang[3];
  4727.  
  4728.    srand(int(PARTICLE_SEED) * Perm(index) + int(PARTICLE_SEED));
  4729.    
  4730.    for (int i=0; i<3; i++) {
  4731.       ang[i] = (float(2*rand())/float(RAND_MAX) - 1.0f);
  4732.       if (amount>0.0f) {
  4733.          float off = 8725.0f*i;
  4734.          ang[i] += noise3((parts[index]+Point3(off,off,off))*scale)*amount;
  4735.          }
  4736.       ang[i] *= TWOPI;
  4737.       }
  4738.    
  4739.    EulerToQuat(ang,q);
  4740.    q.MakeMatrix(mat);
  4741.    return mat;
  4742.    }
  4743.  
  4744. TimeValue CommonParticle::ParticleLife(TimeValue t, int i)
  4745. {   int pcount=parts.Count();
  4746.    if (!(i<pcount)) return 0;
  4747.    return sdata[i].L;
  4748. }
  4749.  
  4750. Point3 BlizzardParticle::ParticlePosition(TimeValue t,int i)
  4751. {  int pcount=parts.points.Count();
  4752.    if (!(i<pcount)) return Zero;
  4753.    Point3 retpt=parts.points[i];
  4754.    return retpt;
  4755. }
  4756.  
  4757. Point3 SuprSprayParticle::ParticlePosition(TimeValue t,int i)
  4758. {  int pcount=parts.points.Count();
  4759.    if (!(i<pcount)) return Zero;
  4760.    Point3 FinalP=parts.points[i];
  4761. // figure out particle class
  4762.    int isinst;
  4763.    pblock->GetValue(PB_PARTICLECLASS,0,isinst,FOREVER);
  4764. // if we have custom geometry, find the center of the bounding box and velocity normal
  4765.    if ((isinst==INSTGEOM)&&(custnode))
  4766.    {  int anioff;
  4767.       float dlgsize;
  4768.       dlgsize=parts.radius[i];
  4769.       float zoffset=0.0f;
  4770.       Point3 OffsetV=Zero;;
  4771.       TimeValue aniend=GetAnimEnd();
  4772.       int anifr=aniend+GetTicksPerFrame();
  4773.       pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  4774.       TimeValue Ctime=(anioff?GetCurTime(sdata[i].showframe,(anioff>1?t:parts.ages[i]),anifr):t);
  4775.       int mnum=TimeFound(times,Ctime,(sdata[i].gennum>nlist.Count()?nlist.Count():sdata[i].gennum));
  4776.       if (mnum>=0) zoffset=cmesh[mnum].getBoundingBox().Center().z;
  4777. // if we're using DoT/MBlur, account for scaling due to stretch
  4778.       int axisentered;
  4779.       pblock->GetValue(PB_SPINAXISTYPE,0,axisentered,FOREVER);
  4780.       if (axisentered==DIRTRAVEL)
  4781.       {  int K;
  4782.          pblock->GetValue(PB_STRETCH,t,K,FOREVER);
  4783.          float strlen=GetLen(parts.vels[i],K);
  4784.          zoffset*=strlen;
  4785.       }
  4786.       float lenV=Length(parts.vels[i]);
  4787.       if (lenV>EPSILON) OffsetV=parts.vels[i]/lenV;
  4788.       FinalP+=zoffset*dlgsize*OffsetV;
  4789.    }
  4790.    return FinalP;
  4791. }
  4792.  
  4793. Point3 SuprSprayParticle::ParticleVelocity(TimeValue t,int i)
  4794. {  Point3 retvel=Zero;
  4795.    int pcount=parts.vels.Count();
  4796.    if (i<pcount)
  4797.       retvel=parts.vels[i];
  4798.    return retvel;
  4799. }
  4800.  
  4801. float SuprSprayParticle::ParticleSize(TimeValue t,int i)
  4802. {  float strlen=1.0f;
  4803.    float boxlen=1.0f;
  4804.    float dlgsize;
  4805.    int pcount=parts.radius.Count();
  4806.    if (!(i<pcount)) return 0.0f;
  4807.    int axisentered,K,isinst,ptype;
  4808. // get the size/scale from the dialog box processed for this particle...
  4809.    dlgsize=parts.radius[i];
  4810. // figure out particle type and class
  4811.    pblock->GetValue(PB_PARTICLETYPE,0,ptype,FOREVER);
  4812.    pblock->GetValue(PB_PARTICLECLASS,0,isinst,FOREVER);
  4813. // if there are custom particles, find bounding box params...
  4814.    if ((isinst==INSTGEOM)&&(custnode))
  4815.    {  int anioff;
  4816.       TimeValue aniend=GetAnimEnd();
  4817.       int anifr=aniend+GetTicksPerFrame();
  4818.       pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  4819.       TimeValue Ctime=(anioff?GetCurTime(sdata[i].showframe,(anioff>1?t:parts.ages[i]),anifr):t);
  4820.       int mnum=TimeFound(times,Ctime,(sdata[i].gennum>nlist.Count()?nlist.Count():sdata[i].gennum));
  4821.       if (mnum>=0) boxlen=cmesh[mnum].getBoundingBox().Width().z;
  4822.    }
  4823. // if we're using MBlur and DoT then account for scaling along DoT
  4824.    pblock->GetValue(PB_SPINAXISTYPE,0,axisentered,FOREVER);
  4825.    if (axisentered==DIRTRAVEL)
  4826.    {  pblock->GetValue(PB_STRETCH,t,K,FOREVER);
  4827.       strlen=GetLen(parts.vels[i],K);
  4828.    }
  4829.    float templen=boxlen*strlen;
  4830.    if ((isinst!=PB_PARTICLECLASS)&&(ptype==RENDTET)) templen*=1.3f;
  4831.    return templen*dlgsize;
  4832. }
  4833.  
  4834. int SuprSprayParticle::ParticleCenter(TimeValue t,int i)
  4835. {  int ptype,isinst;
  4836.    pblock->GetValue(PB_PARTICLECLASS,0,isinst,FOREVER);
  4837.    pblock->GetValue(PB_PARTICLETYPE,0,ptype,FOREVER);
  4838.    if (isinst==INSTGEOM) return PARTCENTER_CENTER;
  4839.    if (ptype==RENDTET) return PARTCENTER_HEAD;
  4840.    return PARTCENTER_CENTER;  
  4841. }
  4842.  
  4843. Point3 BlizzardParticle::ParticleVelocity(TimeValue t,int i)
  4844. {  Point3 retvel=Zero;
  4845.    int pcount=parts.vels.Count();
  4846.    if (i<pcount)
  4847.       retvel=parts.vels[i];
  4848.    return retvel;
  4849. }
  4850.  
  4851. float BlizzardParticle::ParticleSize(TimeValue t,int i)
  4852. {  int isinst;
  4853.    int pcount=parts.radius.Count();
  4854.    if (!(i<pcount)) return 0.0f;
  4855.    float radius=1.0f,size=parts.radius[i];
  4856.    pblock->GetValue(PB_PARTICLECLASS,0,isinst,FOREVER);
  4857.    if ((isinst==INSTGEOM) &&(custnode))
  4858.    {  int anioff;
  4859.       TimeValue aniend=GetAnimEnd();
  4860.       int anifr=aniend+GetTicksPerFrame();
  4861.       pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  4862.       TimeValue Ctime=(anioff?GetCurTime(sdata[i].showframe,(anioff>1?t:parts.ages[i]),anifr):t);
  4863.       int mnum=TimeFound(times,Ctime,(sdata[i].gennum>nlist.Count()?nlist.Count():sdata[i].gennum));
  4864.       if (mnum>=0)
  4865.       radius=(cmesh[mnum].getBoundingBox().Width()).z;
  4866.    }
  4867.    return radius*size;  
  4868. }
  4869.  
  4870. int BlizzardParticle::ParticleCenter(TimeValue t,int i)
  4871. {  return PARTCENTER_CENTER;  
  4872. }
  4873.  
  4874. int CommonParticle::RenderBegin(TimeValue t, ULONG flags)
  4875.    {  SetAFlag(A_RENDER);
  4876.       ParticleInvalid();      
  4877.       NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  4878.       cancelled=FALSE;
  4879.       int isinst;
  4880.       pblock->GetValue(PB_PARTICLECLASS,0,isinst,FOREVER);
  4881.       if ((isinst==INSTGEOM) &&(custnode))
  4882.          custnode->SetProperty(PROPID_FORCE_RENDER_MESH_COPY,(void *)1);
  4883.    return 0;
  4884.    }
  4885.  
  4886. int CommonParticle::RenderEnd(TimeValue t)
  4887.    {
  4888.       ClearAFlag(A_RENDER);
  4889.       ParticleInvalid();      
  4890.       NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  4891.       int isinst;
  4892.       pblock->GetValue(PB_PARTICLECLASS,0,isinst,FOREVER);
  4893.       if ((isinst==INSTGEOM) &&(custnode))
  4894.          custnode->SetProperty(PROPID_FORCE_RENDER_MESH_COPY,(void *)0);
  4895.    return 0;
  4896.    }
  4897.  
  4898. void SuprSprayParticle::BeginEditParams(
  4899.       IObjParam *ip, ULONG flags,Animatable *prev)
  4900.    {
  4901.    SimpleParticle::BeginEditParams(ip,flags,prev);
  4902.    editOb = this;
  4903.    this->ip = ip;
  4904.  
  4905.    if (flags&BEGIN_EDIT_CREATE) {
  4906.       creating = TRUE;
  4907.    } else { creating = FALSE; }
  4908.    if (pmapParam && pmapPGen && pmapPType && pmapPSpin && pmapEmitV && pmapBubl && pmapSpawn)
  4909.    {  pmapParam->SetParamBlock(pblock);
  4910.       pmapPGen->SetParamBlock(pblock);
  4911.       pmapPType->SetParamBlock(pblock);
  4912.       pmapPSpin->SetParamBlock(pblock);
  4913.       pmapEmitV->SetParamBlock(pblock);
  4914.       pmapBubl->SetParamBlock(pblock);
  4915.       pmapSpawn->SetParamBlock(pblock);
  4916.       DLSetWindowLongPtr(hParams2, this);
  4917.    } else
  4918.    {  pmapParam = CreateCPParamMap(
  4919.          descParamSuprSpray,PARAMSuprSpray_LENGTH,
  4920.          pblock,
  4921.          ip,
  4922.          hInstance,
  4923.          MAKEINTRESOURCE(IDD_SUPRPRTS_SUPERSPRAY),
  4924.          GetString(IDS_RB_PARAMETERS),
  4925.          dflags&APRTS_ROLLUP1_OPEN?0:APPENDROLL_CLOSED);
  4926.  
  4927.       pmapPGen = CreateCPParamMap(
  4928.          descParamPGen,PARAMPGEN_LENGTH,
  4929.          pblock,
  4930.          ip,
  4931.          hInstance,
  4932.          MAKEINTRESOURCE(IDD_SUPRPRTS_GEN_SS),
  4933.          GetString(IDS_RB_PGEN),
  4934.          dflags&APRTS_ROLLUP2_OPEN?0:APPENDROLL_CLOSED);
  4935.      
  4936.       pmapPType = CreateCPParamMap(
  4937.          descParamPType,PARAMPTYPE_LENGTH,
  4938.          pblock,
  4939.          ip,
  4940.          hInstance,
  4941.          MAKEINTRESOURCE(IDD_SUPRPRTS_PARTTYPE_SS),
  4942.          GetString(IDS_RB_PTYPE),
  4943.          dflags&APRTS_ROLLUP3_OPEN?0:APPENDROLL_CLOSED);    
  4944.    
  4945.       pmapPSpin = CreateCPParamMap(
  4946.          descParamPSpin,PARAMPSPIN_LENGTH,
  4947.          pblock,
  4948.          ip,
  4949.          hInstance,
  4950.          MAKEINTRESOURCE(IDD_SUPRPRTS_ROT),
  4951.          GetString(IDS_RB_SPIN),
  4952.          dflags&APRTS_ROLLUP4_OPEN?0:APPENDROLL_CLOSED);    
  4953.    
  4954.       pmapEmitV = CreateCPParamMap(
  4955.          descParamEmitV,PARAMEMITV_LENGTH,
  4956.          pblock,
  4957.          ip,
  4958.          hInstance,
  4959.          MAKEINTRESOURCE(IDD_SUPRPRTS_EMITV),
  4960.          GetString(IDS_RB_EMITV),
  4961.          dflags&APRTS_ROLLUP5_OPEN?0:APPENDROLL_CLOSED);    
  4962.    
  4963.       pmapBubl = CreateCPParamMap(
  4964.          descParamBubl,PARAMBUBL_LENGTH,
  4965.          pblock,
  4966.          ip,
  4967.          hInstance,
  4968.          MAKEINTRESOURCE(IDD_SUPRPRTS_BUBL),
  4969.          GetString(IDS_RB_BUBL),
  4970.          dflags&APRTS_ROLLUP6_OPEN?0:APPENDROLL_CLOSED);    
  4971.       pmapSpawn = CreateCPParamMap(
  4972.          descPSpawning,PSPAWNINGPARAMS_LENGTH,
  4973.          pblock,
  4974.          ip,
  4975.          hInstance,
  4976.          MAKEINTRESOURCE(IDD_SUPRPRTS_SPAWNING),
  4977.          GetString(IDS_AP_PSPAWN),
  4978.          dflags&APRTS_ROLLUP7_OPEN?0:APPENDROLL_CLOSED);    
  4979.  
  4980.       hParams2 = ip->AddRollupPage(
  4981.             hInstance,
  4982.             MAKEINTRESOURCE(IDD_SUPRPRTS_SAVE),
  4983.             CustomSettingParamDlgProc,
  4984.             GetString(IDS_RB_LOADSAVE),
  4985.             (LPARAM)this,dflags&APRTS_ROLLUP8_OPEN?0:APPENDROLL_CLOSED);      
  4986.       ip->RegisterDlgWnd(hParams2);
  4987.  
  4988.       }
  4989.    spawn=pmapSpawn->GetHWnd();
  4990.    hparam=pmapParam->GetHWnd();
  4991.    hgen=pmapPGen->GetHWnd();
  4992.    hptype=pmapPType->GetHWnd();
  4993.    hrot=pmapPSpin->GetHWnd();
  4994.    hbubl=pmapBubl->GetHWnd();
  4995.    if (pmapPType) pmapPType->SetUserDlgProc(new SSParticleDisableDlgProc(this));
  4996.    if (pmapPGen) pmapPGen->SetUserDlgProc(new SSParticleGenDlgProc(this));
  4997.    if (pmapParam) pmapParam->SetUserDlgProc(new SSParticleDlgProc(this));
  4998.    if (pmapSpawn) pmapSpawn->SetUserDlgProc(new ComParticleSpawnDlgProc(this));
  4999.    if (pmapPSpin) pmapPSpin->SetUserDlgProc(new SSParticleSpinDlgProc(this));
  5000. }  
  5001.  
  5002. void SuprSprayParticle::EndEditParams(
  5003.       IObjParam *ip, ULONG flags,Animatable *next)
  5004.    {TimeValue t0,t2;
  5005.    SetFlag(dflags,APRTS_ROLLUP1_OPEN,IsRollupPanelOpen(hparam));
  5006.    SetFlag(dflags,APRTS_ROLLUP2_OPEN,IsRollupPanelOpen(hgen));
  5007.    SetFlag(dflags,APRTS_ROLLUP3_OPEN,IsRollupPanelOpen(hptype));
  5008.    SetFlag(dflags,APRTS_ROLLUP4_OPEN,IsRollupPanelOpen(hrot));
  5009.    SetFlag(dflags,APRTS_ROLLUP5_OPEN,IsRollupPanelOpen(pmapEmitV->GetHWnd()));
  5010.    SetFlag(dflags,APRTS_ROLLUP6_OPEN,IsRollupPanelOpen(hbubl));
  5011.    SetFlag(dflags,APRTS_ROLLUP7_OPEN,IsRollupPanelOpen(spawn));
  5012.    SetFlag(dflags,APRTS_ROLLUP8_OPEN,IsRollupPanelOpen(hParams2));
  5013.    SimpleParticle::EndEditParams(ip,flags,next);
  5014.  
  5015.    if (flags&END_EDIT_REMOVEUI) {
  5016.       pblock->GetValue(PB_EMITSTART,0,t0,FOREVER);
  5017.       pblock->GetValue(PB_EMITSTOP,0,t2,FOREVER);
  5018.       if (t2<t0) pblock->SetValue(PB_EMITSTOP,0,t0);
  5019.       DestroyCPParamMap(pmapParam);
  5020.       DestroyCPParamMap(pmapPGen);
  5021.       DestroyCPParamMap(pmapPType);
  5022.       DestroyCPParamMap(pmapPSpin);
  5023.       DestroyCPParamMap(pmapEmitV);
  5024.       DestroyCPParamMap(pmapBubl);
  5025.       DestroyCPParamMap(pmapSpawn);
  5026.  
  5027.       ip->UnRegisterDlgWnd(hParams2);
  5028.       ip->DeleteRollupPage(hParams2);
  5029.       hParams2 = NULL;
  5030.  
  5031.       pmapParam  = NULL;
  5032.       pmapPGen = NULL;
  5033.       pmapPType = NULL;
  5034.       pmapPSpin = NULL;
  5035.       pmapEmitV = NULL;
  5036.       pmapBubl = NULL;
  5037.       pmapSpawn = NULL;
  5038.    }else
  5039.       DLSetWindowLongPtr(hParams2, NULL);
  5040.    ip->ClearPickMode();
  5041.    ip= NULL;
  5042.    creating = FALSE;
  5043.    }
  5044.  
  5045. void CommonParticle::MapKeys(TimeMap *map,DWORD flags)
  5046. {  Animatable::MapKeys(map,flags);
  5047.    TimeValue TempTime;
  5048. // remap values
  5049.    pblock->GetValue(PB_EMITSTART,0,TempTime,FOREVER);
  5050.    TempTime=map->map(TempTime);
  5051.    pblock->SetValue(PB_EMITSTART,0,TempTime);
  5052.    pblock->GetValue(PB_EMITSTOP,0,TempTime,FOREVER);
  5053.    TempTime=map->map(TempTime);
  5054.    pblock->SetValue(PB_EMITSTOP,0,TempTime);
  5055.    pblock->GetValue(PB_DISPUNTIL,0,TempTime,FOREVER);
  5056.    TempTime=map->map(TempTime);
  5057.    pblock->SetValue(PB_DISPUNTIL,0,TempTime);
  5058. // scaled values
  5059.    pblock->GetValue(PB_LIFE,0,TempTime,FOREVER);
  5060.    TempTime=map->map(TempTime);
  5061.    pblock->SetValue(PB_LIFE,0,TempTime);
  5062.    pblock->GetValue(PB_LIFEVAR,0,TempTime,FOREVER);
  5063.    TempTime=map->map(TempTime);
  5064.    pblock->SetValue(PB_LIFEVAR,0,TempTime);
  5065.    pblock->GetValue(PB_GROWTIME,0,TempTime,FOREVER);
  5066.    TempTime=map->map(TempTime);
  5067.    pblock->SetValue(PB_GROWTIME,0,TempTime);
  5068.    pblock->GetValue(PB_FADETIME,0,TempTime,FOREVER);
  5069.    TempTime=map->map(TempTime);
  5070.    pblock->SetValue(PB_FADETIME,0,TempTime);
  5071.    pblock->GetValue(PB_MAPPINGTIME,0,TempTime,FOREVER);
  5072.    TempTime=map->map(TempTime);
  5073.    pblock->SetValue(PB_MAPPINGTIME,0,TempTime);
  5074.    pblock->GetValue(PB_SPINTIME,0,TempTime,FOREVER);
  5075.    TempTime=map->map(TempTime);
  5076.    pblock->SetValue(PB_SPINTIME,0,TempTime);
  5077. // pblock->GetValue(PB_OFFSETAMOUNT,0,TempTime,FOREVER);
  5078. // TempTime=map->map(TempTime);
  5079. // pblock->SetValue(PB_OFFSETAMOUNT,0,TempTime);
  5080.    if (ClassID()==SUPRSPRAY_CLASS_ID)
  5081.    {  pblock->GetValue(PB_BUBLPER,0,TempTime,FOREVER);
  5082.       TempTime=map->map(TempTime);
  5083.       pblock->SetValue(PB_BUBLPER,0,TempTime);
  5084.    }
  5085. }  
  5086.  
  5087. Interval CommonParticle::GetValidity(TimeValue t)
  5088.    {
  5089.    // For now...
  5090.    return Interval(t,t);
  5091.    }
  5092.  
  5093. void SuprSprayParticle::BuildEmitter(TimeValue t, Mesh& amesh)
  5094.    {
  5095.    float width,hwidth,u;
  5096.    mvalid = FOREVER;
  5097.    pblock->GetValue(PB_EMITRWID,t,width,mvalid);
  5098. // width  *= 0.5f;
  5099.    hwidth =width*0.5f;
  5100.  
  5101.    mesh.setNumVerts(23);
  5102.    mesh.setNumFaces(18);
  5103.    for (int i=0; i<12; i++) {
  5104.       u = float(i)/12.0f * TWOPI;
  5105.       mesh.setVert(i, Point3((float)cos(u) * width, (float)sin(u) * width, 0.0f));
  5106.    }
  5107.    for (int i=0; i<12; i++)
  5108.    { int i1 = i+1;
  5109.      if (i1==12) i1 = 0;
  5110.      mesh.faces[i].setEdgeVisFlags(1,0,0);
  5111.      mesh.faces[i].setSmGroup(0);
  5112.      mesh.faces[i].setVerts(i,i1,12);
  5113.    }
  5114.    mesh.setVert(12, Point3(0.0f, 0.0f, 0.0f));
  5115.    mesh.setVert(13, Point3(width,0.0f, width));
  5116.    mesh.setVert(14, Point3(0.0f, 0.0f, width));
  5117.    mesh.setVert(15, Point3(-width, 0.0f, width));
  5118.    mesh.setVert(16, Point3( width, 0.0f,-width));
  5119.    mesh.setVert(17, Point3( 0.0f, 0.0f, -width));
  5120.    mesh.setVert(18, Point3(-width, 0.0f, -width));
  5121.    mesh.setVert(19, Point3(hwidth, 0.0f,hwidth));
  5122.    mesh.setVert(20, Point3(-hwidth, 0.0f,hwidth));
  5123.    mesh.setVert(21, Point3(0.0f,hwidth,hwidth));
  5124.    mesh.setVert(22, Point3(0.0f,-hwidth,hwidth));
  5125.  
  5126.    mesh.faces[12].setVerts(13,14,17);
  5127.    mesh.faces[12].setEdgeVisFlags(1,1,0);
  5128.    mesh.faces[12].setSmGroup(0);
  5129.  
  5130.    mesh.faces[13].setEdgeVisFlags(0,1,1);
  5131.    mesh.faces[13].setSmGroup(0);
  5132.    mesh.faces[13].setVerts(13,17,16);
  5133.  
  5134.    mesh.faces[14].setEdgeVisFlags(1,1,0);
  5135.    mesh.faces[14].setSmGroup(0);
  5136.    mesh.faces[14].setVerts(14,15,18);
  5137.  
  5138.    mesh.faces[15].setEdgeVisFlags(0,1,1);
  5139.    mesh.faces[15].setSmGroup(0);
  5140.    mesh.faces[15].setVerts(14,18,17);
  5141.  
  5142.    mesh.faces[16].setEdgeVisFlags(1,1,1);
  5143.    mesh.faces[16].setSmGroup(0);
  5144.    mesh.faces[16].setVerts(19,14,20);
  5145.  
  5146.    mesh.faces[17].setEdgeVisFlags(1,1,1);
  5147.    mesh.faces[17].setSmGroup(0);
  5148.    mesh.faces[17].setVerts(21,14,22);
  5149.  
  5150.    mesh.InvalidateGeomCache();
  5151.    }
  5152.  
  5153. int CommonParticle::CountLive()
  5154. {  int c=0;
  5155.    for (int i=0; i<parts.Count(); i++)
  5156.      {if (parts.Alive(i)) c++;}
  5157.    return c;
  5158. }
  5159.  
  5160. void CommonParticle::RetrieveMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t)
  5161. { int nc,i;
  5162.   Mtl *submtl=node->GetMtl();
  5163.   if (subtree)
  5164.   { if ((nc=node->NumberOfChildren())>0)
  5165.    for (i=0;i<nc;i++)
  5166.      RetrieveMtls(node->GetChildNode(i),subtree,numsubs,numtabs,tabmax,t);
  5167.   }
  5168.   if (IsGEOM(node->EvalWorldState(t).obj)!=NULL)
  5169.   { if (*numtabs>=*tabmax)
  5170.    { mttab.Resize((*tabmax)+=256);}
  5171.    if (submtl!=NULL)
  5172.    { mttab[(*numtabs)++]=submtl;
  5173.      int subs;
  5174.      if ((subs=submtl->NumSubMtls())>0)
  5175.        (*numsubs)+=subs;
  5176.      else (*numsubs)++;
  5177.    }
  5178.    else
  5179.    {DWORD tc=node->GetWireColor();
  5180.    StdMat *m = NewDefaultStdMat();
  5181.    m->SetName(TSTR(_T("C"))+node->GetName());
  5182.    Color bcolor(tc);
  5183.    m->SetDiffuse(bcolor,0);
  5184.    mttab[(*numtabs)++]=(Mtl*)m;
  5185.    (*numsubs)++;
  5186.    }
  5187.   }
  5188. }
  5189.  
  5190. void CommonParticle::DoGroupMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t)
  5191. { int nc;
  5192.   if ((nc=node->NumberOfChildren())>0)
  5193.    for (int i=0;i<nc;i++)
  5194.    { INode *nxtnode=node->GetChildNode(i);
  5195.      if (nxtnode->IsGroupHead()) DoGroupMtls(nxtnode,subtree,numsubs,numtabs,tabmax,t);
  5196.      else if((subtree)||(nxtnode->IsGroupMember())) RetrieveMtls(nxtnode,subtree,numsubs,numtabs,tabmax,t);
  5197.   }
  5198. }
  5199.  
  5200. void CommonParticle::AssignMtl(INode *node,INode *topnode,int subtree,TimeValue t)
  5201. {  Mtl *submtl;
  5202.    MultiMtl *newmat=NULL;
  5203.    Mtl *nmtl=NULL;
  5204.    TSTR newname;
  5205.    MtlBaseLib glib;
  5206.    int tabmax=256;
  5207.    newname=TSTR(_T("CMat"))+node->GetName();
  5208.    if (_tcslen(newname)>16) newname[16]='\0';
  5209.    int numsubs=0,numtabs=0,nCount=nlist.Count();
  5210.    nmtls.SetCount(nCount);
  5211.     mttab.SetCount(tabmax);
  5212.     submtl=custnode->GetMtl();
  5213.    INode *tmpnode=custnode;
  5214.    backpatch=FALSE;
  5215.    for (int mut=0;mut<=nCount;mut++)
  5216.    { if (tmpnode->IsGroupHead())
  5217.        DoGroupMtls(tmpnode,subtree,&numsubs,&numtabs,&tabmax,t);
  5218.      else
  5219.      RetrieveMtls(tmpnode,subtree,&numsubs,&numtabs,&tabmax,t);
  5220.      if (mut!=nCount)
  5221.      {nmtls[mut]=numsubs;
  5222.       tmpnode=nlist[mut];
  5223.      }
  5224.    }
  5225.    mttab.Shrink();
  5226.    if (!((numtabs==1)&&(submtl!=NULL)))
  5227.    { TSTR oldname=TSTR(_T(" "));
  5228.    nmtl=node->GetMtl();
  5229.      if (nmtl != NULL)
  5230.         oldname=nmtl->GetName();
  5231.      if (_tcscmp(oldname,newname)!=0)
  5232.      { newmat=NewDefaultMultiMtl();
  5233.        newmat->SetName(newname); }
  5234.      else newmat=(MultiMtl*)nmtl;
  5235. //   nmtl->FindMtl(nmtl);
  5236.      newmat->SetNumSubMtls(numsubs);
  5237.      int k=0,nt=0,j;
  5238.      for (int i=0;i<numtabs;i++)
  5239.      {   if ((nt=mttab[i]->NumSubMtls())>0)
  5240.         for (j=0;j<nt;j++)
  5241.        { newmat->SetSubMtl(k,mttab[i]->GetSubMtl(j));
  5242.           k++;
  5243.         }
  5244.         else
  5245.        { newmat->SetSubMtl(k,mttab[i]);
  5246.          k++;
  5247.        }
  5248.      }
  5249.    }
  5250.     mttab.SetCount(0); mttab.Shrink();
  5251.    node->SetMtl(newmat!=NULL?newmat:submtl);  
  5252. }
  5253. void CommonParticle::CntRetrieveMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t)
  5254. { int nc,i;
  5255.   Mtl *submtl=node->GetMtl();
  5256.   if (subtree)
  5257.   { if ((nc=node->NumberOfChildren())>0)
  5258.    for (i=0;i<nc;i++)
  5259.      CntRetrieveMtls(node->GetChildNode(i),subtree,numsubs,numtabs,tabmax,t);
  5260.   }
  5261.   if (IsGEOM(node->EvalWorldState(t).obj)!=NULL)
  5262.   { if (submtl!=NULL)
  5263.    { int subs;
  5264.      if ((subs=submtl->NumSubMtls())>0)
  5265.        (*numsubs)+=subs;
  5266.      else (*numsubs)++;
  5267.    }
  5268.    else
  5269.    (*numsubs)++;
  5270.   }
  5271. }
  5272.  
  5273. void CommonParticle::CntDoGroupMtls(INode *node,int subtree,int *numsubs,int *numtabs,int *tabmax,TimeValue t)
  5274. { int nc;
  5275.   if ((nc=node->NumberOfChildren())>0)
  5276.    for (int i=0;i<nc;i++)
  5277.    { INode *nxtnode=node->GetChildNode(i);
  5278.      if (nxtnode->IsGroupHead()) CntDoGroupMtls(nxtnode,subtree,numsubs,numtabs,tabmax,t);
  5279.      else if ((subtree)||(nxtnode->IsGroupMember())) CntRetrieveMtls(nxtnode,subtree,numsubs,numtabs,tabmax,t);
  5280.   }
  5281. }
  5282.  
  5283. void CommonParticle::GetSubs(INode *node,INode *topnode,int subtree,TimeValue t)
  5284. {  Mtl *submtl;
  5285.    int tabmax=256;
  5286.    int numsubs=0,numtabs=0;
  5287.    int mstart=0,mcnt=nlist.Count();INode *onode;
  5288.    onode=custnode;
  5289.    nmtls.SetCount(mcnt);
  5290.     submtl=onode->GetMtl();
  5291.    INode *tmpnode=onode;
  5292.    for (int mut=mstart;mut<=mcnt;mut++)
  5293.    { if (tmpnode->IsGroupHead())
  5294.        CntDoGroupMtls(tmpnode,subtree,&numsubs,&numtabs,&tabmax,t);
  5295.      else
  5296.      CntRetrieveMtls(tmpnode,subtree,&numsubs,&numtabs,&tabmax,t);
  5297.      if (mut!=mcnt)
  5298.      {nmtls[mut]=numsubs;
  5299.       tmpnode=nlist[mut];
  5300.      }
  5301.    }
  5302. }
  5303.  
  5304. void CommonParticle::GetNextBB(INode *node,int subtree,int *count,int *tabmax,Point3 boxcenter,TimeValue t,int tcount,INode *onode)
  5305. {int i,nc;
  5306.    if (subtree)
  5307.   { if ((nc=node->NumberOfChildren())>0)
  5308.    for (i=0;i<nc;i++)
  5309.      GetNextBB(node->GetChildNode(i),subtree,count,tabmax,boxcenter,t,tcount,onode);
  5310.   }
  5311.   Object *cobj=node->EvalWorldState(t).obj;
  5312.   TriObject *triOb=TriIsUseable(cobj,t);
  5313.   if (triOb)
  5314.   {    if (*count>=*tabmax)
  5315.    { theSuprSprayDraw.bboxpt[tcount].bpts.Resize((*tabmax)+=256);}
  5316.     Matrix3 ctm = node->GetObjTMAfterWSM(t);
  5317.    if (node!=custnode)
  5318.   { theSuprSprayDraw.bboxpt[tcount].bpts[*count].Suboffset=Point3(0.0f,0.0f,0.0f)*ctm-boxcenter;
  5319.   }  
  5320.   else theSuprSprayDraw.bboxpt[tcount].bpts[*count].Suboffset=Point3(0.0f,0.0f,0.0f);
  5321.    ctm.NoTrans();
  5322.   Box3 bbox=triOb->GetMesh().getBoundingBox();
  5323.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[0]=Point3(bbox.pmax[0],bbox.pmax[1],bbox.pmax[2])*ctm;
  5324.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[1]=Point3(bbox.pmax[0],bbox.pmax[1],bbox.pmin[2])*ctm;
  5325.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[2]=Point3(bbox.pmax[0],bbox.pmin[1],bbox.pmin[2])*ctm;
  5326.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[3]=Point3(bbox.pmax[0],bbox.pmin[1],bbox.pmax[2])*ctm;
  5327.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[4]=Point3(bbox.pmin[0],bbox.pmax[1],bbox.pmax[2])*ctm;
  5328.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[5]=Point3(bbox.pmin[0],bbox.pmax[1],bbox.pmin[2])*ctm;
  5329.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[6]=Point3(bbox.pmin[0],bbox.pmin[1],bbox.pmin[2])*ctm;
  5330.   theSuprSprayDraw.bboxpt[tcount].bpts[*count].pts[7]=Point3(bbox.pmin[0],bbox.pmin[1],bbox.pmax[2])*ctm;
  5331.   (*count)++;
  5332.   if (triOb!=cobj) triOb->DeleteThis();
  5333.   }
  5334. }
  5335.  
  5336. void CommonParticle::DoGroupBB(INode *node,int subtree,int *count,int *tabmax,Point3 boxcenter,TimeValue t,int tcount,INode *onode)
  5337. { int nc;
  5338.   if ((nc=node->NumberOfChildren())>0)
  5339.    for (int j=0;j<nc;j++)
  5340.    { INode *nxtnode=node->GetChildNode(j);
  5341.      if (nxtnode->IsGroupHead()) DoGroupBB(nxtnode,subtree,count,tabmax,boxcenter,t,tcount,onode);
  5342.      else if ((subtree)||(nxtnode->IsGroupMember())) GetNextBB(nxtnode,subtree,count,tabmax,boxcenter,t,tcount,onode);
  5343.    }
  5344. }
  5345.  
  5346. void CommonParticle::GetallBB(INode *custnode,int subtree,TimeValue t)
  5347. { int tabmax=256;
  5348.   int count=1,ocount=times.tl.Count();
  5349.   if (ocount>0) count=ocount;
  5350.   if (theSuprSprayDraw.bboxpt) delete[] theSuprSprayDraw.bboxpt;
  5351.   theSuprSprayDraw.bboxpt=NULL;
  5352.   INode *tmpnode = NULL;
  5353.   if (custnode!=NULL)
  5354.   { theSuprSprayDraw.bboxpt=new boxlst[count];
  5355.     int cgen;
  5356.     for (int tcount=0;tcount<count;tcount++)
  5357.     { TimeValue tofs=(ocount>0?times.tl[tcount].tl:t);
  5358.      cgen=(times.tl.Count()>0?times.tl[tcount].gennum-1:-1);
  5359.      if ((cgen>-1)&&(cgen<nlist.Count()))
  5360.      { if ((tmpnode=nlist[cgen]) == NULL) tmpnode=custnode;
  5361.      } else tmpnode=custnode;
  5362.      theSuprSprayDraw.bboxpt[tcount].bpts.SetCount(tabmax);
  5363.       theSuprSprayDraw.bboxpt[tcount].numboxes=0;
  5364.       Matrix3 ctm = tmpnode->GetObjTMAfterWSM(tofs);
  5365.       boxcenter=Zero*ctm;
  5366.      if (tmpnode->IsGroupHead())
  5367.        DoGroupBB(tmpnode,subtree,&(theSuprSprayDraw.bboxpt[tcount].numboxes),&tabmax,boxcenter,tofs,tcount,tmpnode);
  5368.      else
  5369.       GetNextBB(tmpnode,subtree,&(theSuprSprayDraw.bboxpt[tcount].numboxes),&tabmax,boxcenter,tofs,tcount,tmpnode);
  5370.      theSuprSprayDraw.bboxpt[tcount].bpts.SetCount(theSuprSprayDraw.bboxpt[tcount].numboxes);
  5371.     theSuprSprayDraw.bboxpt[tcount].bpts.Shrink();
  5372.     }
  5373.   }
  5374. }
  5375.  
  5376. void CommonParticle::CheckTree(INode *node,Matrix3 tspace,Mesh *cmesh,int *numV,int *numF,int *tvnum,int *ismapped,TimeValue t,int subtree,int custmtl)
  5377. { Object *pobj;    
  5378.   TriObject *triOb;
  5379.   Point3 deftex=Point3(0.5f,0.5f,0.0f);
  5380.   TVFace Zerod;
  5381.   Zerod.t[0]=0;Zerod.t[1]=0;Zerod.t[2]=0;
  5382.   int nc,i,j,subv=0,subf=0,subtvnum=0,tface,tvert;
  5383.  
  5384.   if (subtree)
  5385.   { if ((nc=node->NumberOfChildren())>0)
  5386.    for (i=0;i<nc;i++)
  5387.      CheckTree(node->GetChildNode(i),tspace,cmesh,numV,numF,tvnum,ismapped,t,subtree,custmtl);
  5388.   }
  5389.   if ((triOb=TriIsUseable(pobj = node->EvalWorldState(t).obj,t))!=NULL)
  5390.   {   Point3 Suboffset;
  5391.     Matrix3 ctm = node->GetObjTMAfterWSM(t);
  5392. /* if (node!=custnode)
  5393.      Suboffset=Point3(0.0f,0.0f,0.0f)*ctm-boxcenter;
  5394.    else
  5395.       Suboffset=Point3(0.0f,0.0f,0.0f);
  5396.    ctm.NoTrans();*/
  5397.    int submtls=0;
  5398.    Mtl* m=node->GetMtl();
  5399.    if (!((m!=NULL)&&(submtls=m->NumSubMtls()) != 0))
  5400.      submtls=-1;
  5401.    int tottv;
  5402.    subv=triOb->GetMesh().getNumVerts();
  5403.     subf=triOb->GetMesh().getNumFaces();
  5404.     subtvnum=triOb->GetMesh().getNumTVerts();
  5405.     cmesh->setNumFaces(tface=(*numF+subf),(*numF>0?TRUE:FALSE));
  5406.     cmesh->setNumVerts(tvert=(*numV+subv),(*numV>0?TRUE:FALSE));
  5407.     cmesh->setNumTVerts(tottv=(*tvnum+subtvnum),(*tvnum>0?TRUE:FALSE));
  5408.     if ((subtvnum>0)||(*ismapped))
  5409.     { if ((!(*ismapped))&&(*numF>0))
  5410.      { cmesh->setNumTVFaces(tface);
  5411.        *tvnum=1;
  5412.       cmesh->setNumTVerts(tottv+1);
  5413.       cmesh->tVerts[0]=deftex;
  5414.       for (int k=0;k<*numF;k++)
  5415.         memcpy(&(cmesh->tvFace[k]),&Zerod,sizeof(TVFace));
  5416.       }
  5417.      else
  5418.       cmesh->setNumTVFaces(tface,(*numF>0?TRUE:FALSE),*numF);
  5419.      *ismapped=1;
  5420.    }
  5421.    if (subf>0)
  5422.    { memcpy(&(cmesh->faces[*numF]),triOb->GetMesh().faces,sizeof(Face)*subf);
  5423.      if (subtvnum>0)
  5424.        memcpy(&(cmesh->tvFace[*numF]),triOb->GetMesh().tvFace,sizeof(TVFace)*subf);
  5425.    }
  5426.    BOOL mirror=DotProd(ctm.GetRow(0)^ctm.GetRow(1),ctm.GetRow(2))<0.0f;
  5427.    for (j=(*numF);j<tface;j++)
  5428.    { cmesh->faces[j].v[0]+=*numV;
  5429.      cmesh->faces[j].v[1]+=*numV;
  5430.      cmesh->faces[j].v[2]+=*numV;
  5431.      if (mirror) MirrorFace(&cmesh->faces[j]);
  5432.      if (custmtl)
  5433.      { if (submtls<0) cmesh->faces[j].setMatID(CustMtls);
  5434.      else cmesh->faces[j].setMatID(cmesh->faces[j].getMatID()+CustMtls);
  5435.      }
  5436.      if (subtvnum>0)
  5437.      { cmesh->tvFace[j].t[0]+=*tvnum;
  5438.        cmesh->tvFace[j].t[1]+=*tvnum;
  5439.        cmesh->tvFace[j].t[2]+=*tvnum;
  5440.       if (mirror) MirrorTVs(&cmesh->tvFace[j]);
  5441.      }
  5442.      else if (*ismapped)
  5443.        memcpy(&(cmesh->tvFace[j]),&Zerod,sizeof(TVFace));
  5444.    }
  5445.    if (subtvnum>0)
  5446.       memcpy(&(cmesh->tVerts[*tvnum]),triOb->GetMesh().tVerts,sizeof(UVVert)*subtvnum);
  5447. // if (subv) memcpy(&(clst->v[*numV]),triOb->mesh.verts,sizeof(Point3)*subv);
  5448.    int k=0;
  5449.    ctm=ctm*tspace;
  5450. /* Matrix3 objoff(1);
  5451.    Point3 pos = node->GetObjOffsetPos();objoff.PreTranslate(pos);
  5452.    Quat quat = node->GetObjOffsetRot();PreRotateMatrix(objoff, quat);
  5453.    ScaleValue scaleValue = node->GetObjOffsetScale();ApplyScaling(objoff, scaleValue);*/
  5454.    for (j=*numV;j<tvert;j++)
  5455.    { cmesh->verts[j]=(triOb->GetMesh().verts[k]*ctm);//+Suboffset;
  5456.      k++;
  5457.    }
  5458.  
  5459.    // Multiple Channel Map Support (single line)
  5460.    CopyMultipleMapping(cmesh, triOb, numF, tface, deftex, Zerod, subf, mirror);
  5461.  
  5462.    *numV+=subv;
  5463.    *numF+=subf;
  5464.    *tvnum+=subtvnum;
  5465.    if (submtls>0)
  5466.    CustMtls+=submtls;
  5467.    else CustMtls++;
  5468.    if (triOb!=pobj) triOb->DeleteThis();
  5469.   }
  5470. }
  5471.  
  5472. void CommonParticle::TreeDoGroup(INode *node,Matrix3 tspace,Mesh *cmesh,int *numV,int *numF,int *tvnum,int *ismapped,TimeValue t,int subtree,int custmtl)
  5473. { int nc;
  5474.   if ((nc=node->NumberOfChildren())>0)
  5475.    for (int j=0;j<nc;j++)
  5476.    { INode *nxtnode=node->GetChildNode(j);
  5477.      if (nxtnode->IsGroupHead()) TreeDoGroup(nxtnode,tspace,cmesh,numV,numF,tvnum,ismapped,t,subtree,custmtl);
  5478.      else if ((subtree)||(nxtnode->IsGroupMember())) CheckTree(nxtnode,tspace,cmesh,numV,numF,tvnum,ismapped,t,subtree,custmtl);
  5479.    }
  5480. }
  5481.  
  5482. void CommonParticle::GetMesh(TimeValue t,int subtree,int custmtl)
  5483. {  int tnums = 0, numV = 0, numF = 0, tvnum = 0, ismapped = 0;
  5484.    INode *tmpnode = NULL;
  5485.    tnums=times.tl.Count();
  5486.    if (tnums==0) tnums=1;
  5487.    if (cmesh) delete[] cmesh;cmesh=NULL;
  5488.    if (custnode!=NULL)
  5489.    { cmesh=new Mesh[tnums];
  5490.      int cgen;
  5491.     for (int i=0;i<tnums;i++)
  5492.    { TimeValue tofs=(tnums>1?times.tl[i].tl:t);
  5493.      cgen=(times.tl.Count()>0?times.tl[i].gennum-1:-1);
  5494.      if ((cgen>-1)&&(cgen<nlist.Count()))
  5495.      { if ((tmpnode=nlist[cgen]) == NULL) tmpnode=custnode;
  5496.      } else tmpnode=custnode;
  5497.      Matrix3 ptm = tmpnode->GetObjTMAfterWSM(tofs);
  5498.      Matrix3 topspace=Inverse(ptm);
  5499.      numV=numF=tvnum=CustMtls=ismapped=0;
  5500.      if (tmpnode->IsGroupHead())
  5501.       TreeDoGroup(tmpnode,topspace,&cmesh[i],&numV,&numF,&tvnum,&ismapped,tofs,subtree,custmtl);
  5502.      else
  5503.       CheckTree(tmpnode,topspace,&cmesh[i],&numV,&numF,&tvnum,&ismapped,tofs,subtree,custmtl);
  5504.    }
  5505.    }
  5506. }
  5507. /*void ResizeAllParts(ParticleSys &parts,int c)
  5508. { parts.points.Resize(c);parts.points.SetCount(c);
  5509.   parts.vels.Resize(c);parts.vels.SetCount(c);
  5510.   parts.ages.Resize(c);parts.ages.SetCount(c);
  5511.   parts.radius.Resize(c);parts.radius.SetCount(c);
  5512.   parts.tension.Resize(c);parts.tension.SetCount(c);
  5513. }*/
  5514.  
  5515. void CommonParticle::DoSpawn(int j,int spmult,SpawnVars spvars,TimeValue lvar,BOOL emit)
  5516. { if (!emit) spmult--;
  5517.   int oldcount,newcount=((oldcount=parts.Count())+spmult);
  5518.   srand(rseed);
  5519.   if (spmult)
  5520.   {   parts.SetCount(newcount,PARTICLE_VELS|PARTICLE_AGES|PARTICLE_RADIUS|PARTICLE_TENSION);
  5521.    CSavePt *tmp=sdata;
  5522.    sdata=new CSavePt[newcount];
  5523.    if (tmp)
  5524.    { for (int j=0;j<oldcount;j++) sdata[j]=tmp[j];
  5525.      delete[] tmp;
  5526.    }
  5527.   }
  5528.   int Lcnt=llist.Count();
  5529.   int baselife=(Lcnt==0?deftime:(sdata[j].gennum<Lcnt?llist[sdata[j].gennum]:llist[Lcnt-1]))*GetTicksPerFrame();
  5530.   if (!emit)
  5531.   { sdata[j].gennum++;
  5532.    parts.ages[j]=0;}
  5533.   Point3 holdv=(emit?-parts.vels[j]:parts.vels[j]);
  5534.   for (int i=oldcount;i<newcount;i++)
  5535.   { parts.points[i]=parts.points[j];
  5536.     parts.vels[i]=holdv;
  5537.    parts.radius[i]=parts.radius[j];
  5538.    parts.tension[i]=parts.tension[j];
  5539.    parts.ages[i]=0;
  5540.    memcpy(&sdata[i],&sdata[j],sizeof(CSavePt));
  5541.    if (emit) sdata[i].gennum++;
  5542.     parts.vels[i]=DoSpawnVars(spvars,parts.vels[j],holdv,&parts.radius[i],&sdata[i].W);
  5543.    sdata[i].Vsz=parts.radius[i];
  5544.    sdata[i].L=baselife+(int)RND11()*lvar;
  5545.    sdata[i].Mltvar=RND11();
  5546.    sdata[i].SpVar=RND0x(99);
  5547.    sdata[i].DL=-1;
  5548.  }
  5549.   if (!emit)
  5550.   { parts.vels[j]=DoSpawnVars(spvars,parts.vels[j],holdv,&parts.radius[j],&sdata[j].W);
  5551.     sdata[j].Vsz=parts.radius[j];
  5552.     sdata[j].L=baselife+(int)RND11()*lvar;
  5553.       sdata[j].Mltvar=RND11();
  5554.       sdata[j].SpVar=RND0x(99);
  5555.       sdata[j].DL=-1;
  5556.   }
  5557.   int tmprseed=rand();
  5558.   rseed=(tmprseed==rseed?rand():tmprseed);
  5559. }
  5560.  
  5561. #define VEL_SCALE (0.01f*1200.0f/float(TIME_TICKSPERSEC))
  5562. #define VAR_SCALE (0.01f*1200.0f/float(TIME_TICKSPERSEC))
  5563.  
  5564. BOOL SuprSprayParticle::ComputeParticleStart(TimeValue t0,int c)
  5565.    {
  5566.    int seed,anioff,tani;
  5567.    TimeValue anifr;
  5568.    if (c > gCountUpperLimit) c = gCountUpperLimit;
  5569.    pblock->GetValue(PB_RNDSEED,t0,seed,FOREVER);
  5570.     pblock->GetValue(PB_OFFSETAMOUNT,t0,anifr,FOREVER);
  5571.     pblock->GetValue(PB_ANIMATIONOFFSET,t0,anioff,FOREVER);
  5572.    srand(seed);              
  5573.    parts.SetCount(c,PARTICLE_VELS|PARTICLE_AGES|PARTICLE_RADIUS|PARTICLE_TENSION);
  5574.    int pcount=parts.Count();
  5575.     if (sdata){delete[] sdata;sdata=NULL;} if (pcount) sdata=new CSavePt[pcount];
  5576.    if ((pcount<c)||(c>0 && (!sdata)))
  5577.    {   parts.FreeAll();if (sdata) delete sdata;sdata=NULL;maincount=0;
  5578.       BOOL playing=GetCOREInterface()->IsAnimPlaying();
  5579.       if (playing) GetCOREInterface()->EndAnimPlayback();
  5580.        TSTR name;name=(cnode ? cnode->GetName() : TSTR(GetString(IDS_AP_SUPRSPRAY)));
  5581.       TSTR buf; buf=TSTR(GetString(IDS_OFM_PART));
  5582.       GetCOREInterface()->Log()->LogEntry(SYSLOG_ERROR,DISPLAY_DIALOG,
  5583.          GetString(IDS_OFM_ERROR),_T("%s: \n\n%s\n"),buf,name);
  5584.      return (0);
  5585.    }
  5586.    float tmp;
  5587.    int oneframe=GetTicksPerFrame();
  5588.    for (int i=0; i<parts.Count(); i++) {
  5589.       parts.ages[i] = -1;
  5590.       sdata[i].themtl=0;
  5591.       sdata[i].L=RND0x(99);sdata[i].DL=-1;sdata[i].pvar=RND11();
  5592.       tmp=RND01();sdata[i].Fo=tmp;
  5593.       tani=RND0x(anifr/oneframe);
  5594.       sdata[i].showframe=(anioff==2?tani*oneframe:0);
  5595.       sdata[i].gennum=0;
  5596.       sdata[i].V.x=RND11();
  5597.       sdata[i].V.y=RND11();
  5598.       sdata[i].V.z=RND11();
  5599.       sdata[i].Ts0=RND11();
  5600.       sdata[i].Ts=0.0f;
  5601.       sdata[i].LamTs=RND11();
  5602.       sdata[i].A=RND11();
  5603.       sdata[i].LamA=RND11();
  5604.       tmp=RND11();sdata[i].M=tmp;
  5605.       // Martell 4/14/01: Fix for order of ops bug.
  5606.       float ztmp=RND11(); float ytmp=RND11(); float xtmp=RND11();
  5607.       parts.vels[i]=Point3(xtmp,ytmp,ztmp);
  5608.       sdata[i].To=RND11();
  5609.       sdata[i].Vsz=RND11();
  5610.       // Martell 4/14/01: Fix for order of ops bug.
  5611.       ztmp=RND11(); ytmp=RND11(); xtmp=RND11();
  5612.       sdata[i].W=Point3(xtmp,ytmp,ztmp);
  5613.       // Martell 4/14/01: Fix for order of ops bug.
  5614.       ztmp=RND11(); ytmp=RND11(); xtmp=RND11();
  5615.       sdata[i].RV=Point3(xtmp,ytmp,ztmp);
  5616.       tmp=RND11();sdata[i].Dis=tmp;
  5617.       parts.radius[i]=0.0f;
  5618.       parts.tension[i]=RND11();
  5619.       sdata[i].Mltvar=RND11();
  5620.       sdata[i].SpVar=RND0x(99);
  5621.       }
  5622.    tvalid = t0-1;
  5623.    valid  = TRUE;
  5624.    rseed=rand();
  5625.    return (1);
  5626.    }
  5627.  
  5628. void SuprSprayParticle::BirthParticle(INode *node,TimeValue bt,int num,VelDir* ptvel,Matrix3 tmlast)
  5629. {
  5630.    Matrix3 tm = node->GetObjTMBeforeWSM(bt);
  5631.    Matrix3 atm = node->GetObjTMAfterWSM(bt);
  5632.    tm.SetRow(3,atm.GetRow(3));
  5633.    Point3 vel;
  5634.    float Ie,Em,Vm;
  5635.    int RotSampleOn;
  5636.    srand(rseed);
  5637.  
  5638.    pblock->GetValue(PB_EMITVINFL,bt,Ie,FOREVER);
  5639.    pblock->GetValue(PB_EMITVMULT,bt,Em,FOREVER);
  5640.    pblock->GetValue(PB_EMITVMULTVAR,bt,Vm,FOREVER);
  5641.    pblock->GetValue(PB_SUBFRAMEROT,bt,RotSampleOn,FOREVER);
  5642.  
  5643.    int MotionOffset,EmitOffset;
  5644.  
  5645.    pblock->GetValue(PB_SUBFRAMEMOVE,bt,MotionOffset,FOREVER);
  5646.    pblock->GetValue(PB_SUBFRAMETIME,bt,EmitOffset,FOREVER);
  5647.  
  5648.    sdata[num].Ts0 = (1.0f + sdata[num].Ts0*ptvel->VSpin)/TWOPI;
  5649.    sdata[num].Ts = (float)ptvel->Spin*sdata[num].Ts0;
  5650.    parts.tension[num] = ptvel->bstr*(1.0f + parts.tension[num]*ptvel->bstrvar);
  5651.    sdata[num].persist = (TimeValue)(ptvel->persist*(1.0f + sdata[num].pvar*ptvel->pvar));
  5652. // ok, so I'm using L for M and .z for L.  They were unused float and ints
  5653.    sdata[num].M = (sdata[num].L<Ie?Em*(1 + sdata[num].M*Vm):0);  
  5654.    sdata[num].L = ptvel->Life + (int)(parts.vels[num].z*ptvel->Vl);
  5655.    sdata[num].Vsz *= ptvel->VSz;
  5656.    sdata[num].LamTs = ptvel->Phase*(1.0f + sdata[num].LamTs*ptvel->VPhase);
  5657.  
  5658.    sdata[num].A = ptvel->ToAmp*(1.0f + sdata[num].A*ptvel->VToAmp);
  5659.    sdata[num].LamA = ptvel->ToPhase*(1 + sdata[num].LamA*ptvel->VToPhase);
  5660.    sdata[num].To = ptvel->ToPeriod*(1 + sdata[num].To*ptvel->VToPeriod);
  5661.  
  5662.    if (ptvel->axisentered==2)
  5663.    {  sdata[num].W = Normalize(ptvel->Axis);
  5664.       if (ptvel->axisvar>0.0f)
  5665.          VectorVar(&sdata[num].W,ptvel->axisvar,180.0f);
  5666.    }
  5667.    else
  5668.       sdata[num].W = Normalize(sdata[num].W);
  5669.  
  5670.    parts.ages[num] = 0;
  5671.    float Thetav,Thetah,SSv,SCv;
  5672.    Thetav = ptvel->Av180+ptvel->VAv*parts.vels[num].x;
  5673.    Thetah = ptvel->Ah180+ptvel->VAh*parts.vels[num].y;
  5674.    SSv = (float)sin(Thetav);
  5675.    SCv = (float)cos(Thetav);
  5676.    vel.y = (float)(SSv*sin(Thetah));
  5677.    vel.x = (float)(SSv*cos(Thetah));
  5678.    vel.z = SCv;
  5679.  
  5680.    Matrix3 OffRotTm;
  5681.    if (RotSampleOn)
  5682.       MakeInterpRotXform(tmlast,tm,(1.0f - sdata[num].Fo),OffRotTm);
  5683.    else
  5684.       OffRotTm = tm;
  5685.  
  5686.    vel = VectorTransform(OffRotTm,vel); //speed value and direction according to orientation
  5687.  
  5688.    vel = vel*ptvel->Speed*(1.0f + sdata[num].V.z*ptvel->VSpeed); // speed variation
  5689.  
  5690.    parts[num] = tm.GetRow(3);
  5691.  
  5692.    if (MotionOffset)
  5693.       parts[num] = ptvel->bps.Position(1.0f - sdata[num].Fo);
  5694.  
  5695.    if (EmitOffset)
  5696.       parts[num] += vel*(sdata[num].Fo);
  5697. //    parts[num] -= (sdata[num].Fo)*vel;
  5698.  
  5699.    if (sdata[num].M != 0.0f)
  5700.    {
  5701.       Point3 inhVel = ptvel->bps.Speed(1.0f - sdata[num].Fo);
  5702.       parts[num] += inhVel*sdata[num].M*sdata[num].Fo;
  5703.       vel += inhVel*sdata[num].M; // motion inheritance
  5704.    }
  5705.  
  5706.    vel /= (float)GetTicksPerFrame();
  5707.  
  5708.    parts.vels[num] = vel;
  5709.    sdata[num].V = parts[num];
  5710.    rseed = rand();
  5711. }
  5712.  
  5713. void SuprSprayParticle::MovePart(int j,TimeValue dt,BOOL fullframe,int tpf)
  5714. {  parts[j] = sdata[j].V+parts.vels[j] * (float)dt;
  5715.    // add transverse oscillation
  5716.    if (fullframe) sdata[j].V=parts[j];
  5717.    Point3 DotPt=(FGT0(parts.vels[j]*(float)tpf)?parts.vels[j]:sdata[j].W);
  5718.    DotPt=sdata[j].RV^DotPt;            // Cross Product
  5719.    DotPt=Normalize(DotPt);        
  5720.    float oscil=(sdata[j].To>0.0f?parts.ages[j]*TWOPI/sdata[j].To:0.0f);
  5721.    oscil=sdata[j].A*(float)sin(oscil+sdata[j].LamA);
  5722.    parts[j] +=DotPt*oscil;
  5723. }
  5724.  
  5725.  
  5726. void SuprSprayParticle::UpdateParticles(TimeValue t,INode *node)
  5727. {  TimeValue t0,dt,t2,grow,fade;
  5728.    int i, j, birth,counter,tpf=GetTicksPerFrame(),count=0,anioff;
  5729.    VelDir ptvel;
  5730.    int isrend=TestAFlag(A_RENDER),bmethod,onscreen,oneframe;
  5731.    TimeValue c(0);
  5732.    // variable for new collision scheme (Bayboro 2/5/01)
  5733.    CollisionCollection cc;
  5734.  
  5735.    // fix for "Abort by Escape key" problem (Bayboro 1/31/01)
  5736.    if (cancelled && (tvalid == t)) return;
  5737.    if (cancelled && valid) tvalid = TIME_NegInfinity;
  5738.    cancelled = FALSE;  
  5739.  
  5740.    // initialization for new collision scheme (Bayboro 2/5/01)
  5741.    cc.Init(cobjs);
  5742.  
  5743.    // The size of steps we take to integrate will be frame size steps.
  5744.    oneframe=GetTicksPerFrame();
  5745.    if (stepSize!=oneframe)
  5746.    {  stepSize = oneframe;
  5747.       valid = FALSE;
  5748.    }
  5749.    float FperT = GetFrameRate()/(float)TIME_TICKSPERSEC;
  5750.     pblock->GetValue(PB_ANIMATIONOFFSET,t,anioff,FOREVER);
  5751.    pblock->GetValue(PB_EMITSTART,t,t0,FOREVER);
  5752.    pblock->GetValue(PB_SIZE,t,parts.size,FOREVER);
  5753.    pblock->GetValue(PB_BIRTHMETHOD,0,bmethod,FOREVER);
  5754.    pblock->GetValue(PB_VIEWPORTSHOWS,0,onscreen,FOREVER);
  5755.    pblock->GetValue(PB_EMITSTOP,0,t2,FOREVER);
  5756.    if (bmethod)
  5757.       pblock->GetValue(PB_PTOTALNUMBER,0,c,FOREVER);
  5758.    int subtree,frag,custmtl=0;
  5759.     pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  5760.    pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  5761.    pblock->GetValue(PB_PARTICLECLASS,0,frag,FOREVER);
  5762.  
  5763.    // Before the start time, nothing is happening
  5764.    if (t < t0)
  5765.    {  parts.FreeAll();
  5766.       if (sdata)
  5767.       {  delete[] sdata;
  5768.          sdata=NULL;
  5769.       }
  5770.       ResetSystem(t);
  5771.       return;
  5772.    }
  5773.    int pkind;
  5774.    float dpercent;
  5775.    pblock->GetValue(PB_DISPLAYPORTION,0,dpercent,FOREVER);
  5776.    pblock->GetValue(PB_PARTICLETYPE,0,pkind,FOREVER);
  5777.  
  5778.    // Set the particle system to the initial condition
  5779.    if ((!valid || t<tvalid) || tvalid<t0)
  5780.    {   int cincr;
  5781.       if (!bmethod)
  5782.       {  c=0;
  5783.          for (TimeValue ti=t0;ti<=t2;ti+=oneframe)
  5784.          {  pblock->GetValue(PB_PBIRTHRATE,ti,cincr,FOREVER);
  5785.             if (cincr<0) cincr=0;
  5786.             c += cincr;
  5787.          }
  5788.       }
  5789.       if (!isrend)
  5790.          c=(int)(dpercent*(float)c+FTOIEPS);
  5791.       if (!ComputeParticleStart(t0,c))
  5792.       { ResetSystem(t);
  5793.         return;
  5794.       }
  5795.       dispt=t-1;
  5796.       maincount=parts.Count();
  5797.       ResetSystem(t,FALSE);
  5798.    }
  5799.    int total;
  5800.    total=maincount;
  5801.    valid = TRUE;
  5802.    int stype,maxgens,spmultb;
  5803.    float spawnbvar;
  5804.     pblock->GetValue(PB_SPAWNTYPE,0,stype,FOREVER);
  5805.     pblock->GetValue(PB_SPAWNGENS,0,maxgens,FOREVER);
  5806.     pblock->GetValue(PB_SPAWNCOUNT,0,spmultb,FOREVER);
  5807.     pblock->GetValue(PB_SPINAXISTYPE,0,ptvel.axisentered,FOREVER);
  5808.    SpawnVars spawnvars;
  5809.    spawnvars.axisentered=ptvel.axisentered;
  5810.    TimeValue dis;
  5811.     pblock->GetValue(PB_DISPUNTIL,0,dis,FOREVER);
  5812.  
  5813.    if (t2<t0)
  5814.       t2 = t0;
  5815.    TimeValue fstep=oneframe;
  5816.  
  5817. // t2+=fstep;
  5818.    TimeValue createover;
  5819.    createover = t2-t0+oneframe;
  5820.    counter = (isrend?rcounter:vcounter);
  5821.    float frate,grate;
  5822.    pblock->GetValue(PB_GROWTIME,0,grow,FOREVER);
  5823.     pblock->GetValue(PB_FADETIME,0,fade,FOREVER);
  5824.    frate=(fade>0.0f?(1-M)/fade:0.0f);
  5825.    grate=(grow>0.0f?(1-M)/grow:0.0f);
  5826.    float basesize;
  5827.    BOOL fullframe;
  5828.    if (!isrend)
  5829.    {  int offby=t%oneframe;
  5830.       if (offby!=0)
  5831.          t-=offby;
  5832.    }
  5833.    pblock->GetValue(PB_SPAWNSCALESIGN,0,spawnvars.scsign,FOREVER);
  5834.     pblock->GetValue(PB_SPAWNSPEEDSIGN,0,spawnvars.spsign,FOREVER);
  5835.     pblock->GetValue(PB_SPAWNINHERITV,0,spawnvars.invel,FOREVER);
  5836.     pblock->GetValue(PB_SPAWNSPEEDFIXED,0,spawnvars.spconst,FOREVER);
  5837.     pblock->GetValue(PB_SPAWNSCALEFIXED,0,spawnvars.scconst,FOREVER);
  5838.    int sper,spmult;
  5839.    float smper;BOOL first=(tvalid<t0);
  5840.    while ((tvalid < t)&&(tvalid<=dis))
  5841.    {  int born = 0;
  5842.        count=0;
  5843.       if (first)
  5844.          tvalid=t0;
  5845.       // Compute our step size
  5846.       if (tvalid%stepSize !=0)
  5847.       {  dt = stepSize - abs(tvalid)%stepSize;
  5848.       }
  5849.       else
  5850.       {  dt = stepSize;
  5851.       }
  5852.       if (tvalid + dt > t)
  5853.       {  dt = t-tvalid;
  5854.       }
  5855.  
  5856.       // Increment time
  5857.       if (!first)
  5858.          tvalid += dt;
  5859.       if (tvalid>dis)
  5860.       {  for (j=0; j<parts.Count(); j++)
  5861.          {  parts.ages[j] = -1;  
  5862.          }
  5863.          tvalid=t;
  5864.          continue;
  5865.       }
  5866.       // Compute the number of particles that should be born!
  5867.       birth=0;
  5868.       fullframe=(tvalid%tpf==0);
  5869.       if (fullframe)
  5870.       {  if (bmethod)
  5871.          {  int tdelta;
  5872.             if (tvalid>=t2)
  5873.                birth=total-counter;
  5874.             else
  5875.             {  tdelta=int((float)total*(tvalid-t0+oneframe)/createover);
  5876.                birth=tdelta-counter;
  5877.             }
  5878.          }
  5879.          else if (tvalid<=t2)
  5880.          {  pblock->GetValue(PB_PBIRTHRATE,tvalid,total,FOREVER);
  5881.             if (!isrend)
  5882.                total = (int)(dpercent*(float)total+FTOIEPS);
  5883.             birth=total;
  5884.             if (birth+counter>maincount)
  5885.                birth=0;
  5886.          }
  5887.       }
  5888.        pblock->GetValue(PB_SSSPAWNDIEAFTER,tvalid,ptvel.persist,FOREVER);
  5889.        pblock->GetValue(PB_SSSPAWNDIEAFTERVAR,tvalid,ptvel.pvar,FOREVER);
  5890.        pblock->GetValue(PB_SPEED,tvalid,ptvel.Speed,FOREVER);
  5891.       pblock->GetValue(PB_SPEEDVAR,tvalid,ptvel.VSpeed,FOREVER);
  5892.       pblock->GetValue(PB_SIZE,tvalid,ptvel.Size,FOREVER);
  5893.       pblock->GetValue(PB_OFFAXIS,tvalid,ptvel.Av180,FOREVER);
  5894.       pblock->GetValue(PB_AXISSPREAD,tvalid,ptvel.VAv,FOREVER);
  5895.       pblock->GetValue(PB_OFFPLANE,tvalid,ptvel.Ah180,FOREVER);
  5896.       pblock->GetValue(PB_PLANESPREAD,tvalid,ptvel.VAh,FOREVER);
  5897.       pblock->GetValue(PB_LIFE,tvalid,ptvel.Life,FOREVER);
  5898.       pblock->GetValue(PB_LIFEVAR,tvalid,ptvel.Vl,FOREVER);
  5899.       pblock->GetValue(PB_SPINTIME,tvalid,ptvel.Spin,FOREVER);
  5900.       pblock->GetValue(PB_SPINTIMEVAR,tvalid,ptvel.VSpin,FOREVER);
  5901.       pblock->GetValue(PB_SPINPHASE,tvalid,ptvel.Phase,FOREVER);
  5902.       pblock->GetValue(PB_SPINPHASEVAR,tvalid,ptvel.VPhase,FOREVER);
  5903.       pblock->GetValue(PB_SIZEVAR,tvalid,ptvel.VSz,FOREVER);
  5904.        pblock->GetValue(PB_METATENSION,tvalid,ptvel.bstr,FOREVER);
  5905.       pblock->GetValue(PB_METATENSIONVAR,tvalid,ptvel.bstrvar,FOREVER);
  5906.       pblock->GetValue(PB_BUBLAMP,tvalid,ptvel.ToAmp,FOREVER);
  5907.       pblock->GetValue(PB_BUBLAMPVAR,tvalid,ptvel.VToAmp,FOREVER);
  5908.       pblock->GetValue(PB_BUBLPHAS,tvalid,ptvel.ToPhase,FOREVER);
  5909.       pblock->GetValue(PB_BUBLPHASVAR,tvalid,ptvel.VToPhase,FOREVER);
  5910.       pblock->GetValue(PB_BUBLPER,tvalid,ptvel.ToPeriod,FOREVER);
  5911.       pblock->GetValue(PB_BUBLPERVAR,tvalid,ptvel.VToPeriod,FOREVER);
  5912.        pblock->GetValue(PB_SPAWNDIRCHAOS,tvalid,spawnvars.dirchaos,FOREVER);
  5913.        pblock->GetValue(PB_SPAWNSPEEDCHAOS,tvalid,spawnvars.spchaos,FOREVER);
  5914.       spawnvars.spchaos/=100.0f;
  5915.        pblock->GetValue(PB_SPAWNSCALECHAOS,tvalid,spawnvars.scchaos,FOREVER);
  5916.       spawnvars.scchaos/=100.0f;
  5917.        pblock->GetValue(PB_SPAWNPERCENT,tvalid,sper,FOREVER);  
  5918.       pblock->GetValue(PB_SPAWNMULTVAR,tvalid,smper,FOREVER);  
  5919.       spawnbvar=smper*spmultb;
  5920.       pblock->GetValue(PB_SPINAXISX,tvalid,ptvel.Axis.x,FOREVER);
  5921.       pblock->GetValue(PB_SPINAXISY,tvalid,ptvel.Axis.y,FOREVER);
  5922.       pblock->GetValue(PB_SPINAXISZ,tvalid,ptvel.Axis.z,FOREVER);
  5923.       if (Length(ptvel.Axis)==0.0f)
  5924.          ptvel.Axis.x=0.001f;
  5925.       pblock->GetValue(PB_SPINAXISVAR,tvalid,ptvel.axisvar,FOREVER);
  5926.       spawnvars.Axis=ptvel.Axis;
  5927.       spawnvars.axisvar=ptvel.axisvar;
  5928.       if (llist.Count()==0)
  5929.          deftime=ptvel.Life/oneframe;
  5930.       basesize=M*ptvel.Size;
  5931.       // First increment age and kill off old particles
  5932.       for (j=0;j<parts.Count();j++)
  5933.       {  if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  5934.          {  valid=FALSE;
  5935.             tvalid=t;
  5936.             cancelled=TRUE;
  5937.             parts.FreeAll();
  5938.             return;
  5939.          }
  5940.          if (!parts.Alive(j))
  5941.             continue;
  5942.          parts.ages[j] += dt;
  5943.          if (parts.ages[j] >= sdata[j].L)
  5944.          {  if ((stype!=ONDEATH)||(sdata[j].gennum>=maxgens)||(sdata[j].SpVar>=sper))
  5945.                parts.ages[j] = -1;  
  5946.             else if (fullframe)
  5947.             {  spmult=(int)(sdata[j].Mltvar*spawnbvar)+spmultb;
  5948.                if (spmult!=0)
  5949.                   DoSpawn(j,spmult,spawnvars,ptvel.Vl,FALSE);
  5950.                else
  5951.                   parts.ages[j] = -1;
  5952.             }
  5953.          }
  5954.          else if (sdata[j].DL>-1)
  5955.          {  sdata[j].DL+=dt;
  5956.             if (sdata[j].DL>sdata[j].persist)
  5957.                parts.ages[j]=-1;
  5958.          }
  5959.          if (parts.ages[j]>-1)
  5960.          {  if (fullframe && ((stype==EMIT)&&(sdata[j].gennum==0)&&(sdata[j].SpVar<sper)))
  5961.             {  spmult=(int)(sdata[j].Mltvar*spawnbvar)+spmultb;
  5962.                if (spmult!=0)
  5963.                   DoSpawn(j,spmult,spawnvars,ptvel.Vl,TRUE);
  5964.             }
  5965. //       if (pkind==RENDTYPE6)
  5966. //        parts.radius[j]=ptvel.Size; else
  5967.             if ((stype<2)||(maxgens==0))
  5968.                parts.radius[j]=FigureOutSize(parts.ages[j],ptvel.Size,grow,fade,sdata[j].L,grate,frate)*(1+sdata[j].Vsz);
  5969.             else
  5970.             {  if (sdata[j].gennum==0)
  5971.                   parts.radius[j]=FigureOutSize(parts.ages[j],ptvel.Size,grow,0,sdata[j].L,grate,frate)*(1+sdata[j].Vsz);
  5972.                else if (sdata[j].gennum==maxgens)
  5973.                   parts.radius[j]=FigureOutSize(parts.ages[j],sdata[j].Vsz,0,fade,sdata[j].L,grate,frate);
  5974.             }
  5975.          }
  5976.       }
  5977.       // Apply forces to modify velocity
  5978. //    if (fullframe)
  5979.       if (birth>0)
  5980.       {  Matrix3 tm,tmold;
  5981.          float stepCoef = 1.0f;
  5982.          TimeValue checkone = tvalid - t0;
  5983.  
  5984.          if (checkone < 0)
  5985.             checkone = -checkone;                  // ***** I just added this line
  5986.  
  5987.          if (checkone == 0)
  5988.             tmold = node->GetObjTMBeforeWSM(tvalid - stepSize);
  5989.          else
  5990.             tmold = node->GetObjTMBeforeWSM(checkone<stepSize?t0:(tvalid - stepSize));
  5991.  
  5992.          tm = node->GetObjTMBeforeWSM(tvalid);
  5993.          ptvel.bps.Init(node, tvalid, stepSize);
  5994.  
  5995.       // Next, birth particles at the birth rate
  5996.          for (j=counter; j<maincount; j++)
  5997.          {  if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  5998.             {  valid=FALSE;
  5999.                tvalid=t;cancelled=TRUE;
  6000.                parts.FreeAll();
  6001.                return;
  6002.             }
  6003.             if (born>=birth)
  6004.                break;
  6005.  
  6006.             BirthParticle(node,tvalid,j,&ptvel,tmold);
  6007. //          if ((pkind==RENDTYPE5)||(pkind==RENDTYPE6))
  6008. //             parts.radius[j]=ptvel.Size;  
  6009. //          else
  6010.             parts.radius[j]=(grow>0?basesize:ptvel.Size)*(1.0f + sdata[j].Vsz);
  6011.             sdata[j].themtl = int((tvalid-t0)*FperT);
  6012.             sdata[j].showframe = (anioff==1?0:sdata[j].showframe);
  6013.             born++;
  6014.             counter++;
  6015.          }
  6016.       }
  6017.       int fc=fields.Count();
  6018.  
  6019.       if (fc>0)
  6020.          for (j=0; j<parts.Count(); j++)
  6021.          {  Point3 force,tvel=Zero;
  6022.             for (i=0; i<fc; i++)
  6023.             {  if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  6024.                {  valid=FALSE;
  6025.                   tvalid=t;
  6026.                   cancelled=TRUE;
  6027.                   parts.FreeAll();
  6028.                   return;
  6029.                }
  6030.                if (!parts.Alive(j))
  6031.                   continue;
  6032.                parts[j]=sdata[j].V;
  6033.                force = fields[i]->Force(tvalid,parts[j],parts.vels[j],j);
  6034.                float curdt = (float)dt;
  6035.                if ((parts.ages[j]==0)&&(sdata[j].gennum==0))
  6036.                   curdt=tpf*sdata[j].Fo;
  6037.                tvel += 10.0f*force * curdt;
  6038.             }
  6039.             parts.vels[j]+=tvel;
  6040.          }
  6041.  
  6042. // IPC IPC IPC IPC ss
  6043.  
  6044.       int IPC,ipcsteps;float B,Vb;
  6045.       pblock->GetValue(PB_IPCOLLIDE_ON,tvalid,IPC,FOREVER);
  6046.       pblock->GetValue(PB_IPCOLLIDE_STEPS,tvalid,ipcsteps,FOREVER);
  6047.       pblock->GetValue(PB_IPCOLLIDE_BOUNCE,tvalid,B,FOREVER);
  6048.       pblock->GetValue(PB_IPCOLLIDE_BOUNCEVAR,tvalid,Vb,FOREVER);
  6049.       if (IPC)
  6050.       {  CollideParticle cp;
  6051.          int ddt=dt/ipcsteps,remtime=0,snum=0;
  6052.          TimeValue curt=tvalid;
  6053.          if (dt > 0)
  6054.          {  while (snum < ipcsteps)
  6055.             { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  6056.               {   valid=FALSE;
  6057.                tvalid=t;
  6058.                cancelled=TRUE;
  6059.                parts.FreeAll();
  6060.                return;
  6061.               }
  6062.               if (remtime==0) remtime=ddt;
  6063.               mindata md=cp.InterPartCollide(parts,cobjs,remtime,snum,B,Vb,curt,lc);
  6064.               for (j=0; j<parts.Count(); j++)
  6065.               {   if (parts.ages[j]>0)
  6066.                { if ((j!=md.min)&&(j!=md.min2))
  6067.                  { if (fullframe)
  6068.                     MovePart(j,md.mintime,fullframe,tpf);
  6069.                   else
  6070.                     parts[j]+=parts.vels[j]*(float)md.mintime;
  6071.                  }
  6072.                  else if (fullframe) sdata[j].V=parts[j];
  6073.                }
  6074.               }
  6075.             }
  6076.          }
  6077.       }
  6078.       else
  6079.          for (j=0; j<parts.Count(); j++)
  6080.          {  if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  6081.             {  valid=FALSE;
  6082.                tvalid=t;
  6083.                cancelled=TRUE;
  6084.                parts.FreeAll();
  6085.                return;
  6086.             }
  6087.             if ((!parts.Alive(j))||(parts.ages[j]==0))
  6088.                continue;
  6089.             count++;
  6090.  
  6091.          // Check for collisions
  6092.             BOOL collide = FALSE;
  6093.          // float meaninglesstime;
  6094.             float collisionTime, remTime = (float)dt;
  6095.             BOOL maybeStuck = FALSE;
  6096. //          for (int i=0; i<cobjs.Count(); i++)
  6097.             for (int i=0; i<cc.MAX_COLLISIONS_PER_STEP; i++)
  6098.             {  
  6099. //             if (cobjs[i]->CheckCollision(tvalid,parts[j],parts.vels[j], (float)dt, j,&meaninglesstime,TRUE))
  6100.                if (cc.CheckCollision(tvalid, parts[j], parts.vels[j], remTime, j, &collisionTime, FALSE))
  6101.                {
  6102.                   collide = TRUE;
  6103.                   remTime -= collisionTime;
  6104.                   if (remTime <= 0.0f) break; // time limit for the current inegration step
  6105.                }
  6106.                else break;
  6107.                if (i==cc.MAX_COLLISIONS_PER_STEP-1) maybeStuck = TRUE;
  6108.             }
  6109.             if (collide)
  6110.             {
  6111.                if (!maybeStuck) // if particle stuck we can't risk to propagate particle movement for the current frame
  6112.                   parts[j] += parts.vels[j] * remTime;
  6113.                if (stype==1)
  6114.                {  if (sdata[j].persist==0)
  6115.                   {  parts.ages[j] = -1;
  6116.                      count--;
  6117.                   }
  6118.                   else
  6119.                      sdata[j].DL=0;
  6120.                }
  6121.                else if (fullframe &&((stype==COLLIDE)&&(sdata[j].gennum<maxgens)&&(sdata[j].SpVar<sper)))
  6122.                {  int spmult=(int)(sdata[j].Mltvar*spawnbvar)+spmultb;
  6123.                   if (spmult!=0)
  6124.                      DoSpawn(j,spmult,spawnvars,ptvel.Vl,FALSE);
  6125.                }
  6126.             }
  6127.          // If we didn't collide, then increment.
  6128.             if (!collide)
  6129.                MovePart(j,dt,fullframe,tpf);
  6130.             else if (fullframe)
  6131.                sdata[j].V=parts[j];
  6132.          }
  6133.  
  6134. // end of code that will change to support IPC
  6135.  
  6136.       if (first)
  6137.          first=FALSE;
  6138.       for (j=0; j<parts.Count(); j++)
  6139.       {  sdata[j].Ts = (float)ptvel.Spin*sdata[j].Ts0;
  6140.          sdata[j].LamTs += (FloatEQ0(sdata[j].Ts)?0.0f:dt/sdata[j].Ts);
  6141.       }
  6142.    }  
  6143.  
  6144. /* if ((frag==METABALLS)&&((!isrend)&&(onscreen==2)))
  6145.    {  float res,bstr,thres=0.6f;
  6146.       pblock->GetValue(PB_METATENSION,t,bstr,FOREVER);
  6147.       pblock->GetValue(PB_METACOURSE,0,res,FOREVER);
  6148.       if (cmesh) delete[] cmesh;cmesh=new Mesh;
  6149.       metap.CreateMetas(parts,cmesh,thres,res,bstr);
  6150.    }
  6151.    else*/
  6152.    if ((frag==INSTGEOM)&&(onscreen>1)&&(custnode))
  6153.    {  TimeValue anist=GetAnimStart(),aniend=GetAnimEnd();
  6154.       theSuprSprayDraw.anifr=aniend+stepSize;
  6155.       theSuprSprayDraw.t=t;
  6156.       theSuprSprayDraw.anioff=anioff;
  6157.       if (count>0)
  6158.          GetTimes(times,t,theSuprSprayDraw.anifr,anioff);
  6159.       else
  6160.          times.tl.ZeroCount();
  6161.       if (onscreen==2)
  6162.          GetMesh(t,subtree,custmtl);
  6163.       else
  6164.          GetallBB(custnode,subtree,t);
  6165.    }  
  6166.    if (isrend)
  6167.       rcounter=counter;
  6168.    else
  6169.       vcounter=counter;
  6170.    if (tvalid<t)
  6171.       tvalid=t;
  6172.    valid=TRUE;
  6173. // ssert(tvalid==t);
  6174. }
  6175.  
  6176.  
  6177. void SuprSprayParticle::InvalidateUI()
  6178.    {
  6179.    if (pmapParam) pmapParam->Invalidate();
  6180.    if (pmapPGen) pmapPGen->Invalidate();
  6181.    if (pmapPType) pmapPType->Invalidate();
  6182.    if (pmapPSpin) pmapPSpin->Invalidate();
  6183.    if (pmapEmitV) pmapEmitV->Invalidate();
  6184.    if (pmapBubl) pmapBubl->Invalidate();
  6185.    if (pmapSpawn) pmapSpawn->Invalidate();
  6186.    }
  6187.  
  6188. BOOL CommonParticle::EmitterVisible()
  6189.    {
  6190.    int hide;
  6191.    pblock->GetValue(PB_EMITRHID,0,hide,FOREVER);
  6192.    return !hide;
  6193.    }
  6194.  
  6195. ParamDimension *SuprSprayParticle::GetParameterDim(int pbIndex)
  6196.    {
  6197.    switch (pbIndex) {
  6198.       case PB_SPEED:
  6199.       case PB_SIZE:
  6200.       case PB_METATENSION:
  6201.       case PB_METACOURSE:
  6202.       case PB_MAPPINGDIST:
  6203.       case PB_SPINAXISX:
  6204.       case PB_SPINAXISY:
  6205.       case PB_SPINAXISZ:
  6206.       case PB_EMITVMULT:
  6207.       case PB_BUBLAMP:
  6208.       case PB_EMITRWID:          return stdWorldDim;
  6209.  
  6210.       case PB_RNDSEED:
  6211.       case PB_PBIRTHRATE:
  6212.       case PB_PTOTALNUMBER:
  6213.                            return defaultDim;
  6214.  
  6215.       case PB_OFFAXIS:
  6216.       case PB_AXISSPREAD:
  6217.       case PB_OFFPLANE:
  6218.       case PB_PLANESPREAD:
  6219.       case PB_SPINPHASE:
  6220.       case PB_SPINAXISVAR:
  6221.       case PB_BUBLPHAS:       return stdAngleDim;
  6222.  
  6223.       case PB_DISPLAYPORTION:
  6224.       case PB_SIZEVAR:
  6225.       case PB_SPEEDVAR:
  6226.       case PB_SPAWNDIRCHAOS:
  6227.       case PB_METATENSIONVAR:
  6228.       case PB_SPINTIMEVAR:
  6229.       case PB_SPINPHASEVAR:
  6230.       case PB_EMITVMULTVAR:
  6231.       case PB_BUBLAMPVAR:
  6232.       case PB_BUBLPERVAR:
  6233.       case PB_BUBLPHASVAR:
  6234.       case PB_SPAWNMULTVAR:
  6235.       case PB_SSSPAWNDIEAFTERVAR:        
  6236.       case PB_IPCOLLIDE_BOUNCE:        
  6237.       case PB_IPCOLLIDE_BOUNCEVAR:        
  6238.                      return stdPercentDim;
  6239.  
  6240.       case PB_EMITSTART:
  6241.       case PB_EMITSTOP:
  6242.       case PB_DISPUNTIL:
  6243.       case PB_LIFE:
  6244.       case PB_LIFEVAR:
  6245.       case PB_GROWTIME:
  6246.       case PB_FADETIME:
  6247.       case PB_MAPPINGTIME:
  6248.       case PB_SPINTIME:
  6249.       case PB_BUBLPER:
  6250.       case PB_OFFSETAMOUNT:
  6251.       case PB_SSSPAWNDIEAFTER:
  6252.                         return stdTimeDim;
  6253.      
  6254.       default: return defaultDim;
  6255.       }
  6256.    }
  6257.  
  6258. TSTR SuprSprayParticle::GetParameterName(int pbIndex)
  6259.    {
  6260.    switch (pbIndex) {
  6261.       case PB_OFFAXIS:        return GetString(IDS_AP_OFFAXIS);
  6262.       case PB_AXISSPREAD:        return GetString(IDS_AP_AXISSPREAD);
  6263.       case PB_OFFPLANE:       return GetString(IDS_AP_OFFPLANE);
  6264.       case PB_PLANESPREAD:    return GetString(IDS_AP_PLANESPREAD);
  6265.       case PB_SPEED:          return GetString(IDS_RB_SPEED);
  6266.       case PB_SPEEDVAR:       return GetString(IDS_RB_SPEEDVAR);
  6267.       case PB_PBIRTHRATE:        return GetString(IDS_RB_PBIRTHRATE);
  6268.       case PB_PTOTALNUMBER:      return GetString(IDS_RB_PTOTALNUMBER);
  6269.       case PB_DISPLAYPORTION:    return GetString(IDS_RB_DISPLAYPORTION);
  6270.       case PB_EMITSTART:         return GetString(IDS_RB_EMITSTART);
  6271.       case PB_EMITSTOP:       return GetString(IDS_RB_EMITSTOP);
  6272.       case PB_DISPUNTIL:         return GetString(IDS_RB_DISPUNTIL);
  6273.       case PB_LIFE:           return GetString(IDS_RB_LIFE);
  6274.       case PB_LIFEVAR:        return GetString(IDS_RB_LIFEVAR);
  6275.       case PB_SIZE:           return GetString(IDS_RB_SIZE);
  6276.       case PB_SIZEVAR:        return GetString(IDS_RB_SIZEVAR);
  6277.       case PB_GROWTIME:       return GetString(IDS_RB_GROWTIME);
  6278.       case PB_FADETIME:       return GetString(IDS_RB_FADETIME);
  6279.       case PB_RNDSEED:        return GetString(IDS_RB_RNDSEED);
  6280.       case PB_METATENSION:    return GetString(IDS_RB_METATENSION);
  6281.       case PB_METATENSIONVAR:    return GetString(IDS_RB_METATENSIONVAR);
  6282.       case PB_METACOURSE:        return GetString(IDS_RB_METACOURSE);
  6283.       case PB_MAPPINGTIME:    return GetString(IDS_RB_MAPPINGTIME);
  6284.       case PB_MAPPINGDIST:    return GetString(IDS_RB_MAPPINGDIST);
  6285.       case PB_SPINTIME:       return GetString(IDS_RB_SPINTIME);
  6286.       case PB_SPINTIMEVAR:    return GetString(IDS_RB_SPINTIMEVAR);
  6287.       case PB_SPINPHASE:         return GetString(IDS_RB_SPINPHASE);
  6288.       case PB_SPINPHASEVAR:      return GetString(IDS_RB_SPINPHASEVAR);
  6289.       case PB_SPINAXISX:         return GetString(IDS_RB_SPINAXISX);
  6290.       case PB_SPINAXISY:         return GetString(IDS_RB_SPINAXISY);
  6291.       case PB_SPINAXISZ:         return GetString(IDS_RB_SPINAXISZ);
  6292.       case PB_SPINAXISVAR:    return GetString(IDS_RB_SPINAXISVAR);
  6293.       case PB_EMITVINFL:         return GetString(IDS_RB_EMITVINFL);
  6294.       case PB_EMITVMULT:         return GetString(IDS_RB_EMITVMULT);
  6295.       case PB_EMITVMULTVAR:      return GetString(IDS_RB_EMITVMULTVAR);
  6296.       case PB_BUBLAMP:        return GetString(IDS_RB_BUBLAMP);
  6297.       case PB_BUBLAMPVAR:        return GetString(IDS_RB_BUBLAMPVAR);
  6298.       case PB_BUBLPER:        return GetString(IDS_RB_BUBLPER);
  6299.       case PB_BUBLPERVAR:        return GetString(IDS_RB_BUBLPERVAR);
  6300.       case PB_BUBLPHAS:       return GetString(IDS_RB_BUBLPHAS);
  6301.       case PB_BUBLPHASVAR:    return GetString(IDS_RB_BUBLPHASVAR);
  6302.       case PB_EMITRWID:       return GetString(IDS_RB_EMITRWID);
  6303.       case PB_STRETCH:        return GetString(IDS_AP_STRETCH);
  6304.       case PB_OFFSETAMOUNT:      return GetString(IDS_AP_OFFSETAMT);
  6305.       case PB_SPAWNDIRCHAOS:     return GetString(IDS_AP_SPAWNDIRCHAOS);
  6306.       case PB_SPAWNSPEEDCHAOS:      return GetString(IDS_AP_SPAWNSPEEDCHAOS);
  6307.       case PB_SPAWNSCALECHAOS:      return GetString(IDS_AP_SPAWNSCALECHAOS);
  6308.       case PB_SPAWNMULTVAR:         return GetString(IDS_EP_SPAWNMULTVAR);
  6309.       case PB_SPAWNPERCENT:         return GetString(IDS_EP_SPAWNAFFECTS);
  6310.       case PB_SSSPAWNDIEAFTER:      return GetString(IDS_AP_SPAWNDIEAFTER);
  6311.       case PB_SSSPAWNDIEAFTERVAR:      return GetString(IDS_AP_SPAWNDIEAFTERVAR);
  6312.       case PB_IPCOLLIDE_ON:         return GetString(IDS_AP_IPCOLLIDE_ON);
  6313.       case PB_IPCOLLIDE_STEPS:      return GetString(IDS_AP_IPCOLLIDE_STEPS);
  6314.       case PB_IPCOLLIDE_BOUNCE:     return GetString(IDS_AP_IPCOLLIDE_BOUNCE);
  6315.       case PB_IPCOLLIDE_BOUNCEVAR:  return GetString(IDS_AP_IPCOLLIDE_BOUNCEVAR);
  6316.       default:                   return TSTR(_T(""));
  6317.       }
  6318.    }  
  6319.  
  6320.  
  6321. void CommonParticle::GetWorldBoundBox(
  6322.       TimeValue t, INode *inode, ViewExp* vpt, Box3& box)
  6323.    {
  6324.    // particles may require update (bayboro|march.25.2002)
  6325.    if (!OKtoDisplay(t)) return;
  6326.    if (t!=tvalid) cancelled=FALSE;
  6327.    BOOL doupdate=((!cancelled)&&((t!=tvalid)||!valid));
  6328.    if (doupdate) Update(t,inode);
  6329.    // end of particles may require update (bayboro|march.25.2002)
  6330.  
  6331.    cnode=inode;
  6332.    int type,ptype,disptype;
  6333.    pblock->GetValue(PB_VIEWPORTSHOWS,0,type,FOREVER);
  6334.    pblock->GetValue(PB_PARTICLECLASS,0,disptype,FOREVER);
  6335.    pblock->GetValue(PB_PARTICLETYPE,0,ptype,FOREVER);
  6336. // if ((type>2)&&((ptype==RENDTYPE5)||(ptype==RENDTYPE6)||((disptype>0)&&(!custnode))  )) type=1;
  6337.    if ((type>2)&&(((disptype>0)&&(!custnode))  )) type=1;
  6338.    if ((type==3)&&((disptype!=INSTGEOM)||(!custnode))) type=1;
  6339.    if (type==2)
  6340.    { Box3 pbox;
  6341.       Matrix3 mat = inode->GetObjTMBeforeWSM(t);
  6342.       UpdateMesh(t);
  6343.       box  = mesh.getBoundingBox();
  6344.       box  = box * mat;
  6345.       for (int i=0; i<parts.points.Count(); i++) {
  6346.          if (!parts.Alive(i)) {continue;  }
  6347.          Point3 pt = parts.points[i];
  6348.          float r=parts.radius[i]*SQR2,strlen=1.0f;
  6349.          int axisentered,K;
  6350.          pblock->GetValue(PB_SPINAXISTYPE,0,axisentered,FOREVER);
  6351.           if ((ptype!=RENDTYPE5)&&(ptype!=RENDTYPE6))
  6352.           {if ((ClassID()!=BLIZZARD_CLASS_ID)&&(axisentered==DIRTRAVEL))
  6353.          { pblock->GetValue(PB_STRETCH,t,K,FOREVER);
  6354.            strlen=GetLen(parts.vels[i],K);
  6355.            r*=strlen;
  6356.           }}
  6357.          if ((disptype==INSTGEOM)&&(custnode))
  6358.          { int tlst=times.tl.Count();if (tlst==0) tlst=1;
  6359.            pbox += pt;
  6360.            for (int level=0;level<tlst;level++)
  6361.            {   Box3 cbb=cmesh[level].getBoundingBox();
  6362.              Point3 dist=cbb.pmax-cbb.pmin;
  6363.             float pdist=Largest(dist)*r;
  6364.            pbox += pt + Point3( pdist, 0.0f, 0.0f);
  6365.            pbox += pt + Point3(-pdist, 0.0f, 0.0f);
  6366.            pbox += pt + Point3( 0.0f, pdist, 0.0f);
  6367.            pbox += pt + Point3( 0.0f,-pdist, 0.0f);
  6368.            pbox += pt + Point3( 0.0f, 0.0f, pdist);
  6369.            pbox += pt + Point3( 0.0f, 0.0f,-pdist);
  6370.            }
  6371.          }
  6372.          else
  6373.          { if (ptype==RENDTET) r*=8.0f;
  6374.            pbox += pt;
  6375.            pbox += pt + Point3( r, 0.0f, 0.0f);
  6376.            pbox += pt + Point3(-r, 0.0f, 0.0f);
  6377.            pbox += pt + Point3( 0.0f, r, 0.0f);
  6378.            pbox += pt + Point3( 0.0f,-r, 0.0f);
  6379.            pbox += pt + Point3( 0.0f, 0.0f, r);
  6380.            pbox += pt + Point3( 0.0f, 0.0f,-r);
  6381.          }
  6382.       }
  6383.       if (!pbox.IsEmpty()) box += pbox;
  6384.      }
  6385.    else if (type==3)
  6386.    { Box3 pbox;
  6387.       Matrix3 mat = inode->GetObjTMBeforeWSM(t);
  6388.       UpdateMesh(t);
  6389.       box  = mesh.getBoundingBox();
  6390.       box  = box * mat;
  6391.       for (int i=0; i<parts.points.Count(); i++)
  6392.       {  if (!parts.Alive(i)) {continue;  }
  6393.          Point3 pt;
  6394.          float radius=parts.radius[i]*SQR2;
  6395.          int axisentered,K;
  6396.          pblock->GetValue(PB_SPINAXISTYPE,0,axisentered,FOREVER);
  6397.           if ((ptype!=RENDTYPE5)&&(ptype!=RENDTYPE6))
  6398.           {if ((ClassID()!=BLIZZARD_CLASS_ID)&&(axisentered==DIRTRAVEL))
  6399.          { pblock->GetValue(PB_STRETCH,t,K,FOREVER);
  6400.            float strlen=GetLen(parts.vels[i],K);
  6401.            radius*=strlen;
  6402.           }}
  6403.          int n=0,found=0;
  6404.          TimeValue Ctime=(theSuprSprayDraw.anioff?GetCurTime(sdata[i].showframe,(theSuprSprayDraw.anioff>1?theSuprSprayDraw.t:parts.ages[i]),theSuprSprayDraw.anifr):theSuprSprayDraw.t);
  6405.          found=((n=TimeFound(times,Ctime,(sdata[i].gennum>nlist.Count()?nlist.Count():sdata[i].gennum)))>-1);
  6406.          for (int nb=0;nb<theSuprSprayDraw.bboxpt[n].numboxes;nb++)
  6407.          { pt=theSuprSprayDraw.bboxpt[n].bpts[nb].Suboffset+parts[i];
  6408.            float pdist=Largest(theSuprSprayDraw.bboxpt[n].bpts[nb].pts[0]-theSuprSprayDraw.bboxpt[n].bpts[nb].pts[6])*radius;
  6409.            pbox += pt + Point3( pdist, 0.0f, 0.0f);
  6410.            pbox += pt + Point3(-pdist, 0.0f, 0.0f);
  6411.            pbox += pt + Point3( 0.0f, pdist, 0.0f);
  6412.            pbox += pt + Point3( 0.0f,-pdist, 0.0f);
  6413.            pbox += pt + Point3( 0.0f, 0.0f, pdist);
  6414.            pbox += pt + Point3( 0.0f, 0.0f,-pdist);
  6415.          }
  6416.         }
  6417.       if (!pbox.IsEmpty()) box += pbox;
  6418.      }
  6419.    else {SimpleParticle::GetWorldBoundBox(t,inode,vpt,box);}
  6420.    }
  6421.  
  6422.  
  6423.  
  6424. int GetDrawType(CommonParticle *po, int &ptype,int &disptype)
  6425. {  int type;
  6426.    po->pblock->GetValue(PB_VIEWPORTSHOWS,0,type,FOREVER);
  6427.    po->pblock->GetValue(PB_PARTICLECLASS,0,disptype,FOREVER);
  6428.    po->pblock->GetValue(PB_PARTICLETYPE,0,ptype,FOREVER);
  6429.    TimeValue aniend;
  6430.  
  6431. // if ((type>2)&&((ptype==RENDTYPE5)||(ptype==RENDTYPE6)||((disptype>0)&&(!po->custnode))  )) type=1;
  6432.    if ((type>2)&&(((disptype>0)&&(!po->custnode))  )) type=1;
  6433.    if ((type==3)&&((disptype!=INSTGEOM)||(!po->custnode))) type=1;
  6434.    if (type>1)
  6435.    { aniend=GetAnimEnd();
  6436.      int oneframe=GetTicksPerFrame();
  6437.       po->theSuprSprayDraw.anifr=aniend+oneframe;
  6438.      if (po->ClassID()==BLIZZARD_CLASS_ID) po->theSuprSprayDraw.indir.inaxis=0;
  6439.      else
  6440.      { int axisentered = 0;
  6441.       po->pblock->GetValue(PB_SPINAXISTYPE,0,axisentered,FOREVER);
  6442.        if ((po->theSuprSprayDraw.indir.inaxis=(axisentered==DIRTRAVEL)) == TRUE)
  6443.        { po->pblock->GetValue(PB_STRETCH,po->theSuprSprayDraw.t,po->theSuprSprayDraw.indir.K,FOREVER);
  6444.         po->theSuprSprayDraw.indir.oneframe=oneframe;
  6445.        }
  6446.      }
  6447.    }
  6448.    return type;
  6449. }
  6450.  
  6451. /*BOOL CommonParticleDraw::DrawParticle(GraphicsWindow *gw,ParticleSys &parts,int i)
  6452. { HCURSOR hCur;
  6453.   BOOL chcur=FALSE;
  6454. if (disptype==METABALLS)
  6455. { if (firstpart)
  6456.   { Point3 pt[4];
  6457.     int nfaces=obj->metamesh->getNumFaces();
  6458.     if (nfaces>LOTSOFACES)
  6459.    { hCur = SetCursor(LoadCursor(NULL,IDC_WAIT));
  6460.      chcur=TRUE;
  6461.    }
  6462.     for (int j=0;j<nfaces;j++)
  6463.     { pt[0]=obj->metamesh->verts[obj->metamesh->faces[j].v[0]];
  6464.       pt[1]=obj->metamesh->verts[obj->metamesh->faces[j].v[1]];
  6465.      pt[2]=obj->metamesh->verts[obj->metamesh->faces[j].v[2]];
  6466.       gw->polyline(3,pt,NULL,NULL,TRUE,NULL);
  6467.      if (GetAsyncKeyState (VK_ESCAPE))
  6468.      { if (chcur) SetCursor(hCur);  return TRUE;}
  6469.     }
  6470.     firstpart=FALSE;
  6471.   }
  6472. }
  6473. else if (disptype==INSTGEOM)
  6474. { Point3 pt[4];  
  6475.  if (obj->custnode)
  6476.   {int n=0,found=0;
  6477.     TimeValue Ctime=(anioff?GetCurTime(obj->sdata[i].showframe,(anioff>1?t:parts.ages[i]),anifr):t);
  6478.    found=((n=TimeFound(obj->times,Ctime,(obj->sdata[i].gennum>obj->nCount?obj->nCount:obj->sdata[i].gennum)))>-1);
  6479.    float radius=parts.radius[i];
  6480.    float elapsedtime=(float)parts.ages[i];
  6481.     float Angle=(FloatEQ0(obj->sdata[i].Ts)?0.0f:elapsedtime/obj->sdata[i].Ts)+obj->sdata[i].LamTs;
  6482.    if (indir.inaxis)
  6483.      indir.vel=parts.vels[i];
  6484.    Point3 nextpt;
  6485.    if (found)
  6486.    { BOOL dotumble=((obj->ClassID()==BLIZZARD_CLASS_ID)&&(tumble>0.0f));
  6487.      Matrix3 mat; if (dotumble) mat= obj->TumbleMat(i,tumble,scale);
  6488.    if (bb)
  6489.     { Point3 pt[9];
  6490.      for (int nb=0;nb<bboxpt[n].numboxes;nb++)
  6491.      { for (int j=0;j<8;j++)
  6492.        {if (indir.inaxis)
  6493.        pt[j]=RotateAboutAxis(Angle,parts.points[i],radius*(bboxpt[n].bpts[nb].pts[j]+bboxpt[n].bpts[nb].Suboffset),obj->sdata[i].W,indir);
  6494.        else
  6495.       { nextpt=(radius*(bboxpt[n].bpts[nb].pts[j]+bboxpt[n].bpts[nb].Suboffset))+parts[i];
  6496.         RotateOnePoint(&nextpt.x,&parts.points[i].x,&(obj->sdata[i].W.x),Angle);
  6497.         if (dotumble) pt[j]=parts.points[i]+(nextpt-parts.points[i])*mat;
  6498.         else pt[j]=nextpt;
  6499.       }
  6500.      }
  6501.       gw->polyline(4,pt,NULL,NULL,TRUE,NULL);
  6502.       Point3 tmppt[5]; for (int k=0;k<4;k++) tmppt[k]=pt[4+k];
  6503.       gw->polyline(4,tmppt,NULL,NULL,TRUE,NULL);
  6504.       tmppt[0]=pt[0];tmppt[1]=pt[4];
  6505.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6506.       tmppt[0]=pt[1];tmppt[1]=pt[5];
  6507.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6508.       tmppt[0]=pt[2];tmppt[1]=pt[6];
  6509.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6510.       tmppt[0]=pt[3];tmppt[1]=pt[7];
  6511.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6512.        if (GetAsyncKeyState (VK_ESCAPE)) return TRUE;
  6513.      }
  6514.    }
  6515.     else
  6516.     { Mesh *mp;
  6517.      mp=&obj->cmesh[n];
  6518.      int nfaces=mp->getNumFaces();
  6519.      if (nfaces>LOTSOFACES)
  6520.      {  hCur = SetCursor(LoadCursor(NULL,IDC_WAIT));
  6521.        chcur=TRUE;
  6522.      }
  6523.       for (int j=0;j<nfaces;j++)
  6524.       { for (int pnum=0;pnum<3;pnum++)
  6525.       {if (indir.inaxis)
  6526.        pt[pnum]=RotateAboutAxis(Angle,parts.points[i],radius*(mp->verts[mp->faces[j].v[pnum]]),obj->sdata[i].W,indir);
  6527.       else
  6528.         { nextpt=(radius*(mp->verts[mp->faces[j].v[pnum]]))+parts[i];
  6529.           RotateOnePoint(&nextpt.x,&parts.points[i].x,&(obj->sdata[i].W.x),Angle);
  6530.           if (dotumble) pt[pnum]=parts.points[i]+(nextpt-parts.points[i])*mat;
  6531.          else pt[pnum]=nextpt;
  6532.         }}
  6533.         gw->polyline(3,pt,NULL,NULL,TRUE,NULL);
  6534.         if (GetAsyncKeyState (VK_ESCAPE))  
  6535.         { if (chcur) SetCursor(hCur);  return TRUE;}
  6536.       }
  6537.    }
  6538.    }
  6539.   }
  6540. }
  6541. else
  6542. {  Mesh *pm = new Mesh;
  6543.     Point3 pt[4],W;  
  6544.    int numF,numV;
  6545.     GetMeshInfo(ptype,1,pm,&numF,&numV);
  6546.    if (indir.inaxis)
  6547.        indir.vel=parts.vels[i];
  6548.     float elapsedtime=(float)parts.ages[i];
  6549.     float Angle=(FloatEQ0(obj->sdata[i].Ts)?0.0f:elapsedtime/obj->sdata[i].Ts)+obj->sdata[i].LamTs;
  6550.    W=obj->sdata[i].W;
  6551.    if (ptype==RENDTYPE1) PlotTriangle(parts.radius[i],0,0,pm,Angle,&W.x,0,&parts.points[i],indir);
  6552.    else if (ptype==RENDTYPE2) PlotCube8(parts.radius[i],0,0,pm,Angle,&W.x,0,&parts.points[i],indir);
  6553.    else if (ptype==RENDTYPE3) PlotSpecial(parts.radius[i],0,0,pm,Angle,&W.x,0,&parts.points[i],indir);
  6554.    else if (ptype==RENDTET) PlotTet(parts.radius[i],0,0,pm,Angle,W,0,&parts.points[i],indir);
  6555.    else if (ptype==REND6PT) Plot6PT(parts.radius[i],0,0,pm,Angle,&W.x,0,&parts.points[i],indir);
  6556.    int nfaces=pm->getNumFaces();
  6557.    if (nfaces>LOTSOFACES)
  6558.    {  hCur = SetCursor(LoadCursor(NULL,IDC_WAIT));
  6559.       chcur=TRUE;
  6560.    }
  6561.    if ((obj->ClassID()==BLIZZARD_CLASS_ID)&&(tumble>0.0f))
  6562.    { Matrix3 mat = obj->TumbleMat(i,tumble,scale);
  6563.      for (int j=0;j<numV;j++)
  6564.         pm->verts[j]=obj->parts.points[i]+(pm->verts[j]-obj->parts.points[i])*mat;
  6565.    }
  6566.    for (int j=0;j<nfaces;j++)
  6567.    { pt[0]=pm->verts[pm->faces[j].v[0]];
  6568.       pt[1]=pm->verts[pm->faces[j].v[1]];
  6569.      pt[2]=pm->verts[pm->faces[j].v[2]];
  6570.       gw->polyline(3,pt,NULL,NULL,TRUE,NULL);
  6571.     }
  6572.     if (pm) delete pm;
  6573.    if (GetAsyncKeyState (VK_ESCAPE))
  6574.    { if (chcur) SetCursor(hCur); return TRUE;}
  6575. }
  6576. return 0;
  6577. }  */
  6578.  
  6579. BOOL CommonParticleDraw::DrawParticle(
  6580.       GraphicsWindow *gw,ParticleSys &parts,int i)
  6581. { HCURSOR hCur = NULL;
  6582.   BOOL chcur=FALSE;
  6583.   if (!((disptype==INSTGEOM)&&(bb))) return TRUE;
  6584.   Point3 pt[4];  
  6585.   if (obj->custnode)
  6586.   { int n=0,found=0;
  6587.     TimeValue Ctime=(anioff?GetCurTime(obj->sdata[i].showframe,(anioff>1?t:parts.ages[i]),anifr):t);
  6588.    found=((n=TimeFound(obj->times,Ctime,(obj->sdata[i].gennum>obj->nlist.Count()?obj->nlist.Count():obj->sdata[i].gennum)))>-1);
  6589.    float radius=parts.radius[i];
  6590.    float elapsedtime=(float)parts.ages[i];
  6591.     float Angle=obj->sdata[i].LamTs;
  6592.    if (indir.inaxis)
  6593.      indir.vel=parts.vels[i];
  6594.    Point3 nextpt;
  6595.    if (found)
  6596.    { Point3 pt[9];
  6597.      if (bboxpt[n].numboxes*8>LOTSOFACES)
  6598.      { hCur = SetCursor(LoadCursor(NULL,IDC_WAIT));
  6599.        chcur=TRUE;
  6600.      }
  6601.      for (int nb=0;nb<bboxpt[n].numboxes;nb++)
  6602.      { for (int j=0;j<8;j++)
  6603.        {if (indir.inaxis)
  6604.           pt[j]=RotateAboutAxis(Angle,parts.points[i],radius*(bboxpt[n].bpts[nb].pts[j]+bboxpt[n].bpts[nb].Suboffset),obj->sdata[i].W,indir);
  6605.         else
  6606.        { nextpt=(radius*(bboxpt[n].bpts[nb].pts[j]+bboxpt[n].bpts[nb].Suboffset))+parts[i];
  6607.          RotateOnePoint(&nextpt.x,&parts.points[i].x,&(obj->sdata[i].W.x),Angle);
  6608.          pt[j]=nextpt;
  6609.        }
  6610.        }
  6611.        gw->polyline(4,pt,NULL,NULL,TRUE,NULL);
  6612.       Point3 tmppt[5]; for (int k=0;k<4;k++) tmppt[k]=pt[4+k];
  6613.       gw->polyline(4,tmppt,NULL,NULL,TRUE,NULL);
  6614.       tmppt[0]=pt[0];tmppt[1]=pt[4];
  6615.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6616.       tmppt[0]=pt[1];tmppt[1]=pt[5];
  6617.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6618.       tmppt[0]=pt[2];tmppt[1]=pt[6];
  6619.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6620.       tmppt[0]=pt[3];tmppt[1]=pt[7];
  6621.       gw->polyline(2,tmppt,NULL,NULL,FALSE,NULL);
  6622.       if (GetAsyncKeyState (VK_ESCAPE))  { return TRUE;}
  6623.      }
  6624.    }
  6625.   }
  6626.   if (GetAsyncKeyState (VK_ESCAPE))
  6627.   { if (chcur) SetCursor(hCur);  return TRUE;}
  6628. return 0;
  6629. }
  6630.  
  6631. MarkerType CommonParticle::GetMarkerType()
  6632.    {int ptype,disptype,type=GetDrawType(this,ptype,disptype);
  6633.      switch (type) {
  6634.       case 0:
  6635.          parts.SetCustomDraw(NULL);
  6636.          return POINT_MRKR;        
  6637.       case 1:
  6638.          parts.SetCustomDraw(NULL);
  6639.          return PLUS_SIGN_MRKR;
  6640.       case 2:  {        
  6641.          theSuprSprayDraw.obj = this;
  6642.          theSuprSprayDraw.firstpart=TRUE;
  6643.          theSuprSprayDraw.disptype=disptype;
  6644.          theSuprSprayDraw.ptype=ptype;
  6645.          parts.SetCustomDraw(&theSuprSprayDraw);        
  6646.          theSuprSprayDraw.bb=FALSE;
  6647.          return POINT_MRKR;
  6648.          }  
  6649.       case 3:{theSuprSprayDraw.obj = this;
  6650.          theSuprSprayDraw.firstpart=TRUE;
  6651.          theSuprSprayDraw.disptype=disptype;
  6652.          theSuprSprayDraw.ptype=ptype;
  6653.          theSuprSprayDraw.bb=TRUE;
  6654.          parts.SetCustomDraw(&theSuprSprayDraw);        
  6655.          return POINT_MRKR;
  6656.          }
  6657.       default:
  6658.          return PLUS_SIGN_MRKR;
  6659.       }
  6660.    }
  6661.  
  6662.  
  6663. void CacheSpin(float *holddata,CSavePt *sdata,int pcount,BOOL issave)
  6664. { for (int i=0;i<pcount;i++)
  6665.    if (issave) holddata[i]=sdata[i].LamTs;
  6666.    else sdata[i].LamTs=holddata[i];
  6667. }
  6668.  
  6669. //--- SuprSpray particle -----------------------------------------------
  6670.  
  6671. RefTargetHandle SuprSprayParticle::Clone(RemapDir& remap)
  6672.    {
  6673.    SuprSprayParticle* newob = new SuprSprayParticle();  
  6674.    newob->ReplaceReference(0,remap.CloneRef(pblock));
  6675.    if (custnode) newob->ReplaceReference(CUSTNODE,custnode);
  6676.    newob->custname=custname;
  6677.    newob->mvalid.SetEmpty();  
  6678.    newob->tvalid = FALSE;
  6679.    newob->nlist.SetCount(nlist.Count());
  6680.    newob->llist.SetCount(llist.Count());
  6681.    for (int ix=0;ix<nlist.Count();ix++)
  6682.    { newob->nlist[ix]=NULL;
  6683.      newob->ReplaceReference(ix+BASER,nlist[ix]);
  6684.    }
  6685.    for (int ix=0;ix<llist.Count();ix++) newob->llist[ix]=llist[ix];
  6686.    newob->dflags=dflags;
  6687.    newob->dispmesh=NULL;
  6688.    newob->times.tl.SetCount(0);
  6689.    newob->nmtls.ZeroCount();
  6690.    newob->cancelled=FALSE;
  6691.    newob->wasmulti=FALSE;
  6692.    newob->stepSize=stepSize;
  6693.    int vshow;
  6694.    pblock->GetValue(PB_VIEWPORTSHOWS,0,vshow,FOREVER);
  6695.    if (vshow>1)
  6696.    {int subtree,anioff,custmtl;
  6697.     pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  6698.     pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  6699.     TimeValue aniend=GetAnimEnd();
  6700.     int anifr=aniend+GetTicksPerFrame();
  6701.     TimeValue t=GetCOREInterface()->GetTime();
  6702.     newob->GetTimes(newob->times,t,anifr,anioff);
  6703.     if (vshow==2)
  6704.     { pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  6705.       newob->GetMesh(t,subtree,custmtl);
  6706.     }
  6707.     else newob->GetallBB(custnode,subtree,t);
  6708.    }
  6709.    BaseClone(this, newob, remap);
  6710.    return newob;
  6711.    }
  6712.  
  6713. static float findmappos(float curpos)
  6714. { float mappos;
  6715.  
  6716.   return(mappos=((mappos=curpos)<0?0:(mappos>1?1:mappos)));
  6717. }
  6718.  
  6719. Mesh *SuprSprayParticle::GetRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete)
  6720. {  float Mval(0.0f), Uval(0.0f), Vval(0.0f), Wval(0.0f), Angle(0.0f), elapsedtime(0.0f);
  6721.    int type(0), count(0), maptype(0), anifr(0);
  6722.    float width(0.0f);
  6723.    Point3 Center;
  6724.    BOOL mirror=FALSE;
  6725.    TVFace defface;
  6726.    Tab<int> tVertsOffset;
  6727.    MultipleChannelMapMerger mcmm;
  6728.    Mesh *pm = new Mesh;
  6729.    if (cancelled)
  6730.    {ZeroMesh(pm);mesh.InvalidateGeomCache();
  6731.    needDelete = TRUE;
  6732.    return pm;}
  6733.    TimeValue mt(0), aniend=GetAnimEnd();
  6734.    dispt=t;
  6735.     anifr=aniend+GetTicksPerFrame();
  6736.    int nummtls=0,curmtl=0,multi=0,pc=0,custmtl=0;
  6737.    pblock->GetValue(PB_PARTICLETYPE,0,type,FOREVER);
  6738.    pblock->GetValue(PB_PARTICLECLASS,0,pc,FOREVER);
  6739.    if (pc==METABALLS) type=RENDMETA;
  6740.    else if (pc==INSTGEOM)
  6741.    {if (custnode==NULL) {type=0;pc=ISSTD;} else type=RENDGEOM;
  6742.    pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  6743.    }
  6744.    float FperT=GetFrameRate()/(float)TIME_TICKSPERSEC;
  6745.    pblock->GetValue(PB_EMITRWID,t,width,FOREVER);
  6746.    pblock->GetValue(PB_MAPPINGTYPE,t,maptype,FOREVER);
  6747.    if (maptype)
  6748.     pblock->GetValue(PB_MAPPINGDIST,t,Mval,FOREVER);
  6749.    else
  6750.     pblock->GetValue(PB_MAPPINGTIME,0,mt,FOREVER);
  6751.    int isrend=!TestAFlag(A_NOTREND);
  6752.  
  6753. //my comment out below - ecp
  6754. // if ((!isrend)&&((type==RENDTYPE5)||(type==RENDTYPE6)))
  6755. //    type=RENDTYPE1;
  6756.  
  6757.    Matrix3 wcam, cam = ident;
  6758.    Point3 v, v0, v1, otherV = Zero, camV = Zero;
  6759.  
  6760.    if (isrend)
  6761.    {
  6762.       cam = Inverse(wcam = view.worldToView);
  6763.       otherV = cam.GetRow(2), camV = cam.GetRow(3);
  6764.    }
  6765.    else
  6766.    {
  6767.       // this is new active viewport stuff here
  6768.       ViewExp *VE = GetCOREInterface()->GetActiveViewport();
  6769.       VE->GetAffineTM(wcam);
  6770.       GetCOREInterface()->ReleaseViewport(VE);
  6771.       cam = Inverse(wcam);
  6772.       otherV = cam.GetRow(2), camV = cam.GetRow(3);
  6773.    }
  6774.  
  6775.    Matrix3 tm = inode->GetObjTMAfterWSM(t);
  6776.    Matrix3 itm = Inverse(tm);
  6777.    int vertexnum=0, face=0,numV=0,numF=0,j=0,tvnum=0,ismapped=0;
  6778.    ParticleSys lastparts;
  6779.    TimeValue offtime=t%GetTicksPerFrame();
  6780.    BOOL midframe;
  6781.    midframe=offtime>0;
  6782.    float *holddata=NULL;int pcount=0;
  6783.    if (isrend)
  6784.    {if (midframe)
  6785.    { Update(t-offtime,inode);
  6786.      if ((pcount=parts.Count())>0)
  6787.      { DL_CacheData(&parts,&lastparts);
  6788.        holddata=new float[pcount];
  6789.         CacheSpin(holddata,sdata,pcount,TRUE);
  6790.      }
  6791.    }
  6792.    Update(t,inode);
  6793.    }
  6794.    count = CountLive();
  6795.    Center = Zero* tm;
  6796.    float Thetah(0.0f);
  6797.    Point3 r1;
  6798.    if (count==0)
  6799.    { ZeroMesh(pm);   goto quit;}
  6800.    else
  6801.    {mirror=DotProd(tm.GetRow(0)^tm.GetRow(1),tm.GetRow(2))<0.0f;
  6802.    if (type==RENDTYPE6)
  6803.    {
  6804.       if (view.projType)
  6805.          type = RENDTYPE5;
  6806.       else
  6807.       {
  6808.          Thetah = view.fov;
  6809.          r1 = cam.GetRow(1);
  6810.       }
  6811.    }
  6812.  
  6813. /* { if (cview==NULL) type=RENDTYPE5;
  6814.       else
  6815.      { Thetah=(cview!=NULL?((CameraObject *)cview->GetObjectRef())->GetFOV(t):0);
  6816.        r1=cam.GetRow(1);
  6817.      }
  6818.    }*/
  6819.    int gtvnum=0,anioff=0;
  6820.    if (pc<METABALLS) GetMeshInfo(type,count,pm,&numF,&numV);
  6821.    else if (type==RENDGEOM)
  6822.    { int subtree,onscreen;
  6823.      pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  6824.      pblock->GetValue(PB_VIEWPORTSHOWS,0,onscreen,FOREVER);
  6825.      pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  6826. //   if (onscreen!=2) {
  6827.      theSuprSprayDraw.t=t;
  6828.      GetTimes(times,t,anifr,anioff);
  6829.      GetMesh(t,subtree,custmtl);
  6830. //   }
  6831.      int custmtl,frag;
  6832.       pblock->GetValue(PB_CUSTOMMTL,0,custmtl,FOREVER);
  6833.       pblock->GetValue(PB_PARTICLECLASS,0,frag,FOREVER);
  6834.      if ((custnode)&&(frag==INSTGEOM)&& custmtl)
  6835.       GetSubs(inode,custnode,subtree,t);
  6836.      TimeValue Ctime;
  6837.      int mnum,tmptvs=0;
  6838.      numV=0;numF=0;
  6839.      BOOL alltex=TRUE;
  6840.      for (int pcnt=0;pcnt<parts.Count();pcnt++)
  6841.      { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  6842.       { ZeroMesh(pm);cancelled=TRUE;goto quit;}
  6843.       if (!parts.Alive(pcnt)) continue;
  6844.       Ctime=(anioff?GetCurTime(sdata[pcnt].showframe,(anioff>1?t:parts.ages[pcnt]),anifr):t);
  6845.       mnum=TimeFound(times,Ctime,(sdata[pcnt].gennum>nlist.Count()?nlist.Count():sdata[pcnt].gennum));
  6846.       numV+=cmesh[mnum].getNumVerts();
  6847.       numF+=cmesh[mnum].getNumFaces();
  6848.      }
  6849.      pm->setNumFaces(numF);
  6850.      pm->setNumVerts(numV);
  6851.      int mcnt=0;
  6852.      int numInstGeomWithMapping=0;
  6853.       if (!custmtl) gtvnum=count;
  6854.      else
  6855.      {   mcnt=times.tl.Count();if (mcnt==0) mcnt=1;
  6856.       for (int mc=0;mc<mcnt;mc++)
  6857.       { tmptvs=cmesh[mc].getNumTVerts();
  6858.         if (tmptvs==0) alltex=FALSE;
  6859.         else gtvnum+=tmptvs;
  6860.       }
  6861.         if ((!alltex)&&(gtvnum>0))
  6862.       { defface.setTVerts(gtvnum,gtvnum,gtvnum);gtvnum++;}
  6863.       tVertsOffset.SetCount(mcnt);
  6864.       tVertsOffset[0]=0;
  6865.      }
  6866.      int gtv;
  6867. //   pm->setNumTVerts(gtv=(custmtl?gtvnum:count*numV));
  6868.      pm->setNumTVerts(gtv=gtvnum);
  6869.      if ((custmtl)&&(gtvnum>0))
  6870.      { int tvs=0,mtvs=0,imtv;
  6871.        for (int mc=0;mc<mcnt;mc++)
  6872.         { if (mc) tVertsOffset[mc]=tVertsOffset[mc-1]+mtvs;
  6873.          mtvs=cmesh[mc].getNumTVerts();
  6874.          if (mtvs>0)
  6875.          { for (imtv=0;imtv<mtvs;imtv++)
  6876.             pm->tVerts[tvs++]=cmesh[mc].tVerts[imtv];
  6877.          }
  6878.        }
  6879.        if (!alltex) pm->tVerts[tvs]=deftex;
  6880.      }
  6881.      pm->setNumTVFaces(gtv>0?numF:0);
  6882.  
  6883.      // Multiple Channel Map Support (single line)
  6884.      if (custmtl) mcmm.setNumTVertsTVFaces(pm, cmesh, mcnt);
  6885.    }
  6886.    Uval=0.5f;Wval=0.5f;
  6887.    Point3 ipt;
  6888.    int i;
  6889.    if (count>0)
  6890.    {
  6891.    if (type==RENDMETA)
  6892.    { float res,bstr,thres=0.6f;int notdraft;
  6893.       pblock->GetValue(PB_METATENSION,t,bstr,FOREVER);
  6894.       pblock->GetValue(PB_SSNOTDRAFT,t,notdraft,FOREVER);
  6895.      notdraft = (notdraft?0:1);
  6896.      if (isrend)
  6897.       pblock->GetValue(PB_METACOURSE,0,res,FOREVER);
  6898.      else pblock->GetValue(PB_METACOURSEV,0,res,FOREVER);
  6899.      metap.CreateMetas(parts,pm,thres,res,bstr,notdraft);  
  6900.      for (int j=0;j<pm->getNumVerts();j++)
  6901.          pm->verts[j] = itm * pm->verts[j];
  6902.    }
  6903.    else
  6904.    { Mtl *mtl = NULL;
  6905.      mtl=inode->GetMtl();
  6906.      if (mtl)
  6907.      { Class_ID mc=Class_ID(MULTI_CLASS_ID,0);
  6908.        Class_ID oc=mtl->ClassID();
  6909.        multi=(oc==mc);
  6910.        if (multi!=0)
  6911.        { nummtls=mtl->NumSubMtls();
  6912.         if (nummtls==0) multi=0;
  6913.       }
  6914.      }
  6915.      wasmulti=multi;
  6916.    InDirInfo indir; indir.oneframe=GetTicksPerFrame();
  6917.    int axisentered;indir.vel=Zero;indir.K=0;
  6918.     pblock->GetValue(PB_SPINAXISTYPE,0,axisentered,FOREVER);
  6919.    if ((indir.inaxis=(axisentered==DIRTRAVEL)) == TRUE)
  6920.    {  pblock->GetValue(PB_STRETCH,t,indir.K,FOREVER);
  6921.    }
  6922.   MtlID cm;
  6923.     for (i=0; i<parts.Count(); i++)
  6924.    { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  6925.       { ZeroMesh(pm);cancelled=TRUE;goto quit;}
  6926.       if (!parts.Alive(i)) continue;
  6927.        if (multi)
  6928.       { curmtl=sdata[i].themtl;
  6929.          if (curmtl>=nummtls)
  6930.           curmtl=curmtl % nummtls;
  6931.        } else curmtl=i;
  6932.      if (indir.inaxis)
  6933.        indir.vel=parts.vels[i];
  6934.       float x;
  6935.        elapsedtime=(float)parts.ages[i];
  6936.       if (maptype) Vval=(x=Length(parts[i]-Center))/Mval;
  6937.       else Vval=(float)elapsedtime/mt;
  6938.         Angle=sdata[i].LamTs;
  6939.        if (type==RENDTYPE1) PlotTriangle(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  6940.        else if (type==RENDTYPE2) PlotCube8(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  6941.        else if (type==RENDTYPE3) PlotSpecial(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  6942.        else if (type==RENDTET) PlotTet(parts.radius[i],vertexnum,face,pm,Angle,sdata[i].W,curmtl,&parts.points[i],indir);
  6943.        else if (type==REND6PT) Plot6PT(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  6944.       else if (type==RENDSPHERE) PlotSphere(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  6945.       else if (type==RENDTYPE5)
  6946.       {  v  = (view.projType?otherV:Normalize(camV-parts[i]));
  6947.          v0 = Normalize(v111^v) * parts.radius[i];
  6948.           v1 = Normalize(v0^v) * parts.radius[i];
  6949.           pm->verts[vertexnum] = (parts[i]+v0+v1);
  6950.           pm->verts[vertexnum+1] = (parts[i]-v0+v1);
  6951.           pm->verts[vertexnum+2] = (parts[i]-v0-v1);
  6952.           pm->verts[vertexnum+3] = (parts[i]+v0-v1);
  6953.           for (int l=0;l<4;l++)
  6954.             RotateOnePoint(pm->verts[vertexnum+l],&parts.points[i].x,&v.x,Angle);
  6955.           AddFace(vertexnum+3,vertexnum+2,vertexnum+1,face,pm,curmtl);
  6956.           AddFace(vertexnum+1,vertexnum,vertexnum+3,face+1,pm,curmtl);
  6957.        }
  6958.        else if (type==RENDTYPE6)
  6959.        {    Point3 a,b,Rv;
  6960.          float Theta(0.0f), R=Length(Rv=(parts[i]-camV)),angle=parts.radius[i]*R*Thetah/view.screenW;
  6961.          a=angle*Normalize(r1^Rv);
  6962.          b=angle*Normalize(a^Rv);
  6963.          pm->verts[vertexnum]=parts[i];
  6964.          int l;
  6965.          for (l=0;l<numV;l++)
  6966.          { Theta=(l-1)*PIOver5;
  6967.            pm->verts[vertexnum+l]=parts[i]+(float)cos(Theta)*a+(float)sin(Theta)*b;
  6968.          }
  6969.          for (l=0;l<numF-1;l++)
  6970.            AddFace(vertexnum,vertexnum+1+l,vertexnum+2+l,face+l,pm,curmtl);
  6971.           AddFace(vertexnum,vertexnum+1+l,vertexnum+1,face+l,pm,curmtl);
  6972.        }
  6973.        else if (type==RENDGEOM)
  6974.        { TimeValue Ctime=(anioff?GetCurTime(sdata[i].showframe,(anioff>1?t:parts.ages[i]),anifr):t);
  6975.          int mnum=TimeFound(times,Ctime,(sdata[i].gennum>nlist.Count()?nlist.Count():sdata[i].gennum));
  6976.          if (mnum<0) continue;
  6977.          numF=cmesh[mnum].getNumFaces();
  6978.          numV=cmesh[mnum].getNumVerts();
  6979.          if ((gtvnum>0)&&(custmtl))
  6980.          { for (j=0;j<numF;j++)
  6981.             if (cmesh[mnum].getNumTVerts()>0)
  6982.               pm->tvFace[j+face].setTVerts(cmesh[mnum].tvFace[j].t[0]+tVertsOffset[mnum],
  6983.                                     cmesh[mnum].tvFace[j].t[1]+tVertsOffset[mnum],
  6984.                                     cmesh[mnum].tvFace[j].t[2]+tVertsOffset[mnum]);
  6985.             else pm->tvFace[j+face]=defface;
  6986.          }
  6987.          // Multiple Channel Map Support (single line)
  6988.          if (custmtl) mcmm.setTVFaces(pm, cmesh, face, mnum);
  6989.  
  6990.          int jf=face;
  6991.         for (j=0;j<numF;j++)
  6992.         { Face cface=cmesh[mnum].faces[j];
  6993.           pm->faces[jf].flags=cface.flags;
  6994.           pm->faces[jf].setSmGroup(cface.smGroup);
  6995.           pm->faces[jf].setVerts(vertexnum+cface.v[0],vertexnum+cface.v[1],vertexnum+cface.v[2]);
  6996.           if (!custmtl)
  6997.             pm->faces[jf].setMatID((MtlID)curmtl);
  6998.           else
  6999.          {cm=cmesh[mnum].faces[j].getMatID();
  7000.           int mtlgen=times.tl[mnum].gennum-1,maxmtl=nmtls.Count();
  7001.           if (mtlgen>=maxmtl) mtlgen=maxmtl-1;
  7002.           if ((mtlgen>-1)&&((times.tl.Count()>0)&&(times.tl[mnum].gennum>0)))
  7003.             cm+=nmtls[mtlgen];
  7004.           pm->faces[jf].setMatID(cm);
  7005.          }
  7006.          pm->faces[jf].setEdgeVisFlags(cface.getEdgeVis(0),cface.getEdgeVis(1),cface.getEdgeVis(2));
  7007.          jf++;
  7008.         }
  7009.         PlotCustom(parts.radius[i],i,vertexnum,pm,Angle,&sdata[i].W.x,&cmesh[mnum],&parts.points[i],numV,indir);
  7010.        }
  7011.      // Convert to object coords
  7012.         for (j=0;j<numV;j++)
  7013.         { pm->verts[vertexnum] = itm * pm->verts[vertexnum];
  7014.           vertexnum++;
  7015.         }
  7016.       if ((type!=RENDTET)&&(!custmtl))
  7017.       { pm->tVerts[tvnum]=Point3(findmappos(Uval),findmappos(Vval),findmappos(Wval));
  7018.          for (j=0;j<numF;j++)
  7019.           { pm->tvFace[face++].setTVerts(tvnum,tvnum,tvnum); }
  7020.          tvnum++;
  7021.       } else face+=numF;
  7022.      }
  7023.    }
  7024. }
  7025. }
  7026.   if (mirror) SwitchVerts(pm);
  7027. quit:mesh.InvalidateGeomCache();
  7028.   if ((isrend)&&(midframe) )
  7029.   { if (pcount>0)
  7030.    {DL_CacheData(&lastparts,&parts);
  7031.     CacheSpin(holddata,sdata,pcount,FALSE);
  7032.    delete[] holddata;}
  7033.     tvalid=t-offtime;
  7034.   }
  7035.    needDelete = TRUE;
  7036.    return pm;
  7037. }
  7038.  
  7039. const TCHAR *SuprSprayClassDesc::ClassName ()   {return GetString(IDS_AP_SUPRSPRAY);}
  7040. const TCHAR *SuprSprayClassDesc::Category () {return GetString(IDS_RB_PARTICLESYSTEMS);}
  7041. TCHAR *SuprSprayParticle::GetObjectName() {return GetString(IDS_AP_SUPRSPRAYGC);}
  7042.  
  7043. class BEmitterCreateCallback : public CreateMouseCallBack {
  7044.    public:
  7045.       BlizzardParticle *blizzard;
  7046.       Point3 p0,p1;
  7047.       IPoint2 sp0, sp1;
  7048.       int proc( ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat);
  7049.    };
  7050.  
  7051. int BEmitterCreateCallback::proc(
  7052.       ViewExp *vpt,int msg, int point, int flags, IPoint2 m, Matrix3& mat)
  7053.    {
  7054.  
  7055. #ifdef _3D_CREATE
  7056.    DWORD snapdim = SNAP_IN_3D;
  7057. #else
  7058.    DWORD snapdim = SNAP_IN_PLANE;
  7059. #endif
  7060.  
  7061. #ifdef _OSNAP
  7062.    if (msg == MOUSE_FREEMOVE)
  7063.    { vpt->SnapPreview(m,m,NULL, snapdim);
  7064.    }
  7065. #endif
  7066.    if (msg==MOUSE_POINT||msg==MOUSE_MOVE) {
  7067.       switch(point)  {
  7068.          case 0:
  7069.             // if hidden by category, re-display particles and objects
  7070.             GetCOREInterface()->SetHideByCategoryFlags(
  7071.                   GetCOREInterface()->GetHideByCategoryFlags() & ~(HIDE_OBJECTS|HIDE_PARTICLES));
  7072.             sp0 = m;
  7073.             p0 = vpt->SnapPoint(m,m,NULL,snapdim);
  7074.             mat.SetTrans(p0);
  7075.             blizzard->pblock->SetValue(PB_EMITRWID,0,0.01f);
  7076.             blizzard->pblock->SetValue(PB_EMITRLENGTH,0,0.01f);
  7077.             blizzard->pmapParam->Invalidate();
  7078.             break;
  7079.  
  7080.          case 1: {
  7081.             mat.IdentityMatrix();
  7082.             sp1 = m;
  7083.             p1 = vpt->SnapPoint(m,m,NULL,snapdim);
  7084.             Point3 center = (p0+p1)/float(2);
  7085.             mat.SetTrans(center);
  7086.             blizzard->pblock->SetValue(PB_EMITRWID,0,
  7087.                (float)fabs(p1.x-p0.x));
  7088.             blizzard->pblock->SetValue(PB_EMITRLENGTH,0,
  7089.                (float)fabs(p1.y-p0.y));
  7090.             blizzard->pmapParam->Invalidate();
  7091.  
  7092.             if (msg==MOUSE_POINT) {
  7093.                if (Length(m-sp0)<3 || Length(p1-p0)<0.1f) {                
  7094.                   return CREATE_ABORT;
  7095.                } else { CheckPickButtons(blizzard->pblock,blizzard->hptype,blizzard->spawn,blizzard->pickCB.repi);
  7096.                   return CREATE_STOP;
  7097.                   }
  7098.                }
  7099.             break;
  7100.             }
  7101.  
  7102.          }
  7103.    } else {
  7104.       if (msg == MOUSE_ABORT)
  7105.          return CREATE_ABORT;
  7106.       }
  7107.    return 1;
  7108.    }
  7109.  
  7110. static BEmitterCreateCallback BemitterCallback;
  7111.  
  7112. CreateMouseCallBack* BlizzardParticle::GetCreateMouseCallBack()
  7113.    {
  7114.    BemitterCallback.blizzard = this;
  7115.    return &BemitterCallback;
  7116.    }
  7117. BlizzardParticle::BlizzardParticle()
  7118.    {int FToTick=(int)((float)TIME_TICKSPERSEC/(float)GetFrameRate());
  7119.      int tpf=GetTicksPerFrame();
  7120.  
  7121.    sdata=NULL;
  7122.    cnode=NULL;
  7123.    custnode=NULL;
  7124.    cmesh=NULL;
  7125.    dispmesh=NULL;
  7126.    origmtl=NULL;
  7127.  
  7128.    ReplaceReference(PBLK, CreateParameterBlock(BdescVer6, PBLOCK_LENGTH_BLIZZARD, CURRENT_VERSION));
  7129.    pblock->SetValue(PB_SPEED,0,10.0f);
  7130.    pblock->SetValue(PB_SPEEDVAR,0,0.0f);
  7131.    pblock->SetValue(PB_PBIRTHRATE,0,10);
  7132.    pblock->SetValue(PB_PTOTALNUMBER,0,100);
  7133.    pblock->SetValue(PB_BIRTHMETHOD,0,0);
  7134.    pblock->SetValue(PB_DISPLAYPORTION,0,0.1f);
  7135.    pblock->SetValue(PB_EMITSTART,0,TimeValue(0));
  7136.    pblock->SetValue(PB_EMITSTOP,0,(TimeValue)30*FToTick);// correct constant?
  7137.    pblock->SetValue(PB_DISPUNTIL,0,100*FToTick);// correct constant?
  7138.    pblock->SetValue(PB_LIFE,0,30*FToTick);// correct constant?
  7139.    pblock->SetValue(PB_LIFEVAR,0,0.0f);
  7140.    pblock->SetValue(PB_SUBFRAMEMOVE,0,1);
  7141.    pblock->SetValue(PB_SUBFRAMETIME,0,1);
  7142.    pblock->SetValue(PB_SUBFRAMEROT2,0,0);
  7143.    pblock->SetValue(PB_SIZE,0,1.0f);
  7144.    pblock->SetValue(PB_SIZEVAR,0,0.0f);
  7145.    pblock->SetValue(PB_GROWTIME,0,10*FToTick);
  7146.    pblock->SetValue(PB_FADETIME,0,10*FToTick);
  7147.    pblock->SetValue(PB_RNDSEED,0,12345);
  7148.  
  7149.    pblock->SetValue(PB_PARTICLETYPE,0,0);
  7150.    pblock->SetValue(PB_METATENSION,0,1.0f);
  7151.    pblock->SetValue(PB_METATENSIONVAR,0,0.0f);
  7152.    pblock->SetValue(PB_METAAUTOCOARSE,0,1);
  7153.    pblock->SetValue(PB_METACOURSE,0,0.5f);
  7154.    pblock->SetValue(PB_VIEWPORTSHOWS,0,1);
  7155.    pblock->SetValue(PB_MAPPINGTYPE,0,0);
  7156.    pblock->SetValue(PB_MAPPINGTIME,0,30*FToTick);
  7157.    pblock->SetValue(PB_MAPPINGDIST,0,100.0f);
  7158.  
  7159.    pblock->SetValue(PB_SPINTIME,0,30*FToTick);
  7160.    pblock->SetValue(PB_SPINTIMEVAR,0,0.0f);
  7161.    pblock->SetValue(PB_SPINPHASE,0,0.0f);
  7162.    pblock->SetValue(PB_SPINPHASEVAR,0,0.0f);
  7163.    pblock->SetValue(PB_SPINAXISTYPE,0,0);
  7164.    pblock->SetValue(PB_SPINAXISX,0,1.0f);
  7165.    pblock->SetValue(PB_SPINAXISY,0,0.0f);
  7166.    pblock->SetValue(PB_SPINAXISZ,0,0.0f);
  7167.    pblock->SetValue(PB_SPINAXISVAR,0,0.0f);
  7168.  
  7169.    pblock->SetValue(PB_EMITVINFL,0,100.0f);
  7170.    pblock->SetValue(PB_EMITVMULT,0,1.0f);
  7171.    pblock->SetValue(PB_EMITVMULTVAR,0,0.0f);
  7172.  
  7173.    pblock->SetValue(PB_EMITRWID,0,0.0f);
  7174.    pblock->SetValue(PB_EMITRLENGTH,0,0.0f);
  7175.  
  7176.    pblock->SetValue(PB_EMITRHID,0,0);
  7177.    pblock->SetValue(PB_SPAWNGENS,0,1);
  7178.    pblock->SetValue(PB_SPAWNCOUNT,0,1);
  7179.    pblock->SetValue(PB_METACOURSEVB,0,1.0f);
  7180.    pblock->SetValue(PB_SPAWNPERCENT2,0,100);
  7181.    pblock->SetValue(PB_SPAWNMULTVAR2,0,0);
  7182.  
  7183.    pblock->SetValue(PB_BLNOTDRAFT,0,0);
  7184.    pblock->SetValue(PB_BLSPAWNDIEAFTER,0,0);
  7185.  
  7186.    pblock->SetValue(PB_BLIPCOLLIDE_ON,0,0);
  7187.    pblock->SetValue(PB_BLIPCOLLIDE_STEPS,0,2);
  7188.    pblock->SetValue(PB_BLIPCOLLIDE_BOUNCE,0,1.0f);
  7189.    pblock->SetValue(PB_BLIPCOLLIDE_BOUNCEVAR,0,0.0f);
  7190.    
  7191.    custname=TSTR(_T(" "));
  7192.    ResetSystem(0,FALSE);
  7193.    int plength=PBLOCK_LENGTH_BLIZZARD;
  7194.    size=0;
  7195.    for (int i=0;i<plength;i++)
  7196.      size+=(BdescVer6[i].type==TYPE_INT?isize:fsize);
  7197. // size=40*isize+fsize*32;
  7198.    dispt=-99999;
  7199.    theSuprSprayDraw.bboxpt=NULL;
  7200.    nmtls.ZeroCount();
  7201.    parts.points.ZeroCount();
  7202.    nlist.ZeroCount();
  7203.    llist.ZeroCount();
  7204.    maincount=0;
  7205.    deftime=0;
  7206.    cancelled=FALSE;
  7207.    dflags=APRTS_ROLLUP_FLAGS;
  7208.    backpatch=TRUE;
  7209.    ClearAFlag(A_NOTREND);
  7210.     stepSize=GetTicksPerFrame();
  7211. }
  7212.  
  7213. BlizzardParticle::~BlizzardParticle()
  7214. {
  7215.    if (sdata) {delete[] sdata;sdata=NULL;}
  7216.    DeleteAllRefsFromMe();
  7217.    pblock=NULL;
  7218.    parts.FreeAll();
  7219.    times.tl.SetCount(0);
  7220.    times.tl.Shrink();
  7221.    nmtls.ZeroCount();nmtls.Shrink();
  7222.    llist.ZeroCount();llist.Shrink();
  7223.    nlist.ZeroCount();nlist.Shrink();
  7224.    if (cmesh) delete[] cmesh;
  7225.    if (theSuprSprayDraw.bboxpt) delete[] theSuprSprayDraw.bboxpt;
  7226.    if (dispmesh) delete dispmesh;
  7227. }
  7228.  
  7229. void BlizzardParticle::BeginEditParams(
  7230.       IObjParam *ip, ULONG flags,Animatable *prev)
  7231.    {  SimpleParticle::BeginEditParams(ip,flags,prev);
  7232.    editOb = this;
  7233.    this->ip = ip;
  7234.  
  7235.    if (flags&BEGIN_EDIT_CREATE) {
  7236.       creating = TRUE;
  7237.    } else { creating = FALSE; }
  7238.    if (pmapParam && pmapPGen && pmapPType && pmapPSpin && pmapEmitV && pmapSpawn)
  7239.    {  pmapParam->SetParamBlock(pblock);
  7240.       pmapPGen->SetParamBlock(pblock);
  7241.       pmapPType->SetParamBlock(pblock);
  7242.       pmapPSpin->SetParamBlock(pblock);
  7243.       pmapEmitV->SetParamBlock(pblock);
  7244.       pmapSpawn->SetParamBlock(pblock);
  7245.       DLSetWindowLongPtr(hParams2, this);
  7246.    } else
  7247.    {  pmapParam = CreateCPParamMap(
  7248.          BdescParam,PARAMBLIZZARD_LENGTH,
  7249.          pblock,
  7250.          ip,
  7251.          hInstance,
  7252.          MAKEINTRESOURCE(IDD_SUPRPRTS_BLIZZARD),
  7253.          GetString(IDS_RB_PARAMETERS),
  7254.          dflags&APRTS_ROLLUP1_OPEN?0:APPENDROLL_CLOSED);
  7255.  
  7256.       pmapPGen = CreateCPParamMap(
  7257.          BdescParamPGen,BPARAMPGEN_LENGTH,
  7258.          pblock,
  7259.          ip,
  7260.          hInstance,
  7261.          MAKEINTRESOURCE(IDD_SUPRPRTS_GEN_BL),
  7262.          GetString(IDS_RB_PGEN),
  7263.          dflags&APRTS_ROLLUP2_OPEN?0:APPENDROLL_CLOSED);
  7264.      
  7265.       pmapPType = CreateCPParamMap(
  7266.          BdescParamPType,BPARAMPTYPE_LENGTH,
  7267.          pblock,
  7268.          ip,
  7269.          hInstance,
  7270.          MAKEINTRESOURCE(IDD_SUPRPRTS_PARTTYPE_BL),
  7271.          GetString(IDS_RB_PTYPE),
  7272.          dflags&APRTS_ROLLUP3_OPEN?0:APPENDROLL_CLOSED);    
  7273.    
  7274.       pmapPSpin = CreateCPParamMap(
  7275.          descBParamPSpin,BPARAMPSPIN_LENGTH,
  7276.          pblock,
  7277.          ip,
  7278.          hInstance,
  7279.          MAKEINTRESOURCE(IDD_SUPRPRTS_ROT_BL),
  7280.          GetString(IDS_RB_SPIN),
  7281.          dflags&APRTS_ROLLUP4_OPEN?0:APPENDROLL_CLOSED);    
  7282.    
  7283.       pmapEmitV = CreateCPParamMap(
  7284.          descParamEmitV,PARAMEMITV_LENGTH,
  7285.          pblock,
  7286.          ip,
  7287.          hInstance,
  7288.          MAKEINTRESOURCE(IDD_SUPRPRTS_EMITV),
  7289.          GetString(IDS_RB_EMITV),
  7290.          dflags&APRTS_ROLLUP5_OPEN?0:APPENDROLL_CLOSED);    
  7291.  
  7292.       pmapSpawn = CreateCPParamMap(
  7293.          descBPSpawning,PBSPAWNINGPARAMS_LENGTH,
  7294.          pblock,
  7295.          ip,
  7296.          hInstance,
  7297.          MAKEINTRESOURCE(IDD_SUPRPRTS_SPAWNINGB),
  7298.          GetString(IDS_AP_PSPAWN),
  7299.          dflags&APRTS_ROLLUP6_OPEN?0:APPENDROLL_CLOSED);    
  7300.    
  7301.       hParams2 = ip->AddRollupPage(
  7302.             hInstance,
  7303.             MAKEINTRESOURCE(IDD_SUPRPRTS_SAVE),
  7304.             CustomSettingParamDlgProc,
  7305.             GetString(IDS_RB_LOADSAVE),
  7306.             (LPARAM)this,dflags&APRTS_ROLLUP7_OPEN?0:APPENDROLL_CLOSED);      
  7307.       ip->RegisterDlgWnd(hParams2);
  7308.  
  7309.       }
  7310.    spawn=pmapSpawn->GetHWnd();
  7311.    hparam=pmapParam->GetHWnd();
  7312.    hgen=pmapPGen->GetHWnd();
  7313.    hptype=pmapPType->GetHWnd();
  7314.    hrot=pmapPSpin->GetHWnd();
  7315.    if (pmapParam) pmapParam->SetUserDlgProc(new BLParticleDlgProc(this));
  7316.    if (pmapPType) pmapPType->SetUserDlgProc(new BLParticleDisableDlgProc(this));
  7317.    if (pmapPGen) pmapPGen->SetUserDlgProc(new SSParticleGenDlgProc(this));
  7318.    if (pmapSpawn) pmapSpawn->SetUserDlgProc(new ComParticleSpawnDlgProc(this));
  7319.    if (pmapPSpin) pmapPSpin->SetUserDlgProc(new BParticleSpinDlgProc(this));
  7320. }  
  7321.  
  7322. void BlizzardParticle::EndEditParams(
  7323.       IObjParam *ip, ULONG flags,Animatable *next)
  7324. {   TimeValue t0,t2;
  7325.    SetFlag(dflags,APRTS_ROLLUP1_OPEN,IsRollupPanelOpen(hparam));
  7326.    SetFlag(dflags,APRTS_ROLLUP2_OPEN,IsRollupPanelOpen(hgen));
  7327.    SetFlag(dflags,APRTS_ROLLUP3_OPEN,IsRollupPanelOpen(hptype));
  7328.    SetFlag(dflags,APRTS_ROLLUP4_OPEN,IsRollupPanelOpen(hrot));
  7329.    SetFlag(dflags,APRTS_ROLLUP5_OPEN,IsRollupPanelOpen(pmapEmitV->GetHWnd()));
  7330.    SetFlag(dflags,APRTS_ROLLUP6_OPEN,IsRollupPanelOpen(spawn));
  7331.    SetFlag(dflags,APRTS_ROLLUP7_OPEN,IsRollupPanelOpen(hParams2));
  7332.    SimpleParticle::EndEditParams(ip,flags,next);
  7333.  
  7334.    if (flags&END_EDIT_REMOVEUI) {
  7335.       pblock->GetValue(PB_EMITSTART,0,t0,FOREVER);
  7336.       pblock->GetValue(PB_EMITSTOP,0,t2,FOREVER);
  7337.       if (t2<t0) pblock->SetValue(PB_EMITSTOP,0,t0);
  7338.       DestroyCPParamMap(pmapParam);
  7339.       DestroyCPParamMap(pmapPGen);
  7340.       DestroyCPParamMap(pmapPType);
  7341.       DestroyCPParamMap(pmapPSpin);
  7342.       DestroyCPParamMap(pmapEmitV);
  7343.       DestroyCPParamMap(pmapSpawn);
  7344.  
  7345.       ip->UnRegisterDlgWnd(hParams2);
  7346.       ip->DeleteRollupPage(hParams2);
  7347.       hParams2 = NULL;
  7348.  
  7349.       pmapParam  = NULL;
  7350.       pmapPGen = NULL;
  7351.       pmapPType = NULL;
  7352.       pmapPSpin = NULL;
  7353.       pmapEmitV = NULL;
  7354.       pmapSpawn = NULL;
  7355.    }else
  7356.       DLSetWindowLongPtr(hParams2, NULL);
  7357.       ip->ClearPickMode();
  7358.    ip= NULL;
  7359.    creating = FALSE;
  7360.    }
  7361.  
  7362. void BlizzardParticle::BuildEmitter(TimeValue t, Mesh& amesh)
  7363.    {
  7364.    float width, height;
  7365.    mvalid = FOREVER;
  7366.    pblock->GetValue(PB_EMITRWID,t,width,mvalid);
  7367.    pblock->GetValue(PB_EMITRLENGTH,t,height,mvalid);
  7368.    width  *= 0.5f;
  7369.    height *= 0.5f;
  7370.  
  7371.    mesh.setNumVerts(7);
  7372.    mesh.setNumFaces(6);
  7373.    mesh.setVert(0, Point3(-width,-height, 0.0f));
  7374.    mesh.setVert(1, Point3( width,-height, 0.0f));
  7375.    mesh.setVert(2, Point3( width, height, 0.0f));
  7376.    mesh.setVert(3, Point3(-width, height, 0.0f));
  7377.    mesh.setVert(4, Point3(  0.0f,   0.0f, 0.0f));
  7378.    mesh.setVert(5, Point3(  0.0f,   0.0f, -(width+height)/2.0f));
  7379.    mesh.setVert(6, Point3(  0.0f,   0.0f, 0.0f));
  7380.  
  7381.    mesh.faces[0].setEdgeVisFlags(1,0,1);
  7382.    mesh.faces[0].setSmGroup(0);
  7383.    mesh.faces[0].setVerts(0,1,3);
  7384.  
  7385.    mesh.faces[1].setEdgeVisFlags(1,1,0);
  7386.    mesh.faces[1].setSmGroup(0);
  7387.    mesh.faces[1].setVerts(1,2,3);
  7388.  
  7389.    mesh.faces[2].setEdgeVisFlags(1,1,0);
  7390.    mesh.faces[2].setSmGroup(0);
  7391.    mesh.faces[2].setVerts(4,5,6);
  7392.  
  7393.    mesh.faces[3].setEdgeVisFlags(1,0,1);
  7394.    mesh.faces[3].setSmGroup(0);
  7395.    mesh.faces[3].setVerts(0,3,1);
  7396.  
  7397.    mesh.faces[4].setEdgeVisFlags(0,1,1);
  7398.    mesh.faces[4].setSmGroup(0);
  7399.    mesh.faces[4].setVerts(1,3,2);
  7400.  
  7401.    mesh.faces[5].setEdgeVisFlags(1,0,0);
  7402.    mesh.faces[5].setSmGroup(0);
  7403.    mesh.faces[5].setVerts(5,4,6);
  7404.  
  7405.    mesh.InvalidateGeomCache();
  7406.    }
  7407.  
  7408. BOOL BlizzardParticle::ComputeParticleStart(TimeValue t0,int c)
  7409.    {
  7410.    int seed,anifr,anioff,tani;
  7411.    if (c > gCountUpperLimit) c = gCountUpperLimit;
  7412.    pblock->GetValue(PB_RNDSEED,t0,seed,FOREVER);
  7413.     pblock->GetValue(PB_OFFSETAMOUNT,t0,anifr,FOREVER);
  7414.     pblock->GetValue(PB_ANIMATIONOFFSET,t0,anioff,FOREVER);
  7415.    srand(seed);              
  7416.    parts.SetCount(c,PARTICLE_VELS|PARTICLE_AGES|PARTICLE_RADIUS|PARTICLE_TENSION);
  7417.    int pcount=parts.Count();
  7418.     if (sdata){delete[] sdata;sdata=NULL;} if (pcount) sdata=new CSavePt[pcount];
  7419.    if ((pcount<c)||(c>0 && (!sdata)))
  7420.    {   parts.FreeAll();if (sdata) delete sdata;sdata=NULL;  maincount=0;
  7421.       BOOL playing=GetCOREInterface()->IsAnimPlaying();
  7422.       if (playing) GetCOREInterface()->EndAnimPlayback();
  7423.        TSTR name;name=(cnode ? cnode->GetName() : TSTR(GetString(IDS_AP_BLIZZARD)));
  7424.       TSTR buf; buf=TSTR(GetString(IDS_OFM_PART));
  7425.       GetCOREInterface()->Log()->LogEntry(SYSLOG_ERROR,DISPLAY_DIALOG,
  7426.          GetString(IDS_OFM_ERROR),_T("%s: \n\n%s\n"),buf,name);
  7427.      return(0);
  7428.    }
  7429.    float tmp;
  7430.    int oneframe=GetTicksPerFrame();
  7431.    for (int i=0; i<parts.Count(); i++) {
  7432.       parts.ages[i] = -1;
  7433.       sdata[i].themtl=0;
  7434.       sdata[i].gennum=0;
  7435.       sdata[i].L=RND0x(99);sdata[i].DL=-1;sdata[i].pvar=RND11();
  7436.       tani=RND0x(anifr/oneframe);
  7437.       sdata[i].showframe=(anioff==2?tani*oneframe:0);
  7438.       tmp=RND01();sdata[i].Fo=tmp;
  7439.       sdata[i].V.x=RND01();
  7440.       sdata[i].V.y=RND01();
  7441.       sdata[i].V.z=RND11();
  7442.       sdata[i].Ts0=RND11();
  7443.       sdata[i].Ts=0.0f;
  7444.       sdata[i].LamTs=RND11();
  7445.       tmp=RND11();sdata[i].M=tmp;
  7446.       // Martell 4/14/01: Fix for order of ops bug.
  7447.       float ztmp=RND11(); float ytmp=RND11(); float xtmp=RND11();
  7448.       parts.vels[i]=Point3(xtmp,ytmp,ztmp);
  7449.       sdata[i].Vsz=RND11();
  7450.       // Martell 4/14/01: Fix for order of ops bug.
  7451.       ztmp=RND11(); ytmp=RND11(); xtmp=RND11();
  7452.       sdata[i].W=Point3(xtmp,ytmp,ztmp);
  7453.       tmp=RND11();sdata[i].Dis=tmp;
  7454.       parts.radius[i]=0.0f;
  7455.       parts.tension[i]=RND11();
  7456.       sdata[i].Mltvar=RND11();
  7457.       sdata[i].SpVar=RND0x(99);
  7458.       }
  7459.    tvalid = t0-1;
  7460.    valid  = TRUE;
  7461.    rseed=rand();
  7462.    return (1);
  7463.    }
  7464.  
  7465. void BlizzardParticle::BirthParticle(INode *node,TimeValue bt,int num,VelDir* ptvel,Matrix3 tmlast)
  7466. {  Matrix3 tm = node->GetObjTMBeforeWSM(bt);
  7467.    Matrix3 atm = node->GetObjTMAfterWSM(bt);
  7468. // tm.SetRow(3,atm.GetRow(3));
  7469.    Point3 vel;
  7470.    float Ie,Em,Vm,width,height;
  7471.    int RotSampleOn;
  7472.    srand(rseed);
  7473.  
  7474.    pblock->GetValue(PB_EMITRWID,bt,width,FOREVER);
  7475.    pblock->GetValue(PB_EMITRLENGTH,bt,height,FOREVER);
  7476.    pblock->GetValue(PB_EMITVINFL,bt,Ie,FOREVER);
  7477.    pblock->GetValue(PB_EMITVMULT,bt,Em,FOREVER);
  7478.    pblock->GetValue(PB_EMITVMULTVAR,bt,Vm,FOREVER);
  7479.    pblock->GetValue(PB_SUBFRAMEROT2,bt,RotSampleOn,FOREVER);
  7480.  
  7481.    int MotionOffset,EmitOffset;
  7482.  
  7483.    pblock->GetValue(PB_SUBFRAMEMOVE,bt,MotionOffset,FOREVER);
  7484.    pblock->GetValue(PB_SUBFRAMETIME,bt,EmitOffset,FOREVER);
  7485.  
  7486.    sdata[num].Ts0 = (1.0f + sdata[num].Ts0*ptvel->VSpin)/TWOPI;
  7487.    sdata[num].Ts = (float)ptvel->Spin*sdata[num].Ts0;
  7488.    parts.tension[num] = ptvel->bstr*(1.0f + parts.tension[num]*ptvel->bstrvar);
  7489.    sdata[num].persist = (TimeValue)(ptvel->persist*(1.0f + sdata[num].pvar*ptvel->pvar));
  7490. // ok, so I'm using L for M and .z for L.  They were unused float and ints
  7491.    sdata[num].M = (sdata[num].L<Ie?Em*(1 + sdata[num].M*Vm):0);  
  7492.    sdata[num].L = ptvel->Life + (int)(parts.vels[num].z*ptvel->Vl);
  7493.    sdata[num].Vsz *= ptvel->VSz;
  7494.    sdata[num].LamTs = ptvel->Phase*(1.0f + sdata[num].LamTs*ptvel->VPhase);
  7495.  
  7496.    if (ptvel->axisentered==1)
  7497.    {  sdata[num].W = Normalize(ptvel->Axis);
  7498.       if (ptvel->axisvar>0.0f)
  7499.          VectorVar(&sdata[num].W,ptvel->axisvar,180.0f);
  7500.    }
  7501.    else
  7502.       sdata[num].W = Normalize(sdata[num].W);
  7503.  
  7504.    parts.ages[num] = 0;
  7505.    vel = Point3(0.0f,0.0f,-ptvel->Speed*(1.0f + sdata[num].V.z*ptvel->VSpeed));
  7506.  
  7507.    Matrix3 OffRotTm;
  7508.    if (RotSampleOn)
  7509.       MakeInterpRotXform(tmlast,tm,(1.0f - sdata[num].Fo),OffRotTm);
  7510.    else
  7511.       OffRotTm=tm;
  7512.  
  7513.    vel = VectorTransform(OffRotTm,vel);
  7514.  
  7515.    parts.points[num].x = -width/2.0f + sdata[num].V.x * width;
  7516.    parts.points[num].y = -height/2.0f + sdata[num].V.y * height;
  7517.    parts.points[num].z = 0.0f;
  7518.    parts[num] = parts[num]*tm;
  7519.  
  7520.    if (MotionOffset)
  7521.       parts[num] += ptvel->bps.Position(1.0f - sdata[num].Fo) - tm.GetTrans();
  7522.  
  7523.    if (EmitOffset)
  7524.       parts[num] += vel*(sdata[num].Fo);
  7525.  
  7526.    if (sdata[num].M != 0.0f)  
  7527.    {
  7528.       Point3 inhVel = ptvel->bps.Speed(1.0f - sdata[num].Fo);
  7529.       parts[num] += inhVel*sdata[num].M*sdata[num].Fo;
  7530.       vel += inhVel*sdata[num].M; // motion inheritance  
  7531.    }
  7532.  
  7533.    vel /= (float)GetTicksPerFrame();
  7534.  
  7535.    parts.vels[num] = vel;
  7536.    sdata[num].V = parts[num];
  7537.    rseed = rand();
  7538. }
  7539.  
  7540. void CommonParticle::GetTimes(TimeLst &times,TimeValue t,int anifr,int ltype)
  7541. { int m,n,found,tmax,tnums=0,tgen;
  7542.   TimeValue tframe;
  7543.   times.tl.SetCount(0);times.tl.Shrink();
  7544.   times.tl.Resize(100);tmax=100;times.tl.SetCount(tmax);
  7545.   for (m=0;m<parts.Count();m++)
  7546.   { if (!parts.Alive(m)) continue;
  7547.     if (ltype)
  7548.    { if (ltype==1) tframe=sdata[m].showframe+parts.ages[m];
  7549.      else tframe=sdata[m].showframe+t;
  7550.      // if ((tframe>=anifr)&&(anifr!=0)) tframe=tframe % anifr;
  7551.    } else tframe=t;
  7552.    found=n=0;
  7553.    tgen=(sdata[m].gennum>nlist.Count()?nlist.Count():sdata[m].gennum);
  7554.    while ((n<tnums)&&(!found))
  7555.    { found=((times.tl[n].gennum==tgen)&&(tframe==times.tl[n].tl));
  7556.      n++;
  7557.    }
  7558.    if (!found)
  7559.    { if (tnums>=tmax)
  7560.      { times.tl.Resize(tmax+=100);times.tl.SetCount(tmax);}
  7561.      times.tl[tnums].gennum=tgen;times.tl[tnums++].tl=tframe;
  7562.    }
  7563.   }
  7564.   times.tl.SetCount(tnums);
  7565.   times.tl.Shrink();
  7566. }
  7567.  
  7568. void BlizzardParticle::UpdateParticles(TimeValue t,INode *node)
  7569. {
  7570.    TimeValue t0,dt,t2,grow,fade;
  7571.    int i(0), j(0), c(0), birth(0), counter(0), tpf=GetTicksPerFrame(), count=0, anioff(0);
  7572.    VelDir ptvel;
  7573.    int isrend = TestAFlag(A_RENDER), bmethod(0), onscreen(0), oneframe(0);
  7574.    // variable for new collision scheme (Bayboro 2/5/01)
  7575.    CollisionCollection cc;
  7576.  
  7577.    // fix for "Abort by Escape key" problem (Bayboro 1/31/01)
  7578.    if (cancelled && (tvalid == t)) return;
  7579.    if (cancelled && valid) tvalid = TIME_NegInfinity;
  7580.    cancelled = FALSE;  
  7581.  
  7582.    // initialization for new collision scheme (Bayboro 2/5/01)
  7583.    cc.Init(cobjs);
  7584.  
  7585.    // The size of steps we take to integrate will be frame size steps.
  7586.    oneframe = GetTicksPerFrame();
  7587.    if (stepSize!=oneframe)
  7588.    {  stepSize = oneframe;
  7589.       valid = FALSE;
  7590.    }
  7591.    float FperT = GetFrameRate()/(float)TIME_TICKSPERSEC;
  7592.     pblock->GetValue(PB_ANIMATIONOFFSET,t,anioff,FOREVER);
  7593.    pblock->GetValue(PB_EMITSTART,t,t0,FOREVER);
  7594.    pblock->GetValue(PB_SIZE,t,parts.size,FOREVER);
  7595.    pblock->GetValue(PB_BIRTHMETHOD,0,bmethod,FOREVER);
  7596.    pblock->GetValue(PB_VIEWPORTSHOWS,0,onscreen,FOREVER);
  7597.    pblock->GetValue(PB_EMITSTOP,0,t2,FOREVER);
  7598.    pblock->GetValue(PB_TUMBLE,t,theSuprSprayDraw.tumble,FOREVER);
  7599.    pblock->GetValue(PB_TUMBLERATE,t,theSuprSprayDraw.scale,FOREVER);
  7600.    int subtree,frag,custmtl=0;
  7601.     pblock->GetValue(PB_CUSTOMMTL2,0,custmtl,FOREVER);
  7602.    pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  7603.    pblock->GetValue(PB_PARTICLECLASS,0,frag,FOREVER);
  7604.    theSuprSprayDraw.scale /= 50.0f;
  7605.    if (bmethod)
  7606.       pblock->GetValue(PB_PTOTALNUMBER,0,c,FOREVER);
  7607.    if (t < t0)
  7608.    {
  7609.       // Before the start time, nothing is happening
  7610.       parts.FreeAll();
  7611.       if (sdata)
  7612.       {
  7613.          delete[] sdata;
  7614.          sdata=NULL;
  7615.       }
  7616.       ResetSystem(t);
  7617.       return;
  7618.    }
  7619.    int pkind;
  7620.    float dpercent;
  7621.    pblock->GetValue(PB_DISPLAYPORTION,0,dpercent,FOREVER);
  7622.    pblock->GetValue(PB_PARTICLETYPE,0,pkind,FOREVER);
  7623.  
  7624.    if ((!valid || t<tvalid)|| tvalid<t0)
  7625.    {  // Set the particle system to the initial condition
  7626.        int cincr;
  7627.       if (!bmethod)
  7628.       {  c=0;
  7629.          for (TimeValue ti=t0;ti<=t2;ti+=oneframe)
  7630.          {  pblock->GetValue(PB_PBIRTHRATE,ti,cincr,FOREVER);
  7631.             if (cincr<0) cincr=0;
  7632.                c += cincr;
  7633.          }
  7634.       }
  7635.       if (!isrend)
  7636.          c = (int)(dpercent*(float)c+FTOIEPS);
  7637.       if (!ComputeParticleStart(t0,c))
  7638.       {  ResetSystem(t);
  7639.          return;
  7640.       }
  7641.       dispt = t-1;
  7642.       maincount = parts.Count();
  7643.       ResetSystem(t,FALSE);
  7644.    }
  7645.    int total;
  7646.    total = maincount;
  7647.    valid = TRUE;
  7648.    int stype,maxgens,spmultb,sper;float spawnbvar;
  7649.     pblock->GetValue(PB_SPAWNTYPE,0,stype,FOREVER);
  7650.     pblock->GetValue(PB_SPAWNGENS,0,maxgens,FOREVER);
  7651.     pblock->GetValue(PB_SPAWNCOUNT,0,spmultb,FOREVER);
  7652.     pblock->GetValue(PB_SPINAXISTYPE,0,ptvel.axisentered,FOREVER);
  7653.    SpawnVars spawnvars;
  7654.    spawnvars.axisentered=ptvel.axisentered;
  7655.    TimeValue dis;
  7656.     pblock->GetValue(PB_DISPUNTIL,0,dis,FOREVER);
  7657.  
  7658.    if (t2<t0)
  7659.       t2=t0;
  7660. // TimeValue fstep=oneframe;
  7661.  
  7662. // t2+=fstep;
  7663.    TimeValue createover;
  7664.    createover = t2-t0+oneframe;
  7665.    counter = (isrend?rcounter:vcounter);
  7666.    float frate,grate;
  7667.    pblock->GetValue(PB_GROWTIME,0,grow,FOREVER);
  7668.     pblock->GetValue(PB_FADETIME,0,fade,FOREVER);
  7669.    frate = (fade>0.0f?(1-M)/fade:0.0f);
  7670.    grate = (grow>0.0f?(1-M)/grow:0.0f);
  7671.    float basesize,smper;
  7672.    BOOL fullframe;
  7673.    if (!isrend)
  7674.    {  int offby = t%oneframe;
  7675.       if (offby!=0)
  7676.          t -= offby;
  7677.    }
  7678.     pblock->GetValue(PB_SPAWNSCALESIGN,0,spawnvars.scsign,FOREVER);
  7679.     pblock->GetValue(PB_SPAWNSPEEDSIGN,0,spawnvars.spsign,FOREVER);
  7680.     pblock->GetValue(PB_SPAWNINHERITV,0,spawnvars.invel,FOREVER);
  7681.     pblock->GetValue(PB_SPAWNSPEEDFIXED,0,spawnvars.spconst,FOREVER);
  7682.     pblock->GetValue(PB_SPAWNSCALEFIXED,0,spawnvars.scconst,FOREVER);
  7683.    BOOL first=(tvalid<t0);
  7684.    while ((tvalid < t)&&(tvalid<=dis))
  7685.    {  int born = 0;    
  7686.       if (first) tvalid=t0;
  7687.          // Compute our step size
  7688.       if (tvalid%stepSize !=0)
  7689.       {  
  7690.          dt = stepSize - abs(tvalid)%stepSize;
  7691.       }
  7692.       else
  7693.       {    
  7694.          dt = stepSize;
  7695.       }
  7696.       if (tvalid + dt > t)
  7697.       {
  7698.          dt = t-tvalid;
  7699.       }
  7700.  
  7701.         // Increment time
  7702.       if (!first)
  7703.          tvalid +=dt;
  7704.       if (tvalid>dis)
  7705.       {  for (j=0; j<parts.Count(); j++)
  7706.          {  
  7707.             parts.ages[j] = -1;  
  7708.          }
  7709.          tvalid = t;
  7710.          continue;
  7711.       }
  7712.        pblock->GetValue(PB_BLSPAWNDIEAFTER,tvalid,ptvel.persist,FOREVER);
  7713.        pblock->GetValue(PB_BLSPAWNDIEAFTERVAR,tvalid,ptvel.pvar,FOREVER);
  7714.        pblock->GetValue(PB_SPEED,tvalid,ptvel.Speed,FOREVER);
  7715.       pblock->GetValue(PB_SPEEDVAR,tvalid,ptvel.VSpeed,FOREVER);
  7716.       pblock->GetValue(PB_SIZE,tvalid,ptvel.Size,FOREVER);
  7717.       pblock->GetValue(PB_LIFE,tvalid,ptvel.Life,FOREVER);
  7718.       pblock->GetValue(PB_LIFEVAR,tvalid,ptvel.Vl,FOREVER);
  7719.       pblock->GetValue(PB_SPINTIME,tvalid,ptvel.Spin,FOREVER);
  7720.       pblock->GetValue(PB_SPINTIMEVAR,tvalid,ptvel.VSpin,FOREVER);
  7721.       pblock->GetValue(PB_SPINPHASE,tvalid,ptvel.Phase,FOREVER);
  7722.       pblock->GetValue(PB_SPINPHASEVAR,tvalid,ptvel.VPhase,FOREVER);
  7723.       pblock->GetValue(PB_SIZEVAR,tvalid,ptvel.VSz,FOREVER);
  7724.       pblock->GetValue(PB_METATENSION,tvalid,ptvel.bstr,FOREVER);
  7725.       pblock->GetValue(PB_METATENSIONVAR,tvalid,ptvel.bstrvar,FOREVER);
  7726.       pblock->GetValue(PB_SPAWNDIRCHAOS,tvalid,spawnvars.dirchaos,FOREVER);
  7727.       pblock->GetValue(PB_SPAWNSPEEDCHAOS,tvalid,spawnvars.spchaos,FOREVER);
  7728.       spawnvars.spchaos/=100.0f;
  7729.  
  7730.       pblock->GetValue(PB_SPAWNPERCENT2,tvalid,sper,FOREVER);  
  7731.       pblock->GetValue(PB_SPAWNMULTVAR2,tvalid,smper,FOREVER);
  7732.       spawnbvar=smper*(float)spmultb;
  7733.  
  7734.       pblock->GetValue(PB_SPAWNSCALECHAOS,tvalid,spawnvars.scchaos,FOREVER);
  7735.       pblock->GetValue(PB_SPINAXISX,tvalid,ptvel.Axis.x,FOREVER);
  7736.       pblock->GetValue(PB_SPINAXISY,tvalid,ptvel.Axis.y,FOREVER);
  7737.       pblock->GetValue(PB_SPINAXISZ,tvalid,ptvel.Axis.z,FOREVER);
  7738.       if (Length(ptvel.Axis)==0.0f)
  7739.          ptvel.Axis.x = 0.001f;
  7740.       pblock->GetValue(PB_SPINAXISVAR,tvalid,ptvel.axisvar,FOREVER);
  7741.       spawnvars.scchaos /= 100.0f;
  7742.       spawnvars.Axis = ptvel.Axis;spawnvars.axisvar=ptvel.axisvar;
  7743.       if (llist.Count()==0)
  7744.          deftime=ptvel.Life/oneframe;
  7745.       basesize = M*ptvel.Size;
  7746.       // Compute the number of particles that should be born
  7747.       birth=0;
  7748.       fullframe = (tvalid%tpf==0);
  7749.       if (fullframe)
  7750.       {  if (bmethod)
  7751.          {  int tdelta;
  7752.             if (tvalid>=t2)
  7753.                birth = total-counter;
  7754.             else
  7755.             {  
  7756.                tdelta = int((float)total*(tvalid-t0+oneframe)/createover);
  7757.                birth = tdelta-counter;
  7758.             }
  7759.          }
  7760.          else if (tvalid<=t2)
  7761.          {  pblock->GetValue(PB_PBIRTHRATE,tvalid,total,FOREVER);
  7762.             if (!isrend)
  7763.                total = (int)(dpercent*(float)total+FTOIEPS);
  7764.             birth = total;
  7765.             if (birth+counter>maincount)
  7766.                birth = 0;
  7767.          }
  7768.       }
  7769.       // First increment age and kill off old particles
  7770.       for (j=0;j<parts.Count();j++)
  7771.       {  if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  7772.          {
  7773.             valid = FALSE;
  7774.             tvalid = t;
  7775.             cancelled = TRUE;
  7776.             parts.FreeAll();
  7777.             return;
  7778.          }
  7779.          if (!parts.Alive(j))
  7780.             continue;
  7781.          int spmult;
  7782.          parts.ages[j] += dt;
  7783.          if (parts.ages[j] >= sdata[j].L)
  7784.          {  
  7785.             spmult = (int)(sdata[j].Mltvar*spawnbvar)+spmultb;
  7786.             if ((stype!=ONDEATH)||(sdata[j].gennum>=maxgens)||(sdata[j].SpVar>=sper))
  7787.                parts.ages[j] = -1;  
  7788.             else if (fullframe)
  7789.             {  
  7790.                spmult = (int)(sdata[j].Mltvar*(float)spawnbvar)+spmultb;
  7791.                if (spmult!=0)
  7792.                   DoSpawn(j,spmult,spawnvars,ptvel.Vl,FALSE);
  7793.                else
  7794.                   parts.ages[j]=-1;
  7795.             }
  7796.          }
  7797.          else if (sdata[j].DL>-1)
  7798.          {
  7799.             sdata[j].DL+=dt;
  7800.             if (sdata[j].DL>sdata[j].persist)
  7801.                parts.ages[j]=-1;
  7802.          }
  7803.          if (parts.ages[j]>-1)
  7804.          {  if (fullframe && ((stype==EMIT)&&(sdata[j].gennum==0)&&(sdata[j].SpVar<sper)))
  7805.             {  
  7806.                spmult = (int)(sdata[j].Mltvar*spawnbvar)+spmultb;
  7807.                if (spmult!=0)
  7808.                   DoSpawn(j,spmult,spawnvars,ptvel.Vl,TRUE);
  7809.             }
  7810. //       if ((pkind==RENDTYPE5)||(pkind==RENDTYPE6))
  7811. //         parts.radius[j]=ptvel.Size;  else
  7812.             if ((stype<2)||(maxgens==0))
  7813.                parts.radius[j]=FigureOutSize(parts.ages[j],ptvel.Size,grow,fade,sdata[j].L,grate,frate)*(1+sdata[j].Vsz);
  7814.             else
  7815.             {
  7816.                if (sdata[j].gennum==0)
  7817.                   parts.radius[j] = FigureOutSize(parts.ages[j],ptvel.Size,grow,0,sdata[j].L,grate,frate)*(1+sdata[j].Vsz);
  7818.                else if (sdata[j].gennum==maxgens)
  7819.                   parts.radius[j] = FigureOutSize(parts.ages[j],sdata[j].Vsz,0,fade,sdata[j].L,grate,frate);
  7820.             }
  7821.          }
  7822.       }
  7823.       if (birth>0)
  7824.       {  Matrix3 tm,tmold;
  7825.          float stepCoef = 1.0f;
  7826.          TimeValue checkone = tvalid-t0;
  7827.  
  7828.          if (checkone < 0)
  7829.             checkone = -checkone;                  // ***** I just added this line
  7830.  
  7831.          if (checkone == 0)
  7832.             tmold = node->GetObjTMBeforeWSM(tvalid - stepSize);
  7833.          else
  7834.             tmold = node->GetObjTMBeforeWSM(checkone<stepSize?t0:(tvalid - stepSize));
  7835.  
  7836.          tm = node->GetObjTMBeforeWSM(tvalid);
  7837.          ptvel.bps.Init(node, tvalid, stepSize);
  7838.  
  7839.       // Next, birth particles at the birth rate
  7840.          for (j=counter; j<maincount; j++)
  7841.          {
  7842.             if (born>=birth) break;
  7843.  
  7844.             BirthParticle(node,tvalid,j,&ptvel,tmold);
  7845. //          BirthParticle(node,tvalid,j,&ptvel,tm);
  7846.  
  7847. //          if ((pkind==RENDTYPE5)||(pkind==RENDTYPE6))
  7848. //             parts.radius[j]=ptvel.Size;  
  7849. //          else
  7850.             parts.radius[j] = (grow>0?basesize:ptvel.Size)*(1.0f + sdata[j].Vsz);
  7851.             sdata[j].themtl = int((tvalid-t0)*FperT);
  7852. //          sdata[j].showframe=(anioff==1?tlast:tlast+sdata[j].showframe);
  7853.             sdata[j].showframe=(anioff==1?0:sdata[j].showframe);
  7854.             born++;
  7855.             counter++;
  7856.          }
  7857.       }
  7858.       // Apply forces to modify velocity
  7859.       int fc=fields.Count();
  7860.       if (fc>0)
  7861.         for (j=0; j<parts.Count(); j++)
  7862.         { Point3 force,tvel=Zero;
  7863.           for (i=0; i<fc; i++)
  7864.          { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  7865.          { valid=FALSE;tvalid=t;cancelled=TRUE;parts.FreeAll();return;}
  7866.          if (!parts.Alive(j)) continue;
  7867.           force = fields[i]->Force(tvalid,parts[j],parts.vels[j],j);
  7868.           float curdt=(float)dt;
  7869.           if ((parts.ages[j]==0)&&(sdata[j].gennum==0)) curdt=tpf*sdata[j].Fo;
  7870.           tvel += 10.0f*force * curdt;
  7871.          }
  7872.           parts.vels[j]+=tvel;
  7873.       }
  7874.       count=0;
  7875.       int IPC,ipcsteps;float B,Vb;
  7876.       pblock->GetValue(PB_BLIPCOLLIDE_ON,tvalid,IPC,FOREVER);
  7877.       pblock->GetValue(PB_BLIPCOLLIDE_STEPS,tvalid,ipcsteps,FOREVER);
  7878.       pblock->GetValue(PB_BLIPCOLLIDE_BOUNCE,tvalid,B,FOREVER);
  7879.       pblock->GetValue(PB_BLIPCOLLIDE_BOUNCEVAR,tvalid,Vb,FOREVER);
  7880.       if (IPC)
  7881.       {  CollideParticle cp;
  7882.          int ddt=dt/ipcsteps,remtime=0,snum=0;
  7883.          TimeValue curt=t;
  7884.          if (dt > 0)
  7885.            while (snum < ipcsteps)
  7886.             { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  7887.               {   valid=FALSE;
  7888.                tvalid=t;
  7889.                cancelled=TRUE;
  7890.                parts.FreeAll();
  7891.                return;
  7892.               }
  7893.                if (remtime==0) remtime=ddt;
  7894.                mindata md=cp.InterPartCollide(parts,cobjs,remtime,snum,B,Vb,curt,lc);
  7895.                for (j=0; j<parts.Count(); j++)
  7896.                {  if (parts.ages[j]>0)
  7897.                   {  if ((j!=md.min)&&(j!=md.min2))
  7898.                        parts[j]+=parts.vels[j]*(float)md.mintime;
  7899.                   }
  7900.                }
  7901.             }
  7902.          // If we didn't collide, then increment.
  7903.       }
  7904.       else
  7905.       // Increment the positions
  7906.       for (j=0; j<parts.Count(); j++)
  7907.       { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  7908.          { valid=FALSE;tvalid=t;cancelled=TRUE;parts.FreeAll();return;}
  7909.          if ((!parts.Alive(j))||(parts.ages[j]==0)) continue;
  7910.         count++;
  7911.  
  7912.          // Check for collisions
  7913.          BOOL collide = FALSE;
  7914.          // float meaninglesstime;
  7915.          float collisionTime, remTime = (float)dt;
  7916.          BOOL maybeStuck = FALSE;
  7917.          // for (int i=0; i<cobjs.Count(); i++)
  7918.          for (int i=0; i<cc.MAX_COLLISIONS_PER_STEP; i++)
  7919.          {
  7920.             // if (cobjs[i]->CheckCollision(tvalid,parts[j],parts.vels[j], (float)dt, j,&meaninglesstime,TRUE))
  7921.             if (cc.CheckCollision(tvalid, parts[j], parts.vels[j], remTime, j, &collisionTime, FALSE))
  7922.             {
  7923.                collide = TRUE;
  7924.                remTime -= collisionTime;
  7925.                if (remTime <= 0.0f) break; // time limit for the current integration step
  7926.             }
  7927.             else break;
  7928.             if (i==cc.MAX_COLLISIONS_PER_STEP-1) maybeStuck = TRUE;
  7929.          }    
  7930.          if (collide)
  7931.          {
  7932.             if (!maybeStuck) // if particle stuck we can't risk to propagate particle movement for the current frame
  7933.                parts[j] += parts.vels[j] * remTime;
  7934.             if (stype==1)
  7935.             {
  7936.                if (sdata[j].persist==0) {parts.ages[j] = -1;count--;}
  7937.                else sdata[j].DL=0;
  7938.             }
  7939.             else if (fullframe &&((stype==COLLIDE)&&(sdata[j].gennum<maxgens)&&(sdata[j].SpVar<sper)))
  7940.             {
  7941.                int spmult=(int)(sdata[j].Mltvar*spawnbvar)+spmultb;
  7942.                if (spmult!=0) DoSpawn(j,spmult,spawnvars,ptvel.Vl,FALSE);
  7943.             }
  7944.          }
  7945.          
  7946.          if (!collide) parts[j] += parts.vels[j] * (float)dt;
  7947.       }
  7948.       if (first) first=FALSE;
  7949.       for (j=0; j<parts.Count(); j++)
  7950.       { if ((!parts.Alive(j))||(parts.ages[j]==0)) continue;
  7951.         sdata[j].Ts = (float)ptvel.Spin*sdata[j].Ts0;
  7952.         sdata[j].LamTs += (FloatEQ0(sdata[j].Ts)?0.0f:dt/sdata[j].Ts);
  7953.       }
  7954.    }
  7955. /* if ((frag==METABALLS)&&(onscreen==2))
  7956.    { float res,bstr,thres=0.6f;
  7957.       pblock->GetValue(PB_METATENSION,t,bstr,FOREVER);
  7958.       pblock->GetValue(PB_METACOURSE,0,res,FOREVER);
  7959.      if (cmesh) delete[] cmesh;cmesh=new Mesh;
  7960.       metap.CreateMetas(parts,cmesh,thres,res,bstr);
  7961.    }
  7962.    else */if ((frag==INSTGEOM)&&(onscreen>1)&&(custnode))
  7963.    { TimeValue anist=GetAnimStart(),aniend=GetAnimEnd();
  7964.       theSuprSprayDraw.anifr=aniend+stepSize;
  7965.      theSuprSprayDraw.t=t;
  7966.      theSuprSprayDraw.anioff=anioff;
  7967.    if (count>0)
  7968.       GetTimes(times,t,theSuprSprayDraw.anifr,anioff);
  7969.    else times.tl.ZeroCount();
  7970.    if (onscreen==2)
  7971.      GetMesh(t,subtree,custmtl);
  7972.    else  GetallBB(custnode,subtree,t);
  7973.    }  
  7974.    if (isrend) rcounter=counter;
  7975.    else
  7976.    { vcounter=counter;
  7977.    }
  7978.    if (tvalid<t) tvalid=t;
  7979.    valid=TRUE;
  7980. // assert(tvalid==t);
  7981.    }
  7982.  
  7983. Mesh *BlizzardParticle::GetRenderMesh(TimeValue t, INode *inode, View& view, BOOL& needDelete)
  7984. {  float Mval=1.0f, Uval(0.0f), Vval(0.0f), Wval(0.0f), Angle(0.0f), elapsedtime(0.0f), tumble(0.0f), scale(0.0f);
  7985.    int type(0), count(0), maptype(0), anifr(0);
  7986.    float height(0.0f);
  7987.    Point3 Center;
  7988.    TVFace defface;
  7989.    Tab<int> tVertsOffset;
  7990.    MultipleChannelMapMerger mcmm;
  7991.    BOOL mirror=FALSE;
  7992.    TimeValue mt(0), aniend=GetAnimEnd();
  7993.    Mesh *pm = new Mesh;    
  7994.    if (cancelled)
  7995.    {ZeroMesh(pm);mesh.InvalidateGeomCache();
  7996.    needDelete = TRUE;
  7997.    return pm;}
  7998.    dispt=t;
  7999.     anifr=aniend+GetTicksPerFrame();
  8000.    int nummtls=0,curmtl=0,multi=0,pc=0,custmtl=0;
  8001.    pblock->GetValue(PB_PARTICLETYPE,0,type,FOREVER);
  8002.    pblock->GetValue(PB_PARTICLECLASS,0,pc,FOREVER);
  8003.    if (pc==METABALLS) type=RENDMETA;
  8004.    else if (pc==INSTGEOM)
  8005.    {if (custnode==NULL) {type=0;pc=ISSTD;} else type=RENDGEOM;
  8006.     pblock->GetValue(PB_CUSTOMMTL2,0,custmtl,FOREVER);
  8007.    }
  8008.    float FperT=GetFrameRate()/(float)TIME_TICKSPERSEC;
  8009.    pblock->GetValue(PB_MAPPINGTYPE,t,maptype,FOREVER);
  8010.    if (maptype==2)
  8011.    { pblock->GetValue(PB_EMITRWID,t,Mval,FOREVER);
  8012.       pblock->GetValue(PB_EMITRLENGTH,t,height,FOREVER);
  8013.      if (height==0.0f) height=0.01f;
  8014.    }
  8015.     else if (maptype==1)
  8016.     pblock->GetValue(PB_MAPPINGDIST,t,Mval,FOREVER);
  8017.    else
  8018.     pblock->GetValue(PB_MAPPINGTIME,0,mt,FOREVER);
  8019.     if (Mval==0.0f) Mval=0.01f;
  8020.    pblock->GetValue(PB_TUMBLE,t,tumble,FOREVER);
  8021.    pblock->GetValue(PB_TUMBLERATE,t,scale,FOREVER);
  8022.    Matrix3 wcam,cam=ident;
  8023.    Point3 v, v0,v1, otherV,camV;
  8024.    int isrend=!TestAFlag(A_NOTREND);
  8025.  
  8026. //my comment out below - ecp
  8027. // if ((!isrend)&&((type==RENDTYPE5)||(type==RENDTYPE6)))
  8028. //    type=RENDTYPE1;
  8029.  
  8030.    if (isrend)
  8031.    {
  8032.       cam = Inverse(wcam = view.worldToView);
  8033.       otherV = cam.GetRow(2),camV = cam.GetRow(3);
  8034.    }
  8035.    else
  8036.    {
  8037.       // this is new active viewport stuff here
  8038.       ViewExp *VE = GetCOREInterface()->GetActiveViewport();
  8039.       VE->GetAffineTM(wcam);
  8040.       GetCOREInterface()->ReleaseViewport(VE);
  8041.       cam = Inverse(wcam);
  8042.       otherV = cam.GetRow(2), camV = cam.GetRow(3);
  8043.    }
  8044.  
  8045.    Matrix3 tm = inode->GetObjTMAfterWSM(t);
  8046.    Matrix3 itm = Inverse(tm);
  8047.    int vertexnum=0, face=0,numV=0,numF=0,j=0,tvnum=0,ismapped=0;
  8048.    ParticleSys lastparts;
  8049.    TimeValue offtime=t%GetTicksPerFrame();
  8050.    BOOL midframe;
  8051.    midframe=offtime>0;
  8052.    float *holddata=NULL;int pcount=0;
  8053.    if (isrend)
  8054.    { if (midframe)
  8055.    { Update(t-offtime,inode);
  8056.      if ((pcount=parts.Count())>0)
  8057.      {   DL_CacheData(&parts,&lastparts);
  8058.       holddata=new float[pcount];
  8059.       CacheSpin(holddata,sdata,pcount,TRUE);
  8060.      }
  8061.    }
  8062.      Update(t,inode);
  8063.    }
  8064.    count = CountLive();
  8065.    Center = Zero * tm;
  8066.    float Thetah(0.0f);
  8067.    Point3 r1;
  8068.    if (count==0)
  8069.    { ZeroMesh(pm);goto quit;}
  8070.    else
  8071.    { mirror=DotProd(tm.GetRow(0)^tm.GetRow(1),tm.GetRow(2))<0.0f;
  8072.    if (type==RENDTYPE6)
  8073.    {
  8074.       if (view.projType)
  8075.          type=RENDTYPE5;
  8076.       else
  8077.       {
  8078.          Thetah=view.fov;
  8079.          r1=cam.GetRow(1);
  8080.       }
  8081.    }
  8082.    int i,gtvnum=0,anioff=0;
  8083.    if (pc<METABALLS) GetMeshInfo(type,count,pm,&numF,&numV);
  8084.    else if (type==RENDGEOM)
  8085.    { int subtree,onscreen;
  8086.      pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  8087.      pblock->GetValue(PB_VIEWPORTSHOWS,0,onscreen,FOREVER);
  8088.      pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  8089. //   if (onscreen!=2) {
  8090.      theSuprSprayDraw.t=t;
  8091.      GetTimes(times,t,anifr,anioff);
  8092.      GetMesh(t,subtree,custmtl);
  8093. //   }
  8094.      if (backpatch)
  8095.      { int custmtl,frag;
  8096.         pblock->GetValue(PB_CUSTOMMTL2,0,custmtl,FOREVER);
  8097.         pblock->GetValue(PB_PARTICLECLASS,0,frag,FOREVER);
  8098.        if ((custnode)&&(frag==INSTGEOM)&& custmtl)
  8099.         GetSubs(inode,custnode,subtree,t);
  8100.      }
  8101.      TimeValue Ctime;
  8102.      int mnum,tmptvs=0;
  8103.      numV=0;numF=0;
  8104.      BOOL alltex=TRUE;
  8105.      for (int pcnt=0;pcnt<parts.Count();pcnt++)
  8106.      { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  8107.       { ZeroMesh(pm);cancelled=TRUE;goto quit;}
  8108.        if (!parts.Alive(pcnt)) continue;
  8109.       Ctime=(anioff?GetCurTime(sdata[pcnt].showframe,(anioff>1?t:parts.ages[pcnt]),anifr):t);
  8110.       mnum=TimeFound(times,Ctime,(sdata[pcnt].gennum>nlist.Count()?nlist.Count():sdata[pcnt].gennum));
  8111.       numV+=cmesh[mnum].getNumVerts();
  8112.       numF+=cmesh[mnum].getNumFaces();
  8113.      }
  8114.      pm->setNumFaces(numF);
  8115.      pm->setNumVerts(numV);
  8116.      int mcnt=0;
  8117.       if (!custmtl) gtvnum=count;
  8118.      else
  8119.      {   mcnt=times.tl.Count();if (mcnt==0) mcnt=1;
  8120.       for (int mc=0;mc<mcnt;mc++)
  8121.       { tmptvs=cmesh[mc].getNumTVerts();
  8122.         if (tmptvs==0) alltex=FALSE;
  8123.         else gtvnum+=tmptvs;
  8124.       }
  8125.         if ((!alltex)&&(gtvnum>0))
  8126.       { defface.setTVerts(gtvnum,gtvnum,gtvnum);gtvnum++;}
  8127.       tVertsOffset.SetCount(mcnt);
  8128.       tVertsOffset[0]=0;
  8129.      }
  8130.      int gtv;
  8131.      pm->setNumTVerts(gtv=gtvnum);
  8132.      if ((custmtl)&&(gtvnum>0))
  8133.      { int tvs=0,mtvs=0,imtv;
  8134.        for (int mc=0;mc<mcnt;mc++)
  8135.         { if (mc) tVertsOffset[mc]=tVertsOffset[mc-1]+mtvs;
  8136.          mtvs=cmesh[mc].getNumTVerts();
  8137.          if (mtvs>0)
  8138.          { for (imtv=0;imtv<mtvs;imtv++)
  8139.             pm->tVerts[tvs++]=cmesh[mc].tVerts[imtv];
  8140.          }
  8141.        }
  8142.        if (!alltex) pm->tVerts[tvs]=deftex;
  8143.      }
  8144.      pm->setNumTVFaces(gtv>0?numF:0);
  8145.  
  8146.      // Multiple Channel Map Support (single line)
  8147.      if (custmtl) mcmm.setNumTVertsTVFaces(pm, cmesh, mcnt);
  8148.    }
  8149.    Uval=0.5f;Wval=0.5f;
  8150.    Point3 ipt;
  8151.    if (count>0)
  8152.    {
  8153.    if (type==RENDMETA)
  8154.    { float res,bstr,thres=0.6f;int notdraft;
  8155.       pblock->GetValue(PB_METATENSION,t,bstr,FOREVER);
  8156.       pblock->GetValue(PB_BLNOTDRAFT,t,notdraft,FOREVER);
  8157.      notdraft = (notdraft?0:1);
  8158.      if (isrend) pblock->GetValue(PB_METACOURSE,0,res,FOREVER);
  8159.      else pblock->GetValue(PB_METACOURSEVB,0,res,FOREVER);
  8160.      metap.CreateMetas(parts,pm,thres,res,bstr,notdraft);
  8161.      for (int j=0;j<pm->getNumVerts();j++)
  8162.          pm->verts[j] = itm * pm->verts[j];
  8163.    }
  8164.    else
  8165.    { Mtl *mtl = NULL;
  8166.      mtl=inode->GetMtl();
  8167.      if (mtl)
  8168.      { Class_ID mc=Class_ID(MULTI_CLASS_ID,0);
  8169.        Class_ID oc=mtl->ClassID();
  8170.        multi=(oc==mc);
  8171.        if (multi!=0)
  8172.        { nummtls=mtl->NumSubMtls();
  8173.         if (nummtls==0) multi=0;
  8174.       }
  8175.      }
  8176.      wasmulti=multi;
  8177.    InDirInfo indir;
  8178.    indir.vel=Zero;
  8179.    indir.inaxis=0;
  8180.    indir.K = 0;
  8181.    indir.oneframe = GetTicksPerFrame();
  8182.    MtlID cm;
  8183.     for (i=0; i<parts.Count(); i++)
  8184.    { if ((!isrend)&&(GetAsyncKeyState (VK_ESCAPE)) )
  8185.       { ZeroMesh(pm);cancelled=TRUE;goto quit;}
  8186.       if (!parts.Alive(i)) continue;
  8187.        if (multi)
  8188.       { curmtl=sdata[i].themtl;
  8189.          if (curmtl>=nummtls)
  8190.           curmtl=curmtl % nummtls;
  8191.        } else curmtl=i;
  8192.       float x;
  8193.        elapsedtime=(float)parts.ages[i];
  8194.       if (maptype==2)
  8195.       { Uval=(parts.points[i].x-(Center.x-Mval/2.0f))/Mval;
  8196.         Vval=(parts.points[i].y-(Center.y-height/2.0f))/height;
  8197.       }
  8198.       else if (maptype) Vval=(x=Length(parts[i]-Center))/Mval;
  8199.       else Vval=(float)elapsedtime/mt;
  8200.         Angle=sdata[i].LamTs;
  8201.        if (type==RENDTYPE1) PlotTriangle(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  8202.        else if (type==RENDTYPE2) PlotCube8(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  8203.        else if (type==RENDTYPE3) PlotSpecial(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  8204.        else if (type==RENDTET) PlotTet(parts.radius[i],vertexnum,face,pm,Angle,sdata[i].W,curmtl,&parts.points[i],indir);
  8205.        else if (type==REND6PT) Plot6PT(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  8206.       else if (type==RENDSPHERE) PlotSphere(parts.radius[i],vertexnum,face,pm,Angle,&sdata[i].W.x,curmtl,&parts.points[i],indir);
  8207.       else if (type==RENDTYPE5)
  8208.        {   v  = (view.projType?otherV:Normalize(camV-parts[i]));
  8209.          v0 = Normalize(v111^v) * parts.radius[i];
  8210.           v1 = Normalize(v0^v) * parts.radius[i];
  8211.           pm->verts[vertexnum] = (parts[i]+v0+v1);
  8212.           pm->verts[vertexnum+1] = (parts[i]-v0+v1);
  8213.           pm->verts[vertexnum+2] = (parts[i]-v0-v1);
  8214.           pm->verts[vertexnum+3] = (parts[i]+v0-v1);
  8215.           for (int l=0;l<4;l++)
  8216.             RotateOnePoint(pm->verts[vertexnum+l],&parts.points[i].x,&v.x,Angle);
  8217.           AddFace(vertexnum+3,vertexnum+2,vertexnum+1,face,pm,curmtl);
  8218.           AddFace(vertexnum+1,vertexnum,vertexnum+3,face+1,pm,curmtl);
  8219.        }
  8220.        else if (type==RENDTYPE6)
  8221.        {    Point3 a,b,Rv;
  8222.          float Theta(0.0f), R=Length(Rv=(parts[i]-camV)),angle=parts.radius[i]*R*Thetah/view.screenW;
  8223.          a=angle*Normalize(r1^Rv);
  8224.          b=angle*Normalize(a^Rv);
  8225.          pm->verts[vertexnum]=parts[i];
  8226.          int l;
  8227.          for (l=0;l<numV;l++)
  8228.          { Theta=(l-1)*PIOver5;
  8229.            pm->verts[vertexnum+l]=parts[i]+(float)cos(Theta)*a+(float)sin(Theta)*b;
  8230.          }
  8231.          for (l=0;l<numF-1;l++)
  8232.            AddFace(vertexnum,vertexnum+1+l,vertexnum+2+l,face+l,pm,curmtl);
  8233.           AddFace(vertexnum,vertexnum+1+l,vertexnum+1,face+l,pm,curmtl);
  8234.        }
  8235.        else if (type==RENDGEOM)
  8236.        {TimeValue Ctime=(anioff?GetCurTime(sdata[i].showframe,(anioff>1?t:parts.ages[i]),anifr):t);
  8237.        int mnum=TimeFound(times,Ctime,(sdata[i].gennum>nlist.Count()?nlist.Count():sdata[i].gennum));
  8238.          if (mnum<0) continue;
  8239.          numF=cmesh[mnum].getNumFaces();
  8240.          numV=cmesh[mnum].getNumVerts();
  8241.          if ((gtvnum>0)&&(custmtl))
  8242.          { if (cmesh[mnum].getNumTVerts()>0)
  8243.            { for (j=0;j<numF;j++)
  8244.               pm->tvFace[j+face].setTVerts(cmesh[mnum].tvFace[j].t[0]+tVertsOffset[mnum],
  8245.                                     cmesh[mnum].tvFace[j].t[1]+tVertsOffset[mnum],
  8246.                                     cmesh[mnum].tvFace[j].t[2]+tVertsOffset[mnum]);
  8247.            } else pm->tvFace[j+face]=defface;
  8248.          }
  8249.          // Multiple Channel Map Support (single line)
  8250.          if (custmtl) mcmm.setTVFaces(pm, cmesh, face, mnum);
  8251.  
  8252.          int jf=face;
  8253.         for (j=0;j<numF;j++)
  8254.         { Face cface=cmesh[mnum].faces[j];
  8255.           pm->faces[jf].flags=cface.flags;
  8256.           pm->faces[jf].setSmGroup(cface.smGroup);
  8257.           pm->faces[jf].setVerts(vertexnum+cface.v[0],vertexnum+cface.v[1],vertexnum+cface.v[2]);
  8258.           if (!custmtl)
  8259.             pm->faces[jf].setMatID((MtlID)curmtl);
  8260.           else
  8261.          {cm=cmesh[mnum].faces[j].getMatID();
  8262.           int mtlgen=times.tl[mnum].gennum-1,maxmtl=nmtls.Count();
  8263.           if (mtlgen>=maxmtl) mtlgen=maxmtl-1;
  8264.           if ((mtlgen>-1)&&((times.tl.Count()>0)&&(times.tl[mnum].gennum>0)))
  8265.             cm+=nmtls[mtlgen];
  8266.           pm->faces[jf].setMatID(cm);
  8267.          }
  8268.          pm->faces[jf].setEdgeVisFlags(cface.getEdgeVis(0),cface.getEdgeVis(1),cface.getEdgeVis(2));
  8269.          jf++;
  8270.         }
  8271.         PlotCustom(parts.radius[i],i,vertexnum,pm,Angle,&sdata[i].W.x,&cmesh[mnum],&parts.points[i],numV,indir);
  8272.        }
  8273.       if (((type<RENDTYPE5)||(type>RENDTYPE6))&&(tumble>0.0f))
  8274.        { Matrix3 mat = TumbleMat(i,tumble,scale);
  8275.         for (int j=vertexnum;j<vertexnum+numV;j++)
  8276.         pm->verts[j]=parts.points[i]+(pm->verts[j]-parts.points[i])*mat;}
  8277.  
  8278.      // Convert to object coords
  8279.         for (j=0;j<numV;j++)
  8280.         { pm->verts[vertexnum] = itm * pm->verts[vertexnum];
  8281.           vertexnum++;
  8282.         }
  8283.       if ((type!=RENDTET)&&(!custmtl))
  8284.       { pm->tVerts[tvnum]=Point3(findmappos(Uval),findmappos(Vval),findmappos(Wval));
  8285.          for (j=0;j<numF;j++)
  8286.           { pm->tvFace[face++].setTVerts(tvnum,tvnum,tvnum); }
  8287.          tvnum++;
  8288.       } else face+=numF;
  8289.      }
  8290.    }
  8291. }
  8292. }
  8293.   if ((isrend)&&(midframe) )
  8294.   { if (pcount>0)
  8295.    {DL_CacheData(&lastparts,&parts);
  8296.     CacheSpin(holddata,sdata,pcount,FALSE);
  8297.    delete[] holddata;}
  8298.     tvalid=t-offtime;
  8299.   }
  8300.   if (mirror) SwitchVerts(pm);
  8301.    quit: mesh.InvalidateGeomCache();
  8302.    needDelete = TRUE;
  8303.    return pm;
  8304. }
  8305.  
  8306.  
  8307. void BlizzardParticle::InvalidateUI()
  8308.    {
  8309.    if (pmapParam) pmapParam->Invalidate();
  8310.    if (pmapPGen) pmapPGen->Invalidate();
  8311.    if (pmapPType) pmapPType->Invalidate();
  8312.    if (pmapPSpin) pmapPSpin->Invalidate();
  8313.    if (pmapEmitV) pmapEmitV->Invalidate();
  8314.    if (pmapSpawn) pmapSpawn->Invalidate();
  8315.    }
  8316.  
  8317. RefTargetHandle BlizzardParticle::Clone(RemapDir& remap)
  8318.    {
  8319.    BlizzardParticle* newob = new BlizzardParticle();  
  8320.    newob->ReplaceReference(0,remap.CloneRef(pblock));
  8321.    if (custnode) newob->ReplaceReference(CUSTNODE,custnode);
  8322.    newob->custname=custname;
  8323.    newob->mvalid.SetEmpty();  
  8324.    newob->tvalid = FALSE;
  8325.    newob->dflags=dflags;
  8326.    newob->nlist.SetCount(nlist.Count());
  8327.    newob->llist.SetCount(llist.Count());
  8328.    for (int ix=0;ix<nlist.Count();ix++)
  8329.    { newob->nlist[ix]=NULL;
  8330.      newob->ReplaceReference(ix+BASER,nlist[ix]);
  8331.    }
  8332.    for (int ix=0;ix<llist.Count();ix++)
  8333.      newob->llist[ix]=llist[ix];
  8334.    newob->dispmesh=NULL;
  8335.    newob->times.tl.SetCount(0);
  8336.    newob->nmtls.ZeroCount();
  8337.    newob->cancelled=FALSE;
  8338.    newob->wasmulti=FALSE;
  8339.     newob->stepSize=stepSize;
  8340.    int vshow;
  8341.    pblock->GetValue(PB_VIEWPORTSHOWS,0,vshow,FOREVER);
  8342.    if (vshow>1)
  8343.    {int subtree,anioff,custmtl;
  8344.     pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  8345.     pblock->GetValue(PB_ANIMATIONOFFSET,0,anioff,FOREVER);
  8346.     TimeValue aniend=GetAnimEnd();
  8347.     int anifr=aniend+GetTicksPerFrame();
  8348.     TimeValue t=GetCOREInterface()->GetTime();
  8349.     newob->GetTimes(newob->times,t,anifr,anioff);
  8350.     if (vshow==2)
  8351.     { pblock->GetValue(PB_CUSTOMMTL2,0,custmtl,FOREVER);
  8352.       newob->GetMesh(t,subtree,custmtl);
  8353.     }
  8354.     else newob->GetallBB(custnode,subtree,t);
  8355.    }
  8356.    BaseClone(this, newob, remap);
  8357.    return newob;
  8358.    }
  8359.  
  8360. ParamDimension *BlizzardParticle::GetParameterDim(int pbIndex)
  8361.    {
  8362.    switch (pbIndex) {
  8363.       case PB_SPEED:
  8364.       case PB_SIZE:
  8365.       case PB_METATENSION:
  8366.       case PB_METACOURSE:
  8367.       case PB_MAPPINGDIST:
  8368.       case PB_SPINAXISX:
  8369.       case PB_SPINAXISY:
  8370.       case PB_SPINAXISZ:
  8371.       case PB_EMITVMULT:
  8372. //    case PB_TUMBLE:
  8373. //    case PB_TUMBLERATE:
  8374.       case PB_EMITRWID:      
  8375.       case PB_EMITRLENGTH:       return stdWorldDim;
  8376.      
  8377.       case PB_RNDSEED:
  8378.       case PB_PBIRTHRATE:
  8379.       case PB_PTOTALNUMBER:
  8380.          return defaultDim;
  8381.  
  8382.       case PB_SPINPHASE:
  8383.       case PB_SPINAXISVAR: return stdAngleDim;
  8384.  
  8385.       case PB_DISPLAYPORTION:
  8386.       case PB_SIZEVAR:
  8387.       case PB_SPEEDVAR:
  8388.       case PB_METATENSIONVAR:
  8389.       case PB_SPINTIMEVAR:
  8390.       case PB_SPINPHASEVAR:
  8391.       case PB_EMITVMULTVAR:  
  8392.       case PB_SPAWNMULTVAR2:
  8393.       case PB_BLSPAWNDIEAFTERVAR:      
  8394.       case PB_BLIPCOLLIDE_BOUNCE:      
  8395.       case PB_BLIPCOLLIDE_BOUNCEVAR:      
  8396.                         return stdPercentDim;
  8397.  
  8398.       case PB_EMITSTART:
  8399.       case PB_EMITSTOP:
  8400.       case PB_DISPUNTIL:
  8401.       case PB_LIFE:
  8402.       case PB_LIFEVAR:
  8403.       case PB_GROWTIME:
  8404.       case PB_FADETIME:
  8405.       case PB_MAPPINGTIME:
  8406.       case PB_SPINTIME:    
  8407.       case PB_BLSPAWNDIEAFTER:      
  8408.                         return stdTimeDim;
  8409.      
  8410.       default: return defaultDim;
  8411.       }
  8412.    }
  8413.  
  8414. TSTR BlizzardParticle::GetParameterName(int pbIndex)
  8415.    {
  8416.    switch (pbIndex) {
  8417.       case PB_TUMBLE:         return GetString(IDS_AP_TUMBLE);
  8418.       case PB_TUMBLERATE:     return GetString(IDS_AP_TUMBLERATE);
  8419.       case PB_EMITRLENGTH: return GetString(IDS_AP_EMITRLENGTH);
  8420.       case PB_SPEED:       return GetString(IDS_RB_SPEED);
  8421.       case PB_SPEEDVAR:    return GetString(IDS_RB_SPEEDVAR);
  8422.       case PB_PBIRTHRATE:     return GetString(IDS_RB_PBIRTHRATE);
  8423.       case PB_PTOTALNUMBER:   return GetString(IDS_RB_PTOTALNUMBER);
  8424.       case PB_DISPLAYPORTION: return GetString(IDS_RB_DISPLAYPORTION);
  8425.       case PB_EMITSTART:      return GetString(IDS_RB_EMITSTART);
  8426.       case PB_EMITSTOP:    return GetString(IDS_RB_EMITSTOP);
  8427.       case PB_DISPUNTIL:      return GetString(IDS_RB_DISPUNTIL);
  8428.       case PB_LIFE:        return GetString(IDS_RB_LIFE);
  8429.       case PB_LIFEVAR:     return GetString(IDS_RB_LIFEVAR);
  8430.       case PB_SIZE:        return GetString(IDS_RB_SIZE);
  8431.       case PB_SIZEVAR:     return GetString(IDS_RB_SIZEVAR);
  8432.       case PB_GROWTIME:    return GetString(IDS_RB_GROWTIME);
  8433.       case PB_FADETIME:    return GetString(IDS_RB_FADETIME);
  8434.       case PB_RNDSEED:     return GetString(IDS_RB_RNDSEED);
  8435.       case PB_METATENSION: return GetString(IDS_RB_METATENSION);
  8436.       case PB_METATENSIONVAR: return GetString(IDS_RB_METATENSIONVAR);
  8437.       case PB_METACOURSE:     return GetString(IDS_RB_METACOURSE);
  8438.       case PB_MAPPINGTIME: return GetString(IDS_RB_MAPPINGTIME);
  8439.       case PB_MAPPINGDIST: return GetString(IDS_RB_MAPPINGDIST);
  8440.       case PB_SPINTIME:    return GetString(IDS_RB_SPINTIME);
  8441.       case PB_SPINTIMEVAR: return GetString(IDS_RB_SPINTIMEVAR);
  8442.       case PB_SPINPHASE:      return GetString(IDS_RB_SPINPHASE);
  8443.       case PB_SPINPHASEVAR:   return GetString(IDS_RB_SPINPHASEVAR);
  8444.       case PB_SPINAXISX:      return GetString(IDS_RB_SPINAXISX);
  8445.       case PB_SPINAXISY:      return GetString(IDS_RB_SPINAXISY);
  8446.       case PB_SPINAXISZ:      return GetString(IDS_RB_SPINAXISZ);
  8447.       case PB_SPINAXISVAR: return GetString(IDS_RB_SPINAXISVAR);
  8448.       case PB_EMITVINFL:      return GetString(IDS_RB_EMITVINFL);
  8449.       case PB_EMITVMULT:      return GetString(IDS_RB_EMITVMULT);
  8450.       case PB_EMITVMULTVAR:   return GetString(IDS_RB_EMITVMULTVAR);
  8451.       case PB_BUBLAMP:     return GetString(IDS_RB_BUBLAMP);
  8452.       case PB_BUBLAMPVAR:     return GetString(IDS_RB_BUBLAMPVAR);
  8453.       case PB_BUBLPER:     return GetString(IDS_RB_BUBLPER);
  8454.       case PB_BUBLPERVAR:     return GetString(IDS_EP_SPAWNAFFECTS);
  8455.       case PB_BUBLPHAS:    return GetString(IDS_EP_SPAWNMULTVAR);
  8456.       case PB_BUBLPHASVAR: return GetString(IDS_RB_BUBLPHASVAR);
  8457.       case PB_EMITRWID:    return GetString(IDS_RB_EMITRWID);
  8458.       case PB_OFFSETAMOUNT:   return GetString(IDS_AP_OFFSETAMT);
  8459.       case PB_SPAWNDIRCHAOS:  return GetString(IDS_AP_SPAWNDIRCHAOS);
  8460.       case PB_SPAWNSPEEDCHAOS:      return GetString(IDS_AP_SPAWNSPEEDCHAOS);
  8461.       case PB_SPAWNSCALECHAOS:      return GetString(IDS_AP_SPAWNSCALECHAOS);
  8462.       case PB_BLSPAWNDIEAFTER:      return GetString(IDS_AP_SPAWNDIEAFTER);
  8463.       case PB_BLSPAWNDIEAFTERVAR:      return GetString(IDS_AP_SPAWNDIEAFTERVAR);
  8464.       case PB_BLIPCOLLIDE_ON:       return GetString(IDS_AP_IPCOLLIDE_ON);
  8465.       case PB_BLIPCOLLIDE_STEPS:    return GetString(IDS_AP_IPCOLLIDE_STEPS);
  8466.       case PB_BLIPCOLLIDE_BOUNCE:      return GetString(IDS_AP_IPCOLLIDE_BOUNCE);
  8467.       case PB_BLIPCOLLIDE_BOUNCEVAR:   return GetString(IDS_AP_IPCOLLIDE_BOUNCEVAR);
  8468.          
  8469.       default:             return TSTR(_T(""));
  8470.       }
  8471.    }  
  8472.  
  8473. BOOL CPickOperand::Filter(INode *node)
  8474.    {
  8475.    if ((node)&&(!node->IsGroupHead())) {
  8476.       ObjectState os = node->GetObjectRef()->Eval(po->ip->GetTime());
  8477.       if (!IsGEOM(os.obj))
  8478.       {  node = NULL;
  8479.          return FALSE;
  8480.       }
  8481.    }
  8482.  
  8483.    return node ? TRUE : FALSE;
  8484. }
  8485.  
  8486. BOOL CPickOperand::HitTest(
  8487.       IObjParam *ip,HWND hWnd,ViewExp *vpt,IPoint2 m,int flags)
  8488.    {  
  8489.    INode *node = ip->PickNode(hWnd,m,this);
  8490.    
  8491.    if ((node)&&(!node->IsGroupHead()))
  8492.    {  ObjectState os = node->GetObjectRef()->Eval(ip->GetTime());
  8493.       if (!IsGEOM(os.obj))
  8494.       {  node = NULL;
  8495.          return FALSE;
  8496.          }
  8497.    }
  8498.  
  8499.    return node ? TRUE : FALSE;
  8500.    }
  8501.  
  8502. void CommonParticle::ShowName()
  8503. { TSTR name;
  8504. if (hptype)
  8505. {FormatName(name=TSTR(GetString(IDS_AP_OBJECTSTR)) + (custnode ? custname : TSTR(GetString(IDS_AP_NONE))));
  8506.  SetWindowText(GetDlgItem(hptype, IDC_AP_INSTANCESRCNAME), name);}
  8507. }
  8508.  
  8509. BOOL CPickOperand::Pick(IObjParam *ip,ViewExp *vpt)
  8510.    {
  8511.    INode *node = vpt->GetClosestHit();
  8512.    assert(node);
  8513.  
  8514.    INodeTab nodes;
  8515. // if ((dodist==1)||(dodist==2)) {nodes.SetCount(1);nodes[0]=node;}
  8516.    int subtree;
  8517.      if (node->IsGroupMember())
  8518.        while (node->IsGroupMember()) node=node->GetParentNode();
  8519.      po->pblock->GetValue(PB_USESUBTREE,0,subtree,FOREVER);
  8520.      nodes.SetCount(0);
  8521.    if (dodist==1)
  8522.     {  theHold.Begin();
  8523.       ComObjectListRestore *padd;
  8524.       theHold.Put(padd=(new ComObjectListRestore(po)));
  8525.       po->AddToList(node,po->nlist.Count(),TRUE);
  8526.       theHold.Accept(GetString(IDS_AP_OBJADD));
  8527.      }
  8528.    else if (dodist==2)
  8529.      { theHold.Begin();
  8530.       ComObjectListRestore *padd;
  8531.       theHold.Put(padd=(new ComObjectListRestore(po)));
  8532.        po->AddToList(node,repi,FALSE);
  8533.       theHold.Accept(GetString(IDS_AP_OBJADD));
  8534.      }
  8535.    else
  8536.    {
  8537.    theHold.Begin();
  8538.    theHold.Put(new CreateCPartPickNode(po,po->custname,node->GetName()));
  8539.    po->ReplaceReference(CUSTNODE,node);
  8540.    theHold.Accept(GetString(IDS_AP_COMPICK));
  8541.    po->custname = TSTR(node->GetName());
  8542.    // Automatically check show result and do one update
  8543.    po->ShowName();  
  8544. }
  8545.    po->flags=(node->IsGroupHead()?1:0);
  8546.    if (po->flags != 0)
  8547.     MakeGroupNodeList(node,&nodes,subtree,ip->GetTime());
  8548.    else MakeNodeList(node,&nodes,subtree,ip->GetTime());
  8549.    int frag,custmtl,onscreen;
  8550.    po->pblock->GetValue((po->ClassID()==BLIZZARD_CLASS_ID?PB_CUSTOMMTL2:PB_CUSTOMMTL),0,custmtl,FOREVER);
  8551.    po->pblock->GetValue(PB_PARTICLECLASS,0,frag,FOREVER);
  8552.    po->pblock->GetValue(PB_VIEWPORTSHOWS,0,onscreen,FOREVER);
  8553.    if ((frag==INSTGEOM)&&(onscreen>1))
  8554.    {  if (onscreen==2)
  8555.       po->GetMesh(ip->GetTime(),subtree,custmtl);
  8556.      else po->GetallBB(node,subtree,ip->GetTime());}
  8557.    po->pmapParam->Invalidate();
  8558.    ip->FlashNodes(&nodes);
  8559.    nodes.Resize(0);
  8560.    po->valid=FALSE;
  8561.    po->NotifyDependents(FOREVER,PART_ALL,REFMSG_CHANGE);
  8562.    if (po->creating) {
  8563.       theCreateSSBlizMode.JumpStart(ip,po);
  8564.       ip->SetCommandMode(&theCreateSSBlizMode);
  8565.       ip->RedrawViews(ip->GetTime());
  8566.       return FALSE;
  8567.    } else {
  8568.       return TRUE;
  8569.       }
  8570.    }
  8571.  
  8572. void CPickOperand::EnterMode(IObjParam *ip)
  8573.    {
  8574.    ICustButton *iBut;
  8575.    if (dodist)
  8576.    {iBut=GetICustButton(GetDlgItem(po->spawn,(dodist==2?IDC_AP_OBJQUEUEREPLACE:IDC_AP_OBJECTQUEUEPICK)));
  8577.      TurnButton(po->spawn,(dodist==1?IDC_AP_OBJQUEUEREPLACE:IDC_AP_OBJECTQUEUEPICK),FALSE);
  8578.      TurnButton(po->spawn,IDC_AP_OBJQUEUEDELETE,FALSE);
  8579.       TurnButton(po->hptype,IDC_AP_OBJECTPICK,FALSE);
  8580.    }
  8581.    else
  8582.    { iBut=GetICustButton(GetDlgItem(po->hptype,IDC_AP_OBJECTPICK));
  8583.      TurnButton(po->spawn,IDC_AP_OBJECTQUEUEPICK,FALSE);
  8584.      TurnButton(po->spawn,IDC_AP_OBJQUEUEREPLACE,FALSE);
  8585.    }
  8586.    if (iBut) iBut->SetCheck(TRUE);
  8587.    ReleaseICustButton(iBut);
  8588.    GetCOREInterface()->PushPrompt(GetString(IDS_AP_PICKMODE));
  8589. }
  8590.  
  8591. void CPickOperand::ExitMode(IObjParam *ip)
  8592.    {if (!po->ip) return;
  8593.    ICustButton *iBut;
  8594.    if (dodist)
  8595.    {  iBut=GetICustButton(GetDlgItem(po->spawn,(dodist==2?IDC_AP_OBJQUEUEREPLACE:IDC_AP_OBJECTQUEUEPICK)));
  8596.       CheckInstButtons(po->pblock,po->hptype);
  8597.      TurnButton(po->spawn,IDC_AP_OBJQUEUEREPLACE,FALSE);
  8598.      if (dodist==2)
  8599.       TurnButton(po->spawn,IDC_AP_OBJECTQUEUEPICK,TRUE);
  8600. //   TurnButton(po->spawn,IDC_AP_OBJQUEUEDELETE,TRUE);
  8601.    }
  8602.    else
  8603.    {iBut=GetICustButton(GetDlgItem(po->hptype,IDC_AP_OBJECTPICK));
  8604.      CheckSpawnButtons(po->pblock,po->spawn,repi);
  8605.    }
  8606.    if (iBut) iBut->SetCheck(FALSE);
  8607.    ReleaseICustButton(iBut);
  8608.     GetCOREInterface()->PopPrompt();
  8609.    }
  8610. RefTargetHandle CommonParticle::GetReference(int i)
  8611. {  switch(i) {
  8612.       case PBLK: return(RefTargetHandle)pblock;
  8613.       case CUSTNODE: return (RefTargetHandle)custnode;
  8614.       default: return (RefTargetHandle)nlist[i-BASER];
  8615.       }
  8616.    }
  8617.  
  8618. void CommonParticle::SetReference(int i, RefTargetHandle rtarg) {
  8619.    switch(i) {
  8620.       case PBLK: pblock=(IParamBlock*)rtarg; return;
  8621.       case CUSTNODE: custnode = (INode *)rtarg; return;
  8622.       default: nlist[i-BASER]= (INode *)rtarg;return;
  8623.       }
  8624.    }
  8625.  
  8626. RefResult CommonParticle::NotifyRefChanged(
  8627.       Interval changeInt,
  8628.       RefTargetHandle hTarget,
  8629.       PartID& partID,
  8630.       RefMessage message )
  8631.    {          
  8632.    switch (message) {      
  8633.       case REFMSG_TARGET_DELETED:  
  8634.          { if (hTarget==custnode)
  8635.             {if (theHold.Holding())
  8636.                theHold.Put(new CreateCPartDelNode(this,custnode->GetName()));
  8637.             DeleteReference(CUSTNODE);
  8638.             custnode=NULL;
  8639.             custname=TSTR(_T(" "));cancelled=FALSE;
  8640.          }
  8641.            BOOL notfound=TRUE;
  8642.            for (int i=0;(i<nlist.Count())&&(notfound);i++)
  8643.             if (hTarget==nlist[i])
  8644.             { DeleteFromList(i,TRUE);
  8645.                notfound=FALSE;cancelled=FALSE;
  8646.             }
  8647.          }
  8648.          break;
  8649.       case REFMSG_NODE_NAMECHANGE:
  8650.          { if (hTarget==custnode)
  8651.            { custname = TSTR(custnode->GetName());
  8652.              ShowName();
  8653.             cancelled=FALSE;
  8654.             }
  8655.            BOOL notfound=TRUE;
  8656.            for (int i=0;(i<nlist.Count())&&(notfound);i++)
  8657.             if (hTarget==nlist[i])
  8658.                {notfound=FALSE;SetUpList();cancelled=FALSE;}
  8659.            break;
  8660.          }
  8661.       case REFMSG_NODE_LINK:    
  8662.       case REFMSG_CHANGE:
  8663.          {int pblst=0;
  8664.            if (pblock && (pblock==hTarget))
  8665.            { pblst=pblock->LastNotifyParamNum();
  8666.              if (pblst==PB_METACOURSE)
  8667.               return REF_STOP;
  8668.             if (pblst==PB_SPAWNLIFEVLUE)
  8669.                return REF_STOP;
  8670.            }
  8671.            MeshInvalid();
  8672.            ParticleInvalid();
  8673.            if (editOb==this) InvalidateUI();
  8674.            cancelled=FALSE;
  8675.          }
  8676.          break;
  8677. /*    case REFMSG_SUBANIM_STRUCTURE_CHANGED:
  8678.          EnableWindow(GetDlgItem(hptype,IDC_SP_MAPCUSTOMEMIT),TRUE);
  8679.          if (editOb==this) InvalidateUI();
  8680.          break;*/
  8681.       default: SimpleParticle::NotifyRefChanged(changeInt,hTarget,partID,message);
  8682.       }
  8683.    return REF_SUCCEED;
  8684.    }
  8685. class CommonPostLoadCallback : public PostLoadCallback {
  8686.    public:
  8687.       ParamBlockPLCB *cb;
  8688.       CommonPostLoadCallback(ParamBlockPLCB *c) {cb=c;}
  8689.       void proc(ILoad *iload) {
  8690.          DWORD oldVer = ((CommonParticle*)(cb->targ))->pblock->GetVersion();
  8691.          ReferenceTarget *targ = cb->targ;
  8692.          cb->proc(iload);
  8693.          int mc;
  8694.          if (oldVer<6)
  8695.          {  if (((CommonParticle*)targ)->ClassID()==BLIZZARD_CLASS_ID)
  8696.             { ((CommonParticle*)targ)->pblock->SetValue(PB_BLIPCOLLIDE_ON,0,0);
  8697.               ((CommonParticle*)targ)->pblock->SetValue(PB_BLIPCOLLIDE_STEPS,0,2);
  8698.               ((CommonParticle*)targ)->pblock->SetValue(PB_BLIPCOLLIDE_BOUNCE,0,1.0f);
  8699.               ((CommonParticle*)targ)->pblock->SetValue(PB_BLIPCOLLIDE_BOUNCEVAR,0,0.0f);
  8700.             }
  8701.             else
  8702.             { ((CommonParticle*)targ)->pblock->SetValue(PB_IPCOLLIDE_ON,0,0);
  8703.               ((CommonParticle*)targ)->pblock->SetValue(PB_IPCOLLIDE_STEPS,0,2);
  8704.               ((CommonParticle*)targ)->pblock->SetValue(PB_IPCOLLIDE_BOUNCE,0,1.0f);
  8705.               ((CommonParticle*)targ)->pblock->SetValue(PB_IPCOLLIDE_BOUNCEVAR,0,0.0f);
  8706.             }
  8707.          }
  8708.          if (oldVer<5)
  8709.          {  if (((CommonParticle*)targ)->ClassID()==BLIZZARD_CLASS_ID)
  8710.             {((CommonParticle*)targ)->pblock->SetValue(PB_BLSPAWNDIEAFTER,0,0);
  8711.              ((CommonParticle*)targ)->pblock->SetValue(PB_BLSPAWNDIEAFTERVAR,0,0.0f);}
  8712.             else
  8713.             { ((CommonParticle*)targ)->pblock->SetValue(PB_SSSPAWNDIEAFTER,0,0);
  8714.               ((CommonParticle*)targ)->pblock->SetValue(PB_SSSPAWNDIEAFTERVAR,0,0.0f);
  8715.             }
  8716.          }
  8717.          if (oldVer<4)
  8718.          {  if (((CommonParticle*)targ)->ClassID()==BLIZZARD_CLASS_ID)
  8719.             ((CommonParticle*)targ)->pblock->SetValue(PB_BLNOTDRAFT,0,0);
  8720.             else ((CommonParticle*)targ)->pblock->SetValue(PB_SSNOTDRAFT,0,0);
  8721.          }
  8722.          if (oldVer<3)
  8723.          {  if (((CommonParticle*)targ)->ClassID()==BLIZZARD_CLASS_ID)
  8724.             ((CommonParticle*)targ)->pblock->SetValue(PB_SPAWNPERCENT2,0,100);
  8725.             else ((CommonParticle*)targ)->pblock->SetValue(PB_SPAWNPERCENT,0,100);
  8726.          }
  8727.          if (oldVer<2)
  8728.          {  if (((CommonParticle*)targ)->ClassID()==BLIZZARD_CLASS_ID)
  8729.             ((CommonParticle*)targ)->pblock->SetValue(PB_SUBFRAMEROT2,0,0);
  8730.             else ((CommonParticle*)targ)->pblock->SetValue(PB_SUBFRAMEROT,0,0);
  8731.          }
  8732.          if (oldVer<1) {  
  8733.             ((CommonParticle*)targ)->pblock->GetValue(PB_METACOURSE,0,mc,FOREVER);
  8734.              if (((CommonParticle*)targ)->ClassID()==BLIZZARD_CLASS_ID)
  8735.             ((CommonParticle*)targ)->pblock->SetValue(PB_METACOURSEVB,0,mc);
  8736.             else ((CommonParticle*)targ)->pblock->SetValue(PB_METACOURSEV,0,mc);
  8737.             }
  8738.          delete this;
  8739.          }
  8740.    };
  8741.  
  8742. #define COM_CUSTNAME_CHUNK 0x0100
  8743. #define COM_CUSTFLAGS_CHUNK   0x0101
  8744. #define COM_SPAWNC_CHUNK   0x0102
  8745. #define COM_LCNT_CHUNK     0x0103
  8746. #define COM_LIFE_CHUNK     0x0104
  8747.  
  8748. IOResult CommonParticle::Save(ISave *isave)
  8749.    {  ULONG nb;
  8750.    isave->BeginChunk(COM_CUSTNAME_CHUNK);    
  8751.    isave->WriteWString(custname);
  8752.    isave->EndChunk();
  8753.  
  8754.    isave->BeginChunk(COM_CUSTFLAGS_CHUNK);      
  8755.    isave->Write(&flags,sizeof(flags),&nb);
  8756.    isave->EndChunk();
  8757.  
  8758.    int nCount=nlist.Count();
  8759.    isave->BeginChunk(COM_SPAWNC_CHUNK);      
  8760.    isave->Write(&nCount,sizeof(nCount),&nb);
  8761.    isave->EndChunk();
  8762.    
  8763.    int Lcnt=llist.Count();
  8764.    isave->BeginChunk(COM_LCNT_CHUNK);    
  8765.    isave->Write(&Lcnt,sizeof(Lcnt),&nb);
  8766.    isave->EndChunk();
  8767.  
  8768.    isave->BeginChunk(COM_LIFE_CHUNK);
  8769.    for (int i=0;i<llist.Count();i++)
  8770.    { isave->Write(&llist[i],sizeof(int),&nb);
  8771.    }
  8772.    isave->EndChunk();
  8773.  
  8774.    return IO_OK;
  8775.    }
  8776.  
  8777. IOResult CommonParticle::Load(ILoad *iload)
  8778.    {
  8779.    if (ClassID()==BLIZZARD_CLASS_ID) {
  8780.       iload->RegisterPostLoadCallback(
  8781.          new CommonPostLoadCallback(
  8782.             new ParamBlockPLCB(Bversions,NUM_OLDVERSIONS,&curVersionBL,this,0)));
  8783.    } else {
  8784.       iload->RegisterPostLoadCallback(
  8785.          new CommonPostLoadCallback(
  8786.             new ParamBlockPLCB(spversions,NUM_OLDVERSIONS,&curVersionSp,this,0)));
  8787.       }
  8788.    ULONG nb;
  8789.    IOResult res = IO_OK;
  8790.    int cnmtl=0,nCount;
  8791.    
  8792.    // Default names
  8793.    custname = TSTR(_T(" "));
  8794.    while (IO_OK==(res=iload->OpenChunk())) {
  8795.       switch (iload->CurChunkID()) {
  8796.          case COM_CUSTNAME_CHUNK: {
  8797.             TCHAR *buf;
  8798.             res=iload->ReadWStringChunk(&buf);
  8799.             custname = TSTR(buf);
  8800.             break;
  8801.             }
  8802.          case COM_CUSTFLAGS_CHUNK:
  8803.             res=iload->Read(&flags,sizeof(flags),&nb);
  8804.             break;
  8805.          case COM_SPAWNC_CHUNK:
  8806.             {  res=iload->Read(&nCount,sizeof(nCount),&nb);
  8807.                nlist.SetCount(nCount);
  8808.                for (int i=0; i<nCount; i++) nlist[i] = NULL;
  8809.             }
  8810.             break;
  8811.          case COM_LCNT_CHUNK:
  8812.             {  int Lcnt;
  8813.                res=iload->Read(&Lcnt,sizeof(Lcnt),&nb);
  8814.                llist.SetCount(Lcnt);
  8815.                for (int i=0; i<Lcnt; i++) llist[i] = NULL;
  8816.             }
  8817.             break;
  8818.          case COM_LIFE_CHUNK:
  8819.             {  for (int i=0;i<llist.Count();i++)
  8820.                res=iload->Read(&llist[i],sizeof(int),&nb);}
  8821.             break;
  8822.          }
  8823.      
  8824.       iload->CloseChunk();
  8825.       if (res!=IO_OK)  return res;
  8826.       }
  8827.  
  8828.    return IO_OK;
  8829.    }
  8830.  
  8831. const TCHAR *BlizzardClassDesc::ClassName () {return GetString(IDS_AP_BLIZZARD);}
  8832. const TCHAR *BlizzardClassDesc::Category ()  {return GetString(IDS_RB_PARTICLESYSTEMS);}
  8833. TCHAR *BlizzardParticle::GetObjectName() {return GetString(IDS_AP_BLIZZARDGC);}
  8834. void CommonParticle::SetUpList()
  8835. {
  8836.     SendMessage(GetDlgItem(spawn,IDC_AP_OBJECTQUEUE),LB_RESETCONTENT,0,0);
  8837.     for (int i=0;i<nlist.Count(); i++)
  8838.         SendMessage(GetDlgItem(spawn,IDC_AP_OBJECTQUEUE),
  8839.         LB_ADDSTRING,0,(LPARAM)(TCHAR*)(nlist[i]->GetName()));
  8840. }
  8841.  
  8842. void CommonParticle::AddToList(INode *newnode,int i,BOOL add)
  8843. {
  8844.     if (add)
  8845.     {
  8846.         INode *null_ptr = NULL;
  8847.         nlist.Insert(i,1,&null_ptr);
  8848.     }    
  8849.     ReplaceReference(i+BASER,newnode);
  8850.     NotifyDependents(FOREVER,0,REFMSG_CHANGE);
  8851.     SetUpList();
  8852. }
  8853.  
  8854. void CommonParticle::DeleteFromList(int nnum,BOOL all)
  8855. { int nCount=nlist.Count();
  8856.   INode *cnode=nlist[nnum];
  8857.   DeleteReference(nnum+BASER);
  8858.   if (theHold.Holding() && !TestAFlag(A_HELD))
  8859.      theHold.Put(new ComObjectListRestore(this));
  8860.   nlist.Delete(nnum,1);
  8861.   if (all)
  8862.   { for (int di=nnum;di<nlist.Count();di++)
  8863.      if (nlist[di]==cnode)
  8864.     { DeleteReference(di+BASER);
  8865.       nlist.Delete(di,1);
  8866.     }
  8867.   }
  8868.   NotifyDependents(FOREVER,0,REFMSG_CHANGE);
  8869.   if (ip) SetUpList();
  8870.   valid=FALSE;
  8871. }
  8872.  
  8873. void CommonParticle::SetUpLifeList()
  8874. { TCHAR buffer[20];
  8875.   SendMessage(GetDlgItem(spawn,IDC_AP_LIFEQUEUE),LB_RESETCONTENT,0,0);
  8876.   for (int i=0;i<llist.Count(); i++)
  8877.   {   _itoa(llist[i], buffer, 10 );
  8878.    SendMessage(GetDlgItem(spawn,IDC_AP_LIFEQUEUE),LB_ADDSTRING,0,(LPARAM)(TCHAR*)buffer);
  8879.   }
  8880. }
  8881.  
  8882. void CommonParticle::AddToLifeList(int newlife)
  8883. {  llist.Insert(llist.Count(),1,&newlife);
  8884.    SetUpLifeList();
  8885. }
  8886.  
  8887. void CommonParticle::DeleteFromLifeList(int nnum)
  8888. {  llist.Delete(nnum,1);
  8889.     if (ip) SetUpLifeList();
  8890. }
  8891. int CommonParticle::HitTest(
  8892.       TimeValue t, INode *inode, int type, int crossing, int flags,
  8893.       IPoint2 *p, ViewExp *vpt)
  8894. {  BOOL doupdate=((!cancelled)&&((t!=tvalid)||!valid));
  8895.    if (doupdate) Update(t,inode);
  8896.    Point2 pt( (float)p[0].x, (float)p[0].y );
  8897.    HitRegion hitRegion;
  8898.    GraphicsWindow *gw = vpt->getGW();  
  8899.    MakeHitRegion(hitRegion, type, crossing, 4, p);
  8900.    DWORD rlim  = gw->getRndLimits();
  8901.    int res;
  8902.  
  8903.    gw->setTransform(ident);
  8904.    int ptype,disptype,dtype=GetDrawType(this,ptype,disptype);
  8905.    if ((dtype<2)||(dtype==3))
  8906.    {  if (parts.HitTest(gw,&hitRegion,flags&HIT_ABORTONHIT,GetMarkerType()))
  8907.       {return TRUE;}
  8908.    }
  8909.    else
  8910.    { if ((t!=dispt)||doupdate||!dispmesh)
  8911.      {   NullView nullView;
  8912.       BOOL needdel;
  8913.       if (dispmesh) delete dispmesh;
  8914.       SetAFlag(A_NOTREND);
  8915.        dispmesh=GetRenderMesh(t,inode,nullView,needdel);}
  8916.       ClearAFlag(A_NOTREND);
  8917.       gw->setRndLimits(rlim);
  8918.       gw->setTransform(inode->GetObjTMBeforeWSM(t));
  8919.       res = dispmesh->select(gw, &particleMtl, &hitRegion, flags & HIT_ABORTONHIT);
  8920.       if (res) return TRUE;
  8921.    }
  8922.    
  8923.    if (EmitterVisible()) {
  8924.       gw->setRndLimits((rlim|GW_PICK|GW_WIREFRAME)
  8925.          & ~(GW_ILLUM|GW_BACKCULL|GW_FLAT|GW_SPECULAR));
  8926.       gw->setTransform(inode->GetObjTMBeforeWSM(t));
  8927.       res = mesh.select(gw, &particleMtl, &hitRegion, flags & HIT_ABORTONHIT);
  8928.  
  8929.       gw->setRndLimits(rlim);
  8930.    } else {
  8931.       res = 0;
  8932.       }
  8933.    return res;
  8934.    }
  8935.  
  8936. int CommonParticle::Display(TimeValue t, INode* inode, ViewExp *vpt, int flags)
  8937. {   if (!OKtoDisplay(t)) return 0;
  8938.    if (t!=tvalid) cancelled=FALSE;
  8939.    if ((ip && origmtl) &&(origmtl!=inode->GetMtl()))
  8940.    { EnableWindow(GetDlgItem(hptype,IDC_SP_MAPCUSTOMEMIT),TRUE);
  8941.      origmtl=NULL;
  8942.    }
  8943.    BOOL doupdate=((!cancelled)&&((t!=tvalid)||!valid));
  8944.    if (!doupdate) doupdate=CheckMtlChange(inode->GetMtl(),wasmulti);
  8945.    if (doupdate) Update(t,inode);
  8946.    GraphicsWindow *gw = vpt->getGW();
  8947.    DWORD rlim  = gw->getRndLimits();
  8948.  
  8949.    // Draw emitter
  8950.    gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY|/*GW_BACKCULL|*/ (rlim&GW_Z_BUFFER) );  //removed BC on 4/29/99 DB
  8951.    if (inode->Selected())
  8952.       gw->setColor( LINE_COLOR, GetSelColor());
  8953.    else if(!inode->IsFrozen())
  8954.       gw->setColor(LINE_COLOR,GetUIColor(COLOR_PARTICLE_EM));
  8955.  
  8956.    if (EmitterVisible()) {
  8957.       gw->setTransform(inode->GetObjTMBeforeWSM(t));  
  8958.       mesh.render(gw, &particleMtl,
  8959.          (flags&USE_DAMAGE_RECT) ? &vpt->GetDammageRect() : NULL, COMP_ALL);
  8960.       }
  8961.      
  8962.      Material *mtl = gw->getMaterial();  
  8963.      if (!inode->Selected() && !inode->IsFrozen())
  8964.       gw->setColor( LINE_COLOR, mtl->Kd[0], mtl->Kd[1], mtl->Kd[2]);
  8965.    int ptype,disptype,type=GetDrawType(this,ptype,disptype);
  8966.    if (type==3)
  8967.    { theSuprSprayDraw.obj = this;
  8968.       theSuprSprayDraw.firstpart=TRUE;
  8969.       theSuprSprayDraw.disptype=disptype;
  8970.       theSuprSprayDraw.ptype=ptype;
  8971.       theSuprSprayDraw.bb=TRUE;
  8972.       parts.SetCustomDraw(&theSuprSprayDraw);        
  8973.    }
  8974.    if ((type<2)||(type==3)) // Draw particles
  8975.    { if (type<2) parts.SetCustomDraw(NULL);
  8976.      MarkerType mt=(type==0?POINT_MRKR:PLUS_SIGN_MRKR);
  8977.      gw->setRndLimits(GW_WIREFRAME|GW_EDGES_ONLY|GW_BACKCULL| (rlim&(GW_Z_BUFFER|GW_BOX_MODE)) );
  8978.      gw->setTransform(ident);
  8979.      parts.Render(gw,mt);
  8980.      gw->setRndLimits(rlim);
  8981.    }
  8982.    else
  8983.    { parts.SetCustomDraw(&theSuprSprayDraw);      
  8984.      NullView nullView;
  8985.      BOOL needdel;
  8986.       gw->setRndLimits(rlim);
  8987.      if ((t!=dispt)||doupdate||!dispmesh)
  8988.       {
  8989.       if (dispmesh) delete dispmesh;
  8990.       SetAFlag(A_NOTREND);
  8991.       dispmesh=GetRenderMesh(t,inode,nullView,needdel);  
  8992.       ClearAFlag(A_NOTREND);
  8993.       }
  8994.      Matrix3 mat = inode->GetObjTMAfterWSM(t);
  8995.      gw->setTransform(mat);
  8996.      if(dispmesh) // dispmesh was NULL in bug 257748  DB 11/00
  8997.        dispmesh->render(gw, inode->Mtls(),
  8998.         (flags&USE_DAMAGE_RECT) ? &vpt->GetDammageRect() : NULL,
  8999.         COMP_ALL, inode->NumMtls());
  9000.    }
  9001.    return(0);
  9002. }
  9003.  
  9004. #endif // NO_PARTICLE_BIZZARD NO_PARTICLE_SUPERSPRAY
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement