1 #include "stdafx.h"
2 #pragma hdrstop
3 
4 #include "..\material\GameMaterial.h"
5 #include "..\material\BlenderListLoader.h"
6 
7 #include "macrorec.h"
8 
9 class XRayMtlClassDesc:public ClassDesc2 {
10 public:
IsPublic()11 	int 			IsPublic		()				{ return 1; }
Create(BOOL loading)12 	void *			Create			(BOOL loading)	{ return new XRayMtl(loading); }
ClassName()13 	const TCHAR *	ClassName		()				{ return GetString(IDS_CLASS_NAME); }
SuperClassID()14 	SClass_ID		SuperClassID	()				{ return MATERIAL_CLASS_ID; }
ClassID()15 	Class_ID 		ClassID			()				{ return XRAYMTL_CLASS_ID; }
Category()16 	const TCHAR* 	Category		()				{ return GetString(IDS_CATEGORY);  }
17 	// JBW: new descriptor data accessors added.  Note that the
18 	//      internal name is hardwired since it must not be localized.
InternalName()19 	const TCHAR*	InternalName	()				{ return _T("S.T.A.L.K.E.R.Mtl"); }		// returns fixed parsable name (scripter-visible name)
HInstance()20 	HINSTANCE		HInstance		()				{ return hInstance; }			// returns owning module handle
21 };
22 
23 static XRayMtlClassDesc stdmtl2CD;
GetXRayMtlDesc()24 ClassDesc2* GetXRayMtlDesc() { return &stdmtl2CD;  }
25 
26 ShaderParamDlg* XRayMtl::pShaderDlg;
27 IAutoMParamDlg* XRayMtl::xrayDlg;
28 IAutoMParamDlg* XRayMtl::masterDlg;
29 IAutoMParamDlg* XRayMtl::texmapDlg;
30 IAutoMParamDlg* XRayMtl::extendedDlg;
31 IAutoMParamDlg* XRayMtl::samplingDlg;
32 HWND			XRayMtl::curHwmEdit;
33 IMtlParams*	    XRayMtl::curImp;
34 Tab<ClassDesc*> XRayMtl::shaderList;
35 Tab<ClassDesc*> XRayMtl::samplerList;
36 LPSTR_vec		XRayMtl::EShaders;
37 LPSTR_vec		XRayMtl::CShaders;
38 LPSTR_vec		XRayMtl::GameMtls;
39 
40 /////////////////////////////////////////////////////////////////////////
41 // utility function
Min(float a,float b)42 IC float Min( float a, float b ) { return (a < b) ? a : b; }
Min(float a,float b,float c)43 IC float Min( float a, float b, float c ) { return (a < b) ? Min(a,c) : Min(b,c); }
Min(Color & c)44 IC float Min( Color& c ){ return Min( c.r, c.g, c.b ); }
Max(float a,float b)45 IC float Max( float a, float b ) { return (a < b) ? b : a; }
Max(float a,float b,float c)46 IC float Max( float a, float b, float c ) { return (a < b) ? Max( b, c ) : Max(a,c); }
Max(Color & c)47 IC float Max( Color& c ){ return Max( c.r, c.g, c.b ); }
48 
LBound(float x,float min=0.0f)49 IC float LBound( float x, float min = 0.0f ){ return x < min ? min : x; }
LBound(Color & c,float min=0.0f)50 IC Color LBound( Color& c, float min = 0.0f )
51 { return Color( LBound(c.r, min), LBound(c.g, min), LBound(c.b, min) ); }
UBound(float x,float max=1.0f)52 IC float UBound( float x, float max = 1.0f ){ return x > max ? max : x; }
UBound(Color & c,float max=1.0f)53 IC Color UBound( Color& c, float max = 1.0f )
54 { return Color( UBound(c.r,max), UBound(c.g,max), UBound(c.b,max) ); }
55 
Bound(float x,float min=0.0f,float max=1.0f)56 IC float Bound( float x, float min = 0.0f, float max = 1.0f ){ return x < min? min:( x > max? max : x); }
Bound(Color & c,float min=0.0f,float max=1.0f)57 IC Color Bound( Color& c, float min = 0.0f, float max = 1.0f ){
58 	return Color( Bound(c.r,min,max), Bound(c.r,min,max), Bound(c.r,min,max) );
59 }
BoundInPlace(AColor & c,float min=0.0f,float max=1.0f)60 IC void BoundInPlace( AColor& c , float min = 0.0f, float max = 1.0f ){
61 	if( c.r > max ) c.r = max; else if( c.r < min ) c.r = min;
62 	if( c.g > max ) c.g = max; else if( c.g < min ) c.g = min;
63 	if( c.b > max ) c.b = max; else if( c.b < min ) c.b = min;
64 	if( c.a > max ) c.a = max; else if( c.a < min ) c.a = min;
65 }
66 /////////////////////////////////////////////////////////////////////////
67 
68 /////////////////////////////////////////////////////////////////////////
69 //	Material Texture Channels
70 //
71 #define MTL_NTEXMAPS	4
72 
73 
74 // channels ids needed by shader
75 #define _BUMP		0
76 #define _REFLECT	1
77 #define _REFRACT	2
78 #define _DISPLACE	3
79 
80 // channel names
81 static int mtlChannelNameIDS[] = {
82 	IDS_DS_BU, IDS_DS_RL, IDS_DS_RR, IDS_DS_DP,
83 };
84 
85 // what channel corresponds to the stdMat ID's
86 static int mtlStdIDToChannel[N_ID_CHANNELS] = { -1, -1, -1, -1, -1,	-1,   -1, -1, 0, 1, 2, 3  };
87 
88 // internal non-local parsable channel map names
89 static TCHAR* mtlChannelInternalNames[STD2_NMAX_TEXMAPS] = {
90 	_T("bumpMap"), _T("reflectionMap"), _T("refractionMap"), _T("displacementMap"),
91 		_T(""),	_T(""),	_T(""),	_T(""),
92 
93 		_T(""),	_T(""),	_T(""),	_T(""),
94 		_T(""),	_T(""),	_T(""),	_T(""),
95 
96 		_T(""),	_T(""),	_T(""),	_T(""),
97 		_T(""),	_T(""),	_T(""),	_T(""),
98 };
99 
100 // sized for nmax textures
101 static int mtlChannelType[STD2_NMAX_TEXMAPS] = {
102 	BUMP_CHANNEL, REFL_CHANNEL, REFR_CHANNEL, DISP_CHANNEL,
103 		UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL,
104 
105 		UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL,
106 		UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL,
107 		UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL,
108 		UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL, UNSUPPORTED_CHANNEL,
109 };
110 
111 
112 static IReshading::ReshadeRequirements chooseReshade[3][3] = {
113 	{ IReshading::RR_None,
114 		IReshading::RR_NeedPreshade,
115 		IReshading::RR_NeedReshade  },		// RR_None
116 	{ IReshading::RR_NeedPreshade,
117 	IReshading::RR_NeedPreshade,
118 	IReshading::RR_NeedPreshade },		// RR_NeedPreshade
119 	{ IReshading::RR_NeedReshade,
120 	IReshading::RR_NeedPreshade,
121 	IReshading::RR_NeedReshade  },		// RR_NeedReshade
122 };
123 
124 #define NO_UPDATE	-2
125 
126 // parameter setter callback, reflect any ParamBlock-mediated param setting in instance data members.
127 // Since standard2 keeps many parameters as instance data members, these setter callbacks
128 // are implemented to reduce changes to existing code
129 
130 class ShaderPBAccessor : public PBAccessor
131 {
132 public:
Set(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)133 	void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
134 	{
135 		XRayMtl* m = (XRayMtl*)owner;
136 		switch (id)
137 		{
138 			// use item data to unscramble sorted lists
139 		case std2_shader_type: {
140 			ClassDesc* pCD = XRayMtl::GetShaderCD(v.i);
141 			if (pCD && m->GetShaderIndx() != NO_UPDATE )
142 			{
143 				m->SwitchShader(pCD);
144 				m->shaderId = v.i;
145 			}
146 							   } break;
147 		case std2_shader_by_name: {
148 			for (int i = 0; i < XRayMtl::NumShaders(); i++)
149 			{
150 				ClassDesc* pCD = XRayMtl::GetShaderCD(i);
151 				if (_tcsicmp(pCD->ClassName(), v.s) == 0)
152 				{
153 					m->pb_shader->SetValue(std2_shader_type, 0, i);
154 					break;
155 				}
156 			}
157 								  } break;
158 		case std2_wire:
159 			m->SetFlag(NEWSTDMTL_WIRE, v.i); break;
160 		case std2_two_sided:
161 			m->SetFlag(NEWSTDMTL_2SIDE, v.i); break;
162 		case std2_face_map:
163 			m->SetFlag(NEWSTDMTL_FACEMAP, v.i); break;
164 		case std2_faceted:
165 			m->SetFlag(NEWSTDMTL_FACETED, v.i); break;
166 		}
167 	}
168 
Get(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t,Interval & valid)169 	void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval& valid)    // get into v
170 	{
171 		XRayMtl* m = (XRayMtl*)owner;
172 		switch (id)
173 		{
174 		case std2_shader_by_name: {
175 			ClassDesc* pCD = XRayMtl::GetShaderCD(m->shaderId);
176 			if (pCD)
177 				v.s = (TCHAR*)pCD->ClassName();
178 								  } break;
179 		}
180 	}
181 };
182 static ShaderPBAccessor shaderPBAccessor;
183 
184 // shader rollout dialog proc
185 class ShaderDlgProc : public ParamMap2UserDlgProc
186 {
187 public:
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)188 	BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
189 	{
190 		switch (msg)
191 		{
192 		case WM_INITDIALOG:
193 			//  load the shader dropdown
194 			HWND hwndShader = GetDlgItem(hWnd, IDC_SHADER);
195 			SendMessage(hwndShader, CB_RESETCONTENT, 0L, 0L);
196 			for (int i = 0; i < XRayMtl::NumShaders(); i++) {
197 				ClassDesc* pClassD = XRayMtl::GetShaderCD(i);
198 				int n = SendMessage(hwndShader, CB_ADDSTRING, 0L, (LPARAM)(pClassD->ClassName()) );
199 				SendMessage(hwndShader, CB_SETITEMDATA, n, (LPARAM)pClassD );
200 			}
201 			return TRUE;
202 		}
203 		return FALSE;
204 	}
DeleteThis()205 	void DeleteThis() { }
206 };
207 
208 
209 static ShaderDlgProc shaderDlgProc;
210 
211 // shader parameters
212 static ParamBlockDesc2 std2_shader_blk ( std2_shader, _T("newShaderParameters"),  0, &stdmtl2CD, P_AUTO_CONSTRUCT + P_AUTO_UI, SHADER_PB_REF,
213 										//rollout
214 										IDD_DMTL_SHADER4, IDS_KE_SHADER, 0, 0, &shaderDlgProc,
215 										// params
216 										std2_shader_type, _T("shaderType"), TYPE_INT, 				0, 		IDS_JW_SHADERTYPE,
217 										p_default, 		3,
218 										p_ui, 			TYPE_INTLISTBOX, IDC_SHADER, 0,
219 										p_accessor,		&shaderPBAccessor,
220 										end,
221 										std2_wire, 		_T("wire"), 		TYPE_BOOL, 				0, 		IDS_DS_WIREFRAME,
222 										p_default, 		FALSE,
223 										p_ui, 			TYPE_SINGLECHEKBOX, IDC_WIRE,
224 										p_accessor,		&shaderPBAccessor,
225 										end,
226 										std2_two_sided, 	_T("twoSided"), TYPE_BOOL, 				0, 		IDS_JW_TWOSIDED,
227 										p_default, 		FALSE,
228 										p_ui, 			TYPE_SINGLECHEKBOX, IDC_2SIDE,
229 										p_accessor,		&shaderPBAccessor,
230 										end,
231 										std2_face_map, 	_T("faceMap"), 		TYPE_BOOL, 				0, 		IDS_JW_FACEMAP,
232 										p_default, 		FALSE,
233 										p_ui, 			TYPE_SINGLECHEKBOX, IDC_FACE_MAP,
234 										p_accessor,		&shaderPBAccessor,
235 										end,
236 										std2_faceted, 		_T("faceted"), 		TYPE_BOOL, 			0, 		IDS_KE_FACETED,
237 										p_default, 		FALSE,
238 										p_ui, 			TYPE_SINGLECHEKBOX, IDC_FACETED,
239 										p_accessor,		&shaderPBAccessor,
240 										end,
241 										std2_shader_by_name, _T("shaderByName"), TYPE_STRING, 		0, 		IDS_JW_SHADERBYNAME,
242 										p_accessor,		&shaderPBAccessor,
243 										end,
244 										end
245 										);
246 
247 ////////////////////////
248 // Extended Rollout
249 class ExtendedPBAccessor : public PBAccessor
250 {
251 public:
Set(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)252 	void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
253 	{
254 		XRayMtl* m = (XRayMtl*)owner;
255 		IParamMap2* map = m->pb_extended ? m->pb_extended->GetMap() : NULL;
256 
257 		switch (id)
258 		{
259 		case std2_opacity_type:
260 			m->SetFlag(NEWSTDMTL_ADD_TRANSP, v.i == 2);
261 			m->SetFlag(NEWSTDMTL_FILT_TRANSP, v.i == 0);
262 			if (map != NULL)
263 			{
264 				map->Show(std2_filter_color, v.i == 0);
265 				map->Show(std2_ep_filter_map, v.i == 0);
266 				m->UpdateTexmaps();
267 				m->UpdateLockADTex(FALSE);
268 			}
269 			break;
270 		case std2_opacity:
271 			m->opacity = v.f;
272 			if (m->pShader->GetParamDlg())
273 				m->pShader->GetParamDlg()->UpdateOpacity();
274 			break;
275 		case std2_filter_color:
276 			m->filter = *v.p; break;
277 		case std2_falloff_type:
278 			m->SetFlag(NEWSTDMTL_FALLOFF_OUT, v.i == 1); break;
279 		case std2_falloff_amnt:
280 			m->opfall = v.f; break;
281 		case std2_ior:
282 			m->ioRefract = v.f; break;
283 
284 		case std2_wire_size:
285 			m->wireSize = v.f; break;
286 		case std2_wire_units:
287 			m->SetFlag(NEWSTDMTL_WIRE_UNITS, v.i == 1); break;
288 
289 		case std2_apply_refl_dimming:
290 			m->dimReflect = v.i; break;
291 		case std2_dim_lvl:
292 			m->dimIntens = v.f; break;
293 		case std2_refl_lvl:
294 			m->dimMult = v.f; break;
295 		}
296 	}
297 };
298 
299 static ExtendedPBAccessor extendedPBAccessor;
300 
301 // extra rollout dialog proc
302 class ExtraDlgProc : public ParamMap2UserDlgProc
303 {
304 public:
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)305 	BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
306 	{
307 		switch (msg)
308 		{
309 		case WM_INITDIALOG:{
310 			XRayMtl* m = (XRayMtl*)map->GetParamBlock()->GetOwner();
311 			m->UpdateExtraParams( m->GetShader()->SupportStdParams() );
312 			return TRUE;
313 						   }
314 		}
315 		return FALSE;
316 	}
DeleteThis()317 	void DeleteThis() { }
318 };
319 
320 static ExtraDlgProc extraDlgProc;
321 
322 // extended parameters
323 static ParamBlockDesc2 std2_extended_blk ( std2_extended, _T("extendedParameters"),  0, &stdmtl2CD, P_AUTO_CONSTRUCT + P_AUTO_UI, EXTENDED_PB_REF,
324 										  //rollout
325 										  IDD_DMTL_EXTRA6, IDS_DS_EXTRA, 0, APPENDROLL_CLOSED, &extraDlgProc,
326 										  // params
327 										  std2_opacity_type,  _T("opacityType"), 	TYPE_INT, 		0, 				IDS_JW_OPACITYTYPE,
328 										  p_default, 		0,
329 										  p_range, 		0, 2,
330 										  p_ui, 			TYPE_RADIO, 	3, IDC_TR_SUB2, IDC_TR_SUB, IDC_TR_ADD,
331 										  p_accessor,		&extendedPBAccessor,
332 										  end,
333 										  std2_opacity,		_T("opacity"), 	TYPE_PCNT_FRAC, 	P_ANIMATABLE, 	IDS_DS_OPACITY,
334 										  p_default, 		0.0,
335 										  p_range, 		0.0, 100.0,   // UI us in the shader rollout
336 										  p_accessor,		&extendedPBAccessor,
337 										  end,
338 										  std2_filter_color, 	 _T("filterColor"), TYPE_RGBA, 		P_ANIMATABLE, 	IDS_DS_FILTER,
339 										  p_default, 		Color(0, 0, 0),
340 										  p_ui, 			TYPE_COLORSWATCH, IDC_FILTER_CS,
341 										  p_accessor,		&extendedPBAccessor,
342 										  end,
343 										  std2_ep_filter_map, _T("filterMap"), 	TYPE_TEXMAP, 	P_SUBTEX + P_NO_AUTO_LABELS, IDS_JW_FILTERMAP,
344 										  p_subtexno, 	ID_FI,
345 										  p_ui, 			TYPE_TEXMAPBUTTON, IDC_MAPON_FI,
346 										  p_accessor,		&extendedPBAccessor,
347 										  end,
348 										  std2_falloff_type,  _T("opacityFallOffType"), 	TYPE_INT, 	0, 			IDS_JW_FALLOFFTYPE,
349 										  p_default, 		0,
350 										  p_range, 		0, 1,
351 										  p_ui, 			TYPE_RADIO, 	2, IDC_TF_IN, IDC_TF_OUT,
352 										  p_accessor,		&extendedPBAccessor,
353 										  end,
354 										  std2_falloff_amnt, _T("opacityFallOff"), TYPE_PCNT_FRAC, 	P_ANIMATABLE, 	IDS_DS_FALLOFF,
355 										  p_default, 		0.0,
356 										  p_range, 		0.0, 100.0,
357 										  p_ui, 			TYPE_SPINNER, EDITTYPE_INT, IDC_TF_EDIT, IDC_TF_SPIN, 0.1,
358 										  p_accessor,		&extendedPBAccessor,
359 										  end,
360 										  std2_ior, 			_T("ior"), 			TYPE_FLOAT, 	P_ANIMATABLE, 	IDS_DS_IOR,
361 										  p_default, 		1.5,
362 										  p_range, 		0.0, 10.0,
363 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_IOR_EDIT, IDC_IOR_SPIN, 0.01,
364 										  p_accessor,		&extendedPBAccessor,
365 										  end,
366 										  std2_wire_size, 		_T("wireSize"), TYPE_FLOAT, 	P_ANIMATABLE, 	IDS_DS_WIRESZ,
367 										  p_default, 		1.0,
368 										  p_range, 		0.0, 100.0,
369 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_WIRE_EDIT, IDC_WIRE_SPIN, 1.0,
370 										  p_accessor,		&extendedPBAccessor,
371 										  end,
372 										  std2_wire_units, 	_T("wireUnits"), 	TYPE_INT, 		0, 				IDS_JW_WIREUNITS,
373 										  p_default, 		0,
374 										  p_range, 		0, 1,
375 										  p_ui, 			TYPE_RADIO, 	2, IDC_PIXELS, IDC_UNITS,
376 										  p_accessor,		&extendedPBAccessor,
377 										  end,
378 										  std2_apply_refl_dimming, _T("applyReflectionDimming"), 	TYPE_BOOL, 	0, 	IDS_JW_APPLYREFDIM,
379 										  p_default, 		FALSE,
380 										  p_ui, 			TYPE_SINGLECHEKBOX, IDC_DIM_REFL,
381 										  p_accessor,		&extendedPBAccessor,
382 										  end,
383 										  std2_dim_lvl, 		_T("dimLevel"), 		TYPE_FLOAT, 	P_ANIMATABLE, 	IDS_DS_DIMLEV,
384 										  p_default, 		0.0,
385 										  p_range, 		0.0, 1.0,
386 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_DIM_AMT, IDC_DIM_AMTSPIN, 0.01,
387 										  p_accessor,		&extendedPBAccessor,
388 										  end,
389 										  std2_refl_lvl, 		_T("reflectionLevel"), 	TYPE_FLOAT, 	P_ANIMATABLE, 	IDS_DS_DIMMULT,
390 										  p_default, 		1.0,
391 										  p_range, 		0.1, 10.0,
392 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_DIM_MULT, IDC_DIM_MULTSPIN, 0.01,
393 										  p_accessor,		&extendedPBAccessor,
394 										  end,
395 										  end
396 										  );
397 
398 ///////////////////////////////////////////////////////////////////////////////////
399 // Sampling Rollout
400 //
401 class SamplingPBAccessor : public PBAccessor
402 {
403 public:
Set(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)404 	void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
405 	{
406 		XRayMtl* m = (XRayMtl*)owner;
407 		macroRecorder->Disable();
408 		switch (id)
409 		{
410 		case std2_ssampler: {
411 			ClassDesc* pCD = XRayMtl::GetSamplerCD(v.i);
412 			if (pCD && m->GetSamplerIndx() != NO_UPDATE )
413 			{
414 				m->SwitchSampler(pCD);
415 				//					m->samplerId = v.i;
416 			}
417 							} break;
418 		case std2_ssampler_by_name: {
419 			for (int i = 0; i < XRayMtl::NumSamplers(); i++)
420 			{
421 				ClassDesc* pCD = XRayMtl::GetSamplerCD(i);
422 				if (_tcsicmp(pCD->ClassName(), v.s) == 0)
423 				{
424 					m->pb_sampling->SetValue(std2_ssampler, 0, i);
425 					break;
426 				}
427 			}
428 									} break;
429 		case std2_ssampler_qual:
430 			m->GetPixelSampler()->SetQuality( v.f ); break;
431 		case std2_ssampler_enable:
432 			m->GetPixelSampler()->SetEnable( v.i );
433 			m->SetFlag(NEWSTDMTL_SSAMP_ON, v.i); break;
434 
435 		case std2_ssampler_adapt_threshold:
436 			m->GetPixelSampler()->SetAdaptiveThreshold( v.f ); break;
437 		case std2_ssampler_adapt_on:{
438 			m->GetPixelSampler()->SetAdaptiveOn( v.i );
439 			IParamMap2* map = m->pb_sampling ? m->pb_sampling->GetMap() : NULL;
440 			if ( map ) {
441 				map->Enable(std2_ssampler_adapt_threshold, v.i );
442 			}
443 									} break;
444 		case std2_ssampler_subsample_tex_on:
445 			m->GetPixelSampler()->SetTextureSuperSampleOn( v.i ); break;
446 		case std2_ssampler_advanced: {
447 			IParamMap2* map = m->pb_sampling ? m->pb_sampling->GetMap() : NULL;
448 			HWND hwnd = ( map ) ? map->GetHWnd() : NULL;
449 			m->GetPixelSampler()->ExecuteParamDialog( hwnd, m );
450 									 } break;
451 		case std2_ssampler_param0:
452 			m->GetPixelSampler()->SetOptionalParam( 0, v.f ); break;
453 		case std2_ssampler_param1:
454 			m->GetPixelSampler()->SetOptionalParam( 1, v.f ); break;
455 
456 		}
457 		macroRecorder->Enable();
458 	}
Get(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t,Interval & valid)459 	void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval& valid)    // get into v
460 	{
461 		XRayMtl* m = (XRayMtl*)owner;
462 		switch (id)
463 		{
464 		case std2_ssampler_by_name: {
465 			ClassDesc* pCD = XRayMtl::GetSamplerCD(m->samplerId);
466 			if (pCD)
467 				v.s = (TCHAR*)pCD->ClassName();
468 									} break;
469 		}
470 	}
471 };
472 
473 
474 static SamplingPBAccessor samplingPBAccessor;
475 
476 // sampling rollout dialog proc
477 
478 class SamplingDlgProc : public ParamMap2UserDlgProc
479 {
480 public:
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)481 	BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
482 	{
483 		switch (msg)
484 		{
485 		case WM_INITDIALOG:
486 			//  load the sampler dropdown
487 			HWND hwndSamplerCombo = GetDlgItem(hWnd, IDC_PIX_SAMPLER);
488 			SendMessage(hwndSamplerCombo, CB_RESETCONTENT, 0L, 0L);
489 			for (int i = 0; i < XRayMtl::NumSamplers(); i++) {
490 				ClassDesc* pClassD = XRayMtl::GetSamplerCD(i);
491 				int n = SendMessage(hwndSamplerCombo, CB_ADDSTRING, 0L, (LPARAM)(pClassD->ClassName()) );
492 				SendMessage(hwndSamplerCombo, CB_SETITEMDATA, n, (LPARAM)pClassD );
493 			}
494 			XRayMtl* m = (XRayMtl*)map->GetParamBlock()->GetOwner();
495 			//					Class_ID sampId = m->GetPixelSampler()->ClassID();
496 
497 			// JohnW: Are these still necessary? removed setindx 3/23/99 ke
498 			macroRecorder->Disable();
499 			//					m->SetSamplerIndx( m->FindSampler( sampId ) );
500 			m->UpdateSamplingParams();
501 			macroRecorder->Enable();
502 			return TRUE;
503 		}
504 		return FALSE;
505 	}
DeleteThis()506 	void DeleteThis() { }
507 };
508 
509 static SamplingDlgProc samplingDlgProc;
510 
511 // supersampling parameters
512 static ParamBlockDesc2 std2_sampling_blk ( std2_sampling, _T("samplingParameters"), 0, &stdmtl2CD, P_AUTO_CONSTRUCT + P_AUTO_UI, SAMPLING_PB_REF,
513 										  //rollout
514 										  IDD_DMTL_SAMPLING3, IDS_KE_SAMPLING, 0, APPENDROLL_CLOSED, &samplingDlgProc,
515 										  // params
516 										  std2_ssampler, _T("sampler"), TYPE_INT, 0,	IDS_JW_PIXELSAMPLER,
517 										  p_default, 		0,
518 										  p_ui, 			TYPE_INTLISTBOX, IDC_PIX_SAMPLER, 0,
519 										  p_accessor,		&samplingPBAccessor,
520 										  end,
521 										  std2_ssampler_qual, _T("samplerQuality"), TYPE_FLOAT, P_ANIMATABLE, IDS_JW_SAMPLERQUAL,
522 										  p_default, 		0.5,
523 										  p_range, 		0.0, 1.0,
524 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_SAMPLEQUALITY_EDIT, IDC_SAMPLEQUALITY_SPIN, 0.01,
525 										  p_accessor,		&samplingPBAccessor,
526 										  end,
527 										  std2_ssampler_enable, _T("samplerEnable"), TYPE_BOOL, P_ANIMATABLE, IDS_JW_SAMPLERENABLE,
528 										  p_default, 		FALSE,
529 										  p_ui, 			TYPE_SINGLECHEKBOX, IDC_SUPER_SAMP,
530 										  p_accessor,		&samplingPBAccessor,
531 										  end,
532 										  std2_ssampler_adapt_threshold, _T("samplerAdaptThreshold"), TYPE_FLOAT, 0, IDS_KE_SAMPLERADAPTTHRESH,
533 										  p_default, 		0.1,
534 										  p_range, 		0.0, 1.0,
535 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_THRESHOLD_EDIT, IDC_THRESHOLD_SPIN, 0.001,
536 										  p_accessor,		&samplingPBAccessor,
537 										  end,
538 										  std2_ssampler_adapt_on, _T("samplerAdaptOn"), TYPE_BOOL, 0, IDS_KE_SAMPLERADAPTON,
539 										  p_default, 		TRUE,
540 										  p_ui, 			TYPE_SINGLECHEKBOX, IDC_ADAPT_ON,
541 										  p_accessor,		&samplingPBAccessor,
542 										  end,
543 										  std2_ssampler_subsample_tex_on, _T("subSampleTextureOn"), TYPE_BOOL, 0, IDS_KE_SUBSAMPLE_TEX_ON,
544 										  p_default, 		TRUE,
545 										  p_ui, 			TYPE_SINGLECHEKBOX, IDC_SAMPLE_TEX,
546 										  p_accessor,		&samplingPBAccessor,
547 										  end,
548 										  std2_ssampler_advanced, _T("samplerAdvancedOptions"), TYPE_BOOL, 0, IDS_KE_SAMPLERADVANCED,
549 										  p_default, 		TRUE,
550 										  p_ui, 			TYPE_SINGLECHEKBOX, IDC_ADVANCED_BUTTON,
551 										  p_accessor,		&samplingPBAccessor,
552 										  end,
553 										  std2_ssampler_by_name, _T("samplerByName"), TYPE_STRING, 		0, 		IDS_JW_SAMPLERBYNAME,
554 										  p_accessor,		&samplingPBAccessor,
555 										  end,
556 										  std2_ssampler_param0, _T("UserParam0"), TYPE_FLOAT, 0, IDS_KE_SAMPLER_PARAM0,
557 										  p_default, 		0.0,
558 										  p_range, 		0.0, 1.0,
559 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_PARAM0_EDIT, IDC_PARAM0_SPIN, 0.01,
560 										  p_accessor,		&samplingPBAccessor,
561 										  end,
562 										  std2_ssampler_param1, _T("UserParam1"), TYPE_FLOAT, 0, IDS_KE_SAMPLER_PARAM1,
563 										  p_default, 		0.0,
564 										  p_range, 		0.0, 1.0,
565 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_PARAM1_EDIT, IDC_PARAM1_SPIN, 0.01,
566 										  p_accessor,		&samplingPBAccessor,
567 										  end,
568 										  end
569 										  );
570 
571 class XRayPBAccessor : public PBAccessor
572 {
573 public:
Set(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)574 	void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
575 	{
576 		XRayMtl* m = (XRayMtl*)owner;
577 		switch (id)
578 		{
579 		case std2_eshader_type:
580 			m->eshaderId = (m->GetEShader(v.i))?v.i:-1;
581 			break;
582 		case std2_cshader_type:
583 			m->cshaderId = (m->GetCShader(v.i))?v.i:-1;
584 			break;
585 		case std2_gamemtl_type:
586 			m->gamemtlId = (m->GetGameMtl(v.i))?v.i:-1;
587 			break;
588 		case std2_eshader_by_name: {
589 			int idx = m->FindEShader(v.s);
590 			if (idx>=0) m->pb_xray->SetValue(std2_eshader_type, 0, idx);
591 								   }break;
592 		case std2_cshader_by_name: {
593 			int idx = m->FindCShader(v.s);
594 			if (idx>=0) m->pb_xray->SetValue(std2_cshader_type, 0, idx);
595 								   }break;
596 		case std2_gamemtl_by_name: {
597 			int idx = m->FindGameMtl(v.s);
598 			if (idx>=0) m->pb_xray->SetValue(std2_gamemtl_type, 0, idx);
599 								   }break;
600 		}
601 	}
602 
Get(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t,Interval & valid)603 	void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval& valid)    // get into v
604 	{
605 		XRayMtl* m = (XRayMtl*)owner;
606 		switch (id)
607 		{
608 		case std2_eshader_by_name:{
609 			v.s = m->GetEShader(m->eshaderId);
610 								  }break;
611 		case std2_cshader_by_name:{
612 			v.s = m->GetCShader(m->cshaderId);
613 								  }break;
614 		case std2_gamemtl_by_name:{
615 			v.s = m->GetGameMtl(m->gamemtlId);
616 								  }break;
617 		}
618 	}
619 };
620 
621 static XRayPBAccessor xrayPBAccessor;
622 
623 // shader rollout dialog proc
624 class XRayDlgProc : public ParamMap2UserDlgProc
625 {
626 public:
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)627 	BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
628 	{
629 		switch (msg)
630 		{
631 		case WM_INITDIALOG:{
632 			XRayMtl* m = (XRayMtl*)map->GetParamBlock()->GetOwner();
633 			//  load the shader dropdown
634 			{
635 				HWND hwndEShader = GetDlgItem(hWnd, IDC_ESHADER);
636 				SendMessage(hwndEShader, CB_RESETCONTENT, 0L, 0L);
637 				for (DWORD i = 0; i < XRayMtl::EShaders.size(); i++)
638 				{
639 					int n = SendMessage(hwndEShader, CB_ADDSTRING, 0L, (LPARAM)m->GetEShader(i));
640 					SendMessage(hwndEShader, CB_SETITEMDATA, n, (LPARAM)i);
641 				}
642 			}
643 			{
644 				HWND hwndEShader = GetDlgItem(hWnd, IDC_CSHADER);
645 				SendMessage(hwndEShader, CB_RESETCONTENT, 0L, 0L);
646 				for (DWORD i = 0; i < XRayMtl::CShaders.size(); i++)
647 				{
648 					int n = SendMessage(hwndEShader, CB_ADDSTRING, 0L, (LPARAM)m->GetCShader(i));
649 					SendMessage(hwndEShader, CB_SETITEMDATA, n, (LPARAM)i);
650 				}
651 			}
652 			{
653 				HWND hwndEShader = GetDlgItem(hWnd, IDC_GAMEMTL);
654 				SendMessage(hwndEShader, CB_RESETCONTENT, 0L, 0L);
655 				for (DWORD i = 0; i < XRayMtl::GameMtls.size(); i++)
656 				{
657 					int n = SendMessage(hwndEShader, CB_ADDSTRING, 0L, (LPARAM)m->GetGameMtl(i));
658 					SendMessage(hwndEShader, CB_SETITEMDATA, n, (LPARAM)i);
659 				}
660 			}
661 		}return TRUE;
662 		}
663 		return FALSE;
664 	}
DeleteThis()665 	void DeleteThis() { }
666 };
667 
668 
669 static XRayDlgProc xrayDlgProc;
670 
671 // shader parameters
672 static ParamBlockDesc2 std2_xray_blk ( std2_xray, _T("Parameters"),  0, &stdmtl2CD, P_AUTO_CONSTRUCT + P_AUTO_UI, XRAY_PB_REF,
673 									  //rollout
674 									  IDD_DMTL_XRAY, IDS_KE_XRAY, 0, APPENDROLL_CLOSED, &xrayDlgProc,
675 									  // params
676 									  std2_eshader_type, _T("EShaderType"),		TYPE_INT, 		0,		IDS_JW_ESHADERTYPE,
677 									  p_default, 		0,
678 									  p_ui, 			TYPE_INTLISTBOX, IDC_ESHADER, 0,
679 									  p_accessor,		&xrayPBAccessor,
680 									  end,
681 									  std2_cshader_type, _T("CShaderType"),		TYPE_INT, 		0,		IDS_JW_CSHADERTYPE,
682 									  p_default, 		0,
683 									  p_ui, 			TYPE_INTLISTBOX, IDC_CSHADER, 0,
684 									  p_accessor,		&xrayPBAccessor,
685 									  end,
686 									  std2_gamemtl_type, _T("GameMtlType"),		TYPE_INT, 		0,		IDS_JW_GAMEMTLTYPE,
687 									  p_default, 		0,
688 									  p_ui, 			TYPE_INTLISTBOX, IDC_GAMEMTL, 0,
689 									  p_accessor,		&xrayPBAccessor,
690 									  end,
691 									  std2_eshader_by_name, _T("EShaderByName"),TYPE_STRING,	0,		IDS_JW_ESHADERBYNAME,
692 									  p_accessor,		&xrayPBAccessor,
693 									  end,
694 									  std2_cshader_by_name, _T("CShaderByName"),TYPE_STRING, 	0,		IDS_JW_CSHADERBYNAME,
695 									  p_accessor,		&xrayPBAccessor,
696 									  end,
697 									  std2_gamemtl_by_name, _T("GameMtlByName"),TYPE_STRING, 	0,		IDS_JW_GAMEMTLBYNAME,
698 									  p_accessor,		&xrayPBAccessor,
699 									  end,
700 									  end
701 									  );
702 
703 //////////////////////////////////////////end, sampling
704 static HIMAGELIST hLockButtons = NULL;
705 
706 // mjm - begin - 5.10.99
707 class ResourceDelete
708 {
709 public:
ResourceDelete()710 	ResourceDelete() {}
~ResourceDelete()711 	~ResourceDelete() { if (hLockButtons) ImageList_Destroy(hLockButtons); }
712 };
713 
714 static ResourceDelete theResourceDelete;
715 // mjm - end
716 
SetupPadLockButton(HWND hWnd,int id,BOOL check)717 static void SetupPadLockButton(HWND hWnd, int id, BOOL check)
718 {
719 	ICustButton *iBut;
720 	iBut = GetICustButton(GetDlgItem(hWnd, id));
721 	iBut->SetImage(hLockButtons, 2, 2, 2, 2, 16, 15);
722 	iBut->SetType(CBT_CHECK);
723 	ReleaseICustButton(iBut);
724 }
725 
LoadXRayMtlResources()726 static void LoadXRayMtlResources()
727 {
728 	static BOOL loaded=FALSE;
729 	if (loaded) return;
730 	loaded = TRUE;
731 	HBITMAP hBitmap, hMask;
732 	hLockButtons = ImageList_Create(16, 15, TRUE, 2, 0);
733 	hBitmap = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_BUTTONS));
734 	hMask   = LoadBitmap(hInstance, MAKEINTRESOURCE(IDB_DMTL_MASKBUTTONS));
735 	ImageList_Add(hLockButtons, hBitmap, hMask);
736 	DeleteObject(hBitmap);
737 	DeleteObject(hMask);
738 }
739 
740 class StdMapsDlgProc : public ParamMap2UserDlgProc
741 {
742 public:
DlgProc(TimeValue t,IParamMap2 * map,HWND hWnd,UINT msg,WPARAM wParam,LPARAM lParam)743 	BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
744 	{
745 		XRayMtl* m = (XRayMtl*)map->GetParamBlock()->GetOwner();
746 		switch (msg)
747 		{
748 		case WM_INITDIALOG:
749 			// conditionally set map amount spinner ranges and padlock button images
750 			LoadXRayMtlResources();
751 			int bumpChan = m->stdIDToChannel[ ID_BU ];
752 			int dispChan = m->stdIDToChannel[ ID_DP ];
753 			int slevChan = m->stdIDToChannel[ ID_SS ];
754 
755 			for (int i = 0; i < STD2_NMAX_TEXMAPS; i++)
756 			{
757 				if (i == bumpChan || i == dispChan || i == slevChan)
758 					map->SetRange(std2_map_amnts, -999, 999, i);
759 				else
760 					map->SetRange(std2_map_amnts, 0, 100, i);
761 			}
762 
763 			SetupPadLockButton(hWnd, IDC_LOCK_TEX01, TRUE);
764 			macroRecorder->Disable();
765 			{
766 				KillRefmsg kill( m->killRefmsg );
767 				m->UpdateLockADTex(TRUE);
768 			}
769 			macroRecorder->Enable();
770 			return TRUE;
771 		}
772 		return FALSE;
773 	}
774 
DeleteThis()775 	void DeleteThis() { }
776 };
777 
778 static StdMapsDlgProc stdMapsDlgProc;
779 
IsMultipleInstanced(XRayMtl * m,Texmap * t)780 static BOOL IsMultipleInstanced(XRayMtl *m, Texmap *t) {
781 	int cnt=0;
782 	for (int i = 0; i < STD2_NMAX_TEXMAPS; i++) {
783 		if (m->maps->txmap[i].map == t)
784 			cnt++;
785 	}
786 	return (cnt>1)?TRUE:FALSE;
787 }
788 
789 #define BUMP_DEF_AMT .30f
790 
791 class MapsPBAccessor : public PBAccessor
792 {
793 public:
794 	// the texture maps are stored, as before, in the Texmaps structure, so the parameters in the
795 	// pb_map block act as 'views' onto this structure.  Any setting of map info (say from the scripter)
796 	// is reflected here in the Texmaps structure, and any getting of map info is extracted here from
797 	// this structure.
798 
799 	// I hope to be able to host the texmap stuff entirely in the paramblock when I get assignable subanim
800 	// numbers supported in PB2's (so that the map, map enable and map amount Tab<>s are number in interleaved row order)
Set(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)801 	void Set(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
802 	{
803 		XRayMtl* m = (XRayMtl*)owner;
804 		switch (id)
805 		{
806 		case std2_map_enables:
807 			m->maps->txmap[tabIndex].mapOn = v.i;
808 			m->UpdateMapButtons();
809 			m->UpdateExtendedMapButtons();
810 			break;
811 
812 		case std2_maps:
813 			{
814 				Texmap* tex = (Texmap*)v.r;
815 				m->maps->ReplaceReference(2*tabIndex+1, tex);
816 				if (tex != NULL) {
817 					macroRecorder->Disable();
818 					m->EnableMap(tabIndex, TRUE);
819 					macroRecorder->Enable();
820 					if (m->maps->txmap[tabIndex].amtCtrl == NULL) {
821 						m->maps->ReplaceReference(2*tabIndex, NewDefaultFloatController());
822 						m->maps->txmap[tabIndex].amtCtrl->SetValue(TimeValue(0), &m->maps->txmap[tabIndex].amount);
823 					}
824 				} else {
825 					if (m->maps->txmap[tabIndex].amtCtrl != NULL)
826 						m->maps->DeleteReference(2*tabIndex);
827 					macroRecorder->Disable();
828 					m->SetTexmapAmt(tabIndex, ((tabIndex == m->stdIDToChannel[ID_BU]) ? BUMP_DEF_AMT : 1.0f), TimeValue(0));
829 					m->EnableMap(tabIndex, FALSE);
830 					macroRecorder->Enable();
831 				}
832 				if (tex && (tabIndex == m->stdIDToChannel[ID_RL]|| tabIndex == m->stdIDToChannel[ID_RR]) ){
833 					if (!IsMultipleInstanced(m,tex)) {  //DS 4/26/99: keep settings for instanced map
834 						UVGen* uvg0 = tex->GetTheUVGen();
835 						if (uvg0 && uvg0->IsStdUVGen()) {
836 							StdUVGen *uvg = (StdUVGen*)uvg0;
837 							uvg->InitSlotType(MAPSLOT_ENVIRON);
838 							uvg->SetCoordMapping(UVMAP_SPHERE_ENV);
839 						}
840 					}
841 				}
842 				m->UpdateMapButtons();
843 				m->UpdateExtendedMapButtons();
844 
845 				break;
846 			}
847 
848 		case std2_map_amnts:
849 			{
850 				// Kill the refmessage from the map, since it will
851 				// be fixed later by the ref message for std2_map_amnts.
852 				KillRefmsg kill(m->killRefmsg);
853 				if (m->maps->txmap[tabIndex].amtCtrl)
854 					m->maps->txmap[tabIndex].amtCtrl->SetValue(t, &v.f);
855 				m->maps->txmap[tabIndex].amount = v.f;
856 				if (tabIndex == m->stdIDToChannel[ID_BU])
857 					m->mInRQ = chooseReshade[m->mInRQ][IReshading::RR_NeedPreshade];
858 			}
859 			break;
860 
861 		case std2_mp_ad_texlock:
862 			m->SetFlag(NEWSTDMTL_LOCK_ADTEX, v.i);
863 			m->UpdateLockADTex(TRUE);
864 			//			 removed to avoid multiple viewport redraws on change shader
865 			//				m->UpdateMtlDisplay();
866 			break;
867 		}
868 	}
869 
Get(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t,Interval & valid)870 	void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval& valid)    // set from v
871 	{
872 		XRayMtl* m = (XRayMtl*)owner;
873 		switch (id)
874 		{
875 		case std2_map_enables:
876 			v.i = m->maps->txmap[tabIndex].mapOn; break;
877 		case std2_maps:
878 			v.r = m->maps->txmap[tabIndex].map; break;
879 		case std2_map_amnts:
880 			if (m->maps->txmap[tabIndex].amtCtrl)
881 				m->maps->txmap[tabIndex].amtCtrl->GetValue(t, &v.f, valid);
882 			else
883 				v.f = m->maps->txmap[tabIndex].amount;
884 			break;
885 		}
886 	}
887 
888 	// this allows 'virtual' parameters to refelect key state if in spinners and the underlying
889 	// source parameter is animatable (map amount in this case)
KeyFrameAtTime(ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)890 	BOOL KeyFrameAtTime(ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
891 	{
892 		if (id == std2_map_amnts)
893 			return ((XRayMtl*)owner)->AmtKeyAtTime(tabIndex, t);
894 		else
895 			return FALSE;
896 	}
897 
898 };
899 static MapsPBAccessor mapsPBAccessor;
900 
901 
902 // std_maps parameters
903 static ParamBlockDesc2 std_maps_blk ( std_maps, _T("maps"),  0, &stdmtl2CD, P_AUTO_CONSTRUCT + P_AUTO_UI, MAPS_PB_REF,
904 									 //rollout
905 									 IDD_DMTL_TEXMAP4, IDS_DS_TEXMAP, 0, APPENDROLL_CLOSED, &stdMapsDlgProc,
906 									 // params
907 									 std2_map_enables,	_T("mapEnables"), 	TYPE_BOOL_TAB, STD2_NMAX_TEXMAPS, 		0, 				IDS_JW_MAPENABLES,
908 									 p_default, 		FALSE,
909 									 p_ui, 			TYPE_SINGLECHEKBOX, IDC_USEMAP_0, IDC_USEMAP_1, IDC_USEMAP_2, IDC_USEMAP_3,
910 									 IDC_USEMAP_4, IDC_USEMAP_5, IDC_USEMAP_6, IDC_USEMAP_7,
911 									 IDC_USEMAP_8, IDC_USEMAP_9, IDC_USEMAP_10, IDC_USEMAP_11,
912 									 IDC_USEMAP_12, IDC_USEMAP_13, IDC_USEMAP_14, IDC_USEMAP_15,
913 									 IDC_USEMAP_16, IDC_USEMAP_17, IDC_USEMAP_18, IDC_USEMAP_19,
914 									 IDC_USEMAP_20, IDC_USEMAP_21, IDC_USEMAP_22, IDC_USEMAP_23,
915 									 p_accessor,		&mapsPBAccessor,
916 									 end,
917 									 std2_maps, 			_T("maps"), 		TYPE_TEXMAP_TAB, STD2_NMAX_TEXMAPS,	P_NO_REF,		IDS_JW_MAPS,
918 									 p_ui, 			TYPE_TEXMAPBUTTON,  IDC_MAP_0, IDC_MAP_1, IDC_MAP_2, IDC_MAP_3,
919 									 IDC_MAP_4, IDC_MAP_5, IDC_MAP_6, IDC_MAP_7,
920 									 IDC_MAP_8, IDC_MAP_9, IDC_MAP_10, IDC_MAP_11,
921 									 IDC_MAP_12, IDC_MAP_13, IDC_MAP_14, IDC_MAP_15,
922 									 IDC_MAP_16, IDC_MAP_17, IDC_MAP_18, IDC_MAP_19,
923 									 IDC_MAP_20, IDC_MAP_21, IDC_MAP_22, IDC_MAP_23,
924 									 p_accessor,		&mapsPBAccessor,
925 									 end,
926 									 std2_map_amnts, 	_T("mapAmounts"), 	TYPE_PCNT_FRAC_TAB, STD2_NMAX_TEXMAPS, 0, 				IDS_JW_MAPAMOUNTS,
927 									 p_default, 		1.0,   // default is given in internal units   JBW 10.8.99
928 									 p_range, 		0.0, 100.0,
929 									 p_ui, 			TYPE_SPINNER, EDITTYPE_INT, IDC_AMTEDIT_0, IDC_AMTSPIN_0, IDC_AMTEDIT_1, IDC_AMTSPIN_1,
930 									 IDC_AMTEDIT_2, IDC_AMTSPIN_2, IDC_AMTEDIT_3, IDC_AMTSPIN_3,
931 									 IDC_AMTEDIT_4, IDC_AMTSPIN_4, IDC_AMTEDIT_5, IDC_AMTSPIN_5,
932 									 IDC_AMTEDIT_6, IDC_AMTSPIN_6, IDC_AMTEDIT_7, IDC_AMTSPIN_7,
933 									 IDC_AMTEDIT_8, IDC_AMTSPIN_8, IDC_AMTEDIT_9, IDC_AMTSPIN_9,
934 									 IDC_AMTEDIT_10, IDC_AMTSPIN_10, IDC_AMTEDIT_11, IDC_AMTSPIN_11,
935 									 IDC_AMTEDIT_12, IDC_AMTSPIN_12, IDC_AMTEDIT_13, IDC_AMTSPIN_13,
936 									 IDC_AMTEDIT_14, IDC_AMTSPIN_14, IDC_AMTEDIT_15, IDC_AMTSPIN_15,
937 									 IDC_AMTEDIT_16, IDC_AMTSPIN_16, IDC_AMTEDIT_17, IDC_AMTSPIN_17,
938 									 IDC_AMTEDIT_18, IDC_AMTSPIN_18, IDC_AMTEDIT_19, IDC_AMTSPIN_19,
939 									 IDC_AMTEDIT_20, IDC_AMTSPIN_20, IDC_AMTEDIT_21, IDC_AMTSPIN_21,
940 									 IDC_AMTEDIT_22, IDC_AMTSPIN_22, IDC_AMTEDIT_23, IDC_AMTSPIN_23,
941 									 1.0,
942 									 p_accessor,		&mapsPBAccessor,
943 									 end,
944 									 std2_mp_ad_texlock, _T("adTextureLock"), 	TYPE_BOOL, 			0,				IDS_JW_ADTEXLOCK,
945 									 p_default, 		TRUE,
946 									 p_ui, 			TYPE_CHECKBUTTON, IDC_LOCK_TEX01,
947 									 p_accessor,		&mapsPBAccessor,
948 									 end,
949 									 end
950 									 );
951 
952 #ifndef DESIGN_VER
953 // std2_dynamics parameters
954 static ParamBlockDesc2 std2_dynamics_blk ( std2_dynamics, _T("dynamicsParameters"),  0, &stdmtl2CD, P_AUTO_CONSTRUCT + P_AUTO_UI, DYNAMICS_PB_REF,
955 										  //rollout
956 										  IDD_DMTL_DYNAM, IDS_DS_DYNAMICS, 0, APPENDROLL_CLOSED, NULL,
957 										  // params
958 										  std2_bounce, 	_T("bounce"), 	TYPE_FLOAT, 	P_ANIMATABLE, 	IDS_DS_BOUNCE,
959 										  p_default, 		1.0,
960 										  p_range, 		0.0, 1.0,
961 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_BOUNCE_EDIT, IDC_BOUNCE_SPIN, 0.01,
962 										  end,
963 										  std2_static_friction, 	_T("staticFriction"), 	TYPE_FLOAT, 	P_ANIMATABLE, 	IDS_DS_STATFRIC,
964 										  p_default, 		0.0,
965 										  p_range, 		0.0, 1.0,
966 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_STATFRIC_EDIT, IDC_STATFRIC_SPIN, 0.01,
967 										  end,
968 										  std2_sliding_friction, 	_T("slidingFriction"), 	TYPE_FLOAT, 	P_ANIMATABLE, 	IDS_DS_SLIDFRIC,
969 										  p_default, 		0.0,
970 										  p_range, 		0.0, 1.0,
971 										  p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT, IDC_SLIDFRIC_EDIT, IDC_SLIDFRIC_SPIN, 0.01,
972 										  end,
973 										  end
974 										  );
975 #endif
976 
977 // Old Parameter block indices, kept around for old-version loading
978 #define PB_AMBIENT_O		0
979 #define PB_DIFFUSE_O		1
980 #define PB_SPECULAR_O		2
981 #define PB_SHININESS_O 		3
982 #define PB_SHIN_STR_O		4
983 #define PB_SELFI_O			5
984 #define PB_OPAC_O			6
985 #define PB_OPFALL_O			7
986 #define PB_FILTER_O			8
987 #define PB_WIRESZ_O			9
988 #define PB_IOR_O 			10
989 #define PB_BOUNCE_O			11
990 #define PB_STATFRIC_O		12
991 #define PB_SLIDFRIC_O		13
992 #define PB_DIMLEV_O			14
993 #define PB_DIMMULT_O		15
994 #define PB_SOFTEN_O			16
995 #define PB_SELFILLUM_CLR_O	17
996 
997 // Ver. 10 Parameter block indices
998 #define PB_OPAC			0
999 #define PB_OPFALL		1
1000 #define PB_FILTER 		2
1001 #define PB_WIRESZ 		3
1002 #define PB_IOR	 		4
1003 #define PB_BOUNCE 		5
1004 #define PB_STATFRIC		6
1005 #define PB_SLIDFRIC		7
1006 #define PB_DIMLEV		8
1007 #define PB_DIMMULT		9
1008 
1009 #define CURRENT_NEWSTDMTL_VERSION 12
1010 #define FINAL_PARAMBLOCK_v1_VERSION 10
1011 
1012 #define NPARAMS 10
1013 #define XRAYMTL_PBVERSION	1
1014 #define NEWSTDMTL_PBVERSION	9
1015 
1016 // conversion descriptors for old ParamBlocks to ParamBlock2s
1017 // here we have two version descriptors, one for parameters going into
1018 // new pb_extended pblock, the other for params going into the
1019 // new pb_dynamics block.  The -1 ID's below indicate no copy,
1020 // so we use to update calls to distribute old params from one block
1021 // into two new blocks
1022 
1023 static ParamBlockDescID extVer10[] = {
1024 	{ TYPE_FLOAT, NULL, TRUE, std2_opacity },		// opacity
1025 	{ TYPE_FLOAT, NULL, TRUE, std2_falloff_amnt },	// opfalloff
1026 	{ TYPE_RGBA,  NULL, TRUE, std2_filter_color },	// filter
1027 	{ TYPE_FLOAT, NULL, TRUE, std2_wire_size },		// wireSize
1028 	{ TYPE_FLOAT, NULL, TRUE, std2_ior },			// index of refraction
1029 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// bounce
1030 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// static friction
1031 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// sliding friction
1032 	{ TYPE_FLOAT, NULL, TRUE, std2_dim_lvl },		// reflect dim level
1033 	{ TYPE_FLOAT, NULL, TRUE, std2_refl_lvl },		// reflect dim multiplier
1034 };
1035 
1036 static ParamBlockDescID dynVer10[] = {
1037 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// opacity
1038 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// opfalloff
1039 	{ TYPE_RGBA,  NULL, TRUE, -1 },					// filter
1040 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// wireSize
1041 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// index of refraction
1042 	{ TYPE_FLOAT, NULL, TRUE, std2_bounce },		// bounce
1043 	{ TYPE_FLOAT, NULL, TRUE, std2_static_friction }, // static friction
1044 	{ TYPE_FLOAT, NULL, TRUE, std2_sliding_friction }, // sliding friction
1045 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// reflect dim level
1046 	{ TYPE_FLOAT, NULL, TRUE, -1 },					// reflect dim multiplier
1047 };
1048 
1049 // v10 Param Block Descriptor
1050 static ParamBlockDescID stdmtl2PB[ NPARAMS ] = {
1051 	{ TYPE_FLOAT, NULL, TRUE, 7 },   // opacity
1052 	{ TYPE_FLOAT, NULL, TRUE, 8 }, 	// opfalloff
1053 	{ TYPE_RGBA,  NULL, TRUE, 9 },   // filter
1054 	{ TYPE_FLOAT, NULL, TRUE, 10 },  // wireSize
1055 	{ TYPE_FLOAT, NULL, TRUE, 11 },  // index of refraction
1056 	{ TYPE_FLOAT, NULL, TRUE, 12 },  // bounce
1057 	{ TYPE_FLOAT, NULL, TRUE, 13 },  // static friction
1058 	{ TYPE_FLOAT, NULL, TRUE, 14 },  // sliding friction
1059 	{ TYPE_FLOAT, NULL, TRUE, 15 },  // reflect dim level
1060 	{ TYPE_FLOAT, NULL, TRUE, 16 },  // reflect dim multiplier
1061 };
1062 
1063 #define NPARAMS_O 17
1064 
1065 //Old (2.5 and before) Param Block Descriptor
1066 static ParamBlockDescID stdmtlPB[ NPARAMS_O ] = {
1067 	{ TYPE_RGBA, NULL, TRUE, 1 },    // ambient
1068 	{ TYPE_RGBA, NULL, TRUE, 2 },    // diffuse
1069 	{ TYPE_RGBA, NULL, TRUE, 3 },    // specular
1070 	{ TYPE_FLOAT, NULL, TRUE, 4 },   // shininess
1071 	{ TYPE_FLOAT, NULL, TRUE, 5 },   // shini_strength
1072 	{ TYPE_FLOAT, NULL, TRUE, 6 },   // self-illum
1073 	{ TYPE_FLOAT, NULL, TRUE, 7 },   // opacity
1074 	{ TYPE_FLOAT, NULL, TRUE, 8 }, 	// opfalloff
1075 	{ TYPE_RGBA,  NULL, TRUE, 9 },   // filter
1076 	{ TYPE_FLOAT, NULL, TRUE, 10 },  // wireSize
1077 	{ TYPE_FLOAT, NULL, TRUE, 11 },  // index of refraction
1078 	{ TYPE_FLOAT, NULL, TRUE, 12 },  // bounce
1079 	{ TYPE_FLOAT, NULL, TRUE, 13 },  // static friction
1080 	{ TYPE_FLOAT, NULL, TRUE, 14 },  // sliding friction
1081 	{ TYPE_FLOAT, NULL, TRUE, 15 },  // reflect dim level
1082 	{ TYPE_FLOAT, NULL, TRUE, 16 },  // reflect dim multiplier
1083 	{ TYPE_FLOAT, NULL, TRUE, 17 }   // soften
1084 };
1085 
1086 // Descriptor for mapping old (2.5 and before) shader parameters into new stdShader PB2's
1087 // Shader::ConvertParamBlock() uses this to extract old mtl shader params into new Shader
1088 static ParamBlockDescID stdmtlPB2[ NPARAMS_O ] = {
1089 	{ TYPE_RGBA, NULL, TRUE, shdr_ambient },			// ambient
1090 	{ TYPE_RGBA, NULL, TRUE, shdr_diffuse },			// diffuse
1091 	{ TYPE_RGBA, NULL, TRUE, shdr_specular },			// specular
1092 	{ TYPE_FLOAT, NULL, TRUE, shdr_glossiness },		// shininess
1093 	{ TYPE_FLOAT, NULL, TRUE, shdr_spec_lvl },			// shini_strength
1094 	{ TYPE_FLOAT, NULL, TRUE, shdr_self_illum_amnt },   // self-illum
1095 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// opacity
1096 	{ TYPE_FLOAT, NULL, TRUE, -1 }, 					// opfalloff
1097 	{ TYPE_RGBA,  NULL, TRUE, -1 },						// filter
1098 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// wireSize
1099 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// index of refraction
1100 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// bounce
1101 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// static friction
1102 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// sliding friction
1103 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// reflect dim level
1104 	{ TYPE_FLOAT, NULL, TRUE, -1 },						// reflect dim multiplier
1105 	{ TYPE_FLOAT, NULL, TRUE, shdr_soften }				// soften
1106 };
1107 #define NUMOLDVER 1
1108 static ParamVersionDesc oldXRayMtlVersions[ NUMOLDVER ] = {
1109 	ParamVersionDesc(stdmtl2PB, NPARAMS, 0),
1110 };
1111 
1112 #define NEWSTDMTL_NUMOLDVER 9
1113 
1114 static ParamVersionDesc oldNewStdMtlVersions[ NEWSTDMTL_NUMOLDVER+1 ] = {
1115 	ParamVersionDesc(stdmtlPB, 8, 0),
1116 		ParamVersionDesc(stdmtlPB, 9, 1),
1117 		ParamVersionDesc(stdmtlPB, 9, 2),
1118 		ParamVersionDesc(stdmtlPB, 10, 3),
1119 		ParamVersionDesc(stdmtlPB, 11, 4),
1120 		ParamVersionDesc(stdmtlPB, 14, 5),
1121 		ParamVersionDesc(stdmtlPB, 15, 6),
1122 		ParamVersionDesc(stdmtlPB, 15, 7),
1123 		ParamVersionDesc(stdmtlPB, 16, 8),
1124 		ParamVersionDesc(stdmtlPB, 17, 9)
1125 };
1126 
1127 static ParamVersionDesc curVersion(stdmtl2PB, NPARAMS, XRAYMTL_PBVERSION);
1128 static ParamVersionDesc stdMtlVersion(stdmtlPB, NPARAMS_O, NEWSTDMTL_PBVERSION);
1129 
1130 #define IDT_MYTIMER 1010
1131 #define DRAGTHRESH 6
1132 #define DITHER_WHEN_INACTIVE // avoids palette conflict probs
1133 
1134 //-----------------------------------------------------------------------------
1135 //  XRayMtl
1136 //-----------------------------------------------------------------------------
1137 /*
1138 TCHAR* XRayMtl::get_string(int i)
1139 {
1140 	return strings[i];
1141 }
1142 
1143 int XRayMtl::n_strings()
1144 {
1145 	return strings.Count();
1146 }
1147 */
GetInterface(ULONG id)1148 void* XRayMtl::GetInterface(ULONG id)
1149 {
1150 	if( id == IID_IReshading )
1151 		return (IReshading*)( this );
1152 	//	else if ( id == IID_IValidityToken )
1153 	//		return (IValidityToken*)( this );
1154 	else
1155 		return Mtl::GetInterface(id);
1156 }
1157 
1158 
Reset()1159 void XRayMtl::Reset()
1160 {
1161 	ReplaceReference( TEXMAPS_REF, new Texmaps((MtlBase*)this));
1162 	ivalid.SetEmpty();
1163 
1164 	SetShaderIndx( FindShader( Class_ID(DEFAULT_SHADER_CLASS_ID,0) ));
1165 	// back in 4.28, as it broke reset....fixed in shader.reset so only allocs pb if not there
1166 	pShader->Reset(); // mjm - 4.22.99 - fix mem leak (pblock already created through SetShaderIndx() above.
1167 
1168 	SetSamplerIndx( FindSampler( Class_ID(DEFAULT_SAMPLER_CLASS_ID,0) ) );
1169 
1170 	// HEY!! this should all be done automatically in ParamBlock init...
1171 	macroRecorder->Disable();  // don't want to see this parameter reset in macrorecorder
1172 	// ensure all map-related parameters are set up
1173 	UpdateMapButtons();	// calls updatetexmaps
1174 	UpdateExtendedMapButtons();
1175 
1176 	pb_shader->SetValue(std2_wire, 0, FALSE );
1177 	pb_shader->SetValue(std2_two_sided, 0, FALSE );
1178 	pb_shader->SetValue(std2_faceted, 0, FALSE );
1179 	pb_shader->SetValue(std2_face_map, 0, FALSE );
1180 
1181 	SetDimIntens( 0.0f, 0 );
1182 	SetDimMult( 3.0f, 0 );
1183 
1184 	pb_extended->SetValue(std2_opacity_type, 0, 0 );
1185 	pb_extended->SetValue(std2_falloff_type, 0, 0 );
1186 	pb_extended->SetValue(std2_wire_units, 0, 0 );
1187 	pb_extended->SetValue(std2_apply_refl_dimming, 0, FALSE );
1188 	SetOpacity(1.0f, 0);
1189 	SetFilter(Color(.5f, .5f, .5f), 0);
1190 	SetIOR(1.5f, 0);
1191 
1192 	// sampling
1193 	SetSamplingQuality( 0.5f );
1194 	SetSamplingOn( FALSE );
1195 	pb_sampling->SetValue(std2_ssampler_subsample_tex_on, 0, TRUE );
1196 	pb_sampling->SetValue(std2_ssampler_adapt_threshold, 0, .1f );
1197 	pb_sampling->SetValue(std2_ssampler_adapt_on, 0, TRUE );
1198 
1199 	SetOpacFalloff(0.0f, 0);
1200 	SetWireSize(1.0f, 0);
1201 	int bumpChan = stdIDToChannel[ ID_BU ];
1202 	SetTexmapAmt(bumpChan, BUMP_DEF_AMT, 0);
1203 	SetDynamicsProperty(0, 0, DYN_BOUNCE, 1.0f);
1204 	SetDynamicsProperty(0, 0, DYN_STATIC_FRICTION, 0.0f);
1205 	SetDynamicsProperty(0, 0, DYN_SLIDING_FRICTION, 0.0f);
1206 
1207 	SetEShaderIndx(FindEShader("default"));
1208 	SetCShaderIndx(FindCShader("default"));
1209 	SetGameMtlIndx(FindGameMtl("default"));
1210 
1211 	macroRecorder->Enable();
1212 }
1213 
XRayMtl(BOOL loading)1214 XRayMtl::XRayMtl(BOOL loading) : mReshadeRQ(RR_None), mInRQ(RR_None) // mjm - 06.02.00
1215 {
1216 	texHandle[0] = texHandle[1] = NULL;
1217 	texHandleValid.SetEmpty();
1218 
1219 	pixelSampler = NULL;
1220 	samplerId = -1;
1221 
1222 	filterOverrideOn = FALSE;
1223 	filterSz = 1.0f;
1224 	ioRefract = 1.5f;
1225 
1226 	old_pblock = NULL;
1227 	pb_xray = pb_shader = pb_extended = pb_sampling = pb_maps = pb_dynamics = NULL;
1228 	maps = NULL;
1229 	filter = Color(0.0f, 0.0f, 0.0f);
1230 	pShader = NULL;
1231 	shaderId = -1;
1232 	flags = NEWSTDMTL_FILT_TRANSP | NEWSTDMTL_ROLLUP1_OPEN;
1233 
1234 	dimReflect = FALSE;
1235 	dimIntens = 0.0f;
1236 	dimMult = 2.0f;
1237 	wireSize = opacity = 1.0f;
1238 	opfall = 0.0f;
1239 	for ( int i = 0; i < 12; ++i )
1240 		stdIDToChannel[i] = -1;
1241 
1242 	for ( i = 0; i < STD2_NMAX_TEXMAPS; ++i )
1243 		channelTypes[i] = UNSUPPORTED_CHANNEL;
1244 
1245 	ivalid.SetEmpty();
1246 
1247 /*
1248 	if(strings.Count() == 0)
1249 	{
1250 		char path[MAX_PATH];
1251 		sprintf(path, "%s/%s", GetCOREInterface()->GetDir(APP_PLUGCFG_DIR), "strings.txt");
1252 		FILE* fstr = fopen(path, "r");
1253 		if(fstr != NULL)
1254 		{
1255 			while(!feof(fstr))
1256 			{
1257 				TCHAR str[100];
1258 
1259 				_fgetts(str, 100, fstr);
1260 				TCHAR* res_str = _tcsdup(str);
1261 				strings.Append(1, &res_str);
1262 			}
1263 			fclose(fstr);
1264 		}
1265 	}
1266 */
1267 	if (!loading){
1268 		// ask the ClassDesc to make the P_AUTO_CONSTRUCT paramblocks
1269 		stdmtl2CD.MakeAutoParamBlocks(this);
1270 		Reset();
1271 	}
1272 }
1273 
Clone(RemapDir & remap)1274 RefTargetHandle XRayMtl::Clone(RemapDir &remap) {
1275 	//DebugPrint(" Cloning NEWSTDMTL %d \n", ++numNewStdMtls);
1276 	macroRecorder->Disable();
1277 	XRayMtl *mnew = new XRayMtl(TRUE);
1278 	*((MtlBase*)mnew) = *((MtlBase*)this);  // copy superclass stuff
1279 	mnew->ReplaceReference(TEXMAPS_REF,		remap.CloneRef(maps));
1280 	mnew->ReplaceReference(SHADER_REF,		remap.CloneRef(pShader));
1281 	mnew->ReplaceReference(XRAY_PB_REF,		remap.CloneRef(pb_xray));
1282 	mnew->ReplaceReference(SHADER_PB_REF,	remap.CloneRef(pb_shader));
1283 	mnew->ReplaceReference(EXTENDED_PB_REF, remap.CloneRef(pb_extended));
1284 	mnew->ReplaceReference(SAMPLING_PB_REF, remap.CloneRef(pb_sampling));
1285 	mnew->ReplaceReference(MAPS_PB_REF,		remap.CloneRef(pb_maps));
1286 #ifndef DESIGN_VER
1287 	mnew->ReplaceReference(DYNAMICS_PB_REF, remap.CloneRef(pb_dynamics));
1288 #endif
1289 	mnew->ReplaceReference(SAMPLER_REF,		remap.CloneRef(pixelSampler));
1290 
1291 	mnew->ivalid.SetEmpty();
1292 	mnew->flags = flags;
1293 
1294 	mnew->filterOverrideOn = filterOverrideOn;
1295 	mnew->filterSz = filterSz;
1296 
1297 	mnew->ioRefract = ioRefract;
1298 	mnew->opacity = opacity;
1299 	mnew->filter = filter;
1300 	mnew->opfall = opfall;
1301 
1302 	mnew->wireSize = wireSize;
1303 	mnew->dimReflect = dimReflect;
1304 
1305 	mnew->samplerId = samplerId;
1306 	mnew->shaderId = shaderId;
1307 
1308 	mnew->eshaderId = eshaderId;
1309 	mnew->cshaderId = cshaderId;
1310 	mnew->gamemtlId = gamemtlId;
1311 
1312 	for ( int i = 0; i < 12; ++i )
1313 		mnew->stdIDToChannel[i] = stdIDToChannel[i];
1314 
1315 	for ( i = 0; i < STD2_NMAX_TEXMAPS; ++i )
1316 		mnew->channelTypes[i] = channelTypes[i];
1317 	macroRecorder->Enable();
1318 	BaseClone(this, mnew, remap);
1319 	return (RefTargetHandle)mnew;
1320 }
1321 
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)1322 ParamDlg* XRayMtl::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp)
1323 {
1324 	KillRefmsg kill( killRefmsg );
1325 
1326 	Interval v;
1327 	macroRecorder->Disable();
1328 	Update(imp->GetTime(), v);
1329 	// save the creation context for possible later shader switching requiring a new CreateParamDialog
1330 	curHwmEdit = hwMtlEdit;
1331 	curImp = imp;
1332 	// create the rollouts, first the main shader dialog as master
1333 	//  note, we can't use PB2 AUTO_UI here, since the shader's dialog is to be installed in the
1334 	//        middle of the rollouts
1335 	masterDlg = stdmtl2CD.CreateParamDlg(std2_shader, hwMtlEdit, imp, this);
1336 	// then have the selected shader make its own
1337 	pShaderDlg = pShader->CreateParamDialog(NULL, hwMtlEdit, imp, this,
1338 		((flags & NEWSTDMTL_ROLLUP1_OPEN) ? 0 : APPENDROLL_CLOSED));
1339 	masterDlg->AddDlg(pShaderDlg);
1340 	// now make the rest (they are added to the master automatically)
1341 
1342 	if( pShader->SupportStdParams() & STD_EXTRA_DLG )
1343 		extendedDlg = stdmtl2CD.CreateParamDlg(std2_extended, hwMtlEdit, imp, this);
1344 	else
1345 		extendedDlg = NULL;
1346 
1347 	samplingDlg		= stdmtl2CD.CreateParamDlg(std2_sampling,	hwMtlEdit, imp, this);
1348 	texmapDlg		= stdmtl2CD.CreateParamDlg(std_maps,		hwMtlEdit, imp, this);
1349 	xrayDlg			= stdmtl2CD.CreateParamDlg(std2_xray,		hwMtlEdit, imp, this);
1350 	UpdateTexmaps();
1351 	if( pb_dynamics )	// not in the VIZ version
1352 		stdmtl2CD.CreateParamDlg(std2_dynamics, hwMtlEdit, imp, this);
1353 	// restore any saved rollout state
1354 	stdmtl2CD.RestoreRolloutState();
1355 	UpdateMapButtons();
1356 	UpdateExtendedMapButtons();
1357 
1358 	macroRecorder->Enable();
1359 	return masterDlg;
1360 }
1361 
SetDlgThing(ParamDlg * dlg)1362 BOOL XRayMtl::SetDlgThing(ParamDlg* dlg)
1363 {
1364 	KillRefmsg kill( killRefmsg );
1365 
1366 	// set the appropriate 'thing' sub-object for each secondary dialog
1367 	if (dlg == pShaderDlg)
1368 	{
1369 		// handle material switching in the shader dialog, incoming material is 'this'
1370 		assert (SuperClassID() == MATERIAL_CLASS_ID);
1371 		assert (ClassID() == XRAYMTL_CLASS_ID);
1372 		XRayMtl* oldMtl = (XRayMtl*)pShaderDlg->GetThing();
1373 		ULONG oldParams, newParams;
1374 		Class_ID newClassId, oldClassId;
1375 
1376 		if (oldMtl) {
1377 			Shader* oldShader = oldMtl->GetShader();
1378 			oldParams = oldShader->SupportStdParams();
1379 			oldClassId = oldShader->ClassID();
1380 		} else oldParams = 0;;
1381 
1382 		newParams = pShader->SupportStdParams();
1383 		newClassId = pShader->ClassID();
1384 
1385 		if ( shaderId < 0 ) {
1386 			//it's the standin shader
1387 			int i = -1;
1388 			//			DbgAssert(0);
1389 			//			SetShaderIndx( FindShader( pShader->ClassID() ), FALSE );
1390 		}
1391 
1392 		// see if we need to change Shader basic params rollup
1393 		if ( (oldClassId == newClassId) ||
1394 			((newParams & STD_BASIC2_DLG) && (oldParams & STD_BASIC2_DLG)) ){
1395 				assert( pShaderDlg );
1396 				// update in case of partial stdParam support
1397 				pShaderDlg->SetThings(this, pShader);
1398 				pShader->SetParamDlg( pShaderDlg );
1399 				pShaderDlg->ReloadDialog();
1400 				UpdateMapButtons();
1401 			} else {
1402 				// different shader in this Std2Mtl, toss out the old rollup
1403 				HWND oldPanel = pShaderDlg->GetHWnd();
1404 				masterDlg->DeleteDlg(pShaderDlg);
1405 				pShaderDlg->DeleteThis();
1406 
1407 				// make a new one
1408 				pShaderDlg = pShader->CreateParamDialog(oldPanel, curHwmEdit, curImp, this,
1409 					(flags & NEWSTDMTL_ROLLUP1_OPEN ? 0 : APPENDROLL_CLOSED));
1410 				pShader->SetParamDlg(pShaderDlg);
1411 				pShaderDlg->LoadDialog(TRUE);
1412 				masterDlg->AddDlg(pShaderDlg);
1413 
1414 				UpdateMapButtons(); // calls update texmaps
1415 			}
1416 	}
1417 	else if (dlg == texmapDlg)
1418 	{
1419 		texmapDlg->SetThing(this);
1420 		UpdateTexmaps();
1421 		UpdateLockADTex(TRUE);
1422 	}
1423 	else if (dlg == extendedDlg)
1424 	{
1425 		extendedDlg->SetThing(this);
1426 		UpdateExtraParams( pShader->SupportStdParams() );
1427 		UpdateExtendedMapButtons();
1428 		std2_extended_blk.SetSubTexNo(std2_ep_filter_map, stdIDToChannel[ID_FI]);
1429 	}
1430 	else if (dlg == samplingDlg)
1431 	{
1432 		samplingDlg->SetThing(this);
1433 		if ( samplerId < 0 ) {
1434 			DbgAssert(0);
1435 			//			SetSamplerIndx( FindSampler( pixelSampler->ClassID() ) );
1436 		}
1437 		UpdateSamplingParams();
1438 	}
1439 	else if ( pb_dynamics == NULL )
1440 	{
1441 		//maybe do something here for viz case of no pb_dynamics
1442 		int i = 9;
1443 	}else if ( pb_xray == NULL )
1444 	{
1445 		//maybe do something here for viz case of no pb_dynamics
1446 		int i = 9;
1447 	}
1448 	else
1449 		return FALSE;
1450 	return TRUE;
1451 }
1452 
1453 // compare function for sorting Shader Tab<>
classDescListCompare(const void * elem1,const void * elem2)1454 static int __cdecl classDescListCompare(const void *elem1, const void *elem2)
1455 {
1456 	ClassDesc* s1 = *(ClassDesc**)elem1;
1457 	ClassDesc* s2 = *(ClassDesc**)elem2;
1458 	TSTR sn1 = s1->ClassName();  // need to snap name string, since both use GetString()
1459 	TSTR sn2 = s2->ClassName();
1460 	return _tcscmp(sn1.data(), sn2.data());
1461 }
1462 
LoadShaderList()1463 void XRayMtl::LoadShaderList()
1464 {
1465 	// loads static shader list with name-sorted Shader ClassDesc*'s
1466 	shaderList.ZeroCount();
1467 	SubClassList* scList = GetCOREInterface()->GetDllDir().ClassDir().GetClassList(SHADER_CLASS_ID);
1468 	for (long i = 0, j = 0; i < scList->Count(ACC_ALL); ++i) {
1469 		if ( (*scList)[ i ].IsPublic() ) {
1470 			ClassDesc* pClassD = (*scList)[ i ].CD();
1471 			shaderList.Append(1, &pClassD);
1472 		}
1473 	}
1474 	shaderList.Sort(&classDescListCompare);
1475 }
1476 
NumShaders()1477 int XRayMtl::NumShaders()
1478 {
1479 	if (shaderList.Count() == 0)
1480 		LoadShaderList();
1481 	return shaderList.Count();
1482 }
1483 
GetShaderCD(int i)1484 ClassDesc* XRayMtl::GetShaderCD(int i)
1485 {
1486 	if (shaderList.Count() == 0)
1487 		LoadShaderList();
1488 	return (i >= 0 && i < shaderList.Count()) ? shaderList[i] : NULL;
1489 }
1490 
LoadSamplerList()1491 void XRayMtl::LoadSamplerList()
1492 {
1493 	// loads static sampler list with name-sorted Sampler ClassDesc*'s
1494 	samplerList.ZeroCount();
1495 	SubClassList* scList = GetCOREInterface()->GetDllDir().ClassDir().GetClassList(SAMPLER_CLASS_ID);
1496 	for (long i = 0, j = 0; i < scList->Count(ACC_ALL); ++i) {
1497 		if ( (*scList)[ i ].IsPublic() ) {
1498 			ClassDesc* pClassD = (*scList)[ i ].CD();
1499 			samplerList.Append(1, &pClassD);
1500 		}
1501 	}
1502 	samplerList.Sort(&classDescListCompare);
1503 }
1504 
NumSamplers()1505 int XRayMtl::NumSamplers()
1506 {
1507 	if (samplerList.Count() == 0)
1508 		LoadSamplerList();
1509 	return samplerList.Count();
1510 }
1511 
GetSamplerCD(int i)1512 ClassDesc* XRayMtl::GetSamplerCD(int i)
1513 {
1514 	if (samplerList.Count() == 0)
1515 		LoadSamplerList();
1516 	return (i >= 0 && i < samplerList.Count()) ? samplerList[i] : NULL;
1517 }
1518 
1519 
1520 //-------------------------------------------------------------------
1521 // DS: This class is handy for implementing UNDO - 10/31/00
1522 #if MAX_VERSION_MAJOR<=5
1523 	#define  SRM_CLASS_ID 0xB8073421
1524 	class SingleRefMaker: public ReferenceMaker {
1525 	public:
1526 		RefTargetHandle rtarget;
SingleRefMaker()1527 		SingleRefMaker() { rtarget = NULL; }
~SingleRefMaker()1528 		~SingleRefMaker() {
1529 			DeleteAllRefsFromMe();
1530 		}
SetRef(RefTargetHandle rt)1531 		void SetRef(RefTargetHandle rt) {
1532 			theHold.Suspend();
1533 			ReplaceReference(0,rt);
1534 			theHold.Resume();
1535 		}
GetRef()1536 		RefTargetHandle GetRef() { return rtarget; }
1537 		// ReferenceMaker
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)1538 		RefResult NotifyRefChanged( Interval changeInt,RefTargetHandle hTarget,
1539 			PartID& partID, RefMessage message ) {
1540 				if (message==REFMSG_TARGET_DELETED) {
1541 					if (hTarget==rtarget)
1542 						rtarget = NULL;
1543 				}
1544 				return REF_SUCCEED;
1545 			}
DeleteThis()1546 			void DeleteThis() { delete this; }
1547 
SuperClassID()1548 			SClass_ID  SuperClassID() { return SRM_CLASS_ID; }
1549 			// From ref
NumRefs()1550 			int NumRefs() { return 1; }
GetReference(int i)1551 			RefTargetHandle GetReference(int i) { return rtarget; }
SetReference(int i,RefTargetHandle rtarg)1552 			void SetReference(int i, RefTargetHandle rtarg) { rtarget = rtarg;			}
CanTransferReference(int i)1553 			BOOL CanTransferReference(int i) {return FALSE;}
1554 	};
1555 #endif
1556 
1557 //-------------------------------------------------------------------
1558 // This handles Undo/Redo of SwitchShader
1559 
1560 class SwitchShaderRestore: public RestoreObj {
1561 public:
1562 	XRayMtl *mtl;
1563 	SingleRefMaker oldShader;
1564 	SingleRefMaker newShader;
SwitchShaderRestore()1565 	SwitchShaderRestore() { mtl = NULL; }
SwitchShaderRestore(XRayMtl * m,Shader * olds,Shader * news)1566 	SwitchShaderRestore( XRayMtl * m, Shader *olds, Shader *news) {
1567 		mtl = m;
1568 		oldShader.SetRef(olds);
1569 		newShader.SetRef(news);
1570 	}
Restore(int isUndo)1571 	void Restore(int isUndo) {
1572 		mtl->SwitchShader((Shader *)oldShader.GetRef());
1573 	}
Redo()1574 	void Redo() {
1575 		mtl->SwitchShader((Shader *)newShader.GetRef());
1576 	}
Description()1577 	TSTR Description() { return(TSTR(_T("SwitchShaderRestore"))); }
1578 };
1579 
1580 
1581 //--------------------------------------------------------------------------
1582 
1583 
SwitchShader(Shader * newShader,BOOL loadDlg)1584 void XRayMtl::SwitchShader(Shader* newShader, BOOL loadDlg )
1585 {
1586 	// switch to a different shader
1587 	SuspendAnimate();
1588 	Class_ID oldShaderId = pShader? pShader->ClassID(): Class_ID(0,0);
1589 	Class_ID newShaderId = newShader->ClassID();
1590 	Class_ID constShaderId( CONSTClassID, 0 );
1591 	if ( newShaderId != oldShaderId )
1592 	{
1593 		if ( pb_extended ) {
1594 			int n = pb_extended->IDtoIndex( std2_opacity );
1595 			pb_extended->RemoveController( n, 0);
1596 		}
1597 
1598 		theHold.Suspend(); //-----------------------------------------------------
1599 
1600 		if (newShaderId == constShaderId ) { // constant
1601 			SetFlag( NEWSTDMTL_FACETED, TRUE );
1602 			pb_shader->SetValue(std2_faceted, 0, TRUE );
1603 		} else if ( oldShaderId == constShaderId ) {
1604 			SetFlag( NEWSTDMTL_FACETED, FALSE );
1605 			pb_shader->SetValue(std2_faceted, 0, FALSE );
1606 		}
1607 
1608 		Shader * oldShader = GetShader();
1609 		ULONG	 oldParams = oldShader ? oldShader->SupportStdParams() : 0;
1610 		ShaderParamDlg* oldShaderDlg = oldShader ? oldShader->GetParamDlg() : loadDlg? pShaderDlg:NULL;
1611 
1612 		ULONG	 newParams = newShader->SupportStdParams();
1613 
1614 		// copy any params in common
1615 		if (  oldShader && newShader ){
1616 			ShuffleShaderParams( newShader, oldShader );
1617 			ShuffleTexMaps( newShader, oldShader );
1618 		}
1619 
1620 		theHold.Resume(); //-----------------------------------------------------
1621 
1622 		if (theHold.Holding())
1623 			theHold.Put(new SwitchShaderRestore(this,oldShader,newShader));  // this will make a ref to oldShader
1624 
1625 		theHold.Suspend(); //-----------------------------------------------------
1626 
1627 		// moved from below, or it crashes on reset
1628 		if( oldShader) oldShader->SetParamDlg(NULL);  // DS 3/9/99 ( undo may bring oldShader back, have to clear invalid pointer)
1629 		if(	oldShaderDlg )	oldShaderDlg->SetThings( this, NULL );
1630 
1631 		// NB: this deletes the oldShader ( unless it being ref'd by SwitchShaderRestore)
1632 		SetShader( newShader );
1633 
1634 
1635 		UpdateTexmaps();
1636 		std2_extended_blk.SetSubTexNo(std2_ep_filter_map, stdIDToChannel[ID_FI]);
1637 
1638 		// update UI if open
1639 		if (oldShaderDlg != NULL )
1640 		{
1641 			// enable or disable extra params
1642 			UpdateExtraParams( newParams );
1643 
1644 			// now update or replace the basic rollup
1645 			if ((newParams & STD_BASIC2_DLG) && (oldParams & STD_BASIC2_DLG)) {
1646 				// update in case of partial stdParam support
1647 				oldShaderDlg->SetThings( this, newShader );
1648 				newShader->SetParamDlg( oldShaderDlg );
1649 				oldShaderDlg->LoadDialog(TRUE);
1650 				pShaderDlg = oldShaderDlg;
1651 
1652 			} else {
1653 
1654 				HWND oldPanel = oldShaderDlg->GetHWnd();
1655 				masterDlg->DeleteDlg(oldShaderDlg);
1656 				oldShaderDlg->DeleteThis();
1657 
1658 				// including oldPanel replaces it...
1659 				pShaderDlg = newShader->CreateParamDialog(oldPanel,
1660 					curHwmEdit, curImp, this,
1661 					((flags & NEWSTDMTL_ROLLUP1_OPEN) ? 0 : APPENDROLL_CLOSED));
1662 				newShader->SetParamDlg(pShaderDlg,0);
1663 				pShaderDlg->LoadDialog(TRUE);
1664 				masterDlg->AddDlg(pShaderDlg);
1665 
1666 			}
1667 			newShader->SetParamDlg(pShaderDlg,0);
1668 			SyncADTexLock( newShader->GetLockADTex() );
1669 			UpdateMapButtons();
1670 			UpdateExtendedMapButtons();
1671 
1672 			UpdateMtlDisplay();
1673 
1674 		}// end, oldShaderDlg not NULL
1675 
1676 		theHold.Resume(); //--------------------------------------------------
1677 
1678 	}
1679 	ResumeAnimate();
1680 }
1681 
1682 // this is exposed at stdmat2 level
SwitchShader(Class_ID shaderId)1683 BOOL XRayMtl::SwitchShader(Class_ID shaderId)
1684 {
1685 	ClassDesc* pCD;
1686 	int n = FindShader( shaderId, &pCD );
1687 	if ( pCD ){
1688 		//SS 1/26/2000: fix suggested by Kells
1689 		//SwitchShader(pCD);
1690 		SetShaderIndx(n);	// sets pb2 & set calls switchshader w/ a real shader
1691 		return TRUE;
1692 	}
1693 	return FALSE;
1694 }
1695 
1696 
SwitchShader(ClassDesc * pNewCD)1697 void XRayMtl::SwitchShader(ClassDesc* pNewCD)
1698 {
1699 	// create the new shader object
1700 	Shader * newShader = (Shader*)(pNewCD->Create(0));
1701 	newShader->Reset();	// creates pblock
1702 
1703 	SwitchShader( newShader );
1704 }
1705 
1706 
1707 // these provide R 2.5 id access to the old shaders.
SetShading(int s)1708 void XRayMtl::SetShading(int s)
1709 {
1710 	long cid;
1711 	pb_shader->SetValue(std2_faceted,0,FALSE);
1712 	switch( s ) {
1713 case 0: cid = PHONGClassID;
1714 	pb_shader->SetValue(std2_faceted,0,TRUE);
1715 	break;
1716 case 1: cid = PHONGClassID; break;
1717 case 2: cid = METALClassID; break;
1718 case 3: cid = BLINNClassID; break;
1719 	}
1720 	long indx =  FindShader( Class_ID(cid, 0) );
1721 
1722 	// this sets the new shader via pb2 accessor
1723 	SetShaderIndx( indx );
1724 }
1725 
1726 // all faceted shaders approximated by constant, all new shaders by blinn.
GetShading()1727 int XRayMtl::GetShading() {
1728 	if (IsFaceted()) return 0;
1729 	Class_ID id = pShader->ClassID();
1730 	if ( id == Class_ID(PHONGClassID,0) ) return 1;
1731 	else if ( id == Class_ID(METALClassID,0) ) return 2;
1732 	return 3;
1733 }
1734 
1735 
1736 //-------------------------------------------------------------------
1737 // This handles Undo/Redo of SwitchSampler
1738 
1739 class SwitchSamplerRestore: public RestoreObj, public ReferenceMaker {
1740 public:
1741 	XRayMtl *mtl;
1742 	Sampler *saveSampler;
SwitchSamplerRestore()1743 	SwitchSamplerRestore() { saveSampler = NULL; mtl = NULL; }
SwitchSamplerRestore(XRayMtl * m,Sampler * s)1744 	SwitchSamplerRestore( XRayMtl * m, Sampler *s) {
1745 		mtl = m;
1746 		saveSampler = NULL;
1747 		theHold.Suspend();
1748 		ReplaceReference(0,s);
1749 		theHold.Resume();
1750 	}
~SwitchSamplerRestore()1751 	~SwitchSamplerRestore() { DeleteAllRefsFromMe();	}
Switch()1752 	void Switch() {
1753 		Sampler *samp = mtl->pixelSampler;
1754 
1755 		samp->SetAFlag(A_LOCK_TARGET); // keeps sh from getting auto-deleted
1756 		mtl->SwitchSampler(saveSampler);
1757 		samp->ClearAFlag(A_LOCK_TARGET);
1758 
1759 		ReplaceReference(0,samp);
1760 	}
Restore(int isUndo)1761 	void Restore(int isUndo) { Switch(); }
Redo()1762 	void Redo() { Switch(); }
Description()1763 	TSTR Description() { return(TSTR(_T("SwitchSamplerRestore"))); }
1764 
1765 	// ReferenceMaker
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)1766 	RefResult NotifyRefChanged( Interval changeInt,RefTargetHandle hTarget,
1767 		PartID& partID, RefMessage message ) {
1768 			if (message==REFMSG_TARGET_DELETED) {
1769 				if (hTarget==saveSampler)
1770 					saveSampler = NULL;
1771 			}
1772 			return REF_SUCCEED;
1773 		}
DeleteThis()1774 		void DeleteThis() { SwitchSamplerRestore* ptr=this; delete ptr; }
1775 
1776 		// From ref
NumRefs()1777 		int NumRefs() { return 1; }
GetReference(int i)1778 		RefTargetHandle GetReference(int i) { return saveSampler; }
SetReference(int i,RefTargetHandle rtarg)1779 		void SetReference(int i, RefTargetHandle rtarg) { 	saveSampler = (Sampler*)rtarg;	}
CanTransferReference(int i)1780 		BOOL CanTransferReference(int i) {return FALSE;}
1781 };
1782 
1783 
1784 //--------------------------------------------------------------------------
1785 
1786 // copy of classid of the default sampler
1787 static Class_ID defaultSamplerID( DEFAULT_SAMPLER_CLASS_ID , 0);
1788 
1789 
1790 
SwitchSampler(Sampler * newSampler)1791 void XRayMtl::SwitchSampler( Sampler* newSampler )
1792 {
1793 	theHold.Suspend(); //-----------------------------------------------------
1794 
1795 	DbgAssert( newSampler );
1796 	Class_ID oldSamplerId = pixelSampler? pixelSampler->ClassID(): Class_ID(0,0);
1797 	Class_ID newSamplerId = newSampler->ClassID();
1798 
1799 	if ( oldSamplerId != newSamplerId ) {
1800 
1801 		theHold.Resume(); //-----------------------------------------------------
1802 		if (theHold.Holding())
1803 			theHold.Put(new SwitchSamplerRestore(this, pixelSampler));  // this will make a ref to oldShader
1804 		theHold.Suspend(); //-----------------------------------------------------
1805 
1806 		SetPixelSampler( newSampler );
1807 	}
1808 
1809 	if ( pb_sampling )
1810 		UpdateSamplingParams();
1811 
1812 	theHold.Resume(); //-----------------------------------------------------
1813 }
1814 
1815 
SwitchSampler(ClassDesc * pNewCD)1816 void XRayMtl::SwitchSampler(ClassDesc* pNewCD)
1817 {
1818 	//	if ( ! pNewCD ) {
1819 	// get default
1820 	//		ClassDesc* pCD;
1821 	//		int indx = FindSampler( defaultSamplerID, &pCD );
1822 	//		pNewCD = pCD;
1823 	//		DbgAssert( pNewCD);
1824 	//	}
1825 	DbgAssert( pNewCD);
1826 	Sampler * newSampler = (Sampler*)(pNewCD->Create(0));
1827 	SwitchSampler( newSampler );
1828 }
1829 
1830 // this is exposed at stdmat2 level
SwitchSampler(Class_ID samplerId)1831 BOOL XRayMtl::SwitchSampler(Class_ID samplerId){
1832 	//	ClassDesc* pCD;
1833 	//	int n = FindSampler( samplerId, &pCD );
1834 	int n = FindSampler( samplerId );
1835 	//	if ( pCD ){
1836 	if ( n >= 0 ){
1837 		//		SwitchSampler( (Sampler*)(pCD->Create(0)) );
1838 		SetSamplerIndx( n );
1839 		return TRUE;
1840 	}
1841 	return FALSE;
1842 }
1843 
1844 
1845 
SetPixelSampler(Sampler * sampler)1846 void XRayMtl::SetPixelSampler( Sampler * sampler )
1847 {
1848 	BOOL on = pixelSampler? pixelSampler->GetEnable() : FALSE;
1849 	BOOL superTex = pixelSampler? pixelSampler->GetTextureSuperSampleOn() : TRUE;
1850 	float quality = pixelSampler? pixelSampler->GetQuality() : 0.5f;
1851 	ReplaceReference( SAMPLER_REF, sampler );
1852 	NotifyDependents(FOREVER, 0, REFMSG_SUBANIM_STRUCTURE_CHANGED);
1853 	if(pixelSampler) {
1854 		pixelSampler->SetEnable( on );
1855 		pixelSampler->SetTextureSuperSampleOn( superTex );
1856 		pixelSampler->SetQuality( quality );
1857 	}
1858 }
1859 
1860 static TCHAR dots[] = _T(". . . . . . . . . . . . . . . . . . . . . . . .");
1861 
UpdateTexmaps()1862 void XRayMtl::UpdateTexmaps()
1863 {
1864 	// if the UI is up for the maps paramblock, adjust button text and enables
1865 	// according to current shader's capabilities
1866 	// UI controls are updated indirectly via calls on the ParamMap2.
1867 	// further, a Param Alias table is set up for all the pmap Tab<> params for scripter access
1868 	IParamMap2* pmap = pb_maps->GetMap();
1869 	Shader* pShader = GetShader();
1870 	long nShaderMapChannels = pShader->nTexChannelsSupported();
1871 	long nMtlMapChannels = MTL_NTEXMAPS;
1872 	pb_maps->ClearParamAliases();
1873 	int slevChan = pShader->StdIDToChannel( ID_SS );
1874 
1875 	for ( long i = 0; i < STD2_NMAX_TEXMAPS; ++i )
1876 	{
1877 		if ( i < nShaderMapChannels )
1878 		{
1879 			BOOL isSupported = ! (pShader->ChannelType( i ) & UNSUPPORTED_CHANNEL);
1880 			if (pmap != NULL)
1881 			{
1882 				TSTR chanName = maps->txmap[i].name = pShader->GetTexChannelName(i);
1883 				// append dots
1884 				int n = chanName.length();
1885 				chanName.append( _T(" " ) );
1886 				chanName.append( &dots[ n+1 ] );
1887 				pmap->SetText(std2_map_enables, chanName, i);
1888 				pmap->Enable(std2_map_enables, isSupported, i);
1889 				pmap->Enable(std2_map_amnts, isSupported, i);
1890 				pmap->Enable(std2_maps, isSupported, i);
1891 
1892 				if ( i == slevChan || pShader->ChannelType( i ) == SLEV_CHANNEL )
1893 					pmap->SetRange(std2_map_amnts, -999, 999, i);
1894 				else
1895 					pmap->SetRange(std2_map_amnts, 0, 100, i);
1896 
1897 			}
1898 			// set up the Tab<> param aliases
1899 			TSTR chanIntName = pShader->GetTexChannelInternalName(i);
1900 			if (chanIntName.Length() > 0)
1901 			{
1902 				channelTypes[ i ] = pShader->ChannelType( i );
1903 				pb_maps->DefineParamAlias(chanIntName, std2_maps, i);
1904 				pb_maps->DefineParamAlias(chanIntName + _T("Enable"), std2_map_enables, i);  // JBW 5/24/99, made non-localizable (as names s/b internal)
1905 				pb_maps->DefineParamAlias(chanIntName + _T("Amount"), std2_map_amnts, i);
1906 			}
1907 		}
1908 		else
1909 		{ // beyond the end of supported shader channels
1910 			if (pmap != NULL)
1911 			{
1912 				// add the mtls texture channels
1913 				if ( nMtlMapChannels > 0 ) {
1914 					TSTR chanName = maps->txmap[i].name = GetString( mtlChannelNameIDS[ i - nShaderMapChannels ] );
1915 					// append dots
1916 					int n = chanName.length();
1917 					chanName.append( _T(" " ) );
1918 					chanName.append( &dots[ n+1 ] );
1919 					pmap->SetText(std2_map_enables, chanName, i);
1920 					pmap->Enable(std2_map_enables, TRUE, i);
1921 					pmap->Enable(std2_map_amnts, TRUE, i);
1922 					pmap->Enable(std2_maps, TRUE, i);
1923 					// range, first channel is bumps, last is displacement
1924 					if ( nMtlMapChannels == MTL_NTEXMAPS || nMtlMapChannels == 1 )
1925 						pmap->SetRange(std2_map_amnts, -999, 999, i);
1926 					else
1927 						pmap->SetRange(std2_map_amnts, 0, 100, i);
1928 
1929 					--nMtlMapChannels;
1930 
1931 				} else {
1932 					// channel is not used for this mtl/shader
1933 					pmap->SetText(std2_map_enables, dots, i);
1934 					macroRecorder->Disable();
1935 					SetTexmapAmt(i, 0.0f, 0);
1936 					macroRecorder->Enable();
1937 					pmap->Enable(std2_map_enables, FALSE, i);
1938 					pmap->Enable(std2_map_amnts, FALSE, i);
1939 					pmap->Enable(std2_maps, FALSE, i);
1940 				}
1941 			}
1942 			TSTR chanIntName = mtlChannelInternalNames[ i - nShaderMapChannels ] ;
1943 			if (chanIntName.Length() > 0)
1944 			{
1945 				channelTypes[ i ] = mtlChannelType[ i - nShaderMapChannels ];
1946 				pb_maps->DefineParamAlias(chanIntName, std2_maps, i);
1947 				pb_maps->DefineParamAlias(chanIntName + GetString(IDS_JW_ENABLE), std2_map_enables, i);
1948 				pb_maps->DefineParamAlias(chanIntName + GetString(IDS_JW_AMOUNT), std2_map_amnts, i);
1949 			}
1950 
1951 		}
1952 	}
1953 
1954 	// last do the Channel Ids from stdMat
1955 	for ( i = 0; i < N_ID_CHANNELS; ++i ){
1956 		int chan = pShader->StdIDToChannel(i);
1957 		if ( chan >= 0 ) {
1958 			stdIDToChannel[i] = chan;
1959 		} else if (mtlStdIDToChannel[ i ] >= 0){
1960 			stdIDToChannel[i] = mtlStdIDToChannel[ i ] + pShader->nTexChannelsSupported();
1961 		} else
1962 			stdIDToChannel[i] = -1;
1963 	}
1964 
1965 	// disable for old metal
1966 	ULONG stdParms =  pShader->SupportStdParams();
1967 	if ( (stdParms & STD_BASIC2_DLG) &&  (stdParms & STD_PARAM_METAL) ){
1968 		//metal std shader, turn off stuff
1969 		int n = stdIDToChannel[ ID_SP ];
1970 		if ( pmap ) {
1971 			pmap->Enable(std2_map_amnts, FALSE, n );
1972 			pmap->Enable(std2_maps, FALSE, n);
1973 			pmap->Enable(std2_map_enables, FALSE, n);
1974 		}
1975 	}
1976 	// disable filter on additive/subtractive
1977 	if ( (stdParms & STD_EXTRA_DLG) &&  TRANSP_FILTER != GetTransparencyType() ){
1978 		//metal std shader, turn off stuff
1979 		int n = stdIDToChannel[ ID_FI ];
1980 		if ( pmap ) {
1981 			pmap->Enable(std2_map_amnts, FALSE, n );
1982 			pmap->Enable(std2_maps, FALSE, n);
1983 			pmap->Enable(std2_map_enables, FALSE, n);
1984 		}
1985 	}
1986 
1987 }
1988 
1989 static TCHAR* mapStates[] = { _T(" "), _T("m"),  _T("M") };
1990 
UpdateMapButtons()1991 void XRayMtl::UpdateMapButtons()
1992 {
1993 	UpdateTexmaps();
1994 	if (IsShaderInUI()){
1995 		pShader->GetParamDlg()->UpdateMapButtons();
1996 		UpdateLockADTex(TRUE);
1997 	}
1998 	//	UpdateExtendedMapButtons();
1999 }
2000 
UpdateExtendedMapButtons()2001 void XRayMtl::UpdateExtendedMapButtons()
2002 {
2003 	IParamMap2* pmap = pb_extended->GetMap();
2004 	if (pmap != NULL){
2005 		int filtChan = stdIDToChannel[ID_FI];
2006 		int state = GetMapState( filtChan );
2007 		pmap->SetText(std2_ep_filter_map, mapStates[ state ]);
2008 
2009 		TSTR nm	 = GetMapName( filtChan );
2010 		pmap->SetTooltip(std2_ep_filter_map, TRUE, nm);
2011 	}
2012 }
2013 
UpdateSamplingParams()2014 void XRayMtl::UpdateSamplingParams()
2015 {
2016 	IParamMap2* map = pb_sampling->GetMap();
2017 	if ( map ) {
2018 		HWND hwnd = map->GetHWnd();
2019 		BOOL qualityOn = pixelSampler->SupportsQualityLevels()>0 ? TRUE:FALSE ;
2020 		map->Show(std2_ssampler_qual, qualityOn );
2021 		HWND hwQual = GetDlgItem( hwnd, IDC_QUALITY_TEXT );
2022 		ShowWindow( hwQual, qualityOn );
2023 
2024 		ULONG samplerParms = pixelSampler->SupportsStdParams();
2025 		map->Show(std2_ssampler_adapt_on, samplerParms & ADAPTIVE_CHECK_BOX );
2026 		map->Enable(std2_ssampler_adapt_threshold, pixelSampler->IsAdaptiveOn() );
2027 		map->Show(std2_ssampler_adapt_threshold, samplerParms & ADAPTIVE_THRESHOLD );
2028 
2029 		map->Show(std2_ssampler_subsample_tex_on, samplerParms & SUPER_SAMPLE_TEX_CHECK_BOX );
2030 		HWND hwThresh = GetDlgItem( hwnd, IDC_ADAPT_STATIC );
2031 		ShowWindow( hwThresh, samplerParms & ADAPTIVE_THRESHOLD?TRUE:FALSE );
2032 		map->Show(std2_ssampler_advanced, samplerParms & ADVANCED_DLG_BUTTON );
2033 		SetDlgItemText( hwnd, IDC_COMMENT_TEXT, pixelSampler->GetDefaultComment() );
2034 
2035 		map->Show(std2_ssampler_param0, samplerParms & OPTIONAL_PARAM_0 );
2036 		if( samplerParms & OPTIONAL_PARAM_0 )
2037 			SetDlgItemText( hwnd, IDC_PARAM0_TEXT, pixelSampler->GetOptionalParamName(0) );
2038 		ShowWindow( GetDlgItem( hwnd, IDC_PARAM0_TEXT ), samplerParms & OPTIONAL_PARAM_0 );
2039 
2040 		map->Show(std2_ssampler_param1, samplerParms & OPTIONAL_PARAM_1 );
2041 		if( samplerParms & OPTIONAL_PARAM_1 )
2042 			SetDlgItemText( hwnd, IDC_PARAM1_TEXT, pixelSampler->GetOptionalParamName(1) );
2043 		ShowWindow( GetDlgItem( hwnd, IDC_PARAM1_TEXT ), samplerParms & OPTIONAL_PARAM_1 );
2044 	}
2045 }
2046 
2047 // enable & disable extra params possibly overridden by the shader
UpdateExtraParams(ULONG stdParams)2048 void XRayMtl::UpdateExtraParams( ULONG stdParams )
2049 {
2050 	// update shader dlg map buttons
2051 	IParamMap2* pmap = pb_extended->GetMap();
2052 	if (pmap != NULL)
2053 	{
2054 		HWND hRollup = pmap->GetHWnd();
2055 		BOOL opacOn = ( stdParams & STD_EXTRA_OPACITY ) ? TRUE : FALSE;
2056 		pmap->Show( std2_opacity_type, opacOn );
2057 		pmap->Show( std2_falloff_type, opacOn );
2058 		pmap->Show( std2_falloff_amnt, opacOn );
2059 		ShowWindow( GetDlgItem(hRollup,  IDC_OPAC_TEXT1), opacOn );
2060 		ShowWindow( GetDlgItem(hRollup,  IDC_OPAC_TEXT2), opacOn );
2061 		ShowWindow( GetDlgItem(hRollup,  IDC_OPAC_TEXT3), opacOn );
2062 		ShowWindow( GetDlgItem(hRollup,  IDC_FILTER_OVERLAY), !opacOn );
2063 
2064 		BOOL reflOn = ( stdParams & STD_EXTRA_REFLECTION) ? TRUE : FALSE;
2065 		pmap->Show( std2_apply_refl_dimming, reflOn );
2066 		pmap->Show( std2_dim_lvl, reflOn );
2067 		pmap->Show( std2_refl_lvl, reflOn );
2068 		ShowWindow( GetDlgItem(hRollup,  IDC_REFL_TEXT1), reflOn );
2069 		ShowWindow( GetDlgItem(hRollup,  IDC_REFL_TEXT2), reflOn );
2070 		ShowWindow( GetDlgItem(hRollup,  IDC_REFL_BOX), reflOn );
2071 		//		EnableWindow( GetDlgItem(hRollup,  IDC_REFL_BOX), reflOn );
2072 
2073 		BOOL refrOn = ( stdParams & STD_EXTRA_REFRACTION ) ? TRUE : FALSE;
2074 		pmap->Show( std2_ior, refrOn );
2075 		ShowWindow( GetDlgItem(hRollup,  IDC_REFR_TEXT1), refrOn );
2076 
2077 		//		BOOL filterOn = (refrOn || opacOn) && GetTransparencyType() == TRANSP_FILTER;
2078 		BOOL filterOn = (refrOn && !opacOn) || (opacOn && GetTransparencyType() == TRANSP_FILTER);
2079 		pmap->Show( std2_filter_color, filterOn );
2080 		pmap->Show( std2_ep_filter_map, filterOn );
2081 		EnableWindow( GetDlgItem(hRollup,  IDC_OPAC_BOX), (refrOn || opacOn) );
2082 	}
2083 }
2084 
GetMapState(int nMap)2085 int XRayMtl::GetMapState( int nMap )
2086 {
2087 	Texmap *t = (*maps)[nMap].map;
2088 	if ( t == NULL ) return 0;
2089 	return (*maps)[nMap].mapOn ? 2 :1;
2090 }
2091 
2092 
GetMapName(int nMap)2093 TSTR XRayMtl::GetMapName( int nMap )
2094 {
2095 	Texmap *t = (*maps)[nMap].map;
2096 	if ( t == NULL )
2097 		return TSTR( GetString( IDS_KE_NONE ) );
2098 	return t->GetFullName();
2099 }
2100 
2101 
SyncADTexLock(BOOL lockOn)2102 void XRayMtl::SyncADTexLock( BOOL lockOn )
2103 {
2104 	pb_maps->SetValue(std2_mp_ad_texlock, 0, lockOn );
2105 	UpdateLockADTex(FALSE);
2106 	//	SetFlag( NEWSTDMTL_LOCK_ADTEX, lockOn );
2107 	// force an update
2108 	//	if (masterDlg)
2109 	//		masterDlg->ReloadDialog();
2110 }
2111 
UpdateLockADTex(BOOL passOn)2112 void XRayMtl::UpdateLockADTex( BOOL passOn )
2113 {
2114 	IParamMap2* pmap = pb_maps->GetMap();
2115 	int lock = 	GetFlag(NEWSTDMTL_LOCK_ADTEX)!=0;
2116 	if ( pShader->SupportStdParams() & STD_PARAM_LOCKADTEX ) {
2117 		if ( passOn ){
2118 			pShader->SetLockADTex( lock );
2119 			if (pmap != NULL && pShader->GetParamDlg())
2120 				pShader->GetParamDlg()->LoadDialog(TRUE);
2121 		}
2122 		if (pmap != NULL)
2123 		{
2124 			pmap->Show(std2_mp_ad_texlock, TRUE);
2125 			pmap->Enable(std2_maps, !lock, 0);
2126 		}
2127 	} else {
2128 		// no std params, so no amb/diff lock
2129 		if (pmap != NULL)
2130 		{
2131 			pmap->Show(std2_mp_ad_texlock, FALSE);
2132 			pmap->Enable(std2_maps, TRUE, 0);
2133 		}
2134 	}
2135 
2136 }
2137 
UpdateMtlDisplay()2138 void XRayMtl::UpdateMtlDisplay()
2139 {
2140 	IParamMap2* map = pb_maps->GetMap();
2141 	if (map != NULL)
2142 	{
2143 		//	 removed to avoid multiple viewport redraws on change shader
2144 		//		map->RedrawViews(GetCOREInterface()->GetTime());
2145 		map->Invalidate();
2146 	}
2147 }
2148 
2149 #define LIMIT0_1(x) if (x<0.0f) x = 0.0f; else if (x>1.0f) x = 1.0f;
2150 #define LIMIT1(x) if (x > 1.0f) x = 1.0f;
2151 #define LIMITMINMAX(x, min, max) if (x<min) x = min; else if (x>max) x = max;
2152 
LimitColor(Color c)2153 static Color LimitColor(Color c) {
2154 	LIMIT0_1(c.r);
2155 	LIMIT0_1(c.g);
2156 	LIMIT0_1(c.b);
2157 	return c;
2158 }
2159 
Update(TimeValue t,Interval & valid)2160 void XRayMtl::Update(TimeValue t, Interval &valid) {
2161 	Point3 p;
2162 	if (!ivalid.InInterval(t)) {
2163 		ivalid.SetInfinite();
2164 
2165 		pb_extended->GetValue(std2_filter_color, t, p, ivalid );
2166 		filter = LimitColor(Color(p.x, p.y, p.z));
2167 		pb_extended->GetValue(std2_ior, t, ioRefract, ivalid );
2168 		pb_extended->GetValue(std2_opacity, t, opacity, ivalid );
2169 		LIMIT0_1(opacity);
2170 
2171 		if (IsShaderInUI())
2172 			pShader->GetParamDlg()->UpdateOpacity();
2173 
2174 		pb_extended->GetValue(std2_falloff_amnt, t, opfall, ivalid );
2175 		LIMIT0_1(opfall);
2176 
2177 		pb_extended->GetValue(std2_wire_size, t, wireSize, ivalid );
2178 		pb_extended->GetValue(std2_dim_lvl, t, dimIntens, ivalid );
2179 		LIMIT0_1(dimIntens);
2180 		pb_extended->GetValue(std2_refl_lvl, t, dimMult, ivalid );
2181 
2182 		SetFlag(NEWSTDMTL_WIRE, pb_shader->GetInt(std2_wire, t));
2183 		SetFlag(NEWSTDMTL_2SIDE, pb_shader->GetInt(std2_two_sided, t));
2184 		SetFlag(NEWSTDMTL_FACEMAP, pb_shader->GetInt(std2_face_map, t));
2185 		SetFlag(NEWSTDMTL_FACETED, pb_shader->GetInt(std2_faceted, t));
2186 
2187 		SetFlag(NEWSTDMTL_ADD_TRANSP, pb_extended->GetInt(std2_opacity_type, t) == 2);
2188 		SetFlag(NEWSTDMTL_FILT_TRANSP, pb_extended->GetInt(std2_opacity_type, t) == 0);
2189 		SetFlag(NEWSTDMTL_FALLOFF_OUT, pb_extended->GetInt(std2_falloff_type, t) == 1);
2190 		SetFlag(NEWSTDMTL_WIRE_UNITS, pb_extended->GetInt(std2_wire_units, t) == 1);
2191 		SetFlag(NEWSTDMTL_LOCK_ADTEX, pb_maps->GetInt(std2_mp_ad_texlock, t) == 1);
2192 		dimReflect = pb_extended->GetInt(std2_apply_refl_dimming, t);
2193 
2194 		if (pShader)
2195 			pShader->Update( t, ivalid );
2196 
2197 		for (int i = 0; i < STD2_NMAX_TEXMAPS; i++)
2198 			if (MAPACTIVE(i))
2199 				maps->txmap[i].Update(t, ivalid);
2200 
2201 	}
2202 	valid &= ivalid;
2203 }
2204 
AmtKeyAtTime(int i,TimeValue t)2205 BOOL XRayMtl::AmtKeyAtTime(int i, TimeValue t) {
2206 	if (maps->txmap[i].amtCtrl)
2207 		return 	maps->txmap[i].amtCtrl->IsKeyAtTime(t,0);
2208 	else
2209 		return FALSE;
2210 }
2211 
2212 typedef struct {
2213 	float amount;
2214 	Control *amtCtrl;
2215 	Texmap *map;
2216 	BOOL mapOn;
2217 	TSTR name;
2218 } saveChan;
2219 
ShuffleTexMaps(Shader * newShader,Shader * oldShader)2220 void XRayMtl::ShuffleTexMaps( Shader* newShader, Shader* oldShader )
2221 {
2222 	saveChan oldMaps[STD2_NMAX_TEXMAPS];
2223 
2224 	for( long i = 0; i < STD2_NMAX_TEXMAPS; ++i ){
2225 		oldMaps[i].amtCtrl = maps->txmap[i].amtCtrl; maps->txmap[i].amtCtrl = NULL;
2226 		oldMaps[i].amount = maps->txmap[i].amount; maps->txmap[i].amount = 1.0f;
2227 		oldMaps[i].map = maps->txmap[i].map; maps->txmap[i].map = NULL;
2228 		oldMaps[i].mapOn = maps->txmap[i].mapOn; maps->txmap[i].mapOn = FALSE;
2229 		oldMaps[i].name = maps->txmap[i].name; maps->txmap[i].name = _T("");
2230 	}
2231 	int nOldShadeMaps = oldShader->nTexChannelsSupported();
2232 	int nNewShadeMaps = newShader->nTexChannelsSupported();
2233 
2234 	// for each new shader map
2235 	for( int oldChan, newChan = 0; newChan < nNewShadeMaps; ++newChan ){
2236 
2237 		TSTR newName = newShader->GetTexChannelInternalName(newChan);
2238 
2239 		// look for match in each old map
2240 		for ( oldChan = 0; oldChan < nOldShadeMaps; ++oldChan ) {
2241 			if ( newName == oldShader->GetTexChannelInternalName(oldChan) )
2242 				break;
2243 		}
2244 
2245 		if( oldChan < nOldShadeMaps ) {	// found it
2246 			maps->txmap[newChan].amtCtrl = oldMaps[oldChan].amtCtrl;
2247 			maps->txmap[newChan].amount = oldMaps[oldChan].amount;
2248 			maps->txmap[newChan].map = oldMaps[oldChan].map;
2249 			maps->txmap[newChan].mapOn = oldMaps[oldChan].mapOn;
2250 			maps->txmap[newChan].name = oldMaps[oldChan].name;
2251 		}
2252 
2253 	}// end, for each new map
2254 
2255 	// now do the mtl maps
2256 	for ( int n = 0; n < MTL_NTEXMAPS; ++n ){
2257 		newChan = n + nNewShadeMaps;
2258 		oldChan = n + nOldShadeMaps;
2259 		maps->txmap[newChan].amtCtrl = oldMaps[oldChan].amtCtrl;
2260 		maps->txmap[newChan].amount = oldMaps[oldChan].amount;
2261 		maps->txmap[newChan].map = oldMaps[oldChan].map;
2262 		maps->txmap[newChan].mapOn = oldMaps[oldChan].mapOn;
2263 		maps->txmap[newChan].name = oldMaps[oldChan].name;
2264 	}
2265 }
2266 
ShuffleShaderParams(Shader * newShader,Shader * oldShader)2267 void XRayMtl::ShuffleShaderParams( Shader* newShader, Shader* oldShader )
2268 {
2269 	ClassDesc2 *oldCD2 = NULL, *newCD2 = NULL;
2270 
2271 	ClassDesc * newCD;
2272 	FindShader( newShader->ClassID(), &newCD );
2273 
2274 	ClassDesc * oldCD;
2275 	FindShader( oldShader->ClassID(), &oldCD );
2276 
2277 	// check if we have a ParamBlock2-based shaders
2278 	if (oldCD != NULL && oldCD->InternalName() != NULL)
2279 		oldCD2 = (ClassDesc2*)oldCD;
2280 	if (newCD != NULL && newCD->InternalName() != NULL)
2281 		newCD2 = (ClassDesc2*)newCD;
2282 
2283 	// loop over destination shaders PB2-based parameters
2284 	if (oldCD2 != NULL && newCD2 != NULL){
2285 		// loop over each block in the new shader
2286 		for (int i = 0; i < newCD2->NumParamBlockDescs(); i++){
2287 			// get block descriptor and source paramblock
2288 			ParamBlockDesc2* newPBdesc = newCD2->GetParamBlockDesc(i);
2289 			IParamBlock2* newPB2 = newShader->GetParamBlockByID(newPBdesc->ID);
2290 			// loop over each new param and copy from old if there's a match
2291 			for (int j = 0; j < newPBdesc->count; j++){
2292 				ParamDef& paramDef = newPBdesc->paramdefs[j];
2293 
2294 				// Now search the old shaders blocks
2295 				for (int i = 0; i < oldCD2->NumParamBlockDescs(); i++){
2296 					ParamBlockDesc2* oldPBdesc = oldCD2->GetParamBlockDesc(i);
2297 					int j = oldPBdesc->NameToIndex(paramDef.int_name);
2298 					if (j >= 0){
2299 						// found an internal name match, get the dest pblock and param def
2300 						ParamDef& srcParamDef = oldPBdesc->paramdefs[j];
2301 						// copy only if types match
2302 						if (srcParamDef.type == paramDef.type){
2303 							IParamBlock2* oldPB2 = oldShader->GetParamBlockByID(oldPBdesc->ID);
2304 							newPB2->Assign(paramDef.ID, oldPB2, srcParamDef.ID);
2305 							goto nextParam;	// found it, outta here...
2306 						}
2307 
2308 					}
2309 				}
2310 nextParam:		;
2311 			}// end, dest param loop
2312 		}// end, desk block loop
2313 		Interval v;
2314 		v.SetInfinite();
2315 		newShader->Update(0, v);
2316 
2317 		// end, pb2 copying
2318 	} else {
2319 
2320 		// StdParam based copy
2321 		newShader->CopyStdParams( oldShader );
2322 	}
2323 }
2324 
GetXParency(int mtlNum,BOOL backFace)2325 float XRayMtl::GetXParency(int mtlNum, BOOL backFace) {
2326 	int opacChan = stdIDToChannel[ ID_OP ];
2327 
2328 	// When the mtl has "Show Map in Viewport" turned on, and has an opacity map,
2329 	// the opacity map over-rides the opacity.  DS 6/16/00
2330 	// (Actually, when the hardward doesn't support enough texture channels to do
2331 	// the opacity map, the overide is only true for NON-decal maps).
2332 	//
2333 	if (((*maps)[opacChan].map&&MAPACTIVE(opacChan)&&Active())) {
2334 		return 0.0f;
2335 	}
2336 
2337 	// The following statement looks dubious -- what is it trying to do? -- DS 6/16/00
2338 	if(opacity>0.9f && opfall>0.0f)
2339 		return 0.1f;
2340 	else
2341 		return 1.0f-opacity;
2342 }
2343 
Requirements(int subMtlNum)2344 ULONG XRayMtl::Requirements(int subMtlNum) {
2345 	ULONG req;
2346 
2347 	assert( pShader );
2348 	req = pShader->GetRequirements(subMtlNum);
2349 
2350 	int opacChan = stdIDToChannel[ ID_OP ];
2351 	int bumpChan = stdIDToChannel[ ID_BU ];
2352 	int dispChan = stdIDToChannel[ ID_DP ];
2353 
2354 	if (opacity!=1.0f||MAPACTIVE(opacChan)||opfall>0.0f) {
2355 		req |= MTLREQ_TRANSP;
2356 	}
2357 
2358 	if (opacity!=1.0f|| ((*maps)[opacChan].map&&MAPACTIVE(opacChan)&&Active()))
2359 		req |= MTLREQ_TRANSP_IN_VP;
2360 
2361 	for (int i=0; i<STD2_NMAX_TEXMAPS; i++) {
2362 		if (MAPACTIVE(i))
2363 			req |= (*maps)[i].map->Requirements(subMtlNum);
2364 	}
2365 	if (MAPACTIVE(bumpChan)) {
2366 		ULONG bmpreq = (*maps)[bumpChan].map->Requirements(subMtlNum);
2367 		if (bmpreq&MTLREQ_UV)
2368 			req |= MTLREQ_BUMPUV;
2369 		if (bmpreq&MTLREQ_UV2)
2370 			req |= MTLREQ_BUMPUV2;
2371 	}
2372 	if (flags&NEWSTDMTL_WIRE) 	req|= MTLREQ_WIRE;
2373 	if (flags&NEWSTDMTL_2SIDE) req|= MTLREQ_2SIDE;
2374 	//	if (pixelSampler && pixelSampler->GetEnable() )
2375 	if ( flags&NEWSTDMTL_SSAMP_ON )
2376 		req|= MTLREQ_SUPERSAMPLE;
2377 	if (flags&NEWSTDMTL_WIRE_UNITS) req|= MTLREQ_WIRE_ABS;
2378 	if (flags&NEWSTDMTL_FACEMAP) req |= MTLREQ_FACEMAP;
2379 	if (flags&NEWSTDMTL_ADD_TRANSP) req |= MTLREQ_ADDITIVE_TRANSP;
2380 	if (flags&NEWSTDMTL_FACETED) req |= MTLREQ_FACETED;
2381 	if (MAPACTIVE(dispChan)) req |= MTLREQ_DISPLACEMAP;
2382 	return req;
2383 }
2384 
MapSlotType(int i)2385 int XRayMtl::MapSlotType(int i)
2386 {
2387 	if (i==stdIDToChannel[ID_DP]) return MAPSLOT_DISPLACEMENT;  // DS 4/12/99
2388 	return (i==stdIDToChannel[ID_RL] || i==stdIDToChannel[ID_RR])?
2389 MAPSLOT_ENVIRON : MAPSLOT_TEXTURE;
2390 }
2391 
MappingsRequired(int subMtlNum,BitArray & mapreq,BitArray & bumpreq)2392 void XRayMtl::MappingsRequired(int subMtlNum, BitArray & mapreq, BitArray &bumpreq) {
2393 	int bumpChan = stdIDToChannel[ ID_BU ];
2394 	for (int i=0; i<STD2_NMAX_TEXMAPS; i++) {
2395 		if (MAPACTIVE(i)) {
2396 			if (i==bumpChan)
2397 				(*maps)[i].map->MappingsRequired(subMtlNum,bumpreq,bumpreq);
2398 			else
2399 				(*maps)[i].map->MappingsRequired(subMtlNum,mapreq,bumpreq);
2400 		}
2401 	}
2402 }
2403 
Validity(TimeValue t)2404 Interval XRayMtl::Validity(TimeValue t) {
2405 	Interval v;
2406 	Update(t, v);
2407 	return ivalid;
2408 }
2409 
NotifyChanged()2410 void XRayMtl::NotifyChanged() {
2411 	NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
2412 }
2413 
SetFlag(ULONG f,ULONG val)2414 void XRayMtl::SetFlag(ULONG f, ULONG val) {
2415 	if (val) flags|=f;
2416 	else flags &= ~f;
2417 }
2418 
SetTransparencyType(int type)2419 void XRayMtl::SetTransparencyType(int type) {
2420 	switch (type) {
2421 case TRANSP_SUBTRACTIVE:
2422 	SetFlag(NEWSTDMTL_ADD_TRANSP, 0);
2423 	SetFlag(NEWSTDMTL_FILT_TRANSP, 0);
2424 	pb_extended->SetValue(std2_opacity_type, 0, 1);
2425 	break;
2426 case TRANSP_ADDITIVE:
2427 	SetFlag(NEWSTDMTL_ADD_TRANSP, 1);
2428 	SetFlag(NEWSTDMTL_FILT_TRANSP, 0);
2429 	pb_extended->SetValue(std2_opacity_type, 0, 2);
2430 	break;
2431 case TRANSP_FILTER:
2432 	SetFlag(NEWSTDMTL_ADD_TRANSP, 0);
2433 	SetFlag(NEWSTDMTL_FILT_TRANSP, 1);
2434 	pb_extended->SetValue(std2_opacity_type, 0, 0);
2435 	break;
2436 	}
2437 }
2438 
DeleteThis()2439 void XRayMtl::DeleteThis()
2440 {
2441 	delete this;
2442 }
2443 
2444 
SubAnimName(int i)2445 TSTR XRayMtl::SubAnimName(int i) {
2446 	switch(i){
2447 case TEXMAPS_SUB: return TSTR(GetString( IDS_DS_TEXMAPS ));
2448 case SHADER_SUB: return TSTR(GetString( IDS_KE_SHADER ));
2449 case EXTRA_PB_SUB:	return TSTR(GetString( IDS_DS_EXTRA ));
2450 case SAMPLING_PB_SUB:	return TSTR(GetString( IDS_KE_SAMPLING ));
2451 case DYNAMICS_PB_SUB:	return TSTR(GetString( IDS_DS_DYNAMICS ));
2452 	}
2453 	return TSTR("");
2454 }
2455 
SubAnim(int i)2456 Animatable* XRayMtl::SubAnim(int i) {
2457 	switch(i) {
2458 case TEXMAPS_SUB: return maps;
2459 case SHADER_SUB: return pShader;
2460 case EXTRA_PB_SUB:	return pb_extended;
2461 case SAMPLING_PB_SUB:	return pb_sampling;
2462 case DYNAMICS_PB_SUB:	return pb_dynamics;
2463 default: DbgAssert(0); return NULL;
2464 	}
2465 }
2466 
SubNumToRefNum(int subNum)2467 int XRayMtl::SubNumToRefNum(int subNum)
2468 {
2469 	switch (subNum)
2470 	{
2471 	case TEXMAPS_SUB: return TEXMAPS_REF;
2472 	case SHADER_SUB: return SHADER_REF;
2473 	case EXTRA_PB_SUB:	return EXTENDED_PB_REF;
2474 	case SAMPLING_PB_SUB:	return SAMPLING_PB_REF;
2475 	case DYNAMICS_PB_SUB:	return DYNAMICS_PB_REF;
2476 	default: DbgAssert(0); return 0;
2477 	}
2478 }
2479 
2480 IParamBlock2*
GetParamBlock(int i)2481 XRayMtl::GetParamBlock(int i)
2482 {
2483 	switch (i)
2484 	{
2485 	case 0:	return pb_shader;
2486 	case 1:	return pb_extended;
2487 	case 2:	return pb_sampling;
2488 	case 3:	return pb_maps;
2489 	case 4:	return pb_dynamics;
2490 	case 5: return pb_xray;
2491 	}
2492 	return NULL;
2493 }
2494 
2495 IParamBlock2*
GetParamBlockByID(BlockID id)2496 XRayMtl::GetParamBlockByID(BlockID id)
2497 {
2498 	// return id'd ParamBlock
2499 	switch (id)
2500 	{
2501 	case std2_shader:	return pb_shader;
2502 	case std2_extended:	return pb_extended;
2503 	case std2_sampling:	return pb_sampling;
2504 	case std_maps:		return pb_maps;
2505 	case std2_dynamics:	return pb_dynamics;
2506 	case std2_xray:		return pb_xray;
2507 	}
2508 	return NULL;
2509 }
2510 
GetReference(int i)2511 RefTargetHandle XRayMtl::GetReference(int i) {
2512 	switch(i) {
2513 case OLD_PBLOCK_REF:	return old_pblock;  // old pblock, replaced by the 6 new pb2's
2514 case TEXMAPS_REF:		return maps;
2515 case SHADER_REF:		return pShader;
2516 case SHADER_PB_REF:		return pb_shader;
2517 case EXTENDED_PB_REF:	return pb_extended;
2518 case SAMPLING_PB_REF:	return pb_sampling;
2519 case MAPS_PB_REF:		return pb_maps;
2520 #ifndef DESIGN_VER
2521 case DYNAMICS_PB_REF:	return pb_dynamics;
2522 #else
2523 case DYNAMICS_PB_REF:	return NULL;
2524 #endif
2525 case XRAY_PB_REF:		return pb_xray;
2526 case SAMPLER_REF:		return pixelSampler;
2527 default: assert(0);		return NULL;
2528 	}
2529 }
2530 
SetReference(int i,RefTargetHandle rtarg)2531 void XRayMtl::SetReference(int i, RefTargetHandle rtarg) {
2532 	switch(i) {
2533 case OLD_PBLOCK_REF:	old_pblock = (IParamBlock*)rtarg; return;
2534 case TEXMAPS_REF:	{
2535 	maps = (Texmaps*)rtarg;
2536 	if (maps != NULL)
2537 		maps->client = this;
2538 	return;
2539 					}
2540 case SHADER_REF:
2541 	if (IsShaderInUI()){
2542 		pShader->GetParamDlg()->SetThings(this, NULL);
2543 		pShader->SetParamDlg(NULL);
2544 	}
2545 	pShader = (Shader*)rtarg;
2546 
2547 	return;
2548 case SHADER_PB_REF:		pb_shader		= (IParamBlock2*)rtarg; return;
2549 case EXTENDED_PB_REF:	pb_extended		= (IParamBlock2*)rtarg; return;
2550 case SAMPLING_PB_REF:	pb_sampling		= (IParamBlock2*)rtarg; return;
2551 case MAPS_PB_REF:		pb_maps			= (IParamBlock2*)rtarg; return;
2552 case DYNAMICS_PB_REF:	pb_dynamics		= (IParamBlock2*)rtarg; return;
2553 case XRAY_PB_REF:		pb_xray			= (IParamBlock2*)rtarg; return;
2554 case SAMPLER_REF:		pixelSampler	= (Sampler*)rtarg; return;
2555 default: assert(0);
2556 	}
2557 }
2558 
SetSubTexmap(int i,Texmap * m)2559 void XRayMtl::SetSubTexmap(int i, Texmap *m)
2560 {
2561 	assert(i < STD2_NMAX_TEXMAPS);
2562 	pb_maps->SetValue(std2_maps, TimeValue(0), m, i);
2563 }
2564 
2565 // mjm - begin - 06.02.00
UpdateReshadeRequirements(RefTargetHandle hTarget,PartID partID)2566 void XRayMtl::UpdateReshadeRequirements(RefTargetHandle hTarget, PartID partID)
2567 {
2568 	if (!killRefmsg.DistributeRefmsg())
2569 	{
2570 		mReshadeRQ = RR_None;
2571 	}
2572 	else if (hTarget == maps)
2573 	{
2574 		mReshadeRQ = RR_NeedPreshade;
2575 	}
2576 	else if (hTarget == pShader)
2577 	{
2578 		mReshadeRQ = RR_NeedReshade;
2579 	}
2580 	else if (hTarget == pb_xray)
2581 	{
2582 		mReshadeRQ = RR_None;
2583 	}
2584 	else if (hTarget == pb_shader)
2585 	{
2586 		mReshadeRQ = RR_NeedReshade;
2587 	}
2588 	else if (hTarget == pb_extended)
2589 	{
2590 		mReshadeRQ = RR_NeedReshade;
2591 	}
2592 	else if (hTarget == pb_sampling)
2593 	{
2594 		mReshadeRQ = RR_None;
2595 	}
2596 	else if (hTarget == pb_maps)
2597 	{
2598 		if ( pb_maps->LastNotifyParamID() == std2_map_amnts)
2599 			mReshadeRQ = RR_NeedReshade;
2600 		else
2601 			mReshadeRQ = RR_NeedPreshade;
2602 	}
2603 	else if (hTarget == pb_dynamics)
2604 	{
2605 		mReshadeRQ = RR_None;
2606 	}
2607 	else if (hTarget == pixelSampler)
2608 	{
2609 		mReshadeRQ = RR_None;
2610 	}
2611 
2612 	mReshadeRQ = chooseReshade[mReshadeRQ][mInRQ];
2613 	mInRQ = RR_None;
2614 }
2615 // mjm - end
2616 
2617 // invaldate for the viewport
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)2618 RefResult XRayMtl::NotifyRefChanged( Interval changeInt, RefTargetHandle hTarget,
2619 									   PartID& partID, RefMessage message )
2620 {
2621 	switch (message) {
2622 case REFMSG_WANT_SHOWPARAMLEVEL:
2623 	{
2624 		BOOL *pb = (BOOL *)(partID);
2625 		*pb = TRUE;
2626 		return REF_STOP;
2627 	}
2628 case REFMSG_CHANGE:
2629 	UpdateReshadeRequirements(hTarget, partID); // mjm - 06.02.00
2630 
2631 	ivalid.SetEmpty();
2632 	// ask ClassDesc if any paramblock change caused the notify
2633 	// if not and changing ref was one of the pblocks, inval all PB2 UI
2634 	// else inval indicated param UI
2635 	IParamBlock2* cpb;
2636 	ParamID changing_param = stdmtl2CD.LastNotifyParamID(this, cpb);
2637 	if (hTarget != pShader) // && hTarget != maps)
2638 	{
2639 		if (changing_param != -1)
2640 		{
2641 			// DS 10/13/00: I needed to add code to check of the dialog for this map was actualy active because
2642 			// on during the creation of new materials, messages were getting routed to the current
2643 			// medit material, causing problems for undo of sub-object mtl assignment.
2644 			// DS 10/24/31:  Removed the test because it isn't quite right, and was causing some problems ( #264662)
2645 			//  and no longer seems necessary. (we need a better test for whether a mtl is in medit or not)
2646 			//if (cpb->GetMap()&&cpb->GetMap()->DlgActive()))
2647 			cpb->GetDesc()->InvalidateUI(changing_param);
2648 			if (changing_param == std2_opacity &&
2649 				cpb == pb_extended && pShader &&
2650 				pShader->GetParamDlg())
2651 				pShader->GetParamDlg()->UpdateOpacity();
2652 		}
2653 		else
2654 		{
2655 			stdmtl2CD.InvalidateUI();
2656 			if (hTarget == pb_extended && pShader &&
2657 				pShader->GetParamDlg())
2658 				pShader->GetParamDlg()->UpdateOpacity();
2659 			if (texHandle[0]||texHandle[1]) {
2660 				if (curImp)
2661 					curImp->MtlChanged();
2662 			}
2663 		}
2664 		DiscardTexHandles(); // DS 5/22/00
2665 	}
2666 	break;
2667 	}
2668 
2669 	return REF_SUCCEED;
2670 }
2671 
ClassID()2672 Class_ID XRayMtl::ClassID() { return XRAYMTL_CLASS_ID; }
2673 
GetSubTexmapSlotName(int i)2674 TSTR XRayMtl::GetSubTexmapSlotName(int i) {
2675 	if ( pShader ){
2676 		long nShaderChan = pShader->nTexChannelsSupported();
2677 		if ( i < nShaderChan )
2678 			return pShader->GetTexChannelName( i );
2679 		else
2680 			return GetString( mtlChannelNameIDS[i - nShaderChan] );
2681 	} else return TSTR("");
2682 }
2683 
2684 
EnableMap(int i,BOOL onoff)2685 void XRayMtl::EnableMap(int i, BOOL onoff) {
2686 	pb_maps->SetValue(std2_map_enables, TimeValue(0), onoff, i);
2687 }
2688 
SetFilter(Color c,TimeValue t)2689 void XRayMtl::SetFilter(Color c, TimeValue t) {
2690 	filter = c;
2691 	pb_extended->SetValue( std2_filter_color, t, Point3(c.r, c.g, c.b));
2692 	int opacChan = stdIDToChannel[ ID_OP ];
2693 	if (opacity!=1.0f||opfall!=0.0f||MAPACTIVE(opacChan))
2694 		NotifyChanged();
2695 }
2696 
SetIOR(float v,TimeValue t)2697 void XRayMtl::SetIOR(float v, TimeValue t) {
2698 	ioRefract = v;
2699 	pb_extended->SetValue(std2_ior, t, v);
2700 }
2701 
SetOpacity(float v,TimeValue t)2702 void XRayMtl::SetOpacity(float v, TimeValue t) {
2703 	opacity = v;
2704 	pb_extended->SetValue(std2_opacity, t, v);
2705 }
2706 
SetOpacFalloff(float v,TimeValue t)2707 void XRayMtl::SetOpacFalloff(float v, TimeValue t) {
2708 	opfall = v;
2709 	pb_extended->SetValue(std2_falloff_amnt, t, v);
2710 	int opacChan = stdIDToChannel[ ID_OP ];
2711 	if (opacity!=1.0f||opfall!=0.0f||MAPACTIVE(opacChan))
2712 		NotifyChanged();
2713 }
2714 
SetWireSize(float v,TimeValue t)2715 void XRayMtl::SetWireSize(float v, TimeValue t) {
2716 	wireSize = v;
2717 	pb_extended->SetValue(std2_wire_size, t, v);
2718 	if (flags&NEWSTDMTL_WIRE)
2719 		NotifyChanged();
2720 }
2721 
SetDimIntens(float v,TimeValue t)2722 void XRayMtl::SetDimIntens(float v, TimeValue t) {
2723 	dimIntens = v;
2724 	pb_extended->SetValue(std2_dim_lvl, t, v);
2725 }
2726 
SetDimMult(float v,TimeValue t)2727 void XRayMtl::SetDimMult(float v, TimeValue t) {
2728 	dimMult = v;
2729 	pb_extended->SetValue(std2_refl_lvl, t, v);
2730 }
2731 
SetTexmapAmt(int imap,float amt,TimeValue t)2732 void XRayMtl::SetTexmapAmt(int imap, float amt, TimeValue t) {
2733 	pb_maps->SetValue(std2_map_amnts, t, amt, imap);
2734 }
2735 
2736 /////////////////////////////////////////////////////////////////////
2737 // shaders
SetShaderIndx(long indx,BOOL update)2738 void XRayMtl::SetShaderIndx( long indx, BOOL update )
2739 {
2740 	if( !update ) shaderId = NO_UPDATE;
2741 	pb_shader->SetValue(std2_shader_type, 0, indx<0 ? 0 : indx );
2742 	shaderId = indx;
2743 }
2744 
SetSamplerIndx(long indx,BOOL update)2745 void XRayMtl::SetSamplerIndx( long indx, BOOL update )
2746 {
2747 	if( !update ) samplerId = NO_UPDATE;
2748 	pb_sampling->SetValue(std2_ssampler, 0, indx<0 ? 0 : indx );
2749 	samplerId = indx;
2750 }
2751 
2752 
2753 static Class_ID ClassID0(0, 0);
2754 static Class_ID ClassID1(1, 0);
2755 
SetShader(Shader * pNewShader)2756 void XRayMtl::SetShader( Shader* pNewShader )
2757 {
2758 	//	if ( (pShader?pShader->ClassID():ClassID0) != (pNewShader?pNewShader->ClassID():ClassID1) ){
2759 	ReplaceReference( SHADER_REF, pNewShader );
2760 	NotifyChanged();
2761 	NotifyDependents(FOREVER, 0, REFMSG_SUBANIM_STRUCTURE_CHANGED);
2762 	//	}
2763 }
2764 
2765 // the shader Gets & Sets
IsSelfIllumColorOn()2766 BOOL XRayMtl::IsSelfIllumColorOn()
2767 {	if (pShader->SupportStdParams() & STD_PARAM_SELFILLUM_CLR){
2768 	return pShader->IsSelfIllumClrOn();
2769 }
2770 return FALSE;
2771 }
2772 
SetSelfIllumColorOn(BOOL on)2773 void XRayMtl::SetSelfIllumColorOn( BOOL on )
2774 {	if (pShader->SupportStdParams() & STD_PARAM_SELFILLUM_CLR){
2775 	pShader->SetSelfIllumClrOn( on );
2776 }
2777 }
2778 
SetAmbient(Color c,TimeValue t)2779 void XRayMtl::SetAmbient(Color c, TimeValue t)
2780 {	if (pShader->SupportStdParams() & STD_PARAM_AMBIENT_CLR){
2781 	pShader->SetAmbientClr( c, t );
2782 }
2783 }
2784 
SetDiffuse(Color c,TimeValue t)2785 void XRayMtl::SetDiffuse(Color c, TimeValue t)
2786 {	if (pShader->SupportStdParams() & STD_PARAM_DIFFUSE_CLR){
2787 	pShader->SetDiffuseClr( c, t );
2788 }
2789 }
2790 
SetSpecular(Color c,TimeValue t)2791 void XRayMtl::SetSpecular(Color c, TimeValue t)
2792 {	if (pShader->SupportStdParams() & STD_PARAM_SPECULAR_CLR){
2793 	pShader->SetSpecularClr( c, t );
2794 }
2795 }
2796 
SetShininess(float v,TimeValue t)2797 void XRayMtl::SetShininess(float v, TimeValue t)
2798 {	if (pShader->SupportStdParams() & STD_PARAM_GLOSSINESS ){
2799 	pShader->SetGlossiness( v, t );
2800 }
2801 }
2802 
SetShinStr(float v,TimeValue t)2803 void XRayMtl::SetShinStr(float v, TimeValue t)
2804 {	if (pShader->SupportStdParams() & STD_PARAM_SPECULAR_LEV ){
2805 	pShader->SetSpecularLevel( v, t );
2806 }
2807 }
2808 
SetSelfIllum(float v,TimeValue t)2809 void XRayMtl::SetSelfIllum(float v, TimeValue t)
2810 {	if (pShader->SupportStdParams() & STD_PARAM_SELFILLUM ){
2811 	pShader->SetSelfIllum( v, t );
2812 }
2813 }
2814 
2815 
SetSelfIllumColor(Color c,TimeValue t)2816 void XRayMtl::SetSelfIllumColor(Color c, TimeValue t)
2817 {	if (pShader->SupportStdParams() & STD_PARAM_SELFILLUM_CLR){
2818 	pShader->SetSelfIllumClr( c, t );
2819 }
2820 }
2821 
2822 static Color blackClr( 0.0, 0.0, 0.0 );
2823 
GetAmbient(int mtlNum,BOOL backFace)2824 Color XRayMtl::GetAmbient(int mtlNum, BOOL backFace)
2825 {
2826 	return pShader->GetAmbientClr( mtlNum, backFace );
2827 }
2828 
GetDiffuse(int mtlNum,BOOL backFace)2829 Color XRayMtl::GetDiffuse(int mtlNum, BOOL backFace)
2830 {
2831 	return pShader->GetDiffuseClr( mtlNum, backFace );
2832 }
2833 
GetSpecular(int mtlNum,BOOL backFace)2834 Color XRayMtl::GetSpecular(int mtlNum, BOOL backFace)
2835 {
2836 	return pShader->GetSpecularClr( mtlNum, backFace );
2837 }
2838 
GetSelfIllumColor(int mtlNum,BOOL backFace)2839 Color XRayMtl::GetSelfIllumColor(int mtlNum, BOOL backFace)
2840 {
2841 	return pShader->GetSelfIllumClr( mtlNum, backFace );
2842 }
2843 
2844 
GetShininess(int mtlNum,BOOL backFace)2845 float XRayMtl::GetShininess(int mtlNum, BOOL backFace)
2846 {
2847 	float g = pShader->GetGlossiness( mtlNum, backFace );
2848 	return Bound( g, 0.01f, 1.0f );
2849 }
2850 
GetShinStr(int mtlNum,BOOL backFace)2851 float XRayMtl::GetShinStr(int mtlNum, BOOL backFace)
2852 {
2853 	return pShader->GetSpecularLevel( mtlNum, backFace );
2854 }
2855 
GetSelfIllum(int mtlNum,BOOL backFace)2856 float XRayMtl::GetSelfIllum(int mtlNum, BOOL backFace)
2857 {
2858 	return pShader->GetSelfIllum( mtlNum, backFace );
2859 }
2860 
GetShininess(TimeValue t)2861 float XRayMtl::GetShininess(TimeValue t)
2862 {
2863 	return pShader->GetGlossiness( t );
2864 }
2865 
GetShinStr(TimeValue t)2866 float XRayMtl::GetShinStr(TimeValue t)
2867 {
2868 	return pShader->GetSpecularLevel( t );
2869 }
2870 
GetSelfIllum(TimeValue t)2871 float XRayMtl::GetSelfIllum(TimeValue t)
2872 {
2873 	return pShader->GetSelfIllum(t);
2874 }
2875 
2876 
GetSelfIllumColorOn(int mtlNum,BOOL backFace)2877 BOOL XRayMtl::GetSelfIllumColorOn(int mtlNum, BOOL backFace)
2878 {
2879 	return pShader->IsSelfIllumClrOn();
2880 }
2881 
GetAmbient(TimeValue t)2882 Color XRayMtl::GetAmbient(TimeValue t)
2883 {
2884 	return pShader->GetAmbientClr( t );
2885 }
GetDiffuse(TimeValue t)2886 Color XRayMtl::GetDiffuse(TimeValue t)
2887 {
2888 	return pShader->GetDiffuseClr(t);
2889 }
GetSpecular(TimeValue t)2890 Color XRayMtl::GetSpecular(TimeValue t)
2891 {
2892 	return pShader->GetSpecularClr( t );
2893 }
GetSelfIllumColor(TimeValue t)2894 Color XRayMtl::GetSelfIllumColor(TimeValue t)
2895 {
2896 	return pShader->GetSelfIllumClr(t );
2897 }
2898 
GetSoftenLevel(TimeValue t)2899 float XRayMtl::GetSoftenLevel( TimeValue t)
2900 {
2901 	return pShader->GetSoftenLevel(t);
2902 }
2903 
GetFilter()2904 Color XRayMtl::GetFilter() {	return filter;	}
GetTexmapAmt(int imap)2905 float XRayMtl::GetTexmapAmt(int imap) {	return maps->txmap[imap].amount;	}
GetTexmapAmt(int imap,TimeValue t)2906 float XRayMtl::GetTexmapAmt(int imap, TimeValue t) {	return maps->txmap[imap].GetAmount(t); 	}
2907 
GetFilter(TimeValue t)2908 Color XRayMtl::GetFilter(TimeValue t)   { return pb_extended->GetColor(std2_filter_color, t);	}
GetOpacity(TimeValue t)2909 float XRayMtl::GetOpacity( TimeValue t) { return  pb_extended->GetFloat(std2_opacity, t); }
GetOpacFalloff(TimeValue t)2910 float XRayMtl::GetOpacFalloff(TimeValue t){ return  pb_extended->GetFloat(std2_falloff_amnt, t);}
GetWireSize(TimeValue t)2911 float XRayMtl::GetWireSize(TimeValue t) { return  pb_extended->GetFloat(std2_wire_size, t);}
GetIOR(TimeValue t)2912 float XRayMtl::GetIOR( TimeValue t)     { return  pb_extended->GetFloat(std2_ior, t);}
GetDimIntens(TimeValue t)2913 float XRayMtl::GetDimIntens( TimeValue t)   { return  pb_extended->GetFloat(std2_dim_lvl, t); }
GetDimMult(TimeValue t)2914 float XRayMtl::GetDimMult( TimeValue t)   { return  pb_extended->GetFloat(std2_refl_lvl, t); }
MapEnabled(int i)2915 BOOL XRayMtl::MapEnabled(int i)         { return maps->txmap[i].mapOn;}
2916 
2917 
GetDynamicsProperty(TimeValue t,int mtlNum,int propID)2918 float XRayMtl::GetDynamicsProperty(TimeValue t, int mtlNum, int propID) {
2919 	float val;
2920 	Interval ivalid;
2921 	switch(propID) {
2922 case DYN_BOUNCE:
2923 	pb_dynamics->GetValue(std2_bounce, t, val, ivalid);
2924 	return val;
2925 case DYN_STATIC_FRICTION:
2926 	pb_dynamics->GetValue(std2_static_friction, t, val, ivalid);
2927 	return val;
2928 case DYN_SLIDING_FRICTION:
2929 	pb_dynamics->GetValue(std2_sliding_friction, t, val, ivalid);
2930 	return val;
2931 default:
2932 	assert(0);
2933 	return 0.0f;
2934 	}
2935 }
2936 
SetDynamicsProperty(TimeValue t,int mtlNum,int propID,float value)2937 void XRayMtl::SetDynamicsProperty(TimeValue t, int mtlNum, int propID, float value){
2938 #ifndef DESIGN_VER
2939 	switch(propID) {
2940 case DYN_BOUNCE:
2941 	pb_dynamics->SetValue( std2_bounce, t, value);
2942 	break;
2943 case DYN_STATIC_FRICTION:
2944 	pb_dynamics->SetValue( std2_static_friction, t, value);
2945 	break;
2946 case DYN_SLIDING_FRICTION:
2947 	pb_dynamics->SetValue( std2_sliding_friction, t, value);
2948 	break;
2949 default:
2950 	assert(0);
2951 	break;
2952 	}
2953 #endif
2954 }
2955 
2956 // returns the index of the shader in the list
FindShader(Class_ID & findId,ClassDesc ** ppCD)2957 int XRayMtl::FindShader( Class_ID& findId, ClassDesc** ppCD )
2958 {
2959 	for (int i = 0; i < XRayMtl::NumShaders(); i++) {
2960 		ClassDesc* pCD = XRayMtl::GetShaderCD(i);
2961 		if ( findId == pCD->ClassID() ){
2962 			if (ppCD) *ppCD = pCD;
2963 			return i;
2964 		}
2965 	}
2966 	if (ppCD) *ppCD = NULL; // not found
2967 	return -1;
2968 }
2969 
FindSampler(Class_ID findId,ClassDesc ** ppCD)2970 int XRayMtl::FindSampler( Class_ID findId, ClassDesc** ppCD )
2971 {
2972 	for (int i = 0; i < XRayMtl::NumSamplers(); i++) {
2973 		ClassDesc* pCD = XRayMtl::GetSamplerCD(i);
2974 		if ( findId == pCD->ClassID() ){
2975 			if (ppCD) *ppCD = pCD;
2976 			return i;
2977 		}
2978 	}
2979 	if (ppCD) *ppCD = NULL; // not found
2980 	return -1;
2981 }
2982 
2983 /***
2984 ClassDesc* XRayMtl::SamplerIndxToCD( int indx )
2985 {
2986 IParamMap2* map = pb_sampling ? pb_sampling->GetMap() : NULL;
2987 if ( indx < 0 ) indx = 0;
2988 if ( map ) {
2989 HWND hwnd = map->GetHWnd();
2990 HWND hwndSampler = GetDlgItem(hwnd, IDC_PIX_SAMPLER);
2991 ClassDesc* pCD = (ClassDesc*)SendMessage( hwndSampler, CB_GETITEMDATA, indx, 0 );
2992 return pCD;
2993 }
2994 // last resort
2995 SubClassList * scList = GetCOREInterface()->GetDllDir().ClassDir().GetClassList(SAMPLER_CLASS_ID);
2996 return (*scList)[ 1 ].CD();
2997 }
2998 ***/
2999 
3000 
3001 
3002 /////////////////////////////////////////////////////////////////////////
3003 //	Filing
3004 //
3005 #define MTL_HDR_CHUNK 0x4000
3006 #define NEWSTDMTL_FLAGS_CHUNK 0x5000
3007 #define NEWSTDMTL_SHADING_CHUNK 0x5004
3008 #define NEWSTDMTL_TEX_ONOFF_CHUNK 0x5002
3009 #define NEWSTDMTL_TEX_AMT0 0x5100
3010 #define NEWSTDMTL_TEX_AMT1 0x5101
3011 #define NEWSTDMTL_TEX_AMT2 0x5102
3012 #define NEWSTDMTL_TEX_AMT3 0x5103
3013 #define NEWSTDMTL_TEX_AMT4 0x5104
3014 #define NEWSTDMTL_TEX_AMT5 0x5105
3015 #define NEWSTDMTL_TEX_AMT6 0x5106
3016 #define NEWSTDMTL_TEX_AMT7 0x5107
3017 #define NEWSTDMTL_TEX_AMT8 0x5108
3018 #define NEWSTDMTL_TEX_AMT9 0x5109
3019 #define NEWSTDMTL_TEX_AMTA 0x510A
3020 
3021 //xray part
3022 #define NEWSTDMTL_XRAY_ESHADER_CHUNK 0x5200
3023 #define NEWSTDMTL_XRAY_CSHADER_CHUNK 0x5201
3024 #define NEWSTDMTL_XRAY_GAMEMTL_CHUNK 0x5202
3025 
3026 //#define NEWSTDMTL_BUMP1_CHUNK 0x5200
3027 #define NEWSTDMTL_VERS_CHUNK 0x5300
3028 #define NEWSTDMTL_DIM_REFLECT 0x5400
3029 
3030 #define NEWSTDMTL_SELFILLUM_CLR_ON 0x5500
3031 #define NEWSTDMTL_SAMPLING_ON		0x5510
3032 #define NEWSTDMTL_SAMPLING_QUALITY	0x5511
3033 
3034 // IO
Save(ISave * isave)3035 IOResult XRayMtl::Save(ISave *isave)
3036 {
3037 	ULONG nb;
3038 	IOResult res;
3039 	isave->BeginChunk(MTL_HDR_CHUNK);
3040 	res = MtlBase::Save(isave);
3041 	if (res!=IO_OK) return res;
3042 	isave->EndChunk();
3043 
3044 	isave->BeginChunk(NEWSTDMTL_VERS_CHUNK);
3045 	int version = CURRENT_NEWSTDMTL_VERSION;
3046 	isave->Write(&version, sizeof(version), &nb);
3047 	isave->EndChunk();
3048 
3049 	// xray params
3050 	isave->BeginChunk(NEWSTDMTL_XRAY_ESHADER_CHUNK);
3051 	isave->WriteCString(GetEShader(eshaderId));
3052 	isave->EndChunk();
3053 
3054 	isave->BeginChunk(NEWSTDMTL_XRAY_CSHADER_CHUNK);
3055 	isave->WriteCString(GetCShader(cshaderId));
3056 	isave->EndChunk();
3057 
3058 	isave->BeginChunk(NEWSTDMTL_XRAY_GAMEMTL_CHUNK);
3059 	isave->WriteCString(GetGameMtl(gamemtlId));
3060 	isave->EndChunk();
3061 
3062 	return IO_OK;
3063 }
3064 
3065 
FindNodeRef(ReferenceTarget * rt)3066 static INode* FindNodeRef(ReferenceTarget *rt) {
3067 	DependentIterator di(rt);
3068 	ReferenceMaker *rm;
3069 	INode *nd = NULL;
3070 	while (rm=di.Next()) {
3071 		if (rm->SuperClassID()==BASENODE_CLASS_ID) return (INode *)rm;
3072 		nd = FindNodeRef((ReferenceTarget *)rm);
3073 		if (nd) return nd;
3074 	}
3075 	return NULL;
3076 }
3077 
3078 
3079 
GetNodeScaling(Mtl * m)3080 static float  GetNodeScaling(Mtl *m) {
3081 	INode *n = FindNodeRef(m);
3082 	if (n==NULL)
3083 		return 1.0f;
3084 	Interval v;
3085 	Matrix3 tm = n->GetNodeTM(0, &v);
3086 	float f = float(  abs(Length(tm.GetRow(0))) + abs(Length(tm.GetRow(1))) + abs(Length(tm.GetRow(2))) )/3.0f;
3087 	return f;
3088 }
3089 
3090 
3091 //-----------------------------------------------------------------------
3092 // DS - 4/7/97: Changed Opacity, Self-illumination, SHininess, Shininess strengh
3093 // so that the map amount blends between the corresponding slider
3094 // setting and the map value.  This code fixes up old files so they
3095 // will render the same way. This does not correctly handle animated values
3096 // for the amount or parameter sliders.
3097 //
3098 // KE - 8/4/98 modified for converting old stdmtls to stdmtl2's
3099 // JBW - 11/19/98 updated to convert old stdmtls and v.10 stdmtl2's to ParamBlock2-based XRayMtl's
3100 //-----------------------------------------------------------------------
3101 
OldVerFix(int loadVer)3102 void XRayMtl::OldVerFix(int loadVer)
3103 {
3104 	ULONG stdParams;
3105 
3106 	macroRecorder->Disable();
3107 
3108 	// ask the ClassDesc to make the P_AUTO_CONSTRUCT paramblock2s
3109 	stdmtl2CD.MakeAutoParamBlocks(this);
3110 
3111 	if (loadVer < 10) {
3112 		// create a shader, note: always a stdshader as it's an old version
3113 		if ( shaderId < 0 || shaderId > 3 ) shaderId = 1;	// v1 files
3114 		long cid;
3115 		switch( shaderId ) {
3116 case 0: cid = PHONGClassID;
3117 	pb_shader->SetValue(std2_faceted,0,TRUE);
3118 	break;
3119 case 1: cid = PHONGClassID; break;
3120 case 2: cid = METALClassID; break;
3121 case 3: cid = BLINNClassID; break;
3122 		}
3123 		long indx =  FindShader( Class_ID(cid, 0) );
3124 
3125 		if ( indx < 0 ) return;
3126 
3127 		// this sets the new shader via pb2 accessor
3128 		SetShaderIndx( indx );
3129 
3130 		pShader->SetSelfIllumClrOn( FALSE );
3131 		stdParams = pShader->SupportStdParams();
3132 
3133 		// convert param blocks
3134 		IParamBlock* oldPB = old_pblock;
3135 		IParamBlock* newParamBlk = UpdateParameterBlock(stdmtlPB, NPARAMS_O, oldPB,
3136 			stdmtl2PB, NPARAMS, NEWSTDMTL_PBVERSION);
3137 
3138 		// if shader is PB2-based, give it the PB2 remapping descriptor
3139 		if (pShader->NumParamBlocks() > 0)
3140 			pShader->ConvertParamBlk(stdmtlPB2, NPARAMS_O, oldPB);
3141 		else
3142 			pShader->ConvertParamBlk(stdmtlPB, NPARAMS_O, oldPB);
3143 
3144 		ReplaceReference( OLD_PBLOCK_REF, newParamBlk );
3145 		UpdateTexmaps();
3146 		std2_extended_blk.SetSubTexNo(std2_ep_filter_map, stdIDToChannel[ID_FI]);
3147 
3148 		SetSamplerIndx( FindSampler( Class_ID(DEFAULT_SAMPLER_CLASS_ID,0) ) );
3149 		if (flags & NEWSTDMTL_SSAMP_ON) {
3150 			pb_sampling->SetValue( std2_ssampler_enable,0, TRUE );
3151 		}
3152 
3153 		// gloss & strength are swapped from old versions
3154 		TexmapSlot tmSlot = maps->txmap[ID_SH];
3155 		maps->txmap[ID_SH] = maps->txmap[ID_SS];
3156 		maps->txmap[ID_SS] = tmSlot;
3157 
3158 
3159 	}
3160 
3161 	// now set values that were previously stored outside the PB, prior to update
3162 	pb_shader->SetValue(std2_wire, 0, GetFlag(NEWSTDMTL_WIRE)!=0);
3163 	pb_shader->SetValue(std2_two_sided, 0, GetFlag(NEWSTDMTL_2SIDE)!=0);
3164 	pb_shader->SetValue(std2_face_map, 0, GetFlag(NEWSTDMTL_FACEMAP)!=0);
3165 	pb_shader->SetValue(std2_faceted, 0, GetFlag(NEWSTDMTL_FACETED)!=0);
3166 
3167 	pb_extended->SetValue(std2_opacity_type, 0, (GetFlag(NEWSTDMTL_ADD_TRANSP) ? 2 : GetFlag(NEWSTDMTL_FILT_TRANSP) ? 0 : 1));
3168 	pb_extended->SetValue(std2_falloff_type, 0, GetFlag(NEWSTDMTL_FALLOFF_OUT) ? 1 : 0);
3169 	pb_extended->SetValue(std2_wire_units, 0, GetFlag(NEWSTDMTL_WIRE_UNITS) ? 1 : 0);
3170 	pb_extended->SetValue(std2_apply_refl_dimming, 0, dimReflect);
3171 
3172 	pShader->SetLockAD( GetFlag(NEWSTDMTL_LOCK_AD)?TRUE:FALSE );
3173 	pShader->SetLockDS( GetFlag(NEWSTDMTL_LOCK_DS)?TRUE:FALSE );
3174 	pShader->SetLockADTex( GetFlag(NEWSTDMTL_LOCK_ADTEX)!=0 );
3175 	pb_maps->SetValue(std2_mp_ad_texlock, 0, GetFlag(NEWSTDMTL_LOCK_ADTEX)!=0 );
3176 
3177 	if (loadVer < 8) {
3178 		Interval v;
3179 		Update(0, v);
3180 		// In old versions, the ID's & the channel numbers correspond
3181 		if (MAPACTIVE(ID_OP)) {
3182 			if (maps->txmap[ID_OP].amount != 1.0f)
3183 				SetOpacity(0.0f, 0);
3184 		}
3185 
3186 		if ( stdParams & STD_PARAM_SELFILLUM )
3187 			if (MAPACTIVE(ID_SI)) {
3188 				if (maps->txmap[ID_SI].amount != 1.0f)
3189 					pShader->SetSelfIllum(0.0f, 0);
3190 			}
3191 
3192 			if ( stdParams & STD_PARAM_SPECULAR_LEV )
3193 				if (MAPACTIVE(ID_SS)) {
3194 					float amt = maps->txmap[ID_SS].amount;
3195 					SetTexmapAmt(ID_SS, amt * pShader->GetSpecularLevel(0, 0), 0);
3196 					pShader->SetSpecularLevel(0.0f, 0);
3197 				}
3198 
3199 				if ( stdParams & STD_PARAM_GLOSSINESS )
3200 					if (MAPACTIVE(ID_SH)) {
3201 						float amt = maps->txmap[ID_SH].amount;
3202 						SetTexmapAmt(ID_SH, amt* pShader->GetGlossiness(0, 0), 0);
3203 						pShader->SetGlossiness(0.0f, 0);
3204 					}
3205 
3206 	}
3207 	if (loadVer < 9) {
3208 		if ( stdParams & STD_PARAM_SOFTEN_LEV )
3209 			if (flags&NEWSTDMTL_SOFTEN)
3210 				pShader->SetSoftenLevel(.6f, 0);
3211 			else
3212 				pShader->SetSoftenLevel(0.0f, 0);
3213 	}
3214 
3215 	// at this point we have a v10 Stdmtl2, convert to PB2-based
3216 	// distribute old pblock values to new pb2 blocks
3217 	UpdateParameterBlock2(extVer10, NPARAMS, old_pblock, &std2_extended_blk, pb_extended);
3218 #ifndef DESIGN_VER
3219 	UpdateParameterBlock2(dynVer10, NPARAMS, old_pblock, &std2_dynamics_blk, pb_dynamics);
3220 #endif
3221 
3222 	// mask off  rollup flags
3223 	flags &= ~NEWSTDMTL_ROLLUP_FLAGS;
3224 	flags |= NEWSTDMTL_ROLLUP1_OPEN;
3225 	//	pb_shader->SetRolloutOpen( flags & NEWSTDMTL_ROLLUP1_OPEN );
3226 
3227 	macroRecorder->Enable();
3228 
3229 	// delete old pblock
3230 	ReplaceReference(OLD_PBLOCK_REF, NULL);
3231 
3232 }
3233 
3234 
3235 // versin update post-load call back
3236 class NewStdMtl2UpdateCB: public PostLoadCallback {
3237 public:
3238 	// create shader & new pblock
3239 	XRayMtl *m;
3240 	int loadVersion;
3241 
NewStdMtl2UpdateCB(XRayMtl * s,int loadVers)3242 	NewStdMtl2UpdateCB( XRayMtl *s, int loadVers ){ m = s; loadVersion = loadVers; }
proc(ILoad * iload)3243 	void proc(ILoad *iload) {
3244 		m->OldVerFix( loadVersion );
3245 		delete this;
3246 	}
3247 };
3248 
BumpFix()3249 void XRayMtl::BumpFix( ) {
3250 	// Fix up bump map amount on old files if the node is scaled.	DS 4/16/99
3251 	int bumpChannel = stdIDToChannel[ID_BU];
3252 	if ((*maps)[ bumpChannel].IsActive()) {
3253 		float s = GetNodeScaling(this);
3254 		if (s!=1.0f) {
3255 			float am = GetTexmapAmt(bumpChannel);
3256 			SetTexmapAmt(bumpChannel, s*am, 0);
3257 		}
3258 	}
3259 }
3260 
3261 
3262 // Bumpp map amount fix post-load call back
3263 class NewStdMtl2BumpFixCB: public PostLoadCallback {
3264 public:
3265 	// create shader & new pblock
3266 	XRayMtl *m;
3267 
NewStdMtl2BumpFixCB(XRayMtl * s)3268 	NewStdMtl2BumpFixCB( XRayMtl *s ){ m = s; }
Priority()3269 	int Priority() { return 7; } // run at lower priority after normal PLCB's are all finished
proc(ILoad * iload)3270 	void proc(ILoad *iload) {
3271 		m->BumpFix( );
3272 		delete this;
3273 	}
3274 };
3275 
3276 // post-load finalize callback
3277 class NewStdMtl2CB: public PostLoadCallback {
3278 public:
3279 	XRayMtl *m;
3280 
NewStdMtl2CB(XRayMtl * s)3281 	NewStdMtl2CB(XRayMtl *s){ m = s; }
proc(ILoad * iload)3282 	void proc(ILoad *iload)
3283 	{
3284 		// ensure all map-related parameters are set up
3285 		m->UpdateTexmaps();
3286 
3287 		// make sure the right indx is selected for shaders & samplers
3288 		m->SetShaderIndx( m->FindShader( m->pShader->ClassID() ), FALSE );
3289 		if( m->pixelSampler == NULL ) // for some alpha files!
3290 			m->SetSamplerIndx( m->FindSampler( Class_ID(DEFAULT_SAMPLER_CLASS_ID,0) ) );
3291 
3292 		m->SetSamplerIndx( m->FindSampler( m->pixelSampler->ClassID() ), FALSE );
3293 		m->SetFlag(NEWSTDMTL_SSAMP_ON, m->pixelSampler->GetEnable() );
3294 
3295 #ifndef	DESIGN_VER
3296 		if( m->pb_dynamics == NULL )
3297 			//create the parameter block
3298 			CreateParameterBlock2(&std2_dynamics_blk, m);
3299 #endif
3300 		if( m->pb_xray == NULL )
3301 			//create the parameter block
3302 			CreateParameterBlock2(&std2_xray_blk, m);
3303 
3304 		m->SetEShaderIndx( m->eshaderId );
3305 		m->SetCShaderIndx( m->cshaderId );
3306 		m->SetGameMtlIndx( m->gamemtlId );
3307 
3308 
3309 		// DS - 2/11/99 This Update should not be here: it causes all
3310 		// submaps to be loaded when loading, which makes loading matlibs very slow.
3311 		//		Interval i;
3312 		//		i.SetInfinite();
3313 		//		m->Update(0, i);
3314 
3315 		delete this;
3316 	}
3317 };
3318 
Load(ILoad * iload)3319 IOResult XRayMtl::Load(ILoad *iload) {
3320 	ULONG nb;
3321 	int id;
3322 	int version = 0;
3323 	dimReflect = FALSE;
3324 
3325 	// fix old ver
3326 	gamemtlId = -1;
3327 
3328 	IOResult res;
3329 	while (IO_OK==(res=iload->OpenChunk())) {
3330 		switch(id = iload->CurChunkID())  {
3331 case MTL_HDR_CHUNK:
3332 	res = MtlBase::Load(iload);
3333 	ivalid.SetEmpty();
3334 	break;
3335 case NEWSTDMTL_FLAGS_CHUNK:
3336 	res = iload->Read(&flags, sizeof(flags), &nb);
3337 	break;
3338 case NEWSTDMTL_SHADING_CHUNK:
3339 	res = iload->Read(&shaderId, sizeof(shaderId), &nb);
3340 	break;
3341 case NEWSTDMTL_XRAY_ESHADER_CHUNK:{
3342 	LPSTR es_name;
3343 	res = iload->ReadCStringChunk(&es_name);
3344 	if (res==IO_OK) eshaderId = XRayMtl::FindEShader(es_name);
3345 	}break;
3346 case NEWSTDMTL_XRAY_CSHADER_CHUNK:{
3347 	LPSTR cs_name;
3348 	res = iload->ReadCStringChunk(&cs_name);
3349 	if (res==IO_OK) cshaderId = XRayMtl::FindCShader(cs_name);
3350 	}break;
3351 case NEWSTDMTL_XRAY_GAMEMTL_CHUNK:{
3352 	LPSTR gm_name;
3353 	res = iload->ReadCStringChunk(&gm_name);
3354 	if (res==IO_OK) gamemtlId = XRayMtl::FindGameMtl(gm_name);
3355 	}break;
3356 case NEWSTDMTL_VERS_CHUNK:
3357 	res = iload->Read(&version, sizeof(version), &nb);
3358 	break;
3359 case NEWSTDMTL_TEX_ONOFF_CHUNK:
3360 	{
3361 		ULONG f;
3362 		res = iload->Read(&f, sizeof(f), &nb);
3363 		for (int i=0; i<STD2_NMAX_TEXMAPS; i++)
3364 			maps->txmap[i].mapOn = (f&(1<<i))?1:0;
3365 	}
3366 	break;
3367 case NEWSTDMTL_DIM_REFLECT:
3368 	dimReflect = TRUE;
3369 	break;
3370 		}
3371 		iload->CloseChunk();
3372 		if (res!=IO_OK)
3373 			return res;
3374 	}
3375 
3376 	// register version updaters
3377 	if (version <= FINAL_PARAMBLOCK_v1_VERSION) {
3378 		iload->RegisterPostLoadCallback(new ParamBlockPLCB((ParamVersionDesc*)oldNewStdMtlVersions, NEWSTDMTL_NUMOLDVER, &stdMtlVersion, this, 0));
3379 		iload->RegisterPostLoadCallback(new NewStdMtl2UpdateCB(this, version));
3380 		if (version<12)
3381 			iload->RegisterPostLoadCallback(new NewStdMtl2BumpFixCB(this));
3382 		iload->SetObsolete();
3383 	}
3384 
3385 	if (TextureDisplayEnabled()) {
3386 		IncrActive();
3387 	}
3388 
3389 	if (gamemtlId==-1) gamemtlId = XRayMtl::FindGameMtl("default");
3390 
3391 	// register plcb to finalize setup
3392 	iload->RegisterPostLoadCallback(new NewStdMtl2CB(this));
3393 
3394 	return IO_OK;
3395 }
3396 
3397 
3398 #define TRANSP_SUB		0
3399 #define TRANSP_ADD		1
3400 #define TRANSP_FILTER	2
3401 
3402 
3403 // Composite  c_over on top of c. Assume c_over has pre-multiplied alpha.
AlphaCompCol(Color & c,RGBA c_over)3404 IC void AlphaCompCol(Color& c,  RGBA c_over) {
3405 	float ia = 1.0f - abs(c_over.a);
3406 	ia = LBound( ia );
3407 	c.r = c.r * ia + c_over.r;
3408 	c.g = c.g * ia + c_over.g;
3409 	c.b = c.b * ia + c_over.b;
3410 }
3411 
3412 //////////////////////////////////////////////////////////////////////////////
3413 //
3414 //	transpColor utility, same as in shaders/shaderUtil
3415 //
TranspColor(float opac,Color filt,Color diff)3416 Color XRayMtl::TranspColor( float opac, Color filt, Color diff )
3417 {
3418 	// Compute the color of the transparent filter color
3419 	if (flags & NEWSTDMTL_ADD_TRANSP) {
3420 		float f = 1.0f - opac;
3421 		return Color(f, f, f);
3422 
3423 	} else if ( flags & NEWSTDMTL_FILT_TRANSP ){
3424 		// Transparent Filter color mapping
3425 		if (opac>0.5f) {
3426 			// darken as opac goes ( 0.5--> 1.0)
3427 			// so that max component reaches 0.0f when opac reaches 1.0
3428 			// find max component of filt
3429 			float m = Max(filt);
3430 			float d = 2.0f*(opac-.5f)*m;
3431 			Color fc = filt-d;
3432 			fc = LBound( fc );
3433 			return fc;
3434 		} else {
3435 			// lighten as opac goes ( 0.5--> 0.0)
3436 			// so that min component reaches 1.0f when opac reaches 1.0
3437 			// find min component of filt
3438 			float m = Min(filt);
3439 			float d = (1.0f-2.0f*opac)*(1.0f-m);
3440 			Color fc = filt+d;
3441 			fc = UBound( fc );
3442 			return fc;
3443 		}
3444 
3445 	} else {
3446 		// original 3DS transparency, subtractive using diff color
3447 		Color f = (1.0f-diff);
3448 		return  (1.0f-opac)*f;
3449 	}
3450 }
3451 
3452 
3453 #define DOMAP(n) ((n>=0) && sc.doMaps&&(*maps)[ n ].IsActive())
3454 
3455 #ifdef _DEBUG
3456 static long xStop = -1;
3457 static long yStop = -1;
3458 #endif
3459 
3460 // begin - ke/mjm - 03.16.00 - merge reshading code
3461 //BOOL XRayMtl::SupportsReShading(ShadeContext& sc) { return TRUE; }
3462 
PreShade(ShadeContext & sc,IReshadeFragment * pFrag)3463 void XRayMtl::PreShade(ShadeContext& sc, IReshadeFragment* pFrag )
3464 {
3465 	RGBA mval;
3466 	Point3 N, N0, P;
3467 
3468 #ifdef _DEBUG
3469 	IPoint2 sPt = sc.ScreenCoord();
3470 	if( sPt.x == xStop && sPt.y == yStop )
3471 		long junk = -1;
3472 #endif
3473 
3474 	BOOL bumped = FALSE;
3475 	N = sc.Normal();
3476 
3477 	int ambChan = stdIDToChannel[ ID_AM ];
3478 	int diffChan = stdIDToChannel[ ID_DI ];
3479 	int trChan = stdIDToChannel[ ID_OP ];
3480 	int filtChan = stdIDToChannel[ ID_FI ];
3481 	ULONG trType = (flags & NEWSTDMTL_FILT_TRANSP) ? TRANSP_FILTER :
3482 	(flags & NEWSTDMTL_ADD_TRANSP) ? TRANSP_ADD : TRANSP_SUB;
3483 
3484 
3485 	// Do texture mapping
3486 	sc.SetIOR(ioRefract);
3487 
3488 	// Bump mapping: Do this FIRST so other maps can use the perturbed normal
3489 	int bumpChannel = stdIDToChannel[ID_BU];
3490 	if (DOMAP(bumpChannel)) {
3491 		Point3 dn = (*maps)[bumpChannel].EvalNormalPerturb(sc);
3492 		bumped = TRUE;
3493 		N = Normalize( N + (sc.backFace?-dn:dn));
3494 		// NB: shadeContext has perturbed normal
3495 		sc.SetNormal(N);
3496 		pFrag->AddUnitVecChannel( N );
3497 	}
3498 
3499 	// All normal color & scalar maps are handled here
3500 	long t0 = pShader->ChannelType(0);
3501 	RGBA c;
3502 	for ( long i = 0; i < STD2_NMAX_TEXMAPS; ++i ) {
3503 		if ( sc.doMaps && (*maps)[ i ].IsActive()) {
3504 			long t = pShader->ChannelType(i);
3505 			// composite the channel
3506 			if ( (t & SKIP_CHANNELS)==0 ){
3507 				if ( t & MONO_CHANNEL ) {
3508 					// note: r always holds channel data for mono channels
3509 					float m = (*maps)[i].map->EvalMono(sc);
3510 					pFrag->AddFloatChannel( m );
3511 				} else {
3512 					if ( i != ambChan || (flags & NEWSTDMTL_LOCK_ADTEX)==0 ) {
3513 						c = (*maps)[i].map->EvalColor(sc);
3514 						if ((*maps)[i].map->IsHighDynamicRange()) {
3515 							LogLUV32Pixel lc;
3516 
3517 							lc = c;
3518 							pFrag->AddIntChannel(lc.value);
3519 							pFrag->AddFloatChannel(c.a);
3520 						}
3521 						else {
3522 							BoundInPlace( c );
3523 							pFrag->AddColorChannel(c);
3524 						}
3525 					}
3526 				}
3527 			}
3528 		}
3529 	}
3530 
3531 	// Evaluate reflection map.
3532 	int reflChan = stdIDToChannel[ ID_RL ];
3533 	if (DOMAP(reflChan)) {
3534 		AColor rcol;
3535 		Texmap *reflmap = (*maps)[reflChan].map;
3536 		if (reflmap->HandleOwnViewPerturb()) {
3537 			sc.TossCache(reflmap);
3538 			rcol = reflmap->EvalColor(sc);
3539 		} else
3540 			rcol = sc.EvalEnvironMap(reflmap, sc.ReflectVector());
3541 
3542 		if ((*maps)[reflChan].map->IsHighDynamicRange()) {
3543 			LogLUV32Pixel lc;
3544 
3545 			lc = rcol;
3546 			pFrag->AddIntChannel(lc.value);
3547 			pFrag->AddFloatChannel(rcol.a);
3548 		}
3549 		else {
3550 			pFrag->AddColorChannel(rcol);
3551 		}
3552 	}
3553 
3554 	// do refraction map
3555 	int refrChan = stdIDToChannel[ ID_RR ];
3556 	if (DOMAP(refrChan)) {
3557 		// Evaluate refraction map, as yet unfiltered by filter color.
3558 		Texmap *refrmap = (*maps)[refrChan].map;
3559 		AColor rcol;
3560 		if (refrmap->HandleOwnViewPerturb())
3561 			rcol = refrmap->EvalColor( sc );
3562 		else
3563 			rcol = sc.EvalEnvironMap( refrmap, sc.RefractVector(ioRefract) );
3564 
3565 		if ((*maps)[refrChan].map->IsHighDynamicRange()) {
3566 			LogLUV32Pixel lc;
3567 
3568 			lc = rcol;
3569 			pFrag->AddIntChannel(lc.value);
3570 		}
3571 		else {
3572 			pFrag->AddColorChannel(rcol);
3573 		}
3574 	}
3575 
3576 	// see if the shader wants to save anything
3577 	IReshading* pReshading;
3578 	if((pReshading = (IReshading*)pShader->GetInterface(IID_IReshading)) != NULL ){
3579 		pReshading->PreShade( sc, pFrag );
3580 	}
3581 	if( bumped )
3582 		sc.SetNormal( sc.OrigNormal() );
3583 }
3584 
PostShade(ShadeContext & sc,IReshadeFragment * pFrag,int & nextTexIndex,IllumParams *)3585 void XRayMtl::PostShade(ShadeContext& sc, IReshadeFragment* pFrag, int& nextTexIndex, IllumParams*)
3586 {
3587 	IllumParams ip(0, NULL);
3588 	Color lightCol, rescol, diffIllum0;
3589 	float opac;
3590 	RGBA mval;
3591 	Point3  P;
3592 	BOOL bumped = FALSE;
3593 
3594 #ifdef _DEBUG
3595 	IPoint2 sPt = sc.ScreenCoord();
3596 	if( sPt.x == xStop && sPt.y == yStop )
3597 		long junk = -1;
3598 #endif
3599 
3600 	pShader->Update( sc.CurTime(), FOREVER ); // mjm - 12.17.99
3601 	pShader->GetIllumParams( sc, ip );
3602 	ip.ClearOutputs();
3603 	ip.pShader = pShader;
3604 	ip.pMtl = this;
3605 
3606 	opac =  opacity;
3607 
3608 	int ambChan = stdIDToChannel[ ID_AM ];
3609 	int diffChan = stdIDToChannel[ ID_DI ];
3610 	int trChan = stdIDToChannel[ ID_OP ];
3611 	int filtChan = stdIDToChannel[ ID_FI ];
3612 	int reflChan = stdIDToChannel[ ID_RL ];
3613 	int refrChan = stdIDToChannel[ ID_RR ];
3614 
3615 	if ( filtChan >= 0 )ip.channels[filtChan] = filter;
3616 	if ( trChan >= 0 ) ip.channels[trChan].r = opac;
3617 	ULONG trType = (flags & NEWSTDMTL_FILT_TRANSP) ? TRANSP_FILTER :
3618 	(flags & NEWSTDMTL_ADD_TRANSP) ? TRANSP_ADD : TRANSP_SUB;
3619 
3620 	P = sc.P();		// position
3621 
3622 	ip.stdParams = pShader->SupportStdParams();
3623 
3624 	// Do texture mapping
3625 	ip.hasComponents = 0;
3626 	ip.stdIDToChannel = stdIDToChannel;
3627 	//	sc.SetIOR(ioRefract);
3628 
3629 	// All normal color & scalar maps are handled here
3630 	if (pFrag->NChannels() > 0) {
3631 
3632 		// bump mapping
3633 		if( DOMAP( stdIDToChannel[ ID_BU ] ) ) {
3634 			bumped = TRUE;
3635 			// NB: shadeContext has perturbed normal
3636 			sc.SetNormal( pFrag->GetUnitVecChannel( nextTexIndex++ ) );
3637 		}
3638 
3639 		RGBA c;
3640 		for ( long i = 0; i < STD2_NMAX_TEXMAPS; ++i ) {
3641 			if ( sc.doMaps && (*maps)[ i ].IsActive()) {
3642 				long t = pShader->ChannelType(i);
3643 				// composite the channel
3644 				if ( (t & SKIP_CHANNELS)==0 ){
3645 					if ( t & MONO_CHANNEL ) {
3646 						// note: r always holds channel data for mono channels
3647 						ip.channels[ i ].r = (*maps)[i].LerpMono( ip.channels[ i ].r, pFrag->GetFloatChannel(nextTexIndex++)); // mjm - 1.17.00
3648 					} else {
3649 						if ( i != ambChan || (flags & NEWSTDMTL_LOCK_ADTEX)==0 ) {
3650 							if ((*maps)[ i ].map->IsHighDynamicRange()) {
3651 								LogLUV32Pixel lc;
3652 								lc.value = pFrag->GetIntChannel(nextTexIndex++);
3653 								lc.GetRGB(c);
3654 								c.a = pFrag->GetFloatChannel(nextTexIndex++);
3655 							}
3656 							else {
3657 								c = pFrag->GetColorChannel(nextTexIndex++);
3658 							}
3659 							c *= (*maps)[i].amount; // mjm - 1.17.00
3660 							AlphaCompCol( ip.channels[ i ], c);
3661 						}
3662 					}
3663 					// lock adtex, really channels 0 & 1
3664 					if ( i == diffChan && (flags & NEWSTDMTL_LOCK_ADTEX) && ambChan >= 0  ) {
3665 						AlphaCompCol( ip.channels[ ambChan ], c );
3666 					}
3667 				}// end, don't skip
3668 			} // end, is active
3669 		}// end, for each possible map
3670 
3671 		// Evaluate reflection map.
3672 		if ( (*maps)[ reflChan ].map )
3673 			ip.hasComponents |= HAS_REFLECT_MAP;
3674 
3675 		if (DOMAP(reflChan) ) {
3676 			ip.hasComponents |= HAS_REFLECT;
3677 			AColor rcol;										 // mjm - 1.17.00
3678 			if ((*maps)[ reflChan ].map->IsHighDynamicRange()) {
3679 				LogLUV32Pixel lc;
3680 				lc.value = pFrag->GetIntChannel(nextTexIndex++);
3681 				lc.GetRGB(rcol);
3682 				rcol.a = pFrag->GetFloatChannel(nextTexIndex++);
3683 			}
3684 			else {
3685 				rcol = pFrag->GetColorChannel( nextTexIndex++ ); // mjm - 1.17.00
3686 			}
3687 			Color rc(rcol.r, rcol.g, rcol.b);
3688 			ip.channels[reflChan] = rc;
3689 			ip.reflectAmt = rcol.a * (*maps)[reflChan].amount;
3690 		}
3691 
3692 		// do refraction map
3693 		if ( (*maps)[ refrChan ].map )
3694 			ip.hasComponents |= HAS_REFRACT_MAP;
3695 
3696 		if (DOMAP(refrChan) ) {
3697 			// Evaluate refraction map, as yet unfiltered by filter color.
3698 			ip.refractAmt = (*maps)[refrChan].amount;
3699 			AColor rcol;										 // mjm - 1.17.00
3700 			if ((*maps)[ refrChan ].map->IsHighDynamicRange()) {
3701 				LogLUV32Pixel lc;
3702 				lc.value = pFrag->GetIntChannel(nextTexIndex++);
3703 				lc.GetRGB(rcol);
3704 			}
3705 			else {
3706 				rcol = pFrag->GetColorChannel( nextTexIndex++ ); // mjm - 1.17.00
3707 			}
3708 			Color rc(  rcol.r,  rcol.g,  rcol.b );
3709 			ip.channels[refrChan] = rc;
3710 			ip.hasComponents |= HAS_REFRACT;
3711 		}
3712 	} // end, at least one map
3713 
3714 	// get falloff opacity for possible use by shader or compositor
3715 	opac = ip.channels[trChan].r; // get (perhaps) textured opacity
3716 
3717 	ip.finalOpac = GetEffOpacity( sc, opac );
3718 	if( ip.finalOpac < 1.0f )
3719 		ip.hasComponents |= HAS_OPACITY;
3720 
3721 	// init the global ambient
3722 	ip.ambIllumOut = sc.ambientLight;
3723 
3724 	// mapping done, illuminate...
3725 	IReshading* pReshading;
3726 	if((pReshading = (IReshading*)pShader->GetInterface(IID_IReshading)) != NULL ){
3727 		pReshading->PostShade( sc, pFrag, nextTexIndex, &ip );
3728 	}
3729 
3730 	// return color in sc, not the frag itself
3731 	sc.out.c = ip.finalC;
3732 	sc.out.t = ip.finalT;
3733 
3734 	if( bumped )
3735 		sc.SetNormal( sc.OrigNormal() );
3736 }
3737 
3738 // too late for sdk, eco in progress
CloneIp(IllumParams & ip)3739 IllumParams* CloneIp( IllumParams& ip )
3740 {
3741 	IllumParams* pClone = new IllumParams( ip.nUserIllumOut, ip.userIllumNames );
3742 	pClone->finalC = ip.finalC;
3743 	pClone->finalT = ip.finalT;
3744 	pClone->finalOpac = ip.finalOpac;
3745 	pClone->finalAttenuation = ip.finalAttenuation;
3746 	pClone->ambIllumOut = ip.ambIllumOut;
3747 	pClone->diffIllumOut = ip.diffIllumOut;
3748 	pClone->transIllumOut = ip.transIllumOut;
3749 	pClone->selfIllumOut = ip.selfIllumOut;
3750 	pClone->specIllumOut = ip.specIllumOut;
3751 	pClone->reflIllumOut = ip.reflIllumOut;
3752 	pClone->transIllumOut = ip.transIllumOut;
3753 	pClone->diffIllumIntens = ip.diffIllumIntens;
3754 	for( int i=0; i < ip.nUserIllumOut; ++i )
3755 		pClone->userIllumOut[i] = ip.userIllumOut[i];
3756 
3757 	pClone->stdParams = ip.stdParams;
3758 	pClone->hasComponents = ip.hasComponents;
3759 	pClone->pShader = ip.pShader;
3760 	pClone->pMtl = ip.pMtl;
3761 	pClone->stdIDToChannel = ip.stdIDToChannel;
3762 	pClone->refractAmt = ip.refractAmt;
3763 	pClone->reflectAmt = ip.reflectAmt;
3764 
3765 	for( i=0; i < STD2_NMAX_TEXMAPS; ++i )
3766 		pClone->channels[ i ] = ip.channels[ i ];
3767 
3768 	return pClone;
3769 }
3770 
3771 
3772 // if this function changes, please also check SupportsReShading, PreShade, PostShade
3773 // end - ke/mjm - 03.16.00 - merge reshading code
3774 // [attilas|24.5.2000] if this function changes, please also check EvalColorStdChannel
Shade(ShadeContext & sc)3775 void XRayMtl::Shade(ShadeContext& sc)
3776 {
3777 	IllumParams ip( pShader->nUserIllumOut(), pShader->UserIllumNameArray() );
3778 	Color lightCol, rescol, diffIllum0;
3779 	float opac;
3780 	RGBA mval;
3781 	Point3 N0, P;
3782 
3783 #ifdef _DEBUG
3784 	IPoint2 sPt = sc.ScreenCoord();
3785 	if( sPt.x == xStop && sPt.y == yStop )
3786 		long junk = -1;
3787 #endif
3788 
3789 	BOOL bumped = FALSE;
3790 	if (gbufID) sc.SetGBufferID(gbufID);
3791 	//	ip.mtlFlags = flags;
3792 
3793 	pShader->GetIllumParams( sc, ip );
3794 	ip.ClearOutputs();
3795 	ip.pShader = pShader;
3796 	ip.pMtl = this;
3797 
3798 	//	N0 = ip.N = sc.Normal();
3799 	N0 = sc.Normal();
3800 	opac =  opacity;
3801 
3802 	int ambChan = stdIDToChannel[ ID_AM ];
3803 	int diffChan = stdIDToChannel[ ID_DI ];
3804 	int trChan = stdIDToChannel[ ID_OP ];
3805 	int filtChan = stdIDToChannel[ ID_FI ];
3806 	if ( filtChan >= 0 )ip.channels[filtChan] = filter;
3807 	if ( trChan >= 0 ) ip.channels[trChan].r = opac;
3808 	ULONG trType = (flags & NEWSTDMTL_FILT_TRANSP) ? TRANSP_FILTER :
3809 	(flags & NEWSTDMTL_ADD_TRANSP) ? TRANSP_ADD : TRANSP_SUB;
3810 
3811 	if (sc.mode==SCMODE_SHADOW) {
3812 		// Opacity mapping;
3813 		if (DOMAP(trChan))
3814 			opac = (*maps)[trChan].LerpEvalMono(sc, opac);
3815 
3816 		// "Shadow mode": This just computes the transparency, which is all
3817 		// you need for shadowing.
3818 		if (opac!=1.0f || opfall!=0.0f) {
3819 
3820 			if (opfall != 0.0f) {
3821 				opac = GetEffOpacity(sc, opac);
3822 			}
3823 
3824 			// Transparency may use diffuse color mapping, check for orig 3ds transp
3825 			if ((flags & (NEWSTDMTL_ADD_TRANSP|NEWSTDMTL_FILT_TRANSP))==0) {
3826 				if (DOMAP(diffChan)) {
3827 					mval = (*maps)[diffChan].Eval(sc);
3828 					AlphaCompCol(ip.channels[diffChan], mval);
3829 				}
3830 			}
3831 			// Transparency may also use filter color mapping
3832 			if ( flags & NEWSTDMTL_FILT_TRANSP ){
3833 				if (DOMAP(filtChan)) {
3834 					mval = (*maps)[filtChan].Eval(sc);
3835 					AlphaCompCol(ip.channels[filtChan], mval);
3836 				}
3837 			}
3838 			// Compute the transpareny color
3839 			sc.out.t = TranspColor( opac, ip.channels[filtChan], ip.channels[diffChan]);
3840 		} else
3841 			sc.out.t.Black();
3842 		return;
3843 	} // end, shadow mode
3844 
3845 	// any shader can be faceted...& bumpmapped as well
3846 	if ( flags & NEWSTDMTL_FACETED ){
3847 		Point3 N = sc.GNormal();
3848 		bumped = TRUE;
3849 		sc.SetNormal(N);
3850 	}
3851 
3852 	P = sc.P();		// position
3853 
3854 	ip.stdParams = pShader->SupportStdParams();
3855 
3856 	// Do texture mapping
3857 	ip.hasComponents = 0;
3858 	ip.stdIDToChannel = stdIDToChannel;
3859 	sc.SetIOR(ioRefract);
3860 
3861 	// Bump mapping: Do this FIRST so other maps can use the perturbed normal
3862 	int bumpChannel = stdIDToChannel[ID_BU];
3863 	if (DOMAP(bumpChannel)) {
3864 		ip.hasComponents |= HAS_BUMPS;
3865 		Point3 dn = (*maps)[bumpChannel].EvalNormalPerturb(sc);
3866 		Point3 N = Normalize( sc.Normal() + (sc.backFace?-dn:dn) );
3867 		sc.SetNormal(N);
3868 		bumped = TRUE;
3869 	}
3870 
3871 	// All normal color & scalar maps are handled here
3872 	long t0 = pShader->ChannelType(0);
3873 	RGBA c;
3874 	for ( long i = 0; i < STD2_NMAX_TEXMAPS; ++i ) {
3875 		if ( sc.doMaps && (*maps)[ i ].IsActive()) {
3876 			long t = pShader->ChannelType(i);
3877 			// composite the channel
3878 			if ( (t & SKIP_CHANNELS)==0 ){
3879 				if ( t & MONO_CHANNEL ) {
3880 					// note: x always holds channel data for mono channels
3881 					ip.channels[ i ].r = (*maps)[i].LerpEvalMono(sc, ip.channels[ i ].r );
3882 				} else {
3883 					if ( i != ambChan || (flags & NEWSTDMTL_LOCK_ADTEX)==0 ) {
3884 						c = (*maps)[i].Eval(sc);
3885 						AlphaCompCol( ip.channels[ i ], c);
3886 					}
3887 				}
3888 				// lock adtex, really channels 0 & 1
3889 				if ( i == diffChan && ambChan >= 0 && (flags & NEWSTDMTL_LOCK_ADTEX) ) {
3890 					if ( t0 & MONO_CHANNEL ) {
3891 						ip.channels[ ambChan ].r = (*maps)[diffChan].LerpEvalMono(sc, ip.channels[diffChan].r );
3892 					} else {
3893 						AlphaCompCol( ip.channels[ ambChan ], c );
3894 					}
3895 
3896 				}
3897 			}
3898 		}
3899 	}
3900 
3901 	// Evaluate reflection map.
3902 	int reflChan = stdIDToChannel[ ID_RL ];
3903 	if ( (*maps)[ reflChan ].map )
3904 		ip.hasComponents |= HAS_REFLECT_MAP;
3905 
3906 	if (DOMAP(reflChan)) {
3907 		ip.hasComponents |= HAS_REFLECT;
3908 		AColor rcol;
3909 		Texmap *reflmap = (*maps)[reflChan].map;
3910 		if (reflmap->HandleOwnViewPerturb()) {
3911 			sc.TossCache(reflmap);
3912 			rcol = reflmap->EvalColor(sc);
3913 		} else
3914 			rcol = sc.EvalEnvironMap(reflmap, sc.ReflectVector());
3915 		Color rc(rcol.r, rcol.g, rcol.b);
3916 		ip.channels[reflChan] = rc;
3917 		ip.reflectAmt = rcol.a * (*maps)[reflChan].amount;
3918 	}
3919 
3920 	// do refraction map
3921 	int refrChan = stdIDToChannel[ ID_RR ];
3922 	if ( (*maps)[ reflChan ].map )
3923 		ip.hasComponents |= HAS_REFRACT_MAP;
3924 
3925 	if (DOMAP(refrChan)) {
3926 		// Evaluate refraction map, as yet unfiltered by filter color.
3927 		ip.refractAmt = (*maps)[refrChan].amount;
3928 		Texmap *refrmap = (*maps)[refrChan].map;
3929 		AColor rcol;
3930 		if (refrmap->HandleOwnViewPerturb())
3931 			rcol = refrmap->EvalColor( sc );
3932 		else
3933 			rcol = sc.EvalEnvironMap( refrmap, sc.RefractVector(ioRefract) );
3934 
3935 		Color rc(  rcol.r,  rcol.g,  rcol.b );
3936 		ip.channels[refrChan] = rc;
3937 		ip.hasComponents |= HAS_REFRACT;
3938 	}
3939 
3940 	// get falloff opacity for possible use by shader or compositor
3941 	opac = ip.channels[trChan].r; // get (perhaps) textured opacity
3942 
3943 	ip.finalOpac = GetEffOpacity(sc, opac);
3944 	if(ip.finalOpac < 1.0f)
3945 		ip.hasComponents |= HAS_OPACITY;
3946 
3947 	// init the global ambient
3948 	ip.ambIllumOut = sc.ambientLight;
3949 
3950 	// mapping done, illuminate...
3951 	pShader->Illum(sc, ip);
3952 
3953 	// return color in sc, not the frag itself
3954 	sc.out.c = ip.finalC;
3955 	sc.out.t = ip.finalT;
3956 
3957 	// Render Elements
3958 	// note: shadow must be on for any shadows to work. no ele's will get shadows
3959 	// with shadows off
3960 	int nEles = sc.NRenderElements();
3961 	if( nEles != 0 ){
3962 		IllumParams* pIp2 = CloneIp( ip ); // too late for sdk, eco in progress
3963 		if( sc.shadow ){
3964 			// get unshadowed ip
3965 			sc.shadow = FALSE;
3966 			pIp2->ClearOutputs();
3967 			pShader->Illum(sc, *pIp2);
3968 			sc.shadow = TRUE;
3969 		}
3970 		for( int i=0; i < nEles; ++i ){
3971 			IRenderElement* pEle = sc.GetRenderElement(i);
3972 			if( pEle->IsEnabled() ){
3973 				MaxRenderElement* pMaxEle = (MaxRenderElement*)pEle->GetInterface( MaxRenderElement::IID );
3974 				if( pEle->ShadowsApplied() )
3975 					pMaxEle->PostIllum( sc, ip );
3976 				else
3977 					pMaxEle->PostIllum( sc, *pIp2 );
3978 			}
3979 		}
3980 		delete pIp2;
3981 	}
3982 
3983 	if (bumped) sc.SetNormal(N0); // restore normal
3984 }
3985 
3986 
EvalDisplacement(ShadeContext & sc)3987 float XRayMtl::EvalDisplacement(ShadeContext& sc) {
3988 	int dispChan = stdIDToChannel[ ID_DP ];
3989 	if (DOMAP(dispChan))
3990 		return (*maps)[dispChan].EvalMono(sc);
3991 	else return 0.0f;
3992 }
3993 
3994 
DisplacementValidity(TimeValue t)3995 Interval XRayMtl::DisplacementValidity(TimeValue t) {
3996 	int dispChan = stdIDToChannel[ ID_DP ];
3997 	if (MAPACTIVE(dispChan)) {
3998 		Interval iv;
3999 		iv.SetInfinite();
4000 		maps->txmap[dispChan].Update(t, iv);
4001 		return iv;
4002 	}
4003 	else
4004 		return FOREVER;
4005 }
4006 
DiscardTexHandles()4007 void XRayMtl::DiscardTexHandles() {
4008 	for (int i=0; i<2; i++) {
4009 		if (texHandle[i]) {
4010 			texHandle[i]->DeleteThis();
4011 			texHandle[i] = NULL;
4012 		}
4013 	}
4014 	texHandleValid.SetEmpty();
4015 }
4016 
4017 // begin - dds- 04.27.00 - multiple map display support
ActivateTexDisplay(BOOL onoff)4018 void XRayMtl::ActivateTexDisplay(BOOL onoff) {
4019 	if (!onoff) {
4020 		DiscardTexHandles();
4021 	}
4022 }
4023 
4024 struct TextOps {
4025 	UBYTE colorOp;
4026 	UBYTE colorAlphaSource;
4027 	UBYTE colorScale;
4028 	UBYTE alphaOp;
4029 	UBYTE alphaAlphaSource;
4030 	UBYTE alphaScale;
4031 };
4032 
4033 // TBD: these values have to be corrected.
4034 #define TXOP_MODULATE 0
4035 #define TXOP_ALPHABLEND 1
4036 #define TXOP_OPACITY 2
4037 static TextOps txops[] = {
4038 	{ GW_TEX_MODULATE, GW_TEX_TEXTURE, GW_TEX_SCALE_1X, GW_TEX_LEAVE, GW_TEX_TEXTURE, GW_TEX_SCALE_1X },
4039 	{ GW_TEX_ALPHA_BLEND, GW_TEX_TEXTURE, GW_TEX_SCALE_1X, GW_TEX_LEAVE,  GW_TEX_TEXTURE, GW_TEX_SCALE_1X },
4040 	{ GW_TEX_LEAVE, GW_TEX_TEXTURE, GW_TEX_SCALE_1X, GW_TEX_REPLACE, GW_TEX_TEXTURE, GW_TEX_SCALE_1X },
4041 };
4042 
SetTexOps(Material * mtl,int i,int type)4043 void XRayMtl::SetTexOps(Material *mtl, int i, int type) {
4044 	TextureInfo *ti = &mtl->texture[i];
4045 	ti->colorOp = txops[type].colorOp;
4046 	ti->colorAlphaSource = txops[type].colorAlphaSource;
4047 	ti->colorScale = txops[type].colorScale;
4048 	ti->alphaOp = txops[type].alphaOp;
4049 	ti->alphaAlphaSource = txops[type].alphaAlphaSource;
4050 	ti->alphaScale = txops[type].alphaScale;
4051 	texOpsType[i] = type;
4052 }
4053 
4054 #define BMIDATA(x) ((UBYTE *)((BYTE *)(x) + sizeof(BITMAPINFOHEADER)))
4055 
StuffAlpha(BITMAPINFO * bi,float amt,float opac,Color fill)4056 static void StuffAlpha(BITMAPINFO *bi, float amt, float opac, Color fill) {
4057 	int w = bi->bmiHeader.biWidth;
4058 	int h = bi->bmiHeader.biHeight;
4059 	int npix = w*h;
4060 	UBYTE *a = BMIDATA(bi);
4061 	Color24 col;
4062 	col.r = (int)(fill.r*255.0f);
4063 	col.g = (int)(fill.g*255.0f);
4064 	col.b = (int)(fill.b*255.0f);
4065 	if (amt<1.0f) {
4066 		int ia = int(amt*255.0f);
4067 		int	ic = int( (1.0f-amt)*opac*255.0f);
4068 		for (int j=0; j<npix; j++) {
4069 			a[3] = ((( (a[0]+a[1]+a[2])/3 )*ia )>>8) + ic;
4070 			a[0] = col.b;
4071 			a[1] = col.g;
4072 			a[2] = col.r;
4073 			a += 4;
4074 		}
4075 	}
4076 	else {
4077 		for (int j=0; j<npix; j++) {
4078 			a[3] = (a[0]+a[1]+a[2])/3;
4079 			a[0] = col.b;
4080 			a[1] = col.g;
4081 			a[2] = col.r;
4082 			a += 4;
4083 		}
4084 	}
4085 }
4086 
4087 
StuffAlphaInto(BITMAPINFO * bia,BITMAPINFO * bi,float amt,float opac)4088 static void StuffAlphaInto(BITMAPINFO *bia, BITMAPINFO *bi, float amt, float opac) {
4089 	int w = bi->bmiHeader.biWidth;
4090 	int h = bi->bmiHeader.biHeight;
4091 	int npix = w*h;
4092 	UBYTE *a = BMIDATA(bia);
4093 	UBYTE *b = BMIDATA(bi);
4094 	if (amt<1.0f) {
4095 		int ia = int(amt*255.0f);
4096 		int	ic = int( (1.0f-amt)*opac*255.0f);
4097 		for (int j=0; j<npix; j++) {
4098 			b[3] = ((( (a[0]+a[1]+a[2])/3 )*ia )>>8) + ic;
4099 			a += 4;
4100 			b += 4;
4101 		}
4102 	}
4103 	else {
4104 		for (int j=0; j<npix; j++) {
4105 			b[3] = (a[0]+a[1]+a[2])/3;
4106 			a += 4;
4107 			b += 4;
4108 		}
4109 	}
4110 }
4111 
4112 #if 0
4113 static BOOL SameUV(TextureInfo &ta, TextureInfo &tb) {
4114 	if (ta.uvwSource!=tb.uvwSource) return FALSE;
4115 	if (ta.mapChannel!=tb.mapChannel) return FALSE;
4116 	if (ta.tiling[0]!=tb.tiling[0]) return FALSE;
4117 	if (ta.tiling[1]!=tb.tiling[1]) return FALSE;
4118 	if (ta.tiling[2]!=tb.tiling[2]) return FALSE;
4119 	if (ta.faceMap!=tb.faceMap) return FALSE;
4120 	if (!(ta.textTM==tb.textTM)) return FALSE;
4121 	return TRUE;
4122 }
4123 #endif
4124 
4125 static Color whiteCol(1.0f, 1.0f, 1.0f);
4126 
SetupGfxMultiMaps(TimeValue t,Material * mtl,MtlMakerCallback & cb)4127 void XRayMtl::SetupGfxMultiMaps(TimeValue t, Material *mtl, MtlMakerCallback &cb) {
4128 	if (texHandleValid.InInterval(t)) {
4129 		mtl->texture.SetCount(numTexHandlesUsed);
4130 		for (int i=0; i<numTexHandlesUsed; i++) {
4131 			if (texHandle[i]) {
4132 				mtl->texture[i].textHandle = texHandle[i]->GetHandle();
4133 				Texmap *tx = (*maps)[useSubForTex[i]].map;
4134 				cb.GetGfxTexInfoFromTexmap(t, mtl->texture[i], tx );
4135 				SetTexOps(mtl,i,texOpsType[i]);
4136 			}
4137 		}
4138 		return;
4139 	}
4140 
4141 	Texmap *tx[2];
4142 	int diffChan = stdIDToChannel[ ID_DI ];
4143 	int opacChan = stdIDToChannel[ ID_OP ];
4144 	tx[0] = (*maps)[diffChan].IsActive()?(*maps)[diffChan].map:NULL;
4145 	tx[1] = (*maps)[opacChan].IsActive()?(*maps)[opacChan].map:NULL;
4146 
4147 	int nsupport = cb.NumberTexturesSupported();
4148 
4149 	BITMAPINFO *bmi[NTEXHANDLES];
4150 
4151 	int nmaps=0;
4152 	for (int i=0; i<NTEXHANDLES; i++) {
4153 		if (tx[i]) nmaps ++;
4154 		bmi[i] = NULL;
4155 	}
4156 	mtl->texture.SetCount(nmaps);
4157 	if (nmaps==0)
4158 		return;
4159 	for (i=0; i<nmaps; i++)
4160 		mtl->texture[i].textHandle = NULL;
4161 	texHandleValid.SetInfinite();
4162 	Interval  valid;
4163 	BOOL needDecal = FALSE;
4164 	int ntx = 0;
4165 	int op;
4166 
4167 	int forceW = 0;
4168 	int forceH = 0;
4169 	if (tx[0]) {
4170 		cb.GetGfxTexInfoFromTexmap(t, mtl->texture[0], tx[0]);
4171 		TextureInfo &ti = mtl->texture[0];
4172 		if (ti.tiling[0]==GW_TEX_NO_TILING||ti.tiling[1]==GW_TEX_NO_TILING)
4173 			needDecal = TRUE;
4174 		op = needDecal?TXOP_ALPHABLEND:TXOP_MODULATE;
4175 		bmi[0] = tx[0]->GetVPDisplayDIB(t,cb,valid,FALSE);
4176 		if (bmi[0]) {
4177 			texHandleValid &= valid;
4178 			useSubForTex[0] = diffChan;
4179 			ntx = 1;
4180 			forceW = bmi[0]->bmiHeader.biWidth;
4181 			forceH = bmi[0]->bmiHeader.biHeight;
4182 		}
4183 	}
4184 	if (tx[1]) {
4185 		cb.GetGfxTexInfoFromTexmap(t, mtl->texture[ntx], tx[1]);
4186 		if (nsupport>ntx) {
4187 			bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE);
4188 			if (bmi[1]) {
4189 				texHandleValid &= valid;
4190 				StuffAlpha(bmi[1], (*maps)[opacChan].amount, GetOpacity(t),ntx?whiteCol:pShader->GetDiffuseClr(t));
4191 				texHandle[ntx] = cb.MakeHandle(bmi[1]);
4192 				bmi[1] = NULL;
4193 				mtl->texture[ntx].textHandle = texHandle[ntx]->GetHandle();
4194 				SetTexOps(mtl,ntx,TXOP_OPACITY);
4195 				useSubForTex[ntx] = opacChan;
4196 				ntx++;
4197 			}
4198 		}
4199 		else {
4200 			if (!needDecal) {
4201 				TextureInfo ti;
4202 				//				if (SameUV(mtl->texture[0],mtl->texture[1])) {
4203 				// Not really correct to combine channels for different UV's but what the heck.
4204 				bmi[1] = tx[1]->GetVPDisplayDIB(t,cb,valid,TRUE, forceW, forceH);
4205 				if (bmi[1]) {
4206 					texHandleValid &= valid;
4207 					StuffAlphaInto(bmi[1], bmi[0], (*maps)[opacChan].amount, GetOpacity(t));
4208 					op = TXOP_OPACITY;
4209 					free(bmi[1]);
4210 					bmi[1] = NULL;
4211 				}
4212 				//					}
4213 			}
4214 		}
4215 	}
4216 	if (bmi[0])	{
4217 		texHandle[0] = cb.MakeHandle(bmi[0]);
4218 		bmi[0] = NULL;
4219 		mtl->texture[0].textHandle = texHandle[0]->GetHandle();
4220 		SetTexOps(mtl,0,op);
4221 	}
4222 	mtl->texture.SetCount(ntx);
4223 	numTexHandlesUsed = ntx;
4224 }
4225 
4226 // end - dds- 04.27.00 - multiple map display support
4227 
4228 //������������������������������������������������������������������������
4229 // Returns true if the evaluated color\value (output) is constant over all
4230 // possible inputs. This means all points of a face and all faces the
4231 // material is assigned to.
4232 // If it cannot determine the correct answer, it returns false
4233 //
IsOutputConst(ShadeContext & sc,int stdID)4234 bool XRayMtl::IsOutputConst
4235 (
4236  ShadeContext& sc, // describes context of evaluation
4237  int stdID				// must be ID_AM, ect
4238  )
4239 {
4240 	int channelID = StdIDToChannel( stdID );
4241 	DbgAssert( 0 <= channelID && channelID < NumSubTexmaps() );
4242 	if ( channelID < 0 || channelID >= NumSubTexmaps() )
4243 		return false;
4244 
4245 	if ( SubTexmapOn( channelID ) )
4246 	{
4247 		Texmap* texMap = GetSubTexmap( channelID );
4248 		DbgAssert( texMap != NULL );
4249 		if ( texMap != NULL && texMap->IsOutputMeaningful( sc ) )
4250 			// TODO: The texmap can be meaningful but constant
4251 			return false;
4252 	}
4253 	return true;
4254 }
4255 
4256 //������������������������������������������������������������������������
4257 // Evaluates the material on a single texmap channel.
4258 // For a mono channel, the value is copied in all 3 components of the
4259 // output color.
4260 //
EvalColorStdChannel(ShadeContext & sc,int stdID,Color & outClr)4261 bool XRayMtl::EvalColorStdChannel
4262 (
4263  ShadeContext& sc, // describes context of evaluation
4264  int stdID,				// must be ID_AM, ect
4265  Color& outClr			// output var
4266  )
4267 {
4268 	switch ( stdID )
4269 	{
4270 	case ID_BU: // Bump (value 8)
4271 		{
4272 			return EvalBump( sc, outClr );
4273 		}
4274 		break;
4275 
4276 	case ID_RL: // Reflection (value 9)
4277 		{
4278 			return EvalReflection( sc, outClr );
4279 		}
4280 		break;
4281 
4282 	case ID_RR: // Refraction (value 10)
4283 		{
4284 			return EvalRefraction( sc, outClr );
4285 		}
4286 		break;
4287 
4288 	case ID_DP: // Displacement (value 11)
4289 		{
4290 			float outVal;
4291 			bool bRes = EvalDisplacement( sc, outVal );
4292 			if ( bRes )
4293 			{
4294 				outClr.r = outClr.g = outClr.b = outVal;
4295 			}
4296 			return bRes;
4297 		}
4298 		break;
4299 
4300 		// For everything else, there's a smart method
4301 	case ID_AM: // Ambient (value 0)
4302 	case ID_DI: // Diffuse (value 1)
4303 	case ID_SP: // Specular (value 2)
4304 	case ID_SH: // Shininess (value 3).  In R3 and later this is called Glossiness.
4305 	case ID_SS: // Shininess strength (value 4).  In R3 and later this is called Specular Level.
4306 	case ID_SI: // Self-illumination (value 5)
4307 	case ID_OP: // Opacity (value 6)
4308 	case ID_FI: // Filter color (value 7)
4309 		{
4310 			int id = StdIDToChannel( stdID );
4311 			if ( id < 0 || id >= NumSubTexmaps() )
4312 				return false;
4313 			return EvalChannel( sc, id, outClr );
4314 		}
4315 		break;
4316 
4317 	default:
4318 		// Should never happen
4319 		//DbgAssert( false );
4320 		return false;
4321 		break;
4322 	}
4323 	return true;
4324 }
4325 
4326 //������������������������������������������������������������������������
4327 // Evaluates the material on a single texmap channel.
4328 //
EvalMonoStdChannel(ShadeContext & sc,int stdID,float & outVal)4329 bool XRayMtl::EvalMonoStdChannel
4330 (
4331  ShadeContext& sc, // describes context of evaluation
4332  int stdID,				// must be ID_AM, ect
4333  float& outVal			// output var
4334  )
4335 {
4336 	switch ( stdID )
4337 	{
4338 	case ID_BU: // Bump (value 8)
4339 		{
4340 			Color outClr;
4341 			bool bRes = EvalBump( sc, outClr );
4342 			if ( bRes )
4343 				outVal = Intens( outClr );
4344 			return bRes;
4345 		}
4346 		break;
4347 
4348 	case ID_RL: // Reflection (value 9)
4349 		{
4350 			return EvalReflection( sc, outVal );
4351 		}
4352 		break;
4353 
4354 	case ID_RR: // Refraction (value 10)
4355 		{
4356 			return EvalRefraction( sc, outVal );
4357 		}
4358 		break;
4359 
4360 	case ID_DP: // Displacement (value 11)
4361 		{
4362 			return EvalDisplacement( sc, outVal );
4363 		}
4364 		break;
4365 
4366 		// For everything else, there's a smart method
4367 	case ID_AM: // Ambient (value 0)
4368 	case ID_DI: // Diffuse (value 1)
4369 	case ID_SP: // Specular (value 2)
4370 	case ID_SH: // Shininess (value 3).  In R3 and later this is called Glossiness.
4371 	case ID_SS: // Shininess strength (value 4).  In R3 and later this is called Specular Level.
4372 	case ID_SI: // Self-illumination (value 5)
4373 	case ID_OP: // Opacity (value 6)
4374 	case ID_FI: // Filter color (value 7)
4375 		{
4376 			int id = StdIDToChannel( stdID );
4377 			if ( id < 0 || id >= NumSubTexmaps() )
4378 				return false;
4379 			Color outClr;
4380 			bool bRes = EvalChannel( sc, id, outClr );
4381 			if ( bRes )
4382 				outVal = Intens( outClr );
4383 			return bRes;
4384 		}
4385 		break;
4386 
4387 	default:
4388 		// Should never happen
4389 		//DbgAssert( false );
4390 		return false;
4391 		break;
4392 	}
4393 	return true;
4394 }
4395 
4396 //������������������������������������������������������������������������
4397 // channelID is supposed to be mapped from std subtexmap ID to subtexmap id
4398 //
EvalChannel(ShadeContext & sc,int channelID,Color & outClr)4399 bool XRayMtl::EvalChannel(ShadeContext& sc, int channelID, Color& outClr)
4400 {
4401 	// For exmple, the Strauss shader doesn't support the ID_AM channel
4402 	DbgAssert( 0 <= channelID && channelID < NumSubTexmaps() );
4403 
4404 	// Check if the mtl has or not a shader
4405 	Shader* pShad = GetShader();
4406 	DbgAssert( pShader != NULL );
4407 	if ( pShad == NULL )
4408 	{
4409 		// Filter color and opacity values are managed by the stdmtl2?
4410 		if ( channelID == StdIDToChannel(ID_FI) )
4411 		{
4412 			outClr = filter;
4413 			return true;
4414 		}
4415 		else if ( channelID == StdIDToChannel(ID_FI) )
4416 		{
4417 			outClr.r = outClr.g = outClr.b = opacity;
4418 			return true;
4419 		}
4420 		return false;
4421 	}
4422 
4423 	// Get raw color\value from the shader
4424 	IllumParams ip(0, NULL);
4425 
4426 	memset(static_cast<void*>(&ip), 0, sizeof(IllumParams) );
4427 	//	ip.mtlFlags = flags;
4428 	pShad->GetIllumParams( sc, ip );
4429 
4430 	// Filter color and opacity values are managed by the stdmtl2?
4431 	if ( channelID == StdIDToChannel(ID_FI) )
4432 		ip.channels[channelID] = filter;
4433 	else if ( channelID == StdIDToChannel(ID_OP) )
4434 	{
4435 		ip.channels[channelID].r = opacity;
4436 		ip.channels[channelID].g = opacity;
4437 		ip.channels[channelID].b = opacity;
4438 	}
4439 	long channelType = pShad->ChannelType( channelID );
4440 
4441 	// Evaluate the texture map
4442 	if ( sc.doMaps )
4443 	{
4444 		if ( channelID == StdIDToChannel( ID_AM ) &&
4445 			(flags & NEWSTDMTL_LOCK_ADTEX) == NEWSTDMTL_LOCK_ADTEX )
4446 		{
4447 			// Treat exceptional situations first
4448 			//
4449 			// Evaluat the ambient channel using the diffuse texmap
4450 			// if AD texmap lock is on
4451 
4452 			long diffChanID = StdIDToChannel( ID_DI );
4453 			long diffChanType = pShad->ChannelType( ID_DI );
4454 			if ( diffChanID >= 0 &&
4455 				SubTexmapOn( diffChanID ) &&
4456 				( diffChanType & SKIP_CHANNELS ) == 0 )
4457 			{
4458 				Texmap* texMap = GetSubTexmap( diffChanID );
4459 				if ( texMap != NULL && texMap->IsOutputMeaningful( sc ) )
4460 				{
4461 					// Evaluate the diffuse channel first
4462 					AColor diffColor;
4463 					if ( (diffChanType & MONO_CHANNEL ) == MONO_CHANNEL )
4464 					{
4465 						diffColor.r = (*maps)[diffChanID].LerpEvalMono( sc, ip.channels[diffChanID].r );
4466 						diffColor.g = diffColor.b = diffColor.r;
4467 						diffColor.a = 0.0f;
4468 					}
4469 					else //if ( (diffChanType & CLR_CHANNEL ) == CLR_CHANNEL )
4470 					{
4471 						diffColor = (*maps)[diffChanID].Eval( sc );
4472 						AlphaCompCol( ip.channels[diffChanID], diffColor );
4473 					}
4474 
4475 					// Now evaluate the ambient channel
4476 					if ( (channelType & MONO_CHANNEL ) == MONO_CHANNEL )
4477 					{
4478 						ip.channels[channelID].r = (*maps)[diffChanID].LerpEvalMono( sc, ip.channels[diffChanID].r );
4479 						ip.channels[channelID].g = ip.channels[channelID].b = ip.channels[channelID].r;
4480 					}
4481 					else //if ( (channelType & CLR_CHANNEL ) == CLR_CHANNEL )
4482 						AlphaCompCol( ip.channels[channelID], diffColor );
4483 				}
4484 			}
4485 		}
4486 		else
4487 		{
4488 			// Normal course of channel evaluation
4489 
4490 			if ( SubTexmapOn( channelID ) &&
4491 				( channelType & SKIP_CHANNELS ) == 0 )
4492 			{
4493 				Texmap* texMap = GetSubTexmap( channelID );
4494 				if ( texMap != NULL && texMap->IsOutputMeaningful( sc ) )
4495 				{
4496 					if ( (channelType & MONO_CHANNEL ) == MONO_CHANNEL )
4497 					{
4498 						ip.channels[channelID].r = (*maps)[channelID].LerpEvalMono( sc, ip.channels[channelID].r );
4499 						ip.channels[channelID].g = ip.channels[channelID].b = ip.channels[channelID].r;
4500 					}
4501 					else //if ( (channelType & CLR_CHANNEL ) == CLR_CHANNEL )
4502 					{
4503 						AColor c = (*maps)[channelID].Eval( sc );
4504 						AlphaCompCol( ip.channels[channelID], c );
4505 					}
4506 				}
4507 			}
4508 		}
4509 	}
4510 
4511 	// Return a potentialy texture mapped value
4512 	outClr = ip.channels[channelID];
4513 
4514 	return true;
4515 }
4516 
4517 //������������������������������������������������������������������������
4518 // Evaluates the bump map. Returns false if the result is not meaningful
4519 //
EvalBump(ShadeContext & sc,Color & outClr)4520 bool XRayMtl::EvalBump( ShadeContext& sc, Color& outClr )
4521 {
4522 	int id = StdIDToChannel( ID_BU );
4523 	if ( !ShouldEvalSubTexmap( sc, id ) )
4524 	{
4525 		outClr.Black();
4526 		return false;
4527 	}
4528 
4529 	Point3 dn = (*maps)[id].EvalNormalPerturb(sc);
4530 	outClr = Normalize( ( sc.backFace ? -dn : dn ) );
4531 
4532 	return true;
4533 }
4534 
4535 //������������������������������������������������������������������������
4536 // Evaluates reflection map as a color. Returns false if the result is not
4537 // meaningful
4538 //
EvalReflection(ShadeContext & sc,Color & outClr)4539 bool XRayMtl::EvalReflection( ShadeContext& sc, Color& outClr )
4540 {
4541 	int id = StdIDToChannel( ID_RL );
4542 	if ( !ShouldEvalSubTexmap( sc, id ) )
4543 	{
4544 		return false;
4545 	}
4546 
4547 	AColor rcol;
4548 	Texmap* reflmap = (*maps)[id].map;
4549 	DbgAssert( reflmap != NULL );
4550 	if ( reflmap->HandleOwnViewPerturb() )
4551 	{
4552 		sc.TossCache( reflmap );
4553 		rcol = reflmap->EvalColor( sc );
4554 	}
4555 	else
4556 		rcol = sc.EvalEnvironMap( reflmap, sc.ReflectVector() );
4557 
4558 	outClr.r = rcol.r;
4559 	outClr.g = rcol.g;
4560 	outClr.b = rcol.b;
4561 
4562 	return true;
4563 }
4564 
4565 //������������������������������������������������������������������������
4566 // Evaluates reflection map as (mono) value. Returns false if the result
4567 // is not meaningful
4568 //
EvalReflection(ShadeContext & sc,float & outVal)4569 bool XRayMtl::EvalReflection( ShadeContext& sc, float& outVal )
4570 {
4571 	int id = StdIDToChannel( ID_RL );
4572 	if ( !ShouldEvalSubTexmap( sc, id ) )
4573 		return false;
4574 
4575 	Texmap* reflmap = (*maps)[id].map;
4576 	DbgAssert( reflmap != NULL );
4577 	if ( reflmap->HandleOwnViewPerturb() )
4578 	{
4579 		sc.TossCache( reflmap );
4580 		outVal = reflmap->EvalMono( sc );
4581 	}
4582 	else
4583 	{
4584 		AColor rcol;
4585 		rcol = sc.EvalEnvironMap( reflmap, sc.ReflectVector() );
4586 		outVal = Intens( rcol );
4587 	}
4588 
4589 	return true;
4590 }
4591 
4592 //������������������������������������������������������������������������
4593 // Evaluates refraction map as a color. Returns false if the result is not
4594 // meaningful
4595 //
EvalRefraction(ShadeContext & sc,Color & outClr)4596 bool XRayMtl::EvalRefraction( ShadeContext& sc, Color& outClr )
4597 {
4598 	int id = StdIDToChannel( ID_RR );
4599 	if ( !ShouldEvalSubTexmap( sc, id ) )
4600 		return false;
4601 
4602 	AColor rcol;
4603 	Texmap* refrmap = (*maps)[id].map;
4604 	DbgAssert( refrmap != NULL );
4605 	if ( refrmap->HandleOwnViewPerturb() )
4606 	{
4607 		rcol = refrmap->EvalColor( sc );
4608 	}
4609 	else
4610 		rcol = sc.EvalEnvironMap( refrmap, sc.RefractVector( ioRefract ) );
4611 
4612 	outClr.r = rcol.r;
4613 	outClr.g = rcol.g;
4614 	outClr.b = rcol.b;
4615 
4616 	return true;
4617 }
4618 
4619 //������������������������������������������������������������������������
4620 // Evaluates reflection map as (mono) value. Returns false if the result
4621 // is not meaningful
4622 //
EvalRefraction(ShadeContext & sc,float & outVal)4623 bool XRayMtl::EvalRefraction( ShadeContext& sc, float& outVal )
4624 {
4625 	int id = StdIDToChannel( ID_RR );
4626 	if ( !ShouldEvalSubTexmap( sc, id ) )
4627 		return false;
4628 
4629 	Texmap* refrmap = (*maps)[id].map;
4630 	DbgAssert( refrmap != NULL );
4631 	if ( refrmap->HandleOwnViewPerturb() )
4632 	{
4633 		outVal = refrmap->EvalMono( sc );
4634 	}
4635 	else
4636 	{
4637 		AColor rcol;
4638 		rcol = sc.EvalEnvironMap( refrmap, sc.RefractVector( ioRefract ) );
4639 		outVal = Intens( rcol );
4640 	}
4641 
4642 	return true;
4643 }
4644 
4645 //������������������������������������������������������������������������
4646 // Evaluates Displacement map as a color. Returns false if the result is not
4647 // meaningful
4648 //
EvalDisplacement(ShadeContext & sc,float & outVal)4649 bool XRayMtl::EvalDisplacement( ShadeContext& sc, float& outVal )
4650 {
4651 	int id = StdIDToChannel( ID_DP );
4652 	if ( !ShouldEvalSubTexmap( sc, id ) )
4653 		return false;
4654 
4655 	outVal = (*maps)[id].EvalMono(sc);
4656 	return true;
4657 }
4658 
4659 //������������������������������������������������������������������������
4660 // Helper method
4661 //
ShouldEvalSubTexmap(ShadeContext & sc,int id)4662 bool XRayMtl::ShouldEvalSubTexmap( ShadeContext& sc, int id )
4663 {
4664 	if ( id >= 0 && id < NumSubTexmaps() &&
4665 		sc.doMaps &&	 SubTexmapOn( id ) )
4666 	{
4667 		Texmap* texMap = GetSubTexmap( id );
4668 		if ( texMap != NULL && texMap->IsOutputMeaningful( sc ) )
4669 			return true;
4670 	}
4671 
4672 	return false;
4673 }
4674 
4675 // XRay Part
LoadXRayShaderList()4676 void XRayMtl::LoadXRayShaderList()
4677 {
4678 	XRayMtl::EShaders.clear	();
4679 	XRayMtl::CShaders.clear	();
4680 	XRayMtl::GameMtls.clear ();
4681 	int e_res = LoadBlenderList	(XRayMtl::EShaders);
4682 	int c_res = LoadShaderLCList(XRayMtl::CShaders);
4683 	int g_res = LoadGameMtlList	(XRayMtl::GameMtls);
4684 	if ((e_res==-1)||(c_res==-1)||(g_res==-1))
4685 	{
4686 
4687 		xray_re::msg("Can't load shader files!\nGame material will work incorrectly.");
4688 		THROW;
4689 	}
4690 }
4691 
UnloadXRayShaderList()4692 void XRayMtl::UnloadXRayShaderList()
4693 {
4694 	ClearList(XRayMtl::EShaders);
4695 	ClearList(XRayMtl::CShaders);
4696 	ClearList(XRayMtl::GameMtls);
4697 }
4698 
SetEShaderIndx(long indx)4699 void XRayMtl::SetEShaderIndx( long indx )
4700 {
4701 	pb_xray->SetValue(std2_eshader_type, 0, indx<0 ? 0 : indx );
4702 	eshaderId = indx;
4703 }
SetCShaderIndx(long indx)4704 void XRayMtl::SetCShaderIndx( long indx )
4705 {
4706 	pb_xray->SetValue(std2_cshader_type, 0, indx<0 ? 0 : indx );
4707 	cshaderId = indx;
4708 }
SetGameMtlIndx(long indx)4709 void XRayMtl::SetGameMtlIndx( long indx )
4710 {
4711 	pb_xray->SetValue(std2_gamemtl_type, 0, indx<0 ? 0 : indx );
4712 	gamemtlId = indx;
4713 }
GetEShader(DWORD i)4714 TCHAR*	XRayMtl::GetEShader	(DWORD i)
4715 {
4716 	return (i<EShaders.size())?(TCHAR*)EShaders[i]:0;
4717 }
GetCShader(DWORD i)4718 TCHAR*	XRayMtl::GetCShader	(DWORD i)
4719 {
4720 	return (i<CShaders.size())?(TCHAR*)CShaders[i]:0;
4721 }
GetGameMtl(DWORD i)4722 TCHAR*	XRayMtl::GetGameMtl	(DWORD i)
4723 {
4724 	return (i<GameMtls.size())?(TCHAR*)GameMtls[i]:0;
4725 }
4726 
FindEShader(LPCSTR name)4727 int		XRayMtl::FindEShader(LPCSTR name)
4728 {
4729 	if (!name) return -1;
4730 	for (LPSTR_vec_it it=XRayMtl::EShaders.begin(); it!=XRayMtl::EShaders.end(); it++)
4731 		if (0==strcmp(*it,name)) return it-XRayMtl::EShaders.begin();
4732 	return -1;
4733 }
4734 
FindCShader(LPCSTR name)4735 int		XRayMtl::FindCShader(LPCSTR name)
4736 {
4737 	if (!name) return -1;
4738 	for (LPSTR_vec_it it=XRayMtl::CShaders.begin(); it!=XRayMtl::CShaders.end(); it++)
4739 		if (0==strcmp(*it,name)) return it-XRayMtl::CShaders.begin();
4740 	return -1;
4741 }
4742 
FindGameMtl(LPCSTR name)4743 int		XRayMtl::FindGameMtl(LPCSTR name)
4744 {
4745 	if (!name) return -1;
4746 	for (LPSTR_vec_it it=XRayMtl::GameMtls.begin(); it!=XRayMtl::GameMtls.end(); it++)
4747 		if (0==strcmp(*it,name)) return it-XRayMtl::GameMtls.begin();
4748 	return -1;
4749 }
4750