// CamEdit.cpp : implementation file
//

#include "stdafx.h"
#include "thing.h"
#include "CamEdit.h"
#include "resource.h"

#ifdef _DEBUG
#define new DEBUG_NEW
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif

void CCamEdit::SetPath(int p)
{
	if (curpath==p) return;
	curpath=p;
	SetFrame(path().curframe);
}

void CCamEdit::SetFrame(int f)
{
	for (int c1=0;c1<path().frames.size();c1++) 
	{
		path().frames[c1].parent = &path();
		path().frames[c1].framenum = c1;
	}
	
	
	f=bound(0,f,path().frames.size()-1);
	path().curframe=f;
	UpdateData(false); // write to controls
}

void thecam::SetToFrame(CamFrame &fr)
{
	fr.pos = p-f;
	fr.foc = f;
	fr.lpos=0;
	fr.lfoc=0;
	fr.SetVal(CS_FOV,(fov-0.1f)/2.9f);
	fr.SetVal(CS_TILT,(tilt/PI)+0.5f);
	fr.SetVal(CS_XSHIFT,(shiftx/2)+0.5f);
	fr.SetVal(CS_YSHIFT,(shifty/2)+0.5f);
}

void thecam::GetFromFrame(CamFrame fr, bool wib)
{
	f=fr.GetFoc(wib);
	p=fr.GetPos(wib)+f;	
	fov=(fr.GetVal(CS_FOV,wib)*2.9f)+0.1f;
	tilt=(fr.GetVal(CS_TILT,wib)-0.5f) * PI;
	shiftx=(fr.GetVal(CS_XSHIFT,wib)-0.5f)*2;
	shifty=(fr.GetVal(CS_YSHIFT,wib)-0.5f)*2;
}

CamFrame CamPath::Interp(float t, bool wib)
{
	
	int it=int(t)-1;
	t-=floor(t);if (t<0) t+=1;

	int n =frames.size()-1;
	int it0=bound(0,it,n);
	int it1=bound(0,it+1,n);
	int it2=bound(0,it+2,n);
	int it3=bound(0,it+3,n);
	
	CamFrame ret = frames[it0];
	ret.parent=this;
	ret.framenum=it1;
	
	float in[26];
	float in1[26];
	float in2[26];
	float in3[26];

	for (int i=0;i<11;i++)
	{
		in [i+6]=frames[it0].GetVal((CAMSLIDER)i,wib);
		in1[i+6]=frames[it1].GetVal((CAMSLIDER)i,wib);
		in2[i+6]=frames[it2].GetVal((CAMSLIDER)i,wib);
		in3[i+6]=frames[it3].GetVal((CAMSLIDER)i,wib);
	}
	v3 p,f;
	p=frames[it0].GetPos(wib);in [0]=p.x;in [1]=p.y;in [2]=p.z;
	f=frames[it0].GetFoc(wib);in [3]=f.x;in [4]=f.y;in [5]=f.z;

	p=frames[it1].GetPos(wib);in1[0]=p.x;in1[1]=p.y;in1[2]=p.z;
	f=frames[it1].GetFoc(wib);in1[3]=f.x;in1[4]=f.y;in1[5]=f.z;

	p=frames[it2].GetPos(wib);in2[0]=p.x;in2[1]=p.y;in2[2]=p.z;
	f=frames[it2].GetFoc(wib);in2[3]=f.x;in2[4]=f.y;in2[5]=f.z;

	p=frames[it3].GetPos(wib);in3[0]=p.x;in3[1]=p.y;in3[2]=p.z;
	f=frames[it3].GetFoc(wib);in3[3]=f.x;in3[4]=f.y;in3[5]=f.z;
	
	float tt=t*t;
	float ttt=tt*t;
	
	//in[i]*(1-t)*(1-t)*(1-t) + in1*(1-t)*(1-t)*t
	
	for (i=0;i<11+6;i++)
	{

		float a = -1/6.f * ttt + 1/2.f * tt - 1/2.f * t + 1/6.f;
		float b = 1/2.f * ttt - tt + 2/3.f;
		float c = -1/2.f * ttt + 1/2.f * tt + 1/2.f * t + 1/6.f;
		float d = 1/6.f * ttt;
		float e = a+b+c+d;

		in[i] = a*in[i] + b*in1[i] + c*in2[i] + d*in3[i];


/*	
		float a,b,c,d;
		a=(-in[i]+3*in1[i]-3*in2[i]+in3[i])/6;
		b=(in[i]-2*in1[i]+in2[i])/2;
		c=(-2*in[i]-3*in1[i]+6*in2[i]-in3[i])/6;
		d=in1[i];

		in[i]=a*ttt+b*tt+c*t+d;		
		*/
	}

	for (i=0;i<11;i++)
	{
		ret.SetVal((CAMSLIDER)i,in[i+6]);
		ret.lock[i]=0;
	}
	ret.pos=v3(in[0],in[1],in[2]);
	ret.foc=v3(in[3],in[4],in[5]);
	ret.lpos=ret.lfoc=0;

	return ret;
}


