1 /**********************************************************************
2 *<
3 FILE: CHECKER.CPP
4
5 DESCRIPTION: CHECKER 2D Texture map.
6
7 CREATED BY: Dan Silva
8 Update 11/17 to param block2 by Peter Watje
9
10 HISTORY:
11
12 *> Copyright (c) 1994, All Rights Reserved.
13 **********************************************************************/
14
15 #include "mtlhdr.h"
16 #include "mtlres.h"
17 #include "mtlresOverride.h"
18 #include <bmmlib.h>
19 #include "iparamm2.h"
20 #include "macrorec.h"
21
22 extern HINSTANCE hInstance;
23 #define SHOW_3DMAPS_WITH_2D
24
25 #define NPARAMS 3
26
27 #define NSUBTEX 2
28 #define NCOLS 2
29
30 #define UVGEN_REF 0
31 #define PBLOCK_REF 1
32 #define MAP1_REF 2
33 #define MAP2_REF 3
34
35 #define NUM_REFS 4
36
37 static Class_ID checkerClassID(CHECKER_CLASS_ID,0);
38
39 class Checker;
40
41 // JBW: IDs for ParamBlock2 blocks and parameters
42 // Parameter and ParamBlock IDs
43 enum { checker_params, }; // pblock ID
44 // checker_params param IDs
45 enum
46 {
47 checker_blur, checker_color1, checker_color2,
48 checker_map1, checker_map2,
49 checker_map1_on, checker_map2_on, // main grad params
50 checker_coords, // access for UVW mapping
51
52 };
53
54 class Checker;
55
56 //--------------------------------------------------------------
57 // CheckSampler: checker sample function
58 //--------------------------------------------------------------
59 class CheckSampler: public MapSampler {
60 Checker *check;
61 public:
CheckSampler()62 CheckSampler() { check= NULL; }
CheckSampler(Checker * c)63 CheckSampler(Checker *c) { check= c; }
Set(Checker * c)64 void Set(Checker *c) { check = c; }
65 AColor Sample(ShadeContext& sc, float u,float v);
66 AColor SampleFilter(ShadeContext& sc, float u,float v, float du, float dv);
67 float SampleMono(ShadeContext& sc, float u,float v);
68 float SampleMonoFilter(ShadeContext& sc, float u,float v, float du, float dv);
69 } ;
70
71
72 //--------------------------------------------------------------
73 // Checker: A 2D texture map
74 //--------------------------------------------------------------
75
76 class Checker: public Texmap {
77 friend class CheckerPostLoad;
78 Color col[NCOLS];
79 float blur;
80 UVGen *uvGen; // ref #0
81
82 Texmap* subTex[NSUBTEX]; // More refs
83 TexHandle *texHandle;
84 Interval texHandleValid;
85 Interval ivalid;
86 int rollScroll;
87 CheckSampler mysamp;
88 public:
89 Checker();
~Checker()90 ~Checker() {
91 DiscardTexHandle();
92 }
93 IParamBlock2 *pblock; // ref #1
94 BOOL mapOn[2];
95 static ParamDlg* uvGenDlg;
96 ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
97 void Update(TimeValue t, Interval& valid);
98 void Init();
99 void Reset();
Validity(TimeValue t)100 Interval Validity(TimeValue t) { Interval v; Update(t,v); return ivalid; }
101
102 void SetColor(int i, Color c, TimeValue t);
103 void SetBlur(float f, TimeValue t);
104 void NotifyChanged();
105 void SwapInputs();
106 Bitmap *BuildBitmap(int size);
107
108 // Evaluate the color of map for the context.
109 AColor EvalColor(ShadeContext& sc);
110 float EvalMono(ShadeContext& sc);
111 AColor EvalFunction(ShadeContext& sc, float u, float v, float du, float dv);
112 float MonoEvalFunction(ShadeContext& sc, float u, float v, float du, float dv);
113 float CheckerFunction( float u, float v, float du, float dv);
114 AColor DispEvalFunc( float u, float v);
115
116 // For Bump mapping, need a perturbation to apply to a normal.
117 // Leave it up to the Texmap to determine how to do this.
118 Point3 EvalNormalPerturb(ShadeContext& sc);
119
120 // Methods for interactive display
121 void DiscardTexHandle();
SupportTexDisplay()122 BOOL SupportTexDisplay() { return TRUE; }
123 void ActivateTexDisplay(BOOL onoff);
124 BITMAPINFO* GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono=FALSE, BOOL forceW=0, BOOL forceH=0);
125 DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
GetUVTransform(Matrix3 & uvtrans)126 void GetUVTransform(Matrix3 &uvtrans) { uvGen->GetUVTransform(uvtrans); }
GetTextureTiling()127 int GetTextureTiling() { return uvGen->GetTextureTiling(); }
GetUVWSource()128 int GetUVWSource() { return uvGen->GetUVWSource(); }
GetMapChannel()129 int GetMapChannel () { return uvGen->GetMapChannel(); }
GetTheUVGen()130 UVGen *GetTheUVGen() { return uvGen; }
131
132 // Requirements
LocalRequirements(int subMtlNum)133 ULONG LocalRequirements(int subMtlNum) { return uvGen->Requirements(subMtlNum); }
134
LocalMappingsRequired(int subMtlNum,BitArray & mapreq,BitArray & bumpreq)135 void LocalMappingsRequired(int subMtlNum, BitArray & mapreq, BitArray &bumpreq) {
136 uvGen->MappingsRequired(subMtlNum,mapreq,bumpreq);
137 }
138
139 // Methods to access texture maps of material
NumSubTexmaps()140 int NumSubTexmaps() { return NSUBTEX; }
GetSubTexmap(int i)141 Texmap* GetSubTexmap(int i) {
142 return subTex[i];
143 }
144 void SetSubTexmap(int i, Texmap *m);
145 TSTR GetSubTexmapSlotName(int i);
InitSlotType(int sType)146 void InitSlotType(int sType) { if (uvGen) uvGen->InitSlotType(sType); }
147
ClassID()148 Class_ID ClassID() { return checkerClassID; }
SuperClassID()149 SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
GetClassName(TSTR & s)150 void GetClassName(TSTR& s) { s= GetString(IDS_DS_CHECKER); }
DeleteThis()151 void DeleteThis() { delete this; }
152
NumSubs()153 int NumSubs() { return 2+NSUBTEX; }
154 Animatable* SubAnim(int i);
155 TSTR SubAnimName(int i);
SubNumToRefNum(int subNum)156 int SubNumToRefNum(int subNum) { return subNum; }
157 // JBW: direct ParamBlock access is added
NumParamBlocks()158 int NumParamBlocks() { return 1; } // return number of ParamBlocks in this instance
GetParamBlock(int i)159 IParamBlock2* GetParamBlock(int i) { return pblock; } // return i'th ParamBlock
GetParamBlockByID(BlockID id)160 IParamBlock2* GetParamBlockByID(BlockID id) { return (pblock->ID() == id) ? pblock : NULL; } // return id'd ParamBlock
161 BOOL SetDlgThing(ParamDlg* dlg);
162
163 // From ref
NumRefs()164 int NumRefs() { return 2+NSUBTEX; }
165 RefTargetHandle GetReference(int i);
166 void SetReference(int i, RefTargetHandle rtarg);
167
168 RefTargetHandle Clone(RemapDir &remap = DefaultRemapDir());
169 RefResult NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
170 PartID& partID, RefMessage message );
171
172 // IO
173 BOOL Param1;
174 IOResult Save(ISave *isave);
175 IOResult Load(ILoad *iload);
176
177 // From Texmap
IsLocalOutputMeaningful(ShadeContext & sc)178 bool IsLocalOutputMeaningful( ShadeContext& sc ) { return true; }
179 };
180
181
182
183 int numCheckers = 0;
184 class CheckerClassDesc:public ClassDesc2 {
185 public:
IsPublic()186 int IsPublic() { return 1 /*GetAppID() != kAPP_VIZR*/ ; }
Create(BOOL loading)187 void * Create(BOOL loading) { return new Checker; }
ClassName()188 const TCHAR * ClassName() { return GetString(IDS_DS_CHECKER_CDESC); } // mjm - 2.3.99
SuperClassID()189 SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
ClassID()190 Class_ID ClassID() { return checkerClassID; }
Category()191 const TCHAR* Category() { return TEXMAP_CAT_2D; }
192 // PW: new descriptor data accessors added. Note that the
193 // internal name is hardwired since it must not be localized.
InternalName()194 const TCHAR* InternalName() { return _T("Checker"); } // returns fixed parsable name (scripter-visible name)
HInstance()195 HINSTANCE HInstance() { return hInstance; } // returns owning module handle
196 };
197
198 static CheckerClassDesc checkerCD;
GetCheckerDesc()199 ClassDesc* GetCheckerDesc() { return &checkerCD; }
200
201 ParamDlg* Checker::uvGenDlg;
202
203
204 //-----------------------------------------------------------------------------
205 // Checker
206 //-----------------------------------------------------------------------------
207
208 //JBW: here is the new ParamBlock2 descriptor. There is only one block for Gradients, a per-instance block.
209 // for the moment, some of the parameters a Tab<>s to test the Tab system. Aslo note that all the References kept
210 // kept in a Gradient are mapped here, marked as P_OWNERS_REF so that the paramblock accesses and maintains them
211 // as references on owning Gradient. You need to specify the refno for these owner referencetarget parameters.
212 // I even went so far as to expose the UVW mapping and Texture Output sub-objects this way so that they can be
213 // seen by the scripter and the schema-viewer
214
215 // per instance checker block
216
217 static ParamBlockDesc2 checker_param_blk ( checker_params, _T("parameters"), 0, &checkerCD, P_AUTO_CONSTRUCT + P_AUTO_UI, PBLOCK_REF,
218 //rollout
219 IDD_CHECKER, IDS_DS_CHECKPARMS, 0, 0, NULL,
220 // params
221 checker_blur, _T("soften"), TYPE_FLOAT, P_ANIMATABLE, IDS_DS_CHECK_BLUR,
222 p_default, 0.0,
223 p_range, 0.0, 5.0,
224 p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_BLUR_EDIT, IDC_BLUR_SPIN, 0.01f,
225 end,
226 checker_color1, _T("color1"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_COLOR1,
227 p_default, Color(0,0,0),
228 p_ui, TYPE_COLORSWATCH, IDC_CHECK_COL1,
229 end,
230 checker_color2, _T("color2"), TYPE_RGBA, P_ANIMATABLE, IDS_DS_COLOR2,
231 p_default, Color(1,1,1),
232 p_ui, TYPE_COLORSWATCH, IDC_CHECK_COL2,
233 end,
234 checker_map1, _T("map1"), TYPE_TEXMAP, P_OWNERS_REF, IDS_JW_MAP1,
235 p_refno, MAP1_REF,
236 p_subtexno, 0,
237 p_ui, TYPE_TEXMAPBUTTON, IDC_CHECK_TEX1,
238 end,
239 checker_map2, _T("map2"), TYPE_TEXMAP, P_OWNERS_REF, IDS_JW_MAP2,
240 p_refno, MAP2_REF,
241 p_subtexno, 1,
242 p_ui, TYPE_TEXMAPBUTTON, IDC_CHECK_TEX2,
243 end,
244 checker_map1_on, _T("map1Enabled"), TYPE_BOOL, 0, IDS_JW_MAP1ENABLE,
245 p_default, TRUE,
246 p_ui, TYPE_SINGLECHEKBOX, IDC_CHKMAP1,
247 end,
248 checker_map2_on, _T("map2Enabled"), TYPE_BOOL, 0, IDS_JW_MAP2ENABLE,
249 p_default, TRUE,
250 p_ui, TYPE_SINGLECHEKBOX, IDC_CHKMAP2,
251 end,
252 checker_coords, _T("coords"), TYPE_REFTARG, P_OWNERS_REF, IDS_DS_COORDINATES,
253 p_refno, UVGEN_REF,
254 end,
255 end
256 );
257
258
259
260 //dialog stuff to get the Set Ref button
261 class CheckerDlgProc : public ParamMap2UserDlgProc {
262 //public ParamMapUserDlgProc {
263 public:
264 Checker *check;
CheckerDlgProc(Checker * m)265 CheckerDlgProc(Checker *m) {check = m;}
266 INT_PTR DlgProc(TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
DeleteThis()267 void DeleteThis() {delete this;}
SetThing(ReferenceTarget * m)268 void SetThing(ReferenceTarget *m) {
269 check = (Checker*)m;
270 // ReloadDialog();
271 }
272
273 };
274
275
276
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)277 INT_PTR CheckerDlgProc::DlgProc(
278 TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
279 {
280 switch (msg) {
281 case WM_COMMAND:
282 switch (LOWORD(wParam))
283 {
284 case IDC_CHECK_SWAP:
285 {
286 check->SwapInputs();
287 }
288 }
289 break;
290 }
291 return FALSE;
292 }
293
294 //-----------------------------------------------------------------------------
295 // CheckSampler
296 //-----------------------------------------------------------------------------
SampleFilter(ShadeContext & sc,float u,float v,float du,float dv)297 AColor CheckSampler::SampleFilter(ShadeContext& sc, float u,float v, float du, float dv) {
298 return check->EvalFunction(sc, u, v, du, dv);
299 }
Sample(ShadeContext & sc,float u,float v)300 AColor CheckSampler::Sample(ShadeContext& sc, float u,float v) {
301 return check->EvalFunction(sc, u, v, 0.0f, 0.0f);
302 }
303
SampleMonoFilter(ShadeContext & sc,float u,float v,float du,float dv)304 float CheckSampler::SampleMonoFilter(ShadeContext& sc, float u,float v, float du, float dv) {
305 return check->MonoEvalFunction(sc, u, v, du, dv);
306 }
SampleMono(ShadeContext & sc,float u,float v)307 float CheckSampler::SampleMono(ShadeContext& sc, float u,float v) {
308 return check->MonoEvalFunction(sc, u, v, 0.0f, 0.0f);
309 }
310
311 //-----------------------------------------------------------------------------
312 // Checker
313 //-----------------------------------------------------------------------------
314
315 #define CHECKER_VERSION 1
316
317
318 static int name_id[NPARAMS] = {IDS_DS_CHECK_BLUR,IDS_DS_COLOR1, IDS_DS_COLOR2};
319
320 static ParamBlockDescID pbdesc2[] = {
321 { TYPE_FLOAT, NULL, TRUE,checker_blur }, // blur
322 { TYPE_RGBA, NULL, TRUE,checker_color1 }, // col1
323 { TYPE_RGBA, NULL, TRUE,checker_color2 } // col2
324 };
325
326 static ParamVersionDesc versions[] = {
327 ParamVersionDesc(pbdesc2, 3, 1),
328 };
329
330
Init()331 void Checker::Init() {
332 if (uvGen) uvGen->Reset();
333 else ReplaceReference( 0, GetNewDefaultUVGen());
334 ivalid.SetEmpty();
335 macroRecorder->Disable(); // disable macrorecorder during reset
336 SetColor(checker_color1, Color(0.0f,0.0f,0.0f), TimeValue(0));
337 SetColor(checker_color2, Color(1.0f,1.0f,1.0f), TimeValue(0));
338 SetBlur(.0f, TimeValue(0));
339 mapOn[0] = mapOn[1] = 1;
340 macroRecorder->Enable();
341 }
342
Reset()343 void Checker::Reset() {
344 checkerCD.Reset(this, TRUE); // reset all pb2's
345 DeleteReference(2);
346 DeleteReference(3);
347 Init();
348 }
349
NotifyChanged()350 void Checker::NotifyChanged() {
351 NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
352 }
353
Checker()354 Checker::Checker() {
355 mysamp.Set(this);
356 texHandle = NULL;
357 subTex[0] = subTex[1] = NULL;
358 pblock = NULL;
359 uvGen = NULL;
360 // paramDlg = NULL;
361 checkerCD.MakeAutoParamBlocks(this); // make and intialize paramblock2
362 Init();
363 rollScroll=0;
364 Param1 = FALSE;
365 }
366
367
DiscardTexHandle()368 void Checker::DiscardTexHandle() {
369 if (texHandle) {
370 texHandle->DeleteThis();
371 texHandle = NULL;
372 }
373 }
374
ActivateTexDisplay(BOOL onoff)375 void Checker::ActivateTexDisplay(BOOL onoff) {
376 if (!onoff)
377 DiscardTexHandle();
378 }
379
GetVPDisplayDIB(TimeValue t,TexHandleMaker & thmaker,Interval & valid,BOOL mono,BOOL forceW,BOOL forceH)380 BITMAPINFO* Checker::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH) {
381 Bitmap *bm;
382 Interval v;
383 Update(t,v);
384 bm = BuildBitmap(thmaker.Size());
385 BITMAPINFO *bmi = thmaker.BitmapToDIB(bm,uvGen->SymFlags(),0,forceW,forceH);
386 bm->DeleteThis();
387 valid.SetInfinite();
388 Color ac;
389
390 pblock->GetValue( checker_color1, t, ac, valid);
391 pblock->GetValue( checker_color2, t, ac, valid );
392 float b;
393 pblock->GetValue( checker_blur, t, b, valid );
394 return bmi;
395 }
396
GetActiveTexHandle(TimeValue t,TexHandleMaker & thmaker)397 DWORD_PTR Checker::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker) {
398 if (texHandle) {
399 if (texHandleValid.InInterval(t))
400 return texHandle->GetHandle();
401 else DiscardTexHandle();
402 }
403 texHandle = thmaker.MakeHandle(GetVPDisplayDIB(t,thmaker,texHandleValid));
404 return texHandle->GetHandle();
405 }
406
FlToWord(float r)407 inline UWORD FlToWord(float r) {
408 return (UWORD)(65535.0f*r);
409 }
410
BuildBitmap(int size)411 Bitmap *Checker::BuildBitmap(int size) {
412 float u,v;
413 BitmapInfo bi;
414 bi.SetName(_T("checkerTemp"));
415 bi.SetWidth(size);
416 bi.SetHeight(size);
417 bi.SetType(BMM_TRUE_32);
418 Bitmap *bm = TheManager->Create(&bi);
419 if (bm==NULL) return NULL;
420 PixelBuf l64(size);
421 float d = 1.0f/float(size);
422 v = 1.0f - 0.5f*d;
423 for (int y=0; y<size; y++) {
424 BMM_Color_64 *p64=l64.Ptr();
425 u = 0.0f;
426 for (int x=0; x<size; x++, p64++) {
427 AColor c = DispEvalFunc(u,v);
428 p64->r = FlToWord(c.r);
429 p64->g = FlToWord(c.g);
430 p64->b = FlToWord(c.b);
431 p64->a = 0xffff;
432 u += d;
433 }
434 bm->PutPixels(0,y, size, l64.Ptr());
435 v -= d;
436 }
437 return bm;
438 }
439
440 // This is the integral of a square wave function
sintegral(float x)441 static inline float sintegral(float x) {
442 float f = (float)floor(x);
443 return (float)(f*0.5f + fmax(0.0f,(x-f)-.5f));
444 }
445
CheckerFunction(float u,float v,float du,float dv)446 float Checker::CheckerFunction(float u, float v, float du, float dv) {
447 du = blur+du;
448 dv = blur+dv;
449 float hdu = du*.5f;
450 float hdv = dv*.5f;
451 // DS 10/31/00: changed "||" to "&&" to avoid divide by zero when du or dv is zero (# 266070)
452 if (du!=0.0f&&dv!=0.0f) {
453 float s = (sintegral(u+hdu)-sintegral(u-hdu))/du;
454 float t = (sintegral(v+hdv)-sintegral(v-hdv))/dv;
455 return s*t + (1.0f-s)*(1.0f-t);
456 }
457 else {
458 u = u - (float)floor(u);
459 v = v - (float)floor(v);
460 return ((u>.5f)^(v>.5f))?0.0f:1.0f;
461 }
462 }
463
464 // simplified evaluation for interactive render
DispEvalFunc(float u,float v)465 AColor Checker::DispEvalFunc( float u, float v) {
466 float a = CheckerFunction(u,v,0.0f, 0.0f);
467 if (a==0.0f) return col[0];
468 else if (a==1.0f)return col[1];
469 else return a*col[1] + (1.0f-a)*col[0];
470 }
471
472
473 // This function should only be called for samples within the 0,1
474 // box, so a lot of this complication is not necessary.
EvalFunction(ShadeContext & sc,float u,float v,float du,float dv)475 AColor Checker::EvalFunction(ShadeContext& sc, float u, float v, float du, float dv) {
476 float a = CheckerFunction(u,v,du,dv);
477 if (a<=.0005f)
478 return mapOn[0]&&subTex[0] ? subTex[0]->EvalColor(sc): col[0];
479 else if (a>=.9995f)
480 return mapOn[1]&&subTex[1] ? subTex[1]->EvalColor(sc): col[1];
481 else {
482 AColor c0 = mapOn[0]&&subTex[0] ? subTex[0]->EvalColor(sc): col[0];
483 AColor c1 = mapOn[1]&&subTex[1] ? subTex[1]->EvalColor(sc): col[1];
484 return a*c1 + (1.0f-a)*c0;
485 }
486 }
487
488
489 // This function should only be called for samples within the 0,1
490 // box, so a lot of this complication is not necessary.
MonoEvalFunction(ShadeContext & sc,float u,float v,float du,float dv)491 float Checker::MonoEvalFunction(ShadeContext& sc, float u, float v, float du, float dv) {
492 float a = CheckerFunction(u,v,du,dv);
493 if (a<=.0005f)
494 {
495 float level;
496 level = mapOn[0]&&subTex[0] ? subTex[0]->EvalMono(sc): Intens(col[0]);
497 return level;
498 }
499 else if (a>=.9995f)
500 return mapOn[1]&&subTex[1] ? subTex[1]->EvalMono(sc): Intens(col[1]);
501 else {
502 float c0 = mapOn[0]&&subTex[0] ? subTex[0]->EvalMono(sc): Intens(col[0]);
503 float c1 = mapOn[1]&&subTex[1] ? subTex[1]->EvalMono(sc): Intens(col[1]);
504 return a*c1 + (1.0f-a)*c0;
505 }
506 }
507
508 static AColor black(0.0f,0.0f,0.0f,0.0f);
509
EvalColor(ShadeContext & sc)510 AColor Checker::EvalColor(ShadeContext& sc) {
511 if (!sc.doMaps) return black;
512 if (gbufID) sc.SetGBufferID(gbufID);
513 return uvGen->EvalUVMap(sc,&mysamp);
514 }
515
EvalMono(ShadeContext & sc)516 float Checker::EvalMono(ShadeContext& sc) {
517 if (!sc.doMaps) return 0.0f;
518 if (gbufID) sc.SetGBufferID(gbufID);
519 return uvGen->EvalUVMapMono(sc,&mysamp);
520 }
521
EvalNormalPerturb(ShadeContext & sc)522 Point3 Checker::EvalNormalPerturb(ShadeContext& sc) {
523 Point3 dPdu, dPdv;
524 if (!sc.doMaps) return Point3(0,0,0);
525 if (gbufID) sc.SetGBufferID(gbufID);
526 uvGen->GetBumpDP(sc,dPdu,dPdv);
527 Point2 dM = uvGen->EvalDeriv(sc,&mysamp);
528 Point3 np = dM.x*dPdu+dM.y*dPdv;
529
530
531 Texmap *sub0 = mapOn[0]?subTex[0]:NULL;
532 Texmap *sub1 = mapOn[1]?subTex[1]:NULL;
533 if (sub0||sub1) {
534 // d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da)
535 float a,b,k;
536 Point3 da,db;
537 Point2 UV, dUV;
538 uvGen->GetUV(sc, UV,dUV);
539 k = CheckerFunction(UV.x, UV.y, dUV.x, dUV.y);
540 if (sub0) {
541 a = sub0->EvalMono(sc);
542 da = sub0->EvalNormalPerturb(sc);
543 }
544 else {
545 a = Intens(col[0]);
546 da = Point3(0.0f,0.0f,0.0f);
547 }
548 if (sub1) {
549 b = sub1->EvalMono(sc);
550 db = sub1->EvalNormalPerturb(sc);
551 }
552 else {
553 b = Intens(col[1]);
554 db= Point3(0.0f,0.0f,0.0f);
555 }
556 np = (b-a)*np + k*(db-da);
557 }
558 else
559 np *= Intens(col[1])-Intens(col[0]);
560 return np;
561 }
562
Clone(RemapDir & remap)563 RefTargetHandle Checker::Clone(RemapDir &remap) {
564 Checker *mnew = new Checker();
565 *((MtlBase*)mnew) = *((MtlBase*)this); // copy superclass stuff
566 mnew->ReplaceReference(0,remap.CloneRef(uvGen));
567 mnew->ReplaceReference(1,remap.CloneRef(pblock));
568 mnew->col[0] = col[0];
569 mnew->col[1] = col[1];
570 mnew->blur = blur;
571 mnew->ivalid.SetEmpty();
572 for (int i = 0; i<NSUBTEX; i++) {
573 mnew->subTex[i] = NULL;
574 mnew->mapOn[i] = mapOn[i];
575 if (subTex[i])
576 mnew->ReplaceReference(i+2,remap.CloneRef(subTex[i]));
577 }
578 BaseClone(this, mnew, remap);
579 return (RefTargetHandle)mnew;
580 }
581
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)582 ParamDlg* Checker::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp) {
583
584 // JBW: the main difference here is the automatic creation of a ParamDlg by the new
585 // ClassDesc2 function CreateParamDlgs(). This mirrors the way BeginEditParams()
586 // can be redirected to the ClassDesc2 for automatic ParamMap2 management. In this
587 // case a special subclass of ParamDlg, AutoMParamDlg, defined in IParamm2.h, is
588 // created. It can act as a 'master' ParamDlg to which you can add any number of
589 // secondary dialogs and it will make sure all the secondary dialogs are kept
590 // up-to-date and deleted as necessary.
591
592 // create the rollout dialogs
593 uvGenDlg = uvGen->CreateParamDlg(hwMtlEdit, imp);
594 IAutoMParamDlg* masterDlg = checkerCD.CreateParamDlgs(hwMtlEdit, imp, this);
595 // add the secondary dialogs to the master
596 masterDlg->AddDlg(uvGenDlg);
597 //attach a dlg proc to handle the swap button
598 checker_param_blk.SetUserDlgProc(new CheckerDlgProc(this));
599
600 return masterDlg;
601 }
602
603
SetDlgThing(ParamDlg * dlg)604 BOOL Checker::SetDlgThing(ParamDlg* dlg)
605 {
606 // JBW: set the appropriate 'thing' sub-object for each
607 // secondary dialog
608 if (dlg == uvGenDlg)
609 uvGenDlg->SetThing(uvGen);
610 else
611 return FALSE;
612 return TRUE;
613 }
614
615
616
617
Update(TimeValue t,Interval & valid)618 void Checker::Update(TimeValue t, Interval& valid) {
619
620 if (Param1) //this is a hack to fix old 2.5 files check boxes
621 {
622 pblock->SetValue( checker_map1_on, 0, mapOn[0]);
623 pblock->SetValue( checker_map2_on, 0, mapOn[1]);
624 Param1 = FALSE;
625 }
626
627 if (!ivalid.InInterval(t)) {
628 ivalid.SetInfinite();
629 uvGen->Update(t,ivalid);
630 pblock->GetValue( checker_color1, t, col[0], ivalid );
631 col[0].ClampMinMax();
632 pblock->GetValue( checker_color2, t, col[1], ivalid );
633 col[1].ClampMinMax();
634 pblock->GetValue( checker_blur, t, blur, ivalid );
635 pblock->GetValue( checker_map1_on, t, mapOn[0], ivalid);
636 pblock->GetValue( checker_map2_on, t, mapOn[1], ivalid);
637
638 for (int i=0; i<NSUBTEX; i++) {
639 if (subTex[i])
640 subTex[i]->Update(t,ivalid);
641 }
642 }
643 valid &= ivalid;
644 }
645
646
SetColor(int i,Color c,TimeValue t)647 void Checker::SetColor(int i, Color c, TimeValue t) {
648 if (i== checker_color1)
649 col[0] = c;
650 else col[1] = c;
651
652 pblock->SetValue( i, t, c);
653 }
654
SwapInputs()655 void Checker::SwapInputs() {
656 Color t = col[0]; col[0] = col[1]; col[1] = t;
657 Texmap *x = subTex[0]; subTex[0] = subTex[1]; subTex[1] = x;
658 pblock->SwapControllers(checker_color1,0,checker_color2,0);
659 checker_param_blk.InvalidateUI(checker_color1);
660 checker_param_blk.InvalidateUI(checker_color2);
661 checker_param_blk.InvalidateUI(checker_map1);
662 checker_param_blk.InvalidateUI(checker_map2);
663 macroRecorder->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("color1"), mr_reftarg, this, mr_prop, _T("color2"), mr_reftarg, this);
664 macroRecorder->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("map1"), mr_reftarg, this, mr_prop, _T("map2"), mr_reftarg, this);
665 }
666
SetBlur(float f,TimeValue t)667 void Checker::SetBlur(float f, TimeValue t) {
668 blur = f;
669 pblock->SetValue( checker_blur, t, f);
670 }
671
GetReference(int i)672 RefTargetHandle Checker::GetReference(int i) {
673 switch(i) {
674 case 0: return uvGen;
675 case 1: return pblock ;
676 default:return subTex[i-2];
677 }
678 }
679
SetReference(int i,RefTargetHandle rtarg)680 void Checker::SetReference(int i, RefTargetHandle rtarg) {
681 switch(i) {
682 case 0: uvGen = (UVGen *)rtarg; break;
683 case 1: pblock = (IParamBlock2 *)rtarg; break;
684 default: subTex[i-2] = (Texmap *)rtarg; break;
685 }
686 }
687
SetSubTexmap(int i,Texmap * m)688 void Checker::SetSubTexmap(int i, Texmap *m) {
689 ReplaceReference(i+2,m);
690 if (i==0)
691 {
692 checker_param_blk.InvalidateUI(checker_map1);
693 ivalid.SetEmpty();
694 }
695 else if (i==1)
696 {
697 checker_param_blk.InvalidateUI(checker_map2);
698 ivalid.SetEmpty();
699 }
700
701 }
702
GetSubTexmapSlotName(int i)703 TSTR Checker::GetSubTexmapSlotName(int i) {
704 switch(i) {
705 case 0: return TSTR(GetString(IDS_DS_COLOR1));
706 case 1: return TSTR(GetString(IDS_DS_COLOR2));
707 default: return TSTR(_T(""));
708 }
709 }
710
SubAnim(int i)711 Animatable* Checker::SubAnim(int i) {
712 switch (i) {
713 case 0: return uvGen;
714 case 1: return pblock;
715 default: return subTex[i-2];
716 }
717 }
718
SubAnimName(int i)719 TSTR Checker::SubAnimName(int i) {
720 switch (i) {
721 case 0: return TSTR(GetString(IDS_DS_COORDINATES));
722 case 1: return TSTR(GetString(IDS_DS_PARAMETERS));
723 default: return GetSubTexmapTVName(i-2);
724 }
725 }
726
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)727 RefResult Checker::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
728 PartID& partID, RefMessage message ) {
729 switch (message) {
730 case REFMSG_CHANGE:
731 {
732 ivalid.SetEmpty();
733 if (hTarget == pblock)
734 {
735 // see if this message came from a changing parameter in the pblock,
736 // if so, limit rollout update to the changing item and update any active viewport texture
737 ParamID changing_param = pblock->LastNotifyParamID();
738 // if (hTarget != uvGen && hTarget != pblock )
739 checker_param_blk.InvalidateUI(changing_param);
740 if (changing_param != -1)
741 DiscardTexHandle();
742 }
743 break;
744 }
745 case REFMSG_UV_SYM_CHANGE:
746 DiscardTexHandle();
747 break;
748 }
749 return(REF_SUCCEED);
750 }
751
752
753 #define MTL_HDR_CHUNK 0x4000
754 #define MAPOFF_CHUNK 0x1000
755 #define PARAM2_CHUNK 0x1010
756
Save(ISave * isave)757 IOResult Checker::Save(ISave *isave) {
758 IOResult res;
759 // Save common stuff
760 isave->BeginChunk(MTL_HDR_CHUNK);
761 res = MtlBase::Save(isave);
762 if (res!=IO_OK) return res;
763 isave->EndChunk();
764
765 isave->BeginChunk(PARAM2_CHUNK);
766 isave->EndChunk();
767
768 return IO_OK;
769 }
770
771
772 //watje
773 class CheckerPostLoadCallback:public PostLoadCallback
774 {
775 public:
776 Checker *s;
CheckerPostLoadCallback(Checker * r)777 CheckerPostLoadCallback(Checker *r) {s=r;}
778 void proc(ILoad *iload);
779 };
780
781 /*
782 void CheckerPostLoadCallback::proc(ILoad *iload)
783 {
784
785 if (s->Param1)
786 {
787 s->pblock->SetValue( checker_map1_on, 0, s->mapOn[0]);
788 s->pblock->SetValue( checker_map2_on, 0, s->mapOn[1]);
789 }
790
791 delete this;
792
793 }
794 */
795
796
Load(ILoad * iload)797 IOResult Checker::Load(ILoad *iload) {
798 // ULONG nb;
799 IOResult res;
800 int id;
801 Param1 = TRUE;
802 while (IO_OK==(res=iload->OpenChunk())) {
803 switch(id=iload->CurChunkID()) {
804 case MTL_HDR_CHUNK:
805 res = MtlBase::Load(iload);
806 break;
807 case MAPOFF_CHUNK+0:
808 case MAPOFF_CHUNK+1:
809 mapOn[id-MAPOFF_CHUNK] = 0;
810 break;
811 case PARAM2_CHUNK:
812 Param1 = FALSE;
813 break;
814 }
815 iload->CloseChunk();
816 if (res!=IO_OK)
817 return res;
818 }
819
820 // JBW: register old version ParamBlock to ParamBlock2 converter
821 ParamBlock2PLCB* plcb = new ParamBlock2PLCB(versions, 1, &checker_param_blk, this, PBLOCK_REF);
822 iload->RegisterPostLoadCallback(plcb);
823
824 //copy loaded values into the new param block
825 // CheckerPostLoadCallback* checkerplcb = new CheckerPostLoadCallback(this);
826 // iload->RegisterPostLoadCallback(checkerplcb);
827
828 return IO_OK;
829 }
830