/**********************************************************************
 *<
	FILE: edmui.cpp

	DESCRIPTION:  Edit Mesh OSM	UI code

	CREATED BY: Rolf Berteig

	HISTORY: created 1 September, 1995

 *>	Copyright (c) 1994, All Rights Reserved.
 **********************************************************************/
#include "mods.h"
#include "editmesh.h"
#include "units.h"

// in mods.cpp
extern HINSTANCE hInstance;

static HIMAGELIST hFaceImages = NULL;

static float weldThresh     = 0.1f;
static BOOL affectRegion    = FALSE;
static BOOL ignoreBack      = TRUE;
static float lastFaceThresh = 90.0f;
static float lastExpThresh  = 24.0f;
static float lastTens       = 25.0f;
static BOOL expObj          = TRUE;
static BOOL edgeTes         = TRUE;
static int sbmParams[2]     = {1,1};
static DWORD sbsParams[3]   = {1,1,0};
static float lastEdgeThresh = 30.0f;

void ResetEditMeshUI()
	{
	weldThresh     = 0.1f;
	affectRegion   = FALSE;
	ignoreBack     = TRUE;
	lastFaceThresh = 90.0f;
	lastExpThresh  = 24.0f;
	lastTens       = 25.0f;
	expObj         = TRUE;
	edgeTes        = TRUE;
	sbmParams[0]   = 1;
	sbmParams[1]   = 1;
	sbsParams[0]   = 1;
	sbsParams[1]   = 1;
	sbsParams[2]   = 0;
	lastEdgeThresh = 30.0f;
	}

void EditMeshMod::SetSelType(int type)
	{	
	int old = selType;
	selType = type;
	switch (type) {
		case SELTYPE_SINGLE:
			iSingle->SetCheck(TRUE);
			iPoly->SetCheck(FALSE);
			iElement->SetCheck(FALSE);
			break;
		case SELTYPE_POLY:
			iSingle->SetCheck(FALSE);
			iPoly->SetCheck(TRUE);
			iElement->SetCheck(FALSE);
			break;
		case SELTYPE_ELEMENT:
			iSingle->SetCheck(FALSE);
			iPoly->SetCheck(FALSE);
			iElement->SetCheck(TRUE);
			break;
		}
	if (old != selType) {
		NotifyDependents(FOREVER, PART_DISPLAY, REFMSG_CHANGE);
		UpdateWindow(hEditMeshParams);
		iObjParams->RedrawViews(iObjParams->GetTime(),REDRAW_NORMAL);
		}
	}

void LoadImages()
	{
	if ( !hFaceImages ) {
		HBITMAP hBitmap, hMask;
		hFaceImages = ImageList_Create(16, 15, TRUE, 3, 0);
		hBitmap     = LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_FACESELTYPES));
		hMask       = LoadBitmap(hInstance,MAKEINTRESOURCE(IDB_MASK_FACESELTYPES));
		ImageList_Add(hFaceImages,hBitmap,hMask);
		DeleteObject(hBitmap);
		DeleteObject(hMask);
		}
	}	

void EditMeshMod::SetRollupPage(IObjParam *ip)
	{
	EndNormalMove(ip->GetTime());
	if (hEditMeshParams) {
		RemoveRollupPage(ip);
		}
	hEditMeshParams = ip->AddRollupPage( 
			hInstance, 
			MAKEINTRESOURCE(meshDlg[selLevel]),
			meshDlgProc[selLevel],
			GetString(meshDlgString[selLevel]), 
			(LPARAM)this );		
	
	if (selLevel==EM_FACE) {
		hParam2 = ip->AddRollupPage( 
				hInstance, 
				MAKEINTRESOURCE(IDD_EMPARAM_SURFACE),
				SurfaceParamDlgProc,
				GetString(IDS_RB_EDITSURFACE), 
				(LPARAM)this);
		}	
	}

void EditMeshMod::RemoveRollupPage(IObjParam *ip)
	{
	if (hParam2) ip->DeleteRollupPage(hParam2);
	ip->DeleteRollupPage(hEditMeshParams);
	hEditMeshParams = NULL;				
	hParam2 = NULL;
	}

void EditMeshMod::BeginEditParams( IObjParam *ip, ULONG flags,Animatable *prev )
	{
	if (GetSystemSetting(SYSSET_ENABLE_EDITMESHMOD)) {
		iObjParams = ip;
		CreateMeshDataTempData();

		if ( !hEditMeshParams ) {
			SetRollupPage(ip);		
		} else {
			SetWindowLong( hEditMeshParams, GWL_USERDATA, (LONG)this );	
			}
		
		// Create sub object editing modes.
		moveMode       = new MoveModBoxCMode(this,ip);
		rotMode        = new RotateModBoxCMode(this,ip);
		uscaleMode     = new UScaleModBoxCMode(this,ip);
		nuscaleMode    = new NUScaleModBoxCMode(this,ip);
		squashMode     = new SquashModBoxCMode(this,ip);
		selectMode     = new SelectModBoxCMode(this,ip);
		extrudeMode    = new ExtrudeCMode(this,ip);
		createVertMode = new CreateVertCMode(this,ip);
		weldVertMode   = new WeldVertCMode(this,ip);
		attachObjMode  = new ObjAttachCMode(this,ip);
		attachPickMode = new AttachPickMode(this,ip);
		buildFaceMode  = new BuildFaceCMode(this,ip);
		divideEdgeMode = new DivideEdgeCMode(this,ip);
		turnEdgeMode   = new TurnEdgeCMode(this,ip);

		// Add our sub object type
		TSTR type1( GetString(IDS_RB_VERTEX) );
		TSTR type2( GetString(IDS_RB_FACE) );
		TSTR type3( GetString(IDS_RB_EDGE) );
		const TCHAR *ptype[] = { type1, type2, type3 };
		ip->RegisterSubObjectTypes( ptype, 3 );

		// Restore the selection level.
		ip->SetSubObjectLevel(selLevel);
		
		// We want del key input if in sub object selection
		if (selLevel!=0) {
			delEvent.SetEditMeshMod(this);
			iObjParams->RegisterDeleteUser(&delEvent);
			}	

		// Disable show end result.
		ip->EnableShowEndResult(FALSE);

		TimeValue t = ip->GetTime();
		NotifyDependents(Interval(t,t), PART_ALL, REFMSG_BEGIN_EDIT);
		NotifyDependents(Interval(t,t), PART_ALL, REFMSG_MOD_DISPLAY_ON);
		SetAFlag(A_MOD_BEING_EDITED);	
		}
	}
		