v3 CamFrame::GetPos(bool wibble)
{
	CamFrame *f=this;
	//while (f->lpos && f->prev()) f=f->prev();
	v3 p = f->pos;
	if (wibble && parent)
	{
		float posv = GetVal(CS_POSVAR,false);
		float posh = GetVal(CS_POSHVAR,false);
		float r = parent->GetWibble(0,this) * posv * RADFAC;
		float t = parent->GetWibble(1,this) * PI;
		float h = parent->GetWibble(2,this) * posh * HFAC;
		p.y+=h;
		p.x+=r*cos(t);
		p.z+=r*sin(t);
	}
	return p;
}
v3 GetVineFoc();

v3 CamFrame::GetFoc(bool wibble)
{
	CamFrame *f=this;
	//while (f->lfoc && f->prev()) f=f->prev();
	v3 p=f->foc;

	float focrel = GetVal(CS_FOCREL,false);
	if (focrel>0.5f)
	{
		foc = GetVineFoc();
	}

	if (wibble && parent)
	{
		float posv = GetVal(CS_POSVAR,false);
		float posh = GetVal(CS_POSHVAR,false);
		float r = parent->GetWibble(3,this) * posv * RADFAC;
		float t = parent->GetWibble(4,this) * PI;
		float h = parent->GetWibble(5,this) * posh * HFAC;
		p.y+=h;
		p.x+=r*cos(t);
		p.z+=r*sin(t);
	}
	return p;
}
float CamFrame::GetVal(CAMSLIDER s, bool wibble)
{
	CamFrame *f=this;while (f->lock[s] && f->prev()) f=f->prev();
	if (wibble && parent && (s==CS_TILT || s==CS_FOV))
	{
		float var = parent->GetWibble(6+s,this)*0.5f*GetVal((CAMSLIDER)(s+1),false);
		var+=f->slider[s];
		var=bound(0,var,1);
		return var;
	}
	return f->slider[s];		
}

CamFrame *CamFrame::prev()
{
	if (!parent) return NULL;
	if (!framenum) return NULL;
	return &parent->frames[framenum-1];	
}



/////////////////////////////////////////////////////////////////////////////
// CCamEdit

IMPLEMENT_DYNCREATE(CCamEdit, CFormView)

BEGIN_MESSAGE_MAP(CCamEdit, CFormView)
	//{{AFX_MSG_MAP(CCamEdit)
	ON_WM_HSCROLL()
	ON_BN_CLICKED(IDC_CHECK1, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK2, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK3, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK4, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK5, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK6, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK7, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK8, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK9, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK10, OnCheck1)
	ON_BN_CLICKED(IDC_CHECK11, OnCheck1)
	ON_BN_CLICKED(IDC_LOAD, OnLoad)
	ON_BN_CLICKED(IDC_SAVE, OnSave)
	ON_BN_CLICKED(IDC_PREVIEW, OnPreview)
	//}}AFX_MSG_MAP
END_MESSAGE_MAP()



CCamEdit::CCamEdit()
	: CFormView(CCamEdit::IDD)
{
	//{{AFX_DATA_INIT(CCamEdit)
		// NOTE: the ClassWizard will add member initialization here
	//}}AFX_DATA_INIT
	camedit=this;
	inupdate=false;
	curpath=0;
	sliderchanged=0;

	
}

