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