void EditMeshMod::EndEditParams( IObjParam *ip, ULONG flags,Animatable *next )
	{
	if (GetSystemSetting(SYSSET_ENABLE_EDITMESHMOD)) {
		EndNormalMove(ip->GetTime());

		// Unregister del key notification
		if (selLevel!=0) {
			iObjParams->UnRegisterDeleteUser(&delEvent);
			}

		if ( flags&END_EDIT_REMOVEUI ) {
			RemoveRollupPage(ip);
		} else {		
			SetWindowLong( hEditMeshParams, GWL_USERDATA, 0 );		
			}

		// Enable show end result
		ip->EnableShowEndResult(TRUE);

		if ( ip->GetCommandMode()->ID() == CID_EXTRUDE ) {
			ip->SetStdCommandMode( CID_OBJMOVE );
			}

		TimeValue t = ip->GetTime();
		NotifyDependents(Interval(t,t), PART_ALL, REFMSG_END_EDIT);
		NotifyDependents(Interval(t,t), PART_ALL, REFMSG_MOD_DISPLAY_OFF);
		ClearAFlag(A_MOD_BEING_EDITED);
		
		DeleteMeshDataTempData();
		iObjParams = NULL;
		
		ip->DeleteMode(moveMode);
		ip->DeleteMode(rotMode);
		ip->DeleteMode(uscaleMode);
		ip->DeleteMode(nuscaleMode);
		ip->DeleteMode(squashMode);
		ip->DeleteMode(selectMode);
		ip->DeleteMode(extrudeMode);
		ip->DeleteMode(createVertMode);	
		ip->DeleteMode(weldVertMode);	
		ip->DeleteMode(attachObjMode);		
		ip->DeleteMode(buildFaceMode);	
		ip->DeleteMode(divideEdgeMode);	
		ip->DeleteMode(turnEdgeMode);	
		ip->ClearPickMode();
		if (attachPickMode) delete attachPickMode;
		attachPickMode = NULL;
		if ( moveMode ) delete moveMode;
		moveMode = NULL;
		if ( rotMode ) delete rotMode;
		rotMode = NULL;
		if ( uscaleMode ) delete uscaleMode;
		uscaleMode = NULL;
		if ( nuscaleMode ) delete nuscaleMode;
		nuscaleMode = NULL;
		if ( squashMode ) delete squashMode;
		squashMode = NULL;
		if ( selectMode ) delete selectMode;
		selectMode = NULL;
		if( extrudeMode ) delete extrudeMode;
		extrudeMode = NULL;
		if (createVertMode) delete createVertMode;
		createVertMode = NULL;
		if (weldVertMode) delete weldVertMode;
		weldVertMode = NULL;
		if (attachObjMode) delete attachObjMode;
		attachObjMode = NULL;
		if (buildFaceMode) delete buildFaceMode;
		buildFaceMode = NULL;
		if (divideEdgeMode) delete divideEdgeMode;
		divideEdgeMode = NULL;
		if (turnEdgeMode) delete turnEdgeMode;
		turnEdgeMode = NULL;
		}
	}

#define GRAPHSTEPS 20

static void DrawCurve(HWND hWnd,HDC hdc)
	{
	float pinch, falloff, bubble;
	ISpinnerControl *spin = 
		GetISpinner(GetDlgItem(hWnd,IDC_FALLOFFSPIN));
	falloff = spin->GetFVal();
	ReleaseISpinner(spin);	

	spin = GetISpinner(GetDlgItem(hWnd,IDC_PINCHSPIN));
	pinch = spin->GetFVal();
	ReleaseISpinner(spin);

	spin = GetISpinner(GetDlgItem(hWnd,IDC_BUBBLESPIN));
	bubble = spin->GetFVal();
	ReleaseISpinner(spin);	

	TSTR label = FormatUniverseValue(falloff);
	SetWindowText(GetDlgItem(hWnd,IDC_FARLEFTLABEL),label);
	SetWindowText(GetDlgItem(hWnd,IDC_FARRIGHTLABEL),label);

	Rect rect, orect;
	GetClientRectP(GetDlgItem(hWnd,IDC_AR_GRAPH),&rect);
	orect = rect;

	SelectObject(hdc,GetStockObject(NULL_PEN));
	SelectObject(hdc,GetStockObject(WHITE_BRUSH));
	Rectangle(hdc,rect.left,rect.top,rect.right,rect.bottom);	
	SelectObject(hdc,GetStockObject(NULL_BRUSH));
	
	rect.left   += 3;
	rect.right  -= 3;
	rect.top    += 20;
	rect.bottom -= 20;
	
	SelectObject(hdc,CreatePen(PS_DOT,0,GetSysColor(COLOR_BTNFACE)));
	MoveToEx(hdc,orect.left,rect.top,NULL);
	LineTo(hdc,orect.right,rect.top);
	MoveToEx(hdc,orect.left,rect.bottom,NULL);
	LineTo(hdc,orect.right,rect.bottom);
	MoveToEx(hdc,(rect.left+rect.right)/2,orect.top,NULL);
	LineTo(hdc,(rect.left+rect.right)/2,orect.bottom);
	DeleteObject(SelectObject(hdc,GetStockObject(BLACK_PEN)));
	
	MoveToEx(hdc,rect.left,rect.bottom,NULL);
	for (int i=0; i<=GRAPHSTEPS; i++) {
		float dist = falloff * float(abs(i-GRAPHSTEPS/2))/float(GRAPHSTEPS/2);		
		float y = AffectRegionFunction(dist,falloff,pinch,bubble);
		int ix = rect.left + int(float(rect.w()-1) * float(i)/float(GRAPHSTEPS));
		int	iy = rect.bottom - int(y*float(rect.h()-2)) - 1;
		if (iy<orect.top) iy = orect.top;
		if (iy>orect.bottom-1) iy = orect.bottom-1;
		LineTo(hdc, ix, iy);
		}
	
	WhiteRect3D(hdc,orect,TRUE);
	}

