You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 
 

751 lines
26 KiB

/*==LICENSE==*
CyanWorlds.com Engine - MMOG client, server and tools
Copyright (C) 2011 Cyan Worlds, Inc.
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
You can contact Cyan Worlds, Inc. by email legal@cyan.com
or by snail mail at:
Cyan Worlds, Inc.
14617 N Newport Hwy
Mead, WA 99021
*==LICENSE==*/
#include "hsTypes.h"
#include "plLayerTex.h"
#include "plLayerTexBitmapPB.h"
#include "plDetailCurveCtrl.h"
#if 1
class BMTexPBAccessor;
extern BMTexPBAccessor bmtex_accessor;
class BitmapDlgProc;
extern BitmapDlgProc gBitmapDlgProc;
static ParamBlockDesc2 gBitmapParamBlk
(
plLayerTex::kBlkBitmap, _T("bitmap"), 0, GetLayerTexDesc(),//NULL,
P_AUTO_CONSTRUCT + P_AUTO_UI, plLayerTex::kRefBitmap,
IDD_LAYER_TEX, IDS_LAYER_TEX, 0, 0, &gBitmapDlgProc,
// Bitmap
kBmpUseBitmap, _T("useBitmap"), TYPE_BOOL, 0, 0,
p_default, TRUE,
p_ui, TYPE_SINGLECHEKBOX, IDC_USE_BITMAP,
end,
kBmpBitmap, _T("bitmap"), TYPE_BITMAP, P_SHORT_LABELS, 0,
p_accessor, &bmtex_accessor,
end,
// Crop/Place
kBmpApply, _T("apply"), TYPE_BOOL, 0, 0,
p_default, FALSE,
p_ui, TYPE_SINGLECHEKBOX, IDC_BM_CLIP,
end,
kBmpCropPlace, _T("cropPlace"), TYPE_INT, 0, 0,
p_default, 0,
p_range, 0, 1,
p_ui, TYPE_RADIO, 2, IDC_BM_CROP,IDC_BM_PLACE,
end,
kBmpClipU, _T("clipU"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPU,
p_default, 0.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_X, IDC_CLIP_XSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
kBmpClipV, _T("clipV"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPV,
p_default, 0.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_Y, IDC_CLIP_YSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
kBmpClipW, _T("clipW"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPW,
p_default, 1.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_W, IDC_CLIP_WSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
kBmpClipH, _T("clipH"), TYPE_FLOAT, P_ANIMATABLE, IDS_BITMAP_CLIPH,
p_default, 1.0,
p_range, 0.0, 1.0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_CLIP_H, IDC_CLIP_HSPIN, 0.001f,
p_accessor, &bmtex_accessor,
end,
// Texture Color/Alpha
kBmpDiscardColor, _T("discardColor"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_NO_COLOR,
end,
kBmpInvertColor, _T("invertColor"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_COLOR,
end,
kBmpDiscardAlpha, _T("discardAlpha"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_DISCARD_ALPHA,
end,
kBmpInvertAlpha, _T("invertAlpha"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_BLEND_INV_ALPHA,
end,
// Texture Quality
kBmpNonCompressed, _T("nonCompressed"),TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_FORCE_NONCOMPRESSED,
end,
kBmpScaling, _T("scaling"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 3, IDC_SCALE_ALL, IDC_SCALE_HALF, IDC_SCALE_NONE,
end,
// Max Only
kBmpMonoOutput, _T("monoOutput"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_HSMAX_LAYER_RGBOUT, IDC_HSMAX_LAYER_ALPHAOUT,
end,
kBmpRGBOutput, _T("rgbOutput"), TYPE_INT, 0, 0,
p_ui, TYPE_RADIO, 2, IDC_HSMAX_LAYER_RGBOUT2, IDC_HSMAX_LAYER_ALPHAOUT2,
end,
// Mipmap
kBmpNoFilter, _T("noFilter"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_NO_FILTERING,
end,
kBmpMipBlur, _T("mipBlur"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_MIPBLUR_EDIT, IDC_MIPBLUR_SPIN, 0.4,
p_range, 0.01f, 100.0f,
p_default, 1.0,
end,
kBmpMipBias, _T("mipBias"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_USE_MIPBIAS,
p_enable_ctrls, 1, kBmpMipBiasAmt,
end,
kBmpMipBiasAmt, _T("mipBiasAmt"), TYPE_FLOAT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_FLOAT, IDC_MIPBIAS_EDIT, IDC_MIPBIAS_SPIN, 0.7,
p_range, -100.0, 100.0,
p_default, 1.0,
end,
// Detail
kBmpUseDetail, _T("useDetail"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_USE_DETAIL,
p_default, FALSE,
p_enable_ctrls, 4, kBmpDetailStartSize, kBmpDetailStopSize, kBmpDetailStartOpac, kBmpDetailStopOpac,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStartSize,_T("dropOffStart"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_START_SIZE_EDIT, IDC_DETAIL_START_SIZE_SPIN, 0.4,
p_range, 0, 100,
p_default, 0,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStopSize, _T("dropOffStop"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_STOP_SIZE_EDIT, IDC_DETAIL_STOP_SIZE_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStartOpac, _T("detailMax"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_START_OPAC_EDIT, IDC_DETAIL_START_OPAC_SPIN, 0.4,
p_range, 0, 100,
p_default, 100,
p_accessor, &bmtex_accessor,
end,
kBmpDetailStopOpac, _T("detailMin"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_DETAIL_STOP_OPAC_EDIT, IDC_DETAIL_STOP_OPAC_SPIN, 0.4,
p_range, 0, 100,
p_default, 0,
p_accessor, &bmtex_accessor,
end,
kBmpExportWidth, _T("exportWidth"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_EXPORTWIDTH, IDC_EXPORTWIDTH_SPINNER, SPIN_AUTOSCALE,
p_range, 4, 2048,
p_default, 512,
end,
kBmpExportHeight, _T("exportHeight"), TYPE_INT, 0, 0,
p_ui, TYPE_SPINNER, EDITTYPE_INT, IDC_EXPORTHEIGHT, IDC_EXPORTHEIGHT_SPINNER, SPIN_AUTOSCALE,
p_range, 4, 2048,
p_default, 512,
end,
kBmpExportLastWidth, _T("lastExportWidth"), TYPE_INT, 0, 0,
end,
kBmpExportLastHeight, _T("lastExportHeight"), TYPE_INT, 0, 0,
end,
// Keep a sysmem copy at runtime (for image examination/manipulation).
kBmpNoDiscard, _T("noDiscard"), TYPE_BOOL, 0, 0,
p_ui, TYPE_SINGLECHEKBOX, IDC_NO_DISCARD,
p_default, FALSE,
end,
end
);
ParamBlockDesc2 *GetBitmapBlk() { return &gBitmapParamBlk; }
class BMCropper;
class BMTexPBAccessor : public PBAccessor
{
public:
void Set(PB2Value& val, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t)
{
plLayerTex* layer = (plLayerTex*)owner;
if(layer == NULL) return;
IParamBlock2 *pb = layer->GetParamBlockByID(plLayerTex::kBlkBitmap);
switch (id)
{
case kBmpBitmap:
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpBitmap);
// Update the bitmap saved by the layer
//layer->SetBitmap(&val.bm->bi, tabIndex);
break;
/*
case kBmpFilename:
bmt->SetMapName(val.s);
break;
case kBmpFiltering:
bmt->filterType = val.i;
if (bmt->thebm)
bmt->thebm->SetFilter(bmFilterType(val.i));
break;
*/
case kBmpClipU:
{
float u = val.f;
float w = pb->GetFloat(kBmpClipW, t);
if (u + w > 1.0f)
{
pb->SetValue(kBmpClipW, t, 1.0f-u);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipW);
}
break;
}
case kBmpClipW:
{
float w = val.f;
float u = pb->GetFloat(kBmpClipU, t);
if (u + w > 1.0f)
{
pb->SetValue(kBmpClipU, t, 1.0f-w);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipU);
}
break;
}
case kBmpClipV:
{
float v = val.f;
float h = pb->GetFloat(kBmpClipH, t);
if (v + h > 1.0f)
{
pb->SetValue(kBmpClipH, t, 1.0f-v);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipH);
}
break;
}
case kBmpClipH:
{
float h = val.f;
float v = pb->GetFloat(kBmpClipV, t);
if (v + h > 1.0f)
{
pb->SetValue(kBmpClipV, t, 1.0f-h);
if (pb->GetMap())
pb->GetMap()->Invalidate(kBmpClipV);
}
break;
}
case kBmpDetailStartSize:
case kBmpDetailStopSize:
case kBmpDetailStartOpac:
case kBmpDetailStopOpac:
if( pb != NULL )
{
if( IIsProcSettingDetailValues( pb ) )
break; // Ignore, since we're the ones setting 'em
HWND dlg = pb->GetMap()->GetHWnd();
plDetailCurveCtrl *ctrl = GET_DETAIL_CURVE_CTRL( dlg, IDC_DETAIL_CURVE_CTRL );
if( ctrl != NULL )
{
if( id == kBmpDetailStartSize || id == kBmpDetailStartOpac )
ctrl->SetStartPoint( (float)pb->GetInt( kBmpDetailStartSize, t ) / 100.f,
(float)pb->GetInt( kBmpDetailStartOpac, t ) / 100.f );
else
ctrl->SetEndPoint( (float)pb->GetInt( kBmpDetailStopSize, t ) / 100.f,
(float)pb->GetInt( kBmpDetailStopOpac, t ) / 100.f );
}
// Make sure start is less than end
if( id == kBmpDetailStartSize )
{
int end = pb->GetInt( kBmpDetailStopSize, t );
if( val.i > end )
pb->SetValue( kBmpDetailStopSize, t, val.i );
}
else if( id == kBmpDetailStopSize )
{
int start = pb->GetInt( kBmpDetailStartSize, t );
if( val.i < start )
pb->SetValue( kBmpDetailStartSize, t, val.i );
}
}
break;
case kBmpUseDetail:
if( pb != NULL )
{
HWND dlg = pb->GetMap()->GetHWnd();
EnableWindow( GetDlgItem( dlg, IDC_DETAIL_CURVE_CTRL ), (BOOL)val.i );
}
break;
}
}
void Get(PB2Value& v, ReferenceMaker* owner, ParamID id, int tabIndex, TimeValue t, Interval &valid)
{
}
// Gotta love hacks....
bool IIsProcSettingDetailValues( IParamBlock2 *pb );
};
static BMTexPBAccessor bmtex_accessor;
//=========================================================================================
// BMCropper
//=========================================================================================
class BMCropper : public CropCallback
{
IParamBlock2 *fPBlock;
public:
BMCropper(IParamBlock2* pblock) : fPBlock(pblock) {}
float GetInitU() { return fPBlock->GetFloat(kBmpClipU); }
float GetInitV() { return fPBlock->GetFloat(kBmpClipV); }
float GetInitW() { return fPBlock->GetFloat(kBmpClipW); }
float GetInitH() { return fPBlock->GetFloat(kBmpClipH); }
BOOL GetInitMode() { return fPBlock->GetInt(kBmpCropPlace); }
void SetValues(float u, float v, float w, float h, BOOL md);
void OnClose();
};
void BMCropper::SetValues(float u, float v, float w, float h, BOOL md)
{
TimeValue t = GetCOREInterface()->GetTime();
if (u != fPBlock->GetFloat(kBmpClipU, t))
{
fPBlock->SetValue(kBmpClipU, t, u);
fPBlock->GetMap()->Invalidate(kBmpClipU);
}
if (v != fPBlock->GetFloat(kBmpClipV, t))
{
fPBlock->SetValue(kBmpClipV, t, v);
fPBlock->GetMap()->Invalidate(kBmpClipV);
}
if (w != fPBlock->GetFloat(kBmpClipW, t))
{
fPBlock->SetValue(kBmpClipW, t, w);
fPBlock->GetMap()->Invalidate(kBmpClipW);
}
if (h != fPBlock->GetFloat(kBmpClipH, t))
{
fPBlock->SetValue(kBmpClipH, t, h);
fPBlock->GetMap()->Invalidate(kBmpClipH);
}
if (md != fPBlock->GetInt(kBmpCropPlace))
{
fPBlock->SetValue(kBmpCropPlace, t, md);
fPBlock->GetMap()->Invalidate(kBmpCropPlace);
}
}
void BMCropper::OnClose()
{
delete this;
}
class BitmapDlgProc : public ParamMap2UserDlgProc
{
friend class BMTexPBAccessor;
PBBitmap *fLastBMap;
bool fSettingDetailValues;
/// Called to update the controls of the dialog
/// Note: we're bad that we use a static here, but
virtual void Update( TimeValue t, Interval &valid, IParamMap2 *map )
{
ICustButton *bmSelectBtn;
IParamBlock2 *pblock;
int width, height;
ParamMap2UserDlgProc::Update( t, valid, map );
if( fSettingDetailValues )
{
// We're getting an update just because we changed detail values, so we
// know we don't have to do anything ourselves
return;
}
pblock = map->GetParamBlock();
// Update texture map button
bmSelectBtn = GetICustButton( GetDlgItem( map->GetHWnd(), IDC_LAYER_NAME ) );
PBBitmap *pbbm = pblock->GetBitmap( kBmpBitmap, t );
if( pbbm )
{
if( pbbm != fLastBMap )
{
bmSelectBtn->SetText( (TCHAR *)pbbm->bi.Filename() );
// Init values for clamping spinners to powers of 2
width = IFloorPow2( pbbm->bi.Width() );
map->SetRange( kBmpExportWidth, 4.f, (float)width );
height = IFloorPow2( pbbm->bi.Height() );
map->SetRange( kBmpExportHeight, 4.f, (float)height );
IClampTexSizeSpinner( t, map, true );
ISetDetailCurveNumLevels( map, t );
}
}
else if( pbbm != fLastBMap )
bmSelectBtn->SetText( _T( "None" ) );
fLastBMap = pbbm;
ReleaseICustButton( bmSelectBtn );
// Update detail curve control
HWND dlg = map->GetHWnd();
plDetailCurveCtrl *ctrl = GET_DETAIL_CURVE_CTRL( dlg, IDC_DETAIL_CURVE_CTRL );
if( ctrl == NULL )
{
// The control hasn't been created, so create it already!
HWND basis;
RECT r;
// Create the detail map control
basis = GetDlgItem( dlg, IDC_DETAIL_SAMPLE );
GetClientRect( basis, &r );
MapWindowPoints( basis, dlg, (POINT *)&r, 2 );
ctrl = TRACKED_NEW plDetailCurveCtrl( dlg, IDC_DETAIL_CURVE_CTRL, &r );
}
EnableWindow( GetDlgItem( dlg, IDC_DETAIL_CURVE_CTRL ), (BOOL)pblock->GetInt( kBmpUseDetail, t ) );
if( ctrl != NULL )
{
ctrl->SetStartPoint( (float)pblock->GetInt( kBmpDetailStartSize, t ) / 100.f,
(float)pblock->GetInt( kBmpDetailStartOpac, t ) / 100.f );
ctrl->SetEndPoint( (float)pblock->GetInt( kBmpDetailStopSize, t ) / 100.f,
(float)pblock->GetInt( kBmpDetailStopOpac, t ) / 100.f );
}
}
BOOL DlgProc(TimeValue t, IParamMap2 *map, HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
{
static ICustButton* bmSelectBtn;
switch (msg)
{
case WM_INITDIALOG:
fLastBMap = NULL;
fSettingDetailValues = false;
break;
/// Note: the following *could* be done in the accessor, except that you end up in an
/// infinite loop updating the values. Not good.
case CC_SPINNER_CHANGE:
if( LOWORD( wParam ) == IDC_EXPORTWIDTH_SPINNER )
IClampTexSizeSpinner( t, map, true );
else if( LOWORD( wParam ) == IDC_EXPORTHEIGHT_SPINNER )
IClampTexSizeSpinner( t, map, false );
break;
// Message from the detail curve that a point got dragged
case PL_DC_POINT_DRAGGED:
{
plDetailCurveCtrl *ctrl = (plDetailCurveCtrl *)lParam;
IParamBlock2 *pblock = map->GetParamBlock();
float x, y;
fSettingDetailValues = true;
if( wParam == PL_DC_START_POINT )
{
ctrl->GetStartPoint( x, y );
pblock->SetValue( kBmpDetailStartSize, t, (int)( x * 100.f ) );
pblock->SetValue( kBmpDetailStartOpac, t, (int)( y * 100.f ) );
}
else
{
ctrl->GetEndPoint( x, y );
pblock->SetValue( kBmpDetailStopSize, t, (int)( x * 100.f ) );
pblock->SetValue( kBmpDetailStopOpac, t, (int)( y * 100.f ) );
}
map->UpdateUI( t );
fSettingDetailValues = false;
}
return 0;
case WM_COMMAND:
if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_EXPORTWIDTH )
IClampTexSizeSpinner( t, map, true );
else if( HIWORD( wParam ) == EN_CHANGE && LOWORD( wParam ) == IDC_EXPORTHEIGHT )
IClampTexSizeSpinner( t, map, false );
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_BM_CROP_IMAGE)
{
IParamBlock2 *pblock = map->GetParamBlock();
PBBitmap *pbbm = pblock->GetBitmap(kBmpBitmap, t);
if (pbbm)
{
if (!pbbm->bm)
pbbm->bm = TheManager->Load(&pbbm->bi);
BMCropper *cropper = TRACKED_NEW BMCropper(pblock);
pbbm->bm->Display("Specify Cropping/Placement", BMM_CN, FALSE, TRUE, cropper);
}
// bm->DeleteThis();
return TRUE;
}
else if (HIWORD(wParam) == BN_CLICKED && LOWORD(wParam) == IDC_LAYER_RELOAD)
{
// TEMP
IParamBlock2 *pblock = map->GetParamBlock();
PBBitmap *pbbm = pblock->GetBitmap(kBmpBitmap, t);
if (pbbm)
{
plLayerTex *layer = (plLayerTex*)map->GetParamBlock()->GetOwner();
layer->RefreshBitmaps();
layer->fMtlParams->MtlChanged();
layer->IChanged();
}
return TRUE;
}
else if (LOWORD(wParam) == IDC_LAYER_NAME)
{
plPlasmaMAXLayer *layer = (plPlasmaMAXLayer *)map->GetParamBlock()->GetOwner();
if (layer == nil)
return FALSE;
BOOL selectedNewBitmap = layer->HandleBitmapSelection();
if(selectedNewBitmap)
{
IParamBlock2 *pblock = map->GetParamBlock();
//plLayerTex *layer = (plLayerTex*)map->GetParamBlock()->GetOwner();
//layer->SetBitmap(&bi);
//layer->IChanged();
//BitmapInfo *bi = &layer->GetPBBitmap()->bi;
bmSelectBtn = GetICustButton(GetDlgItem(hWnd,IDC_LAYER_NAME));
PBBitmap *pbbm = layer->GetPBBitmap();
bmSelectBtn->SetText(pbbm != nil ? (TCHAR*)pbbm->bi.Filename() : "");
ReleaseICustButton(bmSelectBtn);
if (pbbm != nil)
{
// Init values for clamping spinners to powers of 2
int width = IFloorPow2( pbbm->bi.Width() );
map->SetRange( kBmpExportWidth, 4.f, (float)width );
int height = IFloorPow2( pbbm->bi.Height() );
map->SetRange( kBmpExportHeight, 4.f, (float)height );
if( width > 512 )
{
height = (int)( 512.f * (float)( (float)height / (float)width ) );
width = 512;
}
else if( height > 512 )
{
width = (int)( 512.f * (float)( (float)width / (float)height ) );
height = 512;
}
pblock->SetValue( kBmpExportWidth, t, width );
pblock->SetValue( kBmpExportLastWidth, t, width );
pblock->SetValue( kBmpExportHeight, t, height );
pblock->SetValue( kBmpExportLastHeight, t, height );
IClampTexSizeSpinner( t, map, true );
}
return TRUE;
}
else
{
return FALSE;
}
}
break;
}
return FALSE;
}
void DeleteThis() {};
void ISetDetailCurveNumLevels( IParamMap2 *map, TimeValue t )
{
/// Set the level count on the detail control
plDetailCurveCtrl *ctrl = GET_DETAIL_CURVE_CTRL( map->GetHWnd(), IDC_DETAIL_CURVE_CTRL );
if( ctrl != NULL )
{
IParamBlock2 *pblock = map->GetParamBlock();
int w = pblock->GetInt( kBmpExportWidth, t );
int h = pblock->GetInt( kBmpExportHeight, t );
int numLevels = 0;
while( w > 1 && h > 1 )
{
w >>= 1;
h >>= 1;
numLevels++;
}
ctrl->SetNumLevels( numLevels );
}
}
/// Clamp texture sizes to a power of 2
void IClampTexSizeSpinner( TimeValue t, IParamMap2 *map, bool clampWidth )
{
IParamBlock2 *pblock = map->GetParamBlock();
ParamID clampNew, clampOld;
ParamID otherNew, otherOld;
if( clampWidth )
{
clampNew = kBmpExportWidth; clampOld = kBmpExportLastWidth;
otherNew = kBmpExportHeight; otherOld = kBmpExportLastHeight;
}
else
{
clampNew = kBmpExportHeight; clampOld = kBmpExportLastHeight;
otherNew = kBmpExportWidth; otherOld = kBmpExportLastWidth;
}
int lastVal = pblock->GetInt( clampOld, t );
int tempVal, newVal = pblock->GetInt( clampNew, t );
if( newVal < lastVal )
{
lastVal = newVal;
for( tempVal = 1; tempVal <= newVal; tempVal <<= 1 );
newVal = tempVal >> 1;
}
else
{
lastVal = newVal;
for( tempVal = 1; tempVal < newVal; tempVal <<= 1 );
newVal = tempVal;
}
pblock->SetValue( clampNew, t, newVal );
pblock->SetValue( clampOld, t, newVal );
// And clamp aspect ratio
PBBitmap *pbbm = pblock->GetBitmap( kBmpBitmap, t );
if( pbbm != NULL )
{
int realWidth = pbbm->bi.Width();
int realHeight = pbbm->bi.Height();
float aspect;
if( clampWidth )
aspect = (float)realHeight / (float)realWidth;
else
aspect = (float)realWidth / (float)realHeight;
int value = newVal;
value *= aspect;
if( value < 4 )
{
// Can't be below 4!
value = 4;
pblock->SetValue( otherNew, t, value );
pblock->SetValue( otherOld, t, value );
value = value / aspect;
pblock->SetValue( clampNew, t, value );
pblock->SetValue( clampOld, t, value );
}
else
{
pblock->SetValue( otherNew, t, value );
pblock->SetValue( otherOld, t, value );
}
}
ISetDetailCurveNumLevels( map, t );
}
int IFloorPow2( int value )
{
int v;
for( v = 1; v <= value; v <<= 1 );
return v >> 1;
}
};
static BitmapDlgProc gBitmapDlgProc;
// Gotta love hacks....
bool BMTexPBAccessor::IIsProcSettingDetailValues( IParamBlock2 *pb )
{
BitmapDlgProc *proc = (BitmapDlgProc *)pb->GetMap()->GetUserDlgProc();
if( proc != NULL )
return proc->fSettingDetailValues;
return false;
}
#endif