1 /**********************************************************************
2  *<
3    FILE: stdmtl.cpp
4 
5    DESCRIPTION:  default material class
6 
7    CREATED BY: Dan Silva
8 
9    HISTORY:
10 
11  *>   Copyright (c) 1994, All Rights Reserved.
12  **********************************************************************/
13 
14 
15 #include "buildver.h"
16 #include "mtlhdr.h"
17 #include "mtlres.h"
18 #include "mtlresOverride.h"
19 #include "stdmtl.h"
20 #include "gport.h"
21 #include "hsv.h"
22 #include "iColorMan.h"
23 
24 #include "3dsmaxport.h"
25 
26 static Shader *GetShader(int s);
27 
28 #define HITHRESH 0.5f
29 #define LOTHRESH 0.1f
30 
31 
32 #if 1
33 // Quadratic
Soften(float r)34 static inline float Soften(float r) {
35    return r*(2.0f-r);
36    }
37 #else
38 // Cubic
Soften(float r)39 static inline float Soften(float r) {
40    return r*r*(3.0f-2.0f*r);
41    }
42 #endif
43 
44 struct SIllumParams {
45    ULONG flags;
46    float sh_str, ph_exp, shine, softThresh;
47    Color amb,diff,spec;
48    Point3 N,V;
49    Color diffIllum,specIllum,ambIllum;
50    };
51 
52 // Parameter block indices
53 #define PB_AMBIENT      0
54 #define PB_DIFFUSE      1
55 #define PB_SPECULAR     2
56 #define PB_SHININESS    3
57 #define PB_SHIN_STR     4
58 #define PB_SELFI     5
59 #define PB_OPAC         6
60 #define PB_OPFALL    7
61 #define PB_FILTER       8
62 #define PB_WIRESZ       9
63 #define PB_IOR       10
64 #define PB_BOUNCE       11
65 #define PB_STATFRIC     12
66 #define PB_SLIDFRIC     13
67 #define PB_DIMLEV    14
68 #define PB_DIMMULT      15
69 #define PB_SOFTEN    16
70 
71 //#define OLDFILTER    // scaling instead of additive
72 
73 #define IDT_MYTIMER 1010
74 #define DRAGTHRESH 6
75 #define DITHER_WHEN_INACTIVE // avoids palette conflict probs
76 #define BUMP_DEF_AMT .30f
77 
78 #define NCOLBOX 4
79 static int colID[NCOLBOX] = { IDC_STD_COLOR1, IDC_STD_COLOR2, IDC_STD_COLOR3, IDC_STD_COLOR4 };
80 
81 // >>>> must become dynamic shader table
82 extern HINSTANCE hInstance;
83 static int shadeNameID[] = { IDS_DS_CONSTANT, IDS_DS_PHONG, IDS_DS_BLINN, IDS_DS_METAL };
84 
GetPoint(LPARAM lp)85 static IPoint2 GetPoint(LPARAM lp) {
86    IPoint2 p;
87    MAKEPOINT(lp,p);
88    return p;
89    }
90 #define SET_HSV 1
91 #define SET_RGB 2
92 #define SET_BOTH (SET_HSV|SET_RGB)
93 
94 #ifdef USE_STDMTL2_AS_STDMTL
95 static Class_ID stdmtlClassID(DMTL2_CLASS_ID,0);
96 #else
97 static Class_ID stdmtlClassID(DMTL_CLASS_ID,0);
98 #endif
99 
100 int numStdMtls = 0;
101 class StdMtlClassDesc:public ClassDesc {
102    public:
IsPublic()103    int         IsPublic() { return GetAppID() != kAPP_VIZR; }
Create(BOOL loading)104    void *         Create(BOOL loading) {  return new StdMtl(loading); }
ClassName()105    const TCHAR *  ClassName() { return GetString(IDS_DS_STANDARD_CDESC); } // mjm - 2.3.99
SuperClassID()106    SClass_ID      SuperClassID() { return MATERIAL_CLASS_ID; }
ClassID()107    Class_ID       ClassID() { return stdmtlClassID; }
Category()108    const TCHAR*   Category() { return _T("");  }
109    };
110 
111 static StdMtlClassDesc stdmtlCD;
112 
GetStdMtlDesc()113 ClassDesc* GetStdMtlDesc() { return &stdmtlCD;  }
114 
115 static HIMAGELIST hLockButtons = NULL;
116 
IsButtonChecked(HWND hWnd,int id)117 static BOOL IsButtonChecked(HWND hWnd,int id)
118    {
119    ICustButton *iBut;
120    BOOL res;
121    iBut = GetICustButton(GetDlgItem(hWnd,id));
122    res = iBut->IsChecked();
123    ReleaseICustButton(iBut);
124    return res;
125    }
126 
CheckButton(HWND hWnd,int id,BOOL check)127 static void CheckButton(HWND hWnd,int id, BOOL check) {
128    ICustButton *iBut;
129    iBut = GetICustButton(GetDlgItem(hWnd,id));
130    iBut->SetCheck(check);
131    ReleaseICustButton(iBut);
132    }
133 
SetupLockButton(HWND hWnd,int id,BOOL check)134 static void SetupLockButton(HWND hWnd,int id, BOOL check)
135    {
136    ICustButton *iBut;
137    iBut = GetICustButton(GetDlgItem(hWnd,id));
138    iBut->SetImage(hLockButtons,0,1,0,1,16,15);
139    iBut->SetType(CBT_CHECK);
140    ReleaseICustButton(iBut);
141    }
142 
SetupPadLockButton(HWND hWnd,int id,BOOL check)143 static void SetupPadLockButton(HWND hWnd,int id, BOOL check) {
144    ICustButton *iBut;
145    iBut = GetICustButton(GetDlgItem(hWnd,id));
146    iBut->SetImage(hLockButtons,2,2,2,2,16,15);
147    iBut->SetType(CBT_CHECK);
148    ReleaseICustButton(iBut);
149    }
150 
LoadStdMtlResources()151 static void LoadStdMtlResources()
152    {
153    static BOOL loaded=FALSE;
154    if (loaded) return;
155    loaded = TRUE;
156    HBITMAP hBitmap, hMask;
157 
158    HINSTANCE hInst = hInstance;
159    hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
160    hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_BUTTONS));
161    hMask   = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_MASKBUTTONS));
162    ImageList_Add(hLockButtons,hBitmap,hMask);
163    DeleteObject(hBitmap);
164    DeleteObject(hMask);
165    }
166 
167 
PcToFrac(int pc)168 static inline float PcToFrac(int pc) {
169    return (float)pc/100.0f;
170    }
171 
FracToPc(float f)172 static inline int FracToPc(float f) {
173    if (f<0.0) return (int)(100.0f*f - .5f);
174    else return (int) (100.0f*f + .5f);
175    }
176 
177 
178 static LRESULT CALLBACK HiliteWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam );
179 
180 #define NMBUTS 8
181 static int texMButtons[NMBUTS] = {
182    IDC_MAPON_AM,  IDC_MAPON_DI,  IDC_MAPON_SP,  IDC_MAPON_FI,
183    IDC_MAPON_SH,  IDC_MAPON_SS,  IDC_MAPON_SI,  IDC_MAPON_TR,
184    };
185 
186 // This array gives the text map number for given MButton number
187 static int texmapFromMBut[NMBUTS] = { 0, 1, 2, 7, 3, 4, 5, 6 };
188 
189 // This array gives the MButton number for given Texmap number
190 static int mButFromTexmap[NTEXMAPS] = { 0, 1, 2, 4, 5, 6, 7, 3, -1, -1, -1, -1 };
191 
192 // >>>> these maps either need to be dynamic or allocated w/ a hard maximum.
193 
194 static int texAmtID[NTEXMAPS] = {
195    IDC_AMT_AM, IDC_AMT_DI, IDC_AMT_SP, IDC_AMT_SH, IDC_AMT_SS,
196    IDC_AMT_SI, IDC_AMT_OP, IDC_AMT_FI, IDC_AMT_BU, IDC_AMT_RL, IDC_AMT_RR, IDC_AMT_DP
197    };
198 
199 static int texOnID[NTEXMAPS] =   {
200    IDC_USEMAP_AM, IDC_USEMAP_DI, IDC_USEMAP_SP, IDC_USEMAP_SH, IDC_USEMAP_SS,
201    IDC_USEMAP_SI, IDC_USEMAP_OP, IDC_USEMAP_FI, IDC_USEMAP_BU, IDC_USEMAP_RL, IDC_USEMAP_RR, IDC_USEMAP_DP
202    };
203 
204 static int texSpinID[NTEXMAPS] = {
205    IDC_SPIN_AM, IDC_SPIN_DI, IDC_SPIN_SP, IDC_SPIN_SH, IDC_SPIN_SS,
206    IDC_SPIN_SI, IDC_SPIN_OP, IDC_SPIN_FI, IDC_SPIN_BU,   IDC_SPIN_RL, IDC_SPIN_RR, IDC_SPIN_DP
207    };
208 
209 static int texMapID[NTEXMAPS] =  {
210    IDC_MAP_AM, IDC_MAP_DI, IDC_MAP_SP, IDC_MAP_SH, IDC_MAP_SS,
211    IDC_MAP_SI, IDC_MAP_OP, IDC_MAP_FI, IDC_MAP_BU, IDC_MAP_RL, IDC_MAP_RR, IDC_MAP_DP
212    };
213 
214 static int texNameID[NTEXMAPS] = {
215    IDS_DS_AMBIENT,   IDS_DS_DIFFUSE,   IDS_DS_SPECULAR, IDS_DS_SHININESS, IDS_DS_SHIN_STR,
216    IDS_DS_SELFI,  IDS_DS_TRANS, IDS_DS_FILTER, IDS_DS_BU, IDS_DS_RL, IDS_DS_RR, IDS_DS_DP
217    };
218 
219 // which edit control enum
220 enum EditControl {Hc, Sc, Vc, Rc, Gc, Bc};
221 
222 
223 //-----------------------------------------------------------------------------
224 //  Texmaps
225 //-----------------------------------------------------------------------------
226 /*******
227 //#define TEXMAPS_CLASS_ID 0x001200
228 
229 //#ifdef USE_STDMTL2_AS_STDMTL
230 //#define TEXMAPS_CLASS_ID 0x001200+33
231 //#else
232 #define TEXMAPS_CLASS_ID 0x001200
233 //#endif
234 
235 static Class_ID texmapsClassID(TEXMAPS_CLASS_ID,0);
236 
237 class OldTexmapsClassDesc:public ClassDesc {
238    public:
239    int         IsPublic() { return 0; }
240    void *         Create(BOOL loading) {  return new Texmaps(NULL); }
241    const TCHAR *  ClassName() { return GetString(IDS_DS_CLASSTEXMAPS); }
242    SClass_ID      SuperClassID() { return REF_MAKER_CLASS_ID; }
243    Class_ID       ClassID() { return texmapsClassID; }
244    const TCHAR*   Category() { return _T("");  }
245    };
246 
247 
248 class TexmapsClassDesc:public ClassDesc {
249    public:
250    int         IsPublic() { return 0; }
251    void *         Create(BOOL loading) {  return new Texmaps(NULL); }
252    const TCHAR *  ClassName() { return GetString(IDS_DS_CLASSTEXMAPS); }
253 // SClass_ID      SuperClassID() { return REF_MAKER_CLASS_ID; }
254    SClass_ID      SuperClassID() { return TEXMAP_CONTAINER_CLASS_ID; }
255    Class_ID       ClassID() { return texmapsClassID; }
256    const TCHAR*   Category() { return _T("");  }
257    };
258 
259 TexmapSlot::TexmapSlot() {
260    amount = 1.0f;
261    map = NULL;
262    mapOn = FALSE;
263    amtCtrl=NULL;
264    }
265 
266 void TexmapSlot::Update(TimeValue t,Interval& ivalid) {
267    if (IsActive())
268       map->Update(t,ivalid);
269    if (amtCtrl) {
270       amtCtrl->GetValue(t,&amount,ivalid);
271       }
272    }
273 
274 float TexmapSlot::GetAmount(TimeValue t) {
275    Interval v;
276    float f;
277    if (amtCtrl) {
278       amtCtrl->GetValue(t,&f,v);
279       return f;
280       }
281    else return amount;
282    }
283 
284 Texmaps::Texmaps() {
285    loadingOld = FALSE;
286    client = NULL;
287    }
288 
289 
290 Texmaps::Texmaps(MtlBase *mb) {
291    loadingOld = FALSE;
292    client = mb;
293    }
294 
295 
296 static TexmapsClassDesc texmapsCD;
297 
298 ClassDesc* GetTexmapsDesc() { return &texmapsCD;  }
299 
300 static OldTexmapsClassDesc oldtexmapsCD;
301 
302 ClassDesc* GetOldTexmapsDesc() { return &oldtexmapsCD;  }
303 
304 Class_ID Texmaps::ClassID() { return texmapsClassID; }
305 
306 int Texmaps::NumSubs() { return NTEXMAPS*2; }
307 
308 Animatable* Texmaps::SubAnim(int i) {
309    if (i&1)
310       return txmap[i/2].map;
311    else
312       return txmap[i/2].amtCtrl;
313    }
314 
315 TSTR Texmaps::SubAnimName(int i) {
316    if (i&1)
317       return client->GetSubTexmapTVName(i/2);
318    else  {
319       TSTR nm;
320       nm = GetString(texNameID[i/2]);
321       nm += TSTR(GetString(IDS_DS_AMOUNT));
322       return nm;
323       }
324    }
325 
326 RefTargetHandle Texmaps::GetReference(int i) {
327    if (i&1)
328       return txmap[i/2].map;
329    else
330       return txmap[i/2].amtCtrl;
331    }
332 
333 void Texmaps::SetReference(int i, RefTargetHandle rtarg) {
334    if (loadingOld)
335       txmap[i].map = (Texmap*)rtarg;
336    else {
337       if (i&1)
338          txmap[i/2].map = (Texmap*)rtarg;
339       else
340          txmap[i/2].amtCtrl = (Control*)rtarg;
341       }
342    }
343 
344 void Texmaps::DeleteThis() { delete this;}
345 
346 RefResult Texmaps::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
347    PartID& partID, RefMessage message ) {
348    switch (message) {
349       case REFMSG_GET_PARAM_DIM: {
350          GetParamDim *gpd = (GetParamDim*)partID;
351          gpd->dim = defaultDim;
352          break;
353          }
354       case REFMSG_GET_PARAM_NAME: {
355          GetParamName *gpn = (GetParamName*)partID;
356          return REF_STOP;
357          }
358       }
359    return(REF_SUCCEED);
360    }
361 
362 void Texmaps::RescaleWorldUnits(float f) {
363    if (TestAFlag(A_WORK1))
364       return;
365    SetAFlag(A_WORK1);
366    // This code will be replaced in particular implementations
367    for (int i=0; i<NumRefs(); i++) {
368       if ( (i&1) ==0)
369          continue;  // skip the amount controllers
370       ReferenceMaker *srm = GetReference(i);
371       if (srm) {
372          srm->RescaleWorldUnits(f);
373          }
374       }
375 
376    }
377 
378 RefTargetHandle Texmaps::Clone(RemapDir &remap) {
379    Texmaps *tm = new Texmaps(NULL);
380    for (int i = 0; i<NTEXMAPS; i++) {
381       tm->txmap[i].amount = txmap[i].amount;
382       tm->txmap[i].mapOn = txmap[i].mapOn;
383       tm->txmap[i].map = NULL;
384       if (txmap[i].amtCtrl)
385          tm->ReplaceReference(2*i,remap.CloneRef(txmap[i].amtCtrl));
386       if (txmap[i].map)
387          tm->ReplaceReference(2*i+1,remap.CloneRef(txmap[i].map));
388       }
389       BaseClone(this, tm, remap);
390    return tm;
391    }
392 
393 #define TEX_OLD_ONOFF_CHUNK 0x5002
394 #define TEX_ONOFF_CHUNK 0x5003
395 #define TEX_AMT0 0x5100
396 #define TEX_AMT1 0x5101
397 #define TEX_AMT2 0x5102
398 #define TEX_AMT3 0x5103
399 #define TEX_AMT4 0x5104
400 #define TEX_AMT5 0x5105
401 #define TEX_AMT6 0x5106
402 #define TEX_AMT7 0x5107
403 #define TEX_AMT8 0x5108
404 #define TEX_AMT9 0x5109
405 #define TEX_AMTA 0x510A
406 
407 IOResult Texmaps::Save(ISave *isave) {
408    isave->BeginChunk(TEX_ONOFF_CHUNK);
409    ULONG nb,f=0;
410    for ( int i=0; i<NTEXMAPS; i++)
411       if (txmap[i].mapOn) f|= (1<<i);
412    isave->Write(&f,sizeof(f),&nb);
413    isave->EndChunk();
414 
415    for ( i=0; i<NTEXMAPS; i++) {
416       if (txmap[i].amount!=1.0f) {
417          isave->BeginChunk(TEX_AMT0+i);
418          isave->Write(&txmap[i].amount,sizeof(float),&nb);
419          isave->EndChunk();
420          }
421       }
422    return IO_OK;
423    }
424 
425 class TexmapsPostLoad : public PostLoadCallback {
426    public:
427       Texmaps *tm;
428       TexmapsPostLoad(Texmaps *b) {tm=b;}
429       void proc(ILoad *iload) {  tm->loadingOld = FALSE; delete this; }
430    };
431 
432 
433 IOResult Texmaps::Load(ILoad *iload) {
434    ULONG nb;
435    int id;
436    IOResult res;
437    while (IO_OK==(res=iload->OpenChunk())) {
438       switch(id = iload->CurChunkID())  {
439          case TEX_OLD_ONOFF_CHUNK:
440             iload->SetObsolete();
441             iload->RegisterPostLoadCallback(new TexmapsPostLoad(this));
442             loadingOld = TRUE;
443          case TEX_ONOFF_CHUNK:
444             {
445             ULONG f;
446             res = iload->Read(&f,sizeof(f), &nb);
447             for (int i=0; i<NTEXMAPS; i++)
448                 txmap[i].mapOn = (f&(1<<i))?1:0;
449             }
450             break;
451          case TEX_AMT0: case TEX_AMT1:
452          case TEX_AMT2: case TEX_AMT3:
453          case TEX_AMT4: case TEX_AMT5:
454          case TEX_AMT6: case TEX_AMT7:
455          case TEX_AMT8: case TEX_AMT9:
456          case TEX_AMTA:
457             res = iload->Read(&txmap[id-TEX_AMT0].amount,sizeof(float), &nb);
458             break;
459          }
460       iload->CloseChunk();
461       if (res!=IO_OK)
462          return res;
463       }
464    return IO_OK;
465 
466    }
467 //-----------------------------------------------------------------------------
468 **************/
469 //-----------------------------------------------------------------------------
470 //class StdMtlDlg;
471 
472 
473 //-----------------------------------------------------------------------------
474 //  StdMtlDlg
475 //-----------------------------------------------------------------------------
476 class StdMtlDlg: public ParamDlg {
477    public:
478    HWND hwmedit;   // window handle of the materials editor dialog
479    IMtlParams *ip;
480    StdMtl *theMtl;    // current mtl being edited.
481    HWND hPanelBasic; // Rollup panel
482    HWND hPanelExtra; // Rollup panel
483    HWND hPanelTexmap; // Rollup panel
484    HWND hPanelDynam; // Rollup panel
485    HWND hwHilite;  // the hilite window
486    HPALETTE hOldPal;
487    TimeValue curTime;
488    int instCopy;
489    int iStart;
490    Rect texRect;
491    int isActive;
492    IPoint2 pDown,pDrag;
493    IPoint2 pLast;
494    BOOL dragging,dragAbort;
495    Rect colBox[NCOLBOX];
496    IColorSwatch *cs[NCOLBOX];
497    BOOL animPalOn;
498    BOOL valid;
499    int editingColor; //0= amb,1= diff,2= spec, 3 = filterCol
500    DWORD curRGB;
501    int H,S,V;
502    ISpinnerControl *hSpin,*sSpin,*vSpin;
503    ISpinnerControl *rSpin,*gSpin,*bSpin;
504    ISpinnerControl *softSpin;
505    ISpinnerControl *shSpin, *ssSpin, *siSpin, *trSpin, *tfSpin, *wireSizeSpin, *iorSpin;
506    ISpinnerControl *dimSpin, *dimMultSpin;
507    ISpinnerControl* texAmtSpin[NTEXMAPS];
508    ISpinnerControl *iBounce, *iStatFrict, *iSlidFrict;
509    ICustButton* texMBut[NMBUTS];
510    ICustButton *iBut[NTEXMAPS];
511    TexDADMgr dadMgr;
512 
513    StdMtlDlg(HWND hwMtlEdit, IMtlParams *imp, StdMtl *m);
514    ~StdMtlDlg();
515    void BuildDialog();  // put up the dialog
516    void Invalidate();
517    INT_PTR BasicPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
518    INT_PTR ExtraPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
519    INT_PTR TexmapPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
520    INT_PTR DynamPanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam );
521    void ActivateDlg(BOOL onOff);
522    void LoadDialog(BOOL draw);  // stuff params into dialog
523    void SetEditColor(int i);    //0=amb, 1=diff, 2=spec, 3=filterColor
524    void SetRGB(DWORD rgb);
525    void UpdateColFromSpin(HWND hwndDlg,int indx, ISpinnerControl *spin );
526    void UpdateColControls( int  which);
527    void UpdateColSwatches();
528    void AnimPalette(HDC hdc);
529    Color MtlColor(int i);
530    TCHAR *ColorName(int i);
531    void SetMtlColor(int i, Color c);
532    void UpdateMBut(int i);
533    void ReloadDialog();
534    void EnablePhongStuff();
535    void DrawHilite(HDC hdc, Rect& rect);
536    void GenDrawHilite(HDC hdc, Rect& rect, SShader &sh);
537    void UpdateHilite();
538    void SetLockAD(BOOL lock);
539    void UpdateLockADTex();
540    void SetLockDS(BOOL lock);
541    void SetLockADTex(BOOL lock);
542    void UpdateMtlDisplay();
543    void UpdateTexmapDisplay(int i);
544    void UpdateTexmaps();
545    void FixFilterButtons();
546    void UpdateControlFor(int np);
547    void UpdateColorStuff();
KeyAtCurTime(int id)548    BOOL KeyAtCurTime(int id) { return theMtl->KeyAtTime(id,curTime); }
549    // methods inherited from ParamDLg:
ClassID()550    Class_ID ClassID() {return stdmtlClassID;  }
551    void SetThing(ReferenceTarget *m);
GetThing()552    ReferenceTarget* GetThing() { return (ReferenceTarget*)theMtl; }
DeleteThis()553    void DeleteThis() { delete this;  }
554    void SetTime(TimeValue t);
555    int FindSubTexFromHWND(HWND hw);
556    };
557 
558 static int PB_ID[4] = { PB_AMBIENT, PB_DIFFUSE, PB_SPECULAR, PB_FILTER };
559 
FindSubTexFromHWND(HWND hw)560 int StdMtlDlg::FindSubTexFromHWND(HWND hw) {
561    for (int i=0; i<NTEXMAPS; i++) {
562       if (hw == iBut[i]->GetHwnd())
563          return i;
564       }
565    for (int i=0; i<NMBUTS; i++) {
566       if (hw == texMBut[i]->GetHwnd())
567          return texmapFromMBut[i];
568       }
569    return -1;
570    }
571 
572 
573 //-------------------------------------------------------------------
574 
575 
StdMtlDlg(HWND hwMtlEdit,IMtlParams * imp,StdMtl * m)576 StdMtlDlg::StdMtlDlg(HWND hwMtlEdit, IMtlParams *imp, StdMtl *m) {
577    dadMgr.Init(this);
578    hwmedit = hwMtlEdit;
579    hPanelBasic = hPanelExtra = hPanelTexmap = hPanelDynam = NULL;
580    hOldPal = NULL;
581    theMtl = m;
582    ip = imp;
583    valid = FALSE;
584    editingColor = 1; // default to diffuse
585    animPalOn = 1;
586    isActive = 0;
587    instCopy = FALSE;
588    for (int i=0; i<NTEXMAPS; i++) iBut[i] = NULL;
589    }
590 
591 
592 
Invalidate()593 void StdMtlDlg::Invalidate()
594    {
595    valid = FALSE;
596    InvalidateRect(hPanelBasic,NULL,0);
597    InvalidateRect(hPanelExtra,NULL,0);
598    InvalidateRect(hPanelTexmap,NULL,0);
599 #ifndef NO_MTL_DYNAMICS_PARAMETERS
600    InvalidateRect(hPanelDynam,NULL,0);
601 #endif
602    }
603 
AnimPalette(HDC hdc)604 void StdMtlDlg::AnimPalette(HDC hdc) {
605 #if 0
606    if (animPalOn) {
607       GetGPort()->PlugPalette(hdc);
608       GetGPort()->AnimPalette(hdc);
609       }
610 #endif
611    }
612 
613 static TCHAR blnk[] = _T(" ");
614 static TCHAR lcm[] = _T("m");
615 static TCHAR ucm[] = _T("M");
616 
UpdateMBut(int j)617 void StdMtlDlg::UpdateMBut(int j) {
618    int i = mButFromTexmap[j];
619    if (i<0) return;
620    TCHAR* s = (*theMtl->maps)[j].map?((*theMtl->maps)[j].mapOn?ucm:lcm):blnk;
621    texMBut[i]->SetText(s);
622    Texmap *t = (*theMtl->maps)[j].map;
623    TSTR nm;
624    if (t) nm = t->GetFullName();
625    else  nm = GetString(IDS_DS_NONE);
626    texMBut[i]->SetTooltip(TRUE,nm);
627    }
628 
ReloadDialog()629 void StdMtlDlg::ReloadDialog() {
630    Interval v;
631    theMtl->Update(ip->GetTime(),v);
632    LoadDialog(FALSE);
633    }
634 
FixFilterButtons()635 void StdMtlDlg::FixFilterButtons() {
636    BOOL b = (theMtl->flags&STDMTL_FILT_TRANSP)?1:0;
637    EnableWindow(GetDlgItem(hPanelBasic,IDC_FILT), b);
638    EnableWindow(GetDlgItem(hPanelBasic,IDC_MAPON_FI), b);
639    }
640 
SetTime(TimeValue t)641 void StdMtlDlg::SetTime(TimeValue t) {
642    if (t!=curTime) {
643       curTime = t;
644       Interval v;
645       theMtl->Update(ip->GetTime(),v);
646       LoadDialog(TRUE);
647       }
648    }
649 
650 
651 // >>>> SelfIllum Color ?????
MtlColor(int i)652 Color StdMtlDlg::MtlColor(int i) {
653    switch(i) {
654       case 0: return theMtl->GetAmbient();
655       case 1: return theMtl->GetDiffuse();
656       case 2: return theMtl->GetSpecular();
657       case 3: return theMtl->GetFilter();
658       default: return Color(0,0,0);
659       }
660    }
661 
ColorName(int i)662 TCHAR *StdMtlDlg::ColorName(int i) {
663    switch(i) {
664       case 0:  return GetString(IDS_DS_AMBIENT);
665       case 1:  return GetString(IDS_DS_DIFFUSE);
666       case 2:  return GetString(IDS_DS_SPECULAR);
667       default:  return GetString(IDS_DS_FILTER);
668       }
669    }
670 
SetMtlColor(int i,Color c)671 void StdMtlDlg::SetMtlColor(int i, Color c) {
672    switch(i) {
673       case 0:
674          theMtl->SetAmbient(c,curTime);
675          if (theMtl->GetFlag(STDMTL_LOCK_AD)) {
676             theMtl->SetDiffuse(c,curTime);
677             cs[1]->SetColor(MtlColor(1));
678             if (theMtl->GetFlag(STDMTL_LOCK_DS)) {
679                theMtl->SetSpecular(c,curTime);
680                cs[2]->SetColor(MtlColor(2));
681                }
682             }
683          break;
684       case 1:
685          theMtl->SetDiffuse(c,curTime);
686          if (theMtl->GetFlag(STDMTL_LOCK_AD)) {
687             theMtl->SetAmbient(c,curTime);
688             cs[0]->SetColor(MtlColor(0));
689             }
690          if (theMtl->GetFlag(STDMTL_LOCK_DS)) {
691             theMtl->SetSpecular(c,curTime);
692             cs[2]->SetColor(MtlColor(2));
693             }
694          break;
695       case 2:
696          theMtl->SetSpecular(c,curTime);
697          if (theMtl->GetFlag(STDMTL_LOCK_DS)) {
698             theMtl->SetDiffuse(c,curTime);
699             cs[1]->SetColor(MtlColor(1));
700             if (theMtl->GetFlag(STDMTL_LOCK_AD)) {
701                theMtl->SetAmbient(c,curTime);
702                cs[0]->SetColor(MtlColor(0));
703                }
704             }
705          break;
706       case 3:
707          theMtl->SetFilter(c,curTime);
708          break;
709       }
710 
711    }
712 
~StdMtlDlg()713 StdMtlDlg::~StdMtlDlg() {
714    int i;
715    for (i=0; i<NCOLBOX; i++) {
716       ReleaseIColorSwatch(cs[i]);
717       }
718    if (hPanelBasic) {
719       HDC hdc = GetDC(hPanelBasic);
720       GetGPort()->RestorePalette(hdc, hOldPal);
721       ReleaseDC(hPanelBasic,hdc);
722       }
723 
724    theMtl->SetFlag(STDMTL_ROLLUP1_OPEN,ip->IsRollupPanelOpen(hPanelBasic));
725    theMtl->SetFlag(STDMTL_ROLLUP2_OPEN,ip->IsRollupPanelOpen(hPanelExtra));
726    theMtl->SetFlag(STDMTL_ROLLUP3_OPEN,ip->IsRollupPanelOpen(hPanelTexmap));
727 #ifndef NO_MTL_DYNAMICS_PARAMETERS
728    theMtl->SetFlag(STDMTL_ROLLUP4_OPEN,ip->IsRollupPanelOpen(hPanelDynam));
729 #endif
730    theMtl->rollScroll = ip->GetRollupScrollPos();
731 
732    theMtl->SetParamDlg(NULL);
733    for (i=0; i<NTEXMAPS; i++)
734       ReleaseISpinner(texAmtSpin[i]);
735 
736    for (i=0; i<NMBUTS; i++)
737       ReleaseICustButton(texMBut[i]);
738 
739    for (i=0; i<NTEXMAPS; i++) {
740       ReleaseICustButton(iBut[i]);
741       iBut[i] = NULL;
742       }
743 
744    ReleaseISpinner(hSpin);
745    ReleaseISpinner(sSpin);
746    ReleaseISpinner(vSpin);
747    ReleaseISpinner(rSpin);
748    ReleaseISpinner(gSpin);
749    ReleaseISpinner(bSpin);
750    ReleaseISpinner(softSpin);
751    ReleaseISpinner(shSpin);
752    ReleaseISpinner(ssSpin);
753    ReleaseISpinner(siSpin);
754    ReleaseISpinner(trSpin);
755    ReleaseISpinner(tfSpin);
756    ReleaseISpinner(wireSizeSpin);
757    ReleaseISpinner(iorSpin);
758    ReleaseISpinner(dimSpin);
759    ReleaseISpinner(dimMultSpin);
760 #ifndef NO_MTL_DYNAMICS_PARAMETERS
761    ReleaseISpinner(iBounce);
762    ReleaseISpinner(iStatFrict);
763    ReleaseISpinner(iSlidFrict);
764 #endif
765 
766    DLSetWindowLongPtr(hPanelBasic, NULL);
767    DLSetWindowLongPtr(hPanelExtra, NULL);
768    DLSetWindowLongPtr(hPanelTexmap, NULL);
769 #ifndef NO_MTL_DYNAMICS_PARAMETERS
770    DLSetWindowLongPtr(hPanelDynam, NULL);
771 #endif
772    hPanelBasic = hPanelExtra = hPanelTexmap = hPanelDynam = NULL;
773    }
774 
775 
UpdateColorStuff()776 void StdMtlDlg::UpdateColorStuff() {
777    curRGB = MtlColor(editingColor).toRGB();
778    RGBtoHSV(curRGB, &H, &S, &V);
779    UpdateColControls(SET_HSV|SET_RGB);
780    }
781 
UpdateControlFor(int np)782 void StdMtlDlg::UpdateControlFor(int np) {
783    Point3 p;
784    Interval v;
785    TimeValue t = ip->GetTime();
786    theMtl->Update(t, v);
787    switch(np) {
788       case PB_AMBIENT:
789          UpdateColSwatches();
790          if (editingColor==0)
791             UpdateColorStuff();
792          cs[0]->SetKeyBrackets(theMtl->KeyAtTime(PB_AMBIENT,curTime));
793          break;
794       case PB_DIFFUSE:
795          UpdateColSwatches();
796          if (editingColor==1)
797             UpdateColorStuff();
798          cs[1]->SetKeyBrackets(theMtl->KeyAtTime(PB_DIFFUSE,curTime));
799          break;
800       case PB_SPECULAR:
801          UpdateColSwatches();
802          if (editingColor==2)
803             UpdateColorStuff();
804          cs[2]->SetKeyBrackets(theMtl->KeyAtTime(PB_SPECULAR,curTime));
805          break;
806       case PB_SHININESS:
807          shSpin->SetValue(FracToPc(theMtl->GetShininess()),FALSE);
808          shSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SHININESS,curTime));
809          break;
810       case PB_SHIN_STR:
811          ssSpin->SetValue(FracToPc(theMtl->GetShinStr()),FALSE);
812          ssSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SHIN_STR,curTime));
813          break;
814       case PB_SOFTEN:
815          softSpin->SetValue(theMtl->GetSoftenLevel(curTime),FALSE);
816          softSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SOFTEN,curTime));
817          break;
818 
819       // >>>>
820       case PB_SELFI:
821          siSpin->SetValue(FracToPc(theMtl->GetSelfIll()),FALSE);
822          siSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_SELFI,curTime));
823          break;
824       case PB_OPAC:
825          trSpin->SetValue(FracToPc(theMtl->GetOpacity()),FALSE);
826          trSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_OPAC,curTime));
827          break;
828       case PB_OPFALL:
829          tfSpin->SetValue(FracToPc(theMtl->GetOpacFalloff()),FALSE);
830          tfSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_OPFALL,curTime));
831          break;
832       case PB_FILTER:
833          UpdateColSwatches();
834          if (editingColor==3)
835             UpdateColorStuff();
836          cs[3]->SetKeyBrackets(theMtl->KeyAtTime(PB_FILTER,curTime));
837          break;
838       case PB_WIRESZ:
839          wireSizeSpin->SetValue( theMtl->WireSize(),FALSE);
840          wireSizeSpin->SetKeyBrackets(theMtl->KeyAtTime(PB_WIRESZ,curTime));
841          break;
842       case PB_IOR:
843          iorSpin->SetValue( theMtl->GetIOR(),FALSE);
844          iorSpin->SetKeyBrackets(KeyAtCurTime(PB_IOR));
845          break;
846 #ifndef NO_MTL_DYNAMICS_PARAMETERS
847       case PB_BOUNCE:
848          iBounce->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_BOUNCE),FALSE);
849          iBounce->SetKeyBrackets(KeyAtCurTime(PB_BOUNCE));
850          break;
851       case PB_STATFRIC:
852          iStatFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_STATIC_FRICTION),FALSE);
853          iStatFrict->SetKeyBrackets(KeyAtCurTime(PB_STATFRIC));
854          break;
855       case PB_SLIDFRIC:
856          iSlidFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_SLIDING_FRICTION),FALSE);
857          iSlidFrict->SetKeyBrackets(KeyAtCurTime(PB_SLIDFRIC));
858          break;
859 #endif
860       case PB_DIMLEV:
861          dimSpin->SetValue( theMtl->GetDimIntens(curTime),FALSE);
862          dimSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMLEV));
863          break;
864       case PB_DIMMULT:
865          dimMultSpin->SetValue( theMtl->GetDimMult(curTime),FALSE);
866          dimMultSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMMULT));
867          break;
868       }
869    }
870 
871 
HiliteWndProc(HWND hwnd,UINT msg,WPARAM wParam,LPARAM lParam)872 static LRESULT CALLBACK HiliteWndProc( HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam ) {
873    LONG_PTR id = GetWindowLongPtr(hwnd,GWLP_ID);
874    HWND hwpar = GetParent(hwnd);
875    StdMtlDlg *theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwpar);
876    if (theDlg==NULL) return FALSE;
877     switch (msg)    {
878       case WM_COMMAND:
879          break;
880       case WM_MOUSEMOVE:
881          break;
882       case WM_LBUTTONUP:
883          break;
884       case WM_PAINT:
885          {
886          PAINTSTRUCT ps;
887          Rect rect;
888          HDC hdc = BeginPaint( hwnd, &ps );
889          if (!IsRectEmpty(&ps.rcPaint)) {
890             GetClientRect( hwnd, &rect );
891             theDlg->DrawHilite(hdc, rect);
892             }
893          EndPaint( hwnd, &ps );
894          }
895          break;
896       case WM_CREATE:
897       case WM_DESTROY:
898          break;
899       }
900    return DefWindowProc(hwnd,msg,wParam,lParam);
901    }
902 
ColIDToIndex(int id)903 int ColIDToIndex(int id) {
904    switch (id) {
905       case IDC_STD_COLOR1: return 0;
906       case IDC_STD_COLOR2: return 1;
907       case IDC_STD_COLOR3: return 2;
908       case IDC_STD_COLOR4: return 3;
909       default: return 0;
910       }
911    }
912 
913 
ShadeFromListID(int i)914 static int ShadeFromListID( int i) {
915    switch (i) {
916       case 0: return SHADE_CONST;
917       case 1: return SHADE_PHONG;
918       case 2: return SHADE_BLINN;
919       case 3: return SHADE_METAL;
920       default: return SHADE_PHONG;
921       }
922    }
923 
ListIDFromShade(int i)924 static int ListIDFromShade( int i) {
925    switch (i) {
926       case SHADE_CONST: return 0;
927       case SHADE_PHONG: return 1;
928       case SHADE_BLINN: return 2;
929       case SHADE_METAL: return 3;
930       default: return 1;
931       }
932    }
933 
BasicPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)934 INT_PTR StdMtlDlg::BasicPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
935    int id = LOWORD(wParam);
936    int code = HIWORD(wParam);
937     switch (msg)    {
938       case WM_INITDIALOG:
939          {
940          int i;
941 
942          HDC theHDC = GetDC(hwndDlg);
943          hOldPal = GetGPort()->PlugPalette(theHDC);
944          ReleaseDC(hwndDlg,theHDC);
945 
946          for (i=0; i<NCOLBOX; i++) {
947                cs[i] = GetIColorSwatch(GetDlgItem(hwndDlg, colID[i]),
948                   MtlColor(i), ColorName(i));
949             }
950 
951          hwHilite = GetDlgItem(hwndDlg, IDC_HIGHLIGHT);
952          DLSetWindowLongPtr( hwHilite, HiliteWndProc);
953 
954          HWND hwndShading = GetDlgItem(hwndDlg, IDC_SHADING);
955          for (i=0; i<NSHADES; i++)
956             SendMessage(hwndShading, CB_ADDSTRING, 0, (LPARAM)GetString(shadeNameID[i]));
957 
958          hSpin = SetupIntSpinner(hwndDlg, IDC_H_SPIN, IDC_H_EDIT, 0,255, 0);
959          sSpin = SetupIntSpinner(hwndDlg, IDC_S_SPIN, IDC_S_EDIT, 0,255, 0);
960          vSpin = SetupIntSpinner(hwndDlg, IDC_V_SPIN, IDC_V_EDIT, 0,255, 0);
961 
962          rSpin = SetupIntSpinner(hwndDlg, IDC_R_SPIN, IDC_R_EDIT, 0,255, 0);
963          gSpin = SetupIntSpinner(hwndDlg, IDC_G_SPIN, IDC_G_EDIT, 0,255, 0);
964          bSpin = SetupIntSpinner(hwndDlg, IDC_B_SPIN, IDC_B_EDIT, 0,255, 0);
965 
966          shSpin = SetupIntSpinner(hwndDlg, IDC_SH_SPIN, IDC_SH_EDIT, 0,100, 0);
967          ssSpin = SetupIntSpinner(hwndDlg, IDC_SS_SPIN, IDC_SS_EDIT, 0,999, 0);
968          siSpin = SetupIntSpinner(hwndDlg, IDC_SI_SPIN, IDC_SI_EDIT, 0,100, 0);
969          trSpin = SetupIntSpinner(hwndDlg, IDC_TR_SPIN, IDC_TR_EDIT, 0,100, 0);
970 
971          for (int j=0; j<NMBUTS; j++) {
972             texMBut[j] = GetICustButton(GetDlgItem(hwndDlg,texMButtons[j]));
973             texMBut[j]->SetRightClickNotify(TRUE);
974             texMBut[j]->SetDADMgr(&dadMgr);
975             }
976 
977          softSpin = SetupFloatSpinner(hwndDlg, IDC_SOFT_SPIN, IDC_SOFT_EDIT, 0.0f,1.0f,0.0f,.01f);
978 
979          SetupLockButton(hwndDlg,IDC_LOCK_AD,FALSE);
980          SetupLockButton(hwndDlg,IDC_LOCK_DS,FALSE);
981          SetupPadLockButton(hwndDlg,IDC_LOCK_ADTEX, TRUE);
982          return TRUE;
983          }
984          break;
985       case WM_COMMAND:
986             {
987             for ( int i=0; i<NMBUTS; i++) {
988                if (id == texMButtons[i]) {
989                   PostMessage(hwmedit,WM_TEXMAP_BUTTON, texmapFromMBut[i],(LPARAM)theMtl);
990                   goto exit;
991                   }
992                }
993             }
994           switch (id) {
995             case IDC_SHADING: {
996                if (code==CBN_SELCHANGE) {
997                   int newshade = ShadeFromListID(SendMessage( GetDlgItem(hwndDlg,IDC_SHADING), CB_GETCURSEL, 0, 0 ));
998                   int oldshade = theMtl->GetShaderId();
999                   if ( oldshade != newshade ) {
1000                      theMtl->SetShaderId( newshade );
1001                      softSpin->Enable(theMtl->shading!=SHADE_METAL);
1002                      UpdateMtlDisplay();
1003                      }
1004                   }
1005                break;
1006                }
1007 
1008             case IDC_AMB:
1009             case IDC_DIFF:
1010             case IDC_SPEC:
1011             case IDC_FILT:
1012                // >>>> SELFI
1013                SetEditColor(id-IDC_AMB);
1014                break;
1015 
1016             case IDC_WIRE:
1017                theMtl->SetFlag(STDMTL_WIRE, GetCheckBox(hwndDlg, IDC_WIRE));
1018                theMtl->NotifyChanged();
1019                UpdateMtlDisplay();
1020                break;
1021 
1022             case IDC_FACE_MAP:
1023                theMtl->SetFlag(STDMTL_FACEMAP, GetCheckBox(hwndDlg, IDC_FACE_MAP));
1024                UpdateMtlDisplay();
1025                theMtl->NotifyChanged();
1026                break;
1027 
1028             case IDC_2SIDE:
1029                theMtl->SetFlag(STDMTL_2SIDE, GetCheckBox(hwndDlg, IDC_2SIDE));
1030                theMtl->NotifyChanged();
1031                UpdateMtlDisplay();
1032                break;
1033 
1034             case IDC_SUPER_SAMP:
1035                theMtl->SetFlag(STDMTL_SSAMP, GetCheckBox(hwndDlg, IDC_SUPER_SAMP));
1036                break;
1037 
1038             case IDC_SOFTEN:
1039                theMtl->SetFlag(STDMTL_SOFTEN, GetCheckBox(hwndDlg, id));
1040                theMtl->NotifyChanged();
1041                UpdateMtlDisplay();
1042                break;
1043 
1044 //          case IDC_OLDSPEC:
1045 //             theMtl->SetFlag(STDMTL_OLDSPEC, GetCheckBox(hwndDlg, id));
1046 //             theMtl->NotifyChanged();
1047 //             UpdateMtlDisplay();
1048 //             break;
1049 
1050             case IDC_LOCK_AD:
1051                SetLockAD(IsButtonChecked(hwndDlg, IDC_LOCK_AD));
1052                break;
1053             case IDC_LOCK_DS:
1054                SetLockDS(IsButtonChecked(hwndDlg, IDC_LOCK_DS));
1055                break;
1056             case IDC_LOCK_ADTEX:
1057                SetLockADTex(IsButtonChecked(hwndDlg, IDC_LOCK_ADTEX));
1058                break;
1059             }
1060          break;
1061       case CC_COLOR_SEL:
1062          {
1063          int id = LOWORD(wParam);
1064          SetEditColor(ColIDToIndex(id));
1065          }
1066          break;
1067       case CC_COLOR_DROP:
1068          {
1069          int id = LOWORD(wParam);
1070          SetEditColor(ColIDToIndex(id));
1071          }
1072          break;
1073       case CC_COLOR_BUTTONDOWN:
1074          theHold.Begin();
1075          break;
1076       case CC_COLOR_BUTTONUP:
1077          if (HIWORD(wParam)) theHold.Accept(GetString(IDS_DS_PARAMCHG));
1078          else theHold.Cancel();
1079          break;
1080       case CC_COLOR_CHANGE:
1081          {
1082          int id = LOWORD(wParam);
1083          int buttonUp = HIWORD(wParam);
1084          int n = ColIDToIndex(id);
1085          if (buttonUp) theHold.Begin();
1086          SetRGB(cs[n]->GetColor());
1087          SetMtlColor(n,Color(curRGB));
1088          UpdateColControls(SET_BOTH);
1089          theMtl->NotifyChanged();
1090          if (buttonUp) {
1091             theHold.Accept(GetString(IDS_DS_PARAMCHG));
1092             UpdateMtlDisplay();
1093             }
1094          }
1095          break;
1096       case WM_PAINT:
1097          if (!valid) {
1098             valid = TRUE;
1099             ReloadDialog();
1100             }
1101          return FALSE;
1102       case WM_CLOSE:
1103          break;
1104       case WM_DESTROY:
1105          break;
1106       case CC_SPINNER_CHANGE:
1107          if (!theHold.Holding()) theHold.Begin();
1108          switch (id) {
1109             case IDC_R_SPIN: UpdateColFromSpin(hwndDlg, Rc, rSpin); break;
1110             case IDC_G_SPIN: UpdateColFromSpin(hwndDlg, Gc, gSpin); break;
1111             case IDC_B_SPIN: UpdateColFromSpin(hwndDlg, Bc, bSpin); break;
1112             case IDC_H_SPIN: UpdateColFromSpin(hwndDlg, Hc, hSpin); break;
1113             case IDC_S_SPIN: UpdateColFromSpin(hwndDlg, Sc, sSpin); break;
1114             case IDC_V_SPIN: UpdateColFromSpin(hwndDlg, Vc, vSpin); break;
1115             case IDC_SH_SPIN:
1116                theMtl->SetShininess(PcToFrac(shSpin->GetIVal()), curTime);
1117                UpdateHilite();
1118                break;
1119             case IDC_SS_SPIN:
1120                theMtl->SetShinStr(PcToFrac(ssSpin->GetIVal()),curTime);
1121                UpdateHilite();
1122                break;
1123 
1124                // >>>>
1125             case IDC_SI_SPIN:
1126                theMtl->SetSelfIllum(PcToFrac(siSpin->GetIVal()),curTime);
1127                //UpdateColControls(0);  // makes redraw smoother (black magic)
1128                break;
1129 
1130             case IDC_TR_SPIN:
1131                theMtl->SetOpacity(PcToFrac(trSpin->GetIVal()),curTime);
1132                //UpdateColControls(0);  // makes redraw smoother (black magic)
1133                break;
1134             case IDC_SOFT_SPIN:
1135                theMtl->SetSoftenLevel(softSpin->GetFVal(),curTime);
1136                break;
1137             }
1138          break;
1139       case CC_SPINNER_BUTTONDOWN:
1140          theHold.Begin();
1141          break;
1142       case WM_CUSTEDIT_ENTER:
1143       case CC_SPINNER_BUTTONUP:
1144          if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1145             theHold.Accept(GetString(IDS_DS_PARAMCHG));
1146          else
1147             theHold.Cancel();
1148          UpdateMtlDisplay();
1149          break;
1150 
1151       }
1152    exit:
1153    return FALSE;
1154    }
1155 
ExtraPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1156 INT_PTR StdMtlDlg::ExtraPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
1157    int id = LOWORD(wParam);
1158    int code = HIWORD(wParam);
1159     switch (msg)    {
1160       case WM_INITDIALOG:
1161          wireSizeSpin = SetupFloatSpinner(hwndDlg, IDC_WIRE_SPIN, IDC_WIRE_EDIT, 0.0f, 10000.0f, 1.0f);
1162          wireSizeSpin->SetAutoScale();
1163          tfSpin = SetupIntSpinner(hwndDlg, IDC_TF_SPIN, IDC_TF_EDIT, 0,100, 0);
1164          iorSpin = SetupFloatSpinner(hwndDlg, IDC_IOR_SPIN, IDC_IOR_EDIT, 0.0f,10.0f,1.5f,.01f);
1165          dimSpin = SetupFloatSpinner(hwndDlg, IDC_DIM_AMTSPIN, IDC_DIM_AMT, 0.0f,1.0f,1.0f,.01f);
1166          dimMultSpin = SetupFloatSpinner(hwndDlg, IDC_DIM_MULTSPIN, IDC_DIM_MULT, 0.1f,10.0f,1.0f,.01f);
1167          SetCheckBox(hwndDlg,IDC_DIM_REFL,theMtl->dimReflect);
1168          break;
1169       case WM_COMMAND:
1170           switch (id) {
1171             case IDC_TR_ADD:
1172             case IDC_TR_SUB:
1173             case IDC_TR_SUB2:
1174                CheckRadioButton( hwndDlg, IDC_TR_ADD,IDC_TR_SUB2,id);
1175                theMtl->SetFlag(STDMTL_ADD_TRANSP, id==IDC_TR_ADD);
1176                theMtl->SetFlag(STDMTL_FILT_TRANSP, id==IDC_TR_SUB2);
1177                FixFilterButtons();
1178                theMtl->NotifyChanged();
1179                break;
1180 
1181             case IDC_TF_IN:
1182             case IDC_TF_OUT:
1183                CheckRadioButton( hwndDlg, IDC_TF_IN,IDC_TF_OUT,id);
1184                theMtl->SetFlag(STDMTL_FALLOFF_OUT, id==IDC_TF_OUT);
1185                theMtl->NotifyChanged();
1186                break;
1187 
1188             case IDC_PIXELS:
1189             case IDC_UNITS:
1190                CheckRadioButton( hwndDlg, IDC_PIXELS,IDC_UNITS,id);
1191                theMtl->SetFlag(STDMTL_WIRE_UNITS, id==IDC_UNITS);
1192                if (theMtl->GetFlag(STDMTL_WIRE)) {
1193                   UpdateMtlDisplay();
1194                   theMtl->NotifyChanged();
1195                   }
1196                break;
1197             case IDC_DIM_REFL:
1198                theMtl->dimReflect = GetCheckBox(hwndDlg,IDC_DIM_REFL);
1199                theMtl->NotifyChanged();
1200                break;
1201             }
1202          break;
1203       case WM_PAINT:
1204          if (!valid) {
1205             valid = TRUE;
1206             ReloadDialog();
1207             }
1208          return FALSE;
1209       case WM_DESTROY:     break;
1210          break;
1211       case CC_SPINNER_CHANGE:
1212          if (!theHold.Holding()) theHold.Begin();
1213          switch(id) {
1214             case IDC_WIRE_SPIN:
1215                theMtl->SetWireSize(wireSizeSpin->GetFVal(),curTime);
1216                break;
1217             case IDC_TF_SPIN: theMtl->SetOpacFalloff(PcToFrac(tfSpin->GetIVal()),curTime);
1218                break;
1219             case IDC_IOR_SPIN:
1220                theMtl->SetIOR(iorSpin->GetFVal(),curTime);
1221                break;
1222             case IDC_DIM_AMTSPIN:
1223                theMtl->SetDimIntens(dimSpin->GetFVal(),curTime);
1224                break;
1225             case IDC_DIM_MULTSPIN:
1226                theMtl->SetDimMult(dimMultSpin->GetFVal(),curTime);
1227                break;
1228             }
1229          break;
1230       case CC_SPINNER_BUTTONDOWN:
1231          theHold.Begin();
1232          break;
1233       case WM_CUSTEDIT_ENTER:
1234       case CC_SPINNER_BUTTONUP:
1235          if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1236             theHold.Accept(GetString(IDS_DS_PARAMCHG));
1237          else
1238             theHold.Cancel();
1239          UpdateMtlDisplay();
1240          break;
1241     default:
1242         return FALSE;
1243       }
1244    return FALSE;
1245    }
1246 
1247 //----------------------------------------------------------------------------
1248 // ---  Drag-and-drop for Texture Maps ----
1249 //----------------------------------------------------------------------------
1250 
1251 
TexmapPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1252 INT_PTR StdMtlDlg::TexmapPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
1253    int id = LOWORD(wParam);
1254    int code = HIWORD(wParam);
1255     switch (msg)    {
1256       case WM_INITDIALOG:{
1257          for (int i=0; i<NTEXMAPS; i++) {
1258             if (i==ID_BU||i==ID_DP)
1259                texAmtSpin[i] = SetupIntSpinner(hwndDlg, texSpinID[i],texAmtID[i], -999,999, 0);
1260             else
1261                texAmtSpin[i] = SetupIntSpinner(hwndDlg, texSpinID[i],texAmtID[i], 0,100, 0);
1262             HWND hw = GetDlgItem(hwndDlg, texMapID[i]);
1263 //          WNDPROC oldp = DLGetWindowProc(hw);
1264 //          DLSetWindowLongPtr( hw, TexSlotWndProc);
1265 //          DLSetWindowLongPtr( hw, oldp);
1266             iBut[i] = GetICustButton(GetDlgItem(hwndDlg, texMapID[i]));
1267             iBut[i]->SetDADMgr(&dadMgr);
1268             }
1269          SetupPadLockButton(hwndDlg,IDC_LOCK_ADTEX, TRUE);
1270          }
1271          break;
1272       case WM_COMMAND:
1273          {
1274          for (int i=0; i<NTEXMAPS; i++) {
1275             if (id == texOnID[i]) {
1276                theMtl->EnableMap(i,GetCheckBox(hwndDlg, id));
1277                UpdateMBut(i);
1278                goto exit;
1279                }
1280             if (id == texMapID[i]) {
1281                PostMessage(hwmedit,WM_TEXMAP_BUTTON, i ,(LPARAM)theMtl);
1282                goto exit;
1283                }
1284             }
1285          }
1286 
1287           switch (id) {
1288             case IDC_LOCK_ADTEX:
1289                SetLockADTex(IsButtonChecked(hwndDlg, IDC_LOCK_ADTEX));
1290                break;
1291             }
1292          break;
1293       case WM_PAINT:
1294          if (!valid) {
1295             valid = TRUE;
1296             ReloadDialog();
1297             }
1298          return FALSE;
1299       case WM_DESTROY:     break;
1300       case CC_SPINNER_CHANGE:
1301          {
1302          if (!theHold.Holding()) theHold.Begin();
1303          for (int i=0; i<NTEXMAPS; i++) {
1304             if (id == texSpinID[i]) {
1305                theMtl->SetTexmapAmt(i,PcToFrac(texAmtSpin[i]->GetIVal()), curTime);
1306                texAmtSpin[i]->SetKeyBrackets(theMtl->AmtKeyAtTime(i,curTime));
1307                break;
1308                }
1309             }
1310          }
1311          break;
1312       case CC_SPINNER_BUTTONDOWN:
1313          theHold.Begin();
1314          break;
1315       case WM_CUSTEDIT_ENTER:
1316       case CC_SPINNER_BUTTONUP:
1317          if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1318             theHold.Accept(GetString(IDS_DS_PARAMCHG));
1319          else
1320             theHold.Cancel();
1321          UpdateMtlDisplay();
1322          break;
1323        default:
1324           return FALSE;
1325       }
1326    exit:
1327    return FALSE;
1328    }
1329 
1330 
DynamPanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1331 INT_PTR StdMtlDlg::DynamPanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam ) {
1332    int id = LOWORD(wParam);
1333    int code = HIWORD(wParam);
1334     switch (msg)    {
1335       case WM_INITDIALOG:
1336          iBounce =    SetupFloatSpinner(hwndDlg, IDC_BOUNCE_SPIN, IDC_BOUNCE_EDIT, 0.0f,1.0f,1.0f,.01f);
1337          iStatFrict = SetupFloatSpinner(hwndDlg, IDC_STATFRIC_SPIN, IDC_STATFRIC_EDIT, 0.0f,1.0f,0.0f,.01f);
1338          iSlidFrict = SetupFloatSpinner(hwndDlg, IDC_SLIDFRIC_SPIN, IDC_SLIDFRIC_EDIT, 0.0f,1.0f,0.0f,.01f);
1339          break;
1340       case WM_COMMAND:
1341          break;
1342       case WM_DESTROY:     break;
1343       case CC_SPINNER_CHANGE:
1344          {
1345          if (!theHold.Holding()) theHold.Begin();
1346          switch(id) {
1347             case IDC_BOUNCE_SPIN:
1348                theMtl->SetDynamicsProperty(curTime,0,DYN_BOUNCE,iBounce->GetFVal());
1349                break;
1350             case IDC_STATFRIC_SPIN:
1351                theMtl->SetDynamicsProperty(curTime,0,DYN_STATIC_FRICTION,iStatFrict->GetFVal());
1352                break;
1353             case IDC_SLIDFRIC_SPIN:
1354                theMtl->SetDynamicsProperty(curTime,0,DYN_SLIDING_FRICTION,iSlidFrict->GetFVal());
1355                break;
1356             }
1357          }
1358          break;
1359       case CC_SPINNER_BUTTONDOWN:
1360          theHold.Begin();
1361          break;
1362       case WM_CUSTEDIT_ENTER:
1363       case CC_SPINNER_BUTTONUP:
1364          if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1365             theHold.Accept(GetString(IDS_DS_PARAMCHG));
1366          else
1367             theHold.Cancel();
1368          break;
1369        default:
1370           return FALSE;
1371 
1372       }
1373    return FALSE;
1374    }
1375 
BasicPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1376 static INT_PTR CALLBACK  BasicPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1377    StdMtlDlg *theDlg;
1378    if (msg==WM_INITDIALOG) {
1379       theDlg = (StdMtlDlg*)lParam;
1380       theDlg->hPanelBasic = hwndDlg;
1381       DLSetWindowLongPtr(hwndDlg, lParam);
1382       }
1383    else {
1384        if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1385          return FALSE;
1386       }
1387    BOOL res;
1388    theDlg->isActive = 1;
1389    res = theDlg->BasicPanelProc(hwndDlg,msg,wParam,lParam);
1390    theDlg->isActive = 0;
1391    return res;
1392    }
1393 
ExtraPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1394 static INT_PTR CALLBACK  ExtraPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1395    StdMtlDlg *theDlg;
1396    if (msg==WM_INITDIALOG) {
1397       theDlg = (StdMtlDlg*)lParam;
1398       theDlg->hPanelExtra = hwndDlg;
1399       DLSetWindowLongPtr(hwndDlg, lParam);
1400       }
1401    else {
1402        if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1403          return FALSE;
1404       }
1405    BOOL res;
1406    theDlg->isActive = 1;
1407    res = theDlg->ExtraPanelProc(hwndDlg,msg,wParam,lParam);
1408    theDlg->isActive = 0;
1409    return res;
1410    }
1411 
TexmapPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1412 static INT_PTR CALLBACK  TexmapPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1413    StdMtlDlg *theDlg;
1414    if (msg==WM_INITDIALOG) {
1415       theDlg = (StdMtlDlg*)lParam;
1416       theDlg->hPanelTexmap = hwndDlg;
1417       DLSetWindowLongPtr(hwndDlg, lParam);
1418       }
1419    else {
1420        if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1421          return FALSE;
1422       }
1423    BOOL res;
1424    theDlg->isActive = 1;
1425    res = theDlg->TexmapPanelProc(hwndDlg,msg,wParam,lParam);
1426    theDlg->isActive = 0;
1427    return res;
1428    }
1429 
1430 
DynamPanelDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1431 static INT_PTR CALLBACK  DynamPanelDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1432    StdMtlDlg *theDlg;
1433    if (msg==WM_INITDIALOG) {
1434       theDlg = (StdMtlDlg*)lParam;
1435       theDlg->hPanelDynam = hwndDlg;
1436       DLSetWindowLongPtr(hwndDlg, lParam);
1437       }
1438    else {
1439        if ( (theDlg = DLGetWindowLongPtr<StdMtlDlg *>(hwndDlg) ) == NULL )
1440          return FALSE;
1441       }
1442    BOOL res;
1443    theDlg->isActive = 1;
1444    res = theDlg->DynamPanelProc(hwndDlg,msg,wParam,lParam);
1445    theDlg->isActive = 0;
1446    return res;
1447    }
1448 
UpdateTexmapDisplay(int i)1449 void StdMtlDlg::UpdateTexmapDisplay(int i) {
1450    texAmtSpin[i]->SetValue(FracToPc(theMtl->GetTexmapAmt(i)),FALSE);
1451    texAmtSpin[i]->SetKeyBrackets(theMtl->AmtKeyAtTime(i,curTime));
1452    SetCheckBox(hPanelTexmap, texOnID[i], theMtl->IsMapEnabled(i));
1453    Texmap *t = (*theMtl->maps)[i].map;
1454    TSTR nm;
1455    if (t)
1456       nm = t->GetFullName();
1457    else
1458       nm = GetString(IDS_DS_NONE);
1459    iBut[i]->SetText(nm.data());
1460 // SetDlgItemText(hPanelTexmap, texMapID[i], nm.data());
1461    UpdateMBut(i);
1462    }
1463 
UpdateTexmaps()1464 void StdMtlDlg::UpdateTexmaps() {
1465    for (int i=0; i<NTEXMAPS; i++)
1466       UpdateTexmapDisplay(i);
1467    }
1468 
LoadDialog(BOOL draw)1469 void  StdMtlDlg::LoadDialog(BOOL draw) {
1470    if (theMtl&&hPanelBasic) {
1471       Interval v;
1472 //    assert(hPanelBasic);
1473 
1474       // BASIC PANEL
1475       HWND hwndShading = GetDlgItem(hPanelBasic, IDC_SHADING);
1476       SendMessage( hwndShading, CB_SETCURSEL, ListIDFromShade((WPARAM)theMtl->GetShaderId()), (LPARAM)0 );
1477       ULONG flg = theMtl->flags;
1478       SetCheckBox(hPanelBasic,IDC_WIRE,  (flg&STDMTL_WIRE)?1:0);
1479       SetCheckBox(hPanelBasic,IDC_2SIDE, (flg&STDMTL_2SIDE)?1:0);
1480       SetCheckBox(hPanelBasic,IDC_SUPER_SAMP, (flg&STDMTL_SSAMP)?1:0);
1481 
1482 //    SetCheckBox(hPanelBasic,IDC_SOFTEN, (flg&STDMTL_SOFTEN)?1:0);
1483 //    SetCheckBox(hPanelBasic,IDC_OLD_SPEC, (flg&STDMTL_OLDSPEC)?1:0);
1484       SetCheckBox(hPanelBasic,IDC_FACE_MAP, (flg&STDMTL_FACEMAP)?1:0);
1485       CheckRadioButton( hPanelBasic, IDC_AMB,IDC_FILT, IDC_AMB+editingColor);
1486       shSpin->SetValue(FracToPc(theMtl->GetShininess()),FALSE);
1487       shSpin->SetKeyBrackets(KeyAtCurTime(PB_SHININESS));
1488 
1489       ssSpin->SetValue(FracToPc(theMtl->GetShinStr()),FALSE);
1490       ssSpin->SetKeyBrackets(KeyAtCurTime(PB_SHIN_STR));
1491 
1492       // >>>>
1493       siSpin->SetValue(FracToPc(theMtl->GetSelfIll()),FALSE);
1494       siSpin->SetKeyBrackets(KeyAtCurTime(PB_SELFI));
1495 
1496       trSpin->SetValue(FracToPc(theMtl->GetOpacity()),FALSE);
1497       trSpin->SetKeyBrackets(KeyAtCurTime(PB_OPAC));
1498 
1499       tfSpin->SetValue(FracToPc(theMtl->GetOpacFalloff()),FALSE);
1500       tfSpin->SetKeyBrackets(KeyAtCurTime(PB_OPFALL));
1501 
1502       softSpin->SetValue(theMtl->softThresh,FALSE);
1503       softSpin->SetKeyBrackets(KeyAtCurTime(PB_SOFTEN));
1504       softSpin->Enable(theMtl->shading!=SHADE_METAL);
1505 
1506       CheckButton(hPanelBasic, IDC_LOCK_AD, theMtl->GetFlag(STDMTL_LOCK_AD));
1507       CheckButton(hPanelBasic, IDC_LOCK_DS, theMtl->GetFlag(STDMTL_LOCK_DS));
1508       UpdateLockADTex();
1509       FixFilterButtons();
1510       EnablePhongStuff();
1511 
1512       curRGB = MtlColor(editingColor).toRGB();
1513       RGBtoHSV(curRGB, &H, &S, &V);
1514       UpdateColControls(SET_HSV|SET_RGB);
1515 
1516       UpdateColSwatches();
1517       UpdateHilite();
1518 
1519       // EXTRA PANEL
1520       int b,c;
1521       b = theMtl->GetFlag(STDMTL_ADD_TRANSP);
1522       c = theMtl->GetFlag(STDMTL_FILT_TRANSP);
1523       CheckRadioButton(hPanelExtra,IDC_TR_ADD,IDC_TR_SUB2,b?IDC_TR_ADD:c?IDC_TR_SUB2:IDC_TR_SUB);
1524 
1525       b = theMtl->GetFlag(STDMTL_FALLOFF_OUT);
1526       CheckRadioButton(hPanelExtra,IDC_TF_IN,IDC_TF_OUT,b?IDC_TF_OUT:IDC_TF_IN);
1527 
1528       b = theMtl->GetFlag(STDMTL_WIRE_UNITS);
1529       CheckRadioButton(hPanelExtra,IDC_PIXELS,IDC_UNITS,b?IDC_UNITS:IDC_PIXELS);
1530 
1531       wireSizeSpin->SetValue( theMtl->WireSize(),FALSE);
1532       wireSizeSpin->SetKeyBrackets(KeyAtCurTime(PB_WIRESZ));
1533 
1534       iorSpin->SetValue( theMtl->GetIOR(),FALSE);
1535       iorSpin->SetKeyBrackets(KeyAtCurTime(PB_IOR));
1536 
1537       SetCheckBox(hPanelExtra,IDC_DIM_REFL,theMtl->dimReflect);
1538 
1539       dimSpin->SetValue( theMtl->GetDimIntens(curTime),FALSE);
1540       dimSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMLEV));
1541 
1542       dimMultSpin->SetValue( theMtl->GetDimMult(curTime),FALSE);
1543       dimMultSpin->SetKeyBrackets(KeyAtCurTime(PB_DIMMULT));
1544 
1545 
1546       // TEXMAP PANEL & BASIC PANEL
1547       for (int i=0; i<NTEXMAPS; i++)
1548          UpdateTexmapDisplay(i);
1549 
1550 #ifndef   NO_MTL_DYNAMICS_PARAMETERS
1551       // DYNAMICS PANEL
1552       iBounce->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_BOUNCE),FALSE);
1553       iBounce->SetKeyBrackets(KeyAtCurTime(PB_BOUNCE));
1554 
1555       iStatFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_STATIC_FRICTION),FALSE);
1556       iStatFrict->SetKeyBrackets(KeyAtCurTime(PB_STATFRIC));
1557 
1558       iSlidFrict->SetValue(theMtl->GetDynamicsProperty(curTime,0,DYN_SLIDING_FRICTION),FALSE);
1559       iSlidFrict->SetKeyBrackets(KeyAtCurTime(PB_SLIDFRIC));
1560 #endif
1561       }
1562    }
1563 
SetRGB(DWORD rgb)1564 void StdMtlDlg::SetRGB(DWORD rgb) {
1565    curRGB = rgb;
1566    RGBtoHSV (curRGB, &H, &S, &V);
1567    }
1568 
1569 
UpdateColSwatches()1570 void StdMtlDlg::UpdateColSwatches() {
1571    for(int i=0; i<NCOLBOX; i++) {
1572       cs[i]->SetKeyBrackets(theMtl->KeyAtTime(PB_ID[i],curTime));
1573       cs[i]->SetColor(MtlColor(i));
1574       }
1575    }
1576 
UpdateColControls(int which)1577 void StdMtlDlg::UpdateColControls( int  which) {
1578    HDC hdc;
1579     hdc = GetDC (hPanelBasic);
1580    BOOL key = KeyAtCurTime(PB_ID[editingColor]);
1581     if (which & SET_HSV) {
1582       hSpin->SetValue((int)H,FALSE);
1583       sSpin->SetValue((int)S,FALSE);
1584       vSpin->SetValue((int)V,FALSE);
1585       hSpin->SetKeyBrackets(key);
1586       sSpin->SetKeyBrackets(key);
1587       vSpin->SetKeyBrackets(key);
1588        }
1589     if (which & SET_RGB) {
1590       rSpin->SetValue((int)GetRValue (curRGB),FALSE);
1591       gSpin->SetValue((int)GetGValue (curRGB),FALSE);
1592       bSpin->SetValue((int)GetBValue (curRGB),FALSE);
1593       rSpin->SetKeyBrackets(key);
1594       gSpin->SetKeyBrackets(key);
1595       bSpin->SetKeyBrackets(key);
1596        }
1597    ReleaseDC(hPanelBasic,hdc);
1598    }
1599 
UpdateColFromSpin(HWND hwndDlg,int indx,ISpinnerControl * spin)1600 void StdMtlDlg::UpdateColFromSpin(HWND hwndDlg,int indx, ISpinnerControl *spin ) {
1601     int r, g, b;
1602     int *vals[6] = {&H, &S, &V, &r, &g, &b};
1603     int update = 0;
1604     r = GetRValue (curRGB);
1605     g = GetGValue (curRGB);
1606     b = GetBValue (curRGB);
1607     *vals[indx] = spin->GetIVal();
1608     switch (indx) {
1609         case Hc: case Sc: case Vc:
1610             // Changing the HSV settings.  Compute new RGB.
1611             curRGB = HSVtoRGB (H, S, V);
1612             update |= SET_RGB; // Update only the RGB controls.
1613             break;
1614         case Rc: case Gc:  case Bc:
1615             // Changing the RGB settings.  Compute new HSV.
1616          SetRGB(RGB(r,g,b));
1617             update |= SET_HSV; // Update only the HSV controls.
1618             break;
1619        }
1620    SetMtlColor(editingColor,Color(curRGB));
1621    UpdateColControls(update);
1622    cs[editingColor]->SetColor(MtlColor(editingColor));
1623    }
1624 
UpdateMtlDisplay()1625 void StdMtlDlg::UpdateMtlDisplay() {
1626    ip->MtlChanged(); // redraw viewports
1627    }
1628 
1629 
ActivateDlg(BOOL onOff)1630 void StdMtlDlg::ActivateDlg(BOOL onOff) {
1631    UpdateColControls(0);
1632    for(int i=0; i<NCOLBOX; i++)
1633       cs[i]->Activate(onOff);
1634 // UpdateColSwatches();
1635    }
1636 
SetEditColor(int i)1637 void StdMtlDlg::SetEditColor(int i) {
1638    editingColor = i;
1639    cs[editingColor]->EditThis(FALSE);
1640    curRGB = MtlColor(i).toRGB();
1641    RGBtoHSV(curRGB, &H, &S, &V);
1642    UpdateColControls(SET_HSV|SET_RGB);
1643    if (hPanelBasic) {
1644       CheckRadioButton( hPanelBasic, IDC_AMB,IDC_FILT, IDC_AMB+i);
1645       //cs[i]->SetCheck(check);
1646       }
1647    }
1648 
1649 
SetLockAD(BOOL lock)1650 void StdMtlDlg::SetLockAD(BOOL lock) {
1651    if (lock) {
1652       if (IDYES!=MessageBox(hwmedit, GetString(IDS_DS_LOCKAD), GetString(IDS_DS_LOCKCOL), MB_YESNO)) {
1653          CheckButton(hPanelBasic, IDC_LOCK_AD, FALSE);
1654          return;
1655          }
1656       if (editingColor==0)
1657          SetMtlColor(1, MtlColor(0));
1658       else
1659          SetMtlColor(0, MtlColor(1));
1660       UpdateColControls(SET_HSV|SET_RGB);
1661       UpdateColSwatches();
1662       }
1663    theMtl->SetFlag(STDMTL_LOCK_AD,lock);
1664    }
1665 
IndexForMapID(int id)1666 static int IndexForMapID(int id) {
1667    for (int i=0; i<NTEXMAPS; i++) if (id==texMapID[i]) return i;
1668    return 0;
1669    }
UpdateLockADTex()1670 void StdMtlDlg::UpdateLockADTex() {
1671    int lock =  theMtl->GetFlag(STDMTL_LOCK_ADTEX);
1672    CheckButton(hPanelBasic, IDC_LOCK_ADTEX,lock);
1673    CheckButton(hPanelTexmap, IDC_LOCK_ADTEX,lock);
1674    ShowWindow(GetDlgItem(hPanelBasic,IDC_MAPON_AM), !lock);
1675    iBut[IndexForMapID(IDC_MAP_AM)]->Enable(!lock);
1676    }
1677 
SetLockADTex(BOOL lock)1678 void StdMtlDlg::SetLockADTex(BOOL lock) {
1679    theMtl->SetFlag(STDMTL_LOCK_ADTEX,lock);
1680    UpdateLockADTex();
1681    theMtl->NotifyChanged();
1682    UpdateMtlDisplay();
1683    }
1684 
SetLockDS(BOOL lock)1685 void StdMtlDlg::SetLockDS(BOOL lock) {
1686    if (lock) {
1687       if (IDYES!=MessageBox(hwmedit, GetString(IDS_DS_LOCK_DS),GetString(IDS_DS_LOCKCOL), MB_YESNO)) {
1688          CheckButton(hPanelBasic, IDC_LOCK_DS, FALSE);
1689          return;
1690          }
1691       if (editingColor==2)
1692          SetMtlColor(1, MtlColor(2));
1693       else
1694          SetMtlColor(2, MtlColor(1));
1695       UpdateColControls(SET_HSV|SET_RGB);
1696       UpdateColSwatches();
1697       }
1698    theMtl->SetFlag(STDMTL_LOCK_DS,lock);
1699    }
1700 
SetThing(ReferenceTarget * m)1701 void StdMtlDlg::SetThing(ReferenceTarget *m) {
1702    assert (m->SuperClassID()==MATERIAL_CLASS_ID);
1703    assert (m->ClassID()==stdmtlClassID);
1704    if (theMtl)
1705       theMtl->paramDlg = NULL;
1706    theMtl = (StdMtl *)m;
1707    if (theMtl)
1708       theMtl->paramDlg = this;
1709    LoadDialog(TRUE);
1710    if (hPanelBasic)
1711       for (int i=0; i<4; i++) cs[i]->InitColor(MtlColor(i));
1712    }
1713 
VertLine(HDC hdc,int x,int ystart,int yend)1714 static void VertLine(HDC hdc,int x, int ystart, int yend) {
1715    MoveToEx(hdc,x,ystart,NULL);
1716    if (ystart<=yend)
1717       LineTo(hdc, x, yend+1);
1718    else
1719       LineTo(hdc, x, yend-1);
1720    }
1721 
1722 
1723 //-------------------------------------------------------
1724 
1725 //-------------------------------------------------------
GenDrawHilite(HDC hdc,Rect & rect,SShader & sh)1726 void StdMtlDlg::GenDrawHilite(HDC hdc, Rect& rect, SShader &sh) {
1727    int w,h,npts,xcen,ybot,ytop,ylast,i,iy;
1728    HPEN linePen = (HPEN)GetStockObject(WHITE_PEN);
1729    HPEN fgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNFACE));
1730    HPEN bgPen = CreatePen(PS_SOLID,0,GetCustSysColor(COLOR_BTNSHADOW));
1731    w = rect.w();
1732    h = rect.h()-3;
1733    npts = (w-2)/2;
1734    xcen = rect.left+npts;
1735    ybot = rect.top+h;
1736    ytop = rect.top+2;
1737    ylast = -1;
1738    for (i=0; i<npts; i++) {
1739       float v = sh.EvalHilite((float)i/((float)npts*2.0f));
1740       if (v>2.0f) v = 2.0f; // keep iy from wrapping
1741       iy = ybot-(int)(v*((float)h-2.0f));
1742 
1743       if (iy<ytop) iy = ytop;
1744 
1745       SelectPen(hdc, fgPen);
1746       VertLine(hdc,xcen+i,ybot,iy);
1747       VertLine(hdc,xcen-i,ybot,iy);
1748 
1749       if (iy-1>ytop) {
1750          // Fill in above curve
1751          SelectPen(hdc,bgPen);
1752          VertLine(hdc,xcen+i, ytop, iy-1);
1753          VertLine(hdc,xcen-i, ytop, iy-1);
1754          }
1755       if (ylast>=0) {
1756          SelectPen(hdc,linePen);
1757          VertLine(hdc,xcen+i-1,iy-1,ylast);
1758          VertLine(hdc,xcen-i+1,iy-1,ylast);
1759          }
1760 
1761       ylast = iy;
1762       }
1763    SelectObject( hdc, linePen );
1764    DeleteObject(fgPen);
1765    DeleteObject(bgPen);
1766    WhiteRect3D(hdc, rect, 1);
1767    }
1768 
DrawHilite(HDC hdc,Rect & rect)1769 void StdMtlDlg::DrawHilite(HDC hdc, Rect& rect) {
1770    if (theMtl==NULL) return;
1771    theMtl->UpdateShader();
1772    GenDrawHilite(hdc,rect,*theMtl->curShader);
1773    }
1774 
EnablePhongStuff()1775 void StdMtlDlg::EnablePhongStuff() {
1776    BOOL b = theMtl->shading==SHADE_METAL?0:1;
1777    EnableWindow(GetDlgItem(hPanelBasic,IDC_SOFTEN), b);
1778    EnableWindow(GetDlgItem(hPanelBasic,IDC_SPEC), b);
1779    EnableWindow(GetDlgItem(hPanelBasic,IDC_MAPON_SP), b);
1780    EnableWindow(GetDlgItem(hPanelTexmap,IDC_USEMAP_SP), b);
1781    EnableWindow(GetDlgItem(hPanelTexmap,IDC_AMT_SP), b);
1782    EnableWindow(GetDlgItem(hPanelTexmap,IDC_SPIN_SP), b);
1783    EnableWindow(GetDlgItem(hPanelTexmap,IDC_MAP_SP), b);
1784    EnableWindow(GetDlgItem(hPanelTexmap,IDC_MAP_SP), b);
1785    if (b) cs[2]->Enable(); else cs[2]->Disable();
1786    }
1787 
UpdateHilite()1788 void StdMtlDlg::UpdateHilite() {
1789    HDC hdc = GetDC(hwHilite);
1790    Rect r;
1791    GetClientRect(hwHilite,&r);
1792    DrawHilite(hdc, r);
1793    ReleaseDC(hwHilite,hdc);
1794    }
1795 
1796 
BuildDialog()1797 void StdMtlDlg::BuildDialog() {
1798    if ((theMtl->flags&(STDMTL_ROLLUP_FLAGS))==0)
1799       theMtl->flags |= STDMTL_ROLLUP1_OPEN;
1800    hPanelBasic = ip->AddRollupPage(
1801       hInstance,  //getResMgr().getHInst(RES_ID_DS),
1802       MAKEINTRESOURCE(IDD_DMTL_BASIC),
1803       BasicPanelDlgProc,
1804       GetString(IDS_DS_BASIC),
1805       (LPARAM)this,
1806       theMtl->flags&STDMTL_ROLLUP1_OPEN?0:APPENDROLL_CLOSED
1807       );
1808 
1809    hPanelExtra = ip->AddRollupPage(
1810       hInstance,  //getResMgr().getHInst(RES_ID_DS),
1811       MAKEINTRESOURCE(IDD_DMTL_EXTRA),
1812       ExtraPanelDlgProc,
1813       GetString(IDS_DS_EXTRA),
1814       (LPARAM)this,
1815       theMtl->flags&STDMTL_ROLLUP2_OPEN?0:APPENDROLL_CLOSED
1816       );
1817 
1818       hPanelTexmap = ip->AddRollupPage(
1819       hInstance,  //getResMgr().getHInst(RES_ID_DS),
1820       MAKEINTRESOURCE(IDD_DMTL_TEXMAP),
1821       TexmapPanelDlgProc,
1822       GetString(IDS_DS_TEXMAP),
1823       (LPARAM)this,
1824       theMtl->flags&STDMTL_ROLLUP3_OPEN?0:APPENDROLL_CLOSED
1825       );
1826 
1827 #ifndef NO_MTL_DYNAMICS_PARAMETERS
1828       hPanelDynam = ip->AddRollupPage(
1829       hInstance,  //getResMgr().getHInst(RES_ID_DS),
1830       MAKEINTRESOURCE(IDD_DMTL_DYNAM),
1831       DynamPanelDlgProc,
1832       GetString(IDS_DS_DYNAMICS),
1833       (LPARAM)this,
1834       theMtl->flags&STDMTL_ROLLUP4_OPEN?0:APPENDROLL_CLOSED
1835       );
1836 #endif
1837 
1838    ip->SetRollupScrollPos(theMtl->rollScroll);
1839    }
1840 
1841 
1842 //-----------------------------------------------------------------------------
1843 //  StdMtl
1844 //-----------------------------------------------------------------------------
1845 
1846 
1847 #define NPARAMS 17
1848 #define STDMTL_PBVERSION   9
1849 
1850 //Current Param Block Descriptor
1851 static ParamBlockDescID stdmtlPB[NPARAMS] = {
1852    { TYPE_RGBA, NULL, TRUE,1 },    // ambient
1853    { TYPE_RGBA, NULL, TRUE,2 },    // diffuse
1854    { TYPE_RGBA, NULL, TRUE,3 },    // specular
1855    { TYPE_FLOAT, NULL, TRUE,4 },   // shininess
1856    { TYPE_FLOAT, NULL, TRUE,5 },   // shini_strength
1857    { TYPE_FLOAT, NULL, TRUE,6 },   // self-illum
1858    { TYPE_FLOAT, NULL, TRUE,7 },   // opacity
1859    { TYPE_FLOAT, NULL, TRUE,8 }, // opfalloff
1860    { TYPE_RGBA,  NULL, TRUE,9 },   // filter
1861    { TYPE_FLOAT, NULL, TRUE,10 },  // wireSize
1862    { TYPE_FLOAT, NULL, TRUE,11 },  // index of refraction
1863    { TYPE_FLOAT, NULL, TRUE,12 },  // bounce
1864    { TYPE_FLOAT, NULL, TRUE,13 },  // static friction
1865    { TYPE_FLOAT, NULL, TRUE,14 },  // sliding friction
1866    { TYPE_FLOAT, NULL, TRUE,15 },  // reflect dim level
1867    { TYPE_FLOAT, NULL, TRUE,16 },   // reflect dim multiplier
1868    { TYPE_FLOAT, NULL, TRUE,17 }   // soften
1869    };
1870 
1871 #define NUMOLDVER 9
1872 
1873 static ParamVersionDesc oldVersions[NUMOLDVER] = {
1874    ParamVersionDesc(stdmtlPB,8, 0),
1875    ParamVersionDesc(stdmtlPB,9, 1),
1876    ParamVersionDesc(stdmtlPB,9, 2),
1877    ParamVersionDesc(stdmtlPB,10,3),
1878    ParamVersionDesc(stdmtlPB,11,4),
1879    ParamVersionDesc(stdmtlPB,14,5),
1880    ParamVersionDesc(stdmtlPB,15,6),
1881    ParamVersionDesc(stdmtlPB,15,7),
1882    ParamVersionDesc(stdmtlPB,16,8)
1883    };
1884 
1885 static ParamVersionDesc curVersion(stdmtlPB,NPARAMS,STDMTL_PBVERSION);
1886 
Reset()1887 void StdMtl::Reset() {
1888    SuspendSetKeyMode();
1889 // shading = SHADE_PHONG;
1890    SetShadingNoNotify(SHADE_BLINN);
1891    flags = STDMTL_FILT_TRANSP|STDMTL_LOCK_ADTEX|STDMTL_SOFTEN;
1892    dimReflect = FALSE;
1893    ReplaceReference( 0, CreateParameterBlock( stdmtlPB, NPARAMS, STDMTL_PBVERSION ) );
1894    ReplaceReference( 1, new Texmaps((MtlBase*)this));
1895    ivalid.SetEmpty();
1896    SetDimIntens(0.0f,0);
1897    SetDimMult(3.0f,0);
1898    SetSoftenLevel(0.1f,0);
1899    SetAmbient(Color(0.1f,0.1f,0.1f),0);
1900    SetDiffuse(Color(0.5f,0.5f,0.5f),0);
1901    SetSpecular(Color(0.9f,0.9f,0.9f),0);
1902    SetOpacity(1.0f,0);
1903    SetFilter(Color(.5f,.5f,.5f),0);
1904    SetShininess(.25f,0);   // change from .4, 5-21-97
1905    SetShinStr(.05f,0);      // change from .3, 5-21-97
1906 // >>>>
1907    SetSelfIllum(.0f,0);
1908    SetOpacFalloff(0.0f,0);
1909    SetWireSize(1.0f,0);
1910    SetIOR(1.5f,0);
1911    SetTexmapAmt(ID_BU, BUMP_DEF_AMT, 0);
1912    SetDynamicsProperty(0,0,DYN_BOUNCE,1.0f);
1913    SetDynamicsProperty(0,0,DYN_STATIC_FRICTION,0.0f);
1914    SetDynamicsProperty(0,0,DYN_SLIDING_FRICTION,0.0f);
1915    ResumeSetKeyMode();
1916    }
1917 
StdMtl(BOOL loading)1918 StdMtl::StdMtl(BOOL loading) {
1919    paramDlg = NULL;
1920    pblock = NULL;
1921    maps = NULL;
1922    ambient = diffuse = specular = filter = Color(0.0f,0.0f,0.0f);
1923    SetShadingNoNotify(SHADE_PHONG);
1924    flags = STDMTL_FILT_TRANSP|STDMTL_LOCK_ADTEX|STDMTL_SOFTEN;
1925    dimReflect = FALSE;
1926    dimIntens = 0.0f;
1927    dimMult = 2.0f;
1928    ivalid.SetEmpty();
1929    if (!loading)
1930       Reset();
1931    rollScroll = 0;
1932    flags |= STDMTL_ROLLUP1_OPEN;
1933    }
1934 
Clone(RemapDir & remap)1935 RefTargetHandle StdMtl::Clone(RemapDir &remap) {
1936    //DebugPrint(" Cloning STDMTL %d \n",++numStdMtls);
1937    StdMtl *mnew = new StdMtl();
1938    *((MtlBase*)mnew) = *((MtlBase*)this);  // copy superclass stuff
1939    mnew->ReplaceReference(0,remap.CloneRef(pblock));
1940    mnew->ReplaceReference(1,remap.CloneRef(maps));
1941    mnew->ivalid.SetEmpty();
1942    mnew->flags = flags;
1943    mnew->ambient = ambient;
1944    mnew->diffuse = diffuse;
1945    mnew->specular = specular;
1946    mnew->filter = filter;
1947    mnew->shininess = shininess;
1948    mnew->phongexp = phongexp;
1949    mnew->shine_str = shine_str;
1950    mnew->self_illum = self_illum;
1951    mnew->opacity = opacity;
1952    mnew->opfall = opfall;
1953    mnew->wireSize = wireSize;
1954    mnew->ioRefract = ioRefract;
1955    mnew->dimReflect = dimReflect;
1956    mnew->softThresh = softThresh;
1957    mnew->SetShadingNoNotify(shading);
1958    BaseClone(this, mnew, remap);
1959    return (RefTargetHandle)mnew;
1960    }
1961 
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)1962 ParamDlg* StdMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp) {
1963    Interval v;
1964    Update(imp->GetTime(),v);
1965    StdMtlDlg *dm = new StdMtlDlg(hwMtlEdit, imp, this);
1966    LoadStdMtlResources();
1967    dm->BuildDialog();
1968    dm->LoadDialog(FALSE);
1969    SetParamDlg(dm);
1970    return dm;
1971    }
1972 
1973 #define LIMIT0_1(x) if (x<0.0f) x = 0.0f; else if (x>1.0f) x = 1.0f;
1974 #define LIMITMINMAX(x,min,max) if (x<min) x = min; else if (x>max) x = max;
1975 
LimitColor(Color c)1976 static Color LimitColor(Color c) {
1977    LIMIT0_1(c.r);
1978    LIMIT0_1(c.g);
1979    LIMIT0_1(c.b);
1980    return c;
1981    }
1982 
Update(TimeValue t,Interval & valid)1983 void StdMtl::Update(TimeValue t, Interval &valid) {
1984    Point3 p;
1985    if (!ivalid.InInterval(t)) {
1986       ivalid.SetInfinite();
1987       pblock->GetValue( PB_AMBIENT, t, p, ivalid );
1988       ambient = LimitColor(Color(p.x,p.y,p.z));
1989       pblock->GetValue( PB_DIFFUSE, t, p, ivalid );
1990       diffuse= LimitColor(Color(p.x,p.y,p.z));
1991       pblock->GetValue( PB_SPECULAR, t, p, ivalid );
1992       specular = LimitColor(Color(p.x,p.y,p.z));
1993       pblock->GetValue( PB_FILTER, t, p, ivalid );
1994       filter = LimitColor(Color(p.x,p.y,p.z));
1995       pblock->GetValue( PB_SHININESS, t, shininess, ivalid );
1996       pblock->GetValue( PB_SHIN_STR, t, shine_str, ivalid );
1997       // >>>>>
1998       pblock->GetValue( PB_SELFI, t, self_illum, ivalid );
1999       pblock->GetValue( PB_OPAC, t, opacity, ivalid );
2000 
2001       pblock->GetValue( PB_OPFALL, t, opfall, ivalid );
2002       pblock->GetValue( PB_WIRESZ, t, wireSize, ivalid );
2003       pblock->GetValue( PB_IOR, t, ioRefract, ivalid );
2004       pblock->GetValue( PB_DIMLEV, t, dimIntens, ivalid );
2005       pblock->GetValue( PB_DIMMULT, t, dimMult, ivalid );
2006       pblock->GetValue( PB_SOFTEN, t, softThresh, ivalid);
2007 
2008       LIMIT0_1(opacity);
2009       LIMIT0_1(self_illum);
2010       LIMIT0_1(shininess);
2011       LIMITMINMAX(shine_str,0.0f,9.99f);
2012       LIMIT0_1(opfall);
2013       LIMIT0_1(dimIntens);
2014       LIMIT0_1(softThresh);
2015 
2016       phongexp = (float)pow(2.0,shininess*10.0);
2017 
2018       for (int i=0; i<NTEXMAPS; i++)   {
2019          if (MAPACTIVE(i))
2020             maps->txmap[i].Update(t,ivalid);
2021          }
2022       }
2023    valid &= ivalid;
2024    }
2025 
2026 //-----------------------------------------------------------------------
2027 // DS - 4/7/97: Changed Opacity, Self-illumination, SHininess, Shininess strengh
2028 // so that the map amount blends between the corresponding slider
2029 // setting and the map value.  This code fixes up old files so they
2030 // will render the same way. This does not correctly handle animated values
2031 // for the amount or parameter sliders.
2032 //-----------------------------------------------------------------------
2033 
OldVerFix(int loadVer)2034 void StdMtl::OldVerFix(int loadVer) {
2035    if (loadVer<8) {
2036       Interval v;
2037       Update(0,v);
2038       if (MAPACTIVE(ID_OP)) {
2039          if (maps->txmap[ID_OP].amount != 1.0f)
2040             SetOpacity(0.0f,0);
2041          }
2042       if (MAPACTIVE(ID_SI)) {
2043          if (maps->txmap[ID_SI].amount != 1.0f)
2044             // >>>>>
2045             SetSelfIllum(0.0f,0);
2046          }
2047       if (MAPACTIVE(ID_SS)) {
2048          float amt = maps->txmap[ID_SS].amount;
2049          SetTexmapAmt(ID_SS,amt*shine_str,0);
2050          SetShinStr(0.0f,0);
2051          }
2052       if (MAPACTIVE(ID_SH)) {
2053          float amt = maps->txmap[ID_SH].amount;
2054          SetTexmapAmt(ID_SH,amt*shininess,0);
2055          SetShininess(0.0f,0);
2056          }
2057       }
2058    if (loadVer<9) {
2059       if (flags&STDMTL_SOFTEN)
2060          SetSoftenLevel(.6f,0);
2061       else
2062          SetSoftenLevel(0.0f,0);
2063       }
2064    }
2065 
2066 
2067 
Requirements(int subMtlNum)2068 ULONG StdMtl::Requirements(int subMtlNum) {
2069    ULONG req = 0;
2070 
2071    switch (shading) {
2072       case SHADE_CONST:
2073          req |= MTLREQ_DONTMERGE_FRAGMENTS;
2074          break;
2075       case SHADE_PHONG:
2076       case SHADE_BLINN:
2077       case SHADE_METAL: req |= MTLREQ_PHONG; break;
2078       }
2079 
2080    if (opacity!=1.0f||MAPACTIVE(ID_OP)||opfall>0.0f)
2081       req |= MTLREQ_TRANSP;
2082 
2083    if (opacity!=1.0f)
2084       req |= MTLREQ_TRANSP_IN_VP;
2085 
2086    for (int i=0; i<NTEXMAPS; i++) {
2087       if (MAPACTIVE(i))
2088          req |= (*maps)[i].map->Requirements(subMtlNum);
2089       }
2090    if (MAPACTIVE(ID_BU)) {
2091       ULONG bmpreq = (*maps)[ID_BU].map->Requirements(subMtlNum);
2092       if (bmpreq&MTLREQ_UV)
2093          req |= MTLREQ_BUMPUV;
2094       if (bmpreq&MTLREQ_UV2)
2095          req |= MTLREQ_BUMPUV2;
2096       }
2097    if (flags&STDMTL_WIRE)  req|= MTLREQ_WIRE;
2098    if (flags&STDMTL_2SIDE) req|= MTLREQ_2SIDE;
2099    if (flags&STDMTL_SSAMP) req|= MTLREQ_SUPERSAMPLE;
2100    if (flags&STDMTL_WIRE_UNITS) req|= MTLREQ_WIRE_ABS;
2101    if (flags&STDMTL_FACEMAP) req |= MTLREQ_FACEMAP;
2102    if (flags&STDMTL_ADD_TRANSP) req |= MTLREQ_ADDITIVE_TRANSP;
2103    if (MAPACTIVE(ID_DP)) req |= MTLREQ_DISPLACEMAP;
2104    return req;
2105    }
2106 
Validity(TimeValue t)2107 Interval StdMtl::Validity(TimeValue t) {
2108    Interval v;
2109    Update(t,v);
2110    return ivalid;
2111    }
2112 
NotifyChanged()2113 void StdMtl::NotifyChanged() {
2114    NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
2115    }
2116 
SetFlag(ULONG f,ULONG val)2117 void StdMtl::SetFlag(ULONG f, ULONG val) {
2118    if (val) flags|=f;
2119    else flags &= ~f;
2120    }
2121 
SetTransparencyType(int type)2122 void StdMtl::SetTransparencyType(int type) {
2123    switch (type) {
2124       case TRANSP_SUBTRACTIVE:
2125          SetFlag(STDMTL_ADD_TRANSP,0);
2126          SetFlag(STDMTL_FILT_TRANSP,0);
2127          break;
2128       case TRANSP_ADDITIVE:
2129          SetFlag(STDMTL_ADD_TRANSP,1);
2130          SetFlag(STDMTL_FILT_TRANSP,0);
2131          break;
2132       case TRANSP_FILTER:
2133          SetFlag(STDMTL_ADD_TRANSP,0);
2134          SetFlag(STDMTL_FILT_TRANSP,1);
2135          break;
2136       }
2137    }
2138 
DeleteThis()2139 void StdMtl::DeleteThis() {
2140    //DebugPrint(" Deleting STDMTL %d \n",numStdMtls--);
2141     delete this;
2142    }
2143 
SubAnimName(int i)2144 TSTR StdMtl::SubAnimName(int i) {
2145    return TSTR(GetString(i==0?IDS_DS_PARAMETERS:IDS_DS_TEXMAPS));
2146    }
2147 
SubAnim(int i)2148 Animatable* StdMtl::SubAnim(int i) {
2149    switch(i) {
2150       case 0: return pblock;
2151       case 1: return maps;
2152       default: assert(0); return NULL;
2153       }
2154     }
2155 
GetReference(int i)2156 RefTargetHandle StdMtl::GetReference(int i) {
2157    switch(i) {
2158       case 0: return pblock;
2159       case 1: return maps;
2160       default: assert(0);   return NULL;
2161       }
2162    }
2163 
SetReference(int i,RefTargetHandle rtarg)2164 void StdMtl::SetReference(int i, RefTargetHandle rtarg) {
2165    switch(i) {
2166       case 0:  pblock = (IParamBlock*)rtarg; return;
2167       case 1:  {
2168          maps = (Texmaps*)rtarg;
2169          if (maps!=NULL)
2170             maps->client = this;
2171          return;
2172          }
2173       default: assert(0);
2174       }
2175    }
2176 
SetSubTexmap(int i,Texmap * m)2177 void StdMtl::SetSubTexmap(int i, Texmap *m) {
2178    assert(i<NTEXMAPS);
2179    maps->ReplaceReference(2*i+1,m);
2180    if (m!=NULL) {
2181       EnableMap(i,TRUE);
2182       if (maps->txmap[i].amtCtrl==NULL) {
2183          maps->ReplaceReference(2*i, NewDefaultFloatController());
2184          maps->txmap[i].amtCtrl->SetValue(TimeValue(0),&maps->txmap[i].amount);
2185          }
2186       }
2187    else {
2188       if (maps->txmap[i].amtCtrl!=NULL)
2189          maps->DeleteReference(2*i);
2190       SetTexmapAmt(i, i==ID_BU?BUMP_DEF_AMT:1.0f,TimeValue(0));
2191       EnableMap(i,FALSE);
2192       }
2193    if (m&&(i==ID_RL||i==ID_RR)) {
2194       UVGen* uvg0 = m->GetTheUVGen();
2195       if (uvg0&&uvg0->IsStdUVGen()) {
2196          StdUVGen *uvg = (StdUVGen*)uvg0;
2197          uvg->InitSlotType(MAPSLOT_ENVIRON);
2198          uvg->SetCoordMapping(UVMAP_SPHERE_ENV);
2199          }
2200       }
2201    if (paramDlg)
2202       paramDlg->UpdateTexmapDisplay(i);
2203    }
2204 
2205 static int nameID[NPARAMS] = {
2206    IDS_DS_AMBIENT, IDS_DS_DIFFUSE, IDS_DS_SPECULAR,  IDS_DS_SHININESS,IDS_DS_SHIN_STR,
2207    IDS_DS_SELFI,IDS_DS_OPACITY,IDS_DS_XPFALL,IDS_DS_FILTER,IDS_DS_WIRESZ,
2208     IDS_DS_IOR,IDS_DS_BOUNCE,IDS_DS_STATFRIC,IDS_DS_SLIDFRIC,IDS_DS_DIMLEV,IDS_DS_DIMMULT,
2209     IDS_DS_SOFTEN};
2210 
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)2211 RefResult StdMtl::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
2212    PartID& partID, RefMessage message ) {
2213    switch (message) {
2214       case REFMSG_WANT_SHOWPARAMLEVEL:
2215          {
2216          BOOL *pb = (BOOL *)(partID);
2217          *pb = TRUE;
2218          return REF_STOP;
2219          }
2220       case REFMSG_CHANGE:
2221          ivalid.SetEmpty();
2222          if (paramDlg) {
2223             if (hTarget==pblock) {
2224                int np =pblock->LastNotifyParamNum();
2225                paramDlg->UpdateControlFor(np);
2226                }
2227             else// if (!paramDlg->isActive)
2228                paramDlg->Invalidate();
2229             }
2230          break;
2231       case REFMSG_GET_PARAM_DIM: {
2232          GetParamDim *gpd = (GetParamDim*)partID;
2233          switch (gpd->index) {
2234             case PB_AMBIENT:
2235             case PB_DIFFUSE:
2236             case PB_SPECULAR:
2237             case PB_FILTER:
2238                gpd->dim = stdColor255Dim;
2239                break;
2240             case PB_BOUNCE:
2241             case PB_STATFRIC:
2242             case PB_SLIDFRIC:
2243             case PB_DIMLEV:
2244             case PB_DIMMULT:
2245             case PB_SOFTEN:
2246             case PB_WIRESZ:
2247             case PB_IOR:
2248                gpd->dim = defaultDim;
2249                break;
2250             case PB_SHININESS:
2251             case PB_SHIN_STR:
2252             case PB_SELFI:
2253             case PB_OPAC:
2254             case PB_OPFALL:
2255             default:
2256                gpd->dim = stdPercentDim;
2257                break;
2258             }
2259          return REF_STOP;
2260          }
2261 
2262       case REFMSG_GET_PARAM_NAME: {
2263          GetParamName *gpn = (GetParamName*)partID;
2264          gpn->name =  GetString(nameID[gpn->index]);
2265          return REF_STOP;
2266          }
2267       }
2268    return(REF_SUCCEED);
2269    }
2270 
ClassID()2271 Class_ID StdMtl::ClassID() {
2272    return stdmtlClassID;
2273    }
2274 
GetSubTexmapSlotName(int i)2275 TSTR StdMtl::GetSubTexmapSlotName(int i) {
2276    return GetString(texNameID[i]);
2277    }
2278 
2279 
EnableMap(int i,BOOL onoff)2280 void StdMtl::EnableMap(int i, BOOL onoff) {
2281    maps->txmap[i].mapOn = onoff;
2282    NotifyChanged();
2283    }
2284 
2285 // forward
2286 SShader *GetShaderFromId(int s);
2287 
SetShadingNoNotify(int s)2288 void StdMtl::SetShadingNoNotify( int s) {
2289    shading = s;
2290    curShader = GetShaderFromId(shading);
2291    }
2292 
SetShaderId(long s)2293 void StdMtl::SetShaderId( long s) {
2294    long old = shading;
2295    SetShadingNoNotify(s);
2296    if (old!=shading) {
2297       NotifyChanged();
2298       if (paramDlg) {
2299          paramDlg->UpdateHilite();
2300          paramDlg->EnablePhongStuff();
2301          }
2302       }
2303    }
2304 
SetAmbient(Color c,TimeValue t)2305 void StdMtl::SetAmbient(Color c, TimeValue t) {
2306    ambient =c;
2307    pblock->SetValue( PB_AMBIENT, t, Point3(c.r,c.g,c.b));
2308    NotifyChanged();
2309    }
2310 
SetDiffuse(Color c,TimeValue t)2311 void StdMtl::SetDiffuse(Color c, TimeValue t) {
2312    Point3 p;
2313    Interval iv;
2314    pblock->SetValue( PB_DIFFUSE, t, Point3(c.r,c.g,c.b));
2315    pblock->GetValue( PB_DIFFUSE, t, p, ivalid );
2316    diffuse= LimitColor(Color(p.x,p.y,p.z));
2317    NotifyChanged();
2318    }
2319 
SetSpecular(Color c,TimeValue t)2320 void StdMtl::SetSpecular(Color c, TimeValue t) {
2321     specular =c;
2322    pblock->SetValue( PB_SPECULAR, t, Point3(c.r,c.g,c.b));
2323    NotifyChanged();
2324    }
2325 
SetFilter(Color c,TimeValue t)2326 void StdMtl::SetFilter(Color c, TimeValue t) {
2327     filter =c;
2328    pblock->SetValue( PB_FILTER, t, Point3(c.r,c.g,c.b));
2329    if (opacity!=1.0f||MAPACTIVE(ID_OP))
2330       NotifyChanged();
2331    }
2332 
SetShininess(float v,TimeValue t)2333 void StdMtl::SetShininess(float v, TimeValue t) {
2334    shininess =v;
2335    phongexp = (float)pow(2.0,shininess*10.0);
2336    pblock->SetValue( PB_SHININESS, t, v);
2337    NotifyChanged();
2338    }
2339 
SetShinStr(float v,TimeValue t)2340 void StdMtl::SetShinStr(float v, TimeValue t) {
2341    shine_str =v;
2342    pblock->SetValue( PB_SHIN_STR, t, v);
2343    NotifyChanged();
2344    }
2345 
2346 // >>>>
SetSelfIllum(float v,TimeValue t)2347 void StdMtl::SetSelfIllum(float v, TimeValue t) {
2348    self_illum =v;
2349    pblock->SetValue( PB_SELFI, t, v);
2350    NotifyChanged();
2351    }
2352 
SetOpacity(float v,TimeValue t)2353 void StdMtl::SetOpacity(float v, TimeValue t) {
2354     opacity = v;
2355    pblock->SetValue( PB_OPAC, t, v);
2356    NotifyChanged();
2357    }
2358 
SetOpacFalloff(float v,TimeValue t)2359 void StdMtl::SetOpacFalloff(float v, TimeValue t) {
2360    opfall = v;
2361    pblock->SetValue( PB_OPFALL, t, v);
2362    if (opacity!=1.0f||MAPACTIVE(ID_OP))
2363       NotifyChanged();
2364    }
2365 
SetWireSize(float v,TimeValue t)2366 void StdMtl::SetWireSize(float v, TimeValue t) {
2367    wireSize = v;
2368    pblock->SetValue( PB_WIRESZ, t, v);
2369    if (flags&STDMTL_WIRE)
2370       NotifyChanged();
2371    }
2372 
SetIOR(float v,TimeValue t)2373 void StdMtl::SetIOR(float v, TimeValue t) {
2374    ioRefract = v;
2375    pblock->SetValue( PB_IOR, t, v);
2376    NotifyChanged();
2377    }
2378 
SetDimIntens(float v,TimeValue t)2379 void StdMtl::SetDimIntens(float v, TimeValue t) {
2380    dimIntens = v;
2381    pblock->SetValue( PB_DIMLEV, t, v);
2382    NotifyChanged();
2383    }
2384 
SetDimMult(float v,TimeValue t)2385 void StdMtl::SetDimMult(float v, TimeValue t) {
2386    dimMult = v;
2387    pblock->SetValue( PB_DIMMULT, t, v);
2388    NotifyChanged();
2389    }
2390 
SetSoftenLevel(float v,TimeValue t)2391 void StdMtl::SetSoftenLevel(float v, TimeValue t) {
2392    softThresh = v;
2393    pblock->SetValue( PB_SOFTEN, t, v);
2394    NotifyChanged();
2395    }
2396 
SetTexmapAmt(int imap,float amt,TimeValue t)2397 void StdMtl::SetTexmapAmt(int imap, float amt, TimeValue t) {
2398    if (maps->txmap[imap].amtCtrl)
2399       maps->txmap[imap].amtCtrl->SetValue(t,&amt);
2400    maps->txmap[imap].amount = amt;
2401    if (maps->txmap[imap].IsActive())
2402       NotifyChanged();
2403    }
2404 
AmtKeyAtTime(int i,TimeValue t)2405 BOOL StdMtl::AmtKeyAtTime(int i, TimeValue t) {
2406    if (maps->txmap[i].amtCtrl)
2407       return   maps->txmap[i].amtCtrl->IsKeyAtTime(t,0);
2408    else
2409       return FALSE;
2410    }
2411 
GetShaderId()2412 long StdMtl::GetShaderId() {
2413    return shading;
2414    }
2415 
UpdateShader()2416 void StdMtl::UpdateShader() {
2417    curShader->SetShininess(shininess,shine_str);
2418    }
2419 
GetAmbient(int mtlNum,BOOL backFace)2420 Color StdMtl::GetAmbient(int mtlNum, BOOL backFace) {   return ambient;}
GetDiffuse(int mtlNum,BOOL backFace)2421 Color StdMtl::GetDiffuse(int mtlNum, BOOL backFace) { return diffuse;}
GetSpecular(int mtlNum,BOOL backFace)2422 Color StdMtl::GetSpecular(int mtlNum, BOOL backFace) {   return specular;  }
GetFilter()2423 Color StdMtl::GetFilter() {   return filter; }
2424 
GetTexmapAmt(int imap)2425 float StdMtl::GetTexmapAmt(int imap) { return maps->txmap[imap].amount; }
2426 
GetTexmapAmt(int imap,TimeValue t)2427 float StdMtl::GetTexmapAmt(int imap, TimeValue t) {   return maps->txmap[imap].GetAmount(t);    }
2428 
2429 
GetAmbient(TimeValue t)2430 Color StdMtl::GetAmbient(TimeValue t)  { return pblock->GetColor(PB_AMBIENT,t);}
GetDiffuse(TimeValue t)2431 Color StdMtl::GetDiffuse(TimeValue t)  { return pblock->GetColor(PB_DIFFUSE,t);  }
GetSpecular(TimeValue t)2432 Color StdMtl::GetSpecular(TimeValue t) { return pblock->GetColor(PB_SPECULAR,t); }
GetFilter(TimeValue t)2433 Color StdMtl::GetFilter(TimeValue t)   { return pblock->GetColor(PB_FILTER,t);   }
GetShininess(TimeValue t)2434 float StdMtl::GetShininess( TimeValue t) {return pblock->GetFloat(PB_SHININESS,t);  }
GetShinStr(TimeValue t)2435 float StdMtl::GetShinStr(TimeValue t)  { return  pblock->GetFloat(PB_SHIN_STR,t);   }
2436 // >>>>
GetSelfIllum(TimeValue t)2437 float StdMtl::GetSelfIllum(TimeValue t){ return  pblock->GetFloat(PB_SELFI,t);   }
GetOpacity(TimeValue t)2438 float StdMtl::GetOpacity( TimeValue t) { return  pblock->GetFloat(PB_OPAC,t); }
GetOpacFalloff(TimeValue t)2439 float StdMtl::GetOpacFalloff(TimeValue t){ return  pblock->GetFloat(PB_OPFALL,t);}
GetWireSize(TimeValue t)2440 float StdMtl::GetWireSize(TimeValue t) { return  pblock->GetFloat(PB_WIRESZ,t);}
GetIOR(TimeValue t)2441 float StdMtl::GetIOR( TimeValue t)     { return  pblock->GetFloat(PB_IOR,t);}
GetDimIntens(TimeValue t)2442 float StdMtl::GetDimIntens( TimeValue t)   { return  pblock->GetFloat(PB_DIMLEV,t); }
GetDimMult(TimeValue t)2443 float StdMtl::GetDimMult( TimeValue t)   { return  pblock->GetFloat(PB_DIMMULT,t); }
GetSoftenLevel(TimeValue t)2444 float StdMtl::GetSoftenLevel( TimeValue t)   { return  pblock->GetFloat(PB_SOFTEN,t); }
MapEnabled(int i)2445 BOOL StdMtl::MapEnabled(int i)         { return maps->txmap[i].mapOn;}
2446 
2447 
GetDynamicsProperty(TimeValue t,int mtlNum,int propID)2448 float StdMtl::GetDynamicsProperty(TimeValue t, int mtlNum, int propID) {
2449    float val;
2450    Interval ivalid;
2451    switch(propID) {
2452       case DYN_BOUNCE:
2453          pblock->GetValue(PB_BOUNCE,t,val,ivalid);
2454          return val;
2455       case DYN_STATIC_FRICTION:
2456          pblock->GetValue(PB_STATFRIC,t,val,ivalid);
2457          return val;
2458       case DYN_SLIDING_FRICTION:
2459          pblock->GetValue(PB_SLIDFRIC,t,val,ivalid);
2460          return val;
2461       default:
2462          assert(0);
2463          return 0.0f;
2464       }
2465    }
2466 
SetDynamicsProperty(TimeValue t,int mtlNum,int propID,float value)2467 void StdMtl::SetDynamicsProperty(TimeValue t, int mtlNum, int propID, float value){
2468    switch(propID) {
2469       case DYN_BOUNCE:
2470          pblock->SetValue( PB_BOUNCE, t, value);
2471          break;
2472       case DYN_STATIC_FRICTION:
2473          pblock->SetValue( PB_STATFRIC, t, value);
2474          break;
2475       case DYN_SLIDING_FRICTION:
2476          pblock->SetValue( PB_SLIDFRIC, t, value);
2477          break;
2478       default:
2479          assert(0);
2480          break;
2481       }
2482    }
2483 
2484 #define MTL_HDR_CHUNK 0x4000
2485 #define STDMTL_FLAGS_CHUNK 0x5000
2486 #define STDMTL_SHADING_CHUNK 0x5004
2487 #define STDMTL_TEX_ONOFF_CHUNK 0x5002
2488 #define STDMTL_TEX_AMT0 0x5100
2489 #define STDMTL_TEX_AMT1 0x5101
2490 #define STDMTL_TEX_AMT2 0x5102
2491 #define STDMTL_TEX_AMT3 0x5103
2492 #define STDMTL_TEX_AMT4 0x5104
2493 #define STDMTL_TEX_AMT5 0x5105
2494 #define STDMTL_TEX_AMT6 0x5106
2495 #define STDMTL_TEX_AMT7 0x5107
2496 #define STDMTL_TEX_AMT8 0x5108
2497 #define STDMTL_TEX_AMT9 0x5109
2498 #define STDMTL_TEX_AMTA 0x510A
2499 
2500 //#define STDMTL_BUMP1_CHUNK 0x5200
2501 #define STDMTL_VERS_CHUNK 0x5300
2502 #define STDMTL_DIM_REFLECT 0x5400
2503 
2504 #define STDMTL_VERSION  9
2505 
2506 // IO
Save(ISave * isave)2507 IOResult StdMtl::Save(ISave *isave) {
2508    ULONG nb;
2509    IOResult res;
2510    isave->BeginChunk(MTL_HDR_CHUNK);
2511    res = MtlBase::Save(isave);
2512    if (res!=IO_OK) return res;
2513    isave->EndChunk();
2514 
2515    isave->BeginChunk(STDMTL_FLAGS_CHUNK);
2516    isave->Write(&flags,sizeof(flags),&nb);
2517    isave->EndChunk();
2518 
2519    isave->BeginChunk(STDMTL_SHADING_CHUNK);
2520    isave->Write(&shading,sizeof(shading),&nb);
2521    isave->EndChunk();
2522 
2523    isave->BeginChunk(STDMTL_VERS_CHUNK);
2524    int version = STDMTL_VERSION;
2525    isave->Write(&version,sizeof(version),&nb);
2526    isave->EndChunk();
2527 
2528    if (dimReflect) {
2529       isave->BeginChunk(STDMTL_DIM_REFLECT);
2530       isave->EndChunk();
2531       }
2532    return IO_OK;
2533    }
2534 
2535 class StdMtlCB: public PostLoadCallback {
2536    public:
2537       StdMtl *m;
2538       int loadVersion;
StdMtlCB(StdMtl * s,int loadVers)2539        StdMtlCB(StdMtl *s, int loadVers) { m = s; loadVersion = loadVers; }
proc(ILoad * iload)2540       void proc(ILoad *iload) {
2541          m->OldVerFix(loadVersion);
2542          delete this;
2543          }
2544    };
2545 
2546 
Load(ILoad * iload)2547 IOResult StdMtl::Load(ILoad *iload) {
2548    ULONG nb;
2549    int id;
2550    int version = 0;
2551    IOResult res;
2552 // .......... use this???
2553    iload->RegisterPostLoadCallback(new ParamBlockPLCB(oldVersions,NUMOLDVER, &curVersion, this,0));
2554    while (IO_OK==(res=iload->OpenChunk())) {
2555       switch(id = iload->CurChunkID())  {
2556          case MTL_HDR_CHUNK:
2557             res = MtlBase::Load(iload);
2558             ivalid.SetEmpty();
2559             break;
2560          case STDMTL_FLAGS_CHUNK:
2561             res = iload->Read(&flags,sizeof(flags), &nb);
2562             break;
2563          case STDMTL_SHADING_CHUNK:
2564             res = iload->Read(&shading,sizeof(shading), &nb);
2565             if (shading<0||shading>SHADE_BLINN) {
2566                shading = SHADE_PHONG;
2567                }
2568             SetShadingNoNotify(shading);
2569             break;
2570          case STDMTL_VERS_CHUNK:
2571             res = iload->Read(&version,sizeof(version), &nb);
2572             break;
2573          case STDMTL_TEX_ONOFF_CHUNK:
2574             {
2575             ULONG f;
2576             res = iload->Read(&f,sizeof(f), &nb);
2577             for (int i=0; i<NTEXMAPS; i++)
2578                 maps->txmap[i].mapOn = (f&(1<<i))?1:0;
2579             }
2580             break;
2581          case STDMTL_DIM_REFLECT:
2582             dimReflect = TRUE;
2583             break;
2584          }
2585       iload->CloseChunk();
2586       if (res!=IO_OK)
2587          return res;
2588       }
2589    if (version<9) {
2590       iload->RegisterPostLoadCallback(new StdMtlCB(this,version));
2591       iload->SetObsolete();
2592       }
2593 
2594    return IO_OK;
2595 
2596    }
2597 
2598 // Composite  c_over on top of c. Assume c_over has pre-multiplied
2599 // alpha.
AlphaCompCol(Color & c,RGBA c_over)2600 inline void AlphaCompCol(Color& c,  RGBA c_over) {
2601    float ia = 1.0f - c_over.a;
2602    c.r = c.r*ia + c_over.r;
2603    c.g = c.g*ia + c_over.g;
2604    c.b = c.b*ia + c_over.b;
2605    }
2606 
Intens(RGBA & c)2607 static inline float Intens(RGBA& c) {  return (c.r+c.g+c.b)/3.0f; }
2608 
2609 static Color blackCol(0.0f,0.0f,0.0f);
2610 static Color whiteCol(1.0f,1.0f,1.0f);
2611 
2612 
2613 #define MAX3(a,b,c) ((a)>(b)?((a)>(c)?(a):(c)):((b)>(c)?(b):(c)))
2614 
MaxRGB(Color c)2615 static inline float MaxRGB(Color c) {  return MAX3(c.r,c.g,c.b); }
2616 
TranspColor(ShadeContext & sc,float opac,Color & diff)2617 Color StdMtl::TranspColor(ShadeContext& sc, float opac, Color& diff) {
2618    // Compute the color of the transparent filter color
2619    if (flags&STDMTL_ADD_TRANSP) {
2620       float f = 1.0f - opac;
2621       return Color(f,f,f);   //XXX
2622       }
2623    else
2624       {
2625       // Transparent Filter color mapping
2626       if (flags&STDMTL_FILT_TRANSP) {
2627          Color filt = filter;
2628          if (MAPACTIVE(ID_FI))
2629             AlphaCompCol(filt,(*maps)[ID_FI].Eval(sc));
2630 #ifdef OLDFILTER
2631          if (opac>0.5f) {
2632             // lerp (filt --> black) as opac goes ( 0.5--> 1.0)
2633             float s= 2.0f*(opac-.5f);
2634             return (1.0f-s)*filt;
2635             }
2636          else {
2637             // lerp (white --> filt) as opac goes (0.0 --> .5 )
2638             float s = 2.0f*opac;
2639             return (1.0f-s) + filt*s;
2640             }
2641 #else
2642          if (opac>0.5f) {
2643             // darken as opac goes ( 0.5--> 1.0)
2644             // so that max component reaches 0.0f when opac reaches 1.0
2645             // find max component of filt
2646             float m = (filt.r>filt.g)?filt.r:filt.g;
2647             if(filt.b>m) m = filt.b;
2648             Color fc;
2649             float d = 2.0f*(opac-.5f)*m;
2650             fc = filt-d;
2651             if (fc.r<0.0f) fc.r = 0.0f;
2652             if (fc.g<0.0f) fc.g = 0.0f;
2653             if (fc.b<0.0f) fc.b = 0.0f;
2654             return fc;
2655             }
2656          else {
2657             // lighten as opac goes ( 0.5--> 0.0)
2658             // so that min component reaches 1.0f when opac reaches 1.0
2659             // find min component of filt
2660             float m = (filt.r<filt.g)?filt.r:filt.g;
2661             if(filt.b<m) m = filt.b;
2662             Color fc;
2663             float d = (1.0f-2.0f*opac)*(1.0f-m);
2664             fc = filt+d;
2665             if (fc.r>1.0f) fc.r = 1.0f;
2666             if (fc.g>1.0f) fc.g = 1.0f;
2667             if (fc.b>1.0f) fc.b = 1.0f;
2668             return fc;
2669             }
2670 #endif
2671          }
2672       else {
2673          Color f = (1.0f-diff);  // original 3DS transparency
2674          return  (1.0f-opac)*f;
2675          }
2676       }
2677    }
2678 
2679 
2680 
2681 //----------------------------------------------------------------------------------------
2682 //- Phong Shader  ------------------------------------------------------------------------
2683 //----------------------------------------------------------------------------------------
2684 
2685 
2686 class Phong: public SShader {
2687    float fs;
2688    float shin_str;
2689    public:
2690    void Illum(ShadeContext &sc, SIllumParams &ip);
AffectReflMap(ShadeContext & sc,SIllumParams & ip,Color & rcol)2691    void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.spec; };
SetShininess(float shininess,float shineStr)2692    void SetShininess(float shininess, float shineStr) {
2693       fs = (float)pow(2.0,shininess*10.0);
2694       shin_str = shineStr;
2695       }
EvalHilite(float x)2696    float EvalHilite(float x) {
2697       return shin_str*(float)pow((double)cos(x*PI),(double)fs);
2698       }
2699    };
2700 
whoa()2701 static void whoa(){}
2702 
Illum(ShadeContext & sc,SIllumParams & ip)2703 void Phong::Illum(ShadeContext &sc, SIllumParams &ip) {
2704    LightDesc *l;
2705    Color lightCol;
2706    BOOL is_shiny;
2707    Point3 R;
2708    if (is_shiny=(ip.sh_str>0.0f))
2709     R = sc.ReflectVector();
2710 
2711 // IPoint2 sp = sc.ScreenCoord();
2712 // if (sp.x==260&&sp.y==180)
2713 //    whoa();
2714    for (int i=0; i<sc.nLights; i++) {
2715       l = sc.Light(i);
2716       register float NL, diffCoef;
2717       Point3 L;
2718       if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) {
2719          if (l->ambientOnly) {
2720             ip.ambIllum += lightCol;
2721             continue;
2722             }
2723          if (NL<=0.0f)
2724             continue;
2725          // diffuse
2726          if (l->affectDiffuse)
2727             ip.diffIllum += diffCoef*lightCol;
2728          if (is_shiny&&l->affectSpecular) {
2729             // specular (Phong)
2730             float c = DotProd(L,R);
2731             if (c>0.0f) {
2732                if (ip.softThresh!=0.0&&diffCoef<ip.softThresh) {
2733                   float r = diffCoef/ip.softThresh;
2734                   c *= Soften(r);
2735                   }
2736                c = (float)pow((double)c, (double)ip.ph_exp); // could use table lookup for speed
2737                ip.specIllum += c*ip.sh_str*lightCol;
2738                }
2739             }
2740          }
2741       }
2742    ip.specIllum *= ip.spec;
2743    }
2744 
2745 
2746 //----------------------------------------------------------------------------------------
2747 //- Blinn Shader  ------------------------------------------------------------------------
2748 //----------------------------------------------------------------------------------------
2749 
2750 class Blinn: public SShader {
2751    float fs;
2752    float shin_str;
2753    public:
2754    void Illum(ShadeContext &sc, SIllumParams &ip);
AffectReflMap(ShadeContext & sc,SIllumParams & ip,Color & rcol)2755    void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.spec; };
SetShininess(float shininess,float shineStr)2756    void SetShininess(float shininess, float shineStr) {
2757       fs = (float)pow(2.0,shininess*10.0);
2758       shin_str = shineStr;
2759       }
EvalHilite(float x)2760    float EvalHilite(float x) {
2761       return shin_str*(float)pow((double)cos(x*PI),(double)fs);
2762       }
2763    };
2764 
2765 
Illum(ShadeContext & sc,SIllumParams & ip)2766 void Blinn::Illum(ShadeContext &sc, SIllumParams &ip) {
2767    LightDesc *l;
2768    Color lightCol;
2769 
2770    // Blinn style phong
2771    BOOL is_shiny=(ip.sh_str>0.0f)?1:0;
2772    double ph_exp = double(ip.ph_exp)*4.0; // This is to make the hilite compatible with normal phong
2773    for (int i=0; i<sc.nLights; i++) {
2774       l = sc.Light(i);
2775       register float NL, diffCoef;
2776       Point3 L;
2777       if (l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef)) {
2778          if (l->ambientOnly) {
2779             ip.ambIllum += lightCol;
2780             continue;
2781             }
2782          if (NL<=0.0f)
2783             continue;
2784 
2785          // diffuse
2786          if (l->affectDiffuse)
2787             ip.diffIllum += diffCoef*lightCol;
2788 
2789          // specular (Phong)
2790          if (is_shiny&&l->affectSpecular) {
2791             Point3 H = FNormalize(L-ip.V);
2792             float c = DotProd(ip.N,H);
2793             if (c>0.0f) {
2794                if (ip.softThresh!=0.0&&diffCoef<ip.softThresh) {
2795                   c *= Soften(diffCoef/ip.softThresh);
2796                   }
2797                c = (float)pow((double)c, ph_exp); // could use table lookup for speed
2798                ip.specIllum += c*ip.sh_str*lightCol;
2799                }
2800             }
2801          }
2802       }
2803    ip.specIllum *= ip.spec;
2804    }
2805 
2806 //----------------------------------------------------------------------------------------
2807 //- Metal Shader  ------------------------------------------------------------------------
2808 //----------------------------------------------------------------------------------------
2809 
2810 class Metal: public SShader {
2811    float fm2inv, fshin_str;
2812    public:
2813    void Illum(ShadeContext &sc, SIllumParams &ip);
AffectReflMap(ShadeContext & sc,SIllumParams & ip,Color & rcol)2814    void AffectReflMap(ShadeContext &sc, SIllumParams &ip, Color &rcol) { rcol *= ip.diff; };
2815    void SetShininess(float shininess, float shineStr);
2816    float EvalHilite(float x);
2817    };
2818 
CompK(float f0)2819 float CompK(float f0) {
2820    return float(2.0*sqrt(f0)/sqrt(1.0-f0));
2821    }
2822 
fres_metal(float c,float k)2823 float fres_metal(float c, float k) {
2824    float b,rpl,rpp,c2;
2825    b = k*k + 1.0f;
2826    c2 = c*c;
2827    rpl = (b*c2-2*c+1)/(b*c2+2*c+1);
2828    rpp = (b-2*c+c2)/(b+2*c+c2);
2829    return(.5f*(rpl+rpp));
2830    }
2831 
Illum(ShadeContext & sc,SIllumParams & ip)2832 void Metal::Illum(ShadeContext &sc, SIllumParams &ip) {
2833    LightDesc *l;
2834    Color lightCol;
2835    BOOL gotKav = FALSE;
2836    float kav, fav0, m2inv,NV;
2837 
2838    //IPoint2 sp = sc.ScreenCoord();
2839 
2840    BOOL is_shiny;
2841    if (ip.sh_str>0.0f) {
2842       NV = -DotProd(ip.N,ip.V);  // N dot V: view vector is TOWARDS us.
2843       is_shiny = 1;
2844       float r = 1.0f-ip.shine;
2845       if (r==0.0f) r = .00001f;
2846       m2inv = 1.0f/(r*r);
2847       }
2848    else
2849       is_shiny = 0;
2850 
2851 
2852    for (int i=0; i<sc.nLights; i++) {
2853       l = sc.Light(i);
2854       register float NL, diffCoef;
2855       Point3 L;
2856 
2857       if (!l->Illuminate(sc,ip.N,lightCol,L,NL,diffCoef))
2858          continue;
2859 
2860       if (l->ambientOnly) {
2861          ip.ambIllum += lightCol;
2862          continue;
2863          }
2864 
2865       // diffuse
2866       if (NL>0.0f&&l->affectDiffuse)  // TBD is the NL test necessary?
2867          ip.diffIllum += diffCoef*lightCol;
2868 
2869       if (is_shiny&&l->affectSpecular) { // SPECULAR
2870          Color fcol;
2871          float LH,NH,VH;
2872           float sec2;  // Was double?? TBD
2873          Point3 H;
2874 
2875          if (NV<0.0f) continue;
2876 
2877          H = FNormalize(L-ip.V);
2878 
2879          LH = DotProd(L,H);  // cos(phi)
2880          NH = DotProd(ip.N,H);  // cos(alpha)
2881          if (NH==0.0f) continue;
2882          VH = -DotProd(ip.V,H);
2883 
2884          // compute geometrical attenuation factor
2885          float G = (NV<NL)? (2.0f*NV*NH/VH): (2.0f*NL*NH/VH);
2886          if (G>0.0f) {
2887             // Compute (approximate) indices of refraction
2888             // this can be factored out for non-texture-mapped mtls
2889             if (!gotKav) {
2890                fav0 = Intens(ip.diff);
2891                if (fav0>=1.0f) fav0 = .9999f;
2892                kav = CompK(fav0);
2893                gotKav = TRUE;
2894                }
2895 
2896             float fav = fres_metal(LH,kav);
2897             float t = (fav-fav0)/(1.0f-fav0);
2898             fcol = (1.0f-t)*ip.diff + Color(t,t,t);
2899 
2900             // Beckman distribution  (from Cook-Torrance paper)
2901             sec2 = 1.0f/(NH*NH);  // 1/sqr(cos)
2902             float D = (.5f/PI)*sec2*sec2*m2inv*(float)exp((1.0f-sec2)*m2inv);
2903             if (G>1.0f) G = 1.0f;
2904             float Rs = ip.sh_str*D*G/(NV+.05f);
2905             ip.specIllum += fcol*Rs*lightCol;
2906             }
2907          }
2908       }
2909    ip.diffIllum *= 1.0f - ip.sh_str;
2910    }
2911 
2912 
SetShininess(float shininess,float shineStr)2913 void Metal::SetShininess(float shininess, float shineStr) {
2914    float r = 1.0f-shininess;
2915    if (r==0.0f) r = .00001f;
2916    fm2inv = 1.0f/(r*r);
2917    fshin_str = shineStr;
2918    }
2919 
EvalHilite(float x)2920 float Metal::EvalHilite(float x) {
2921    float c = (float)cos(x*PI);
2922    float sec2 = 1.0f/(c*c);     /* 1/sqr(cos) */
2923    return fshin_str*(.5f/PI)*sec2*sec2*fm2inv*(float)exp((1.0f-sec2)*fm2inv);
2924    }
2925 
2926 //-------------------------------------------------------------------------
2927 
2928 
2929 static Phong phongShader;
2930 static Blinn blinnShader;
2931 static Metal metalShader;
2932 
2933 static SShader *shaders[4] = {
2934    &phongShader, // CONST
2935    &phongShader,
2936    &metalShader,
2937    &blinnShader
2938    };
2939 
GetShaderFromId(int s)2940 static SShader *GetShaderFromId(int s) { return shaders[s]; };
2941 
2942 #define DOMAP(i) (sc.doMaps&&(*maps)[i].IsActive())
2943 
Shade(ShadeContext & sc)2944 void StdMtl::Shade(ShadeContext& sc) {
2945    SIllumParams ip;
2946    Color lightCol,rescol, diffIllum0;
2947    float opac;
2948    RGBA mval;
2949    Point3 N0,P;
2950    BOOL bumped = FALSE;
2951    if (gbufID) sc.SetGBufferID(gbufID);
2952 
2953    ip.flags = flags;
2954    ip.softThresh = softThresh;
2955    ip.diffIllum = blackCol;
2956    ip.specIllum = blackCol;
2957    ip.ambIllum  = blackCol;
2958    ip.amb = ambient;
2959    ip.diff = diffuse;
2960    ip.spec = specular;
2961 
2962    opac =  opacity;
2963 
2964    if (sc.mode==SCMODE_SHADOW) {
2965       // Opacity mapping;
2966       if (DOMAP(ID_OP))
2967          opac = (*maps)[ID_OP].LerpEvalMono(sc,opac);
2968 
2969       // "Shadow mode": This just computes the transparency, which is all
2970       // you need for shadowing.
2971       if (opac!=1.0f||opfall!=0.0f) {
2972          if (opfall!=0.0f) {
2973             ip.N = (shading==SHADE_CONST)?sc.GNormal():sc.Normal();
2974             ip.V = sc.V();  // get unit view vector
2975             float d = (float)fabs(DotProd(ip.N,ip.V));
2976             if (flags&STDMTL_FALLOFF_OUT) d = 1.0f-d;
2977             opac *= (1.0f-opfall*d);
2978             }
2979 
2980          // Transparency may use diffuse color mapping
2981          if ((flags&STDMTL_ADD_TRANSP|STDMTL_FILT_TRANSP)==0) {
2982             if (DOMAP(ID_DI)) {
2983                mval = (*maps)[ID_DI].Eval(sc);
2984                 AlphaCompCol(ip.diff,mval);
2985                }
2986             }
2987          // Compute the transpareny color
2988          sc.out.t = TranspColor(sc, opac, ip.diff);
2989          }
2990       else
2991          sc.out.t = blackCol;
2992       return;
2993       }
2994 
2995    N0 = ip.N = sc.Normal();
2996 
2997    if (shading==SHADE_CONST) {
2998       ip.N = sc.GNormal();
2999       bumped = TRUE;
3000       sc.SetNormal(ip.N);
3001       }
3002 
3003    P = sc.P();
3004    ip.V = sc.V();  // get unit view vector
3005 
3006    // Do texture mapping
3007 
3008    // Bump mapping: Do this FIRST so other maps can use the perturbed normal
3009    if (DOMAP(ID_BU)) {
3010       Point3 dn = (*maps)[ID_BU].EvalNormalPerturb(sc);
3011       bumped = TRUE;
3012       ip.N = FNormalize(ip.N + (sc.backFace?-dn:dn));
3013       sc.SetNormal(ip.N);
3014       }
3015 
3016    // Diffuse color mapping
3017    if (DOMAP(ID_DI)) {
3018       mval = (*maps)[ID_DI].Eval(sc);
3019        AlphaCompCol(ip.diff,mval);
3020       if (flags&STDMTL_LOCK_ADTEX)
3021           AlphaCompCol(ip.amb,mval);
3022       }
3023 
3024    // Ambient color mapping
3025    if (!(flags&STDMTL_LOCK_ADTEX)) {
3026       if (DOMAP(ID_AM)) {
3027          AlphaCompCol(ip.amb, (*maps)[ID_AM].Eval(sc));
3028          }
3029       }
3030 
3031    // Specular color mapping
3032    if (DOMAP(ID_SP))
3033        AlphaCompCol(ip.spec,(*maps)[ID_SP].Eval(sc));
3034 
3035    // Opacity mapping;
3036    if (DOMAP(ID_OP)) {
3037       opac = (*maps)[ID_OP].LerpEvalMono(sc,opac);
3038       }
3039 
3040    // Shininess mapping
3041    if (DOMAP(ID_SH)) {
3042       //ip.shine = shininess*(*maps)[ID_SH].EvalMono(sc);
3043       ip.shine = (*maps)[ID_SH].LerpEvalMono(sc,shininess);
3044       ip.ph_exp = (float)pow(2.0,ip.shine*10.0); // expensive.!!  TBD
3045       }
3046    else {
3047       ip.shine = shininess;
3048       ip.ph_exp = phongexp;
3049       }
3050 
3051    // Shininess strength mapping
3052    ip.sh_str = (DOMAP(ID_SS))? (*maps)[ID_SS].LerpEvalMono(sc,shine_str): shine_str;
3053 
3054    // Self illumination mapping
3055    float self_i = (DOMAP(ID_SI))? (*maps)[ID_SI].LerpEvalMono(sc,self_illum) : self_illum;
3056 
3057    curShader->Illum(sc,ip);
3058 
3059    diffIllum0 = ip.diffIllum; // save this for reflection dimming
3060 
3061    // Apply self illumination
3062    if (self_i>0.0f) {
3063       ip.diffIllum = (self_i>=1.0f) ?  whiteCol: ip.diffIllum*(1.0f-self_i) + self_i;
3064       }
3065 
3066    ip.diffIllum = ip.amb*(sc.ambientLight+ip.ambIllum) +  ip.diff*ip.diffIllum;
3067 
3068    if (DOMAP(ID_RR)) {
3069       // Set up for opacity for Refraction map.
3070       opac *= 1.0f-(*maps)[ID_RR].amount;
3071 
3072       // Make more opaque where specular hilite occurs:
3073       float a_s = MaxRGB(ip.specIllum);
3074       if (a_s>1.0f) a_s = 1.0f;
3075       sc.out.c = opac*ip.diffIllum + ip.specIllum;
3076          opac = opac + a_s - opac*a_s;
3077 
3078       // Evaluate refraction map, filtered by filter color.
3079       Texmap *refrmap = (*maps)[ID_RR].map;
3080       AColor rcol;
3081       sc.SetIOR(ioRefract);
3082       if (refrmap->HandleOwnViewPerturb())
3083          rcol = refrmap->EvalColor(sc);
3084       else
3085          rcol = sc.EvalEnvironMap(refrmap, sc.RefractVector(ioRefract));
3086       sc.out.c += Color(rcol.r,rcol.g,rcol.b)*TranspColor(sc, opac, ip.diff);
3087       sc.out.t.Black();  // no transparency when doing refraction
3088       }
3089    else {
3090       if (opac!=1.0f||opfall!=0.0f) {
3091          if (opfall!=0.0f) {
3092             float d = (float)fabs(DotProd(ip.N,ip.V));
3093             if (flags&STDMTL_FALLOFF_OUT) d = 1.0f-d;
3094             opac *= (1.0f-opfall*d);
3095             }
3096 
3097          // Make more opaque where specular hilite occurs, so you
3098          // can still see the hilite:
3099          float a_s = MaxRGB(ip.specIllum);
3100          if (a_s>1.0f) a_s = 1.0f;
3101          sc.out.c = opac*ip.diffIllum + ip.specIllum;
3102             opac = opac + a_s - opac*a_s;
3103 
3104          // Compute the color of the transparent filter color
3105          sc.out.t = TranspColor(sc, opac, ip.diff);
3106          }
3107       else {
3108          sc.out.t = blackCol;
3109          sc.out.c = ip.diffIllum + ip.specIllum;
3110          }
3111       }
3112 
3113    // Evaluate reflection map.
3114    if (DOMAP(ID_RL)) {
3115       AColor rcol;
3116       Texmap *reflmap = (*maps)[ID_RL].map;
3117       if (reflmap->HandleOwnViewPerturb()) {
3118          sc.TossCache(reflmap);
3119          rcol = reflmap->EvalColor(sc);
3120          }
3121       else
3122          rcol = sc.EvalEnvironMap(reflmap, sc.ReflectVector());
3123       Color rc(rcol.r,rcol.g,rcol.b);
3124       curShader->AffectReflMap(sc,ip,rc);
3125       float r = rcol.a*(*maps)[ID_RL].amount;
3126       if (dimReflect) {
3127          float dimfact = ((1.0f-dimIntens)*Intens(diffIllum0)*dimMult + dimIntens);
3128          r *= dimfact;
3129          }
3130       sc.out.c += (rc*r);
3131       }
3132    if (bumped) sc.SetNormal(N0);
3133    }
3134 
EvalDisplacement(ShadeContext & sc)3135 float StdMtl::EvalDisplacement(ShadeContext& sc) {
3136    if (DOMAP(ID_DP))
3137       return (*maps)[ID_DP].EvalMono(sc);
3138    else return 0.0f;
3139    }
3140 
DisplacementValidity(TimeValue t)3141 Interval StdMtl::DisplacementValidity(TimeValue t) {
3142    if (MAPACTIVE(ID_DP)) {
3143       Interval iv;
3144       iv.SetInfinite();
3145       maps->txmap[ID_DP].Update(t,iv);
3146       return iv;
3147       }
3148    else
3149       return FOREVER;
3150    }
3151 
3152 
3153 
3154 
3155