BOOL CALLBACK AffectRegionDlgProc(
		HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
	EditMeshMod *em = (EditMeshMod*)GetWindowLong(hWnd,GWL_USERDATA);

	switch (msg) {
		case WM_INITDIALOG: {
			em = (EditMeshMod*)lParam;
			SetWindowLong(hWnd,GWL_USERDATA,lParam);

			ISpinnerControl *spin = 
				GetISpinner(GetDlgItem(hWnd,IDC_FALLOFFSPIN));
			spin->SetLimits(0.001f,9999999.0f, FALSE);
			spin->SetAutoScale();
			spin->LinkToEdit(GetDlgItem(hWnd,IDC_FALLOFF), EDITTYPE_POS_UNIVERSE);
			spin->SetValue(em->falloff,FALSE);
			ReleaseISpinner(spin);
			
			spin = GetISpinner(GetDlgItem(hWnd,IDC_PINCHSPIN));
			spin->SetLimits(-10.0f,10.0f, FALSE);
			spin->SetScale(0.01f);
			spin->LinkToEdit(GetDlgItem(hWnd,IDC_PINCH), EDITTYPE_FLOAT);
			spin->SetValue(em->pinch,FALSE);
			ReleaseISpinner(spin);
			
			spin = GetISpinner(GetDlgItem(hWnd,IDC_BUBBLESPIN));
			spin->SetLimits(-10.0f,10.0f, FALSE);
			spin->SetScale(0.01f);
			spin->LinkToEdit(GetDlgItem(hWnd,IDC_BUBBLE), EDITTYPE_FLOAT);
			spin->SetValue(em->bubble,FALSE);
			ReleaseISpinner(spin);
						
			TSTR zero = FormatUniverseValue(0.0f);
			SetWindowText(GetDlgItem(hWnd,IDC_NEARLABEL),zero);

			ShowWindow(GetDlgItem(hWnd,IDC_AR_GRAPH),SW_HIDE);
			CenterWindow(hWnd,GetParent(hWnd));
			break;
			}
		
		case WM_PAINT: {
			PAINTSTRUCT ps;
			HDC hdc = BeginPaint(hWnd,&ps);
			DrawCurve(hWnd,hdc);
			EndPaint(hWnd,&ps);
			break;
			}
			
		case CC_SPINNER_CHANGE:	{
			Rect rect;
			GetClientRectP(GetDlgItem(hWnd,IDC_AR_GRAPH),&rect);
			InvalidateRect(hWnd,&rect,FALSE);
			break;
			}

		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDOK: {
					ISpinnerControl *spin = 
						GetISpinner(GetDlgItem(hWnd,IDC_FALLOFFSPIN));
					em->falloff = spin->GetFVal();
					ReleaseISpinner(spin);

					spin = GetISpinner(GetDlgItem(hWnd,IDC_PINCHSPIN));
					em->pinch = spin->GetFVal();
					ReleaseISpinner(spin);

					spin = GetISpinner(GetDlgItem(hWnd,IDC_BUBBLESPIN));
					em->bubble = spin->GetFVal();
					ReleaseISpinner(spin);

					EndDialog(hWnd,1);
					break;
					}

				case IDCANCEL:
					EndDialog(hWnd,0);
					break;
				}
			break;

		default:
			return FALSE;
		}
	return TRUE;
	}


static BOOL CALLBACK DetachDlgProc(
		HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
	static TSTR *name = NULL;

	switch (msg) {
		case WM_INITDIALOG:
			name = (TSTR*)lParam;
			SetWindowText(
				GetDlgItem(hWnd,IDC_DETACH_NAME),
				name->data());
			CenterWindow(hWnd,GetParent(hWnd));
			SetFocus(GetDlgItem(hWnd,IDC_DETACH_NAME));
			SendMessage(GetDlgItem(hWnd,IDC_DETACH_NAME),
				EM_SETSEL,0,-1);
			return FALSE;

		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDOK:
					name->Resize(
						GetWindowTextLength(GetDlgItem(hWnd,IDC_DETACH_NAME))+1);
					GetWindowText(
						GetDlgItem(hWnd,IDC_DETACH_NAME),
						name->data(),
						name->length()+1);
					EndDialog(hWnd,1);
					break;

				case IDCANCEL:
					EndDialog(hWnd,0);
					break;
				}
			break;

		default:
			return 0;
		}
	return 1;
	}


BOOL CALLBACK ObjectParamDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
	{
	EditMeshMod *em = (EditMeshMod *)GetWindowLong( hDlg, GWL_USERDATA );
	if ( !em && message != WM_INITDIALOG ) return FALSE;
	
	switch ( message ) {
		case WM_INITDIALOG: {
		 	em = (EditMeshMod *)lParam;
		 	SetWindowLong( hDlg, GWL_USERDATA, (LONG)em );		 	
		 	
		 	ICustButton *but = GetICustButton(GetDlgItem(hDlg,IDC_OBJ_ATTACH));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);
		 	break;
			}

		case WM_DESTROY:
			em->iObjParams->DeleteMode(em->attachObjMode);
			em->iObjParams->ClearPickMode();
			break;
		
		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_MOUSEMOVE:   			
   			em->iObjParams->RollupMouseMessage(hDlg,message,wParam,lParam);
			break;
		
		case WM_COMMAND:			
			switch ( LOWORD(wParam) ) {				
				case IDC_OBJ_ATTACH:
					//em->iObjParams->SetCommandMode(em->attachObjMode);
					em->iObjParams->SetPickMode(em->attachPickMode);
					break;
				}
			break;
		
		default:
			return 0;
		}
	
	return TRUE;
	}

BOOL GetDetachObjectName(HWND hDlg,TSTR &name,Interface *ip)
	{
	ModContextList mcList;	
	INodeTab nodes;	
	ip->GetModContexts(mcList,nodes);
	name = nodes[0]->GetName();
	ip->MakeNameUnique(name);
	nodes.DisposeTemporary();
	//name = GetString(IDS_RB_OBJECT);	

	if (DialogBoxParam(
		hInstance, 
		MAKEINTRESOURCE(IDD_DETACH),
		hDlg, 
		DetachDlgProc,						
		(LPARAM)&name)) {
		return TRUE;
	} else {
		return FALSE;
		}
	}