CCamEdit *camedit;

CCamEdit::~CCamEdit()
{
}

void CCamEdit::DoDataExchange(CDataExchange* pDX)
{
	inupdate=1;
	CFormView::DoDataExchange(pDX);
	DDX_Control(pDX, IDC_SLIDER1, m_slider[0]);
	DDX_Control(pDX, IDC_SLIDER2, m_slider[1]);
	DDX_Control(pDX, IDC_SLIDER3, m_slider[2]);
	DDX_Control(pDX, IDC_SLIDER4, m_slider[3]);
	DDX_Control(pDX, IDC_SLIDER5, m_slider[4]);
	DDX_Control(pDX, IDC_SLIDER6, m_slider[5]);
	DDX_Control(pDX, IDC_SLIDER7, m_slider[6]);
	DDX_Control(pDX, IDC_SLIDER8, m_slider[7]);
	DDX_Control(pDX, IDC_SLIDER9, m_slider[8]);
	DDX_Control(pDX, IDC_SLIDER10, m_slider[9]);	
	DDX_Control(pDX, IDC_POS1, m_pos[0]);
	DDX_Control(pDX, IDC_POS2, m_pos[1]);
	DDX_Control(pDX, IDC_POS3, m_pos[2]);
	DDX_Control(pDX, IDC_FOC1, m_foc[0]);
	DDX_Control(pDX, IDC_FOC2, m_foc[1]);
	DDX_Control(pDX, IDC_FOC3, m_foc[2]);
	DDX_Control(pDX, IDC_CHECK1, m_lock[0]);
	DDX_Control(pDX, IDC_CHECK2, m_lock[1]);
	DDX_Control(pDX, IDC_CHECK3, m_lock[2]);
	DDX_Control(pDX, IDC_CHECK4, m_lock[3]);
	DDX_Control(pDX, IDC_CHECK5, m_lock[4]);
	DDX_Control(pDX, IDC_CHECK6, m_lock[5]);
	DDX_Control(pDX, IDC_CHECK7, m_lock[6]);
	DDX_Control(pDX, IDC_CHECK8, m_lock[7]);
	DDX_Control(pDX, IDC_CHECK9, m_lock[8]);
	DDX_Control(pDX, IDC_CHECK10, m_lock[9]);
	DDX_Control(pDX, IDC_CHECK11, m_lock[10]);	
	
	//{{AFX_DATA_MAP(CCamEdit)
	DDX_Control(pDX, IDC_PREVIEW, m_previewon);
	DDX_Control(pDX, IDC_FRAMESLIDER2, m_previewslider);
	DDX_Control(pDX, IDC_FRAMESLIDER, m_frameslider);
	DDX_Control(pDX, IDC_FOCCOMBO, m_foccombo);
	DDX_Control(pDX, IDC_CHECKPOS, m_lockpos);
	DDX_Control(pDX, IDC_CHECKFOC, m_lockfoc);
	//}}AFX_DATA_MAP

	
	if (pDX->m_bSaveAndValidate)
	{
		// read from controls
		CString str;
		path().curframe = bound(0,m_frameslider.GetPos(),path().frames.size()-1);
		path().previewpos=bound(0,m_previewslider.GetPos()/100.f,path().frames.size()-1);
		path().previewmode = m_previewon.GetCheck();

		CamFrame &cf = path().frames[path().curframe];
		v3 pp,ff;
		int pok=0,fok=0;
		m_pos[0].GetWindowText(str);pok+=sscanf(str,"%f",&pp.x);
		m_pos[1].GetWindowText(str);pok+=sscanf(str,"%f",&pp.y);
		m_pos[2].GetWindowText(str);pok+=sscanf(str,"%f",&pp.z);
		m_foc[0].GetWindowText(str);fok+=sscanf(str,"%f",&ff.x);
		m_foc[1].GetWindowText(str);fok+=sscanf(str,"%f",&ff.y);
		m_foc[2].GetWindowText(str);fok+=sscanf(str,"%f",&ff.z);
		if (pok==3) cf.pos=pp;
		if (fok==3) cf.foc=ff;
		cf.lpos = m_lockpos.GetCheck();
		cf.lfoc = m_lockfoc.GetCheck();

		for (int c1=0;c1<11;c1++)
		{
			cf.lock[c1]=m_lock[c1].GetCheck();
			if (c1<10)
			{				
				//cf.slider[c1]=m_slider[c1].GetPos() / 1000.f;
				cf.SetVal((CAMSLIDER)c1,m_slider[c1].GetPos() / 1000.f);
			}
			else
			{
				cf.slider[c1]=m_foccombo.GetCurSel();
			}
		}
	}
	else
	{
		CString str;
		CamFrame &cf = path().frames[path().curframe];
		m_previewon.SetCheck(path().previewmode);
		v3 pp,ff;
		pp=cf.GetPos(false);
		ff=cf.GetFoc(false);
		str.Format("%0.1f",pp.x);m_pos[0].SetWindowText(str);
		str.Format("%0.1f",pp.y);m_pos[1].SetWindowText(str);
		str.Format("%0.1f",pp.z);m_pos[2].SetWindowText(str);
		str.Format("%0.1f",ff.x);m_foc[0].SetWindowText(str);
		str.Format("%0.1f",ff.y);m_foc[1].SetWindowText(str);
		str.Format("%0.1f",ff.z);m_foc[2].SetWindowText(str);
		m_lockpos.SetCheck(cf.lpos);
		m_lockfoc.SetCheck(cf.lfoc);
		m_previewslider.SetRange(0,(path().frames.size()-1)*100);
		m_frameslider.SetRange(0,path().frames.size()-1);
		m_frameslider.SetPos(path().curframe);
		m_previewslider.SetPos(path().previewpos*100);

		// write to controls
		for (int c1=0;c1<11;c1++)
		{
			float f=cf.GetVal((CAMSLIDER)c1,false);
			m_lock[c1].SetCheck(cf.lock[c1]);
			if (c1<10)
			{				
				m_slider[c1].SetRange(0,1000);
				m_slider[c1].SetPos(f*1000);				
			}
			else
			{
				m_foccombo.SetCurSel(int(f));
			}
		}
	}
	inupdate=0;
}



