Files
Cyd 2b8ca921cb Initial full mirror of c:\VWE (source + assets + toolchain + outputs) via Git LFS
Complete disaster-recovery snapshot: engine/game source, game data assets,
VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive.
Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false,
no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
2026-06-24 21:28:16 -05:00

1190 lines
26 KiB
C++

// CurveEditor.cpp : implementation file
//
#include "stdafx.h"
#include "pixelwhippro.h"
#include "CurveEditor.h"
#include "EffectEditWin.h"
#include "TreeParamView.h"
#include "DataParamView.h"
#include "CurveSet.h"
#include <GosFx\GosFx.hpp>
extern CPixelWhipProApp theApp;
extern gosFX::Effect *CurrentEffect;
#define LINEDIVS 30
#define HANDLELEN 5
/////////////////////////////////////////////////////////////////////////////
// CCurveEditor
//IMPLEMENT_DYNCREATE(CCurveEditor, CWnd)
CCurveEditor::CCurveEditor()
{
CurrentEditMode=MOVE;
EditHan=EditVar=false;
StartY=-100;
EndY=100;
NumCurves=0;
DCurve=VCurve=NULL;
CurrentCSet=NULL;
SelectedKey=-1;
}
CCurveEditor::~CCurveEditor()
{
}
BEGIN_MESSAGE_MAP(CCurveEditor, CWnd)
//{{AFX_MSG_MAP(CCurveEditor)
ON_WM_CLOSE()
ON_WM_PAINT()
ON_COMMAND(ID_EDIT_INSERTMODE, OnEditInsertmode)
ON_COMMAND(ID_EDIT_MOVEMODE, OnEditMovemode)
ON_COMMAND(ID_EDIT_PANMODE, OnEditPanmode)
ON_COMMAND(ID_EDIT_SCALEMODE, OnEditScalemode)
ON_COMMAND(ID_EDIT_ZOOMMODE, OnEditZoommode)
ON_UPDATE_COMMAND_UI(ID_EDIT_INSERTMODE, OnUpdateEditInsertmode)
ON_UPDATE_COMMAND_UI(ID_EDIT_MOVEMODE, OnUpdateEditMovemode)
ON_UPDATE_COMMAND_UI(ID_EDIT_PANMODE, OnUpdateEditPanmode)
ON_UPDATE_COMMAND_UI(ID_EDIT_SCALEMODE, OnUpdateEditScalemode)
ON_UPDATE_COMMAND_UI(ID_EDIT_ZOOMMODE, OnUpdateEditZoommode)
ON_COMMAND(ID_EDIT_EDITVARAINCECURVE, OnEditEditvaraincecurve)
ON_UPDATE_COMMAND_UI(ID_EDIT_EDITVARAINCECURVE, OnUpdateEditEditvaraincecurve)
ON_WM_LBUTTONUP()
ON_WM_MOUSEMOVE()
ON_WM_LBUTTONDOWN()
ON_COMMAND(ID_EDIT_DELETEVERTEX, OnEditDeletevertex)
ON_COMMAND(ID_VIEW_ZOOMTOCURVE, OnViewZoomtocurve)
ON_WM_CREATE()
ON_WM_KEYDOWN()
ON_WM_SIZE()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CCurveEditor message handlers
void CCurveEditor::OnClose()
{
ShowWindow(SW_HIDE);
// CWnd::OnClose();
}
void CCurveEditor::Refresh()
{
SelectedKey=-1;
ReDraw();
}
void CCurveEditor::OnPaint()
{
CPaintDC dc(this); // device context for painting
ReDrawInternal();
}
void CCurveEditor::DrawHandles(CDC *dc,gosFX::Curve *curve)
{
CRect crct;
GetClientRect(&crct);
int hlen=crct.Width()<crct.Height()?crct.Width():crct.Height()/HANDLELEN;
CPoint lpt;
if(curve)
{
Check_Object(curve);
switch(curve->m_type)
{
case gosFX::Curve::e_SplineType:
{
gosFX::SplineCurve *SCurve=(gosFX::SplineCurve *)curve;
double ang;
float slp;
lpt.x=0;
lpt.y=CurveToClient(SCurve->ComputeValue(0.0f,0.0f),crct.Height());
dc->MoveTo(lpt);
slp=SCurve->ComputeSlope(0.0f);
slp=(float)(CurveToClient(slp,crct.Height())-CurveToClient(0.0f,crct.Height()))/crct.Width();
ang=atan(slp);
lpt.x+=(int)((float)hlen*cos(ang));
lpt.y+=(int)((float)hlen*sin(ang));
H1Pos=lpt;
dc->LineTo(lpt);
dc->Ellipse(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
lpt.x=crct.Width();
lpt.y=CurveToClient(SCurve->ComputeValue(1.0f,0.0f),crct.Height());
dc->MoveTo(lpt);
slp=SCurve->ComputeSlope(1.0f);
slp=(float)(CurveToClient(slp,crct.Height())-CurveToClient(0.0f,crct.Height()))/crct.Width();
ang=atan(slp);
lpt.x-=(int)(hlen*cos(ang));
lpt.y-=(int)(hlen*sin(ang));
H2Pos=lpt;
dc->LineTo(lpt);
dc->Ellipse(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
break;
case gosFX::Curve::e_ComplexType:
{
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)curve;
Stuff::Scalar tme;
tme=(*SCurve)[SCurve->GetKeyCount()-1].m_time;
lpt.x=(int)(tme*crct.Width());
lpt.y=CurveToClient(SCurve->ComputeValue(tme,0.0f),crct.Height());
dc->MoveTo(lpt);
lpt.x=crct.Width();
lpt.y=CurveToClient(SCurve->ComputeValue(1.0f,0.0f),crct.Height());
H1Pos=lpt;
dc->LineTo(lpt);
dc->Ellipse(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
break;
default:
break;
}
}
}
void CCurveEditor::DrawCurve(CDC *dc,gosFX::Curve *curve,bool DrawKeys)
{
CRect crct;
GetClientRect(&crct);
Check_Object(curve);
switch(curve->m_type)
{
case gosFX::Curve::e_ConstantType:
{
CPoint lpt;
gosFX::ConstantCurve *SCurve=(gosFX::ConstantCurve *)curve;
lpt.x=0;
lpt.y=CurveToClient(SCurve->m_value,crct.Height());
if(DrawKeys)
{
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
dc->MoveTo(lpt);
lpt.x=crct.Width();
dc->LineTo(lpt);
}
break;
case gosFX::Curve::e_LinearType:
{
CPoint lpt;
gosFX::LinearCurve *SCurve=(gosFX::LinearCurve *)curve;
lpt.x=0;
lpt.y=CurveToClient(SCurve->ComputeValue(0.0f,0.0f),crct.Height());
if(DrawKeys)
{
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
dc->MoveTo(lpt);
lpt.x=crct.Width();
lpt.y=CurveToClient(SCurve->ComputeValue(1.0f,0.0f),crct.Height());
dc->LineTo(lpt);
}
break;
case gosFX::Curve::e_SplineType:
{
gosFX::SplineCurve *SCurve=(gosFX::SplineCurve *)curve;
CPoint lpt;
if(DrawKeys)
{
lpt.x=0;
lpt.y=CurveToClient(SCurve->ComputeValue(0.0f,0.0f),crct.Height());
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
lpt.x=crct.Width();
lpt.y=CurveToClient(SCurve->ComputeValue(1.0f,0.0f),crct.Height());
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
lpt.x=0;
lpt.y=CurveToClient(SCurve->ComputeValue(0.0f,0.0f),crct.Height());
float finc,linelen=1.0f/LINEDIVS;
dc->MoveTo(lpt);
for(finc=linelen;finc<=1.0f;finc+=linelen)
{
lpt.x=(long)(finc*crct.Width());
lpt.y=CurveToClient(SCurve->ComputeValue(finc,0.0f),crct.Height());
dc->LineTo(lpt);
}
lpt.x=crct.Width();
lpt.y=CurveToClient(SCurve->ComputeValue(1.0f,0.0f),crct.Height());
dc->LineTo(lpt);
}
break;
case gosFX::Curve::e_ComplexType:
{
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)curve;
int key;
float st,finc,linelen=1.0f/LINEDIVS,nextx=0.0f;
CPoint lpt,pt;
if(DrawKeys)
{
for(key=0;key<SCurve->GetKeyCount();key++)
{
st=(*SCurve)[key].m_time;
lpt.x=(long)(st*crct.Width());
lpt.y=CurveToClient(SCurve->ComputeValue(st,0.0f),crct.Height());
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
}
lpt.x=0;
lpt.y=CurveToClient(SCurve->ComputeValue(0.0,0.0f),crct.Height());
key=1;
for(finc=0.0f;finc<=1.0f;finc+=linelen)
{
if(key<SCurve->GetKeyCount())
{
st=(*SCurve)[key].m_time;
if(finc>st)
{
finc=st;
key++;
}
else
{
if(st-finc<linelen) {finc=st; key++;}
}
}
else
{
if((1.0f-finc)<=linelen)
finc=1.0f;
}
pt.x=(long)(finc*crct.Width());
pt.y=CurveToClient(SCurve->ComputeValue(finc,0.0f),crct.Height());
dc->MoveTo(lpt);
dc->LineTo(pt);
lpt=pt;
if(finc<1.0f && (finc+linelen)>1.0f) finc-=linelen; //cap end
}
}
break;
default:
break;
}
}
void CCurveEditor::OnEditInsertmode() { CurrentEditMode=INSERT; }
void CCurveEditor::OnEditMovemode() { CurrentEditMode=MOVE; }
void CCurveEditor::OnEditPanmode() { CurrentEditMode=PAN; }
void CCurveEditor::OnEditScalemode() { CurrentEditMode=SCALE; }
void CCurveEditor::OnEditZoommode() { CurrentEditMode=ZOOM; }
void CCurveEditor::OnUpdateEditInsertmode(CCmdUI* pCmdUI)
{ pCmdUI->SetCheck(CurrentEditMode==INSERT?1:0); }
void CCurveEditor::OnUpdateEditMovemode(CCmdUI* pCmdUI)
{ pCmdUI->SetCheck(CurrentEditMode==MOVE?1:0); }
void CCurveEditor::OnUpdateEditPanmode(CCmdUI* pCmdUI)
{ pCmdUI->SetCheck(CurrentEditMode==PAN?1:0); }
void CCurveEditor::OnUpdateEditScalemode(CCmdUI* pCmdUI)
{ pCmdUI->SetCheck(CurrentEditMode==SCALE?1:0); }
void CCurveEditor::OnUpdateEditZoommode(CCmdUI* pCmdUI)
{ pCmdUI->SetCheck(CurrentEditMode==ZOOM?1:0); }
void CCurveEditor::OnEditEditvaraincecurve()
{
EditVar=!EditVar;
SelectedKey=-1;
ReDraw();
}
void CCurveEditor::OnUpdateEditEditvaraincecurve(CCmdUI* pCmdUI)
{ pCmdUI->SetCheck(EditVar?1:0); }
void CCurveEditor::OnLButtonUp(UINT nFlags, CPoint point)
{
switch(CurrentEditMode)
{
case INSERT:
break;
case MOVE:
ReleaseCapture();
break;
case PAN:
ReleaseCapture();
break;
case SCALE:
ReleaseCapture();
break;
case ZOOM:
ReleaseCapture();
break;
}
CWnd::OnLButtonUp(nFlags, point);
}
void CCurveEditor::OnMouseMove(UINT nFlags, CPoint point)
{
if(nFlags&MK_LBUTTON)
{
CRect rct;
GetClientRect(&rct);
switch(CurrentEditMode)
{
case INSERT:
break;
case MOVE:
{
gosFX::Curve *Curve=EditVar?VCurve:DCurve;
if(Curve)
{
Check_Object(Curve);
Stuff::DynamicMemoryStream stream;
if(CurrentCSet)
CurrentCSet->PushState();
Stuff::Scalar newy;
newy=ClientToCurve(point.y,rct.Height());
switch(Curve->m_type)
{
case gosFX::Curve::e_ConstantType:
{
gosFX::ConstantCurve *SCurve=(gosFX::ConstantCurve *)Curve;
SCurve->SetCurve(newy);
}
break;
case gosFX::Curve::e_LinearType:
{
gosFX::LinearCurve *SCurve=(gosFX::LinearCurve *)Curve;
Stuff::Scalar v0,v1;
v0=SCurve->ComputeValue(0.0f,0.0f);
v1=SCurve->ComputeValue(1.0f,0.0f);
if(SelectedKey<0)
v0=newy;
else
v1=newy;
SCurve->SetCurve(v0,v1);
}
break;
case gosFX::Curve::e_SplineType:
{
gosFX::SplineCurve *SCurve=(gosFX::SplineCurve *)Curve;
Stuff::Scalar v0,v1,s0,s1;
v0=SCurve->ComputeValue(0.0f,0.0f);
v1=SCurve->ComputeValue(1.0f,0.0f);
s0=SCurve->ComputeSlope(0.0f);
s1=SCurve->ComputeSlope(1.0f);
if(EditHan)
{
float cx=(float)point.x/rct.Width();
if(cx<0.00000001f || fabs(cx-1.0f)<0.00000001f) return;
if(SelectedKey<0)
s0=(newy-SCurve->ComputeValue(0.0f,0.0f))/cx;
else
s1=-((newy-SCurve->ComputeValue(1.0f,0.0f))/(1.0f-cx));
}
else
{
if(SelectedKey<0)
v0=newy;
else
v1=newy;
}
SCurve->SetCurve(v0,s0,v1,s1);
}
break;
case gosFX::Curve::e_ComplexType:
if(SelectedKey>=0)
{
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)Curve;
if(EditHan)
{
Stuff::Scalar val,tme,ntme;
tme=(*SCurve)[SCurve->GetKeyCount()-1].m_time;
val=(*SCurve)[SCurve->GetKeyCount()-1].m_value;
ntme=((float)point.x/rct.Width());
if(point.x<(tme*rct.Width()) || (ntme-tme)<0.000001f) return;
(*SCurve)[SCurve->GetKeyCount()-1].SetLinearKey(tme,val,newy,ntme-tme);
}
else
{
Stuff::Scalar tme,slp;
int MinX,MaxX;
if(SelectedKey==0)
MinX=0;
else
MinX=(int)ceil((*SCurve)[SelectedKey-1].m_time*rct.Width())+1;
if(SelectedKey==SCurve->GetKeyCount()-1)
MaxX=rct.Width();
else
MaxX=(int)floor((*SCurve)[SelectedKey+1].m_time*rct.Width())-1;
int xval=point.x;
xval=xval<MinX?MinX:xval;
xval=xval>MaxX?MaxX:xval;
// slp=(*SCurve)[SelectedKey].m_slope;
slp=SCurve->ComputeValue(1.0f,0.0f);
tme=(float)xval/rct.Width();
if(tme<1.0f)
{
(*SCurve)[SelectedKey].SetLinearKey(tme,newy,slp,1.0f-tme);
}
}
}
break;
default:
break;
} //end of cs type
FixCurve(Curve);
if(CurrentCSet)
CurrentCSet->VerifyAndPop();
theApp.ParamWin->DataPane->UpdateControls();
ReDraw();
}//end of If Curve
}
break;
case PAN:
{
float add;
add=((point.y-OldPoint.y)*(EndY-StartY))/rct.Height();
StartY+=add;
EndY+=add;
ReDraw();
}
break;
case SCALE:
{
gosFX::Curve *Curve=EditVar?VCurve:DCurve;
if(Curve)
{
Check_Object(Curve);
Stuff::DynamicMemoryStream stream;
if(CurrentCSet)
CurrentCSet->PushState();
float perchange;
perchange=(float)pow((EndY-StartY)/2,(float)(OldPoint.y-point.y)/rct.Height());
Curve->AxisScale(perchange,0.0f);
theApp.ParamWin->DataPane->UpdateControls();
ReDraw();
if(CurrentCSet)
CurrentCSet->VerifyAndPop();
}
}
break;
case ZOOM:
{
float perchange,add;
perchange=(float)pow(4.0,(float)(point.y-OldPoint.y)/rct.Height());
add=(EndY-StartY)*(1.0f-perchange);
StartY+=add;
EndY-=add;
ReDraw();
}
break;
}
OldPoint=point;
}
CWnd::OnMouseMove(nFlags, point);
}
void CCurveEditor::OnLButtonDown(UINT nFlags, CPoint point)
{
OldPoint=point;
switch(CurrentEditMode)
{
case INSERT:
{
CRect crct;
GetClientRect(&crct);
Stuff::DynamicMemoryStream stream;
if(CurrentCSet)
CurrentCSet->PushState();
gosFX::Curve *Curve=EditVar?VCurve:DCurve;
if(Curve && Curve->m_type==gosFX::Curve::e_ComplexType)
{
Check_Object(Curve);
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)Curve;
SelectedKey=SCurve->InsertKey((float)point.x/crct.Width());
}
if(CurrentCSet)
CurrentCSet->VerifyAndPop();
theApp.Modified=true;
ReDraw();
}
break;
case MOVE:
SetCapture();
SelectedKey=GetClosestKey(point);
ReDraw();
theApp.Modified=true;
break;
case PAN:
SetCapture();
break;
case SCALE:
SetCapture();
theApp.Modified=true;
break;
case ZOOM:
SetCapture();
break;
}
CWnd::OnLButtonDown(nFlags, point);
}
void CCurveEditor::UpdateCurveList(HTREEITEM itm)
{
if(itm==NULL) return;
if(itm!=TVI_ROOT)
{
CurveSet *CSet=(CurveSet *)theApp.ParamWin->TreePane->m_PTree.GetItemData(itm);
gosFX::Curve *curve;
if(CSet)
curve=CSet->Curve;
else
curve=NULL;
if(curve)
{
Check_Object(curve);
if(!DCurve && theApp.ParamWin->TreePane->m_PTree.GetSelectedItem()==itm)
{
CurrentCSet=CSet;
DCurve=curve->GetSubCurve(0);
VCurve=curve->GetSubCurve(1);
EditHan=false;
}
else
if(theApp.ParamWin->TreePane->m_PTree.GetCheck(itm))
{
Curves[NumCurves++]=curve->GetSubCurve(0);
Verify(NumCurves<MAXCURVES);
}
}
}
else
{
CurrentCSet=NULL;
NumCurves=0;
DCurve=VCurve=NULL;
EditHan=false;
}
//Draw Children
HTREEITEM nitm=theApp.ParamWin->TreePane->m_PTree.GetChildItem(itm);
while(nitm!=NULL)
{
UpdateCurveList(nitm);
nitm=theApp.ParamWin->TreePane->m_PTree.GetNextSiblingItem(nitm);
}
if(itm==TVI_ROOT) ReDraw();
}
int CCurveEditor::GetClosestKey(CPoint &pnt)
{
int i;
CRect crct;
GetClientRect(&crct);
int kx,ky;
int dist,lval=crct.Width()*crct.Width()+crct.Height()*crct.Height();
int lnum=0;
gosFX::Curve *Curve=EditVar?VCurve:DCurve;
if(!Curve) return -1;
Check_Object(Curve);
switch(Curve->m_type)
{
case gosFX::Curve::e_ConstantType:
{
gosFX::ConstantCurve *SCurve=(gosFX::ConstantCurve *)Curve;
return -1;
}
break;
case gosFX::Curve::e_LinearType:
{
gosFX::LinearCurve *SCurve=(gosFX::LinearCurve *)Curve;
if(pnt.x<crct.Width()/2) return -1; else return 0;
}
break;
case gosFX::Curve::e_SplineType:
{
gosFX::SplineCurve *SCurve=(gosFX::SplineCurve *)Curve;
int tval,lval,tdist,dist;
lval=0;
tval=(int)(pnt.y-CurveToClient(SCurve->ComputeValue(0.0f,0.0f),crct.Height()));
dist=pnt.x*pnt.x+tval*tval;
tval=(int)(pnt.y-CurveToClient(SCurve->ComputeValue(1.0f,0.0f),crct.Height()));
tdist=(pnt.x-crct.Width())*(pnt.x-crct.Width())+tval*tval;
if(tdist<dist) {dist=tdist; lval=1;}
tdist=(pnt.x-H1Pos.x)*(pnt.x-H1Pos.x)+(pnt.y-H1Pos.y)*(pnt.y-H1Pos.y);
if(tdist<dist) {dist=tdist; lval=2;}
tdist=(pnt.x-H2Pos.x)*(pnt.x-H2Pos.x)+(pnt.y-H2Pos.y)*(pnt.y-H2Pos.y);
if(tdist<dist) {dist=tdist; lval=3;}
switch(lval)
{
case 0: //left key
EditHan=false;
return -1;
break;
case 1: //right key
EditHan=false;
return 0;
break;
case 2: //left handle
EditHan=true;
return -1;
break;
case 3: //right handle
EditHan=true;
return 0;
break;
}
}
break;
case gosFX::Curve::e_ComplexType:
{
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)Curve;
kx=crct.Width();
ky=(int)CurveToClient(SCurve->ComputeValue(1.0f,0.0f),crct.Height());
lval=(pnt.x-kx)*(pnt.x-kx)+(pnt.y-ky)*(pnt.y-ky);
lnum=-1;
for(i=0;i<SCurve->GetKeyCount();i++)
{
kx=(int)((*SCurve)[i].m_time*crct.Width());
ky=(int)CurveToClient(SCurve->ComputeValue((*SCurve)[i].m_time,0.0f),crct.Height());
dist=(pnt.x-kx)*(pnt.x-kx)+(pnt.y-ky)*(pnt.y-ky);
if(dist<lval) {lval=dist; lnum=i; }
}
if(lnum<0)
{
EditHan=true;
return SCurve->GetKeyCount()-1;
}
else
{
EditHan=false;
return lnum;
}
}
break;
default:
break;
}
return -1;
}
void CCurveEditor::OnEditDeletevertex()
{
gosFX::Curve *Curve=EditVar?VCurve:DCurve;
if(!Curve || Curve->m_type!=gosFX::Curve::e_ComplexType) return;
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)Curve;
if(SelectedKey>0)
{
float cfx,cfy;
cfx=(*SCurve)[SelectedKey].m_time;
cfy=SCurve->ComputeValue(cfx,0.0f);
SCurve->DeleteKey(SelectedKey);
CRect crct;
GetClientRect(&crct);
SelectedKey=GetClosestKey(CPoint((long)(cfx*crct.Width()),CurveToClient(cfy,crct.Height())));
FixCurve(Curve);
}
else
{
int i;
for(i=1;i<SCurve->GetKeyCount();i++) SCurve->DeleteKey(i);
FixCurve(Curve);
}
ReDraw();
}
void CCurveEditor::FixCurve(gosFX::Curve *Curve)
{
switch(Curve->m_type)
{
case gosFX::Curve::e_SplineType:
{
gosFX::SplineCurve *SCurve=(gosFX::SplineCurve *)Curve;
}
break;
case gosFX::Curve::e_ComplexType:
{
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)Curve;
Stuff::Scalar cval,nval,ctme,ntme;
if(SCurve->GetKeyCount()==1)
{
cval=(*SCurve)[0].m_value;
nval=SCurve->ComputeValue(1.0f,0.0f);
(*SCurve)[0].SetLinearKey(0.0f,cval,nval,1.0f);
}
else
{
cval=(*SCurve)[0].m_value;
(*SCurve)[0].SetLinearKey(0.0f,cval,cval,0.01f);
}
// Connect the Keys
int key;
for(key=0;key<SCurve->GetKeyCount()-1;key++)
{
ctme=(*SCurve)[key].m_time;
ntme=(*SCurve)[key+1].m_time;
cval=(*SCurve)[key].m_value;
nval=(*SCurve)[key+1].m_value;
(*SCurve)[key].SetLinearKey(ctme,cval,nval,ntme-ctme);
}
}
break;
default:
break;
}
}
void CCurveEditor::OnViewZoomtocurve()
{
gosFX::Curve *Curve=EditVar?VCurve:DCurve;
if(Curve==NULL)
{
StartY=-100.0f;
EndY=100.0f;
return;
}
Curve->ExpensiveComputeRange(&StartY,&EndY);
float aval;
aval=(float)fabs(StartY);
aval=(float)fabs(EndY)>aval?(float)fabs(EndY):aval;
aval+=aval*0.2f;
StartY=-aval;
EndY=aval;
/*
if(StartY==EndY)
{
StartY-=.5;
EndY+=.5;
}
else
{
EndY+=(EndY-StartY)*0.1f;
StartY-=(EndY-StartY)*0.1f;
}
*/
ReDraw();
}
void CCurveEditor::DrawTicks(CDC *dc)
{
float cury,nexty;
int Ccury,Cnexty;
CRect rct;
GetClientRect(&rct);
dc->SelectObject(&TickPen);
CString lab;
CRect textrect;
dc->SetTextColor(0xffffff);
dc->SetBkColor(0x000000);
if(StartY<0)
{
cury=-StartY;
cury=(float)pow(10,(int)log10(cury));
Ccury=CurveToClient(-cury,rct.Height());
nexty=cury*0.1f;
Cnexty=CurveToClient(-nexty,rct.Height());
while((Ccury-Cnexty)>3 && Ccury>0 && -cury<EndY)
{
dc->MoveTo(0,Ccury);
dc->LineTo(rct.Width(),Ccury);
lab.Format("%5.3f",-cury);
textrect.top=Ccury-10; textrect.left=0;
textrect.bottom=Ccury+10; textrect.right=100;
dc->DrawText(lab,&textrect,DT_LEFT );
cury=nexty;
Ccury=Cnexty;
nexty=cury*0.1f;
Cnexty=CurveToClient(-nexty,rct.Height());
}
}
if(EndY>0)
{
cury=EndY;
cury=(float)pow(10,(int)log10(cury));
Ccury=CurveToClient(cury,rct.Height());
nexty=cury*0.1f;
Cnexty=CurveToClient(nexty,rct.Height());
while((Cnexty-Ccury)>3 && Ccury<rct.Height() && cury>StartY)
{
dc->MoveTo(0,Ccury);
dc->LineTo(rct.Width(),Ccury);
lab.Format("%5.3f",cury);
textrect.top=Ccury-10; textrect.left=0;
textrect.bottom=Ccury+10; textrect.right=100;
dc->DrawText(lab,&textrect,DT_LEFT );
cury=nexty;
Ccury=Cnexty;
nexty=cury*0.1f;
Cnexty=CurveToClient(nexty,rct.Height());
}
}
dc->SelectObject(&ZeroPen);
dc->MoveTo(0,CurveToClient(0,rct.Height()));
dc->LineTo(rct.Width(),CurveToClient(0,rct.Height()));
}
BOOL CCurveEditor::Create(LPCTSTR lpszClassName, LPCTSTR lpszWindowName, DWORD dwStyle, const RECT& rect, CWnd* pParentWnd, UINT nID, CCreateContext* pContext)
{
// TODO: Add your specialized code here and/or call the base class
return CWnd::Create(lpszClassName, lpszWindowName, dwStyle, rect, pParentWnd, nID, pContext);
}
int CCurveEditor::OnCreate(LPCREATESTRUCT lpCreateStruct)
{
if (CWnd::OnCreate(lpCreateStruct) == -1)
return -1;
LOGBRUSH lb;
lb.lbColor=0x00C800;
lb.lbStyle=BS_SOLID;
InactivePen.CreatePen(PS_SOLID,1,&lb);
lb.lbColor=0x7f7f7f;
lb.lbStyle=BS_SOLID;
TickPen.CreatePen(PS_DASHDOT,1,&lb);
lb.lbColor=0x00ffff;
lb.lbStyle=BS_SOLID;
ZeroPen.CreatePen(PS_DOT,1,&lb);
EditablePen.CreatePen(PS_SOLID,1,0x0000ff);
VarPen.CreatePen(PS_SOLID,1,0xff0000);
SelVertPen.CreatePen(PS_SOLID,1,0x00ff00);
BlackPen.CreatePen(PS_SOLID,1,(COLORREF)0x000000);
HandlePen.CreatePen(PS_SOLID,1,(COLORREF)0xff00ff);
BGBrush.CreateSolidBrush(0xC8C8C8);
return 0;
}
void CCurveEditor::ReDrawInternal()
{
if(theApp.ParamWin)
{
CDC *dc,*pDC=GetDC();
theApp.AllowDraw=false;
CDC bbufDC;
bbufDC.CreateCompatibleDC(pDC);
bbufDC.SelectObject(BackBuffer);
CRect crct;
GetClientRect(&crct);
// dc->SelectObject(&BGBrush);
// dc->Rectangle(crct);
/*
static bool flip=false;
flip=!flip;
pDC->BitBlt(0,0,crct.Width(),crct.Height(),NULL,0,0,flip?BLACKNESS:WHITENESS);
*/
dc=&bbufDC;
// dc=pDC;
dc->BitBlt(0,0,crct.Width(),crct.Height(),NULL,0,0,BLACKNESS);
int i;
dc->SelectObject(GetStockObject(NULL_BRUSH));
DrawTicks(dc);
dc->SelectObject(&InactivePen);
for(i=0;i<NumCurves;i++)
DrawCurve(dc,Curves[i]);
if(EditVar)
{
if(DCurve)
{
dc->SelectObject(&EditablePen);
DrawCurve(dc,DCurve);
}
if(VCurve)
{
dc->SelectObject(&VarPen);
DrawCurve(dc,VCurve,true);
}
}
else
{
if(VCurve)
{
dc->SelectObject(&VarPen);
DrawCurve(dc,VCurve);
}
if(DCurve)
{
dc->SelectObject(&EditablePen);
DrawCurve(dc,DCurve,true);
}
}
gosFX::Curve *Curve=EditVar?VCurve:DCurve;
//DrawHandles
dc->SelectObject(&HandlePen);
DrawHandles(dc,Curve);
//OverDrawSelected Key
dc->SelectObject(&SelVertPen);
if(Curve)
{
Check_Object(Curve);
switch(Curve->m_type)
{
case gosFX::Curve::e_ComplexType:
{
gosFX::ComplexCurve *SCurve=(gosFX::ComplexCurve *)Curve;
if(SelectedKey>=SCurve->GetKeyCount())
SelectedKey=-1;
if(SelectedKey!=-1)
{
float st=(*SCurve)[SelectedKey].m_time;
CPoint lpt;
lpt.x=(long)(st*crct.Width());
lpt.y=CurveToClient(SCurve->ComputeValue(st,0.0f),crct.Height());
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
}
break;
default:
if(SelectedKey<0)
{
CPoint lpt;
lpt.x=0;
lpt.y=CurveToClient(Curve->ExpensiveCompute(0.0f),crct.Height());
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
else
{
CPoint lpt;
lpt.x=crct.Width();
lpt.y=CurveToClient(Curve->ExpensiveCompute(1.0f),crct.Height());
dc->Rectangle(lpt.x-5,lpt.y-5,lpt.x+5,lpt.y+5);
}
break;
}
}
theApp.AllowDraw=true;
pDC->BitBlt(crct.left,crct.top,crct.Width(),crct.Height(),&bbufDC,0,0,SRCCOPY);
ReleaseDC(pDC);
}
}
void CCurveEditor::OnKeyDown(UINT nChar, UINT nRepCnt, UINT nFlags)
{
// TODO: Add your message handler code here and/or call default
switch(nChar)
{
case 'E':
OnEditMovemode();
break ;
case 'A':
OnEditInsertmode();
break ;
case 'Z':
OnEditZoommode();
break ;
case ' ':
OnEditPanmode();
break ;
case 'S':
OnEditScalemode();
break ;
case 'V':
OnEditEditvaraincecurve();
break ;
case 'F':
OnViewZoomtocurve();
break ;
case 'D':
OnEditDeletevertex();
break ;
}
CWnd::OnKeyDown(nChar, nRepCnt, nFlags);
}
void CCurveEditor::BuildBackBuffer()
{
BackBuffer.DeleteObject();
CRect crect;
GetClientRect(&crect);
CDC *pDC=GetDC();
BackBuffer.CreateCompatibleBitmap(pDC,crect.Width(),crect.Height());
ReleaseDC(pDC);
}
void CCurveEditor::OnSize(UINT nType, int cx, int cy)
{
CWnd::OnSize(nType, cx, cy);
BuildBackBuffer();
// TODO: Add your message handler code here
}