BOOL CALLBACK VertexParamDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
	{
	EditMeshMod *em = (EditMeshMod *)GetWindowLong( hDlg, GWL_USERDATA );
	if ( !em && message != WM_INITDIALOG ) return FALSE;
	
	switch ( message ) {
		case WM_INITDIALOG: {
		 	em = (EditMeshMod *)lParam;
		 	SetWindowLong( hDlg, GWL_USERDATA, (LONG)em );		 	
		 	
			ICustButton *but = GetICustButton(GetDlgItem(hDlg,IDC_VERT_CREATE));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);

			but = GetICustButton(GetDlgItem(hDlg,IDC_VERT_WELDTOVERT));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);			

			ISpinnerControl *spin = 
				GetISpinner(GetDlgItem(hDlg,IDC_WELDTHRESHSPIN));
			spin->SetLimits(0,9999999, FALSE);
			spin->SetAutoScale();
			spin->LinkToEdit(GetDlgItem(hDlg,IDC_WELDTHRESH), EDITTYPE_POS_UNIVERSE);
			spin->SetValue(weldThresh,FALSE);
			ReleaseISpinner(spin);
			
			if (affectRegion) {
				CheckDlgButton(hDlg,IDC_AFFECTREGION,TRUE);
			} else {
				EnableWindow(GetDlgItem(hDlg,IDC_BACKFACE_VERTS),FALSE);
				}
			if (ignoreBack) {
				CheckDlgButton(hDlg,IDC_BACKFACE_VERTS,TRUE);
				}
		 	return TRUE;
			}

		case WM_DESTROY: {			
			ISpinnerControl *spin = 
				GetISpinner(GetDlgItem(hDlg,IDC_WELDTHRESHSPIN));
			weldThresh = spin->GetFVal();
			ReleaseISpinner(spin);
			em->iObjParams->DeleteMode(em->createVertMode);
			em->iObjParams->DeleteMode(em->weldVertMode);
			affectRegion = IsDlgButtonChecked(hDlg,IDC_AFFECTREGION);
			ignoreBack   = IsDlgButtonChecked(hDlg,IDC_BACKFACE_VERTS);
			return FALSE;
			}
		
		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_MOUSEMOVE:   			
   			em->iObjParams->RollupMouseMessage(hDlg,message,wParam,lParam);
			return FALSE;		
		
		case WM_COMMAND:			
			switch ( LOWORD(wParam) ) {				
				case IDC_AFFECTREGION:
					if (IsDlgButtonChecked(hDlg,IDC_AFFECTREGION)) {
						EnableWindow(GetDlgItem(hDlg,IDC_BACKFACE_VERTS),TRUE);
					} else {
						EnableWindow(GetDlgItem(hDlg,IDC_BACKFACE_VERTS),FALSE);
						}
					break;

				case IDC_VERT_DELETE:
					em->DeleteKey();
					break;
				
				case IDC_VERT_COLLAPSE:
					em->WeldVerts(0.0f,WELD_COLLAPSE);
					break;

				case IDC_VERT_DETACH: {
					TSTR name;					
					if (GetDetachObjectName(hDlg,name,em->iObjParams)) {
						em->DetachVertFaces(name,FALSE);
						}
					break;
					}

				case IDC_VERT_WELD:	{
					ISpinnerControl *spin = 
						GetISpinner(GetDlgItem(hDlg,IDC_WELDTHRESHSPIN));
					if (!em->WeldVerts(
							spin->GetFVal(),
							WELD_THRESHOLD)) {
						TSTR buf1 = GetString(IDS_RB_NOVERTSTOWELD);
						TSTR buf2 = GetString(IDS_RB_WELDVERTS);
						MessageBox(hDlg,buf1,buf2,MB_OK|MB_TASKMODAL);
						}
					ReleaseISpinner(spin);
					break;
					}

				case IDC_VERT_CREATE:
					if (em->iObjParams->GetCommandMode()==em->createVertMode) {
						em->iObjParams->SetStdCommandMode(CID_OBJMOVE);
					} else {
						em->iObjParams->SetCommandMode(em->createVertMode);
						}
					break;

				case IDC_VERT_WELDTOVERT:
					if (em->iObjParams->GetCommandMode()==em->weldVertMode) {
						em->iObjParams->SetStdCommandMode(CID_OBJMOVE);
					} else {
						em->iObjParams->SetCommandMode(em->weldVertMode);
						}
					break;

				case IDC_EDITCURVE:
					DialogBoxParam(
						hInstance, 
						MAKEINTRESOURCE(IDD_AFFECTREGION),
						hDlg, 
						AffectRegionDlgProc,						
						(LPARAM)em);
					break;
				
				case IDC_VERT_HIDE:
					em->HideSelVerts();
					break;

				case IDC_VERT_UNHIDEALL:
					em->UnhideAllVerts();
					break;
				}
			break;
		}
	
	return FALSE;
	}

