1 ///////////////////////////////////////////////////////////////////
2 //
3 // MultiLayer shader
4 //
5 //    Created: 11/23/98 Kells Elmquist
6 //
7 #include "shadersPch.h"
8 #include "shadersRc.h"
9 #include "gport.h"
10 #include "shaders.h"
11 #include "shaderUtil.h"
12 #include "macrorec.h"
13 #include "toneop.h"
14 
15 #include "3dsmaxport.h"
16 
17 // Class Ids
18 #define MULTILAYERSHADER_CLASS_ID      0x2857f470
19 
20 static Class_ID MultiLayerShaderClassID( MULTILAYERSHADER_CLASS_ID, 0);
21 
22 
23 // paramblock2 block and parameter IDs.
24 enum { multiLayer_params, };
25 // shdr_params param IDs
26 enum
27 {
28    ml_ambient, ml_diffuse, ml_self_illum_color,
29    ml_self_illum_amnt, ml_diffuse_level, ml_diffuse_rough,
30    ml_specular1, ml_specular_level1, ml_glossiness1, ml_anisotropy1, ml_orientation1,
31    ml_specular2, ml_specular_level2, ml_glossiness2, ml_anisotropy2, ml_orientation2,
32    ml_map_channel, ml_ad_texlock, ml_ad_lock, ml_use_self_illum_color,
33 };
34 
35 
36 
37 /////////////////////////////////////////////////////////////////////
38 //
39 // Basic Panel UI
40 //
41 #define MULTI_LAYER_NMBUTS 16
42 #define N_TR_BUT 15
43 
44 // tex channel number to button IDC
45 static int texMButtonsIDC[] = {
46    IDC_MAPON_AM, IDC_MAPON_DI, IDC_MAPON_DIFFLEV, IDC_MAPON_DIFFROUGH,
47    IDC_MAPON_SPECCLR1, IDC_MAPON_SPECLEV1, IDC_MAPON_GL1, IDC_MAPON_AN1, IDC_MAPON_OR1,
48    IDC_MAPON_SPECCLR2, IDC_MAPON_SPECLEV2, IDC_MAPON_GL2, IDC_MAPON_AN2, IDC_MAPON_OR2,
49    IDC_MAPON_SI, IDC_MAPON_TR,
50    -1,  -1, -1, -1, -1, -1, -1, -1
51    };
52 
53 // This array gives the texture map number for given MButton number
54 static int texmapFromMBut[] = { 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15 };
55 
56 // Texture Maps
57 #define MULTI_LAYER_NTEXMAPS  17
58 
59 // channels ids needed by shader
60 #define _AMBCLR      0
61 #define _DIFFCLR  1
62 #define _DIFFLEV  2
63 #define _DIFFROUGH   3
64 #define _SPECCLR1 4
65 #define _SPECLEV1 5
66 #define _GL1      6
67 #define _AN1      7
68 #define _OR1      8
69 #define _SPECCLR2 9
70 #define _SPECLEV2 10
71 #define _GL2      11
72 #define _AN2      12
73 #define _OR2      13
74 #define _SI       14
75 #define _TR       15
76 
77 // channel names
78 static int texNameIDS[STD2_NMAX_TEXMAPS] = {
79    IDS_DS_AMBIENT, IDS_DS_DIFFUSE, IDS_KE_DIFF_LEVEL, IDS_KE_DIFF_ROUGH,
80    IDS_KE_SPEC_CLR1, IDS_KE_SPEC_LEVEL1, IDS_KE_GLOSS1, IDS_KE_ANISO1, IDS_KE_ORIENTATION1,
81    IDS_KE_SPEC_CLR2, IDS_KE_SPEC_LEVEL2, IDS_KE_GLOSS2, IDS_KE_ANISO2, IDS_KE_ORIENTATION2,
82    IDS_KE_SELFILLUM, IDS_DS_TRANS, IDS_DS_FILTER,
83    IDS_KE_NONE, IDS_KE_NONE, IDS_KE_NONE, IDS_KE_NONE,
84    IDS_KE_NONE, IDS_KE_NONE, IDS_KE_NONE,
85 };
86 
87 // internal non-local parsable channel map names
88 static TCHAR* texInternalNames[STD2_NMAX_TEXMAPS] = {
89    _T("ambientMap"), _T("diffuseMap"), _T("diffuseLevelMap"), _T("diffuseRoughnessMap"),
90    _T("specularMap"), _T("specularLevelMap"), _T("glossinessMap"), _T("anisotropyMap"), _T("orientationMap"),
91    _T("specularMap2"), _T("specularLevelMap2"), _T("glossinessMap2"), _T("anisotropyMap2"), _T("orientationMap2"),
92    _T("selfIllumMap"), _T("opacityMap"), _T("filterMap"),
93    _T(""), _T(""), _T(""), _T(""),
94    _T(""), _T(""), _T(""),
95 };
96 
97 
98 // sized for nmax textures
99 // bump, reflection & refraction maps are ignored....done after shading
100 static int chanType[STD2_NMAX_TEXMAPS] = {
101    CLR_CHANNEL, CLR_CHANNEL, MONO_CHANNEL, MONO_CHANNEL,
102    CLR_CHANNEL, SLEV_CHANNEL, MONO_CHANNEL, MONO_CHANNEL, MONO_CHANNEL,
103    CLR_CHANNEL, SLEV_CHANNEL, MONO_CHANNEL, MONO_CHANNEL, MONO_CHANNEL,
104    CLR_CHANNEL, MONO_CHANNEL, CLR_CHANNEL,
105    UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL,UNSUPPORTED_CHANNEL,
106    UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL,
107 };
108 
109 // what channel corresponds to the stdMat ID's
110 static int stdIDToChannel[N_ID_CHANNELS] = { 0, 1, 4, 6, 5, 14, 15, 16, -1, -1, -1, -1, -1, -1, -1, -1 };
111 
112 //////////////////////////////////////////////////////////////////////////////////////////
113 //
114 //    MultiLayer Parameter Block
115 //
116 #define CURRENT_MULTI_LAYER_SHADER_VERSION   2
117 #define MULTI_LAYER_SHADER_NPARAMS        17
118 #define MULTI_LAYER_SHADER_PB_VERSION     1
119 #define MULTI_LAYER_NCOLBOX               5
120 
121 static int colID[MULTI_LAYER_NCOLBOX] = { IDC_AMB_CLR, IDC_DIFF_CLR, IDC_SI_CLR, IDC_SPEC_CLR1, IDC_SPEC_CLR2 };
122 #define N_SI_CLR     2
123 
124 #define PB_AMB_CLR         0
125 #define PB_DIFF_CLR        1
126 #define PB_DIFF_LEV        2
127 #define PB_DIFF_ROUGH      3
128 #define PB_SPEC_CLR1    4
129 #define PB_SPEC_LEV1    5
130 #define PB_GLOSS1       6
131 #define PB_ANISO1       7
132 #define PB_SPEC_CLR2    8
133 #define PB_SPEC_LEV2    9
134 #define PB_GLOSS2       10
135 #define PB_ANISO2       11
136 #define PB_SELFILLUM_CLR   12
137 #define PB_SELFILLUM_LEV   13
138 #define PB_ORIENTATION1    14
139 #define PB_ORIENTATION2    15
140 #define PB_MAP_CHANNEL     16
141 
142 #define ANIMATE      TRUE
143 #define NO_ANIMATE   FALSE
144 
145 //Current Param Block Descriptor
146 static ParamBlockDescID MultiLayerShaderPB[ MULTI_LAYER_SHADER_NPARAMS ] = {
147    { TYPE_RGBA,  NULL, ANIMATE, ml_ambient },   // ambient color
148    { TYPE_RGBA,  NULL, ANIMATE, ml_diffuse },   // diffuse color
149    { TYPE_FLOAT, NULL, ANIMATE, ml_diffuse_level },  // diffuse level
150    { TYPE_FLOAT, NULL, ANIMATE, ml_diffuse_rough },  // diffuse roughness
151    { TYPE_RGBA,  NULL, ANIMATE, ml_specular1 },   // specular layer 1 color
152    { TYPE_FLOAT, NULL, ANIMATE, ml_specular_level1 },   // layer 1 level
153    { TYPE_FLOAT, NULL, ANIMATE, ml_glossiness1 },   // layer 1 gloss
154    { TYPE_FLOAT, NULL, ANIMATE, ml_anisotropy1 },  // layer 1 anisotropy
155    { TYPE_RGBA,  NULL, ANIMATE, ml_specular2 },   // Specular layer 2 color
156    { TYPE_FLOAT, NULL, ANIMATE, ml_specular_level2 },   // layer 2 level
157    { TYPE_FLOAT, NULL, ANIMATE, ml_glossiness2 },   // layer 2 gloss
158    { TYPE_FLOAT, NULL, ANIMATE, ml_anisotropy2 },  // layer 2 anisotropy
159    { TYPE_RGBA,  NULL, ANIMATE, ml_self_illum_color },   // selfIllumClr
160    { TYPE_FLOAT, NULL, ANIMATE, ml_self_illum_amnt},  // selfIllumLevel
161    { TYPE_FLOAT, NULL, ANIMATE, ml_orientation1 }, // orientation1
162    { TYPE_FLOAT, NULL, ANIMATE, ml_orientation2 }, // orientation2
163    { TYPE_INT,   NULL, NO_ANIMATE, ml_map_channel } // map channel
164 };
165 
166 
167 #define MULTI_LAYER_NUMVER 1
168 
169 static ParamVersionDesc oldVersions[MULTI_LAYER_NUMVER] = {
170    ParamVersionDesc(MultiLayerShaderPB, MULTI_LAYER_SHADER_NPARAMS, 0),
171 };
172 
173 //----------------------------------------------------------------------------------------
174 //---- MultiLayer: A 2 layer physically based anisotropic shader -------------------------------
175 //----------------------------------------------------------------------------------------
176 
177 class MultiLayerShaderDlg;
178 
179 class MultiLayerShader : public ExposureMaterialControlImp<MultiLayerShader, CombineComponentsCompShader> {
180 friend class MultiLayerShaderCB;
181 friend class MultiLayerShaderDlg;
182 friend class ExposureMaterialControlImp<MultiLayerShader, CombineComponentsCompShader>;
183 protected:
184    IParamBlock2   *pblock;   // ref 0
185    Interval    ivalid;
186 
187    MultiLayerShaderDlg* paramDlg;
188 
189    Color       ambColor;
190    Color       diffColor;
191    float       diffLevel;
192    float       diffRough;
193 
194    Color       specColor1;
195    float       specLevel1;
196    float       gloss1;
197    float       aniso1;
198    float       orientation1;
199 
200    Color       specColor2;
201    float       specLevel2;
202    float       gloss2;
203    float       aniso2;
204    float       orientation2;
205 
206    float       selfIllumLevel;
207    Color       selfIllum;
208    BOOL        selfIllumClrOn;
209 
210 
211    BOOL        lockAD;
212    BOOL        lockADTex;
213 
214    BOOL         rolloutOpen;
215 
216 
217    static CombineComponentsFPDesc msExpMtlControlDesc;
218 
219    public:
220    MultiLayerShader();
DeleteThis()221    void DeleteThis(){ delete this; }
SupportStdParams()222     ULONG SupportStdParams(){ return (STD_MULTILAYER | STD_EXTRA); }
223 
224    // copy std params, for switching shaders
225     void CopyStdParams( Shader* pFrom );
226 
227    // texture maps
nTexChannelsSupported()228    long  nTexChannelsSupported(){ return MULTI_LAYER_NTEXMAPS; }
GetTexChannelName(long nTex)229    TSTR  GetTexChannelName( long nTex ){ return GetString( texNameIDS[ nTex ] ); }
GetTexChannelInternalName(long nTex)230    TSTR  GetTexChannelInternalName( long nTex ){ return texInternalNames[ nTex ]; }
ChannelType(long nChan)231    long  ChannelType( long nChan ) { return chanType[nChan]; }
StdIDToChannel(long stdID)232    long  StdIDToChannel( long stdID ){ return stdIDToChannel[stdID]; }
233 
KeyAtTime(int id,TimeValue t)234    BOOL KeyAtTime(int id,TimeValue t) { return pblock->KeyFrameAtTime(id,t); }
235 
236    ShaderParamDlg* CreateParamDialog(HWND hOldRollup, HWND hwMtlEdit, IMtlParams *imp, StdMat2* theMtl, int rollupOpen, int );
GetParamDlg(int)237    ShaderParamDlg* GetParamDlg(int){ return (ShaderParamDlg*)paramDlg; }
SetParamDlg(ShaderParamDlg * newDlg,int)238    void SetParamDlg( ShaderParamDlg* newDlg, int ){ paramDlg = (MultiLayerShaderDlg*)newDlg; }
239 
ClassID()240    Class_ID ClassID() { return MultiLayerShaderClassID; }
SuperClassID()241    SClass_ID SuperClassID() { return SHADER_CLASS_ID; }
GetName()242    TSTR GetName() { return GetString( IDS_KE_MULTI_LAYER ); }
GetClassName(TSTR & s)243    void GetClassName(TSTR& s) { s = GetName(); }
244 
NumSubs()245    int NumSubs() { return 1; }
SubAnim(int i)246    Animatable* SubAnim(int i){ return (i==0)? pblock : NULL; }
SubAnimName(int i)247    TSTR SubAnimName(int i){ return TSTR(GetString( IDS_KE_MULTI_LAYER_PARMS )); };
SubNumToRefNum(int subNum)248    int SubNumToRefNum(int subNum) { return subNum; }
249 
250    // add direct ParamBlock2 access
NumParamBlocks()251    int   NumParamBlocks() { return 1; }
GetParamBlock(int i)252    IParamBlock2* GetParamBlock(int i) { return pblock; }
GetParamBlockByID(BlockID id)253    IParamBlock2* GetParamBlockByID(BlockID id) { return (pblock->ID() == id) ? pblock : NULL; }
254 
NumRefs()255    int NumRefs() { return 1; }
GetReference(int i)256    RefTargetHandle GetReference(int i){ return (i==0)? pblock : NULL; }
SetReference(int i,RefTargetHandle rtarg)257    void SetReference(int i, RefTargetHandle rtarg)
258       { if (i==0) pblock = (IParamBlock2*)rtarg; else assert(0); }
NotifyChanged()259    void NotifyChanged(){ NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE); }
260 
261    void Update(TimeValue t, Interval& valid);
262    void Reset();
263    RefTargetHandle Clone( RemapDir &remap=DefaultRemapDir() );
264    RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
265                                PartID& partID, RefMessage message );
266    // IO
267    IOResult Save(ISave *isave);
268    IOResult Load(ILoad *iload);
269 
270    // cache for mapping of params, mtl fills in ip
271    void GetIllumParams( ShadeContext &sc, IllumParams& ip );
272 
273    // MultiLayer Shader specific section
274    void PreShade(ShadeContext& sc, IReshadeFragment* pFrag);
275    void PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams* ip);
276    void  Illum(ShadeContext &sc, IllumParams &ip);
277    void  InternalIllum(ShadeContext &sc, IllumParams &ip, Point3* pTangent );
278    float EvalHiliteCurve2(float x, float y, int layer ); // layer is 1 or 2
279    void AffectReflection(ShadeContext &sc, IllumParams &ip, Color &rcol);
280 
SetGlossiness(float v,TimeValue t)281    void SetGlossiness(float v, TimeValue t)
282       { gloss1= v; pblock->SetValue( ml_glossiness1, t, v); }
SetGlossiness1(float v,TimeValue t)283    void SetGlossiness1(float v, TimeValue t)
284       { gloss1= v; pblock->SetValue( ml_glossiness1, t, v); }
SetAnisotropy1(float v,TimeValue t)285    void SetAnisotropy1(float v, TimeValue t)
286       { aniso1 = v; pblock->SetValue( ml_anisotropy1, t, v); }
SetSpecLevel1(float v,TimeValue t)287    void SetSpecLevel1(float v, TimeValue t)
288       { specLevel1 = v; pblock->SetValue( ml_specular_level1, t, v); }
SetOrientation1(float v,TimeValue t)289    void SetOrientation1(float v, TimeValue t)
290       { orientation1 = v; pblock->SetValue( ml_orientation1, t, v); }
SetOrientation2(float v,TimeValue t)291    void SetOrientation2(float v, TimeValue t)
292       { orientation2 = v; pblock->SetValue( ml_orientation2, t, v); }
GetGlossiness(int mtlNum,BOOL backFace)293    float GetGlossiness(int mtlNum, BOOL backFace){ return gloss1; }
GetGlossiness1(int mtlNum,BOOL backFace)294    float GetGlossiness1(int mtlNum, BOOL backFace){ return gloss1; }
GetAnisotropy1(int mtlNum,BOOL backFace)295    float GetAnisotropy1(int mtlNum, BOOL backFace){ return aniso1; }
GetSpecLevel1(int mtlNum,BOOL backFace)296    float GetSpecLevel1(int mtlNum, BOOL backFace){ return specLevel1; }
GetOrientation1(int mtlNum,BOOL backFace)297    float GetOrientation1(int mtlNum, BOOL backFace){ return orientation1; }
GetOrientation2(int mtlNum,BOOL backFace)298    float GetOrientation2(int mtlNum, BOOL backFace){ return orientation2; }
GetGlossiness(TimeValue t)299    float GetGlossiness( TimeValue t){return pblock->GetFloat(ml_glossiness1,t);  }
GetGlossiness1(TimeValue t)300    float GetGlossiness1( TimeValue t){return pblock->GetFloat(ml_glossiness1,t);  }
GetAnisotropy1(TimeValue t)301    float GetAnisotropy1( TimeValue t){return pblock->GetFloat(ml_anisotropy1,t);  }
GetSpecLevel1(TimeValue t)302    float GetSpecLevel1( TimeValue t){return pblock->GetFloat(ml_specular_level1,t);  }
GetOrientation1(TimeValue t)303    float GetOrientation1( TimeValue t){return pblock->GetFloat(ml_orientation1,t);  }
GetOrientation2(TimeValue t)304    float GetOrientation2( TimeValue t){return pblock->GetFloat(ml_orientation2,t);  }
305 
SetGlossiness2(float v,TimeValue t)306    void SetGlossiness2(float v, TimeValue t)
307       { gloss2= v; pblock->SetValue( ml_glossiness2, t, v); }
SetAnisotropy2(float v,TimeValue t)308    void SetAnisotropy2(float v, TimeValue t)
309       { aniso2 = v; pblock->SetValue( ml_anisotropy2, t, v); }
SetSpecLevel2(float v,TimeValue t)310    void SetSpecLevel2(float v, TimeValue t)
311       { specLevel2 = v; pblock->SetValue( ml_specular_level2, t, v); }
GetGlossiness2(int mtlNum,BOOL backFace)312    float GetGlossiness2(int mtlNum, BOOL backFace){ return gloss2; };
GetAnisotropy2(int mtlNum,BOOL backFace)313    float GetAnisotropy2(int mtlNum, BOOL backFace){ return aniso2; };
GetSpecLevel2(int mtlNum,BOOL backFace)314    float GetSpecLevel2(int mtlNum, BOOL backFace){ return specLevel2; };
GetGlossiness2(TimeValue t)315    float GetGlossiness2( TimeValue t){return pblock->GetFloat(ml_glossiness2,t);  }
GetAnisotropy2(TimeValue t)316    float GetAnisotropy2( TimeValue t){return pblock->GetFloat(ml_anisotropy2,t);  }
GetSpecLevel2(TimeValue t)317    float GetSpecLevel2( TimeValue t){return pblock->GetFloat(ml_specular_level2,t);  }
318 
SetDiffuseLevel(float v,TimeValue t)319    void SetDiffuseLevel(float v, TimeValue t)
320       { diffLevel = v; pblock->SetValue( ml_diffuse_level, t, v); }
GetDiffuseLevel(int mtlNum,BOOL backFace)321    float GetDiffuseLevel(int mtlNum, BOOL backFace){ return diffLevel; }
GetDiffuseLevel(TimeValue t)322    float GetDiffuseLevel( TimeValue t ){ return pblock->GetFloat(ml_diffuse_level,t); }
SetDiffuseRough(float v,TimeValue t)323    void SetDiffuseRough(float v, TimeValue t)
324       { diffRough = v; pblock->SetValue( ml_diffuse_rough, t, v); }
GetDiffuseRough(int mtlNum,BOOL backFace)325    float GetDiffuseRough(int mtlNum, BOOL backFace){ return diffRough; }
GetDiffuseRough(TimeValue t)326    float GetDiffuseRough( TimeValue t ){ return pblock->GetFloat(ml_diffuse_rough,t); }
327 
SetSpecColor1(Color c,TimeValue t)328    void SetSpecColor1(Color c, TimeValue t)
329       { specColor1 = c; pblock->SetValue( ml_specular1, t, c); }
SetSpecColor2(Color c,TimeValue t)330    void SetSpecColor2(Color c, TimeValue t)
331       { specColor2 = c; pblock->SetValue( ml_specular2, t, c); }
332 
GetSpecColor1(int mtlNum,BOOL backFace)333     Color GetSpecColor1(int mtlNum, BOOL backFace){ return specColor1;}
GetSpecColor1(TimeValue t)334    Color GetSpecColor1(TimeValue t){ return pblock->GetColor(ml_specular1,t); }
GetSpecColor2(int mtlNum,BOOL backFace)335    Color GetSpecColor2(int mtlNum, BOOL backFace){ return specColor2; }
GetSpecColor2(TimeValue t)336    Color GetSpecColor2(TimeValue t){ return pblock->GetColor(ml_specular2,t); }
337 
338    // Std Params, these define the interactive settings for OGL, etc....
SetAmbientClr(Color c,TimeValue t)339    void SetAmbientClr(Color c, TimeValue t)
340       { ambColor = c; pblock->SetValue( ml_ambient, t, c); }
SetDiffuseClr(Color c,TimeValue t)341    void SetDiffuseClr(Color c, TimeValue t)
342       { diffColor = c; pblock->SetValue( ml_diffuse, t, c); }
SetSpecularClr(Color c,TimeValue t)343    void SetSpecularClr(Color c, TimeValue t)
344       { SetSpecColor1( c, t ); }
SetSelfIllumClr(Color c,TimeValue t)345    void SetSelfIllumClr(Color c, TimeValue t)
346       { selfIllum = c; pblock->SetValue( ml_self_illum_color, t, c); }
SetSpecularLevel(float v,TimeValue t)347    void SetSpecularLevel(float v, TimeValue t)
348       {SetSpecLevel1( v, t ); }
SetSelfIllum(float v,TimeValue t)349    void SetSelfIllum(float v, TimeValue t)
350       { selfIllumLevel = v; pblock->SetValue( ml_self_illum_amnt, t, v); }
351 
GetAmbientClr(int mtlNum,BOOL backFace)352    Color GetAmbientClr(int mtlNum, BOOL backFace ){ return ambColor;}
GetDiffuseClr(int mtlNum,BOOL backFace)353     Color GetDiffuseClr(int mtlNum, BOOL backFace ){ return diffColor;}
GetSpecularClr(int mtlNum,BOOL backFace)354    Color GetSpecularClr(int mtlNum, BOOL backFace ){ return specColor1; }
GetSelfIllumClr(int mtlNum,BOOL backFace)355    Color GetSelfIllumClr(int mtlNum, BOOL backFace ){ return selfIllum; }
GetSelfIllum(int mtlNum,BOOL backFace)356    float GetSelfIllum(int mtlNum, BOOL backFace ){ return selfIllumLevel; }
GetSpecularLevel(int mtlNum,BOOL backFace)357    float GetSpecularLevel(int mtlNum, BOOL backFace ){ return specLevel1; }
358 
GetAmbientClr(TimeValue t)359    Color GetAmbientClr(TimeValue t){ return pblock->GetColor(ml_ambient,t); }
GetDiffuseClr(TimeValue t)360    Color GetDiffuseClr(TimeValue t){ return pblock->GetColor(ml_diffuse,t); }
GetSpecularClr(TimeValue t)361    Color GetSpecularClr(TimeValue t){ return GetSpecColor1( t );  }
GetSelfIllumClr(TimeValue t)362    Color GetSelfIllumClr(TimeValue t){ return pblock->GetColor(ml_self_illum_color,t);}
GetSelfIllum(TimeValue t)363    float GetSelfIllum(TimeValue t){ return  pblock->GetFloat(ml_self_illum_amnt,t);}
GetSpecularLevel(TimeValue t)364    float GetSpecularLevel( TimeValue t){return GetSpecLevel1( t ); }
365 
SetSelfIllumClrOn(BOOL on)366    void SetSelfIllumClrOn( BOOL on ){ selfIllumClrOn = on; pblock->SetValue( ml_use_self_illum_color, 0, on); }
IsSelfIllumClrOn()367    BOOL IsSelfIllumClrOn(){ return selfIllumClrOn; }
IsSelfIllumClrOn(int mtlNum,BOOL backFace)368    BOOL IsSelfIllumClrOn(int mtlNum, BOOL backFace){ return selfIllumClrOn; }
369 
SetLockAD(BOOL lock)370    void SetLockAD(BOOL lock){ lockAD = lock; pblock->SetValue( ml_ad_lock, 0, lock);  }
GetLockAD()371    BOOL GetLockAD(){ return lockAD; }
SetLockADTex(BOOL lock)372    void SetLockADTex(BOOL lock){ lockADTex = lock; pblock->SetValue( ml_ad_texlock, 0, lock);  }
GetLockADTex()373    BOOL GetLockADTex(){ return lockADTex; }
374 
375    // not supported
SetSoftenLevel(float v,TimeValue t)376    void SetSoftenLevel(float v, TimeValue t) {}
GetSoftenLevel(int mtlNum=0,BOOL backFace=FALSE)377    float GetSoftenLevel(int mtlNum=0, BOOL backFace=FALSE){ return DEFAULT_SOFTEN; }
GetSoftenLevel(TimeValue t)378    float GetSoftenLevel(TimeValue t){ return  DEFAULT_SOFTEN; }
SetLockDS(BOOL lock)379    void SetLockDS(BOOL lock){}
GetLockDS()380    BOOL GetLockDS(){ return FALSE; }
381 
SetPanelOpen(BOOL open)382    void SetPanelOpen(BOOL open){rolloutOpen = open;}
383 
384 };
385 
386 ///////////// Class Descriptor ////////////////////////
387 class MultiLayerShaderClassDesc : public ClassDesc2 {
388    public:
IsPublic()389    int         IsPublic() { return 1; }
Create(BOOL loading)390    void *         Create(BOOL loading) {  return new MultiLayerShader(); }
ClassName()391    const TCHAR *  ClassName() { return GetString(IDS_KE_MULTI_LAYER); }
SuperClassID()392    SClass_ID      SuperClassID() { return SHADER_CLASS_ID; }
ClassID()393    Class_ID       ClassID() { return MultiLayerShaderClassID; }
Category()394    const TCHAR*   Category() { return _T("");  }
InternalName()395    const TCHAR*   InternalName() { return _T("MultiLayer"); } // returns fixed parsable name (scripter-visible name)
HInstance()396    HINSTANCE      HInstance() { return hInstance; }          // returns owning module handle
397 };
398 
399 MultiLayerShaderClassDesc multiLayerCD;
GetMultiLayerShaderCD()400 ClassDesc * GetMultiLayerShaderCD(){ return &multiLayerCD; }
401 
402 // shader parameters
403 static ParamBlockDesc2 multiLayer_param_blk ( multiLayer_params, _T("shaderParameters"),  0, &multiLayerCD, P_AUTO_CONSTRUCT, 0,
404    // params
405    ml_ambient, _T("ambient"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_AMBIENT,
406       p_default, Color(0, 0, 0),
407       end,
408    ml_diffuse, _T("diffuse"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_DIFFUSE,
409       p_default, Color(0.5f, 0.5f, 0.5f),
410       end,
411    ml_self_illum_color, _T("selfIllumColor"), TYPE_RGBA, P_ANIMATABLE, IDS_KE_SELFILLUM_CLR,
412       p_default,     Color(0, 0, 0),
413       end,
414    ml_self_illum_amnt, _T("selfIllumAmount"), TYPE_PCNT_FRAC,  P_ANIMATABLE, IDS_KE_SELFILLUM,
415       p_default,     0.0,
416       p_range,    0.0, 100.0,
417       end,
418    ml_diffuse_level, _T("diffuseLevel"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_DIFF_LEVEL,
419       p_default,     100.0,
420       p_range,    0.0, 400.0,
421       end,
422    ml_diffuse_rough, _T("diffuseRoughness"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_DIFF_ROUGH,
423       p_default,     0.0,
424       p_range,    0.0, 100.0,
425       end,
426    ml_specular1, _T("specular"), TYPE_RGBA, P_ANIMATABLE, IDS_KE_CLR1,
427       p_default, Color(1.0f, 1.0f, 1.0f),
428       end,
429    ml_specular_level1, _T("specularLevel"), TYPE_PCNT_FRAC, P_ANIMATABLE,IDS_KE_LEVEL1,
430       p_default,     10.0,
431       p_range,    0.0, 999.0,
432       end,
433    ml_glossiness1, _T("glossiness"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_GLOSS1,
434       p_default,     25.0,
435       p_range,    0.0, 100.0,
436       end,
437    ml_anisotropy1, _T("anisotropy"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_ANISO1,
438       p_default,     0.0,
439       p_range,    0.0, 100.0,
440       end,
441    ml_orientation1, _T("orientation"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_ORIENTATION1,
442       p_default,     0.0,
443       p_range,    MIN_ORIENT*100.0, MAX_ORIENT*100.0,
444       end,
445    ml_specular2, _T("specular2"), TYPE_RGBA, P_ANIMATABLE, IDS_KE_CLR2,
446       p_default, Color(1.0f, 1.0f, 1.0f),
447       end,
448    ml_specular_level2, _T("specularLevel2"), TYPE_PCNT_FRAC, P_ANIMATABLE,IDS_KE_LEVEL2,
449       p_default,     0.0,
450       p_range,    0.0, 999.0,
451       end,
452    ml_glossiness2, _T("glossiness2"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_GLOSS2,
453       p_default,     25.0,
454       p_range,    0.0, 100.0,
455       end,
456    ml_anisotropy2, _T("anisotropy2"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_ANISO2,
457       p_default,     0.0,
458       p_range,    0.0, 100.0,
459       end,
460    ml_orientation2, _T("orientation2"), TYPE_PCNT_FRAC, P_ANIMATABLE, IDS_KE_ORIENTATION2,
461       p_default,     0.0,
462       p_range,    MIN_ORIENT*100.0, MAX_ORIENT*100.0,
463       end,
464    ml_map_channel, _T("unused"), TYPE_INT, 0, IDS_KE_MAPCHANNEL,
465       p_default,     0,
466       p_range,    0, 16,
467       end,
468    ml_ad_texlock, _T("adTextureLock"), TYPE_BOOL,  0, IDS_JW_ADTEXLOCK,
469       p_default, TRUE,
470       end,
471    ml_ad_lock, _T("adLock"), TYPE_BOOL, 0, IDS_JW_ADLOCK,
472       p_default, TRUE,
473       end,
474    ml_use_self_illum_color, _T("useSelfIllumColor"), TYPE_BOOL, 0, IDS_JW_SELFILLUMCOLORON,
475       p_default, FALSE,
476       end,
477    end
478 );
479 
480 
481 
482 CombineComponentsFPDesc MultiLayerShader::msExpMtlControlDesc(multiLayerCD);
483 
MultiLayerShader()484 MultiLayerShader::MultiLayerShader()
485 {
486    pblock = NULL;
487    multiLayerCD.MakeAutoParamBlocks(this);   // make and intialize paramblock2
488    paramDlg = NULL;
489 
490    selfIllumClrOn = 0;
491    lockAD = lockADTex = TRUE;
492    ambColor = diffColor = specColor1 = specColor2 = selfIllum = Color(0.0f,0.0f,0.0f);
493    gloss1 = orientation1 = aniso1 = specLevel1
494    = gloss2 = orientation2 = aniso2 = specLevel2
495    = diffLevel = diffRough = selfIllumLevel = 0.0f;
496 
497    ivalid.SetEmpty();
498 
499    rolloutOpen = TRUE;
500 
501 }
502 
503 
CopyStdParams(Shader * pFrom)504 void MultiLayerShader::CopyStdParams( Shader* pFrom )
505 {
506    macroRecorder->Disable();
507    // don't want to see this parameter copying in macrorecorder
508       long fromParms = pFrom->SupportStdParams();
509 
510       if ( fromParms & STD_PARAM_SELFILLUM_CLR_ON )
511          SetSelfIllumClrOn( pFrom->IsSelfIllumClrOn() );
512 
513       if ( fromParms & STD_PARAM_AMBIENT_CLR )
514          SetAmbientClr( pFrom->GetAmbientClr(0,0), 0 );
515 
516       if ( fromParms & STD_PARAM_DIFFUSE_CLR )
517          SetDiffuseClr( pFrom->GetDiffuseClr(0,0), 0 );
518 
519       if ( fromParms & STD_PARAM_SPECULAR_CLR )
520          SetSpecularClr( pFrom->GetSpecularClr(0,0), 0 );
521 
522       if ( fromParms & STD_PARAM_SELFILLUM_CLR )
523          SetSelfIllumClr( pFrom->GetSelfIllumClr(0,0), 0 );
524 
525       if ( fromParms & STD_PARAM_SPECULAR_LEV )
526          SetSpecularLevel( pFrom->GetSpecularLevel(0,0), 0 );
527 
528       if ( fromParms & STD_PARAM_GLOSSINESS )
529          SetGlossiness( pFrom->GetGlossiness(0,0), 0 );
530 
531       if ( fromParms & STD_PARAM_SELFILLUM )
532          SetSelfIllum( pFrom->GetSelfIllum(0,0), 0 );
533 
534       if ( fromParms & STD_PARAM_LOCKAD )
535          SetLockAD( pFrom->GetLockAD() );
536 
537       if ( fromParms & STD_PARAM_LOCKADTEX )
538          SetLockADTex( pFrom->GetLockADTex() );
539 
540    macroRecorder->Enable();
541    ivalid.SetEmpty();
542 }
543 
544 
Clone(RemapDir & remap)545 RefTargetHandle MultiLayerShader::Clone( RemapDir &remap )
546 {
547    MultiLayerShader* mnew = new MultiLayerShader();
548    mnew->ExposureMaterialControl::operator=(*this);
549    mnew->ReplaceReference(0, remap.CloneRef(pblock));
550    mnew->ivalid.SetEmpty();
551 
552    mnew->ambColor = ambColor;
553    mnew->diffColor = diffColor;
554 
555    mnew->diffLevel = diffLevel;
556    mnew->diffRough = diffRough;
557 
558    mnew->selfIllum = selfIllum;
559    mnew->selfIllumLevel = selfIllumLevel;
560    mnew->selfIllumClrOn = selfIllumClrOn;
561 
562    mnew->specColor1 = specColor1;
563    mnew->specLevel1 = specLevel1;
564    mnew->gloss1 = gloss1;
565    mnew->aniso1 = aniso1;
566    mnew->orientation1 = orientation1;
567 
568    mnew->specColor2 = specColor2;
569    mnew->specLevel2 = specLevel2;
570    mnew->gloss2 = gloss2;
571    mnew->aniso2 = aniso2;
572    mnew->orientation2 = orientation2;
573 
574    mnew->lockAD = lockAD;
575    mnew->lockADTex = lockADTex;
576 
577    BaseClone(this, mnew, remap);
578    return (RefTargetHandle)mnew;
579 }
580 
581 
GetIllumParams(ShadeContext & sc,IllumParams & ip)582 void MultiLayerShader::GetIllumParams( ShadeContext &sc, IllumParams& ip )
583 {
584    ip.stdParams = SupportStdParams();
585    ip.channels[_AMBCLR] = lockAD? diffColor : ambColor;
586    ip.channels[_DIFFCLR] = diffColor;
587    ip.channels[_DIFFLEV].r = diffLevel;
588    ip.channels[_DIFFROUGH].r = diffRough;
589 
590    ip.channels[_SPECCLR1] = specColor1;
591    ip.channels[_SPECCLR2] = specColor2;
592 
593    ip.channels[_SPECLEV1].r = specLevel1;
594    ip.channels[_GL1].r = gloss1;
595    ip.channels[_AN1].r = aniso1;
596    ip.channels[_OR1].r = orientation1 * (1.0f/1.8f); // this range for mono texturing, 0..1
597 
598    ip.channels[_SPECLEV2].r = specLevel2;
599    ip.channels[_GL2].r = gloss2;
600    ip.channels[_AN2].r = aniso2;
601    ip.channels[_OR2].r = orientation2 * (1.0f/1.8f);
602 
603    if (selfIllumClrOn )
604       ip.channels[_SI] = selfIllum;
605    else
606       ip.channels[_SI].r=ip.channels[_SI].g=ip.channels[_SI].b = selfIllumLevel;
607 }
608 
609 static BOOL inUpdate = FALSE;
610 
611 
Update(TimeValue t,Interval & valid)612 void MultiLayerShader::Update(TimeValue t, Interval &valid) {
613    Point3 p, p2;
614    if( inUpdate )
615       return;
616    inUpdate = TRUE;
617    if (!ivalid.InInterval(t)) {
618       ivalid.SetInfinite();
619 
620 //    pblock->GetValue( ml_ambient, t, p, ivalid );
621 //    ambColor = Bound(Color(p.x,p.y,p.z));
622       pblock->GetValue( ml_diffuse, t, p, ivalid );
623       diffColor = Bound(Color(p.x,p.y,p.z));
624       pblock->GetValue( ml_ambient, t, p2, ivalid );
625       if( lockAD && (p!=p2)){
626          pblock->SetValue( ml_ambient, t, diffColor);
627          ambColor = diffColor;
628       } else {
629          pblock->GetValue( ml_ambient, t, p, ivalid );
630          ambColor = Bound(Color(p.x,p.y,p.z));
631       }
632       pblock->GetValue( ml_diffuse_level, t, diffLevel, ivalid );
633       diffLevel = Bound(diffLevel, 0.0f, 4.0f );
634       pblock->GetValue( ml_diffuse_rough, t, diffRough, ivalid );
635       diffRough = Bound(diffRough);
636 
637       pblock->GetValue( ml_specular1, t, p, ivalid );
638       specColor1 = Bound(Color(p.x,p.y,p.z));
639       pblock->GetValue( ml_specular_level1, t, specLevel1, ivalid );
640       specLevel1 = Bound( specLevel1, 0.0f, 9.99f );
641       pblock->GetValue( ml_glossiness1, t, gloss1, ivalid );
642       gloss1 = Bound( gloss1 );
643       pblock->GetValue( ml_anisotropy1, t, aniso1, ivalid );
644       aniso1 = Bound( aniso1 );
645       pblock->GetValue( ml_orientation1, t, orientation1, ivalid );
646       orientation1 = Bound( orientation1, (float)MIN_ORIENT, (float)MAX_ORIENT );
647 
648       pblock->GetValue( ml_specular2, t, p, ivalid );
649       specColor2 = Bound(Color(p.x,p.y,p.z));
650       pblock->GetValue( ml_specular_level2, t, specLevel2, ivalid );
651       specLevel2 = Bound( specLevel2, 0.0f, 9.99f );
652       pblock->GetValue( ml_glossiness2, t, gloss2, ivalid );
653       gloss2 = Bound( gloss2 );
654       pblock->GetValue( ml_anisotropy2, t, aniso2, ivalid );
655       aniso2 = Bound( aniso2 );
656       pblock->GetValue( ml_orientation2, t, orientation2, ivalid );
657       orientation2 = Bound( orientation2, (float)MIN_ORIENT, (float)MAX_ORIENT );
658 
659       pblock->GetValue( ml_self_illum_amnt, t, selfIllumLevel, ivalid );
660       selfIllumLevel = Bound(selfIllumLevel);
661       pblock->GetValue( ml_self_illum_color, t, p, ivalid );
662       selfIllum = Bound(Color(p.x,p.y,p.z));
663 
664       // also get the non-animatables in case changed from scripter or other pblock accessors
665       pblock->GetValue(ml_ad_lock, t, lockAD, ivalid);
666       pblock->GetValue(ml_ad_texlock, t, lockADTex, ivalid);
667       pblock->GetValue(ml_use_self_illum_color, t, selfIllumClrOn, ivalid);
668 
669    }
670    valid &= ivalid;
671    inUpdate = FALSE;
672 }
673 
Reset()674 void MultiLayerShader::Reset()
675 {
676 // multiLayerCD.MakeAutoParamBlocks(this);   // make and intialize paramblock2
677    ivalid.SetEmpty();
678 
679    SetAmbientClr(Color(0.2f,0.2f,0.2f),0);
680    SetDiffuseClr(Color(0.5f,0.5f,0.5f),0);
681    SetDiffuseLevel( 1.0f,0 );
682    SetDiffuseRough( 0.0f,0 );
683 
684    SetSpecColor1(Color(0.9f,0.9f,0.9f),0);
685    SetSpecLevel1(0.05f,0);
686    SetGlossiness1(.50f,0);
687    SetAnisotropy1(0.0f,0);
688    SetOrientation1(0.0f,0);
689 
690    SetSpecColor2(Color(0.9f,0.9f,0.9f),0);
691    SetSpecLevel2(0.0f,0);
692    SetGlossiness2(.25f,0);
693    SetAnisotropy2(0.0f,0);
694    SetOrientation2(0.0f,0);
695 
696    SetSelfIllumClr(Color(0.0f,0.0f,0.0f),0);
697    SetSelfIllum( 0.0f,0 );
698    SetSelfIllumClrOn( FALSE );
699 
700    SetLockADTex( TRUE );
701    SetLockAD( TRUE );               // > 6/13/02 - 4:48pm --MQM-- was FALSE
702 }
703 
704 
705 
706 //////////////////////////////////////////////////////////////////////////////////////////
707 //
708 // IO Routines
709 //
710 #define SHADER_HDR_CHUNK 0x4000
711 #define SHADER_VERS_CHUNK 0x5300
712 #define SHADER_SELFILLUMCLR_ON_CHUNK   0x5006
713 #define SHADER_LOCKAD_ON_CHUNK   0x5007
714 #define SHADER_LOCKADTEX_ON_CHUNK   0x5008
715 #define SHADER_EXPOSURE_MATERIAL_CONTROL_CHUNK  0x5020
716 
717 // IO
Save(ISave * isave)718 IOResult MultiLayerShader::Save(ISave *isave)
719 {
720 ULONG nb;
721 
722    isave->BeginChunk(SHADER_VERS_CHUNK);
723    int version = CURRENT_MULTI_LAYER_SHADER_VERSION;
724    isave->Write(&version,sizeof(version),&nb);
725    isave->EndChunk();
726 
727    isave->BeginChunk(SHADER_EXPOSURE_MATERIAL_CONTROL_CHUNK);
728    ExposureMaterialControl::Save(isave);
729    isave->EndChunk();
730    return IO_OK;
731 }
732 
733 class MultiLayerShaderCB: public PostLoadCallback {
734    public:
735       MultiLayerShader *s;
736       int loadVersion;
MultiLayerShaderCB(MultiLayerShader * newS,int loadVers)737        MultiLayerShaderCB(MultiLayerShader *newS, int loadVers) { s = newS; loadVersion = loadVers; }
proc(ILoad * iload)738       void proc(ILoad *iload) {
739          // convert old v1 ParamBlock to ParamBlock2
740          s->ReplaceReference(0,
741             UpdateParameterBlock2(MultiLayerShaderPB, MULTI_LAYER_SHADER_NPARAMS, (IParamBlock*)s->pblock, &multiLayer_param_blk));
742 
743          // then set values that were previously stored outside the PB
744          s->pblock->SetValue(ml_use_self_illum_color, 0, s->selfIllumClrOn);
745          s->pblock->SetValue(ml_ad_lock, 0, s->lockAD);
746          s->pblock->SetValue(ml_ad_texlock, 0, s->lockADTex);
747       }
748 };
749 
750 
Load(ILoad * iload)751 IOResult MultiLayerShader::Load(ILoad *iload)
752 {
753    ULONG nb;
754    int id;
755    int version = 0;
756 
757    lockAD = lockADTex = selfIllumClrOn = 0;
758 
759    IOResult res;
760    while (IO_OK==(res=iload->OpenChunk())) {
761       switch(id = iload->CurChunkID())  {
762          case SHADER_VERS_CHUNK:
763             res = iload->Read(&version,sizeof(version), &nb);
764             break;
765          case SHADER_SELFILLUMCLR_ON_CHUNK:
766             selfIllumClrOn = TRUE;
767             break;
768          case SHADER_LOCKAD_ON_CHUNK:
769             lockAD = TRUE;
770             break;
771          case SHADER_LOCKADTEX_ON_CHUNK:
772             lockADTex = TRUE;
773             break;
774          case SHADER_EXPOSURE_MATERIAL_CONTROL_CHUNK:
775             res = ExposureMaterialControl::Load(iload);
776             break;
777       }
778       iload->CloseChunk();
779       if (res!=IO_OK)
780          return res;
781    }
782    if (version < CURRENT_MULTI_LAYER_SHADER_VERSION ) {
783       iload->RegisterPostLoadCallback(new MultiLayerShaderCB(this, version));
784       iload->SetObsolete();
785    }
786 
787    return IO_OK;
788 
789 }
790 
791 
792 ///////////////////////////////////////////////////////////////////////////////////////////
793 // The Shader
794 //
795 // defualt gloss squared, for renormalized controls
796 #define DEFAULT_GLOSS2  0.03f
797 
EvalHiliteCurve2(float x,float y,int layer)798 float MultiLayerShader::EvalHiliteCurve2( float x, float y, int layer )
799 {
800    float g = (layer == 1)? gloss1 : gloss2;
801    float a = (layer == 1)? aniso1 : aniso2;
802    float specLevel = (layer == 1)? specLevel1 : specLevel2;
803 
804    return GaussHiliteCurve2( x, y, specLevel, g, a);
805 
806 }
807 
808 
AffectReflection(ShadeContext & sc,IllumParams & ip,Color & rcol)809 void MultiLayerShader::AffectReflection(ShadeContext &sc, IllumParams &ip, Color &rcol)
810 {
811    //NB kl,aka NL & g cancel out
812 // rcol *= ip.channels[_SPECLEV1].r * ip.channels[_SPECCLR1] * DEFAULT_K_REFL;
813    rcol *= ip.channels[_SPECCLR1] * DEFAULT_K_REFL;
814 }
815 
816 
817 
818 static int stopX = -1;
819 static int stopY = -1;
820 
PreShade(ShadeContext & sc,IReshadeFragment * pFrag)821 void MultiLayerShader::PreShade(ShadeContext& sc, IReshadeFragment* pFrag)
822 {
823 // Point3 U = sc.VectorFrom( Point3( 0.01f, 0.0f, 1.0f ), REF_OBJECT );
824 // U = Normalize( U );
825    Point3 T = GetTangent( sc, 0 );
826    pFrag->AddUnitVecChannel( T );
827 }
828 
PostShade(ShadeContext & sc,IReshadeFragment * pFrag,int & nextTexIndex,IllumParams * ip)829 void MultiLayerShader::PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams* ip)
830 {
831    Point3 T = pFrag->GetUnitVecChannel( nextTexIndex++ );
832    InternalIllum( sc, *ip, &T );
833 }
834 
835 
Illum(ShadeContext & sc,IllumParams & ip)836 void MultiLayerShader::Illum(ShadeContext &sc, IllumParams &ip)
837 {
838    InternalIllum( sc, ip, NULL );
839 }
840 
InternalIllum(ShadeContext & sc,IllumParams & ip,Point3 * pTangent)841 void MultiLayerShader::InternalIllum(ShadeContext &sc, IllumParams &ip, Point3* pTangent )
842 {
843    LightDesc *l;
844    Color lightCol;
845 
846 #ifdef _DEBUG
847    IPoint2 sp = sc.ScreenCoord();
848    if ( sp.x == stopX && sp.y == stopY )
849       sp.x = stopX;
850 #endif
851 
852    for (int i=0; i<sc.nLights; i++) {
853       l = sc.Light(i);
854       float NL, kL;
855       Point3 L;
856       if (l->Illuminate( sc, sc.Normal(), lightCol, L, NL, kL)) {
857          if (l->ambientOnly) {
858             ip.ambIllumOut += lightCol;
859             continue;
860             }
861          if (NL<=0.0f)
862             continue;
863 
864          // specular
865          Color spec(0.0f, 0.0f, 0.0f);
866          if (l->affectSpecular) {
867             Point3 T = (pTangent)? *pTangent : GetTangent( sc, 0 );
868             float g1 = GaussHighlight( ip.channels[_GL1].r, ip.channels[_AN1].r,
869                                  ip.channels[_OR1].r, sc.Normal(), sc.V(), L, T, &NL );
870 
871             Color spec1 = g1 * kL * ip.channels[_SPECLEV1].r * ip.channels[_SPECCLR1] * lightCol;
872             //spec1 = Bound( spec1 );
873 
874             float g2 = GaussHighlight( ip.channels[_GL2].r, ip.channels[_AN2].r,
875                      ip.channels[_OR2].r, sc.Normal(), sc.V(), L, T, &NL );
876 
877             Color spec2 = g2 * kL * ip.channels[_SPECLEV2].r * ip.channels[_SPECCLR2] * lightCol;
878 
879             // composite spec1 over spec2
880             spec = spec1;
881             if (getUseComposite()) {
882                Color rem = 1.0f - Bound( spec1 );
883                spec += rem * spec2;
884             }
885             else {
886                spec += spec2;
887             }
888             ip.specIllumOut += spec;
889 
890          } // end, affect specular
891 
892          // diffuse
893          if (l->affectDiffuse){
894 //          Color d = OrenNayarIllum( ip.N, L, -ip.V, ip.channels[_DIFFROUGH].r * Pi*0.5f, ip.channels[_DIFFCLR], NL );
895 //          d = d * ip.channels[_DIFFLEV].r; // diff lev
896 //          ip.diffIllumOut += kL * d * lightCol;
897             float diffIntens;
898             Color d = OrenNayarIllum( sc.Normal(), L, sc.V(), ip.channels[_DIFFROUGH].r * Pi*0.5f, ip.channels[_DIFFCLR], &diffIntens, NL );
899             d = d * ip.channels[_DIFFLEV].r;
900             ip.diffIllumOut += kL * d * lightCol;
901             ip.diffIllumIntens += kL * diffIntens * Intens(lightCol);
902          }
903 
904       } // end, illuminated
905    } // for each light
906 
907    // Apply mono self illumination
908    if ( ! selfIllumClrOn ){
909       float si = 0.3333333f * (ip.channels[_SI].r + ip.channels[_SI].g + ip.channels[_SI].b);
910 //    float si = ip.channels[_SI].r;
911       if ( si > 0.0f ) {
912          if ( si >= 1.0f ) {
913             ip.selfIllumOut +=  ip.channels[_DIFFCLR];
914             ip.diffIllumOut = Color( 0.0f, 0.0f, 0.0f );
915          } else {
916             ip.selfIllumOut += si * ip.channels[_DIFFCLR];;
917             ip.diffIllumOut *= (1.0f - si); // * ip.channels[_DIFFCLR];
918             // fade the ambient down on si: 5/27/99 ke
919             ip.ambIllumOut *= 1.0f-si;
920          }
921       }
922    } else {
923       // colored self illum,
924       ip.selfIllumOut += ip.channels[_SI];
925    }
926 
927    // now we can multiply by the clrs
928    ip.ambIllumOut *= ip.channels[_AMBCLR];
929 
930    int chan = ip.stdIDToChannel[ ID_RR ];
931    ShadeTransmission(sc, ip, ip.channels[chan], ip.refractAmt);
932    chan = ip.stdIDToChannel[ ID_RL ];
933    ShadeReflection( sc, ip, ip.channels[chan] );
934 
935    if (sc.globContext != NULL && sc.globContext->pToneOp != NULL) {
936       if (isInvertSelfIllum())
937          sc.globContext->pToneOp->RGBToScaled(ip.selfIllumOut);
938       if (isInvertReflect() && (ip.hasComponents & HAS_REFLECT))
939          sc.globContext->pToneOp->RGBToScaled(ip.reflIllumOut);
940       if (isInvertRefract() && (ip.hasComponents & HAS_REFRACT))
941          sc.globContext->pToneOp->RGBToScaled(ip.transIllumOut);
942    }
943 
944    CombineComponents( sc, ip );
945 
946    // get the diffuse intensity...unscramble the wavelength dependence
947 // float rho, diffIntens;
948 // rho = ip.channels[_DIFFCLR].r == 0.0f ? 1.0f : 1.0f / ip.channels[_DIFFCLR].r;
949 // diffIntens = ip.diffIllumOut.r * rho;
950 // rho = ip.channels[_DIFFCLR].g == 0.0f ? 1.0f : 1.0f / ip.channels[_DIFFCLR].g;
951 // diffIntens += ip.diffIllumOut.g * rho;
952 // rho = ip.channels[_DIFFCLR].b == 0.0f ? 1.0f : 1.0f / ip.channels[_DIFFCLR].b;
953 // diffIntens += ip.diffIllumOut.b * rho;
954 // ip.diffIllumIntens = diffIntens * 0.5f;
955 }
956 
957 
958 
959 ///////////////////////// The dialog class //////////////////////////////////
960 class MultiLayerShaderDlg : public ShaderParamDlg {
961 public:
962    MultiLayerShader* pShader;
963    StdMat2* pMtl;
964    HPALETTE hOldPal;
965    HWND     hwmEdit; // window handle of the materials editor dialog
966    IMtlParams* pMtlPar;
967    HWND     hwHilite1;   // the hilite windows
968    HWND     hwHilite2;
969    HWND     hRollup; // Rollup panel
970    TimeValue   curTime;
971    BOOL     valid;
972    BOOL     isActive;
973 
974    IColorSwatch *cs[MULTI_LAYER_NCOLBOX];
975    ISpinnerControl *lev1Spin, *gl1Spin, *an1Spin;
976    ISpinnerControl *lev2Spin, *gl2Spin, *an2Spin;
977    ISpinnerControl *dlevSpin, *droughSpin,*or1Spin, *or2Spin, *trSpin, *siSpin;
978    ICustButton* texMBut[MULTI_LAYER_NMBUTS];
979    TexDADMgr dadMgr;
980 
981    MultiLayerShaderDlg( HWND hwMtlEdit, IMtlParams *pParams );
982    ~MultiLayerShaderDlg();
983 
984    // required for correctly operating map buttons
FindSubTexFromHWND(HWND hw)985    int FindSubTexFromHWND(HWND hw) {
986       for (long i=0; i < MULTI_LAYER_NMBUTS; i++) {
987          if (hw == texMBut[i]->GetHwnd())
988             return texmapFromMBut[i];
989       }
990       return -1;
991    }
992 
993    // Methods
994    INT_PTR PanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam );
ClassID()995    Class_ID ClassID(){ return MultiLayerShaderClassID; }
996 
SetThing(ReferenceTarget * m)997    void SetThing(ReferenceTarget *m){ pMtl = (StdMat2*)m; }
SetThings(StdMat2 * theMtl,Shader * theShader)998    void SetThings( StdMat2* theMtl, Shader* theShader )
999    {  if (pShader) pShader->SetParamDlg(NULL,0);
1000       pShader = (MultiLayerShader*)theShader;
1001       if(pShader) pShader->SetParamDlg(this,0);
1002       pMtl = theMtl;
1003    }
GetThing()1004    ReferenceTarget* GetThing(){ return pMtl; } // mtl is the thing! (for DAD!)
GetShader()1005    Shader* GetShader(){ return pShader; }
1006 
SetTime(TimeValue t)1007    void SetTime(TimeValue t) {
1008       //DS 2/26/99: added interval test to prevent redrawing when not necessary
1009       curTime = t;
1010       if (!pShader->ivalid.InInterval(t)) {
1011          Interval v;
1012          pShader->Update(t,v);
1013          LoadDialog(TRUE);
1014       }
1015    }
KeyAtCurTime(int id)1016    BOOL KeyAtCurTime(int id) { return pShader->KeyAtTime(id,curTime); }
DeleteThis()1017    void DeleteThis() { delete this; }
ActivateDlg(BOOL dlgOn)1018    void ActivateDlg( BOOL dlgOn ){ isActive = dlgOn; }
GetHWnd()1019    HWND GetHWnd(){ return hRollup; }
NotifyChanged()1020    void NotifyChanged(){ pShader->NotifyChanged(); }
1021    void LoadDialog(BOOL draw);
ReloadDialog()1022    void ReloadDialog(){ Interval v; pShader->Update(pMtlPar->GetTime(), v); LoadDialog(FALSE);}
UpdateDialog(ParamID paramId)1023    void UpdateDialog( ParamID paramId ){ ReloadDialog(); }
1024 
UpdateMtlDisplay()1025    void UpdateMtlDisplay(){ pMtlPar->MtlChanged(); } // redraw viewports
1026     void UpdateHilite( long nHilite );
1027    void UpdateColSwatches();
1028    void UpdateMapButtons();
1029    void UpdateOpacity();
1030    void SetLockADTex(BOOL lock);
1031    void SetLockAD(BOOL lock);
1032    void UpdateLockADTex( BOOL passOn);
1033 
SelectEditColor(int i)1034    void SelectEditColor(int i) { cs[ i ]->EditThis(FALSE); }
1035 };
1036 
MultiLayerShaderDlgProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1037 static INT_PTR CALLBACK  MultiLayerShaderDlgProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam) {
1038    MultiLayerShaderDlg *theDlg;
1039    if (msg == WM_INITDIALOG) {
1040       theDlg = (MultiLayerShaderDlg*)lParam;
1041       DLSetWindowLongPtr(hwndDlg, lParam);
1042    } else {
1043        if ( (theDlg = DLGetWindowLongPtr<MultiLayerShaderDlg*>(hwndDlg) ) == NULL )
1044          return FALSE;
1045    }
1046    theDlg->isActive = 1;
1047    BOOL res = theDlg->PanelProc(hwndDlg, msg, wParam, lParam);
1048    theDlg->isActive = 0;
1049    return res;
1050 }
1051 
1052 
CreateParamDialog(HWND hOldRollup,HWND hwMtlEdit,IMtlParams * imp,StdMat2 * theMtl,int rollupOpen,int)1053 ShaderParamDlg* MultiLayerShader::CreateParamDialog(HWND hOldRollup, HWND hwMtlEdit, IMtlParams *imp, StdMat2* theMtl, int rollupOpen, int )
1054 {
1055    Interval v;
1056    Update(imp->GetTime(),v);
1057 
1058    paramDlg = new MultiLayerShaderDlg(hwMtlEdit, imp);
1059    paramDlg->SetThings( theMtl, this  );
1060    int rollupflags = rolloutOpen ? 0  : APPENDROLL_CLOSED;
1061 
1062    LoadStdShaderResources();
1063    if ( hOldRollup ) {
1064       paramDlg->hRollup = imp->ReplaceRollupPage(
1065          hOldRollup,
1066          hInstance,
1067          MAKEINTRESOURCE(IDD_DMTL_BASIC_MULTILAYER1),
1068          MultiLayerShaderDlgProc,
1069          GetString(IDS_KE_MULTI_LAYER_BASIC),   // your name here
1070          (LPARAM)paramDlg ,
1071          // NS: Bugfix 263414 keep the old category and store it for the current rollup
1072          rollupflags|ROLLUP_SAVECAT|ROLLUP_USEREPLACEDCAT
1073          );
1074    } else
1075       paramDlg->hRollup = imp->AddRollupPage(
1076          hInstance,
1077          MAKEINTRESOURCE(IDD_DMTL_BASIC_MULTILAYER1),
1078          MultiLayerShaderDlgProc,
1079          GetString(IDS_KE_MULTI_LAYER_BASIC),
1080          (LPARAM)paramDlg ,
1081          rollupflags
1082          );
1083 
1084    return (ShaderParamDlg*)paramDlg;
1085 }
1086 
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)1087 RefResult MultiLayerShader::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
1088                              PartID& partID, RefMessage message )
1089 {
1090    switch (message) {
1091       case REFMSG_CHANGE:
1092          ivalid.SetEmpty();
1093          if (hTarget == pblock){
1094             // update UI if paramblock changed, possibly from scripter
1095             ParamID changingParam = pblock->LastNotifyParamID();
1096             // reload the dialog if present
1097             if (paramDlg){
1098                paramDlg->UpdateDialog( changingParam );
1099             }
1100          }
1101          break;
1102    }
1103    return(REF_SUCCEED);
1104 }
1105 
1106 
MultiLayerShaderDlg(HWND hwMtlEdit,IMtlParams * pParams)1107 MultiLayerShaderDlg::MultiLayerShaderDlg( HWND hwMtlEdit, IMtlParams *pParams)
1108 {
1109    pMtl = NULL;
1110    pShader = NULL;
1111    hwmEdit = hwMtlEdit;
1112    pMtlPar = pParams;
1113    dadMgr.Init(this);
1114    dlevSpin = droughSpin =lev1Spin = lev2Spin = gl1Spin = an1Spin =gl2Spin = an2Spin = NULL;
1115    or1Spin = or2Spin = trSpin = siSpin = NULL;
1116    hRollup = hwHilite1 = hwHilite2 =NULL;
1117    curTime = pMtlPar->GetTime();
1118 
1119    isActive = valid = FALSE;
1120 
1121    for( long i = 0; i < MULTI_LAYER_NCOLBOX; ++i )
1122       cs[ i ] = NULL;
1123 
1124    for( long i = 0; i < MULTI_LAYER_NMBUTS; ++i )
1125       texMBut[ i ] = NULL;
1126 }
1127 
~MultiLayerShaderDlg()1128 MultiLayerShaderDlg::~MultiLayerShaderDlg()
1129 {
1130    HDC hdc = GetDC(hRollup);
1131    GetGPort()->RestorePalette(hdc, hOldPal);
1132    ReleaseDC(hRollup, hdc);
1133 
1134    if( pShader ) pShader->SetParamDlg(NULL,0);
1135 
1136    for (long i=0; i < MULTI_LAYER_NMBUTS; i++ ){
1137       ReleaseICustButton( texMBut[i] );
1138       texMBut[i] = NULL;
1139    }
1140 
1141    for (long i=0; i<MULTI_LAYER_NCOLBOX; i++)
1142       if (cs[i]) ReleaseIColorSwatch(cs[i]); // mjm - 5.10.99
1143 
1144    ReleaseISpinner(dlevSpin);
1145    ReleaseISpinner(droughSpin);
1146    ReleaseISpinner(lev1Spin);
1147    ReleaseISpinner(lev2Spin);
1148    ReleaseISpinner(gl1Spin);
1149    ReleaseISpinner(an1Spin);
1150    ReleaseISpinner(gl2Spin);
1151    ReleaseISpinner(an2Spin);
1152    ReleaseISpinner(or1Spin);
1153    ReleaseISpinner(or2Spin);
1154    ReleaseISpinner(trSpin);
1155    ReleaseISpinner(siSpin);
1156 
1157    DLSetWindowLongPtr(hRollup, NULL);
1158    DLSetWindowLongPtr(hwHilite1, NULL);
1159    DLSetWindowLongPtr(hwHilite2, NULL);
1160 
1161    if(pShader){
1162       IRollupWindow* pRollup = pMtlPar->GetMtlEditorRollup();
1163       pShader->SetPanelOpen(pRollup->IsPanelOpen(pRollup->GetPanelIndex(hRollup)));
1164    }
1165 
1166    hwHilite1 = hwHilite2 = hRollup = NULL;
1167 }
1168 
1169 
LoadDialog(BOOL draw)1170 void  MultiLayerShaderDlg::LoadDialog(BOOL draw)
1171 {
1172    if (pShader && hRollup) {
1173       dlevSpin->SetValue(FracToPc(pShader->GetDiffuseLevel(0,0)),FALSE);
1174       dlevSpin->SetKeyBrackets(KeyAtCurTime(ml_diffuse_level));
1175       droughSpin->SetValue(FracToPc(pShader->GetDiffuseRough(0,0)),FALSE);
1176       droughSpin->SetKeyBrackets(KeyAtCurTime(ml_diffuse_rough));
1177       lev1Spin->SetValue(FracToPc(pShader->GetSpecLevel1(0,0)),FALSE);
1178       lev1Spin->SetKeyBrackets(KeyAtCurTime(ml_specular_level1));
1179       lev2Spin->SetValue(FracToPc(pShader->GetSpecLevel2(0,0)),FALSE);
1180       lev2Spin->SetKeyBrackets(KeyAtCurTime(ml_specular_level2));
1181 
1182       gl1Spin->SetValue( FracToPc(pShader->GetGlossiness1(0,0)), FALSE);
1183       gl1Spin->SetKeyBrackets(KeyAtCurTime(ml_glossiness1));
1184       gl2Spin->SetValue( FracToPc(pShader->GetGlossiness2(0,0)), FALSE);
1185       gl2Spin->SetKeyBrackets(KeyAtCurTime(ml_glossiness2));
1186 
1187       an1Spin->SetValue( FracToPc(pShader->GetAnisotropy1(0,0)), FALSE);
1188       an1Spin->SetKeyBrackets(KeyAtCurTime(ml_anisotropy1));
1189       an2Spin->SetValue( FracToPc(pShader->GetAnisotropy2(0,0)), FALSE);
1190       an2Spin->SetKeyBrackets(KeyAtCurTime(ml_anisotropy2));
1191 
1192       or1Spin->SetValue( FracToPc(pShader->GetOrientation1(0,0)), FALSE);
1193       or1Spin->SetKeyBrackets(KeyAtCurTime(ml_orientation1));
1194       or2Spin->SetValue( FracToPc(pShader->GetOrientation2(0,0)), FALSE);
1195       or2Spin->SetKeyBrackets(KeyAtCurTime(ml_orientation2));
1196 
1197       trSpin->SetValue(FracToPc(pMtl->GetOpacity( curTime )),FALSE);
1198       trSpin->SetKeyBrackets(pMtl->KeyAtTime(OPACITY_PARAM, curTime));
1199 
1200       //  color selfIllum
1201       BOOL colorSelfIllum = pShader->IsSelfIllumClrOn();
1202       SetCheckBox(hRollup,IDC_SI_COLORON, colorSelfIllum );
1203       if( colorSelfIllum ) {
1204 //       ShowWindow( siSpin->GetHwnd(), SW_HIDE );
1205          ShowWindow( GetDlgItem(hRollup, IDC_SI_EDIT), SW_HIDE );
1206          ShowWindow( GetDlgItem(hRollup, IDC_SI_SPIN), SW_HIDE );
1207          ShowWindow( cs[N_SI_CLR]->GetHwnd(), SW_SHOW );
1208       } else {
1209          // disable the color swatch
1210          ShowWindow( cs[N_SI_CLR]->GetHwnd(), SW_HIDE );
1211          // show self-illum slider
1212 //       ShowWindow( siSpin->GetHwnd(), SW_SHOW );
1213          ShowWindow( GetDlgItem(hRollup, IDC_SI_EDIT), SW_SHOW );
1214          ShowWindow( GetDlgItem(hRollup, IDC_SI_SPIN), SW_SHOW );
1215 
1216          siSpin->SetValue(FracToPc(pShader->GetSelfIllum(0,0)), FALSE);
1217          siSpin->SetKeyBrackets(KeyAtCurTime(ml_self_illum_amnt));
1218       }
1219       CheckButton(hRollup, IDC_LOCK_AD, pShader->GetLockAD() );
1220 
1221       UpdateLockADTex( 0 );
1222       UpdateColSwatches();
1223       UpdateHilite2( hwHilite1, pShader, 1 );
1224       UpdateHilite2( hwHilite2, pShader, 2 );
1225    }
1226 }
1227 
1228 
1229 
1230 static TCHAR* mapStates[] = { _T(" "), _T("m"),  _T("M") };
1231 
UpdateMapButtons()1232 void MultiLayerShaderDlg::UpdateMapButtons()
1233 {
1234 
1235    for ( long i = 0; i < MULTI_LAYER_NMBUTS; ++i ) {
1236       int nMap = texmapFromMBut[ i ];
1237       int state = pMtl->GetMapState( nMap );
1238       texMBut[i]->SetText( mapStates[ state ] );
1239 
1240       TSTR nm   = pMtl->GetMapName( nMap );
1241       texMBut[i]->SetTooltip(TRUE, nm);
1242    }
1243 }
1244 
1245 
UpdateOpacity()1246 void MultiLayerShaderDlg::UpdateOpacity()
1247 {
1248    trSpin->SetValue(FracToPc(pMtl->GetOpacity(curTime)),FALSE);
1249    trSpin->SetKeyBrackets(pMtl->KeyAtTime(OPACITY_PARAM, curTime));
1250 }
1251 
1252 
UpdateColSwatches()1253 void MultiLayerShaderDlg::UpdateColSwatches()
1254 {
1255    cs[0]->SetColor( pShader->GetAmbientClr( curTime ) );
1256    cs[0]->SetKeyBrackets( pShader->KeyAtTime(ml_ambient, curTime) );
1257 
1258    cs[1]->SetColor( pShader->GetDiffuseClr( curTime ) );
1259    cs[1]->SetKeyBrackets( pShader->KeyAtTime(ml_diffuse, curTime) );
1260 
1261    cs[2]->SetColor( pShader->GetSelfIllumClr( curTime ) );
1262    cs[2]->SetKeyBrackets( pShader->KeyAtTime(ml_self_illum_color, curTime) );
1263 
1264    cs[3]->SetColor( pShader->GetSpecColor1( curTime ) );
1265    cs[3]->SetKeyBrackets( pShader->KeyAtTime(ml_specular1, curTime) );
1266 
1267    cs[4]->SetColor( pShader->GetSpecColor2( curTime ) );
1268    cs[4]->SetKeyBrackets( pShader->KeyAtTime(ml_specular2, curTime) );
1269 }
1270 
SetLockAD(BOOL lock)1271 void MultiLayerShaderDlg::SetLockAD(BOOL lock)
1272 {
1273    if (lock) {
1274       if (IDYES!=MessageBox(hwmEdit, GetString(IDS_DS_LOCKAD), GetString(IDS_DS_LOCKCOL), MB_YESNO)) {
1275          CheckButton(hRollup, IDC_LOCK_AD, FALSE);
1276          return;
1277       }
1278       // set ambient color to diffuse
1279       pShader->SetAmbientClr( pShader->GetDiffuseClr(0,0), 0 );
1280       UpdateColSwatches();
1281    }
1282    pShader->SetLockAD(lock);
1283 }
1284 
1285 
UpdateLockADTex(BOOL passOn)1286 void MultiLayerShaderDlg::UpdateLockADTex( BOOL passOn)
1287 {
1288    int lock =  pShader->GetLockADTex();
1289    CheckButton(hRollup, IDC_LOCK_ADTEX, lock);
1290 
1291    ShowWindow(GetDlgItem(hRollup, IDC_MAPON_AM), !lock);
1292    texMBut[ 0 ]->Enable(!lock);
1293 
1294    if ( passOn ) {
1295       pMtl->SyncADTexLock( lock );
1296    }
1297 // UpdateMtlDisplay();
1298 }
1299 
SetLockADTex(BOOL lock)1300 void MultiLayerShaderDlg::SetLockADTex(BOOL lock)
1301 {
1302    pShader->SetLockADTex( lock );
1303    UpdateLockADTex(TRUE); // passon to mtl
1304 // UpdateMtlDisplay();
1305 }
1306 
1307 
ColorIDCToIndex(int idc)1308 static int ColorIDCToIndex(int idc) {
1309    switch (idc) {
1310       case IDC_AMB_CLR:   return 0;
1311       case IDC_DIFF_CLR:  return 1;
1312       case IDC_SI_CLR:    return 2;
1313       case IDC_SPEC_CLR1: return 3;
1314       case IDC_SPEC_CLR2: return 4;
1315       default: return 0;
1316    }
1317 }
1318 
1319 
PanelProc(HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1320 INT_PTR MultiLayerShaderDlg::PanelProc(HWND hwndDlg, UINT msg, WPARAM wParam, LPARAM lParam )
1321 {
1322    int id = LOWORD(wParam);
1323    int code = HIWORD(wParam);
1324     switch (msg) {
1325       case WM_INITDIALOG:
1326          {
1327          HDC theHDC = GetDC(hwndDlg);
1328          hOldPal = GetGPort()->PlugPalette(theHDC);
1329          ReleaseDC(hwndDlg,theHDC);
1330 
1331             cs[0] = GetIColorSwatch(GetDlgItem(hwndDlg, IDC_AMB_CLR),
1332                   pShader->GetAmbientClr(0,0), GetString(IDS_DS_AMBIENT) );
1333 
1334             cs[1] = GetIColorSwatch(GetDlgItem(hwndDlg, IDC_DIFF_CLR),
1335                   pShader->GetDiffuseClr(0,0), GetString(IDS_DS_DIFFUSE) );
1336 
1337             cs[2] = GetIColorSwatch(GetDlgItem(hwndDlg, IDC_SI_CLR),
1338                   pShader->GetSelfIllumClr(0,0), GetString(IDS_KE_SELFILLUM_CLR) );
1339 
1340          cs[3] = GetIColorSwatch(GetDlgItem(hwndDlg, IDC_SPEC_CLR1),
1341                   pShader->GetSpecColor1(0,0), GetString(IDS_KE_SPEC_CLR1) );
1342 
1343             cs[4] = GetIColorSwatch(GetDlgItem(hwndDlg, IDC_SPEC_CLR2),
1344                   pShader->GetSpecColor2(0,0), GetString(IDS_KE_SPEC_CLR2) );
1345 
1346 
1347          hwHilite1 = GetDlgItem(hwndDlg, IDC_HIGHLIGHT1 );
1348          DLSetWindowLongPtr( hwHilite1, Hilite2Layer1WndProc);
1349          hwHilite2 = GetDlgItem(hwndDlg, IDC_HIGHLIGHT2 );
1350          DLSetWindowLongPtr( hwHilite2, Hilite2Layer2WndProc);
1351 
1352          dlevSpin = SetupIntSpinner(hwndDlg, IDC_DIFFLEV_SPIN, IDC_DIFFLEV_EDIT, 0,400, 0);
1353          droughSpin = SetupIntSpinner(hwndDlg, IDC_DIFFROUGH_SPIN, IDC_DIFFROUGH_EDIT, 0,100, 0);
1354          lev1Spin = SetupIntSpinner(hwndDlg, IDC_SPEC_LEV1_SPIN, IDC_SPEC_LEV1_EDIT, 0,999, 0);
1355          gl1Spin = SetupIntSpinner(hwndDlg, IDC_GL1_SPIN, IDC_GL1_EDIT, 0,100, 0);
1356          an1Spin = SetupIntSpinner(hwndDlg, IDC_AN1_SPIN, IDC_AN1_EDIT, 0,100, 0);
1357 
1358          lev2Spin = SetupIntSpinner(hwndDlg, IDC_SPEC_LEV2_SPIN, IDC_SPEC_LEV2_EDIT, 0, 999, 0);
1359          gl2Spin = SetupIntSpinner(hwndDlg, IDC_GL2_SPIN, IDC_GL2_EDIT, 0,100, 0);
1360          an2Spin = SetupIntSpinner(hwndDlg, IDC_AN2_SPIN, IDC_AN2_EDIT, 0,100, 0);
1361 
1362          or1Spin = SetupIntSpinner(hwndDlg, IDC_OR1_SPIN, IDC_OR1_EDIT, -9999, 9999, 0);
1363          or2Spin = SetupIntSpinner(hwndDlg, IDC_OR2_SPIN, IDC_OR2_EDIT, -9999, 9999, 0);
1364          trSpin = SetupIntSpinner(hwndDlg, IDC_TR_SPIN, IDC_TR_EDIT, 0,100, 0);
1365          siSpin = SetupIntSpinner(hwndDlg, IDC_SI_SPIN, IDC_SI_EDIT, 0,100, 0);
1366 
1367          if( pShader->IsSelfIllumClrOn() ) {
1368             // enable the color swatch, disable the spinner
1369             ShowWindow( GetDlgItem(hwndDlg, IDC_SI_EDIT), SW_HIDE );
1370             ShowWindow( GetDlgItem(hwndDlg, IDC_SI_SPIN), SW_HIDE );
1371          } else {
1372             // disable the color swatch
1373             ShowWindow( cs[N_SI_CLR]->GetHwnd(), SW_HIDE );
1374          }
1375 
1376          for (int j=0; j < MULTI_LAYER_NMBUTS; j++) {
1377             texMBut[j] = GetICustButton(GetDlgItem(hwndDlg,texMButtonsIDC[j]));
1378             assert( texMBut[j] );
1379             texMBut[j]->SetRightClickNotify(TRUE);
1380             texMBut[j]->SetDADMgr(&dadMgr);
1381          }
1382 
1383          SetupLockButton(hwndDlg,IDC_LOCK_AD,FALSE);
1384          SetupPadLockButton(hwndDlg,IDC_LOCK_ADTEX, TRUE);
1385 
1386          LoadDialog(TRUE);
1387       }
1388       break;
1389 
1390       case WM_COMMAND:
1391          {
1392          for ( int i=0; i < MULTI_LAYER_NMBUTS; i++) {
1393             if (id == texMButtonsIDC[i]) {
1394                PostMessage(hwmEdit,WM_TEXMAP_BUTTON, texmapFromMBut[i],(LPARAM)pMtl );
1395                UpdateMapButtons();
1396                goto exit;
1397                }
1398             }
1399          }
1400           switch (id) {
1401 
1402             case IDC_LOCK_AD:
1403                SetLockAD(IsButtonChecked(hwndDlg, IDC_LOCK_AD));
1404                UpdateMtlDisplay();
1405                break;
1406 
1407             case IDC_LOCK_ADTEX:{
1408                BOOL on = IsButtonChecked(hwndDlg, IDC_LOCK_ADTEX);
1409                SetLockADTex(on);
1410                UpdateMtlDisplay();
1411             } break;
1412 
1413             case IDC_SI_COLORON:{
1414                int isOn = GetCheckBox(hwndDlg, IDC_SI_COLORON );
1415                pShader->SetSelfIllumClrOn( isOn );
1416                if ( isOn ) {
1417                   // enable the color swatch, disable the spinner
1418                   ShowWindow( GetDlgItem(hwndDlg, IDC_SI_EDIT), SW_HIDE );
1419                   ShowWindow( GetDlgItem(hwndDlg, IDC_SI_SPIN), SW_HIDE );
1420                   ShowWindow( cs[N_SI_CLR]->GetHwnd(), SW_SHOW );
1421                } else {
1422                   // disable the color swatch
1423                   ShowWindow( cs[N_SI_CLR]->GetHwnd(), SW_HIDE );
1424                   ShowWindow( GetDlgItem(hwndDlg, IDC_SI_EDIT), SW_SHOW );
1425                   ShowWindow( GetDlgItem(hwndDlg, IDC_SI_SPIN), SW_SHOW );
1426                }
1427                 NotifyChanged();
1428 //             UpdateMtlDisplay();
1429             }
1430             break;
1431 
1432          }
1433          break;
1434       case CC_COLOR_SEL: {
1435          int id = LOWORD(wParam);
1436          SelectEditColor(ColorIDCToIndex(id));
1437       }
1438       break;
1439       case CC_COLOR_DROP:  {
1440          int id = LOWORD(wParam);
1441          SelectEditColor(ColorIDCToIndex(id));
1442          UpdateMtlDisplay();
1443       }
1444       break;
1445       case CC_COLOR_BUTTONDOWN:
1446          theHold.Begin();
1447        break;
1448       case CC_COLOR_BUTTONUP:
1449          if (HIWORD(wParam)) theHold.Accept(GetString(IDS_DS_PARAMCHG));
1450          else theHold.Cancel();
1451          UpdateMtlDisplay();
1452          break;
1453       case CC_COLOR_CHANGE: {
1454          int id = LOWORD(wParam);
1455          int buttonUp = HIWORD(wParam);
1456          int n = ColorIDCToIndex(id);
1457          if (buttonUp) theHold.Begin();
1458          Color curColor(cs[n]->GetColor());
1459          switch ( n ) {
1460            case 0:   pShader->SetAmbientClr( curColor, curTime );
1461                   if ( pShader->GetLockAD() )
1462                      pShader->SetDiffuseClr(curColor, curTime);
1463               break;
1464            case 1:   pShader->SetDiffuseClr( curColor, curTime );
1465                   if ( pShader->GetLockAD() )
1466                      pShader->SetAmbientClr( curColor, curTime );
1467               break;
1468            case 2:   pShader->SetSelfIllumClr( curColor, curTime ); break;
1469            case 3:   pShader->SetSpecColor1( curColor, curTime ); break;
1470            case 4:   pShader->SetSpecColor2( curColor, curTime ); break;
1471          }
1472          if (buttonUp) {
1473             theHold.Accept(GetString(IDS_DS_PARAMCHG));
1474             NotifyChanged();
1475             // DS: 5/11/99-  this was commented out. I put it back in, because
1476             // it is necessary for the Reset button in the color picker to
1477             // update the viewport.
1478             UpdateMtlDisplay();
1479             }
1480       } break;
1481       case WM_PAINT:
1482          if (!valid) {
1483             valid = TRUE;
1484             ReloadDialog();
1485             }
1486          return FALSE;
1487       case WM_CLOSE:
1488       case WM_DESTROY:
1489          break;
1490       case CC_SPINNER_CHANGE:
1491          if (!theHold.Holding()) theHold.Begin();
1492          switch (id) {
1493             case IDC_DIFFLEV_SPIN:
1494                pShader->SetDiffuseLevel( PcToFrac( dlevSpin->GetIVal() ), curTime );
1495                break;
1496             case IDC_DIFFROUGH_SPIN:
1497                pShader->SetDiffuseRough( PcToFrac( droughSpin->GetIVal() ), curTime );
1498                break;
1499             case IDC_SPEC_LEV1_SPIN:
1500                pShader->SetSpecLevel1( PcToFrac( lev1Spin->GetIVal() ), curTime );
1501                UpdateHilite2( hwHilite1, pShader, 1 );
1502                break;
1503             case IDC_GL1_SPIN:
1504                pShader->SetGlossiness1( PcToFrac( gl1Spin->GetIVal() ), curTime );
1505                UpdateHilite2( hwHilite1, pShader, 1 );
1506                break;
1507             case IDC_AN1_SPIN:
1508                pShader->SetAnisotropy1( PcToFrac( an1Spin->GetIVal() ), curTime );
1509                UpdateHilite2( hwHilite1, pShader, 1 );
1510                break;
1511 
1512             case IDC_GL2_SPIN:
1513                pShader->SetGlossiness2( PcToFrac( gl2Spin->GetIVal() ), curTime );
1514                UpdateHilite2( hwHilite2, pShader, 2 );
1515                break;
1516             case IDC_AN2_SPIN:
1517                pShader->SetAnisotropy2( PcToFrac( an2Spin->GetIVal() ), curTime );
1518                UpdateHilite2( hwHilite2, pShader, 2 );
1519                break;
1520             case IDC_SPEC_LEV2_SPIN:
1521                pShader->SetSpecLevel2( PcToFrac( lev2Spin->GetIVal() ), curTime );
1522                UpdateHilite2( hwHilite2, pShader, 2 );
1523                break;
1524 
1525             case IDC_OR1_SPIN:
1526                pShader->SetOrientation1( PcToFrac(or1Spin->GetIVal()), curTime );
1527                break;
1528             case IDC_OR2_SPIN:
1529                pShader->SetOrientation2( PcToFrac(or2Spin->GetIVal()), curTime );
1530                break;
1531             case IDC_SI_SPIN:
1532                pShader->SetSelfIllum(PcToFrac(siSpin->GetIVal()),curTime);
1533                break;
1534                //***** >>>><<<< required handling for opacity....must be present in all dialogs
1535             case IDC_TR_SPIN:
1536                pMtl->SetOpacity(PcToFrac( trSpin->GetIVal()),curTime);
1537                break;
1538          }
1539 //       UpdateMtlDisplay();
1540       break;
1541 
1542       case CC_SPINNER_BUTTONDOWN:
1543          theHold.Begin();
1544          break;
1545 
1546       case WM_CUSTEDIT_ENTER:
1547       case CC_SPINNER_BUTTONUP:
1548          if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER)
1549             theHold.Accept(GetString(IDS_DS_PARAMCHG));
1550          else
1551             theHold.Cancel();
1552          UpdateMtlDisplay();
1553          break;
1554 
1555     }
1556    exit:
1557    return FALSE;
1558    }
1559 
1560 
1561