1 /*===========================================================================*\
2  |    File: Stucco.cpp
3  |
4  | Purpose: A 3D Map for creating 'stucco' type patterns.
5  |          This is a port of the 3D Studio/DOS SXP by Dan Silva.
6  |
7  | History: Mark Meier, Began 02/05/97.
8  |          MM, Last Change 02/05/97.
9 			Updated to Param Block2 by Peter Watje 12/1/1998
10 \*===========================================================================*/
11 /*===========================================================================*\
12  | Include Files
13 \*===========================================================================*/
14 #include "procmaps.h"
15 #include "iparamm2.h"
16 #include "resource.h"
17 #include "resourceOverride.h"
18 #include "macrorec.h"
19 
20 /*===========================================================================*\
21  | Miscellaneous Defines
22 \*===========================================================================*/
23 
24 #define SHOW_3DMAPS_WITH_2D
25 
26 // The unique ClassID
27 static Class_ID stuccoClassID(STUCCO_CLASS_ID, 0);
28 
29 // This is the number of colors used
30 #define NUM_COLORS 2
31 
32 // This is the number of sub-texmaps used
33 #define NUM_SUB_TEXMAPS 2
34 
35 struct Col24 {
36 	ULONG r, g, b;
37 };
38 
ColorFromCol24(Col24 a)39 static Color ColorFromCol24(Col24 a) {
40 	Color c;
41 	c.r = (float)a.r/255.0f;
42 	c.g = (float)a.g/255.0f;
43 	c.b = (float)a.b/255.0f;
44 	return c;
45 }
46 
Col24FromColor(Color a)47 static Col24 Col24FromColor(Color a) {
48 	Col24 c;
49 	c.r = (ULONG)(a.r*255.0f);
50 	c.g = (ULONG)(a.g*255.0f);
51 	c.b = (ULONG)(a.b*255.0f);
52 	return c;
53 }
54 
55 #define STUCCO_VERS 0xfaaaa3c2
56 
57 #pragma pack(1)
58 struct StuccoState {
59 	ulong version;
60 	float size;
61 	float threshold;
62 	float thickness;
63 	float del;
64 	Col24 col1, col2;
65 };
66 #pragma pack()
67 
68 // These are various resource IDs
69 static int colID[2] = { IDC_COL1, IDC_COL2 };
70 static int subTexId[NUM_SUB_TEXMAPS] = { IDC_TEX1, IDC_TEX2 };
71 static int mapOnId[NUM_SUB_TEXMAPS] = { IDC_MAPON1, IDC_MAPON2 };
72 
73 // Forward references
74 //class Stucco;
75 //class StuccoDlgProc;
76 
77 /*===========================================================================*\
78  | Stucco 3D Texture Map Plug-In Class
79 \*===========================================================================*/
80 class Stucco : public Tex3D {
81 	// This allows the class that manages the UI to access the private
82 	// data members of this class.
83 //	friend class StuccoDlg;
84 
85 	// These are the current colors from the color swatch controls.
86 	Color col[NUM_COLORS];
87 
88 	// These are the parameters managed by the parameter map
89 	float size;
90 	float thresh;
91 	float thick;
92 	float del;
93 	Point3 col1, col2;
94 
95 	// This points to the XYZGen instance used to handle the
96 	// 'Coordinates' rollup in the materials editor.
97 	// This is reference #0 of this class.
98 	XYZGen *xyzGen;
99 	// These are the sub-texmaps.  If these are set by the user
100 	// then the color of our texture is affected by the sub-texmaps
101 	// and not the color swatches.
102 	// These are reference #2 and #3 of this class.
103 	Texmap *subTex[NUM_SUB_TEXMAPS];
104 	// This holds the validity interval of the texmap.
105 	Interval texValidity;
106 	// This is the version of the texture loaded from disk.
107 	int fileVersion;
108 	// This points to the ParamDlg instance used to manage the UI
109 //	StuccoDlg *paramDlg;
110 
111 #ifdef SHOW_3DMAPS_WITH_2D
112 	TexHandle *texHandle;
113 	Interval texHandleValid;
114 #endif
115 
116 	public:
117 		static ParamDlg* xyzGenDlg;
118 	// This is the parameter block which manages the data for the
119 	// spinner and color swatch controls.
120 	// This is reference #1 of this class.
121 		IParamBlock2 *pblock;
122 	// Indicates if a sub-texmap is to be used or not
123 		BOOL mapOn[NUM_SUB_TEXMAPS];
124 
125 		// --- Methods inherited from Animatable ---
ClassID()126 		Class_ID ClassID() { return stuccoClassID; }
SuperClassID()127 		SClass_ID SuperClassID() { return TEXMAP_CLASS_ID; }
GetClassName(TSTR & s)128 		void GetClassName(TSTR& s) { s= GetString(IDS_DS_STUCCO); }
DeleteThis()129 		void DeleteThis() { delete this; }
130 
131 		// We have 4 sub-animatables.  These are the xyzGen,
132 		// the pblock, and the two sub-texmaps
NumSubs()133 		int NumSubs() { return 2+NUM_SUB_TEXMAPS; }
134 		Animatable* SubAnim(int i);
135 		TSTR SubAnimName(int i);
SubNumToRefNum(int subNum)136 		int SubNumToRefNum(int subNum) { return subNum; }
137 
138 		// --- Methods inherited from ReferenceMaker ---
139 		// We have 4 references.  These are the xyzGen,
140 		// the pblock, and the two sub-texmaps
NumRefs()141  		int NumRefs() { return 2+NUM_SUB_TEXMAPS; }
142 		RefTargetHandle GetReference(int i);
143 		void SetReference(int i, RefTargetHandle rtarg);
144 		RefResult NotifyRefChanged(Interval changeInt,
145 			RefTargetHandle hTarget, PartID& partID, RefMessage message);
146 		IOResult Save(ISave *isave);
147 		IOResult Load(ILoad *iload);
148 
149 		// --- Methods inherited from ReferenceTarget ---
150 		RefTargetHandle Clone(RemapDir &remap = DefaultRemapDir());
151 
152 		// --- Methods inherited from MtlBase ---
LocalRequirements(int subMtlNum)153 		ULONG LocalRequirements(int subMtlNum) {
154 			return xyzGen->Requirements(subMtlNum);
155 		}
LocalMappingsRequired(int subMtlNum,BitArray & mapreq,BitArray & bumpreq)156 		void LocalMappingsRequired(int subMtlNum, BitArray & mapreq, BitArray &bumpreq) {
157 			xyzGen->MappingsRequired(subMtlNum,mapreq,bumpreq);
158 		}
159 		void Update(TimeValue t, Interval& ivalid);
160 		void Init();
161 		void Reset();
162 		Interval Validity(TimeValue t);
163 		ParamDlg* CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp);
NumSubTexmaps()164 		int NumSubTexmaps() { return NUM_SUB_TEXMAPS; }
165 		Texmap* GetSubTexmap(int i);
166 		void SetSubTexmap(int i, Texmap *m);
167 		TSTR GetSubTexmapSlotName(int i);
168 		void ReadSXPData(TCHAR *name, void *sxpdata);
169 
170 		// --- Methods inherited from Texmap ---
GetTheXYZGen()171 		XYZGen *GetTheXYZGen() { return xyzGen; }
172 		RGBA EvalColor(ShadeContext& sc);
173 		Point3 EvalNormalPerturb(ShadeContext& sc);
174 
175 #ifdef SHOW_3DMAPS_WITH_2D
DiscardTexHandle()176 		void DiscardTexHandle() {
177 			if (texHandle) {
178 				texHandle->DeleteThis();
179 				texHandle = NULL;
180 				}
181 			}
SupportTexDisplay()182 		BOOL SupportTexDisplay() { return TRUE; }
ActivateTexDisplay(BOOL onoff)183 		void ActivateTexDisplay(BOOL onoff) {
184 			if (!onoff) DiscardTexHandle();
185 			}
186 		DWORD_PTR GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker);
187 #endif SHOW_3DMAPS_WITH_2D
188 
189 		// --- Methods of Stucco ---
190 		Stucco();
~Stucco()191 		~Stucco() {
192 #ifdef SHOW_3DMAPS_WITH_2D
193 			DiscardTexHandle();
194 #endif
195 			}
196 
197 		float Func(Point3 p, float scl);
198 		float EvalFunc(ShadeContext &sc);
199 		void SwapInputs();
200 		void NotifyChanged();
201 		void SetSize(float f, TimeValue t);
202 		void SetThick(float f, TimeValue t);
203 		void SetThresh(float f, TimeValue t);
204 		void SetColor(int i, Color c, TimeValue t);
205 		void ClampFloat(float &f, float min, float max);
206 
207 // JBW: direct ParamBlock access is added
NumParamBlocks()208 		int	NumParamBlocks() { return 1; }					// return number of ParamBlocks in this instance
GetParamBlock(int i)209 		IParamBlock2* GetParamBlock(int i) { return pblock; } // return i'th ParamBlock
GetParamBlockByID(BlockID id)210 		IParamBlock2* GetParamBlockByID(BlockID id) { return (pblock->ID() == id) ? pblock : NULL; } // return id'd ParamBlock
211 		BOOL SetDlgThing(ParamDlg* dlg);
212 
IsLocalOutputMeaningful(ShadeContext & sc)213 		bool IsLocalOutputMeaningful( ShadeContext& sc ) { return true; }
214 
215 };
216 
217 // This is the Class Descriptor for the Stucco 3D Texture plug-in
218 class StuccoClassDesc : public ClassDesc2 {
219 	public:
IsPublic()220 		int 			IsPublic() { return GetAppID() != kAPP_VIZR; }
Create(BOOL loading)221 		void *			Create(BOOL loading) { 	return new Stucco; }
ClassName()222 		const TCHAR *	ClassName() { return GetString(IDS_DS_STUCCO_CDESC); } // mjm - 2.3.99
SuperClassID()223 		SClass_ID		SuperClassID() { return TEXMAP_CLASS_ID; }
ClassID()224 		Class_ID 		ClassID() { return stuccoClassID; }
Category()225 		const TCHAR* 	Category() { return TEXMAP_CAT_3D; }
226 // JBW: new descriptor data accessors added.  Note that the
227 //      internal name is hardwired since it must not be localized.
InternalName()228 		const TCHAR*	InternalName() { return _T("stucco"); }	// returns fixed parsable name (scripter-visible name)
HInstance()229 		HINSTANCE		HInstance() { return hInstance; }			// returns owning module handle
230 
231 };
232 static StuccoClassDesc stuccoCD;
233 
GetStuccoDesc()234 ClassDesc *GetStuccoDesc() { return &stuccoCD; }
235 ParamDlg* Stucco::xyzGenDlg;
236 
237 /*===========================================================================*\
238  | Class to Manage the User Interface in the Materials Editor
239 \*===========================================================================*/
240 /*
241 class StuccoDlg: public ParamDlg {
242 	public:
243 		// This is our UI rollup page window handle in the materials editor
244 		HWND hParamDlg;
245 		// Window handle of the materials editor dialog itself
246 		HWND hMedit;
247 		// Interface for calling methods provided by MAX
248 		IMtlParams *ip;
249 		// The current Stucco being edited.
250 		Stucco *theTex;
251 		// Parameter Map for handling UI controls
252 		IParamMap *pmap;
253 		// Custom buttons for texture maps
254 		ICustButton *iCustButton[NUM_SUB_TEXMAPS];
255 		// Custom conrols for the colors
256 		IColorSwatch *cs[NUM_COLORS];
257 		// This is used inside the SetTime method to only update the UI
258 		// controls when the time slider has changed
259 		TimeValue curTime;
260 		// Point to the XYZGenDlg we use
261 		ParamDlg *xyzGenDlg;
262 		BOOL valid;
263 		BOOL isActive;
264 		TexDADMgr dadMgr;
265 
266 		// --- Methods inherited from ParamDlg ---
267 		Class_ID ClassID();
268 		void SetThing(ReferenceTarget *m);
269 		ReferenceTarget* GetThing();
270 		void SetTime(TimeValue t);
271 		int FindSubTexFromHWND(HWND hw);
272 		void ReloadDialog();
273 		void ActivateDlg(BOOL onOff);
274 		void DeleteThis() { delete this; }
275 
276 		// --- StuccoDlg Methods ---
277 		StuccoDlg(HWND hwMtlEdit, IMtlParams *imp, Stucco *m);
278 		~StuccoDlg();
279 		INT_PTR PanelProc(HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam);
280 		void UpdateSubTexNames();
281 		void LoadDialog();
282 		void UpdateMtlDisplay() { ip->MtlChanged(); }
283 		void Invalidate();
284 };
285 */
286 /*===========================================================================*\
287  | Noise and Lerp Functions
288 \*===========================================================================*/
lerp_color(Col24 * c,Col24 * a,Col24 * b,float f)289 static void lerp_color(Col24 *c, Col24 *a, Col24 *b, float f) {
290 	int alph = (int)(4096*f);
291 	int ialph = 4096-alph;
292 	c->r = (ialph*a->r + alph*b->r)>>12;
293 	c->g = (ialph*a->g + alph*b->g)>>12;
294 	c->b = (ialph*a->b + alph*b->b)>>12;
295 }
296 
297 /*===========================================================================*\
298  | Parameter Map Related Data and Methods
299 \*===========================================================================*/
300 // Parameter block indices
301 /*
302 #define PB_SIZE		0
303 #define PB_THRESH	1
304 #define PB_THICK	2
305 #define PB_COL1		3
306 #define PB_COL2		4
307 */
308 
309 // Spinner limits
310 #define MIN_SIZE 0.001f
311 #define MAX_SIZE 999999999.0f
312 #define MIN_THRESH 0.0f
313 #define MAX_THRESH 1.0f
314 
315 #define MIN_THICK 0.0f
316 #define MAX_THICK 1.0f
317 
318 // Paramter block version number
319 #define STUCCO_PB_VERSION 2
320 
321 enum { stucco_params };  // pblock ID
322 // grad_params param IDs
323 enum
324 {
325 	stucco_size,stucco_thickness,stucco_threshold,
326 	stucco_color1, stucco_color2,
327 	stucco_map1, stucco_map2,
328 	stucco_mapon1,stucco_mapon2,
329 	stucco_coords,	  // access for UVW mapping
330 };
331 
332 static ParamBlockDesc2 stucco_param_blk ( stucco_params, _T("parameters"),  0, &stuccoCD, P_AUTO_CONSTRUCT + P_AUTO_UI, 1,
333 	//rollout
334 	IDD_STUCCO, IDS_DS_STUCCO_PARAMS, 0, 0, NULL,
335 	// params
336 
337 
338 	stucco_size,	_T("size"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_SIZE,
339 		p_default,		20.f,
340 		p_range,		MIN_SIZE, MAX_SIZE,
341 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_SIZE_EDIT,IDC_SIZE_SPIN, 0.1f,
342 		end,
343 	stucco_thickness,	_T("thickness"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_THICKNESS,
344 		p_default,		.15f,
345 		p_range,		MIN_THICK, MAX_THICK,
346 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_THICK_EDIT,IDC_THICK_SPIN, 0.01f,
347 		end,
348 	stucco_threshold,	_T("threshold"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_THRESH,
349 		p_default,		0.57f,
350 		p_range,		MIN_THRESH, MAX_THRESH,
351 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_THRESH_EDIT,IDC_THRESH_SPIN, 0.01f,
352 		end,
353 	stucco_color1,	 _T("color1"),	TYPE_RGBA,				P_ANIMATABLE,	IDS_DS_COL1,
354 		p_default,		Color(0.f, 0.f, 0.0f),
355 		p_ui,			TYPE_COLORSWATCH, IDC_COL1,
356 		end,
357 	stucco_color2,	 _T("color2"),	TYPE_RGBA,				P_ANIMATABLE,	IDS_DS_COL2,
358 		p_default,		Color(0.9f, 0.9f, 0.9f),
359 		p_ui,			TYPE_COLORSWATCH, IDC_COL2,
360 		end,
361 	stucco_map1,		_T("map1"),		TYPE_TEXMAP,			P_OWNERS_REF,	IDS_PW_MAP1,
362 		p_refno,		2,
363 		p_subtexno,		0,
364 		p_ui,			TYPE_TEXMAPBUTTON, IDC_TEX1,
365 		end,
366 	stucco_map2,		_T("map2"),		TYPE_TEXMAP,			P_OWNERS_REF,	IDS_PW_MAP2,
367 		p_refno,		3,
368 		p_subtexno,		1,
369 		p_ui,			TYPE_TEXMAPBUTTON, IDC_TEX2,
370 		end,
371 	stucco_mapon1,	_T("map1On"), TYPE_BOOL,			0,				IDS_PW_MAPON1,
372 		p_default,		TRUE,
373 		p_ui,			TYPE_SINGLECHEKBOX, IDC_MAPON1,
374 		end,
375 	stucco_mapon2,	_T("map2On"), TYPE_BOOL,			0,				IDS_PW_MAPON2,
376 		p_default,		TRUE,
377 		p_ui,			TYPE_SINGLECHEKBOX, IDC_MAPON2,
378 		end,
379 	stucco_coords,		_T("coords"),	TYPE_REFTARG,		P_OWNERS_REF,	IDS_PW_COORDINATES,
380 		p_refno,		0,
381 		end,
382 
383 	end
384 );
385 
386 /*
387 // Array of parameter descriptors
388 static ParamUIDesc paramDesc[] = {
389 	ParamUIDesc(
390 		PB_SIZE,
391 		EDITTYPE_FLOAT,
392 		IDC_SIZE_EDIT,IDC_SIZE_SPIN,
393 		MIN_SIZE, MAX_SIZE,
394 		SPIN_AUTOSCALE),
395 
396 	ParamUIDesc(
397 		PB_THRESH,
398 		EDITTYPE_FLOAT,
399 		IDC_THRESH_EDIT,IDC_THRESH_SPIN,
400 		MIN_THRESH, MAX_THRESH,
401 		SPIN_AUTOSCALE),
402 
403 	ParamUIDesc(
404 		PB_THICK,
405 		EDITTYPE_FLOAT,
406 		IDC_THICK_EDIT,IDC_THICK_SPIN,
407 		MIN_THICK, MAX_THICK,
408 		SPIN_AUTOSCALE),
409 
410 	ParamUIDesc(PB_COL1, TYPE_COLORSWATCH, IDC_COL1),
411 	ParamUIDesc(PB_COL2, TYPE_COLORSWATCH, IDC_COL2)
412 };
413 */
414 // The number of descriptors in the paramDesc array
415 #define PARAMDESC_LENGTH 5
416 
417 // Parameter block parameters
418 static ParamBlockDescID pbdesc[] = {
419 	{ TYPE_FLOAT, NULL, TRUE, stucco_size }, // size
420 	{ TYPE_FLOAT, NULL, TRUE, stucco_threshold }, // thresh
421 	{ TYPE_FLOAT, NULL, TRUE, stucco_thickness }, // thick
422 	{ TYPE_RGBA,  NULL, TRUE, stucco_color1 }, // color 1
423 	{ TYPE_RGBA,  NULL, TRUE, stucco_color2 }  // color 2
424 };
425 // The number of parameters in the parameter block
426 #define PB_LENGTH 5
427 
428 
429 static ParamVersionDesc versions[] = {
430 	ParamVersionDesc(pbdesc,5,1)	// Version 1 params
431 	};
432 
433 // The names of the parameters in the parameter block
434 static int nameIDs[] = {
435 	IDS_DS_SIZE,IDS_DS_THRESH,IDS_DS_THICKNESS,
436 	IDS_DS_COL1, IDS_DS_COL2 };
437 /*
438 // This is the class that allows the sub-map buttons to be processed.
439 class StuccoDlgProc : public ParamMapUserDlgProc {
440 	public:
441 		StuccoDlg *theDlg;
442 		StuccoDlgProc(StuccoDlg *s) { theDlg = s; }
443 		INT_PTR DlgProc(TimeValue t, IParamMap *map,
444 			HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam);
445 		void DeleteThis() { delete this; }
446 };
447 
448 // This is the dialog proc to process the texmap buttons
449 INT_PTR StuccoDlgProc::DlgProc(TimeValue t, IParamMap *map,
450 	HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
451 	theDlg->isActive = TRUE;
452 	BOOL res = theDlg->PanelProc(hWnd, msg, wParam, lParam);
453 	theDlg->isActive = FALSE;
454 	return res;
455 }
456 
457 INT_PTR StuccoDlg::PanelProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam) {
458 	int id = LOWORD(wParam);
459 	int code = HIWORD(wParam);
460     switch (msg) {
461 		case WM_INITDIALOG: {
462 			for (int i = 0; i < NUM_COLORS; i++)
463    				cs[i] = GetIColorSwatch(GetDlgItem(hParamDlg, colID[i]),
464    					theTex->col[i], theTex->GetSubTexmapSlotName(i).data());
465 			for (i = 0; i < NUM_SUB_TEXMAPS; i++) {
466 				iCustButton[i] = GetICustButton(GetDlgItem(hWnd, subTexId[i]));
467 				iCustButton[i]->SetDADMgr(&dadMgr);
468 				SetCheckBox(hWnd, mapOnId[i], theTex->mapOn[i]);
469 			}
470 			return TRUE;
471 		}
472 		break;
473 
474 		case WM_COMMAND:
475 		    switch (id) {
476 				case IDC_TEX1:
477 					PostMessage(hMedit, WM_TEXMAP_BUTTON, 0, (LPARAM)theTex);
478 					break;
479 
480 				case IDC_TEX2:
481 					PostMessage(hMedit, WM_TEXMAP_BUTTON, 1, (LPARAM)theTex);
482 					break;
483 
484 				case IDC_SWAP: {
485 					theTex->SwapInputs();
486 					IParamBlock *pb = (IParamBlock *)pmap->GetParamBlock();
487 					pb->SetValue(PB_COL1, curTime, theTex->col[0]);
488 					pb->SetValue(PB_COL2, curTime, theTex->col[1]);
489 					pmap->Invalidate();
490 					UpdateSubTexNames();
491 					UpdateMtlDisplay();
492 					theTex->NotifyChanged();
493 					}
494 					break;
495 
496 				case IDC_MAPON1:
497 					theTex->mapOn[0] = GetCheckBox(hWnd, id);
498 					theTex->NotifyChanged();
499 					UpdateMtlDisplay();
500 					break;
501 
502 				case IDC_MAPON2:
503 					theTex->mapOn[1] = GetCheckBox(hWnd, id);
504 					theTex->NotifyChanged();
505 					UpdateMtlDisplay();
506 					break;
507 			}
508 			break;
509 
510 		case WM_LBUTTONDOWN: case WM_LBUTTONUP: case WM_MOUSEMOVE:
511 			ip->RollupMouseMessage(hWnd, msg, wParam, lParam);
512 			return FALSE;
513 
514 		case WM_PAINT:
515 			if (!valid) {
516 				valid = TRUE;
517 				ReloadDialog();
518 			}
519 			break;
520 
521 		case WM_CLOSE:
522 			break;
523 
524 		case WM_DESTROY:
525 			break;
526    	}
527 	return FALSE;
528 }
529 */
530 /*===========================================================================*\
531  | StuccoDlg Methods
532 \*===========================================================================*/
533 // --- StuccoDlg Methods ---
534 // Constructor.
535 // This is called from within the Stucco::CreateParamDlg method.  That
536 // method is passed the handle to the materials editor dialog, and an
537 // interface for calling methods of MAX.  These are passed in here and stored.
538 /*
539 StuccoDlg::StuccoDlg(HWND hwMtlEdit, IMtlParams *imp, Stucco *m) {
540 	dadMgr.Init(this);
541 	hMedit = hwMtlEdit;
542 	ip = imp;
543 	theTex = m;
544     valid = FALSE;
545     isActive = FALSE;
546 	curTime = ip->GetTime();
547 
548 	// This call allocates a new instance of the XYZGen class
549 	xyzGenDlg = theTex->xyzGen->CreateParamDlg(hMedit, imp);
550 
551 	// Creates a parameter map to handle the display of texture map
552 	// parameters in the material editor
553 	pmap = CreateMParamMap(paramDesc, PARAMDESC_LENGTH,
554 		theTex->pblock, ip, hInstance, MAKEINTRESOURCE(IDD_STUCCO),
555 		GetString(IDS_DS_STUCCO_PARAMS), 0);
556 
557 	// Save the window handle of the rollup page
558 	hParamDlg = pmap->GetHWnd();
559 
560 	// Establish the dialog proc to handle the custom button controls
561 	pmap->SetUserDlgProc(new StuccoDlgProc(this));
562 }
563 
564 // Destructor.
565 // This is called after the user changes to another sample slot in
566 // the materials editor that does not contain a Stucco texture.
567 // Note that it is not called if they do go to another Stucco -- in
568 // that case, the parameters in the rollup page are updated, but
569 // the entire page is not deleted.  This is accomplished by simply
570 // changing the parameter block pointer (done inside StuccoDlg::SetThing()).
571 StuccoDlg::~StuccoDlg() {
572 	theTex->paramDlg = NULL;
573 	for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
574 		ReleaseICustButton(iCustButton[i]);
575 		iCustButton[i] = NULL;
576 	}
577 	// Delete the XYZGen class we created
578 	xyzGenDlg->DeleteThis();
579 	// Delete the parameter map
580 	DestroyMParamMap(pmap);
581 	pmap = NULL;
582 }
583 
584 // This is called by the DADMgr
585 int StuccoDlg::FindSubTexFromHWND(HWND hw) {
586 	for (int i=0; i<NUM_SUB_TEXMAPS; i++) {
587 		if (hw == iCustButton[i]->GetHwnd()) return i;
588 		}
589 	return -1;
590 	}
591 
592 // This is called when the dialog is loaded to set the names of the
593 // textures displayed
594 void StuccoDlg::UpdateSubTexNames() {
595 	for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
596 		TSTR nm;
597 		Texmap *m = theTex->subTex[i];
598 		if (m)
599 			nm = m->GetFullName();
600 		else
601 			nm = GetString(IDS_DS_NONE);
602 		iCustButton[i]->SetText(nm.data());
603 	}
604 }
605 
606 // Update the dialog display with the values of the texture we are
607 // currently editing.
608 void StuccoDlg::LoadDialog() {
609 	if (theTex) {
610 		Interval ivalid;
611 		theTex->Update(curTime, ivalid);
612 
613 		ISpinnerControl *spin = (ISpinnerControl *)
614 			GetISpinner(GetDlgItem(hParamDlg, IDC_SIZE_SPIN));
615 		spin->SetValue(theTex->size, FALSE);
616 		ReleaseISpinner(spin);
617 
618 		spin = (ISpinnerControl *)
619 			GetISpinner(GetDlgItem(hParamDlg, IDC_THRESH_SPIN));
620 		spin->SetValue(theTex->thresh, FALSE);
621 		ReleaseISpinner(spin);
622 
623 		spin = (ISpinnerControl *)
624 			GetISpinner(GetDlgItem(hParamDlg, IDC_THICK_SPIN));
625 		spin->SetValue(theTex->thick, FALSE);
626 		ReleaseISpinner(spin);
627 
628 		cs[0]->SetColor(theTex->col[0]);
629 		cs[1]->SetColor(theTex->col[1]);
630 
631 		for (int i = 0; i < NUM_SUB_TEXMAPS; i++)
632 			SetCheckBox(hParamDlg, mapOnId[i], theTex->mapOn[i]);
633 
634 		UpdateSubTexNames();
635 	}
636 }
637 
638 // This method invalidates the rollup page so it will get redrawn
639 void StuccoDlg::Invalidate() {
640 	InvalidateRect(hParamDlg, NULL, FALSE);
641 	valid = FALSE;
642 }
643 
644 // --- Methods inherited from ParamDlg ---
645 // Returns the Class_ID of the plug-in this dialog manages
646 Class_ID StuccoDlg::ClassID() {
647 	return stuccoClassID;
648 }
649 
650 // This sets the current texture being edited to the texture passed
651 void StuccoDlg::SetThing(ReferenceTarget *m) {
652 	assert(m->ClassID() == stuccoClassID);
653 	assert(m->SuperClassID() == TEXMAP_CLASS_ID);
654 	if (theTex)
655 		theTex->paramDlg = NULL;
656 
657 	// Set the pointer to the texmap being edited to the one passed.
658 	theTex = (Stucco *)m;
659 
660 	// Point the parameter map parameter block pointer at the
661 	// one that is now being edited.
662 	pmap->SetParamBlock(theTex->pblock);
663 	if (theTex)
664 		theTex->paramDlg = this;
665 
666 	// Let the XYZGen set the new one being edited
667 	xyzGenDlg->SetThing(theTex->xyzGen);
668 
669 	// Update the dialog display with the values of the new texmap.
670 	LoadDialog();
671 }
672 
673 // This returns the current texture being edited
674 ReferenceTarget *StuccoDlg::GetThing() {
675 	return (ReferenceTarget *)theTex;
676 }
677 
678 // This method is called when the current time has changed.
679 // This gives the developer an opportunity to update any user
680 // interface data that may need adjusting due to the change in time.
681 void StuccoDlg::SetTime(TimeValue t) {
682 	Interval ivalid;
683 	if (t != curTime) {
684 		xyzGenDlg->SetTime(t);
685 		curTime = t;
686 		theTex->Update(curTime, ivalid);
687 		LoadDialog();
688 		InvalidateRect(hParamDlg, NULL, 0);
689 	}
690 }
691 
692 // This method should place values into all the parameter dialog's controls,
693 // edit fields etc.
694 void StuccoDlg::ReloadDialog() {
695 	Interval ivalid;
696 	theTex->Update(curTime, ivalid);
697 	LoadDialog();
698 }
699 
700 // This method is called when the dialog box becomes active or inactive.
701 void StuccoDlg::ActivateDlg(BOOL onOff) {
702 	for (int i = 0; i < NUM_COLORS; i++) {
703 		cs[i]->Activate(onOff);
704 	}
705 }
706 */
707 
708 //dialog stuff to get the Set Ref button
709 class StuccoDlgProc : public ParamMap2UserDlgProc {
710 //public ParamMapUserDlgProc {
711 	public:
712 		Stucco *stucco;
StuccoDlgProc(Stucco * m)713 		StuccoDlgProc(Stucco *m) {stucco = m;}
714 		INT_PTR DlgProc(TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam);
DeleteThis()715 		void DeleteThis() {delete this;}
716 	};
717 
718 
719 
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)720 INT_PTR StuccoDlgProc::DlgProc(
721 		TimeValue t,IParamMap2 *map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)
722 	{
723 	switch (msg) {
724 		case WM_COMMAND:
725 			switch (LOWORD(wParam))
726 				{
727 				case IDC_SWAP:
728 					{
729 					stucco = (Stucco*)map->GetParamBlock()->GetOwner();
730 
731 					stucco->SwapInputs();
732 					}
733 				break;
734 				}
735 			break;
736 		}
737 	return FALSE;
738 	}
739 
740 /*===========================================================================*\
741  | Stucco Methods
742 \*===========================================================================*/
743 // --- Methods inherited from Animatable ---
744 // This method returns a pointer to the 'i-th' sub-anim.
SubAnim(int i)745 Animatable* Stucco::SubAnim(int i) {
746 	switch (i) {
747 		case 0: return xyzGen;
748 		case 1: return pblock;
749 		default: return subTex[i-2];
750 	}
751 }
752 
753 // This method returns the name of the 'i-th' sub-anim to appear in track view.
SubAnimName(int i)754 TSTR Stucco::SubAnimName(int i) {
755 	switch (i) {
756 		case 0: return GetString(IDS_DS_COORDS);
757 		case 1: return GetString(IDS_DS_PARAMETERS);
758 		default: return GetSubTexmapTVName(i-2);
759 	}
760 }
761 
762 // --- Methods inherited from ReferenceMaker ---
763 // Return the 'i-th' reference
GetReference(int i)764 RefTargetHandle Stucco::GetReference(int i) {
765 	switch(i) {
766 		case 0: return xyzGen;
767 		case 1:	return pblock ;
768 		default:return subTex[i-2];
769 	}
770 }
771 
772 // Save the 'i-th' reference
SetReference(int i,RefTargetHandle rtarg)773 void Stucco::SetReference(int i, RefTargetHandle rtarg) {
774 	switch(i) {
775 		case 0: xyzGen = (XYZGen *)rtarg; break;
776 		case 1:	pblock = (IParamBlock2 *)rtarg; break;
777 		default: subTex[i-2] = (Texmap *)rtarg; break;
778 	}
779 }
780 
781 // This method is responsible for responding to the change notification
782 // messages sent by the texmap dependants.
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)783 RefResult Stucco::NotifyRefChanged(Interval changeInt,
784 	RefTargetHandle hTarget, PartID& partID, RefMessage message ) {
785 	switch (message) {
786 		case REFMSG_CHANGE:
787 			texValidity.SetEmpty();
788 			if (hTarget == pblock)
789 				{
790 				ParamID changing_param = pblock->LastNotifyParamID();
791 				stucco_param_blk.InvalidateUI(changing_param);
792 #ifdef SHOW_3DMAPS_WITH_2D
793 				if (changing_param != -1)
794 					DiscardTexHandle();
795 #endif
796 				}
797 #ifdef SHOW_3DMAPS_WITH_2D
798 			else if (hTarget == xyzGen)
799 				{
800 				DiscardTexHandle();
801 				}
802 #endif
803 
804 			// One of the texmap dependants have changed.  We set our
805 			// validity interval to empty and invalidate the dialog
806 			// so it gets redrawn.
807 //			texValidity.SetEmpty();
808 //			if (hTarget != xyzGen) {
809 //				if (paramDlg) {
810 //					paramDlg->pmap->Invalidate();
811 //					}
812 //				}
813 			break;
814 
815 /*
816 		case REFMSG_GET_PARAM_DIM: {
817 			// This returns the 'dimension' of the parameter.  This is
818 			// the type and order of magnitude of the parameter.
819 			GetParamDim *gpd = (GetParamDim *)partID;
820 			switch (gpd->index) {
821 				case PB_SIZE:		gpd->dim =  stdWorldDim;
822 					break;
823 				case PB_THRESH:
824 				case PB_THICK:
825 					gpd->dim = defaultDim; break;
826 				case PB_COL1:
827 				case PB_COL2: gpd->dim = stdColor255Dim; break;
828 			}
829 			return REF_STOP;
830 		}
831 
832 		case REFMSG_GET_PARAM_NAME: {
833 			// This returns the name that will appear in track view
834 			// of the parameter.
835 			GetParamName *gpn = (GetParamName *)partID;
836 			gpn->name = GetString(nameIDs[gpn->index]);
837 			return REF_STOP;
838 		}
839 */
840 	}
841 	return(REF_SUCCEED);
842 }
843 
844 // Load/Save Chunk IDs
845 #define MTL_HDR_CHUNK			0x4000
846 #define STUCCO_VERS1_CHUNK		0x4001
847 #define MAPOFF_CHUNK			0x1000
848 #define PARAM2_CHUNK			0x1010
849 
850 // This is called by the system to allow the plug-in to save its data
Save(ISave * isave)851 IOResult Stucco::Save(ISave *isave) {
852 	IOResult res;
853 
854 	// Save the common stuff from the base class
855 	isave->BeginChunk(MTL_HDR_CHUNK);
856 	res = MtlBase::Save(isave);
857 	if (res != IO_OK)
858 		return res;
859 	isave->EndChunk();
860 
861 	isave->BeginChunk(PARAM2_CHUNK);
862 	isave->EndChunk();
863 /*	// Save a version number chunk
864 	isave->BeginChunk(STUCCO_VERS1_CHUNK);
865 	isave->EndChunk();
866 	// Save the on/off status of the sub-texmaps
867 	for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
868 		if (mapOn[i] == 0) {
869 			isave->BeginChunk(MAPOFF_CHUNK+i);
870 			isave->EndChunk();
871 		}
872 	}
873 */
874 	return IO_OK;
875 }
876 
877 class StuccoPostLoad : public PostLoadCallback {
878 	public:
879 		Stucco *n;
880 		BOOL Param1;
StuccoPostLoad(Stucco * ns,BOOL b)881 		StuccoPostLoad(Stucco *ns, BOOL b) {n = ns; Param1 = b;}
proc(ILoad * iload)882 		void proc(ILoad *iload) {
883 			if (Param1)
884 				{
885 				n->pblock->SetValue( stucco_mapon1, 0, n->mapOn[0]);
886 				n->pblock->SetValue( stucco_mapon2, 0, n->mapOn[1]);
887 				}
888 			delete this;
889 
890 
891 			}
892 	};
893 
894 
895 // This is called by the system to allow the plug-in to load its data
Load(ILoad * iload)896 IOResult Stucco::Load(ILoad *iload) {
897 	IOResult res;
898 	int id;
899 	fileVersion = 0;
900 	BOOL Param1 = TRUE;
901 	while (IO_OK == (res = iload->OpenChunk())) {
902 		switch(id = iload->CurChunkID())  {
903 			case MTL_HDR_CHUNK:
904 				// Load the common stuff from the base class
905 				res = MtlBase::Load(iload);
906 				break;
907 			case STUCCO_VERS1_CHUNK:
908 				// Set the version number
909 				fileVersion = 1;
910 				break;
911 			case PARAM2_CHUNK:
912 				// Set the version number
913 				Param1 = FALSE;
914 				break;
915 			case MAPOFF_CHUNK+0:
916 			case MAPOFF_CHUNK+1:
917 				// Set the sub-texmap on/off settings
918 				mapOn[id-MAPOFF_CHUNK] = 0;
919 				break;
920 		}
921 		iload->CloseChunk();
922 		if (res != IO_OK)
923 			return res;
924 	}
925 	// JBW: register old version ParamBlock to ParamBlock2 converter
926 	ParamBlock2PLCB* plcb = new ParamBlock2PLCB(versions, 1, &stucco_param_blk, this, 1);
927 	iload->RegisterPostLoadCallback(plcb);
928 
929 	iload->RegisterPostLoadCallback(new StuccoPostLoad(this,Param1));
930 	return IO_OK;
931 }
932 
933 // --- Methods inherited from ReferenceTarget ---
934 // This method is called to have the plug-in clone itself.
Clone(RemapDir & remap)935 RefTargetHandle Stucco::Clone(RemapDir &remap) {
936 	// Create a new instance of the plug-in class
937 	Stucco *newStucco = new Stucco();
938 
939 	// Copy superclass stuff
940 	*((MtlBase *)newStucco) = *((MtlBase *)this);
941 
942 	// Clone the items we reference
943 	newStucco->ReplaceReference(0, remap.CloneRef(xyzGen));
944 	newStucco->ReplaceReference(1, remap.CloneRef(pblock));
945 	newStucco->col[0] = col[0];
946 	newStucco->col[1] = col[1];
947 	newStucco->size = size;
948 	newStucco->thresh = thresh;
949 	newStucco->thick = thick;
950 	newStucco->texValidity.SetEmpty();
951 	for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
952 		newStucco->subTex[i] = NULL;
953 		newStucco->mapOn[i] = mapOn[i];
954 		if (subTex[i])
955 			newStucco->ReplaceReference(i+2, remap.CloneRef(subTex[i]));
956 		}
957 	BaseClone(this, newStucco, remap);
958 	// Return the new cloned texture
959 	return (RefTargetHandle)newStucco;
960 	}
961 
962 // --- Methods inherited from MtlBase ---
963 // This method is called to return the validity interval of the texmap.
Validity(TimeValue t)964 Interval Stucco::Validity(TimeValue t) {
965 	Interval v;
966 	// Calling Update() sets texValidity.
967 	Update(t, v);
968 	return texValidity;
969 	}
970 
971 #define IN_TO_M(x) (x / 39.370079f)
972 
973 // This method is called to reset the texmap back to its default values.
Init()974 void Stucco::Init() {
975 	// Reset the XYZGen or allocate a new one
976 	if (xyzGen)
977 		xyzGen->Reset();
978 	else
979 		ReplaceReference(0, GetNewDefaultXYZGen());
980 
981 	// Set the inital parameters
982 	SetColor(0, Color(0.0f, 0.0f, 0.0f), TimeValue(0));
983 	SetColor(1, Color(0.9f, 0.9f, 0.9f), TimeValue(0));
984     RegisterDistanceDefault(_T("Stucco Params"), _T("Size"), 20.0f, IN_TO_M(20.0f));
985     float size = GetDistanceDefault(_T("Stucco Params"), _T("Size"));
986     SetSize(size, TimeValue(0));
987 
988 	SetThresh(0.57f, TimeValue(0));
989 	SetThick(0.15f, TimeValue(0));
990 
991 	// Set the validity interval of the texture to empty
992 	texValidity.SetEmpty();
993 	}
994 
Reset()995 void Stucco::Reset() {
996 	stuccoCD.Reset(this, TRUE);	// reset all pb2's
997 	DeleteReference(2);
998 	DeleteReference(3);
999 	Init();
1000 	}
1001 
Stucco()1002 Stucco::Stucco() {
1003 #ifdef SHOW_3DMAPS_WITH_2D
1004 	texHandle = NULL;
1005 #endif
1006 	subTex[0] = subTex[1] = NULL;
1007 	pblock = NULL;
1008 	xyzGen = NULL;
1009 //	paramDlg = NULL;
1010 	mapOn[0] = mapOn[1] = 1;
1011 	stuccoCD.MakeAutoParamBlocks(this);	// make and intialize paramblock2
1012 	Init();
1013 	fileVersion = 0;
1014 	del = 0.1f; // This is a constant for now...
1015 	}
1016 
1017 
1018 #ifdef SHOW_3DMAPS_WITH_2D
GetActiveTexHandle(TimeValue t,TexHandleMaker & thmaker)1019 DWORD_PTR Stucco::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker) {
1020 	if (texHandle) {
1021 		if (texHandleValid.InInterval(t))
1022 			return texHandle->GetHandle();
1023 		else DiscardTexHandle();
1024 		}
1025 	texHandle = thmaker.MakeHandle(GetVPDisplayDIB(t,thmaker,texHandleValid));
1026 	return texHandle->GetHandle();
1027 	}
1028 #endif
1029 
1030 // This method gets called when the material or texture is to be displayed
1031 // in the material editor parameters area.
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)1032 ParamDlg* Stucco::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp) {
1033 	// Allocate a new instance of ParamDlg to manage the UI.  This will
1034 	// create the rollup page in the materials editor.
1035 //	StuccoDlg *stuccoDlg = new StuccoDlg(hwMtlEdit, imp, this);
1036 	// Update the dialog display with the proper values of the texture.
1037 //	stuccoDlg->LoadDialog();
1038 //	paramDlg = stuccoDlg;
1039 //	return stuccoDlg;
1040 	xyzGenDlg = xyzGen->CreateParamDlg(hwMtlEdit, imp);
1041 	IAutoMParamDlg* masterDlg = stuccoCD.CreateParamDlgs(hwMtlEdit, imp, this);
1042 	// add the secondary dialogs to the master
1043 	masterDlg->AddDlg(xyzGenDlg);
1044 	stucco_param_blk.SetUserDlgProc(new StuccoDlgProc(this));
1045 
1046 	return masterDlg;
1047 
1048 
1049 }
1050 
ColrFromCol24(Col24 a)1051 static Color ColrFromCol24(Col24 a) {
1052 	Color c;
1053 	c.r = (float)a.r/255.0f;
1054 	c.g = (float)a.g/255.0f;
1055 	c.b = (float)a.b/255.0f;
1056 	return c;
1057 	}
1058 
1059 
ReadSXPData(TCHAR * name,void * sxpdata)1060 void Stucco::ReadSXPData(TCHAR *name, void *sxpdata) {
1061 	StuccoState *state = (StuccoState*)sxpdata;
1062 	if (state!=NULL && (state->version==STUCCO_VERS)) {
1063 		SetColor(0, ColrFromCol24(state->col1),0);
1064 		SetColor(1, ColrFromCol24(state->col2),0);
1065 		SetSize(state->size,0);
1066 		SetThick(state->thickness,0);
1067 		SetThresh(state->threshold,0);
1068 		del = state->del;
1069 		}
1070 	}
1071 
SetDlgThing(ParamDlg * dlg)1072 BOOL Stucco::SetDlgThing(ParamDlg* dlg)
1073 {
1074 	// JBW: set the appropriate 'thing' sub-object for each
1075 	// secondary dialog
1076 	if ((xyzGenDlg!= NULL) && (dlg == xyzGenDlg))
1077 		xyzGenDlg->SetThing(xyzGen);
1078 	else
1079 		return FALSE;
1080 	return TRUE;
1081 }
1082 
1083 
1084 // This method is called before rendering begins to allow the plug-in
1085 // to evaluate anything prior to the render so it can store this information.
Update(TimeValue t,Interval & ivalid)1086 void Stucco::Update(TimeValue t, Interval& ivalid) {
1087 	if (!texValidity.InInterval(t)) {
1088 		texValidity.SetInfinite();
1089 		xyzGen->Update(t, texValidity);
1090 //		pblock->GetValue(PB_COL1, t, col[0], texValidity);
1091 		pblock->GetValue(stucco_color1, t, col[0], texValidity);
1092 		col[0].ClampMinMax();
1093 //		pblock->GetValue(PB_COL2, t, col[1], texValidity);
1094 		pblock->GetValue(stucco_color2, t, col[1], texValidity);
1095 		col[1].ClampMinMax();
1096 //		pblock->GetValue(PB_SIZE, t, size, texValidity);
1097 		pblock->GetValue(stucco_size, t, size, texValidity);
1098 		ClampFloat(size, MIN_SIZE, MAX_SIZE);
1099 //		pblock->GetValue(PB_THRESH, t, thresh, texValidity);
1100 		pblock->GetValue(stucco_threshold, t, thresh, texValidity);
1101 		ClampFloat(thresh, MIN_THRESH, MAX_THRESH);
1102 //		pblock->GetValue(PB_THICK, t, thick, texValidity);
1103 		pblock->GetValue(stucco_thickness, t, thick, texValidity);
1104 		pblock->GetValue(stucco_mapon1, t, mapOn[0], texValidity);
1105 		pblock->GetValue(stucco_mapon2, t, mapOn[1], texValidity);
1106 		ClampFloat(thick, MIN_THICK, MAX_THICK);
1107 		for (int i = 0; i < NUM_SUB_TEXMAPS; i++) {
1108 			if (subTex[i])
1109 				subTex[i]->Update(t, texValidity);
1110 		}
1111 	}
1112 	ivalid &= texValidity;
1113 }
1114 
ClampFloat(float & f,float min,float max)1115 void Stucco::ClampFloat(float &f, float min, float max) {
1116 	if (f < min) f = min;
1117 	else if (f > max) f = max;
1118 }
1119 
1120 // Returns a pointer to the 'i-th' sub-texmap managed by this texture.
GetSubTexmap(int i)1121 Texmap *Stucco::GetSubTexmap(int i) {
1122 	return subTex[i];
1123 }
1124 
1125 // Stores the 'i-th' sub-texmap managed by the material or texture.
SetSubTexmap(int i,Texmap * m)1126 void Stucco::SetSubTexmap(int i, Texmap *m) {
1127 	ReplaceReference(i+2, m);
1128 	if (i==0)
1129 		{
1130 		stucco_param_blk.InvalidateUI(stucco_map1);
1131 		texValidity.SetEmpty();
1132 		}
1133 	else if (i==1)
1134 		{
1135 		stucco_param_blk.InvalidateUI(stucco_map2);
1136 		texValidity.SetEmpty();
1137 		}
1138 
1139 //	if (paramDlg)
1140 //		paramDlg->UpdateSubTexNames();
1141 }
1142 
1143 // This name appears in the materials editor dialog when editing the
1144 // 'i-th' sub-map.
GetSubTexmapSlotName(int i)1145 TSTR Stucco::GetSubTexmapSlotName(int i) {
1146 	switch(i) {
1147 		case 0:  return GetString(IDS_DS_COL1);
1148 		case 1:  return GetString(IDS_DS_COL2);
1149 		default: return TSTR(_T(""));
1150 	}
1151 }
1152 
1153 
compscl(Point3 dp,float size)1154 static float compscl(Point3 dp, float size) {
1155 	float f;
1156 	float scl = (float)fabs(dp.x);
1157 	if ((f = (float)fabs(dp.y)) > scl)
1158 		scl = f;
1159 	if ((f = (float)fabs(dp.z)) > scl)
1160 		scl = f;
1161 	scl /= size;
1162 	return scl;
1163 	}
1164 
1165 #define CRV  (.2)
1166 #define K   (.5/(1-CRV))
1167 #define K1  (K/CRV)
1168 
1169 /*
1170 STUCCO function
1171 
1172 works off a noise function 'f'in range [0..1.0]
1173 
1174 when f<=threshold returns 0.0;
1175 
1176 state.thickness is the fraction of the remaining interval [thresh..1.0]
1177 taken up by a transition from 0 to 1.0;
1178 Over this interval, a 2nd order curve (piecewise parabolic) is used.
1179 over the first CRV part of the transition its parablolic, then for
1180 the next 1-2*CRV part its linear, then for the last CRV part it's
1181 an inverted parabola.
1182 -------------------------------------------------------
1183 */
Func(Point3 p,float scl)1184 float Stucco::Func(Point3 p, float scl) {
1185 	float f,t;
1186 	f = 0.5f*(noise3(p)+1.0f); /* get number from  0 to 1.0 */
1187 
1188 	if (f <= thresh)
1189 		return(float) 0.0f;
1190 	t = thick+0.5f*scl;
1191 	f = (f-thresh)/t;
1192 	if (f >= 1.0f)
1193 		return (float) (1.0f);
1194 	if (f < CRV) 	{
1195 		return (float) (K1*f*f);
1196 		}
1197 	else
1198 	if (f < (1.0f-CRV)) {
1199 	   return (float) (K*((2.0f*f)-CRV));
1200 		}
1201 	else {
1202 		f = 1.0f-f;
1203 		return (float) (1.0f - K1*(f*f));
1204 		}
1205 	}
1206 
EvalFunc(ShadeContext & sc)1207 float Stucco::EvalFunc(ShadeContext &sc) {
1208 	Point3 p, dp;
1209 	xyzGen->GetXYZ(sc, p, dp);
1210 	if (size == 0.0f)
1211 		size = 0.0001f;
1212 	p /= size;
1213 	float scl = compscl(dp, size);
1214 	return Func(p, scl);
1215 	}
1216 
1217 // --- Methods inherited from Texmap ---
EvalColor(ShadeContext & sc)1218 RGBA Stucco::EvalColor(ShadeContext& sc) {
1219 	float f;
1220 	Point3 p, dp;
1221 
1222 	if (gbufID)
1223 		sc.SetGBufferID(gbufID);
1224 
1225 	xyzGen->GetXYZ(sc, p, dp);
1226 
1227 	if (size == 0.0f)
1228 		size = 0.0001f;
1229 	p /= size;
1230 
1231 	float scl = compscl(dp, size);
1232 	f = Func(p, scl);
1233 
1234 	// If we have sub-texmaps and they are enabled, get the colors from
1235 	// the sub-texmaps, otherwise get them from the color swatch
1236 	RGBA c0 = (mapOn[0]&&subTex[0]) ? subTex[0]->EvalColor(sc): col[0];
1237 	RGBA c1 = (mapOn[1]&&subTex[1]) ? subTex[1]->EvalColor(sc): col[1];
1238 
1239 	Col24 c;
1240 	Col24 col1 = Col24FromColor(c0);
1241 	Col24 col2 = Col24FromColor(c1);
1242 
1243 	lerp_color(&c, &col1, &col2, f);
1244 	return ColorFromCol24(c);
1245 }
1246 
EvalNormalPerturb(ShadeContext & sc)1247 Point3 Stucco::EvalNormalPerturb(ShadeContext& sc) {
1248 	float d,k;
1249 	Point3 p, dp, np;
1250 
1251 	if (gbufID)
1252 		sc.SetGBufferID(gbufID);
1253 
1254 	xyzGen->GetXYZ(sc, p, dp);
1255 
1256 	float scl = compscl(dp, size);
1257 	p /= size;
1258 	d = Func(p, scl);
1259 	k = 0.25f/del;
1260 
1261 	Point3 M[3];
1262 	xyzGen->GetBumpDP(sc,M);
1263 	np.x = (Func(p + del*M[0], scl) - d)*k;
1264 	np.y = (Func(p + del*M[1], scl) - d)*k;
1265 	np.z = (Func(p + del*M[2], scl) - d)*k;
1266 	np = sc.VectorFromNoScale(np,REF_OBJECT);
1267 
1268 	Texmap *sub0 = mapOn[0]?subTex[0]:NULL;
1269 	Texmap *sub1 = mapOn[1]?subTex[1]:NULL;
1270 	if (sub0||sub1) {
1271 		// d((1-k)*a + k*b ) = dk*(b-a) + k*(db-da) + da
1272 		float a,b;
1273 		Point3 da,db;
1274 		if (sub0) {
1275 			a = sub0->EvalMono(sc);
1276 			da = sub0->EvalNormalPerturb(sc);
1277 			}
1278 		else {
1279 			a = Intens(col[0]);
1280 			da = Point3(0.0f,0.0f,0.0f);
1281 			}
1282 		if (sub1) {
1283 			b = sub1->EvalMono(sc);
1284 			db = sub1->EvalNormalPerturb(sc);
1285 			}
1286 		else {
1287 			b = Intens(col[1]);
1288 			db= Point3(0.0f,0.0f,0.0f);
1289 			}
1290 		np = (b-a)*np + d*(db-da) + da;
1291 		}
1292 	else
1293 		np *= Intens(col[1])-Intens(col[0]);
1294 	return np;
1295 }
1296 
1297 // --- Methods of Stucco ---
NotifyChanged()1298 void Stucco::NotifyChanged() {
1299 	NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1300 }
1301 
SwapInputs()1302 void Stucco::SwapInputs() {
1303 	Color t = col[0]; col[0] = col[1]; col[1] = t;
1304 	Texmap *x = subTex[0];  subTex[0] = subTex[1];  subTex[1] = x;
1305 //	pblock->SwapControllers(PB_COL1, PB_COL2);
1306 	pblock->SwapControllers(stucco_color1,0, stucco_color2,0);
1307 	stucco_param_blk.InvalidateUI(stucco_color1);
1308 	stucco_param_blk.InvalidateUI(stucco_color2);
1309 	stucco_param_blk.InvalidateUI(stucco_map1);
1310 	stucco_param_blk.InvalidateUI(stucco_map2);
1311 	macroRec->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("color1"), mr_reftarg, this, mr_prop, _T("color2"), mr_reftarg, this);
1312 	macroRec->FunctionCall(_T("swap"), 2, 0, mr_prop, _T("map1"), mr_reftarg, this, mr_prop, _T("map2"), mr_reftarg, this);
1313 }
1314 
SetColor(int i,Color c,TimeValue t)1315 void Stucco::SetColor(int i, Color c, TimeValue t) {
1316     col[i] = c;
1317 //	pblock->SetValue((i == 0) ? PB_COL1 : PB_COL2, t, c);
1318 	pblock->SetValue((i == 0) ? stucco_color1 : stucco_color2, t, c);
1319 }
1320 
SetThick(float f,TimeValue t)1321 void Stucco::SetThick(float f, TimeValue t) {
1322 	thick = f;
1323 //	pblock->SetValue(PB_THICK, t, f);
1324 	pblock->SetValue(stucco_thickness, t, f);
1325 }
1326 
SetThresh(float f,TimeValue t)1327 void Stucco::SetThresh(float f, TimeValue t) {
1328 	thresh = f;
1329 //	pblock->SetValue(PB_THRESH, t, f);
1330 	pblock->SetValue(stucco_threshold, t, f);
1331 }
1332 
SetSize(float f,TimeValue t)1333 void Stucco::SetSize(float f, TimeValue t) {
1334 	size = f;
1335 //	pblock->SetValue(PB_SIZE, t, f);
1336 	pblock->SetValue(stucco_size, t, f);
1337 }
1338 
1339