BOOL CALLBACK FaceParamDlgProc(
		HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam)
	{		
	EditMeshMod *em = (EditMeshMod *)GetWindowLong( hDlg, GWL_USERDATA );
	if ( !em && message != WM_INITDIALOG ) return FALSE;
	
	switch ( message ) {
		case WM_INITDIALOG: {
		 	LoadImages();
		 	em = (EditMeshMod *)lParam;
		 	SetWindowLong( hDlg, GWL_USERDATA, (LONG)em );		 	
		 	em->amountSpin = GetISpinner(GetDlgItem(hDlg,IDC_EXTRUDESPINNER));
			em->amountSpin->SetLimits( -999999, 999999, FALSE );
			em->amountSpin->LinkToEdit( GetDlgItem(hDlg,IDC_EXTRUDEAMOUNT), EDITTYPE_FLOAT );
			em->tensSpin = GetISpinner(GetDlgItem(hDlg,IDC_TENSIONSPINNER));
			em->tensSpin->SetLimits(-100,100, FALSE);
			em->tensSpin->LinkToEdit( GetDlgItem(hDlg,IDC_TENSION), EDITTYPE_FLOAT );		 	
		 	em->tensSpin->SetValue(lastTens,FALSE);
		 	em->planarSpin = GetISpinner(GetDlgItem(hDlg,IDC_PLANARSPINNER));
			em->planarSpin->SetLimits(0, 180, FALSE);
			em->planarSpin->SetScale(0.1f);
			em->planarSpin->LinkToEdit(GetDlgItem(hDlg,IDC_PLANAR), EDITTYPE_FLOAT);
		 	em->planarSpin->SetValue(lastFaceThresh,FALSE);

			ISpinnerControl *spin = GetISpinner(GetDlgItem(hDlg,IDC_ANGLETHRESHSPIN));
			spin->SetLimits(0, 180, FALSE);
			spin->SetScale(0.1f);
			spin->LinkToEdit(GetDlgItem(hDlg,IDC_ANGLETRESH), EDITTYPE_FLOAT);
		 	spin->SetValue(lastExpThresh,FALSE);
			ReleaseISpinner(spin);

			ICustButton *but = GetICustButton(GetDlgItem(hDlg,IDC_EXTRUDE));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);
		 	
			but = GetICustButton(GetDlgItem(hDlg,IDC_BUILDFACE));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);

		 	ICustToolbar *iToolbar = 
		 		GetICustToolbar(GetDlgItem(hDlg,IDC_SELTYPE));
			iToolbar->SetImage(hFaceImages);
			iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON,0,0,0,0,16,15,24,23,IDC_SELSINGLE));
			iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON,1,1,1,1,16,15,24,23,IDC_SELPOLY));
			iToolbar->AddTool(ToolButtonItem(CTB_CHECKBUTTON,2,2,2,1,16,15,24,23,IDC_SELELEMENT));
			em->iSingle  = iToolbar->GetICustButton(IDC_SELSINGLE);
			em->iPoly    = iToolbar->GetICustButton(IDC_SELPOLY);
			em->iElement = iToolbar->GetICustButton(IDC_SELELEMENT);
			ReleaseICustToolbar(iToolbar);
		 	em->SetSelType(em->selType);

			if (expObj) {
				CheckDlgButton(hDlg,IDC_EXP_OBJECTS,TRUE);
				CheckDlgButton(hDlg,IDC_EXP_ELEMENTS,FALSE);
			} else {
				CheckDlgButton(hDlg,IDC_EXP_OBJECTS,FALSE);
				CheckDlgButton(hDlg,IDC_EXP_ELEMENTS,TRUE);
				}

			if (edgeTes) {
				CheckDlgButton(hDlg,IDC_TES_EDGE,TRUE);
				CheckDlgButton(hDlg,IDC_TES_CENTER,FALSE);
			} else {
				CheckDlgButton(hDlg,IDC_TES_EDGE,FALSE);
				CheckDlgButton(hDlg,IDC_TES_CENTER,TRUE);
				em->tensSpin->Disable();
				EnableWindow(GetDlgItem(hDlg,IDC_TENSTEXT),FALSE);
				}

			CheckDlgButton(hDlg,IDC_SEL_BYVERT,em->selByVert);
		 	return TRUE;
			}

		case WM_DESTROY: {
			lastTens = em->tensSpin->GetFVal();

			if ( em->amountSpin ) {
				ReleaseISpinner(em->amountSpin);
				em->amountSpin = NULL;
				}
			if ( em->tensSpin ) {
				ReleaseISpinner(em->tensSpin);
				em->tensSpin = NULL;
				}
			if ( em->iSingle ) {
				ReleaseICustButton(em->iSingle);
				em->iSingle = NULL;
				}
			if ( em->iPoly ) {
				ReleaseICustButton(em->iPoly);
				em->iPoly = NULL;
				}
			if ( em->iElement ) {
				ReleaseICustButton(em->iElement);
				em->iElement = NULL;
				}
			if ( em->planarSpin ) {
				lastFaceThresh = em->planarSpin->GetFVal();
				ReleaseISpinner(em->planarSpin);
				}

			ISpinnerControl *spin = GetISpinner(GetDlgItem(hDlg,IDC_ANGLETHRESHSPIN));
			lastExpThresh = spin->GetFVal();
			ReleaseISpinner(spin);
			expObj  = IsDlgButtonChecked(hDlg,IDC_EXP_OBJECTS);
			edgeTes = IsDlgButtonChecked(hDlg,IDC_TES_EDGE);

			// Don't leave in extrude mode.
			em->iObjParams->DeleteMode(em->extrudeMode);
			em->iObjParams->DeleteMode(em->buildFaceMode);						
			return FALSE;
			}  
		
		case CC_SPINNER_BUTTONUP:
			switch (LOWORD(wParam)) {
				case IDC_EXTRUDESPINNER:
					em->EndNormalMove(em->iObjParams->GetTime(),TRUE);
					em->iObjParams->RedrawViews(
						em->iObjParams->GetTime(),REDRAW_END);					
					break;
				}
			break;

		case CC_SPINNER_CHANGE:
			switch ( LOWORD(wParam) ) {
				case IDC_EXTRUDESPINNER:
					if (!em->inNormalMove) {
						em->BeginNormalMove(em->iObjParams->GetTime());
						}
					
					em->NormalMove(
						em->iObjParams->GetTime(),
						em->amountSpin->GetFVal() );
					
					if (!HIWORD(wParam)) {
						// hit the enter key
						em->EndNormalMove(em->iObjParams->GetTime(),TRUE);
						em->iObjParams->RedrawViews(
							em->iObjParams->GetTime(),REDRAW_END);
					} else {
						em->iObjParams->RedrawViews(
							em->iObjParams->GetTime(),REDRAW_INTERACTIVE);
						}
					break;
				}
			break;

		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_MOUSEMOVE:   			
   			em->iObjParams->RollupMouseMessage(hDlg,message,wParam,lParam);
			return FALSE;		
		
		case WM_COMMAND:			
			switch ( LOWORD(wParam) ) {				
				case IDC_DELETEFACE:
					em->DeleteKey();
					break;

				case IDC_FACE_DETACH: {
					TSTR name;
					if (GetDetachObjectName(hDlg,name,em->iObjParams)) {
						em->DetachVertFaces(name,TRUE);
						}
					break;
					}

				case IDC_TES_EDGE:
				case IDC_TES_CENTER:
					if (IsDlgButtonChecked(hDlg,IDC_TES_EDGE)) {
						em->tensSpin->Enable();
						EnableWindow(GetDlgItem(hDlg,IDC_TENSTEXT),TRUE);
					} else {
						em->tensSpin->Disable();
						EnableWindow(GetDlgItem(hDlg,IDC_TENSTEXT),FALSE);
						}
					break;

				case IDC_BUILDFACE:
					if (em->iObjParams->GetCommandMode()==em->buildFaceMode) {
						em->iObjParams->SetStdCommandMode(CID_OBJMOVE);
					} else {
						em->iObjParams->SetCommandMode(em->buildFaceMode);
						}
					break;

				case IDC_SELSINGLE:
					em->SetSelType(SELTYPE_SINGLE);
					break;

				case IDC_SELPOLY:
					em->SetSelType(SELTYPE_POLY);
					break;

				case IDC_SELELEMENT:
					em->SetSelType(SELTYPE_ELEMENT);
					break;

				case IDC_SEL_BYVERT:
					em->selByVert = IsDlgButtonChecked(hDlg,IDC_SEL_BYVERT);
					break;

				case IDC_EXTRUDE:
					if (em->iObjParams->GetCommandMode()==em->extrudeMode) {
						em->iObjParams->SetStdCommandMode(CID_OBJMOVE);
					} else {
						em->StartExtrudeMode();
						}
					break;

				case IDC_COLLAPSE:
					em->CollapseSelFaces();
					break;
				
				case IDC_EXPLODE: {			
					TSTR name(GetString(IDS_RB_OBJECT));
					ISpinnerControl *spin = GetISpinner(GetDlgItem(hDlg,IDC_ANGLETHRESHSPIN));									
					if (IsDlgButtonChecked(hDlg,IDC_EXP_OBJECTS)) {
						if (!DialogBoxParam(
							hInstance, 
							MAKEINTRESOURCE(IDD_DETACH),
							hDlg, 
							DetachDlgProc,						
							(LPARAM)&name)) {
							break;
							}
						}
					em->ExplodeFaces(
						DegToRad(spin->GetFVal()),
						IsDlgButtonChecked(hDlg,IDC_EXP_OBJECTS),
						name);	
					ReleaseISpinner(spin);
					break;
					}
				
				case IDC_TESSELLATE:
					em->TesselateFaces(
						em->tensSpin->GetFVal()/400.0f,
						IsDlgButtonChecked(hDlg,IDC_TES_EDGE));
					break;

				case IDC_MAKEPLANAR:
					em->MakePlanar();
					break;

				case IDC_FACE_UNHIDEALL:
					em->UnhideAllFaces();
					break;

				case IDC_FACE_HIDE:
					em->HideSelFaces();
					break;

				}
			break;
		
		case WM_NOTIFY:
			if(((LPNMHDR)lParam)->code == TTN_NEEDTEXT) {
				LPTOOLTIPTEXT lpttt;
				lpttt = (LPTOOLTIPTEXT)lParam;				
				switch (lpttt->hdr.idFrom) {
					case IDC_SELSINGLE:
						lpttt->lpszText = GetString(IDS_RB_FACESEL);
						break;
					case IDC_SELPOLY:
						lpttt->lpszText = GetString(IDS_RB_POLYGONSEL);
						break;
					case IDC_SELELEMENT:
						lpttt->lpszText = GetString(IDS_RB_ELEMENTSEL);
						break;
					}
				}
			break;
		}
	
	return FALSE;
	}



