1 /**********************************************************************
2 *<
3 FILE: BMTEX.CPP
4 
5 DESCRIPTION: BMTEX 2D Texture map.
6 
7 CREATED BY: Dan Silva
8 
9 HISTORY:
10 
11 *>	Copyright (c) 1994, All Rights Reserved.
12 **********************************************************************/
13 
14 #include "bmtex.h"
15 #include "mtlhdr.h"
16 #include "mtlres.h"
17 #include "3dsmaxport.h"
18 #include "notify.h"
19 #include "macrorec.h"
20 
21 extern HINSTANCE hInstance;
22 
23 // Image filtering types
24 #define FILTER_PYR     0
25 #define FILTER_SAT     1
26 #define FILTER_NADA	   2
27 
28 // Alpha source types
29 #define ALPHA_FILE 	0
30 #define ALPHA_RGB	2
31 #define ALPHA_NONE	3
32 
33 // End conditions:
34 #define END_LOOP     0
35 #define END_PINGPONG 1
36 #define END_HOLD     2
37 
38 #define NCOLS 0
39 
40 #define UVGEN_REF 0
41 #define PBLOCK_REF 1
42 #define TEXOUT_REF 2
43 #define PBLOCKTIME_REF 3
44 
45 // Interface ID used to access the particle bitmaps of the Bitmap texture
46 #define IID_BITMAPTEX_PARTICLE_BITMAP_LIST 0x3c34ffff
47 
48 //------------------------------------------------------------------------
49 // Local definitions
50 //------------------------------------------------------------------------
51 
52 namespace {
53 
54 	Class_ID bmTexClassID(BMTEX_CLASS_ID,0);
55 	AColor black(0.0f,0.0f,0.0f,0.0f);
56 
57 
InvalidNameMsg(const TCHAR * name)58 	void InvalidNameMsg(const TCHAR* name) {
59 		if (name==NULL) return;
60 		TCHAR msg[128];
61 		wsprintf(msg,_T("Invalid File Name: %s"), name);
62 		MessageBox(NULL, msg, GetString(IDS_DS_BITMAP_TEXTURE_ERR), MB_TASKMODAL);
63 	}
64 
GetSubjectInfo(BitmapInfo * srcInfo)65 	BitmapInfo* GetSubjectInfo( BitmapInfo* srcInfo ) {
66 		if( srcInfo->GetProxySubject() != NULL )
67 			return srcInfo->GetProxySubject();
68 		else
69 			return srcInfo;
70 	}
71 
72 	// Copy the proxy subject of srcInto into the given subject info, clear proxy request flag on subject info
CopySubjectToSubjectInfo(BitmapInfo & subjectInfo,BitmapInfo & srcInfo)73 	void CopySubjectToSubjectInfo( BitmapInfo& subjectInfo, BitmapInfo& srcInfo ) {
74 		subjectInfo = *GetSubjectInfo( &srcInfo );
75 		subjectInfo.ResetFlags( MAP_PROXYREQUEST ); // Mark as request for non-proxy
76 	}
77 
78 	// Copy the proxy subject of srcInto into the given request info, set proxy request flag on request info
CopySubjectToRequestInfo(BitmapInfo & requestInfo,BitmapInfo & srcInfo)79 	void CopySubjectToRequestInfo( BitmapInfo& requestInfo, BitmapInfo& srcInfo ) {
80 		requestInfo = *GetSubjectInfo( &srcInfo );
81 		requestInfo.SetFlags( MAP_PROXYREQUEST ); // Mark as request for proxy
82 	}
83 
BitmapNonProxy_LoadInto(BitmapInfo & requestInfo,Bitmap ** pBitmap,BOOL forceReload)84 	void BitmapNonProxy_LoadInto( BitmapInfo& requestInfo, Bitmap** pBitmap, BOOL forceReload ) {
85 		requestInfo.ResetFlags( MAP_PROXYREQUEST );
86 		TheManager->LoadInto(&requestInfo, pBitmap, forceReload);
87 	}
88 
BitmapProxy_LoadInto(BitmapInfo & subjectInfo,BitmapInfo & requestInfo,Bitmap ** pBitmap,BOOL forceReload)89 	void BitmapProxy_LoadInto( BitmapInfo& subjectInfo, BitmapInfo& requestInfo, Bitmap** pBitmap, BOOL forceReload ) {
90 		CopySubjectToRequestInfo( requestInfo, subjectInfo ); // Create a request info for the proxy from our subject info
91 		TheManager->LoadInto( &requestInfo, pBitmap, forceReload );
92 		CopySubjectToSubjectInfo( subjectInfo, requestInfo ); // Copy the the updated subject info into our subject info
93 	}
94 
BitmapNonProxy_Load(BitmapInfo & requestInfo,BMMRES * status)95 	Bitmap* BitmapNonProxy_Load( BitmapInfo& requestInfo, BMMRES* status ) {
96 		requestInfo.ResetFlags( MAP_PROXYREQUEST );
97 		Bitmap* retval = TheManager->Load(&requestInfo, status);
98 		return retval;
99 	}
100 
BitmapProxy_Load(BitmapInfo & subjectInfo,BitmapInfo & requestInfo,BMMRES * status)101 	Bitmap* BitmapProxy_Load( BitmapInfo& subjectInfo, BitmapInfo& requestInfo, BMMRES* status ) {
102 		CopySubjectToRequestInfo( requestInfo, subjectInfo ); // Create a request info for the proxy from our subject info
103 		Bitmap* retval = TheManager->Load( &requestInfo, status );
104 		CopySubjectToSubjectInfo( subjectInfo, requestInfo ); // Copy the the updated subject info into our subject info
105 		return retval;
106 	}
107 
BitmapNonProxy_GoTo(BitmapInfo & requestInfo,Bitmap * map)108 	BMMRES BitmapNonProxy_GoTo( BitmapInfo& requestInfo, Bitmap* map ) {
109 		requestInfo.ResetFlags( MAP_PROXYREQUEST );
110 		BMMRES retval = map->GoTo(&requestInfo);
111 		return retval;
112 	}
113 
BitmapProxy_GoTo(BitmapInfo & subjectInfo,BitmapInfo & requestInfo,Bitmap * map)114 	BMMRES BitmapProxy_GoTo( BitmapInfo& subjectInfo, BitmapInfo& requestInfo, Bitmap* map ) {
115 		BitmapInfo backupRequestInfo = requestInfo;
116 		CopySubjectToRequestInfo( requestInfo, subjectInfo ); // Create a request info for the proxy from our subject info
117 		BMMRES retval = map->GoTo( &requestInfo );
118 		CopySubjectToSubjectInfo( subjectInfo, requestInfo ); // Copy the the updated subject info into our subject info
119 
120 		// Restore the original request information if the bitmap doesn't have multiple frames.
121 		// This is necessary to avoid losing proxy information from the requestInfo
122 		if(retval == BMMRES_SINGLEFRAME) {
123 			requestInfo = backupRequestInfo;
124 		}
125 		return retval;
126 	}
127 }
128 
129 //------------------------------------------------------------------------
130 // BMTexPathAccessor -- Methods
131 //------------------------------------------------------------------------
132 
BMTexPathAccessor(BMTex * aTex)133 BMTexPathAccessor::BMTexPathAccessor(BMTex* aTex) : mTex(aTex)	{
134 	DbgAssert(aTex);
135 }
136 
~BMTexPathAccessor()137 BMTexPathAccessor::~BMTexPathAccessor()	{
138 }
139 
GetPath() const140 MaxSDK::Util::Path BMTexPathAccessor::GetPath() const {
141 	return MaxSDK::Util::Path(mTex->GetMapName());
142 }
143 
144 
SetPath(const MaxSDK::Util::Path & aNewPath)145 void BMTexPathAccessor::SetPath(const MaxSDK::Util::Path& aNewPath)	{
146 	mTex->pblock->SetValue(bmtex_filename, 0, const_cast<TCHAR*>(aNewPath.GetCStr()));
147 }
148 
IsInputAsset() const149 bool BMTexPathAccessor::IsInputAsset() const	{
150 	return true;
151 }
152 
GetAssetType() const153 int BMTexPathAccessor::GetAssetType() const	{
154 	return IAssetAccessor::kBitmapAsset;
155 }
156 
GetAssetDesc() const157 const TCHAR* BMTexPathAccessor::GetAssetDesc() const	{
158 	return NULL;
159 }
GetAssetClientDesc() const160 const TCHAR* BMTexPathAccessor::GetAssetClientDesc() const		{
161 	return NULL;
162 }
IsAssetPathWritable() const163 bool BMTexPathAccessor::IsAssetPathWritable() const	{
164 	return true;
165 }
166 
167 
168 TCHAR		BMTex::s_lastName[MAX_PATH];
169 ParamDlg*	BMTex::uvGenDlg;
170 ParamDlg*	BMTex::texoutDlg;
171 BMTexDlg*	BMTex::paramDlg;
172 
173 //------------------------------------------------------------------------
174 // BMSampler -- Methods
175 //------------------------------------------------------------------------
BMSampler()176 BMSampler::BMSampler()
177 : bm(NULL),
178 ufac(0.0f),
179 vfac(0.0f),
180 fbmw(0.0f),
181 fbmh(0.0f)
182 {
183 }
184 
Init(BMTex * bmt,Bitmap * bm)185 void BMSampler::Init(BMTex *bmt, Bitmap *bm) {
186 
187 	if (bm == NULL)
188 		this->bm = bmt->GetActiveBitmap();
189 	else this->bm = bm;
190 
191 	tex = bmt;
192 	alphaSource = bmt->alphaSource;
193 	if (this->bm) {
194 		u0 = tex->clipu;
195 		v0 = tex->clipv;
196 		u1 = tex->clipu + tex->clipw;
197 		v1 = tex->clipv + tex->cliph;
198 		ufac= tex->clipw;
199 		vfac = tex->cliph;
200 		bmw = this->bm->Width();
201 		bmh = this->bm->Height();
202 		fbmw = float(bmw/*-1*/);  // DS 4/23/99
203 		fbmh = float(bmh/*-1*/);  // DS 4/23/99
204 		clipx = int(tex->clipu*fbmw);
205 		clipy = int(tex->clipv*fbmh);
206 		fclipw = tex->clipw*fbmw;
207 		fcliph = tex->cliph*fbmh;
208 		cliph = int(fcliph);
209 		ujit = tex->jitter*(1.0f-ufac);
210 		vjit = tex->jitter*(1.0f-vfac);
211 	}
212 }
213 
214 
Jitter(ShadeContext & sc,float ujit,float vjit,float & ru,float & rv,int iu,int iv)215 static inline void Jitter(ShadeContext &sc, float ujit, float vjit, float &ru, float &rv, int iu, int iv) {
216 	//	srand(((sc.uTile+593)*14693+(sc.vTile+4991)*2517)&0x7fff);
217 	srand(((iu+593)*14693+(iv+967)*29517)&0x7fff);
218 	int urnd = rand()&0x7fff;
219 	rand();	 // these extra calls seem to make the pattern more random
220 	rand();	 // these extra calls seem to make the pattern more random
221 	int vrnd = rand()&0x7fff;
222 	ru = ujit*float(urnd)/float(32767.0f);
223 	rv = vjit*float(vrnd)/float(32767.0f);
224 }
225 
PlaceUV(ShadeContext & sc,float & u,float & v,int iu,int iv)226 int BMSampler::PlaceUV(ShadeContext &sc, float &u, float &v, int iu, int iv) {
227 	/* Avoid division by zero: make sure we don't have zero.*/
228 	if((ufac != 0) && (vfac != 0)) {
229 		if (tex->randPlace) {
230 			float ru,rv;
231 			Jitter(sc,ujit,vjit,ru,rv,iu,iv);
232 			if (u<ru||v<rv||u>ru+ufac||v>rv+vfac)
233 				return 0;
234 			// note jitter ignores u0,v0, effectively setting them to zero
235 			u = (u-ru)/ufac;
236 			v = (v-rv)/vfac;
237 		}
238 		else {
239 			if (u<u0||v<v0||u>u1||v>v1)
240 				return 0;
241 			u = (u-u0)/ufac;
242 			v = (v-v0)/vfac;
243 		}
244 		return 1;
245 	}
246 	else {
247 		return 0;
248 	}
249 }
250 
PlaceUVFilter(ShadeContext & sc,float & u,float & v,int iu,int iv)251 int BMSampler::PlaceUVFilter(ShadeContext &sc, float &u, float &v, int iu, int iv) {
252 
253 	/* Avoid division by zero: make sure we don't have zero.*/
254 	if((ufac != 0) && (vfac != 0)) {
255 		if (tex->randPlace) {
256 			float ru,rv;
257 			Jitter(sc,ujit,vjit,ru,rv,iu,iv);
258 			// note jitter ignores u0,v0, effectively setting them to zero
259 			u = (u-ru)/ufac;
260 			v = (v-rv)/vfac;
261 		}
262 		else {
263 			u = (u-u0)/ufac;
264 			v = (v-v0)/vfac;
265 		}
266 		return 1;
267 	}
268 	else {
269 		return 0;
270 	}
271 }
272 
Sample(ShadeContext & sc,float u,float v)273 AColor BMSampler::Sample(ShadeContext& sc, float u,float v) {
274 	BMM_Color_fl c;
275 	int x,y;
276 	float fu,fv;
277 	fu = frac(u);
278 	fv = 1.0f-frac(v);
279 	if (fu >= 1.0f)
280 		fu = 0.0f;
281 	if (fv >= 1.0f)
282 		fv = 0.0f;
283 	if (tex->applyCrop) {
284 		if (tex->placeImage) {
285 			if (!PlaceUV(sc,fu, fv, int(u), int(v)))
286 				return black;
287 			x = (int)(fu*fbmw);
288 			y = (int)(fv*fbmh);
289 		}
290 		else {
291 			x = mod(clipx + (int)(fu*fclipw),bmw);
292 			y = mod(clipy + (int)(fv*fcliph),bmh);
293 		}
294 	}
295 	else {
296 		x = (int)(fu*fbmw);
297 		y = (int)(fv*fbmh);
298 	}
299 	bm->GetLinearPixels(x,y,1,&c);
300 	switch(alphaSource) {
301 		case ALPHA_NONE:  c.a = 1.0f; break;
302 		case ALPHA_RGB:   c.a = (c.r+c.g+c.b)/3;
303 			if(c.a>1)c.a=1;
304 			else if(c.a<0)c.a=0;
305 			break;
306 			//  TBD
307 			// XPCOL needs to be handled in bitmap for filtering.
308 			// Need to open a bitmap with this property.
309 			//	case ALPHA_XPCOL:  break;
310 	}
311 	return c;
312 }
313 
314 
SampleFilter(ShadeContext & sc,float u,float v,float du,float dv)315 AColor BMSampler::SampleFilter(ShadeContext& sc, float u,float v, float du, float dv) {
316 	BMM_Color_fl c;
317 	float fu,fv;
318 	fu = frac(u);
319 	fv = 1.0f-frac(v);
320 	if (tex->applyCrop) {
321 		if (tex->placeImage) {
322 			if(!PlaceUVFilter(sc,fu, fv, int(u), int(v))) {
323 				return black;
324 			}
325 			du /= ufac;
326 			dv /= vfac;
327 			float du2 = 0.5f*du;
328 			float ua = fu-du2;
329 			float ub = fu+du2;
330 			if (ub<=0.0f||ua>=1.0f) return black;
331 			float dv2 = 0.5f*dv;
332 			float va = fv-dv2;
333 			float vb = fv+du2;
334 			if (vb<=0.0f||va>=1.0f) return black;
335 			BOOL clip = 0;
336 			if (ua<0.0f) { ua=0.0f; clip = 1; }
337 			if (ub>1.0f) { ub=1.0f;	clip = 1; }
338 			if (va<0.0f) { va=0.0f;	clip = 1; }
339 			if (vb>1.0f) { vb=1.0f;	clip = 1; }
340 			bm->GetFiltered(fu,fv,du,dv,&c);
341 			switch(alphaSource) {
342 				case ALPHA_NONE:  c.a = 1.0f; break;
343 				case ALPHA_RGB:   c.a = (c.r+c.g+c.b)/3;
344 					if(c.a>1)c.a=1;
345 					else if(c.a<0)c.a=0;
346 					break;
347 			}
348 			AColor ac(c);
349 			if (clip) {
350 				float f = ((ub-ua)/du) * ((vb-va)/dv);
351 				ac *= f;
352 			}
353 			return ac;
354 		}
355 		else {
356 			fu = (u0 + ufac*fu);
357 			fv = (v0 + vfac*fv);
358 			du *= ufac;
359 			dv *= vfac;
360 			bm->GetFiltered(fu,fv,du,dv,&c);
361 		}
362 	}
363 
364 	else
365 		bm->GetFiltered(fu,fv,du,dv,&c);
366 	switch(alphaSource) {
367 				case ALPHA_NONE:  c.a = 1.0f; break;
368 				case ALPHA_RGB:   c.a = (c.r+c.g+c.b)/3;
369 					if(c.a>1)c.a=1;
370 					else if(c.a<0)c.a=0;
371 					break;
372 	}
373 	return c;
374 }
375 
376 
377 //------------------------------------------------------------------------
378 // BMAlphaSampler -- Methods
379 //------------------------------------------------------------------------
380 
SampleMono(ShadeContext & sc,float u,float v)381 float BMAlphaSampler::SampleMono(ShadeContext& sc, float u,float v) {
382 	BMM_Color_fl c;
383 	int x,y;
384 	float fu,fv;
385 	fu = frac(u);
386 	fv = 1.0f-frac(v);
387 	if (fu >= 1.0f)
388 		fu = 0.0f;
389 	if (fv >= 1.0f)
390 		fv = 0.0f;
391 	if (tex->applyCrop) {
392 		if (tex->placeImage) {
393 			if (!PlaceUV(sc,fu,fv,int(u),int(v))) return 0.0f;
394 			x = (int)(fu*fclipw);
395 			y = (int)(fv*fcliph);
396 		}
397 		else {
398 			x = mod(clipx + (int)(fu*fclipw),bmw);
399 			y = mod(clipy + (int)(fv*fcliph),bmh);
400 		}
401 	}
402 	else {
403 		x = (int)(fu*fbmw);
404 		y = (int)(fv*fbmh);
405 	}
406 	bm->GetLinearPixels(x,y,1,&c);
407 	return( c.a);
408 }
409 
SampleMonoFilter(ShadeContext & sc,float u,float v,float du,float dv)410 float BMAlphaSampler::SampleMonoFilter(ShadeContext& sc, float u,float v, float du, float dv) {
411 	BMM_Color_fl c;
412 	float fu,fv;
413 	fu = frac(u);
414 	fv = 1.0f-frac(v);
415 	if (tex->applyCrop) {
416 		if (tex->placeImage) {
417 			if(!PlaceUVFilter(sc,fu, fv, int(u), int(v))) {
418 				return 0.0f;
419 			}
420 			du /= ufac;
421 			dv /= vfac;
422 			float du2 = 0.5f*du;
423 			float ua = fu-du2;
424 			float ub = fu+du2;
425 			if (ub<=0.0f||ua>=1.0f) return 0.0f;
426 			float dv2 = 0.5f*dv;
427 			float va = fv-dv2;
428 			float vb = fv+du2;
429 			if (vb<=0.0f||va>=1.0f) return 0.0f;
430 			BOOL clip = 0;
431 			if (ua<0.0f) { ua=0.0f; clip = 1; }
432 			if (ub>1.0f) { ub=1.0f;	clip = 1; }
433 			if (va<0.0f) { va=0.0f;	clip = 1; }
434 			if (vb>1.0f) { vb=1.0f;	clip = 1; }
435 			bm->GetFiltered(fu,fv,du,dv,&c);
436 			float alph = c.a;
437 			if (clip) {
438 				float f = ((ub-ua)/du) * ((vb-va)/dv);
439 				alph *= f;
440 			}
441 			return alph;
442 		}
443 		else {
444 			fu = frac(u0 + ufac*fu);
445 			fv = frac(v0 + vfac*fv);
446 			du *= ufac;
447 			dv *= vfac;
448 		}
449 	}
450 	bm->GetFiltered(fu,fv,du,dv,&c);
451 	return( c.a);
452 }
453 
454 //------------------------------------------------------------------------
455 // BMCropper  -- Methods
456 //------------------------------------------------------------------------
457 
458 #ifndef NO_MTLEDITOR_BITMAP_CROPPING
Init(BMTexDlg * txdlg,TimeValue t)459 void BMCropper::Init(BMTexDlg *txdlg, TimeValue t) {
460 	dlg = txdlg;
461 	tex = txdlg->theBMTex;
462 	u0 = tex->GetClipU(t);
463 	v0 = tex->GetClipV(t);
464 	w0 = tex->GetClipW(t);
465 	h0 = tex->GetClipH(t);
466 	mode= tex->placeImage;
467 }
468 
SetValues(float u,float v,float w,float h,BOOL md)469 void BMCropper::SetValues(float u, float v, float w, float h, BOOL md) {
470 	BOOL b = FALSE;
471 	if (u!=tex->clipu) {
472 		tex->SetClipU(dlg->ip->GetTime(), u);
473 		b = TRUE;
474 	}
475 	if (v!=tex->clipv) {
476 		tex->SetClipV(dlg->ip->GetTime(), v);
477 		b = TRUE;
478 	}
479 	if (w!=tex->clipw) {
480 		tex->SetClipW(dlg->ip->GetTime(), w);
481 		b = TRUE;
482 	}
483 	if (h!=tex->cliph) {
484 		tex->SetClipH(dlg->ip->GetTime(), h);
485 		b = TRUE;
486 	}
487 
488 	if (md!=tex->placeImage) {
489 		tex->placeImage= md;
490 		b = TRUE;
491 	}
492 
493 	if(b) {
494 		tex->DiscardTexHandle();
495 		tex->NotifyChanged();
496 		dlg->UpdateMtlDisplay();
497 	}
498 }
499 
OnClose()500 void BMCropper::OnClose(){
501 	dlg->cropping = FALSE;
502 }
503 #endif	// !NO_MTLEDITOR_BITMAP_CROPPING
504 
505 //------------------------------------------------------------------------
506 // BMTexNotify -- Methods
507 //------------------------------------------------------------------------
508 
Changed(ULONG flags)509 int BMTexNotify::Changed(ULONG flags) {
510 	//-- File has been reloaded and it must be reflected as such
511 	if (flags == BMNOTIFY_FLAG_STORAGE_CHANGE) {
512 		tex->NotifyChanged();
513 		tex->DiscardTexHandle();
514 		//-- File has been changed and must be reloaded
515 		// GG: 02/10/02
516 	} else if (flags == BMNOTIFY_FLAG_FILE_CHANGE) {
517 		tex->fnReload();
518 	}
519 	return 1;
520 }
521 
522 //------------------------------------------------------------------------
523 //------------------------------------------------------------------------
524 
525 int numBMTexs = 0;
526 class BMTexClassDesc:public ClassDesc2 {
527 public:
IsPublic()528 	int 			IsPublic() { return 1; }
529 	void *			Create(BOOL loading);
530 	//	{ 	return new BMTex; }
ClassName()531 	const TCHAR *	ClassName() { return GetString(IDS_DS_BITMAP_CDESC); } // mjm - 2.3.99
SuperClassID()532 	SClass_ID		SuperClassID() { return TEXMAP_CLASS_ID; }
ClassID()533 	Class_ID 		ClassID() { return bmTexClassID; }
Category()534 	const TCHAR* 	Category() { return TEXMAP_CAT_2D;  }
535 	// PW: new descriptor data accessors added.  Note that the
536 	//      internal name is hardwired since it must not be localized.
InternalName()537 	const TCHAR*	InternalName() { return _T("bitmapTex"); }	// returns fixed parsable name (scripter-visible name)
HInstance()538 	HINSTANCE		HInstance() { return hInstance; }			// returns owning module handle
539 
540 };
541 
542 static BMTexClassDesc bmTexCD;
543 
bmFilterType(int filt_type)544 static int bmFilterType(int filt_type) {
545 	switch(filt_type) {
546 		case FILTER_PYR: return BMM_FILTER_PYRAMID;
547 		case FILTER_SAT: return BMM_FILTER_SUM;
548 		default: return BMM_FILTER_NONE;
549 	}
550 }
551 
552 
GetBMTexDesc()553 ClassDesc* GetBMTexDesc() { return &bmTexCD;  }
554 
555 class BMTexPBAccessor : public PBAccessor
556 {
557 public:
Set(PB2Value & val,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)558 	void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
559 	{
560 		BMTex* bmt = (BMTex*)owner;
561 		switch (id)
562 		{
563 		case bmtex_bitmap:
564 			{
565 				// 425397
566 				// The code has been removed because "ReloadBitmapAndUpdate" calls the param block to get a pointer to "bmtex_bitmap"
567 				// The documentation is pretty clear about the fact that PBAccessor::Set is called right before the PB is changed.
568 				// The bmtex was reloading using the old data. Because the map was getting deleted, the process was acessing deleted memory
569 				//
570 				// I changed "NotifyRefChanged" to properly handle the change and reload its data.
571 				//if (!bmt->loading) {
572 				//	bmt->ReloadBitmapAndUpdate();
573 				//	// send message so browser/navigator name gets updated
574 				//	bmt->NotifyDependents(FOREVER,PART_ALL,REFMSG_SUBANIM_STRUCTURE_CHANGED);
575 				//	}
576 				break;
577 			}
578 		case bmtex_filename:
579 			{
580 				bmt->SetMapName(val.s);
581 				break;
582 			}
583 		case bmtex_filtering:
584 			//bmt->SetFilterType(val.i);
585 			bmt->filterType = val.i;
586 			bmt->m_theBitmap.SetFilter(bmFilterType(val.i));
587 			break;
588 		case bmtex_clipu: {
589 			float u = val.f;
590 			float w = bmt->GetClipW(t);
591 			if (u+w>1.0f)
592 				bmt->SetClipW(t,1.0f-u);
593 			break;
594 						  }
595 		case bmtex_clipv: {
596 			float v = val.f;
597 			float h = bmt->GetClipH(t);
598 			if (v+h>1.0f)
599 				bmt->SetClipH(t,1.0f-v);
600 			break;
601 						  }
602 		case bmtex_clipw: {
603 			float w = val.f;
604 			float u = bmt->GetClipU(t);
605 			if (u+w>1.0f)
606 				bmt->SetClipU(t,1.0f-w);
607 			break;
608 						  }
609 		case bmtex_cliph: {
610 			float h = val.f;
611 			float v = bmt->GetClipV(t);
612 			if (v+h>1.0f)
613 				bmt->SetClipV(t,1.0f-h);
614 			break;
615 						  }
616 		}
617 	}
Get(PB2Value & v,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t,Interval & valid)618 	void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)    // get into v
619 	{
620 		BMTex* bmt = (BMTex*)owner;
621 		switch (id)
622 		{
623 		case bmtex_filename:
624 			{
625 				v.s = bmt->GetMapName();
626 				break;
627 			}
628 
629 		}
630 	}
631 };
632 
633 static BMTexPBAccessor bmtex_accessor;
634 
635 static ParamBlockDesc2 bmtex_param_blk ( bmtex_params, _T("parameters"),  0, &bmTexCD, P_AUTO_CONSTRUCT + P_AUTO_UI, PBLOCK_REF,
636 	//rollout
637 	IDD_BMTEX, IDS_DS_BITMAP_PARAMS, 0, 0, NULL,
638 	// params
639 
640 	bmtex_clipu,	_T("clipu"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_CLIPU,
641 		p_default,		0.0,
642 		p_range,		0.0, 1.0,
643 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT,  IDC_CLIP_X, IDC_CLIP_XSPIN, 0.001f,
644 		p_accessor,		&bmtex_accessor,
645 		end,
646 	bmtex_clipv,	_T("clipv"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_CLIPV,
647 		p_default,		0.0,
648 		p_range,		0.0, 1.0,
649 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT,  IDC_CLIP_Y, IDC_CLIP_YSPIN, 0.001f,
650 		p_accessor,		&bmtex_accessor,
651 		end,
652 	bmtex_clipw,	_T("clipw"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_CLIPW,
653 		p_default,		0.0,
654 		p_range,		0.0, 1.0,
655 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT,  IDC_CLIP_W, IDC_CLIP_WSPIN, 0.001f,
656 		p_accessor,		&bmtex_accessor,
657 		end,
658 	bmtex_cliph,	_T("cliph"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_CLIPH,
659 		p_default,		0.0,
660 		p_range,		0.0, 1.0,
661 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT,  IDC_CLIP_H, IDC_CLIP_HSPIN, 0.001f,
662 		p_accessor,		&bmtex_accessor,
663 		end,
664 	bmtex_jitter,	_T("jitter"),   TYPE_FLOAT,			P_ANIMATABLE,	IDS_DS_JITTERAMT,
665 		p_default,		0.0,
666 		p_range,		0.0, 1.0,
667 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT,  IDC_JITTER_EDIT, IDC_JITTER_SPIN, 0.01f,
668 		end,
669 	bmtex_usejitter,	_T("useJitter"), TYPE_BOOL,			0,		IDS_PW_USEJITTER,
670 		p_default,		FALSE,
671 		p_ui,			TYPE_SINGLECHEKBOX, IDC_BM_JITTER,
672 		end,
673 	bmtex_apply,	_T("apply"), TYPE_BOOL,			0,		IDS_PW_APPLY,
674 		p_default,		FALSE,
675 		p_ui,			TYPE_SINGLECHEKBOX, IDC_BM_CLIP,
676 		end,
677 	bmtex_crop_place, _T("cropPlace"), TYPE_INT,		0,		IDS_PW_CROPPLACE,
678 		p_default,		0,
679 		p_range,		0,	1,
680 		p_ui,			TYPE_RADIO, 2,  IDC_BM_CROP,IDC_BM_PLACE,
681 		end,
682 
683 	bmtex_filtering, _T("filtering"), TYPE_INT,		0,		IDS_PW_FILTERING,
684 		p_default,		0,
685 		p_range,		0,	2,
686 		p_ui,			TYPE_RADIO, 3, IDC_FILTER_PYR, IDC_FILTER_SAT,IDC_FILTER_NADA,
687 		p_accessor,		&bmtex_accessor,
688 		end,
689 	bmtex_monooutput, _T("monoOutput"), TYPE_INT,		0,		IDS_PW_MONOOUTPUT,
690 		p_default,		0,
691 		p_range,		0,	1,
692 		p_ui,			TYPE_RADIO, 2, IDC_BMTEX_RGBOUT, IDC_BMTEX_ALPHAOUT,
693 		end,
694 	bmtex_rgboutput, _T("rgbOutput"), TYPE_INT,		0,		IDS_PW_RGBOUTPUT,
695 		p_default,		0,
696 		p_range,		0,	1,
697 		p_ui,			TYPE_RADIO, 2, IDC_BMTEX_RGBOUT2, IDC_BMTEX_ALPHAOUT2,
698 		end,
699 	bmtex_alphasource, _T("alphaSource"), TYPE_INT,		0,		IDS_PW_ALPHASOURCE,
700 		p_default,		0,
701 		p_range,		0,	2,
702 		p_ui,			TYPE_RADIO, 3, IDC_ALPHA_FILE, IDC_ALPHA_RGB,IDC_ALPHA_NONE,
703 		end,
704 
705 	bmtex_premultalpha, _T("preMultAlpha"), TYPE_BOOL,		0,		IDS_PW_PREMULT,
706 		p_default,		TRUE,
707 		p_ui,			TYPE_SINGLECHEKBOX, IDC_ALPHA_PREMULT,
708 		end,
709 
710 	bmtex_bitmap, _T("bitmap"),	TYPE_BITMAP, 0, IDS_DS_BITMAP,
711 		p_ui,			TYPE_BITMAPBUTTON, IDC_BMTEX_NAME,
712 		p_accessor,		&bmtex_accessor,
713 		end,
714 
715 	bmtex_coords,		_T("coords"),	TYPE_REFTARG,		P_OWNERS_REF,	IDS_DS_COORDINATES,
716 		p_refno,		UVGEN_REF,
717 		end,
718 	bmtex_output,		_T("output"),	TYPE_REFTARG,		P_OWNERS_REF,	IDS_DS_TEXOUT,
719 		p_refno,		TEXOUT_REF,
720 		end,
721 
722 	bmtex_filename,		_T("fileName"), TYPE_FILENAME,		P_TRANSIENT,	IDS_JW_FILENAME,
723 		p_accessor,		&bmtex_accessor,
724 		end,
725 
726 	end
727 );
728 
729 
730 
731 
732 class BMTexPBTimeAccessor : public PBAccessor
733 {
734 public:
Set(PB2Value & val,ReferenceMaker * owner,ParamID id,int tabIndex,TimeValue t)735 	void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)    // set from v
736 	{
737 		BMTex* bmt = (BMTex*)owner;
738 		switch (id)	{
739 		case bmtex_start:
740 			bmt->startTime = val.i;
741 			break;
742 		case bmtex_playbackrate:
743 			bmt->pbRate= val.f;
744 			break;
745 		case bmtex_endcondition:
746 			bmt->endCond = val.i;
747 			break;
748 		case bmtex_matidtime:
749 			bmt->FreeBitmap();
750 			break;
751 		}
752 	}
753 };
754 
755 static BMTexPBTimeAccessor bmtextime_accessor;
756 
757 // aszabo|Oct.30.01 - 312037 UI for Time rollout should be built.
758 // Fixing incorrect removal of UI dates back to R3
759 #ifdef NO_MTLEDITOR_BITMAP_TIME_ROLLOUT
760 #define TIME_PB_FLAGS P_AUTO_CONSTRUCT
761 #else	// !NO_MTLEDITOR_BITMAP_TIME_ROLLOUT
762 #define TIME_PB_FLAGS P_AUTO_CONSTRUCT + P_AUTO_UI
763 #endif	// !NO_MTLEDITOR_BITMAP_TIME_ROLLOUT
764 
765 static ParamBlockDesc2 bmtex_time_param_blk ( bmtex_time, _T("time parameters"),  0, &bmTexCD, TIME_PB_FLAGS, PBLOCKTIME_REF,
766 
767 #ifndef NO_MTLEDITOR_BITMAP_TIME_ROLLOUT
768     //rollout
769 	IDD_BMTEX_TIME, IDS_DS_TIME_PARAMS, 0, APPENDROLL_CLOSED, NULL,
770 #endif	// !NO_MTLEDITOR_BITMAP_TIME_ROLLOUT
771 
772 	// params
773 	bmtex_start, _T("startTime"), TYPE_TIMEVALUE,			0,	IDS_PW_STARTTIME,
774 		p_default,		0,
775 		p_range,		-1000000,	1000000,
776 		p_ui, 			TYPE_SPINNER, EDITTYPE_INT,  IDC_BMTEX_START, IDC_BMTEX_START_SPIN, 1.0f,
777 		p_accessor,		&bmtextime_accessor,
778 		end,
779 	bmtex_playbackrate, _T("playBackRate"), TYPE_FLOAT,			0,	IDS_PW_PLAYBACK,
780 		p_default,		1.0f,
781 		p_range,		0.0f,	10000.0f,
782 		p_ui, 			TYPE_SPINNER, EDITTYPE_FLOAT,  IDC_BMTEX_RATE, IDC_BMTEX_RATE_SPIN, 1.0f,
783 		p_accessor,		&bmtextime_accessor,
784 		end,
785 	bmtex_endcondition, _T("endCondition"), TYPE_INT,		0,		IDS_PW_ENDCONDITION,
786 		p_default,		0,
787 		p_range,		0,	2,
788 		p_ui,			TYPE_RADIO, 3, IDC_BMTEX_LOOP, IDC_BMTEX_PINGPONG,IDC_BMTEX_HOLD,
789 		p_accessor,		&bmtextime_accessor,
790 		end,
791 
792 	bmtex_matidtime, _T("tieTimeToMatIDs"), TYPE_BOOL,		0,		IDS_PW_MATIDTIME,
793 		p_default,		FALSE,
794 		p_ui,			TYPE_SINGLECHEKBOX, IDC_MATIDTIME_CHECK,
795 		p_accessor,		&bmtextime_accessor,
796 		end,
797 
798 
799 	end
800 	);
801 
802 
803 //Function Publishing descriptor for Mixin interface
804 //*****************************************************
805 static FPInterfaceDesc bitmaptex_interface(
806 	BITMAPTEX_INTERFACE, _T("bitmapTex"), 0, &bmTexCD, FP_MIXIN,
807 	bitmaptex_reload, _T("reload"), 0, TYPE_VOID, 0, 0,
808 	bitmaptex_crop, _T("viewImage"), 0, TYPE_VOID, 0, 0,
809 	end
810 	);
811 
812 
Create(BOOL loading)813 void *	BMTexClassDesc::Create(BOOL loading)
814 {
815 	AddInterface(&bitmaptex_interface);
816 	return new BMTex;
817 }
818 
819 
GetDesc()820 FPInterfaceDesc* BitmapTex::GetDesc()
821 {
822 	return &bitmaptex_interface;
823 }
824 
825 
826 
SetEndCondition(int endcond)827 void BMTex::SetEndCondition(int endcond) {
828 	pblockTime->SetValue( bmtex_endcondition, 0, endcond);
829 	endCond = endcond;
830 	//	ParamID changedParam = pblockTime->LastNotifyParamID();
831 	//	bmtex_time_param_blk.InvalidateUI(changedParam);
832 }
SetStartTime(TimeValue t)833 void BMTex::SetStartTime(TimeValue t) {
834 	pblockTime->SetValue( bmtex_start, 0, t);
835 	startTime = t;
836 	//	ParamID changedParam = pblockTime->LastNotifyParamID();
837 	//	bmtex_time_param_blk.InvalidateUI(changedParam);
838 }
SetPlaybackRate(float r)839 void BMTex::SetPlaybackRate(float r) {
840 	pblockTime->SetValue( bmtex_playbackrate, 0, r);
841 	pbRate = r;
842 	//	ParamID changedParam = pblockTime->LastNotifyParamID();
843 	//	bmtex_time_param_blk.InvalidateUI(changedParam);
844 }
845 
846 
847 //------------------------------------------------------------------------
848 // BMTexDlg -- Methods
849 //------------------------------------------------------------------------
BMTexDlg(HWND hwMtlEdit,IMtlParams * imp,BMTex * m)850 BMTexDlg::BMTexDlg(HWND hwMtlEdit, IMtlParams *imp, BMTex *m)
851 : m_displayBitmap(NULL)
852 {
853 	hwmedit = hwMtlEdit;
854 	ip = imp;
855 	hPanel = NULL;
856 	theBMTex = m;
857 	valid  = FALSE;
858 	isActive  = FALSE;
859 	cropping = FALSE;
860 	curTime = imp->GetTime();
861 
862 	//	hTime = 0;
863 	curTime = 0;
864 }
865 
ReloadDialog()866 void BMTexDlg::ReloadDialog() {
867 	Interval valid;
868 	theBMTex->Update(curTime, valid);
869 	LoadDialog(FALSE);
870 }
871 
Update(TimeValue t)872 void BMTexDlg::Update(TimeValue t) {
873 	Interval valid;
874 	curTime = t;
875 	if (!theBMTex->ivalid.InInterval(t)) {
876 		theBMTex->Update(curTime, valid);
877 #ifndef DESIGN_VER
878 		LoadDialog(FALSE);
879 		InvalidateRect(hPanel,NULL,0);
880 		if (cropping) {
881 			theBMTex->StuffCropValues();
882 		}
883 #endif // !DESIGN_VER
884 	}
885 }
886 
887 
~BMTexDlg()888 BMTexDlg::~BMTexDlg() {
889 	RemoveCropImage();
890 	theBMTex->paramDlg = NULL;
891 	DLSetWindowLongPtr(hPanel, NULL);
892 	hPanel =  NULL;
893 
894 	// This should have been deleted, or else there'll be a memory leak.
895 	DbgAssert(m_displayBitmap == NULL);
896 }
897 
FreeBitmap()898 void BMTex::FreeBitmap() {
899 
900 	m_theBitmap.FreeBitmap();
901 
902 	for(int i = 0; i < m_theBitmapList.length(); ++i) {
903 		BitmapHolder& bitmapHolder = m_theBitmapList[i];
904 		bitmapHolder.FreeBitmap();
905 	}
906 
907 	if (texHandle) {
908 		texHandle->DeleteThis();
909 		texHandle = NULL;
910 	}
911 	loadFailed = FALSE;
912 }
913 
914 
BMNameChanged()915 void BMTexDlg::BMNameChanged() {
916 	theBMTex->FreeBitmap();
917 	theBMTex->NotifyChanged();
918 	StuffBMNameField(hPanel);
919 	theBMTex->loadFailed = FALSE;
920 	BMMRES res = theBMTex->LoadBitmap(ip->GetTime());
921 	if (res==BMMRES_NODRIVER)
922 		InvalidNameMsg(theBMTex->m_bi.Name());
923 	EnableAlphaButtons(TRUE);
924 	UpdateMtlDisplay();
925 }
926 
KeyAtCurTime(int id)927 BOOL BMTexDlg::KeyAtCurTime(int id) { return theBMTex->pblock->KeyFrameAtTime(id,curTime); }
928 
GetBMName(BitmapInfo & bi,TSTR & fname,BOOL full=FALSE)929 void GetBMName(BitmapInfo& bi, TSTR &fname, BOOL full=FALSE) {
930 	TSTR fullName;
931 	if (bi.Name()[0]==0)
932 		fullName = bi.Device();
933 	else
934 		fullName =  bi.Name();
935 	if (full)
936 		fname = fullName;
937 	else
938 		SplitPathFile(fullName,NULL,&fname);
939 }
940 
StuffBMNameField(HWND hwndDlg)941 void BMTexDlg::StuffBMNameField(HWND hwndDlg) {
942 
943 	TSTR fname;
944 	//	GetBMName(theBMTex->bi,fname,TRUE);
945 	//	if (iName) {
946 	//		iName->SetText(fname.data());
947 	//		iName->SetTooltip(TRUE,fname.data());
948 	//		}
949 }
950 
ShowCropImage()951 void BMTexDlg::ShowCropImage() {
952 	if (!theBMTex) return;
953 
954 	// Disable proxy  mode as we don't want to display a proxy image in the viewer.
955 	BMTex::ProxyModeDisableGuard proxyModeDisabler(*theBMTex);
956 
957 	Bitmap *bm = theBMTex->GetActiveBitmap();
958 	if (!bm) {
959 		BMMRES res = theBMTex->LoadBitmap(ip->GetTime());
960 		bm = theBMTex->GetActiveBitmap();
961 		if (!bm) return;
962 	}
963 
964 	// Create a new instance of the bitmap (pointing to the same storage), in order to ensure it's not
965 	// deleted while the bitmap is being displayed, when the non-proxy is flushed as
966 	// proxies are re-enabled. This fixes bug #787907.
967 	if(m_displayBitmap != NULL) {
968 		m_displayBitmap->DeleteThis();
969 		m_displayBitmap = NULL;
970 	}
971 	m_displayBitmap = TheManager->NewBitmap();
972 	if(m_displayBitmap != NULL) {
973 		m_displayBitmap->SetStorage(bm->Storage());
974 		m_displayBitmap->SetNotify(this);
975 		CropCallback* cropCallback = NULL;
976 
977 #ifndef NO_MTLEDITOR_BITMAP_CROPPING
978 		cropper.Init(this,curTime);
979 		cropCallback = &cropper;
980 #endif	// !NO_MTLEDITOR_BITMAP_CROPPING
981 
982 		cropping = TRUE;
983 		// Create an autonomous bitmap to have it deleted automatically when the viewer is closed.
984 		int junk = m_displayBitmap->Display( GetString(IDS_DS_CROP_TITLE),BMM_CN, TRUE, FALSE, cropCallback);
985 	}
986 	else {
987 		DbgAssert(false);
988 	}
989 }
990 
RemoveCropImage()991 void BMTexDlg::RemoveCropImage() {
992 	cropping = FALSE;
993 
994 	// Delete the temporary bitmap that was created for the viewer.
995 	if(m_displayBitmap != NULL) {
996 		// UnDisplay() closes the viewer, but disables the "autonomous" mode on bitmaps, so we still
997 		// need to delete the bitmap, even if it was declared as 'autonomous' when displayed.
998 		// Need to use a copy of the bitmap pointer, since m_displayBitmap is null'ed in VFBClosed().
999 		Bitmap* displayBM = m_displayBitmap;
1000 		displayBM->UnDisplay();
1001 		displayBM->DeleteThis();
1002 		m_displayBitmap = NULL;
1003 	}
1004 }
1005 
Changed(ULONG flags)1006 int BMTexDlg::Changed(ULONG flags) {
1007 
1008 	// Do nothing
1009 
1010 	return 1;
1011 }
1012 
VFBClosed()1013 void BMTexDlg::VFBClosed() {
1014 
1015 	// VFB was closed; the image will be deleted automatically because it was displayed
1016 	// as "autonomous".
1017 	m_displayBitmap = NULL;
1018 }
1019 
1020 static int colID[2] = { IDC_CHECK_COL1, IDC_CHECK_COL2 };
1021 
EnableAlphaButtons(BOOL isNew)1022 void BMTexDlg::EnableAlphaButtons(BOOL isNew) {
1023 	if (hPanel==NULL) return;
1024 	if (theBMTex->m_bi.Flags()&MAP_HAS_ALPHA) {
1025 		EnableWindow(GetDlgItem(hPanel,IDC_ALPHA_FILE), 1);
1026 		EnableWindow(GetDlgItem(hPanel,IDC_ALPHA_PREMULT), 1);
1027 		EnableWindow(GetDlgItem(hPanel,IDC_BMTEX_ALPHAOUT), 1);
1028 		EnableWindow(GetDlgItem(hPanel,IDC_BMTEX_ALPHAOUT2), 1);
1029 		if (isNew) {
1030 			theBMTex->SetAlphaSource(ALPHA_FILE);
1031 		}
1032 	}
1033 	else {
1034 		EnableWindow(GetDlgItem(hPanel,IDC_ALPHA_FILE), 0);
1035 		EnableWindow(GetDlgItem(hPanel,IDC_ALPHA_PREMULT), 0);
1036 		EnableWindow(GetDlgItem(hPanel,IDC_BMTEX_ALPHAOUT), 0);
1037 		EnableWindow(GetDlgItem(hPanel,IDC_BMTEX_ALPHAOUT2), 0);
1038 		if (theBMTex->alphaSource == ALPHA_FILE)
1039 			theBMTex->SetAlphaSource(ALPHA_NONE);
1040 		if (theBMTex->premultAlpha)
1041 			theBMTex->SetPremultAlpha(TRUE);
1042 		if (isNew) {
1043 			if (theBMTex->alphaAsRGB)
1044 				theBMTex->SetAlphaAsRGB(FALSE);
1045 			if (theBMTex->alphaAsMono)
1046 				theBMTex->SetAlphaAsMono(FALSE);
1047 		}
1048 	}
1049 }
1050 
1051 
EnableViewImage()1052 void BMTexDlg::EnableViewImage() {
1053 	EnableWindow(GetDlgItem(hPanel,IDC_BM_CROP_IMAGE),(_tcslen(theBMTex->m_bi.Name())>0)?1:0);
1054 }
1055 
DlgProc(TimeValue t,IParamMap2 * map,HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)1056 INT_PTR BMTexDlg::DlgProc(TimeValue t,IParamMap2 *map,HWND hwndDlg,UINT msg,WPARAM wParam,LPARAM lParam)
1057 {
1058 	int id = LOWORD(wParam);
1059 	int code = HIWORD(wParam);
1060 	switch (msg)    {
1061 	case WM_INITDIALOG:
1062 		{
1063 			hPanel = map->GetHWnd();
1064 			EnableAlphaButtons();
1065 			EnableViewImage();
1066 			return TRUE;
1067 		}
1068 		break;
1069 	case WM_COMMAND:
1070 		switch (id) {
1071 		case IDC_BMTEX_NAME:
1072 			{
1073 				bmtex_param_blk.InvalidateUI(bmtex_bitmap);
1074 
1075 				if(HIWORD(wParam) == BN_CLICKED) {
1076 					// Class ParamMap2UserDlgProc is called _after_ the default processing is complete,
1077 					// meaning that the param block system has already recorded the new name for the bitmap.
1078 					if((map != NULL) && (map->GetParamBlock() != NULL)) {
1079 						ReferenceMaker* pbOwner = map->GetParamBlock()->GetOwner();
1080 						if((pbOwner != NULL) && (pbOwner->ClassID() == bmTexClassID)) {
1081 							BMTex* bmTex = static_cast<BMTex*>(pbOwner);
1082 							bmTex->ShowBitmapProxyPrecacheDialog();
1083 						}
1084 					}
1085 				}
1086 			}
1087 			break;
1088 
1089 		case IDC_ALPHA_FILE:
1090 		case IDC_ALPHA_XPCOL:
1091 		case IDC_ALPHA_RGB:
1092 		case IDC_ALPHA_NONE:
1093 			theBMTex->NotifyChanged();
1094 			theBMTex->DiscardTexHandle();
1095 			UpdateMtlDisplay();
1096 			break;
1097 		case IDC_FILTER_NADA:
1098 		case IDC_FILTER_PYR:
1099 		case IDC_FILTER_SAT:
1100 			theBMTex->NotifyChanged();
1101 			break;
1102 		case IDC_BMTEX_RELOAD:
1103 			theBMTex->ReloadBitmap(true);
1104 			BroadcastNotification(NOTIFY_BITMAP_CHANGED, (void *)theBMTex->m_bi.Name());
1105 			//theBMTex->NotifyChanged();
1106 			UpdateMtlDisplay(); // redraw viewports
1107 			Invalidate();  // incase path of map has changed.
1108 			macroRec->OperandSequence(1, mr_prop, _T("bitmaptex.Reload()"),mr_reftarg, theBMTex);
1109 
1110 			break;
1111 		case IDC_BMTEX_RGBOUT:
1112 		case IDC_BMTEX_ALPHAOUT:
1113 			theBMTex->NotifyChanged();
1114 			break;
1115 		case IDC_BMTEX_RGBOUT2:
1116 		case IDC_BMTEX_ALPHAOUT2:
1117 			theBMTex->NotifyChanged();
1118 			theBMTex->DiscardTexHandle();
1119 			UpdateMtlDisplay();
1120 			break;
1121 		case IDC_ALPHA_PREMULT:
1122 			theBMTex->NotifyChanged();
1123 			theBMTex->DiscardTexHandle();
1124 			UpdateMtlDisplay();
1125 			break;
1126 		case IDC_BM_CLIP:
1127 			//					theBMTex->applyCrop = GetCheckBox(hwndDlg,id);
1128 			theBMTex->NotifyChanged();
1129 			theBMTex->DiscardTexHandle();
1130 			UpdateMtlDisplay();
1131 			break;
1132 		case IDC_BM_CROP_IMAGE:
1133 			ShowCropImage();
1134 			macroRec->OperandSequence(1, mr_prop, _T("bitmaptex.ViewImage()"),mr_reftarg, theBMTex);
1135 
1136 			//					macroRecorder->FunctionCall(_T("$.modifiers[#flex].quality"), 0, 0);
1137 
1138 			break;
1139 		case IDC_BM_CROP:
1140 		case IDC_BM_PLACE:
1141 			//					CheckRadioButton( hwndDlg, IDC_BM_CROP, IDC_BM_PLACE, id);
1142 			//					theBMTex->placeImage = id==IDC_BM_PLACE?1:0;
1143 			theBMTex->NotifyChanged();
1144 			theBMTex->DiscardTexHandle();
1145 			UpdateMtlDisplay();
1146 			if (cropping) theBMTex->StuffCropValues();
1147 			theBMTex->EnableStuff();
1148 			break;
1149 		case IDC_BM_JITTER:
1150 			//					theBMTex->randPlace =  GetCheckBox(hwndDlg,id);
1151 			theBMTex->NotifyChanged();
1152 			UpdateMtlDisplay();
1153 			theBMTex->EnableStuff();
1154 			break;
1155 		}
1156 		break;
1157 
1158 	case WM_PAINT:
1159 		if (!valid) {
1160 			valid = TRUE;
1161 			ReloadDialog();
1162 		}
1163 		break;
1164 
1165 	case CC_SPINNER_CHANGE:
1166 		if (!theHold.Holding()) theHold.Begin();
1167 		//			switch (id) {
1168 		theBMTex->NotifyChanged();
1169 		if (cropping) theBMTex->StuffCropValues();
1170 		//need to make as an accesot
1171 		/*
1172 		case IDC_CLIP_XSPIN: {
1173 		float u = 0.0f;//clipUSpin->GetFVal();
1174 		theBMTex->SetClipU(curTime,u);
1175 		//					clipUSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPU));
1176 		float w = theBMTex->GetClipW(curTime);
1177 		if (u+w>1.0f) {
1178 		w = 1.0f-u;
1179 		theBMTex->SetClipW(curTime,w);
1180 		//						clipWSpin->SetValue(theBMTex->clipw,FALSE);
1181 		//						clipWSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPW));
1182 		}
1183 		theBMTex->NotifyChanged();
1184 		if (cropping) theBMTex->StuffCropValues();
1185 		}
1186 		break;
1187 		case IDC_CLIP_YSPIN: {
1188 		float v = 0.0f;//clipVSpin->GetFVal();
1189 		theBMTex->SetClipV(curTime,v);
1190 		//					clipVSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPV));
1191 		float h = theBMTex->GetClipH(curTime);
1192 		if (v+h>1.0f) {
1193 		h = 1.0f-v;
1194 		theBMTex->SetClipH(curTime,h);
1195 		//						clipHSpin->SetValue(theBMTex->cliph,FALSE);
1196 		//						clipHSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPH));
1197 		}
1198 		theBMTex->NotifyChanged();
1199 		if (cropping) theBMTex->StuffCropValues();
1200 		}
1201 		break;
1202 		case IDC_CLIP_WSPIN: {
1203 		float w = 0.0f;//clipWSpin->GetFVal();
1204 		theBMTex->SetClipW(curTime,w);
1205 		//					clipWSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPW));
1206 		float u = theBMTex->GetClipU(curTime);
1207 		if (u+w>1.0f) {
1208 		u = 1.0f-w;
1209 		theBMTex->SetClipU(curTime,u);
1210 		//						clipUSpin->SetValue(theBMTex->clipu,FALSE);
1211 		//						clipUSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPU));
1212 		}
1213 		theBMTex->NotifyChanged();
1214 		if (cropping) theBMTex->StuffCropValues();
1215 		}
1216 		break;
1217 		case IDC_CLIP_HSPIN: {
1218 		float h = 0.0f;//clipHSpin->GetFVal();
1219 		theBMTex->SetClipH(curTime,h);
1220 		//					clipHSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPH));
1221 		float v = theBMTex->GetClipV(curTime);
1222 		if (v+h>1.0f) {
1223 		v = 1.0f-h;
1224 		theBMTex->SetClipV(curTime,v);
1225 		//						clipVSpin->SetValue(theBMTex->clipv,FALSE);
1226 		//						clipVSpin->SetKeyBrackets(KeyAtCurTime(PB_CLIPV));
1227 		}
1228 		theBMTex->NotifyChanged();
1229 		if (cropping) theBMTex->StuffCropValues();
1230 		}
1231 		break;
1232 		case IDC_JITTER_SPIN:
1233 		//					theBMTex->SetJitter(curTime,jitterSpin->GetFVal());
1234 		//					jitterSpin->SetKeyBrackets(KeyAtCurTime(PB_JITTER));
1235 		theBMTex->NotifyChanged();
1236 		break;
1237 		*/
1238 
1239 		//				}
1240 		break;
1241 	case CC_SPINNER_BUTTONDOWN:
1242 		theHold.Begin();
1243 		break;
1244 	case WM_CUSTEDIT_ENTER:
1245 	case CC_SPINNER_BUTTONUP:
1246 		if (HIWORD(wParam) || msg==WM_CUSTEDIT_ENTER) theHold.Accept(GetString(IDS_DS_PARAMCHG));
1247 		else theHold.Cancel();
1248 		theBMTex->DiscardTexHandle();
1249 		theBMTex->NotifyChanged();
1250 		UpdateMtlDisplay();
1251 		if (cropping) theBMTex->StuffCropValues();
1252 		break;
1253 	case WM_DESTROY:
1254 		RemoveCropImage();
1255 		break;
1256 	}
1257 	return FALSE;
1258 }
1259 
1260 
1261 
LoadDialog(BOOL draw)1262 void BMTexDlg::LoadDialog(BOOL draw) {
1263 	if (theBMTex) {
1264 		Interval valid;
1265 		theBMTex->Update(curTime,valid);
1266 		StuffBMNameField(hPanel);
1267 		CheckRadioButton( hPanel, IDC_ALPHA_FILE, IDC_ALPHA_NONE, IDC_ALPHA_FILE+theBMTex->alphaSource);
1268 		CheckRadioButton( hPanel, IDC_FILTER_PYR, IDC_FILTER_NADA, IDC_FILTER_PYR+theBMTex->filterType);
1269 		CheckRadioButton( hPanel, IDC_BMTEX_RGBOUT, IDC_BMTEX_ALPHAOUT, IDC_BMTEX_RGBOUT+theBMTex->alphaAsMono);
1270 		CheckRadioButton( hPanel, IDC_BMTEX_RGBOUT2, IDC_BMTEX_ALPHAOUT2, IDC_BMTEX_RGBOUT2+theBMTex->alphaAsRGB);
1271 		SetCheckBox( hPanel, IDC_ALPHA_PREMULT, theBMTex->premultAlpha);
1272 		SetCheckBox( hPanel, IDC_BM_CLIP, theBMTex->applyCrop);
1273 		EnableAlphaButtons(FALSE);
1274 	}
1275 }
1276 
ClassID()1277 Class_ID BMTexDlg::ClassID() {
1278 
1279 	return bmTexClassID;
1280 }
1281 
SetThing(ReferenceTarget * m)1282 void BMTexDlg::SetThing(ReferenceTarget *m) {
1283 	assert (m->ClassID()==bmTexClassID);
1284 	assert (m->SuperClassID()==TEXMAP_CLASS_ID);
1285 	RemoveCropImage();
1286 	if (theBMTex) {
1287 		theBMTex->paramDlg = NULL;
1288 	}
1289 	theBMTex = (BMTex *)m;
1290 	if (theBMTex) theBMTex->paramDlg = this;
1291 	LoadDialog(TRUE);
1292 }
1293 
1294 //------------------------------------------------------------------------
1295 // BMTex -- Methods
1296 //------------------------------------------------------------------------
1297 
1298 
1299 
1300 #define BMTEX_VERSION 3
1301 
1302 static ParamBlockDescID pbdesc1[] = {
1303 	{ TYPE_FLOAT, NULL, TRUE,1} 	// blur
1304 };
1305 
1306 static ParamBlockDescID pbdesc2[] = {
1307 	{ TYPE_FLOAT, NULL, TRUE,bmtex_clipu }, // clipu
1308 	{ TYPE_FLOAT, NULL, TRUE,bmtex_clipv }, // clipv
1309 	{ TYPE_FLOAT, NULL, TRUE,bmtex_clipw }, // clipw
1310 	{ TYPE_FLOAT, NULL, TRUE,bmtex_cliph }, // cliph
1311 	{ TYPE_FLOAT, NULL, TRUE,bmtex_jitter } // jitter
1312 };
1313 
1314 static ParamVersionDesc oldVersions[] = {
1315 	ParamVersionDesc(pbdesc1, 1, 0),
1316 	ParamVersionDesc(pbdesc1, 1, 1),
1317 	ParamVersionDesc(pbdesc2, 4, 2),
1318 	ParamVersionDesc(pbdesc2, 5, 3)
1319 };
1320 /*
1321 static ParamVersionDesc oldVersions[] = {
1322 ParamVersionDesc(pbdesc2, 5, 2)
1323 };
1324 */
1325 #define NUMOLDVERSIONS 4
1326 //static ParamVersionDesc curVersion(pbdesc2,5,BMTEX_VERSION);
1327 
1328 //static int name_id[NPARAMS] = { IDS_DS_CLIPU, IDS_DS_CLIPV, IDS_DS_CLIPW, IDS_DS_CLIPH, IDS_DS_JITTERAMT };
1329 
Init()1330 void BMTex::Init() {
1331 	if (uvGen) uvGen->Reset();
1332 	else ReplaceReference( 0, GetNewDefaultUVGen());
1333 	//	ReplaceReference( 1, CreateParameterBlock( pbdesc2, NPARAMS, BMTEX_VERSION) );
1334 	if (texout) texout->Reset();
1335 	else ReplaceReference( 2, GetNewDefaultTextureOutput());
1336 	placeImage = FALSE;
1337 	randPlace = FALSE;
1338 	filterType = FILTER_PYR;
1339 	alphaSource = ALPHA_FILE;
1340 	alphaAsMono = FALSE;
1341 	alphaAsRGB = FALSE;
1342 	premultAlpha = TRUE;
1343 	SetClipU(0,0.0f);
1344 	SetClipV(0,0.0f);
1345 	SetClipW(0,1.0f);
1346 	SetClipH(0,1.0f);
1347 	SetJitter(0,1.0f);
1348 	ivalid.SetEmpty();
1349 	clipValid.SetInfinite();
1350 	mTieTimeToMatID = FALSE; // LAM - 4/21/03
1351 	isNew = FALSE;
1352 	rumax = rvmax = -100000.0f;
1353 	rumin = rvmin = +100000.0f;
1354 }
1355 
Reset()1356 void BMTex::Reset() {
1357 	bmTexCD.Reset(this, TRUE);	// reset all pb2's
1358 	if (!isNew) {
1359 		FreeBitmap();
1360 		NotifyChanged();
1361 		if (paramDlg) paramDlg->UpdateMtlDisplay();
1362 	}
1363 	Init();
1364 }
1365 
NotifyChanged()1366 void BMTex::NotifyChanged() {
1367 	NotifyDependents(FOREVER, PART_ALL, REFMSG_CHANGE);
1368 }
1369 
1370 #ifdef DESIGN_VER
SetGeoReferenceInfo(BitmapInfo & bi,StdUVGen * uvGen)1371 void BMTex::SetGeoReferenceInfo(BitmapInfo & bi, StdUVGen * uvGen)
1372 {
1373 	TheManager->Execute(BMM_RETRIEVE_GEOREF_DATA,
1374 		ULONG_PTR(bi.Name()), ULONG_PTR(&(uvGen->m_geoRefInfo)), 0);
1375 }
1376 #endif
1377 
Notify(NotifyInfo * info)1378 void BMTex::Notify(NotifyInfo* info) {
1379 
1380 	switch(info->intcode) {
1381 		case NOTIFY_BITMAP_CHANGED:
1382 			{
1383 				TCHAR *nm = (TCHAR *)info->callParam;
1384 				if (nm==NULL || !_tcscmp(nm,m_bi.Name())) {
1385 					NotifyChanged();
1386 				}
1387 				if (nm==NULL) {
1388 					fileNotFound = 0;
1389 				}
1390 #ifdef DESIGN_VER
1391 				if (!_tcscmp(_T("TIF Image File"), m_bi.Device()))
1392 					SetGeoReferenceInfo(m_bi, GetUVGen());
1393 #endif
1394 				break;
1395 			}
1396 		case NOTIFY_PROXY_TEMPORARY_DISABLE_START:
1397 			// Keep track of the number of temporary disables that occur
1398 			++m_numTemporaryDisables;
1399 			if(m_numTemporaryDisables == 1) {
1400 				DisableProxyMode(false);
1401 			}
1402 			break;
1403 		case NOTIFY_PROXY_TEMPORARY_DISABLE_END:
1404 			--m_numTemporaryDisables;
1405 			if(m_numTemporaryDisables == 0) {
1406 				EnableProxyMode(!KeepNonProxyInMemoryAfterRendering());
1407 			}
1408 			break;
1409 		default:
1410 			DbgAssert(false);
1411 			break;
1412 	}
1413 }
1414 
BMTexNotify(void * param,NotifyInfo * info)1415 void BMTex::BMTexNotify(void *param, NotifyInfo *info) {
1416 
1417 	BMTex *bmt = (BMTex *) param;
1418 	if(bmt != NULL) {
1419 		bmt->Notify(info);
1420 	}
1421 	else {
1422 		DbgAssert(false);
1423 	}
1424 }
1425 
BMTex()1426 BMTex::BMTex()
1427 : m_bi(m_theBitmap.GetBitmapInfo()),
1428   m_numTemporaryDisables(0),
1429   m_proxiesWereDisabledForRendering(false)
1430 {
1431 	ip = NULL;
1432 	isParm2 = TRUE;
1433 	paramDlg = NULL;
1434 	pblock = NULL;
1435 	pblockTime = NULL;
1436 	uvGen = NULL;
1437 	texout = NULL;
1438 	texHandle = NULL;
1439 	loadFailed = FALSE;
1440 	startTime = 0;
1441 	pbRate = 1.0f;
1442 	endCond = END_LOOP;
1443 	isNew = TRUE;
1444 	applyCrop = FALSE;
1445 	loading = FALSE;
1446 	loadingOld = FALSE;
1447 	clipValid = FOREVER;
1448 	fileNotFound = FALSE;
1449 	bmTexCD.MakeAutoParamBlocks(this);	// make and intialize paramblock2
1450 	Init();
1451 	bmNotify.SetTex(this);
1452 	rollScroll=0;
1453 	bmWasSet = FALSE;
1454 	RegisterNotification(BMTexNotify, this, NOTIFY_BITMAP_CHANGED);
1455 	RegisterNotification(BMTexNotify, this, NOTIFY_PROXY_TEMPORARY_DISABLE_START);
1456 	RegisterNotification(BMTexNotify, this, NOTIFY_PROXY_TEMPORARY_DISABLE_END);
1457 }
1458 
GetActiveBitmap() const1459 Bitmap* BMTex::GetActiveBitmap() const {
1460 
1461 	// We assume that the m_theBitmap is non-null if and only if
1462 	// "tie time to mat ID" is false.
1463 	Bitmap* bitmap = m_theBitmap.GetBitmap();
1464 	if((bitmap == NULL) && !m_theBitmapList.isEmpty()) {
1465 		// Use the last bitmap in the list
1466 		bitmap = m_theBitmapList.last().GetBitmap();
1467 	}
1468 
1469 	return bitmap;
1470 }
1471 
SetClipU(TimeValue t,float f)1472 void BMTex::SetClipU(TimeValue t, float f) {
1473 	clipu  = f;
1474 	pblock->SetValue(bmtex_clipu, t, f);
1475 	bmtex_param_blk.InvalidateUI(bmtex_clipu);
1476 
1477 }
1478 
1479 
SetClipV(TimeValue t,float f)1480 void BMTex::SetClipV(TimeValue t, float f) {
1481 	clipv  = f;
1482 	pblock->SetValue( bmtex_clipv, t, f);
1483 	bmtex_param_blk.InvalidateUI(bmtex_clipv);
1484 }
1485 
SetClipW(TimeValue t,float f)1486 void BMTex::SetClipW(TimeValue t, float f) {
1487 	clipw  = f;
1488 	//	  pblock->SetValue( PB_CLIPW, t, f);
1489 	pblock->SetValue( bmtex_clipw, t, f);
1490 	bmtex_param_blk.InvalidateUI(bmtex_clipw);
1491 }
1492 
SetClipH(TimeValue t,float f)1493 void BMTex::SetClipH(TimeValue t, float f) {
1494 	cliph  = f;
1495 	//	pblock->SetValue( PB_CLIPH, t, f);
1496 	pblock->SetValue( bmtex_cliph, t, f);
1497 	bmtex_param_blk.InvalidateUI(bmtex_cliph);
1498 }
1499 
SetJitter(TimeValue t,float f)1500 void BMTex::SetJitter(TimeValue t, float f) {
1501 	jitter = cliph  = f;
1502 	//	pblock->SetValue( PB_JITTER, t, f);
1503 	pblock->SetValue( bmtex_jitter, t, f);
1504 	bmtex_param_blk.InvalidateUI(bmtex_jitter);
1505 }
1506 
GetBitmap(TimeValue t)1507 Bitmap* BMTex::GetBitmap(TimeValue t) {
1508 
1509 	LoadBitmap(t);
1510 	return GetActiveBitmap();
1511 }
1512 
EnableStuff()1513 void BMTex::EnableStuff() {
1514 	if (pblock) {
1515 		IParamMap2 *map = pblock->GetMap();
1516 		pblock->GetValue( bmtex_crop_place, 0, placeImage, FOREVER );
1517 		pblock->GetValue( bmtex_usejitter, 0, randPlace, FOREVER );
1518 		if (map) {
1519 			map->Enable(bmtex_jitter, placeImage);
1520 			map->Enable(bmtex_usejitter, placeImage);
1521 			map->Enable(bmtex_clipu, !(placeImage&&randPlace));
1522 			map->Enable(bmtex_clipv, !(placeImage&&randPlace));
1523 		}
1524 	}
1525 }
1526 
SetFilterType(int ft)1527 void BMTex::SetFilterType(int ft) {
1528 
1529 	pblock->SetValue( bmtex_filtering, 0, ft);
1530 	bmtex_param_blk.InvalidateUI(bmtex_filtering);
1531 }
1532 
SetAlphaSource(int as)1533 void BMTex::SetAlphaSource(int as) {
1534 	if (as!=alphaSource) {
1535 		alphaSource =as;
1536 
1537 		InitBitmapSamplers();
1538 
1539 		if (alphaSource == ALPHA_FILE) pblock->SetValue( bmtex_alphasource, 0, 0);
1540 		else if (alphaSource == ALPHA_RGB) pblock->SetValue( bmtex_alphasource, 0, 1);
1541 		else if (alphaSource == ALPHA_NONE) pblock->SetValue( bmtex_alphasource, 0, 2);
1542 		bmtex_param_blk.InvalidateUI(bmtex_alphasource);
1543 	}
1544 }
1545 
SetMapName(const TCHAR * name,bool isUIAction)1546 void BMTex::SetMapName(const TCHAR *name, bool isUIAction) {
1547 
1548 	if (name) {
1549 		TCHAR uncname[MAX_PATH];
1550 		if (BMMGetUniversalName(uncname,name))
1551 			m_bi.SetName(uncname);
1552 		else
1553 			m_bi.SetName(name);
1554 
1555 		PBBitmap bt(m_bi);
1556 		pblock->SetValue(bmtex_bitmap, 0, &bt);
1557 		fileNotFound = FALSE;
1558 		if (TestMtlFlag(MTL_TEX_DISPLAY_ENABLED)) {
1559 			if (ip)
1560 				ip->MtlChanged();
1561 		}
1562 
1563 		// Trigger the bitmap proxy pre-caching dialog if the reload occured
1564 		// as the result of a UI command.
1565 		if(isUIAction) {
1566 			ShowBitmapProxyPrecacheDialog();
1567 		}
1568 	}
1569 }
1570 
modt(TimeValue x,TimeValue m)1571 static TimeValue modt(TimeValue x, TimeValue m) {
1572 	TimeValue n = (int)(x/m);
1573 	x -= n*m;
1574 	return (x<0)? x+m : x ;
1575 }
1576 
StuffCropValues()1577 void BMTex::StuffCropValues() {
1578 	pblock->GetValue( bmtex_crop_place, 0, placeImage, FOREVER );
1579 
1580 	m_theBitmap.SetCroppingValues(clipu,clipv,clipw,cliph, placeImage );
1581 }
1582 
CalcFrame(TimeValue t)1583 int BMTex::CalcFrame(TimeValue t) {
1584 	TimeValue tm,dur,td;
1585 	int fstart = m_bi.FirstFrame();
1586 	int fend = m_bi.LastFrame();
1587 	int tpf = GetTicksPerFrame();
1588 	tm = TimeValue(float(t-startTime)*pbRate);
1589 	dur = (fend-fstart+1)*GetTicksPerFrame();
1590 	switch (endCond) {
1591 		case END_HOLD:
1592 			if (tm<=0) return fstart;
1593 			if (tm>=dur) return fend;
1594 			return tm/tpf;
1595 		case END_PINGPONG:
1596 			//if ((tm/dur)&1)
1597 			if ( ((tm>=0) && ((tm/dur)&1)) || ( (tm<0) && !(tm/dur)))
1598 			{
1599 				td = modt(tm,dur);
1600 				return fstart + fend-td/tpf;
1601 			}
1602 			// else fall thrue--
1603 		case END_LOOP:
1604 			td = modt(tm,dur);
1605 			return td/tpf;
1606 	}
1607 	return 0;
1608 }
1609 
LoadBitmap(TimeValue t,bool quiet,bool reload)1610 BMMRES BMTex::LoadBitmap(TimeValue t, bool quiet, bool reload) {
1611 	BOOL silent = FALSE;
1612 	BMMRES status = BMMRES_SUCCESS;
1613 
1614 	if (bmWasSet)
1615 		goto skipall;
1616 
1617 	PBBitmap* bitmapPB = NULL;
1618 	pblock->GetValue( bmtex_bitmap, t,bitmapPB, clipValid );
1619 	if ( ((bitmapPB != NULL) && (_tcscmp(m_bi.Name(), bitmapPB->bi.Name())) )   )
1620 		FreeBitmap();
1621 
1622 	UpdateBIName();   //DS 2/18/99
1623 	if (m_bi.Name()[0]==0) {
1624 		if (m_bi.Device()[0]==0)
1625 			return BMMRES_NODRIVER;
1626 #ifdef DESIGN_VER //KENNY MERGE
1627 		//SS 10/3/2000: In the Kenny source, this line was indented an additional
1628 		// level, as if the intention was to include it within the outer if
1629 		// statement. Since that wasn't the case, I have adjusted indentation.
1630 		// However, if you find a bug here, it could be that this should only be
1631 		// called if bi.Name()[0]==0.
1632 		// Additionally, I don't know if this is a general fix or is specific to
1633 		// VIZ; there were no previous comments.
1634 
1635 		// [d.levesque | 10feb2002] I have include this line of code in the if block,
1636 		// as suggested by Stew's comment. This fixes:
1637 		//   313220 - GAMMA STATE OF IMAGE REVERTS TO USE SYSTEM GAMMA, DOES NOT REMEMBER STATE SET.
1638 		m_bi.ResetCustomFlag(BMM_CUSTOM_FILEGAMMA);
1639 #endif
1640 	}
1641 
1642 	BOOL tieTimeToMatID;
1643 	pblockTime->GetValue( bmtex_matidtime, 0, tieTimeToMatID,FOREVER);
1644 
1645 	if (GetActiveBitmap()==NULL)
1646 	{
1647 		if (!tieTimeToMatID)
1648 		{
1649 			// Load bitmap
1650 			int bitmapFrame = CalcFrame(t);
1651 			m_bi.SetCurrentFrame(bitmapFrame);
1652 			if(!m_theBitmap.LoadBitmap(status, quiet)) {
1653 				fileNotFound = TRUE;
1654 				return status;
1655 			}
1656 			if (bitmapPB) {
1657 				bitmapPB->bi = m_bi;	  //DS 3/29/99: in case name has changed ( or flags)
1658 			}
1659 			fileNotFound = FALSE;
1660 			m_theBitmap.SetNotify(&bmNotify);
1661 			m_theBitmap.SetFilter(bmFilterType(filterType));
1662 			// fixup for imported files
1663 #ifdef RENDER_VER
1664 			{
1665 				// Automatically set the alpha settings depending on whether
1666 				// the file has an alpha channel or not. .PSD files have
1667 				// alpha channels, but we are supposed to ignore them.
1668 				LPCTSTR d = m_bi.Name();
1669 				size_t len = _tcslen(d);
1670 				if (len > 4)
1671 					d += len - 4;
1672 				if ((m_bi.Flags() & MAP_HAS_ALPHA) && _tcsicmp(d, ".psd") != 0) {
1673 					SetAlphaAsMono(true);
1674 					SetAlphaSource(ALPHA_FILE);
1675 				}
1676 				else {
1677 					SetAlphaAsMono(false);
1678 					SetAlphaSource(ALPHA_NONE);
1679 				}
1680 			}
1681 #endif
1682 
1683 		}
1684 
1685 		else
1686 		{
1687 			for (int ct = 0; ct < mysampList.Count(); ct++)
1688 			{
1689 				delete mysampList[ct];
1690 				delete alphasampList[ct];
1691 			}
1692 
1693 			int numberFrames = m_bi.NumberFrames();
1694 			m_theBitmapList.setLengthUsed(numberFrames);
1695 			mysampList.SetCount(numberFrames);
1696 			alphasampList.SetCount(numberFrames);
1697 			for (int ct = 0; ct < numberFrames; ct++)
1698 			{
1699 				mysampList[ct] = new BMSampler();
1700 				alphasampList[ct] = new BMAlphaSampler();
1701 			}
1702 
1703 			int firstFrame = m_bi.FirstFrame();
1704 			int lastFrame = m_bi.LastFrame();
1705 
1706 
1707 			for (int frameIndex = m_bi.FirstFrame(), ct=0; frameIndex <= m_bi.LastFrame(); frameIndex++)
1708 			{
1709 				if (frameIndex >= numberFrames) { // extend the arrays
1710 					BitmapHolder nullBitmap;
1711 					BMSampler* bmSampler = NULL;
1712 					BMAlphaSampler* bmAlphaSampler = NULL;
1713 					for(int j=numberFrames; j<=frameIndex; j++) {
1714 						m_theBitmapList.append(nullBitmap);
1715 						bmSampler = new BMSampler();
1716 						mysampList.Append(1, &bmSampler);
1717 						bmAlphaSampler = new BMAlphaSampler();
1718 						alphasampList.Append(1, &bmAlphaSampler);
1719 					}
1720 					numberFrames = frameIndex+1;
1721 				}
1722 
1723 				// Load bitmap, with proxy support
1724 				BitmapHolder& currentBitmap = m_theBitmapList[ct];
1725 				// Copy the main bitmap info as it's where our bitmap info lies.
1726 				currentBitmap.GetBitmapInfo() = m_bi;
1727 				currentBitmap.GetBitmapInfo().SetCurrentFrame(frameIndex);
1728 				if(!currentBitmap.LoadBitmap(status, quiet)) {
1729 					fileNotFound = TRUE;
1730 					return status;
1731 				}
1732 				if (bitmapPB) {
1733 					bitmapPB->bi = m_bi;	  //DS 3/29/99: in case name has changed ( or flags)
1734 				}
1735 				fileNotFound = FALSE;
1736 				m_theBitmap.SetNotify(&bmNotify);
1737 				m_theBitmap.SetFilter(bmFilterType(filterType));
1738 
1739 				m_theBitmapList[ct].SetNotify(&bmNotify);
1740 				m_theBitmapList[ct].SetFilter(bmFilterType(filterType));
1741 
1742 				ct++;
1743 
1744 			}
1745 			// fixup for imported files
1746 			if (!(m_bi.Flags()&MAP_HAS_ALPHA)&&alphaSource==ALPHA_FILE) {
1747 				if (paramDlg)
1748 					paramDlg->EnableAlphaButtons(FALSE);
1749 				else
1750 					SetAlphaSource(ALPHA_NONE);
1751 			}
1752 			if (!(m_bi.Flags()&MAP_HAS_ALPHA))
1753 				SetPremultAlpha(TRUE);   // DS 6/9/00
1754 			if (paramDlg != NULL) {
1755 				paramDlg->EnableAlphaButtons(!reload);
1756 				paramDlg->EnableViewImage();
1757 			}
1758 		}
1759 	}
1760 
1761 	if (!tieTimeToMatID) {
1762 		m_bi.SetCurrentFrame(CalcFrame(t));
1763 
1764 		// [dl | 11june2003] Commit the bitmap info to the param block, in case the frame changed
1765 		if(bitmapPB != NULL) {
1766 			bitmapPB->bi = m_bi;
1767 		}
1768 
1769 		// Update, with proxy support
1770 		status = m_theBitmap.GotoFrame(true);
1771 	}
1772 
1773 #ifdef DESIGN_VER
1774 	if (!_tcscmp(_T("TIF Image File"), m_bi.Device()))
1775 		SetGeoReferenceInfo(m_bi, GetUVGen());
1776 #endif
1777 	//		}
1778 
1779 skipall:
1780 
1781 	InitBitmapSamplers();
1782 
1783 	return status;
1784 }
1785 
RenderBegin(TimeValue t,ULONG flags)1786 int BMTex::RenderBegin(TimeValue t, ULONG flags) {
1787 
1788 	// Disable proxy for rendering, if necessary
1789 
1790 	DbgAssert(!m_proxiesWereDisabledForRendering);
1791 
1792 	// Don't disable the proxies if they are already temporarily disabled
1793 	if(m_numTemporaryDisables == 0) {
1794 		bool isMEdit = ((flags & RENDERBEGIN_IN_MEDIT) != 0);
1795 		bool disableProxyMode = ShouldDisableProxiesForRendering(isMEdit);
1796 		if(disableProxyMode) {
1797 			DisableProxyMode(false);
1798 			m_proxiesWereDisabledForRendering = true;
1799 		}
1800 	}
1801 
1802 	return 1;
1803 }
1804 
RenderEnd(TimeValue t)1805 int BMTex::RenderEnd(TimeValue t) {
1806 
1807 	// Re-enable proxies when done rendering, if they were disabled previously.
1808 
1809 	if(m_proxiesWereDisabledForRendering) {
1810 		m_proxiesWereDisabledForRendering = false;
1811 		bool flushNonProxy = !KeepNonProxyInMemoryAfterRendering();
1812 		EnableProxyMode(flushNonProxy);
1813 	}
1814 
1815 	return 1;
1816 }
1817 
LoadMapFiles(TimeValue t)1818 int BMTex::LoadMapFiles(TimeValue t) {
1819 	LoadBitmap(t,1,1);
1820 	return 1;
1821 }
1822 
RenderBitmap(TimeValue t,Bitmap * bm,float scale3D,BOOL filter)1823 void BMTex::RenderBitmap(TimeValue t, Bitmap *bm, float scale3D, BOOL filter) {
1824 
1825 	// Disable proxy only when 'filter' is specified, as we assume that 'filter'
1826 	// is equivalent to 'high quality'.
1827 	BMTex::ProxyModeDisableGuard proxyModeDisabler(*this, (filter != 0));
1828 
1829 	LoadBitmap(t);
1830 	Bitmap* thebm = GetActiveBitmap();
1831 	if (thebm)
1832 		bm->CopyImage(thebm, filter?COPY_IMAGE_RESIZE_HI_QUALITY:COPY_IMAGE_RESIZE_LO_QUALITY, 0);
1833 }
1834 
ClassID()1835 Class_ID BMTex::ClassID() {
1836 
1837 	return bmTexClassID;
1838 }
1839 
SuperClassID()1840 SClass_ID BMTex::SuperClassID() {
1841 
1842 	return TEXMAP_CLASS_ID;
1843 }
1844 
GetClassName(TSTR & s)1845 void BMTex::GetClassName(TSTR& s) {
1846 
1847 	s= GetString(IDS_DS_BITMAP);
1848 }
1849 
DeleteThis()1850 void BMTex::DeleteThis() {
1851 
1852 	delete this;
1853 }
1854 
ReloadBitmap(bool isUIAction)1855 void BMTex::ReloadBitmap(bool isUIAction) {
1856 	if(GetActiveBitmap() != NULL) {
1857 		loadFailed = FALSE;
1858 		FreeBitmap();
1859 		LoadBitmap(GetCOREInterface()->GetTime(), TRUE, TRUE);
1860 
1861 		// Re-load the bitmap in-place, forcing a reload.
1862 		m_theBitmap.LoadInto(true);
1863 	}
1864 	else {
1865 		loadFailed = FALSE;
1866 		TimeValue t;
1867 		t = GetCOREInterface()->GetTime();
1868 		LoadBitmap(t);
1869 	}
1870 
1871 	//DS:  10/19/99: update path name on button in case it has changed ( fix for #196020)
1872 	IParamMap2* pmap = pblock->GetMap();
1873 	if (pmap != NULL)
1874 		pmap->SetText(bmtex_bitmap, (char *)m_bi.Name());
1875 
1876 
1877 	if (paramDlg)
1878 		paramDlg->EnableAlphaButtons(FALSE);
1879 
1880 	// Trigger the bitmap proxy pre-caching dialog if the reload occured
1881 	// as the result pressing the "reload" button in the UI.
1882 	if(isUIAction) {
1883 		ShowBitmapProxyPrecacheDialog();
1884 	}
1885 }
1886 
EnumAuxFiles(NameEnumCallback & nameEnum,DWORD flags)1887 void BMTex::EnumAuxFiles(NameEnumCallback& nameEnum, DWORD flags) {
1888 
1889 	if ((flags&FILE_ENUM_CHECK_AWORK1)&&TestAFlag(A_WORK1)) return; // LAM - 4/21/03
1890 
1891 	UpdateBIName(); //k2tong|May.17.2006|update the m_bi before an enum to report the most up to date info.
1892 
1893 	if(flags&FILE_ENUM_ACCESSOR_INTERFACE)	{
1894 		int idx = TheManager->ioList.ResolveDevice(&m_bi);
1895 
1896 		IEnumAuxAssetsCallback* callback = static_cast<IEnumAuxAssetsCallback*>(&nameEnum);
1897 		if(idx >= 0 && TheManager->ioList[idx].TestCapabilities(BMMIO_IFL))	{
1898 			// handle IFL case
1899 			DeclareBitmapAsset(*callback, BMTexPathAccessor(this), &m_bi, BMM_ASSET_PROXY | BMM_ASSET_GROUP);
1900 			m_bi.EnumAuxFiles(nameEnum, flags);
1901 			callback->EndGroup();
1902 		}
1903 		else	{
1904 			// normal bitmap or unsupported type
1905 			DeclareBitmapAsset(*callback, BMTexPathAccessor(this), &m_bi, BMM_ASSET_PROXY);
1906 		}
1907 	}
1908 	else	{
1909 		m_bi.EnumAuxFiles(nameEnum,flags);
1910 	}
1911 
1912 	BitmapTex::EnumAuxFiles(nameEnum,flags); // LAM - 4/21/03
1913 }
1914 
1915 
DiscardTexHandle()1916 void BMTex::DiscardTexHandle() {
1917 	if (texHandle) {
1918 		texHandle->DeleteThis();
1919 		texHandle = NULL;
1920 	}
1921 }
1922 
ActivateTexDisplay(BOOL onoff)1923 void BMTex::ActivateTexDisplay(BOOL onoff) {
1924 	if (!onoff)
1925 		DiscardTexHandle();
1926 }
1927 
1928 static BMM_Color_64 black64(0,0,0,0);
1929 
GetVPDisplayDIB(TimeValue t,TexHandleMaker & thmaker,Interval & valid,BOOL mono,BOOL forceW,BOOL forceH)1930 BITMAPINFO* BMTex::GetVPDisplayDIB(TimeValue t, TexHandleMaker& thmaker, Interval &valid, BOOL mono, BOOL forceW, BOOL forceH) {
1931 	LoadBitmap(t);
1932 	valid = clipValid;
1933 	if (m_bi.FirstFrame()!=m_bi.LastFrame())
1934 	{
1935 		// bug :424747
1936 		//the image has multiple frames, the vlidity should be only for the current frame
1937 		// For cases where the sequence has very few frames, it should be valid for more than just the current "t".
1938 		// We have no real
1939 		valid.SetInstant(t);
1940 		//Without this fix, the viewport does not update with the correct image frame.
1941 		// When GetVPDisplayDIB gets called, some callers look at the validity, others look at the current image frame.
1942 		// When looking at the validity, the viewport was not getting updates.
1943 
1944 	}
1945 
1946 	Bitmap* thebm = GetActiveBitmap();
1947 	if (thebm==NULL) {
1948 		return NULL;
1949 	}
1950 	BITMAPINFO *bmi = NULL;
1951 	int xflags = premultAlpha?0:EX_MULT_ALPHA;
1952 	if (applyCrop) {
1953 		int w = thebm->Width();
1954 		int h = thebm->Height();
1955 		Bitmap *newBM;
1956 		BitmapInfo bif;
1957 		bif.SetName(_T("y8798734"));
1958 		bif.SetType(BMM_TRUE_32);
1959 		bif.SetFlags(MAP_HAS_ALPHA);
1960 		if (placeImage) {
1961 			int x0,y0,nw,nh;
1962 			int bmw = thmaker.Size();
1963 			int bmh = int(float(bmw)*float(h)/float(w));
1964 			bif.SetWidth(bmw);
1965 			bif.SetHeight(bmh);
1966 			newBM = TheManager->Create(&bif);
1967 			newBM->Fill(0,0,0,0);
1968 			nw = int(float(bmw)*clipw);
1969 			nh = int(float(bmh)*cliph);
1970 			x0 = int(float(bmw-1)*clipu);
1971 			y0 = int(float(bmh-1)*clipv);
1972 
1973 			if (nw<1) nw = 1;
1974 			if (nh<1) nh = 1;
1975 			PixelBuf row(nw);
1976 
1977 			Bitmap *tmpBM;
1978 			BitmapInfo bif2;
1979 			bif2.SetName(_T("xxxx67878"));
1980 			bif2.SetType(BMM_TRUE_32);
1981 			bif2.SetFlags(MAP_HAS_ALPHA);
1982 			bif2.SetWidth(nw);
1983 			bif2.SetHeight(nh);
1984 			tmpBM = TheManager->Create(&bif2);
1985 			tmpBM->CopyImage(thebm, COPY_IMAGE_RESIZE_LO_QUALITY, 0);
1986 			BMM_Color_64*  p1 = row.Ptr();
1987 			for (int y = 0; y<nh; y++) {
1988 				tmpBM->GetLinearPixels(0,y, nw, p1);
1989 				if ((mono&&alphaAsMono)||(alphaAsRGB)) {
1990 					for (int ix =0; ix<nw; ix++)
1991 						p1[ix].r = p1[ix].g = p1[ix].b = p1[ix].a;
1992 				}
1993 				//if (alphaSource==ALPHA_NONE||premultAlpha) {
1994 				if (alphaSource==ALPHA_NONE) {
1995 					for (int ix =0; ix<nw; ix++)
1996 						p1[ix].a = 0xffff;
1997 				}
1998 				else if (alphaSource==ALPHA_RGB) {
1999 					for (int ix =0; ix<nw; ix++)
2000 						p1[ix].a = (p1[ix].r+p1[ix].g+p1[ix].b)/3;;
2001 				}
2002 				newBM->PutPixels(x0,y+y0, nw, p1);
2003 			}
2004 			tmpBM->DeleteThis();
2005 			//			texHandle = thmaker.CreateHandle(newBM,uvGen->SymFlags(), xflags);
2006 			bmi = thmaker.BitmapToDIB(newBM,uvGen->SymFlags(), xflags, forceW, forceH);
2007 			newBM->DeleteThis();
2008 		}
2009 		else {
2010 			int x0,y0,nw,nh;
2011 			nw = int(float(w)*clipw);
2012 			nh = int(float(h)*cliph);
2013 			x0 = int(float(w-1)*clipu);
2014 			y0 = int(float(h-1)*clipv);
2015 			if (nw<1) nw = 1;
2016 			if (nh<1) nh = 1;
2017 			bif.SetWidth(nw);
2018 			bif.SetHeight(nh);
2019 			PixelBuf row(nw);
2020 			newBM = TheManager->Create(&bif);
2021 			BMM_Color_64*  p1 = row.Ptr();
2022 			for (int y = 0; y<nh; y++) {
2023 				thebm->GetLinearPixels(x0,y+y0, nw, p1);
2024 				if ((mono&&alphaAsMono)||(alphaAsRGB)) {
2025 					for (int ix =0; ix<nw; ix++)
2026 						p1[ix].r = p1[ix].g = p1[ix].b = p1[ix].a;
2027 				}
2028 				//					if (alphaSource==ALPHA_NONE||premultAlpha) {
2029 				if (alphaSource==ALPHA_NONE) {
2030 					for (int ix =0; ix<nw; ix++)
2031 						p1[ix].a = 0xffff;
2032 				}
2033 				else if (alphaSource==ALPHA_RGB) {
2034 					for (int ix =0; ix<nw; ix++)
2035 						p1[ix].a = (p1[ix].r+p1[ix].g+p1[ix].b)/3;;
2036 				}
2037 				newBM->PutPixels(0,y, nw, p1);
2038 			}
2039 			//			texHandle = thmaker.CreateHandle(newBM,uvGen->SymFlags(), xflags);
2040 			bmi = thmaker.BitmapToDIB(newBM,uvGen->SymFlags(), xflags, forceW, forceH);
2041 			newBM->DeleteThis();
2042 		}
2043 	}
2044 	else {
2045 		if (mono&&alphaAsMono) xflags |= EX_RGB_FROM_ALPHA;
2046 		if (alphaAsRGB) xflags |= EX_RGB_FROM_ALPHA;
2047 		if (alphaSource==ALPHA_NONE) xflags |= EX_OPAQUE_ALPHA;
2048 		if (alphaSource==ALPHA_RGB) xflags |= EX_ALPHA_FROM_RGB;
2049 		//		texHandle = thmaker.CreateHandle(thebm,uvGen->SymFlags(), xflags);
2050 		bmi = thmaker.BitmapToDIB(thebm,uvGen->SymFlags(), xflags, forceW, forceH);
2051 	}
2052 	return bmi;
2053 }
2054 
GetActiveTexHandle(TimeValue t,TexHandleMaker & thmaker)2055 DWORD_PTR BMTex::GetActiveTexHandle(TimeValue t, TexHandleMaker& thmaker) {
2056 	if (texHandle&&texTime==CalcFrame(t)&&texValid.InInterval(t))
2057 		return texHandle->GetHandle();
2058 	else {
2059 		DiscardTexHandle();
2060 		texTime = CalcFrame(t);
2061 		texHandle = thmaker.MakeHandle(GetVPDisplayDIB(t,thmaker,texValid));
2062 		return texHandle->GetHandle();
2063 	}
2064 }
2065 
IsHighDynamicRange() const2066 int BMTex::IsHighDynamicRange( ) const
2067 {
2068 	Bitmap* thebm = GetActiveBitmap();
2069 	return thebm == NULL ? false : thebm->IsHighDynamicRange();
2070 }
2071 
2072 //-----------------------------------------------------------
2073 
EvalColor(ShadeContext & sc)2074 AColor BMTex::EvalColor(ShadeContext& sc) {
2075 	if (!sc.doMaps) return black;
2076 	AColor c;
2077 	if (sc.GetCache(this,c))
2078 		return c;
2079 	IPoint3 sp = sc.ScreenCoord();
2080 	if (gbufID) sc.SetGBufferID(gbufID);
2081 	if (GetActiveBitmap()==NULL)
2082 		return black;
2083 
2084 
2085 
2086 	if (!mTieTimeToMatID)
2087 	{
2088 		if (alphaAsRGB)	{
2089 			float a = texout->Filter(uvGen->EvalUVMapMono(sc,&alphasamp,filterType!=FILTER_NADA));
2090 			c = AColor(a,a,a,a);
2091 		}
2092 		else {
2093 			c = texout->Filter(uvGen->EvalUVMap(sc,&mysamp,filterType!=FILTER_NADA));
2094 			if (!premultAlpha) c= AColor(c.r*c.a, c.g*c.a, c.b*c.a, c.a);
2095 		}
2096 	}
2097 	else
2098 	{
2099 		int whichFrame = ComputeParticleFrame(sc);
2100 		if (alphaAsRGB)	{
2101 			float a = texout->Filter(uvGen->EvalUVMapMono(sc,alphasampList[whichFrame],filterType!=FILTER_NADA));
2102 			c = AColor(a,a,a,a);
2103 		}
2104 		else {
2105 			c = texout->Filter(uvGen->EvalUVMap(sc,mysampList[whichFrame],filterType!=FILTER_NADA));
2106 			if (!premultAlpha) c= AColor(c.r*c.a, c.g*c.a, c.b*c.a, c.a);
2107 		}
2108 	}
2109 	sc.PutCache(this,c);
2110 	return c;
2111 }
2112 
EvalMono(ShadeContext & sc)2113 float BMTex::EvalMono(ShadeContext& sc) {
2114 	if (!sc.doMaps||GetActiveBitmap()==NULL)
2115 		return 0.0f;
2116 	float f;
2117 	if (sc.GetCache(this,f))
2118 		return f;
2119 	if (gbufID) sc.SetGBufferID(gbufID);
2120 
2121 	if (!mTieTimeToMatID)
2122 	{
2123 
2124 		if (alphaAsMono)
2125 			f = texout->Filter(uvGen->EvalUVMapMono(sc,&alphasamp,filterType!=FILTER_NADA));
2126 		else
2127 			f = texout->Filter(uvGen->EvalUVMapMono(sc,&mysamp,filterType!=FILTER_NADA));
2128 	}
2129 	else
2130 	{
2131 		int whichFrame = ComputeParticleFrame(sc);
2132 
2133 		if (alphaAsMono)
2134 			f = texout->Filter(uvGen->EvalUVMapMono(sc,alphasampList[whichFrame],filterType!=FILTER_NADA));
2135 		else
2136 			f = texout->Filter(uvGen->EvalUVMapMono(sc,mysampList[whichFrame],filterType!=FILTER_NADA));
2137 
2138 	}
2139 	sc.PutCache(this,f);
2140 	return f;
2141 }
2142 
EvalNormalPerturb(ShadeContext & sc)2143 Point3 BMTex::EvalNormalPerturb(ShadeContext& sc) {
2144 	Point3 dPdu, dPdv;
2145 	Point2 dM;
2146 	if (!sc.doMaps) return Point3(0,0,0);
2147 	if (gbufID) sc.SetGBufferID(gbufID);
2148 	if (GetActiveBitmap()==NULL)
2149 		return Point3(0,0,0);
2150 	if (!mTieTimeToMatID)
2151 	{
2152 		uvGen->GetBumpDP(sc,dPdu,dPdv);  // get bump basis vectors
2153 		if (alphaAsMono)
2154 			dM =(.01f)*uvGen->EvalDeriv(sc,&alphasamp,filterType!=FILTER_NADA);
2155 		else
2156 			dM =(.01f)*uvGen->EvalDeriv(sc,&mysamp,filterType!=FILTER_NADA);
2157 	}
2158 	else
2159 	{
2160 		int whichFrame = ComputeParticleFrame(sc);
2161 
2162 		if (alphaAsMono)
2163 			dM =(.01f)*uvGen->EvalDeriv(sc,alphasampList[whichFrame],filterType!=FILTER_NADA);
2164 		else
2165 			dM =(.01f)*uvGen->EvalDeriv(sc,mysampList[whichFrame],filterType!=FILTER_NADA);
2166 	}
2167 
2168 #if 0
2169 	// Blinn's algorithm
2170 	Point3 N = sc.Normal();
2171 	Point3 uVec = CrossProd(N,dPdv);
2172 	Point3 vVec = CrossProd(N,dPdu);
2173 	return texout->Filter(-dM.x*uVec+dM.y*vVec);
2174 #else
2175 	return texout->Filter(dM.x*dPdu+dM.y*dPdv);
2176 #endif
2177 }
2178 
Clone(RemapDir & remap)2179 RefTargetHandle BMTex::Clone(RemapDir &remap) {
2180 	// AF Don't log a restore object during this create
2181 	// the Undo of a new inside a clone is the deletion of the new object.
2182 	// No need to undo back to uninitialized values
2183 	theHold.Suspend();
2184 	BMTex *mnew = new BMTex();
2185 	theHold.Resume();
2186 
2187 	*((MtlBase*)mnew) = *((MtlBase*)this);  // copy superclass stuff
2188 	mnew->ReplaceReference(0,remap.CloneRef(uvGen));
2189 	mnew->ReplaceReference(1,remap.CloneRef(pblock));
2190 	mnew->ReplaceReference(2,remap.CloneRef(texout));
2191 	mnew->ReplaceReference(3,remap.CloneRef(pblockTime));
2192 	mnew->filterType  = filterType;
2193 	mnew->alphaSource = alphaSource;
2194 	mnew->alphaAsMono = alphaAsMono;
2195 	mnew->alphaAsRGB  = alphaAsRGB;
2196 	mnew->premultAlpha = premultAlpha;
2197 	mnew->endCond     = endCond;
2198 	mnew->applyCrop   = applyCrop;
2199 	mnew->ivalid.SetEmpty();
2200 	mnew->placeImage  = placeImage;
2201 	mnew->randPlace   = randPlace;
2202 	mnew->applyCrop   = applyCrop;
2203 	mnew->startTime  = startTime;
2204 	mnew->pbRate  = pbRate;
2205 	mnew->m_bi = m_bi;
2206 	BaseClone(this, mnew, remap);
2207 	mnew->LoadBitmap( GetCOREInterface()->GetTime() );
2208 	return (RefTargetHandle)mnew;
2209 }
2210 
CreateParamDlg(HWND hwMtlEdit,IMtlParams * imp)2211 ParamDlg* BMTex::CreateParamDlg(HWND hwMtlEdit, IMtlParams *imp) {
2212 	//	BMTexDlg *dm = new BMTexDlg(hwMtlEdit, imp, this);
2213 	//	dm->LoadDialog(TRUE);
2214 	//	paramDlg = dm;
2215 	//	return dm;
2216 	// JBW: the main difference here is the automatic creation of a ParamDlg by the new
2217 	// ClassDesc2 function CreateParamDlgs().  This mirrors the way BeginEditParams()
2218 	// can be redirected to the ClassDesc2 for automatic ParamMap2 management.  In this
2219 	// case a special subclass of ParamDlg, AutoMParamDlg, defined in IParamm2.h, is
2220 	// created.  It can act as a 'master' ParamDlg to which you can add any number of
2221 	// secondary dialogs and it will make sure all the secondary dialogs are kept
2222 	// up-to-date and deleted as necessary.
2223 	// Here you see we create the Coordinate, Gradient and Output ParamDlgs in the desired
2224 	// order, and then add the Coordinate and Output dlgs as secondaries to the
2225 	// Gradient master AutoMParamDlg so it will keep them up-to-date automatically
2226 
2227 	// create the rollout dialogs
2228 	uvGenDlg = uvGen->CreateParamDlg(hwMtlEdit, imp);
2229 	IAutoMParamDlg* masterDlg = bmTexCD.CreateParamDlgs(hwMtlEdit, imp, this);
2230 	texoutDlg = texout->CreateParamDlg(hwMtlEdit, imp);
2231 	// add the secondary dialogs to the master
2232 	masterDlg->AddDlg(uvGenDlg);
2233 	masterDlg->AddDlg(texoutDlg);
2234 	paramDlg = new BMTexDlg(hwMtlEdit,imp,this);
2235 	bmtex_param_blk.SetUserDlgProc(paramDlg);
2236 	ip = imp;
2237 	EnableStuff();
2238 	return masterDlg;
2239 
2240 }
2241 
~BMTex()2242 BMTex::~BMTex() {
2243 	UnRegisterNotification(BMTexNotify, this, NOTIFY_PROXY_TEMPORARY_DISABLE_END);
2244 	UnRegisterNotification(BMTexNotify, this, NOTIFY_PROXY_TEMPORARY_DISABLE_START);
2245 	UnRegisterNotification(BMTexNotify, this, NOTIFY_BITMAP_CHANGED);
2246 	DiscardTexHandle();
2247 	FreeBitmap();
2248 }
2249 
SetDlgThing(ParamDlg * dlg)2250 BOOL BMTex::SetDlgThing(ParamDlg* dlg)
2251 {
2252 	// JBW: set the appropriate 'thing' sub-object for each
2253 	// secondary dialog
2254 	if (paramDlg) paramDlg->SetThing(this);
2255 	EnableStuff();
2256 
2257 	if ((uvGenDlg!= NULL) && (dlg == uvGenDlg))
2258 		uvGenDlg->SetThing(uvGen);
2259 	else if ((texoutDlg!= NULL) && (dlg == texoutDlg))
2260 		texoutDlg->SetThing(texout);
2261 	else
2262 		return FALSE;
2263 	return TRUE;
2264 
2265 }
2266 
2267 
2268 
Update(TimeValue t,Interval & valid)2269 void BMTex::Update(TimeValue t, Interval& valid) {
2270 
2271 	pblockTime->GetValue( bmtex_matidtime, 0, mTieTimeToMatID,FOREVER);
2272 
2273 	if (!ivalid.InInterval(t)) {
2274 
2275 		uvGen->SetClipFlag(FALSE);
2276 
2277 		ivalid.SetInfinite();
2278 		uvGen->Update(t,ivalid);
2279 		clipValid.SetInfinite();
2280 		pblock->GetValue( bmtex_clipu, t, clipu, clipValid );
2281 		pblock->GetValue( bmtex_clipv, t, clipv, clipValid );
2282 		pblock->GetValue( bmtex_clipw, t, clipw, clipValid );
2283 		pblock->GetValue( bmtex_cliph, t, cliph, clipValid );
2284 		pblock->GetValue( bmtex_jitter, t, jitter, clipValid );
2285 
2286 		pblock->GetValue( bmtex_filtering, t, filterType, clipValid );
2287 		pblock->GetValue( bmtex_alphasource, t, alphaSource, clipValid );
2288 
2289 		if (alphaSource == 0)
2290 			alphaSource  = ALPHA_FILE;
2291 		else if (alphaSource == 1)
2292 			alphaSource  = ALPHA_RGB;
2293 		else if (alphaSource == 2)
2294 			alphaSource  = ALPHA_NONE;
2295 
2296 		pblock->GetValue( bmtex_monooutput, t, alphaAsMono, clipValid );
2297 		pblock->GetValue( bmtex_rgboutput, t, alphaAsRGB, clipValid );
2298 		pblock->GetValue( bmtex_premultalpha, t, premultAlpha, clipValid );
2299 		pblock->GetValue( bmtex_usejitter, t, randPlace, clipValid );
2300 
2301 		pblock->GetValue( bmtex_crop_place, t, placeImage, clipValid );
2302 
2303 		pblock->GetValue( bmtex_apply, t, applyCrop, clipValid );
2304 
2305 		pblockTime->GetValue( bmtex_start, t, startTime, clipValid );
2306 		pblockTime->GetValue( bmtex_playbackrate, t, pbRate, clipValid );
2307 		pblockTime->GetValue( bmtex_endcondition, t, endCond, clipValid );
2308 
2309 		if (applyCrop)
2310 			ivalid &= clipValid;
2311 		else
2312 			clipValid.SetInfinite();
2313 
2314 		texout->Update(t,ivalid);
2315 
2316 		// [dl | 20aug2003] Set the bitmap frame to be used. This is needed by
2317 		// mental ray to correctly pick up which frame of the bitmap to use.
2318 		// This is only necessary if the bitmap is not using the MtlID as frame
2319 		// number.
2320 		if (!mTieTimeToMatID) {
2321 
2322 			// Get the bitmap info from the parameter block
2323 			PBBitmap* bitmapPB = NULL;
2324 			pblock->GetValue( bmtex_bitmap, t,bitmapPB, clipValid );
2325 
2326 			// Free the bitmap if the filenames don't match. We need to do this
2327 			// before we overwrite 'bi', otherwise there'll be no way of
2328 			// telling whether the correct bitmap file is loaded.
2329 			if ( ((bitmapPB != NULL) && (_tcscmp(m_bi.Name(), bitmapPB->bi.Name())) )   )
2330 				FreeBitmap();
2331 
2332 			// Update 'bi' to be current with the contents of the param block
2333 			UpdateBIName();
2334 
2335 			// Calculate the frame number
2336 			m_bi.SetCurrentFrame(CalcFrame(t));
2337 
2338 			// Commit the bitmap info to the param block, since mental ray uses
2339 			// the value from the param block.
2340 			if(bitmapPB != NULL) {
2341 				bitmapPB->bi = m_bi;
2342 			}
2343 		}
2344 	}
2345 
2346 	if (GetActiveBitmap()&&!bmWasSet) {
2347 		if (m_bi.FirstFrame()!=m_bi.LastFrame())
2348 		{
2349 			ivalid.SetInstant(t);  // force bitmap to be reloaded
2350 		}
2351 	}
2352 	else {
2353 		ivalid.SetInstant(t);  // force bitmap to be reloaded
2354 	}
2355 
2356 	UpdtSampler();
2357 	valid &= ivalid;
2358 }
2359 
GetReference(int i)2360 RefTargetHandle BMTex::GetReference(int i) {
2361 	switch(i) {
2362 		case 0: return uvGen;
2363 		case 1: return pblock;
2364 		case 2:	return texout;
2365 		case 3: return pblockTime;
2366 		default: return NULL;
2367 	}
2368 }
2369 
RemapRefOnLoad(int iref)2370 int BMTex::RemapRefOnLoad(int iref) {
2371 	if (loadingOld) {
2372 		switch(iref) {
2373 			case 0: return 0;
2374 			case 1: return 2;
2375 			default: assert(0); return 0;
2376 		}
2377 	}
2378 	else return iref;
2379 }
2380 
SetReference(int i,RefTargetHandle rtarg)2381 void BMTex::SetReference(int i, RefTargetHandle rtarg) {
2382 	switch(i) {
2383 		case 0: uvGen = (UVGen *)rtarg; break;
2384 		case 1: pblock = (IParamBlock2 *)rtarg; break;
2385 		case 2:	texout = (TextureOutput *)rtarg; break;
2386 		case 3: pblockTime = (IParamBlock2 *)rtarg; break;
2387 		default: break;
2388 	}
2389 }
2390 
2391 
SubAnim(int i)2392 Animatable* BMTex::SubAnim(int i) {
2393 	switch (i) {
2394 		case 0: return uvGen;
2395 		case 1: return pblock;
2396 		case 2: return texout;
2397 		case 3: return pblockTime;
2398 		default: assert(0); return NULL;
2399 	}
2400 }
2401 
GetFullName()2402 TSTR BMTex::GetFullName() {
2403 	TSTR cnm,nm,fname;
2404 	GetClassName(cnm);
2405 	UpdateBIName();   //DS 2/18/99
2406 	GetBMName(m_bi,fname);
2407 	TCHAR *s = fname.Length()>0? fname.data(): cnm.data();
2408 	nm.printf(_T("%s (%s)"),GetName().data(), s);
2409 	return nm;
2410 }
2411 
SubAnimName(int i)2412 TSTR BMTex::SubAnimName(int i) {
2413 	switch (i) {
2414 		case 0: return TSTR(GetString(IDS_DS_COORDINATES));
2415 		case 1: return TSTR(GetString(IDS_DS_PARAMETERS));
2416 		case 2: return TSTR(GetString(IDS_DS_OUTPUT));
2417 		case 3: return TSTR(GetString(IDS_DS_PARAMETERS));
2418 		default: assert(0); return TSTR(_T(""));
2419 	}
2420 }
2421 
NotifyRefChanged(Interval changeInt,RefTargetHandle hTarget,PartID & partID,RefMessage message)2422 RefResult BMTex::NotifyRefChanged(Interval changeInt, RefTargetHandle hTarget,
2423 								  PartID& partID, RefMessage message ) {
2424 	switch (message) {
2425 	case REFMSG_CHANGE:
2426 		{
2427 			ivalid.SetEmpty();
2428 			if (hTarget == pblock)
2429 			{
2430 				// see if this message came from a changing parameter in the pblock,
2431 				// if so, limit rollout update to the changing item and update any active viewport texture
2432 				ParamID changing_param = pblock->LastNotifyParamID();
2433 				bmtex_param_blk.InvalidateUI(changing_param);
2434 				if (changing_param != -1)
2435 					DiscardTexHandle();
2436 
2437 				//  435297 : Handling changes here and reload the bitmap
2438 				// The code used to be in PBAccessor::Set for bmtex_bitmap.
2439 				if (changing_param == bmtex_bitmap)
2440 				{
2441 					if (!loading)
2442 					{
2443 						ReloadBitmapAndUpdate();
2444 						// send message so browser/navigator name gets updated
2445 						NotifyDependents(FOREVER,PART_ALL,REFMSG_SUBANIM_STRUCTURE_CHANGED);
2446 					}
2447 				}
2448 			}
2449 
2450 
2451 
2452 			//SS 10/23/2000: Since code accessing this param block is not available
2453 			// to VIZ anywhere else, it made sense to me to add an ifdef check around
2454 			// this entire if statement.
2455 			if (hTarget == pblockTime)
2456 			{
2457 				// see if this message came from a changing parameter in the pblock,
2458 				// if so, limit rollout update to the changing item and update any active viewport texture
2459 				ParamID changing_param = pblockTime->LastNotifyParamID();
2460 				bmtex_time_param_blk.InvalidateUI(changing_param);
2461 			}
2462 
2463 			break;
2464 		}
2465 	case REFMSG_UV_SYM_CHANGE:
2466 		DiscardTexHandle();
2467 		break;
2468 	}
2469 	return(REF_SUCCEED);
2470 }
2471 
2472 
2473 
2474 //------------------------------------------------------------------------
2475 // IO
2476 //------------------------------------------------------------------------
2477 
2478 class BMTexPostLoad : public PostLoadCallback {
2479 public:
2480 	BMTex *chk;
BMTexPostLoad(BMTex * b)2481 	BMTexPostLoad(BMTex *b) {chk=b;}
proc(ILoad * iload)2482 	void proc(ILoad *iload) {
2483 		chk->loadingOld = FALSE;
2484 		delete this;
2485 	}
2486 };
2487 
2488 #define MTL_HDR_CHUNK 0x4000
2489 #define OLDBMTEX_NAME_CHUNK 0x5001
2490 #define BMTEX_FILTER_CHUNK 0x5002
2491 #define BMTEX_ALPHASOURCE_CHUNK 0x5003
2492 #define BMTEX_NAME_CHUNK 0x5004
2493 #define BMTEX_IO_CHUNK 0x5010
2494 #define BMTEX_START_CHUNK 0x5011
2495 #define BMTEX_RATE_CHUNK 0x5012
2496 #define BMTEX_ALPHA_MONO_CHUNK 0x5013
2497 #define BMTEX_ENDCOND_CHUNK 0x5014
2498 #define BMTEX_ALPHA_RGB_CHUNK 0x5016
2499 #define BMTEX_VERSOLD_CHUNK 0x5021
2500 #define BMTEX_VERSION_CHUNK 0x5022
2501 #define BMTEX_ALPHA_NOTPREMULT_CHUNK 0x5030
2502 #define BMTEX_CLIP_CHUNK 0x5040
2503 #define BMTEX_PLACE_IMAGE_CHUNK 0x5050
2504 #define BMTEX_JITTER_CHUNK 0x5060
2505 
Save(ISave * isave)2506 IOResult BMTex::Save(ISave *isave) {
2507 	//	ULONG nb;
2508 	IOResult res;
2509 	// Save common stuff
2510 	isave->BeginChunk(MTL_HDR_CHUNK);
2511 	res = MtlBase::Save(isave);
2512 	if (res!=IO_OK) return res;
2513 	isave->EndChunk();
2514 	return IO_OK;
2515 }
2516 
2517 
2518 class BMTex2PostLoad : public PostLoadCallback {
2519 public:
2520 	BMTex *n;
2521 	BOOL isParam2;
BMTex2PostLoad(BMTex * ns,BOOL b)2522 	BMTex2PostLoad(BMTex *ns, BOOL b) {n = ns;isParam2 = b;}
proc(ILoad * iload)2523 	void proc(ILoad *iload) {
2524 
2525 		if (!isParam2)
2526 		{
2527 			macroRecorder->Disable();
2528 			n->pblock->SetValue( bmtex_filtering, 0, n->filterType);
2529 			if (n->alphaSource == ALPHA_FILE) n->alphaSource  = 0;
2530 			else if (n->alphaSource == ALPHA_RGB) n->alphaSource  = 1;
2531 			else if (n->alphaSource == ALPHA_NONE) n->alphaSource  = 2;
2532 
2533 			n->pblock->SetValue( bmtex_alphasource, 0, n->alphaSource);
2534 
2535 
2536 			n->pblock->SetValue( bmtex_monooutput, 0, n->alphaAsMono );
2537 			n->pblock->SetValue( bmtex_rgboutput, 0, n->alphaAsRGB );
2538 			n->pblock->SetValue( bmtex_premultalpha, 0, n->premultAlpha);
2539 			n->pblock->SetValue( bmtex_usejitter, 0, n->randPlace );
2540 
2541 			n->pblock->SetValue( bmtex_crop_place, 0, n->placeImage);
2542 
2543 			n->pblock->SetValue( bmtex_apply, 0, n->applyCrop);
2544 
2545 			PBBitmap bPB(n->m_bi);
2546 			n->loading = TRUE;
2547 			n->pblock->SetValue( bmtex_bitmap, 0, &bPB);
2548 			n->loading = FALSE;
2549 
2550 			n->pblockTime->SetValue( bmtex_start, 0, n->startTime);
2551 			n->pblockTime->SetValue( bmtex_playbackrate, 0, n->pbRate);
2552 			n->pblockTime->SetValue( bmtex_endcondition, 0, n->endCond);
2553 
2554 			macroRecorder->Enable();
2555 
2556 		}
2557 		delete this;
2558 
2559 
2560 	}
2561 };
2562 
2563 
Load(ILoad * iload)2564 IOResult BMTex::Load(ILoad *iload) {
2565 	ULONG nb;
2566 	IOResult res;
2567 	TSTR oldBMName;
2568 	//	iload->RegisterPostLoadCallback(new ParamBlockPLCB(oldVersions, 3, &curVersion, this,1));
2569 	while (IO_OK==(res=iload->OpenChunk())) {
2570 		switch(iload->CurChunkID())  {
2571 			case MTL_HDR_CHUNK:
2572 				res = MtlBase::Load(iload);
2573 				break;
2574 			case BMTEX_VERSOLD_CHUNK:
2575 				loadingOld = TRUE;
2576 				break;
2577 			case BMTEX_FILTER_CHUNK:
2578 				iload->Read(&filterType,sizeof(filterType),&nb);
2579 				isParm2 = FALSE;
2580 				break;
2581 			case BMTEX_ALPHASOURCE_CHUNK:
2582 				isParm2 = FALSE;
2583 				iload->Read(&alphaSource,sizeof(alphaSource),&nb);
2584 				break;
2585 			case BMTEX_NAME_CHUNK:
2586 				{
2587 					// This chunk is used for old files only
2588 					isParm2 = FALSE;
2589 					TCHAR *buf;
2590 					if(IO_OK==iload->ReadWStringChunk(&buf)) {
2591 						if((buf != NULL) && (buf[0] != _T('\0'))) {
2592 							oldBMName = buf;
2593 						}
2594 					}
2595 				}
2596 				break;
2597 			case BMTEX_IO_CHUNK:
2598 				isParm2 = FALSE;
2599 				res = m_bi.Load(iload);
2600 				// DS 7/18/96 - This is to handle old files
2601 				// that had the bi saved with start = end = 0,
2602 				// which now screws up animation.
2603 				m_bi.SetStartFrame(BMM_UNDEF_FRAME);
2604 				m_bi.SetEndFrame(BMM_UNDEF_FRAME);
2605 				break;
2606 			case BMTEX_START_CHUNK:
2607 				isParm2 = FALSE;
2608 				iload->Read(&startTime,sizeof(startTime),&nb);
2609 				break;
2610 			case BMTEX_RATE_CHUNK:
2611 				isParm2 = FALSE;
2612 				iload->Read(&pbRate,sizeof(pbRate),&nb);
2613 				break;
2614 			case BMTEX_ALPHA_MONO_CHUNK:
2615 				isParm2 = FALSE;
2616 				alphaAsMono = TRUE;
2617 				break;
2618 			case BMTEX_ALPHA_RGB_CHUNK:
2619 				isParm2 = FALSE;
2620 				alphaAsRGB = TRUE;
2621 				break;
2622 			case BMTEX_ALPHA_NOTPREMULT_CHUNK:
2623 				isParm2 = FALSE;
2624 				premultAlpha = FALSE;
2625 				break;
2626 			case BMTEX_ENDCOND_CHUNK:
2627 				isParm2 = FALSE;
2628 				iload->Read(&endCond,sizeof(endCond),&nb);
2629 				break;
2630 			case BMTEX_CLIP_CHUNK:
2631 				isParm2 = FALSE;
2632 				applyCrop = TRUE;
2633 				break;
2634 			case BMTEX_PLACE_IMAGE_CHUNK:
2635 				isParm2 = FALSE;
2636 				placeImage = TRUE;
2637 				break;
2638 			case BMTEX_JITTER_CHUNK:
2639 				isParm2 = FALSE;
2640 				randPlace = TRUE;
2641 				break;
2642 		}
2643 		iload->CloseChunk();
2644 		if (res!=IO_OK)
2645 			return res;
2646 	}
2647 	if (alphaSource<0||alphaSource>ALPHA_NONE)
2648 		alphaSource = ALPHA_FILE;
2649 
2650 
2651 	if (!isParm2)
2652 	{
2653 		ParamBlock2PLCB* plcb = new ParamBlock2PLCB( oldVersions, NUMOLDVERSIONS, &bmtex_param_blk, this, 1);
2654 		iload->RegisterPostLoadCallback(plcb);
2655 
2656 		BMTex2PostLoad *bmt2PLCB = new BMTex2PostLoad(this,isParm2);
2657 		iload->RegisterPostLoadCallback(bmt2PLCB);
2658 	}
2659 
2660 	if (oldBMName.Length()>0) {
2661 		m_bi.SetName(oldBMName);   // for obsolete files
2662 		iload->SetObsolete();
2663 	}
2664 
2665 	return IO_OK;
2666 }
2667 
SetBitmap(Bitmap * bm)2668 void BMTex::SetBitmap(Bitmap *bm) {
2669 	FreeBitmap();
2670 	m_theBitmap.SetBitmap(bm);
2671 	bmWasSet = (bm != NULL);
2672 }
2673 
2674 #define PROPID_SETBITMAP 0x111
2675 
SetProperty(ULONG id,void * data)2676 int BMTex::SetProperty(ULONG id, void *data)
2677 {
2678 	switch (id) {
2679 	case PROPID_CLEARCACHES:
2680 		FreeBitmap();
2681 		return 1;
2682 	case PROPID_SETBITMAP:
2683 		SetBitmap((Bitmap *)data);
2684 		return 1;
2685 
2686 	default: return 0;
2687 	}
2688 }
2689 
2690 
2691 
BitmapLoadDlg()2692 void BMTex::BitmapLoadDlg()	{
2693 	HWND hpanel = GetCOREInterface()->GetMAXHWnd();
2694 
2695 	// lrr 06/04
2696 	if (_tcscmp(s_lastName, _T(""))) {
2697 		m_bi.SetName(s_lastName);
2698 	}
2699 	else {
2700 		// Use the images directory as the default dir.
2701 		TCHAR dummy[MAX_PATH];
2702 		_tcscpy(dummy, TheManager->GetDir(APP_IMAGE_DIR));
2703 		// Need to add a dummy filename to this path
2704 		BMMAppendSlash(dummy);
2705 		m_bi.SetName(dummy);
2706 	}
2707 
2708 	BOOL res = TheManager->SelectFileInputEx(&m_bi, hpanel, GetString(IDS_DS_SELECT_BMFILE));
2709 
2710 	//load into param block
2711 	if (res) {
2712 		PBBitmap bt(m_bi);
2713 		loading = 1;  // disable accessor
2714 		pblock->SetValue(bmtex_bitmap, 0, &bt);
2715 		loading = 0;
2716 		FreeBitmap();   // DS 9/25/00
2717 		ReloadBitmap(false); // DS 9/25/00  -- this is to fix #254986
2718 
2719 		if (m_bi.Name())							//LRR 06/04
2720 			_tcscpy( s_lastName, m_bi.Name() );
2721 
2722 		ShowBitmapProxyPrecacheDialog();
2723 	}
2724 }
2725 
2726 //watje forces the bitmap to reload and view to be redrawn
ReloadBitmapAndUpdate()2727 void BMTex::ReloadBitmapAndUpdate()
2728 {
2729 	FreeBitmap();
2730 	ReloadBitmap(false);
2731 	fileNotFound = FALSE; // DS 4/20/99
2732 	if (TestMtlFlag(MTL_TEX_DISPLAY_ENABLED)) {
2733 		if (ip)
2734 			ip->MtlChanged();
2735 	}
2736 }
2737 
2738 
fnReload()2739 void BMTex::fnReload()
2740 {
2741 	ReloadBitmap(false);
2742 	BroadcastNotification(NOTIFY_BITMAP_CHANGED, (void *)m_bi.Name());
2743 	if (ip) ip->MtlChanged();
2744 	if ((ip) && (paramDlg)) paramDlg->Invalidate();  // incase path of map has changed.
2745 
2746 }
2747 
fnViewImage()2748 void BMTex::fnViewImage()
2749 {
2750 	if ((ip) && (paramDlg)) paramDlg->ShowCropImage();
2751 }
2752 
ComputeParticleFrame(ShadeContext & sc)2753 int BMTex::ComputeParticleFrame(ShadeContext& sc)
2754 {
2755 
2756 	//	return 0;
2757 	// Evaluate...
2758 	Object *ob = sc.GetEvalObject();
2759 	float u=0.0f;
2760 	if (ob && ob->IsParticleSystem()) {
2761 		ParticleObject *obj = (ParticleObject*)ob;
2762 		TimeValue age  = obj->ParticleAge(sc.CurTime(),sc.mtlNum);
2763 		if (age>=0)
2764 		{
2765 			if (m_bi.NumberFrames() <= 1) return 0;
2766 			return CalcFrame(age)%m_bi.NumberFrames();
2767 		}
2768 
2769 	}
2770 	return 0;
2771 
2772 }
2773 
GetInterface(ULONG id)2774 void* BMTex::GetInterface(ULONG id) {
2775 
2776 	// [dl | 27feb2004] I added this to make it possible for mental ray to
2777 	// retrieve the tab of particle bitmaps.
2778 	if(id == IID_BITMAPTEX_PARTICLE_BITMAP_LIST) {
2779 		MaxSDK::Array<Bitmap*>* particleBitmapList = new MaxSDK::Array<Bitmap*>();
2780 		size_t count = m_theBitmapList.length();
2781 		particleBitmapList->setLengthUsed(count);
2782 		for(size_t i = 0; i < count; ++i) {
2783 			(*particleBitmapList)[i] = m_theBitmapList[i].GetBitmap();
2784 		}
2785 		return particleBitmapList;
2786 	}
2787 	else {
2788 		return Texmap::GetInterface(id);
2789 	}
2790 }
2791 
EnableProxyMode(bool deleteNonProxyBitmap)2792 void BMTex::EnableProxyMode(bool deleteNonProxyBitmap) {
2793 
2794 	m_theBitmap.EnableProxyMode(deleteNonProxyBitmap);
2795 	size_t count = m_theBitmapList.length();
2796 	for(size_t i = 0; i < count; ++i) {
2797 		BitmapHolder& currentBitmap = m_theBitmapList[i];
2798 		currentBitmap.EnableProxyMode(deleteNonProxyBitmap);
2799 	}
2800 
2801 	// Re-initialize the bitmap samplers, since the active bitmap might have changed.
2802 	// The previous active bitmap might even have been deleted.
2803 	InitBitmapSamplers();
2804 }
2805 
DisableProxyMode(bool deleteProxyBitmap)2806 void BMTex::DisableProxyMode(bool deleteProxyBitmap) {
2807 
2808 	m_theBitmap.DisableProxyMode(deleteProxyBitmap);
2809 	size_t count = m_theBitmapList.length();
2810 	for(size_t i = 0; i < count; ++i) {
2811 		BitmapHolder& currentBitmap = m_theBitmapList[i];
2812 		currentBitmap.DisableProxyMode(deleteProxyBitmap);
2813 	}
2814 
2815 	InitBitmapSamplers();
2816 }
2817 
ShowBitmapProxyPrecacheDialog()2818 void BMTex::ShowBitmapProxyPrecacheDialog() {
2819 
2820 	const TCHAR* bmName = m_bi.Name();
2821 	if((bmName != NULL) && (bmName[0] != _T('\0'))) {
2822 		// The Bitmap Proxy Pre-Caching dialog is now displayed, if necessary.
2823 		// The  ShowPrecacheDialog() method internally determines whether
2824 		// it's necessary to display the actual dialog.
2825 		IBitmapProxyManager* proxyManager = GetBitmapProxyManager();
2826 		if((proxyManager != NULL) && proxyManager->GetGlobalProxyEnable()) {
2827 			Tab<TCHAR*> filenames;
2828 			TCHAR* bmNameNonConstHackHackHack = const_cast<TCHAR*>(bmName);
2829 			filenames.Append(1, &bmNameNonConstHackHackHack);
2830 			proxyManager->ShowPrecacheDialog(&filenames);
2831 		}
2832 	}
2833 }
2834 
ShouldDisableProxiesForRendering(bool isMtlEditor)2835 bool BMTex::ShouldDisableProxiesForRendering(bool isMtlEditor) {
2836 
2837 	if(isMtlEditor) {
2838 		return false;
2839 	}
2840 	else {
2841 		IBitmapProxyManager* proxyManager = GetBitmapProxyManager();
2842 		if(proxyManager != NULL) {
2843 			IBitmapProxyManager::RenderMode renderMode = proxyManager->GetGlobalProxyRenderMode();
2844 			switch(renderMode) {
2845 				default:
2846 					DbgAssert(false);
2847 					// Fall through...
2848 				case IBitmapProxyManager::kRenderMode_UseProxies:
2849 					return false;
2850 				case IBitmapProxyManager::kRenderMode_UseFullRes_KeepInMemory:
2851 				case IBitmapProxyManager::kRenderMode_UseFullRes_FlushFromMemory:
2852 					return true;
2853 			}
2854 		}
2855 		else {
2856 			DbgAssert(false);
2857 			return false;
2858 		}
2859 	}
2860 }
2861 
KeepNonProxyInMemoryAfterRendering()2862 bool BMTex::KeepNonProxyInMemoryAfterRendering() {
2863 
2864 	IBitmapProxyManager* proxyManager = GetBitmapProxyManager();
2865 	if(proxyManager != NULL) {
2866 		IBitmapProxyManager::RenderMode renderMode = proxyManager->GetGlobalProxyRenderMode();
2867 		switch(renderMode) {
2868 			default:
2869 				DbgAssert(false);
2870 				// Fall through...
2871 			case IBitmapProxyManager::kRenderMode_UseProxies:
2872 			case IBitmapProxyManager::kRenderMode_UseFullRes_FlushFromMemory:
2873 				return false;
2874 			case IBitmapProxyManager::kRenderMode_UseFullRes_KeepInMemory:
2875 				return true;
2876 		}
2877 	}
2878 	else {
2879 		DbgAssert(false);
2880 		return false;
2881 	}
2882 }
2883 
InitBitmapSamplers()2884 void BMTex::InitBitmapSamplers() {
2885 
2886 	BOOL tieTimeToMatID;
2887 	pblockTime->GetValue( bmtex_matidtime, 0, tieTimeToMatID,FOREVER);
2888 
2889 	if (!tieTimeToMatID)
2890 	{
2891 		mysamp.Init(this);
2892 		alphasamp.Init(this);
2893 	}
2894 	else
2895 	{
2896 		for (int i = 0; i < mysampList.Count(); i++)
2897 		{
2898 			mysampList[i]->Init(this,m_theBitmapList[i].GetBitmap());
2899 			alphasampList[i]->Init(this,m_theBitmapList[i].GetBitmap());
2900 		}
2901 	}
2902 }
2903 
2904 //==============================================================================
2905 // class BMTex::BMMSilentModeGuard
2906 //==============================================================================
2907 
BMMSilentModeGuard(bool setSilentMode)2908 BMTex::BMMSilentModeGuard::BMMSilentModeGuard(bool setSilentMode)
2909 : m_setSilentMode(setSilentMode)
2910 {
2911 	if(m_setSilentMode) {
2912 		m_previousSilentMode = TheManager->SetSilentMode(true);
2913 	}
2914 }
~BMMSilentModeGuard()2915 BMTex::BMMSilentModeGuard::~BMMSilentModeGuard() {
2916 	if(m_setSilentMode) {
2917 		TheManager->SetSilentMode(m_previousSilentMode);
2918 	}
2919 }
2920 
2921 //==============================================================================
2922 // class BMTex::BitmapHolder
2923 //==============================================================================
2924 
BitmapHolder()2925 BMTex::BitmapHolder::BitmapHolder()
2926 : m_nonProxyBitmap(NULL),
2927   m_proxyBitmap(NULL),
2928   m_isProxyMode(true)
2929 {
2930 }
2931 
BitmapHolder(const BitmapHolder & other)2932 BMTex::BitmapHolder::BitmapHolder(const BitmapHolder& other) {
2933 
2934 	*this = other;
2935 }
2936 
~BitmapHolder()2937 BMTex::BitmapHolder::~BitmapHolder() {
2938 	// The bitmaps should have already been freed by BMTex. I won't free them here (just in case,
2939 	// to avoid double-deleting something), but I'm still putting a debug assert to catch any
2940 	// possible issues.
2941 	DbgAssert((m_proxyBitmap == NULL) && (m_nonProxyBitmap == NULL));
2942 }
2943 
2944 
operator =(const BitmapHolder & other)2945 BMTex::BitmapHolder& BMTex::BitmapHolder::operator=(const BitmapHolder& other) {
2946 
2947 	m_nonProxyBitmap = other.m_nonProxyBitmap;
2948 	m_proxyBitmap = other.m_proxyBitmap;
2949 	m_isProxyMode = other.m_isProxyMode;
2950 	m_nonProxyBitmapInfo = other.m_nonProxyBitmapInfo;
2951 	m_proxyBitmapInfo = other.m_proxyBitmapInfo;
2952 
2953 	return *this;
2954 }
2955 
IsCurrentFrame(Bitmap * bitmap,int frame)2956 bool IsCurrentFrame( Bitmap* bitmap, int frame ) {
2957 	BitmapStorage* storage = NULL;
2958 	if( bitmap!=NULL ) storage = bitmap->Storage();
2959 
2960 	if( storage==NULL ) return false;
2961 	BitmapInfo* info = GetSubjectInfo( &(storage->bi) );
2962 
2963 	return (info->CurrentFrame() == frame);
2964 }
2965 
EnableProxyMode(bool deleteNonProxyBitmap)2966 void BMTex::BitmapHolder::EnableProxyMode(bool deleteNonProxyBitmap) {
2967 
2968 	if( m_isProxyMode!=true ) {
2969 		m_isProxyMode = true;
2970 
2971 		// Ensure both bitmaps are on the same frame
2972 		// Non-proxy info holds the desired frame, whether in proxy mode or not
2973 		int currentFrame = m_nonProxyBitmapInfo.CurrentFrame();
2974 		if( !IsCurrentFrame( m_proxyBitmap, currentFrame ) ) {
2975 			if( m_proxyBitmap!=NULL )
2976 				BitmapProxy_GoTo( m_nonProxyBitmapInfo, m_proxyBitmapInfo, m_proxyBitmap );
2977 		}
2978 	}
2979 
2980 	if(deleteNonProxyBitmap) {
2981 		FreeNonProxyBitmap();
2982 	}
2983 }
2984 
DisableProxyMode(bool deleteProxyBitmap)2985 void BMTex::BitmapHolder::DisableProxyMode(bool deleteProxyBitmap) {
2986 
2987 	if( m_isProxyMode!=false ) {
2988 		m_isProxyMode = false;
2989 
2990 		// Ensure both bitmaps are on the same frame
2991 		// Non-proxy info holds the desired frame, whether in proxy mode or not
2992 		int currentFrame = m_nonProxyBitmapInfo.CurrentFrame();
2993 		if( !IsCurrentFrame( m_nonProxyBitmap, currentFrame ) ) {
2994 			if( m_nonProxyBitmap!=NULL )
2995 				BitmapNonProxy_GoTo( m_nonProxyBitmapInfo, m_nonProxyBitmap );
2996 		}
2997 	}
2998 
2999 	if(deleteProxyBitmap) {
3000 		FreeProxyBitmap();
3001 	}
3002 }
3003 
LoadBitmap(BMMRES & status,bool silenceBitmapManager)3004 bool BMTex::BitmapHolder::LoadBitmap(BMMRES& status, bool silenceBitmapManager) {
3005 
3006 	// Set silent mode if necessary
3007 	BMMSilentModeGuard silentModeGuard(silenceBitmapManager);
3008 
3009 	if(m_isProxyMode) {
3010 		// The bitmap should be NULL, otherwise we'll get a memory leak
3011 		DbgAssert(m_proxyBitmap == NULL);
3012 		m_proxyBitmap = BitmapProxy_Load(m_nonProxyBitmapInfo, m_proxyBitmapInfo, &status);
3013 		return (m_proxyBitmap != NULL);
3014 	}
3015 	else {
3016 		// The bitmap should be NULL, otherwise we'll get a memory leak
3017 		DbgAssert(m_nonProxyBitmap == NULL);
3018 		m_nonProxyBitmap = BitmapNonProxy_Load(m_nonProxyBitmapInfo, &status);
3019 		return (m_nonProxyBitmap != NULL);
3020 	}
3021 }
3022 
LoadInto(bool forceReload)3023 void BMTex::BitmapHolder::LoadInto(bool forceReload) {
3024 
3025 	// Reload both the proxy and non-proxy bitmaps, to ensure that none of them is invalid.
3026 	if(m_nonProxyBitmap != NULL) {
3027 		BitmapNonProxy_LoadInto(m_nonProxyBitmapInfo, &m_nonProxyBitmap, forceReload);
3028 	}
3029 
3030 	if(m_proxyBitmap != NULL) {
3031 		BitmapProxy_LoadInto(m_nonProxyBitmapInfo, m_proxyBitmapInfo, &m_proxyBitmap, forceReload);
3032 	}
3033 }
3034 
FreeBitmap()3035 void BMTex::BitmapHolder::FreeBitmap() {
3036 
3037 	// Free both the proxy and non-proxy bitmaps.
3038 	FreeNonProxyBitmap();
3039 	FreeProxyBitmap();
3040 }
3041 
FreeProxyBitmap()3042 void BMTex::BitmapHolder::FreeProxyBitmap() {
3043 
3044 	if(m_proxyBitmap != NULL) {
3045 		m_proxyBitmap->DeleteThis();
3046 		m_proxyBitmap = NULL;
3047 	}
3048 }
3049 
FreeNonProxyBitmap()3050 void BMTex::BitmapHolder::FreeNonProxyBitmap() {
3051 
3052 	if(m_nonProxyBitmap != NULL) {
3053 		m_nonProxyBitmap->DeleteThis();
3054 		m_nonProxyBitmap = NULL;
3055 	}
3056 }
3057 
GotoFrame(bool silenceBitmapManager)3058 BMMRES BMTex::BitmapHolder::GotoFrame(bool silenceBitmapManager) {
3059 
3060 	// Forward the call to the active bitmap.
3061 	// The "inactive" bitmap doesn't get the call, which I think should be fine.
3062 	// If there's ever a problem, though, it might be necessary to call GoTo()
3063 	// on both bitmaps.
3064 
3065 	BMMRES result = BMMRES_SUCCESS;
3066 
3067 	// Set silent mode if necessary
3068 	BMMSilentModeGuard silentModeGuard(silenceBitmapManager);
3069 
3070 	if(m_isProxyMode) {
3071 		if(m_proxyBitmap != NULL) {
3072 			result = BitmapProxy_GoTo(m_nonProxyBitmapInfo, m_proxyBitmapInfo, m_proxyBitmap);
3073 		}
3074 		else {
3075 			DbgAssert(false);
3076 		}
3077 	}
3078 	else {
3079 		if(m_nonProxyBitmap != NULL) {
3080 			result = BitmapNonProxy_GoTo(m_nonProxyBitmapInfo, m_nonProxyBitmap);
3081 		}
3082 		else {
3083 			DbgAssert(false);
3084 		}
3085 	}
3086 
3087 	return result;
3088 }
3089 
GetBitmapInfo()3090 BitmapInfo& BMTex::BitmapHolder::GetBitmapInfo() {
3091 
3092 	return m_nonProxyBitmapInfo;
3093 }
3094 
GetBitmapInfo() const3095 const BitmapInfo& BMTex::BitmapHolder::GetBitmapInfo() const {
3096 
3097 	return m_nonProxyBitmapInfo;
3098 }
3099 
GetBitmap() const3100 Bitmap* BMTex::BitmapHolder::GetBitmap() const {
3101 
3102 	if(m_isProxyMode) {
3103 		return m_proxyBitmap;
3104 	}
3105 	else {
3106 		return m_nonProxyBitmap;
3107 	}
3108 }
3109 
SetBitmap(Bitmap * bitmap)3110 void BMTex::BitmapHolder::SetBitmap(Bitmap* bitmap) {
3111 
3112 	// The bitmap should first have been freed in order to avoid memroy leaks.
3113 	DbgAssert((m_nonProxyBitmap == NULL) && (m_proxyBitmap == NULL));
3114 
3115 	// Set the proper bitmap, depending on whether it's a proxy or not.
3116 	if(bitmap == NULL) {
3117 		m_proxyBitmap = NULL;
3118 		m_nonProxyBitmap = NULL;
3119 	}
3120 	else if((bitmap->Storage() != NULL) && (bitmap->Storage()->bi.Flags() & MAP_PROXY)) {
3121 		m_proxyBitmap = bitmap;
3122 	}
3123 	else {
3124 		m_nonProxyBitmap = bitmap;
3125 	}
3126 }
3127 
SetFilter(UINT filterType)3128 int BMTex::BitmapHolder::SetFilter(UINT filterType) {
3129 
3130 	int result = 0;
3131 	if(m_proxyBitmap != NULL) {
3132 		result |= m_proxyBitmap->SetFilter(filterType);
3133 	}
3134 	if(m_nonProxyBitmap != NULL) {
3135 		result |= m_nonProxyBitmap->SetFilter(filterType);
3136 	}
3137 
3138 	return result;
3139 }
3140 
SetCroppingValues(float u,float v,float w,float h,BOOL placeImage)3141 void BMTex::BitmapHolder::SetCroppingValues(float u, float v, float w, float h, BOOL placeImage) {
3142 
3143 	if(m_proxyBitmap != NULL) {
3144 		m_proxyBitmap->SetCroppingValues(u, v, w, h, placeImage);
3145 	}
3146 	if(m_nonProxyBitmap != NULL) {
3147 		m_nonProxyBitmap->SetCroppingValues(u, v, w, h, placeImage);
3148 	}
3149 }
3150 
SetNotify(BitmapNotify * bmnot)3151 void BMTex::BitmapHolder::SetNotify(BitmapNotify *bmnot) {
3152 
3153 	// Register the notification with only one bitmap; registering it
3154 	// with both bitmaps results in a crash when the notification is received
3155 	// and the bitmaps are reloaded (the crash occurs when the notification system
3156 	// attempts to notify the second, now defunct bitmap).
3157 
3158 	// Register the notification with the proxy bitmap.
3159 	// The notification is responsible for updating the viewport,
3160 	// so it must be registered against the proxy bitmap which is used for viewport display.
3161 	// The notification also triggers a full reload if the subject changes,
3162 	// which would be equivalent if registered against either bitmap.
3163 
3164 	if( (m_proxyBitmap != NULL) && (m_proxyBitmap->GetNotify() != bmnot) ) {
3165 		m_proxyBitmap->SetNotify(bmnot);
3166 	}
3167 }
3168 
3169 //==============================================================================
3170 // class BMTex::ProxyModeDisableGuard
3171 //==============================================================================
3172 
ProxyModeDisableGuard(BMTex & bitmapTex,bool doDisable)3173 BMTex::ProxyModeDisableGuard::ProxyModeDisableGuard(BMTex& bitmapTex, bool doDisable)
3174 : m_bitmapTex(bitmapTex),
3175   m_doDisable(doDisable)
3176 {
3177 	if(m_doDisable) {
3178 		m_bitmapTex.DisableProxyMode(false);
3179 	}
3180 }
3181 
~ProxyModeDisableGuard()3182 BMTex::ProxyModeDisableGuard::~ProxyModeDisableGuard() {
3183 
3184 	if(m_doDisable) {
3185 		bool flushNonProxyAfterRender = !KeepNonProxyInMemoryAfterRendering();
3186 		m_bitmapTex.EnableProxyMode(flushNonProxyAfterRender);
3187 	}
3188 }
3189