/////////////////////////////////////////////////////////////////////////////
// CCamEdit diagnostics

#ifdef _DEBUG
void CCamEdit::AssertValid() const
{
	CFormView::AssertValid();
}

void CCamEdit::Dump(CDumpContext& dc) const
{
	CFormView::Dump(dc);
}
#endif //_DEBUG

/////////////////////////////////////////////////////////////////////////////
// CCamEdit message handlers

void CCamEdit::OnInitialUpdate() 
{
	CFormView::OnInitialUpdate();
	
	// TODO: Add your specialized code here and/or call the base class
	OnLoad();
	
}


void thecam::Update()
{
	{
		if (camedit->sliderchanged)
		{
			camedit->sliderchanged=0;
			GetFromFrame(camedit->path().frames[camedit->path().curframe],false);
		}
		if (camedit->path().previewmode)
		{
			CamFrame interp = camedit->path().Interp(camedit->path().previewpos,false);
			GetFromFrame(interp,false);
		}
		else
		{
			//fov = camedit->path().frames[camedit->path().curframe].fov;
			//fov=(camedit->path().frames[camedit->path().curframe].GetVal(CS_FOV,false)*2.9f)+0.1f;
			thecam tempcam;
			tempcam.GetFromFrame(camedit->path().frames[camedit->path().curframe]);
			if (camedit->path().frames[camedit->path().curframe].GetVal(CS_FOCREL,false)>0.5f) 
			{
				p-=f;
				f=GetVineFoc();
				p+=f;
			}


			fov=tempcam.fov;
			shiftx=tempcam.shiftx;
			shifty=tempcam.shifty;
			tilt=tempcam.tilt;
		}
		int tt=GetTickCount();
		if (lastt==0) lastt=tt;
		int idt=tt-lastt;
		lastt=tt;
		float dt=idt/1500.f;

		int shift =GetAsyncKeyState(VK_SHIFT)<0;
		int control=GetAsyncKeyState(VK_CONTROL)<0;
		CThingView *v = CThingView::view;

		float dx=0,dy=0;
		v3 d=p-f;
		float dfx = 0;
		float dfy = 0;

		if (v->mb)
		{
			
			if (v->mb==1)
			{
			
				if (camedit->path().previewmode)
				{
					float pm = camedit->path().previewpos + (v->mx-v->cx) * 0.01f;
					pm=bound(0,pm,camedit->path().frames.size()-1);
					camedit->path().previewpos=pm;
					camedit->UpdateData(false);



				}
				else
				{
				
					dx = (v->mx - v->cx) * -0.01f;
					dy = (v->my - v->cy) * 0.01f;

					if (control)
					{
						shiftx+= dx;
						shifty+= dy;
						shiftx=bound(-1,shiftx,1);
						shifty=bound(-1,shifty,1);
						dx=dy=0;
					}
					else
					{
					
						
						if (shift)
						{
							dx=-dx;
							dy=-dy;
						}
					}
				}
			}

			if (v->mb==4)
			{
				dx = (v->mx - v->cx) * 0.04f;
				dy = (v->my - v->cy) * 0.04f;
				
				dfx+=dx * 10;
				dfy+=dy * 10;

				control=!control;

				dx=dy=0;
			}
				
			v->cx=v->mx;
			v->cy=v->my;

		}
		
		float z = Length(d);
		float h = atan2(d.z,d.x);
		float pi = atan(d.y / sqrtf(d.x*d.x+d.z*d.z));

		
#define MOVESPEED 9.f
		extern HWND thehwnd;
		int focus=0;
		if (GetFocus()== thehwnd || GetFocus()==camedit->GetSafeHwnd())
		{
			focus=1;
		
			if (GetAsyncKeyState(VK_LEFT)<0) dfx+=dt * MOVESPEED;
			if (GetAsyncKeyState(VK_RIGHT)<0) dfx-=dt * MOVESPEED;
			if (GetAsyncKeyState(VK_UP)<0) dfy-=dt * MOVESPEED * 4;
			if (GetAsyncKeyState(VK_DOWN)<0) dfy+=dt * MOVESPEED * 4;

			if (GetAsyncKeyState('P')&1)
			{
				camedit->path().previewmode=!camedit->path().previewmode;
				camedit->UpdateData(false);
			}
			

			
			
		}
		if (GetAsyncKeyState(VK_F2)&1)
		{
			if (camedit->curpath>0) camedit->SetPath(camedit->curpath-1);
		}
		if (GetAsyncKeyState(VK_F3)&1)
		{
			if (camedit->curpath<255) camedit->SetPath(camedit->curpath+1);
		}
		if ((GetAsyncKeyState('R')&1) && focus)
		{
			// edit current frame
			GetFromFrame(camedit->path().frames[camedit->path().curframe]);
		}
		if ((GetAsyncKeyState(VK_NEXT)&1) && focus)
		{
			camedit->SetFrame(camedit->path().curframe + 1);
			GetFromFrame(camedit->path().frames[camedit->path().curframe]);
		}
		if ((GetAsyncKeyState(VK_PRIOR)&1) && focus)
		{
			camedit->SetFrame(camedit->path().curframe - 1);
			GetFromFrame(camedit->path().frames[camedit->path().curframe]);
		}
		if ((GetAsyncKeyState('W')&1) && focus)
		{
			SetToFrame(camedit->path().frames[camedit->path().curframe]);
			camedit->UpdateData(false); // write to controls
		}
		if ((GetAsyncKeyState('V')&1) && focus)
		{
			camedit->path().frames[camedit->path().curframe].lfocrel=0;;
			camedit->path().frames[camedit->path().curframe].focrel=!camedit->path().frames[camedit->path().curframe].focrel;
			camedit->UpdateData(false); // write to controls
		}
		if ((GetAsyncKeyState(VK_SPACE)&1) && focus)
		{
			SetToFrame(camedit->path().frames[camedit->path().curframe]);
			camedit->UpdateData(false); // write to controls
			// insert new frame
			camedit->path().frames.insert(camedit->path().frames.begin()+camedit->path().curframe,
				camedit->path().frames[camedit->path().curframe]);			
			// move on a frame
			camedit->SetFrame(camedit->path().curframe + 1);
			CamFrame &f = camedit->path().frames[camedit->path().curframe];
			f.lpos=f.lfoc=1;
			for (int c1=0;c1<11;c1++) f.lock[c1]=1;
			
			GetFromFrame(camedit->path().frames[camedit->path().curframe]);
			
		}
		if ((GetAsyncKeyState(VK_DELETE)&1) && focus)
		{
			if (camedit->path().frames.size()>1)
				camedit->path().frames.erase(camedit->path().frames.begin()+camedit->path().curframe);
			camedit->SetFrame(camedit->path().curframe);			
			GetFromFrame(camedit->path().frames[camedit->path().curframe]);
		}

			

		
		v3 delta = dfy * fwd + dfx * across;

		if (control) delta = (dfy * up + dfx*across) * 0.1f;

		if (shift) delta.y=0;
		

		p+=delta;
		f+=delta;
		

		h+=dx;
		pi+=dy;
		pi=bound(-3,pi,3);
		if (control)
		{
			fov*=pow(1.1f,v->mw/120.f);
			fov=bound(0.1f,fov,3);
		}
		else
		{
			z*=pow(1.1f,v->mw/-120.f);
		}
		
		v->mw=0;

		d = v3(z*cos(h)*cos(pi),z*sin(pi),z*sin(h)*cos(pi));

		if (!shift)
		{
			p=f+d;
		}
		else
		{
			f=p-d;
		}

		v3 tp,tf;
		GetActualPos(tp,tf,up,shiftx,shifty);
		
		SetCam(tp,tf,up);
		//D3DXMatrixLookAtLH((D3DXMATRIX*)&cammat,(D3DXVECTOR3*)&tp,(D3DXVECTOR3*)&tf,(D3DXVECTOR3*)&up);		
		SetFOV(fov,0.2f);
		
	}
}