static void SetSmoothButtonState(HWND hWnd,DWORD bits,DWORD invalid,DWORD unused=0)
	{
	for (int i=IDC_SMOOTH_GRP1; i<IDC_SMOOTH_GRP1+32; i++) {
		if ( (unused&(1<<(i-IDC_SMOOTH_GRP1))) ) {
			ShowWindow(GetDlgItem(hWnd,i),SW_HIDE);
			continue;
			}

		if ( (invalid&(1<<(i-IDC_SMOOTH_GRP1))) ) {
			SetWindowText(GetDlgItem(hWnd,i),NULL);
			SendMessage(GetDlgItem(hWnd,i),CC_COMMAND,CC_CMD_SET_STATE,FALSE);
		} else {
			TSTR buf;
			buf.printf(_T("%d"),i-IDC_SMOOTH_GRP1+1);
			SetWindowText(GetDlgItem(hWnd,i),buf);
			SendMessage(GetDlgItem(hWnd,i),CC_COMMAND,CC_CMD_SET_STATE,
				(bits&(1<<(i-IDC_SMOOTH_GRP1)))?TRUE:FALSE);
			}
		InvalidateRect(GetDlgItem(hWnd,i),NULL,TRUE);
		}
	}

static BOOL CALLBACK SelectBySmoothDlgProc(
		HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
	static DWORD *param;
	switch (msg) {
		case WM_INITDIALOG:	{
			param = (DWORD*)lParam;
			for (int i=IDC_SMOOTH_GRP1; i<IDC_SMOOTH_GRP1+32; i++) {
				SendMessage(GetDlgItem(hWnd,i),CC_COMMAND,CC_CMD_SET_TYPE,CBT_CHECK);
				}
			SetSmoothButtonState(hWnd,param[0],0,param[2]);
			CheckDlgButton(hWnd,IDC_CLEARSELECTION,param[1]);
			CenterWindow(hWnd,GetParent(hWnd));
			break;
			}

		case WM_COMMAND: 
			if (LOWORD(wParam)>=IDC_SMOOTH_GRP1 &&
				LOWORD(wParam)<=IDC_SMOOTH_GRP32) {
				ICustButton *iBut = GetICustButton(GetDlgItem(hWnd,LOWORD(wParam)));				
				int shift = LOWORD(wParam) - IDC_SMOOTH_GRP1;				
				if (iBut->IsChecked()) {
					param[0] |= 1<<shift;
				} else {
					param[0] &= ~(1<<shift);
					}				
				ReleaseICustButton(iBut);
				break;
				}

			switch (LOWORD(wParam)) {
				case IDOK:
					param[1] = IsDlgButtonChecked(hWnd,IDC_CLEARSELECTION);					
					EndDialog(hWnd,1);					
					break;					

				case IDCANCEL:
					EndDialog(hWnd,0);
					break;
				}
			break;			

		default:
			return FALSE;
		}
	return TRUE;
	}

static BOOL CALLBACK SelectByMatDlgProc(
		HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{
	static int *param;
	switch (msg) {
		case WM_INITDIALOG:
			param = (int*)lParam;
			SetupIntSpinner(hWnd,IDC_MAT_IDSPIN,IDC_MAT_ID,1,MAX_MATID,param[0]);			
			CheckDlgButton(hWnd,IDC_CLEARSELECTION,param[1]);
			CenterWindow(hWnd,GetParent(hWnd));
			break;

		case WM_COMMAND:
			switch (LOWORD(wParam)) {
				case IDOK: {
					ISpinnerControl *spin = GetISpinner(GetDlgItem(hWnd,IDC_MAT_IDSPIN));
					param[0] = spin->GetIVal();
					param[1] = IsDlgButtonChecked(hWnd,IDC_CLEARSELECTION);
					ReleaseISpinner(spin);
					EndDialog(hWnd,1);					
					break;
					}

				case IDCANCEL:
					EndDialog(hWnd,0);
					break;
				}
			break;

		default:
			return FALSE;
		}
	return TRUE;
	}

void EditMeshMod::InvalidateSurfaceUI()
	{
	if (hParam2) {		
		faceUIValid = FALSE;
		InvalidateRect(hParam2,NULL,FALSE);
		}
	}


BOOL CALLBACK SurfaceParamDlgProc(
		HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam)
	{	
	EditMeshMod *em = (EditMeshMod *)GetWindowLong(hWnd, GWL_USERDATA);
	if (!em && msg != WM_INITDIALOG) return FALSE;	

	switch (msg) {
		case WM_INITDIALOG: {
			em = (EditMeshMod *)lParam;
		 	SetWindowLong(hWnd, GWL_USERDATA, (LONG)em);

			for (int i=IDC_SMOOTH_GRP1; i<IDC_SMOOTH_GRP1+32; i++) {
				SendMessage(GetDlgItem(hWnd,i),CC_COMMAND,CC_CMD_SET_TYPE,CBT_CHECK);
				}
			SetupIntSpinner(hWnd,IDC_MAT_IDSPIN,IDC_MAT_ID,1,MAX_MATID,0);
			SetupFloatSpinner(hWnd,IDC_SMOOTH_THRESHSPIN,IDC_SMOOTH_THRESH,0.0f,90.0f,30.0f,0.1f);
			SetupFloatSpinner(hWnd,IDC_NORMAL_SCALESPIN,IDC_NORMAL_SCALE,0.0f,999999999.0f,10.0f,0.1f);
						
			CheckDlgButton(hWnd,IDC_NORMAL_SHOW,em->normScale>0.0f);
			em->ShowNormals();
			
			em->faceUIValid = FALSE;
			break;
			}
		
		case WM_PAINT:
			if (!em->faceUIValid) {
				DWORD invalid;
				DWORD bits = em->GetSelSmoothBits(invalid);
				int mat = em->GetSelMatIndex();
				SetSmoothButtonState(hWnd,bits,invalid);
				ISpinnerControl *spin = GetISpinner(GetDlgItem(hWnd,IDC_MAT_IDSPIN));
				if (mat==-1) {
					spin->SetIndeterminate(TRUE);
				} else {
					spin->SetIndeterminate(FALSE);
					spin->SetValue(mat+1,FALSE);
					}
				ReleaseISpinner(spin);
				em->faceUIValid = TRUE;
				}
			return FALSE;

		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_MOUSEMOVE:   			
   			em->iObjParams->RollupMouseMessage(hWnd,msg,wParam,lParam);
			return FALSE;		
		
		
		case CC_SPINNER_BUTTONUP:
			switch (LOWORD(wParam)) {
				case IDC_MAT_IDSPIN:
					if (HIWORD(wParam)) {
					//	theHold.Accept(GetString(IDS_RB_ASSIGNMATID));
					} else {
					//	theHold.Cancel();
						}
					em->iObjParams->RedrawViews(
						em->iObjParams->GetTime(),REDRAW_END);
					break;

				case IDC_NORMAL_SCALESPIN:
					if (IsDlgButtonChecked(hWnd,IDC_NORMAL_SHOW)) {
						em->iObjParams->RedrawViews(
							em->iObjParams->GetTime(),REDRAW_END);
						}
					break;
				}
			break;

		case CC_SPINNER_CHANGE:
			switch (LOWORD(wParam)) {
				case IDC_MAT_IDSPIN: {
					//if (!theHold.Holding()) theHold.Begin();
					ISpinnerControl *spin = (ISpinnerControl*)lParam;
					em->SetSelMatIndex(spin->GetIVal()-1);
					//if (!HIWORD(wParam)) {
						// Typed in
					//	theHold.Accept(GetString(IDS_RB_ASSIGNMATID));
					//	}
					break;
					}

				case IDC_NORMAL_SCALESPIN: 
					if (IsDlgButtonChecked(hWnd,IDC_NORMAL_SHOW)) {
						ISpinnerControl *spin = (ISpinnerControl*)lParam;					
						em->normScale = spin->GetFVal();
						em->NotifyDependents(FOREVER, PART_DISPLAY, REFMSG_CHANGE);
						em->iObjParams->RedrawViews(
						em->iObjParams->GetTime(),REDRAW_INTERACTIVE);					
						}
					break;					
				}
			break;

		case WM_COMMAND:
			if (LOWORD(wParam)>=IDC_SMOOTH_GRP1 &&
				LOWORD(wParam)<=IDC_SMOOTH_GRP32) {
				ICustButton *iBut = GetICustButton(GetDlgItem(hWnd,LOWORD(wParam)));
				int bit = iBut->IsChecked() ? 1 : 0;
				int shift = LOWORD(wParam) - IDC_SMOOTH_GRP1;
				em->SetSelSmoothBits(bit<<shift,1<<shift);
				ReleaseICustButton(iBut);
				break;
				}

			switch (LOWORD(wParam)) {
				case IDC_SELECT_BYID: {										
					if (DialogBoxParam(
						hInstance, 
						MAKEINTRESOURCE(IDD_EM_SELECTBYMAT),
						hWnd, 
						SelectByMatDlgProc,
						(LPARAM)sbmParams)) {
					
						em->SelectByMat(sbmParams[0]-1/*index*/,sbmParams[1]/*clear*/);
						}
					break;
					}
				
				case IDC_SELECTBYSMOOTH: {					
					sbsParams[2] = ~em->GetUsedSmoothBits();
					if (DialogBoxParam(
						hInstance, 
						MAKEINTRESOURCE(IDD_EM_SELECTBYSMOOTH),
						hWnd, 
						SelectBySmoothDlgProc,
						(LPARAM)sbsParams)) {
					
						em->SelectBySmoothGroup(sbsParams[0]/*bits*/,(BOOL)sbsParams[1]/*clear*/);
						}
					break;
					}
				
				
				case IDC_SMOOTH_AUTO: {
					ISpinnerControl *spin = 
						GetISpinner(GetDlgItem(hWnd,IDC_SMOOTH_THRESHSPIN));
					em->AutoSmooth(DegToRad(spin->GetFVal()));
					break;
					}

				case IDC_NORMAL_FLIP:
					em->FlipSelNormals();
					break;

				case IDC_NORMAL_UNIFY:
					em->UnifySelNormals();
					break;

				case IDC_NORMAL_SHOW: {
					ISpinnerControl *spin = 
						GetISpinner(GetDlgItem(hWnd,IDC_NORMAL_SCALESPIN));
					if (IsDlgButtonChecked(hWnd,IDC_NORMAL_SHOW)) {						
						em->normScale = spin->GetFVal();
						em->ShowNormals();
					} else {
						em->normScale = -1.0f;
						em->ShowNormals();
						}
					ReleaseISpinner(spin);
					break;
					}
				}
			break;

		default:
			return FALSE;
		}
	return TRUE;
	}


BOOL CALLBACK EdgeParamDlgProc( HWND hDlg, UINT message, WPARAM wParam, LPARAM lParam )
	{	
	EditMeshMod *em = (EditMeshMod *)GetWindowLong( hDlg, GWL_USERDATA );
	if ( !em && message != WM_INITDIALOG ) return FALSE;
	
	switch ( message ) {
		case WM_INITDIALOG: {
		 	em = (EditMeshMod *)lParam;
		 	SetWindowLong( hDlg, GWL_USERDATA, (LONG)em );			
		 	
			em->amountSpin = GetISpinner(GetDlgItem(hDlg,IDC_EXTRUDESPINNER));
			em->amountSpin->SetLimits( -999999, 999999, FALSE );
			em->amountSpin->LinkToEdit( GetDlgItem(hDlg,IDC_EXTRUDEAMOUNT), EDITTYPE_FLOAT );

		 	ISpinnerControl *spin;
		 	spin = GetISpinner(GetDlgItem(hDlg,IDC_ANGLETHRESHSPIN));
			spin->SetLimits(0.0f,180.0f,FALSE);
			spin->SetScale(0.1f);
			spin->LinkToEdit(GetDlgItem(hDlg,IDC_ANGLETRESH), EDITTYPE_FLOAT);
		 	spin->SetValue(lastEdgeThresh,FALSE);
			ReleaseISpinner(spin);

			ICustButton *but = GetICustButton(GetDlgItem(hDlg,IDC_EXTRUDE));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);

			but = GetICustButton(GetDlgItem(hDlg,IDC_EDGE_DIVIDE));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);

			but = GetICustButton(GetDlgItem(hDlg,IDC_EDGE_TURN));
			but->SetType(CBT_CHECK);
			but->SetHighlightColor(GREEN_WASH);
			ReleaseICustButton(but);
		 	break;
			}

		case WM_DESTROY: {
			ISpinnerControl *spin;
		 	spin = GetISpinner(GetDlgItem(hDlg,IDC_ANGLETHRESHSPIN));
			lastEdgeThresh = spin->GetFVal();
			ReleaseISpinner(spin);
			if (em->amountSpin) {
				ReleaseISpinner(em->amountSpin);
				em->amountSpin = NULL;
				}
			em->iObjParams->DeleteMode(em->extrudeMode);
			em->iObjParams->DeleteMode(em->divideEdgeMode);	
			em->iObjParams->DeleteMode(em->turnEdgeMode);	
			break;
			}
				
		case WM_LBUTTONDOWN:
		case WM_LBUTTONUP:
		case WM_MOUSEMOVE:   			
   			em->iObjParams->RollupMouseMessage(hDlg,message,wParam,lParam);
			break;
		
		case CC_SPINNER_BUTTONUP:
			switch ( LOWORD(wParam) ) {
				case IDC_EXTRUDESPINNER:
					em->EndNormalMove(em->iObjParams->GetTime(),TRUE);
					em->iObjParams->RedrawViews(
						em->iObjParams->GetTime(),REDRAW_END);
					break;
				}
			break;

		case CC_SPINNER_CHANGE:
			switch ( LOWORD(wParam) ) {
				case IDC_EXTRUDESPINNER:
					if ( !em->inNormalMove ) {
						em->BeginNormalMove(em->iObjParams->GetTime());
						}
					em->NormalMove(
						em->iObjParams->GetTime(),
						em->amountSpin->GetFVal() );					
					
					if (!HIWORD(wParam)) {
						// hit the enter key
						em->EndNormalMove(em->iObjParams->GetTime(),TRUE);
						em->iObjParams->RedrawViews(
							em->iObjParams->GetTime(),REDRAW_END);
					} else {
						em->iObjParams->RedrawViews(
							em->iObjParams->GetTime(),REDRAW_INTERACTIVE);
						}
					break;
				}
			break;
		case WM_COMMAND:			
			switch (LOWORD(wParam)) {
				case IDC_EXTRUDE:
					if (em->iObjParams->GetCommandMode()==em->extrudeMode) {
						em->iObjParams->SetStdCommandMode(CID_OBJMOVE);
					} else {
						em->StartExtrudeMode();
						}
					break;

				case IDC_EDGE_VIS:
					em->SetSelEdgeVis(TRUE);
					break;

				case IDC_EDGE_INVIS:
					em->SetSelEdgeVis(FALSE);
					break;

				case IDC_EDGE_AUTO: {
					ISpinnerControl *spin;
				 	spin = GetISpinner(GetDlgItem(hDlg,IDC_ANGLETHRESHSPIN));					
					em->AutoEdge(DegToRad(spin->GetFVal()));
					ReleaseISpinner(spin);
					break;
					}

				case IDC_EDGE_DIVIDE:
					//em->DivideSelEdges();
					if (em->iObjParams->GetCommandMode()==em->divideEdgeMode) {
						em->iObjParams->SetStdCommandMode(CID_OBJMOVE);
					} else {
						em->iObjParams->SetCommandMode(em->divideEdgeMode);
						}
					break;

				case IDC_EDGE_TURN:
					//em->TurnSelEdges();
					if (em->iObjParams->GetCommandMode()==em->turnEdgeMode) {
						em->iObjParams->SetStdCommandMode(CID_OBJMOVE);
					} else {
						em->iObjParams->SetCommandMode(em->turnEdgeMode);
						}
					break;

				case IDC_EDGE_DELETE:
					em->DeleteKey();
					break;

				case IDC_EDGE_COLLAPSE:
					em->CollapseSelEdges();
					break;
				}
			break;
		
		default:
			return FALSE;
		}
	
	return TRUE;
	}


/*--------------------------------------------------------------------*/