void CCamEdit::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar) 
{
	CFormView::OnHScroll(nSBCode,nPos,pScrollBar);
	if (pScrollBar->GetDlgCtrlID() == IDC_FRAMESLIDER)
	{
		// frame slider;
		int i=m_frameslider.GetPos();
		if (i!=path().curframe) 
		{

			path().curframe=i;
			UpdateData(false); // update controls
			sliderchanged=1;
		}

	}
	else
	{
		UpdateData(true); // read controls
	}
}

void CCamEdit::OnCheck1() 
{
	// TODO: Add your control notification handler code here
	UpdateData(true); // read controls
	
}

void CCamEdit::OnLoad() 
{
	//CFileDialog cfd(true,".path",fname,OFN_FILEMUSTEXIST,"path files|*.path||");
	//if (cfd.DoModal()==IDOK)
	{
		fname="cameras.path";
		//fname=cfd.GetPathName();
		int ocurpath=curpath;
		FILE *f=fopen(fname,"rb");
		if (f)
		{			
			for (curpath=0;curpath<256;curpath++)
			{			
				path().numframes=path().frames.size();
				fread(&path(),4,8, f);
				path().frames.resize(path().numframes);
				fread(path().frames.begin(),sizeof(CamFrame),path().frames.size(),f);
				
				for (int c1=0;c1<path().frames.size();c1++) 
				{
					path().frames[c1].parent = &path();
					path().frames[c1].framenum=c1;
				}
			}
			curpath=0;
			fclose(f);
		}
		UpdateData(false);
		SetPath(ocurpath);
		
		
	}
	
}

void CCamEdit::OnSave() 
{
	//CFileDialog cfd(false,".path",fname,OFN_OVERWRITEPROMPT,"path files|*.path||");
	//if (cfd.DoModal()==IDOK)
	{
		int ocurpath=curpath;
		fname="cameras.path";
		//fname=cfd.GetPathName();
		FILE *f=fopen(fname,"wb");
		for (curpath=0;curpath<256;curpath++)
		{
		
			path().numframes=path().frames.size();
			fwrite(&path(),4,8, f);
			fwrite(path().frames.begin(),sizeof(CamFrame),path().frames.size(),f);
		}
		curpath=0;
		fclose(f);
		SetPath(ocurpath);
	}
	
}

void CCamEdit::OnPreview() 
{
	path().previewmode=!path().previewmode;
	UpdateData(false);	// write controls
}
