khanat-opennel-code/code/nel/tools/3d/object_viewer/animation_dlg.cpp
2010-12-21 15:37:27 +01:00

431 lines
10 KiB
C++

// NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
// Copyright (C) 2010 Winch Gate Property Limited
//
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU Affero 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 Affero General Public License for more details.
//
// You should have received a copy of the GNU Affero General Public License
// along with this program. If not, see <http://www.gnu.org/licenses/>.
#include "std_afx.h"
#include "object_viewer.h"
#include "animation_dlg.h"
#include <math.h>
#include <nel/misc/time_nl.h>
using namespace NLMISC;
using namespace NL3D;
#define SPEED_FOREWARD 3
/////////////////////////////////////////////////////////////////////////////
// CAnimationDlg dialog
CAnimationDlg::CAnimationDlg(class CObjectViewer* main, CWnd* pParent /*=NULL*/)
: CDialog(CAnimationDlg::IDD, pParent)
{
//{{AFX_DATA_INIT(CAnimationDlg)
End = 0.0f;
Speed = 30.0f;
Start = 0.0f;
Loop = TRUE;
UICurrentFrame = 0;
CurrentFrame = 0.0f;
Inplace = FALSE;
IncPos = TRUE;
//}}AFX_DATA_INIT
LastFrame = 0;
Playing=false;
Main=main;
}
void CAnimationDlg::DoDataExchange(CDataExchange* pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(CAnimationDlg)
DDX_Control(pDX, IDC_FRW, FRWCtrl);
DDX_Control(pDX, IDC_FFW, FFWCtrl);
DDX_Control(pDX, IDC_TIME_LINE, TimeLineCtrl);
DDX_Control(pDX, IDC_PLAY, PlayCtrl);
DDX_Control(pDX, IDC_STOP, StopCtrl);
DDX_Text(pDX, IDC_END_EDIT, End);
DDX_Text(pDX, IDC_SPEED, Speed);
DDX_Text(pDX, IDC_START_EDIT, Start);
DDX_Check(pDX, IDC_LOOP, Loop);
DDX_Text(pDX, IDC_CURRENT_FRAME, UICurrentFrame);
DDX_Check(pDX, IDC_INPLACE, Inplace);
DDX_Check(pDX, IDC_INC_POS, IncPos);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(CAnimationDlg, CDialog)
//{{AFX_MSG_MAP(CAnimationDlg)
ON_BN_CLICKED(IDC_END, OnEnd)
ON_BN_CLICKED(IDC_PLAY, OnPlay)
ON_BN_CLICKED(IDC_STOP, OnStop)
ON_EN_CHANGE(IDC_CURRENT_FRAME, OnChangeCurrentFrame)
ON_EN_CHANGE(IDC_END_EDIT, OnChangeEndEdit)
ON_EN_CHANGE(IDC_SPEED, OnChangeSpeed)
ON_BN_CLICKED(IDC_START, OnStart)
ON_EN_CHANGE(IDC_START_EDIT, OnChangeStartEdit)
ON_WM_HSCROLL()
ON_WM_DESTROY()
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
/////////////////////////////////////////////////////////////////////////////
// CAnimationDlg message handlers
void CAnimationDlg::OnEnd()
{
UpdateData ();
CurrentFrame=End;
LastFrame=End;
UICurrentFrame=(int)CurrentFrame;
UpdateData (FALSE);
updateBar ();
}
void CAnimationDlg::OnPlay()
{
// play
UpdateData ();
StopCtrl.SetCheck (0);
PlayCtrl.SetCheck (1);
PlayCtrl.EnableWindow (FALSE);
StopCtrl.EnableWindow (TRUE);
if (!Playing)
{
Playing=true;
}
Main->enableFXs(true);
}
void CAnimationDlg::OnStop()
{
// Is checked ?
UpdateData ();
Playing=false;
StopCtrl.SetCheck (1);
PlayCtrl.SetCheck (0);
PlayCtrl.EnableWindow (TRUE);
StopCtrl.EnableWindow (FALSE);
UpdateData (FALSE);
Main->enableFXs(false);
}
void CAnimationDlg::OnChangeCurrentFrame()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// Update values
UpdateData ();
// Clamp current frame
clamp (UICurrentFrame, (int)Start, (int)End);
CurrentFrame=(float)UICurrentFrame;
LastFrame=CurrentFrame;
// Update
updateBar ();
UpdateData (FALSE);
}
void CAnimationDlg::OnChangeEndEdit()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// TODO: Add your control notification handler code here
// Update values
UpdateData ();
// Clamp current frame
if (End<Start)
Start=End;
if (End<CurrentFrame)
{
CurrentFrame=End;
LastFrame=End;
}
UICurrentFrame=(int)CurrentFrame;
// Update
UpdateData (FALSE);
Main->setAnimTime (Start, End);
}
void CAnimationDlg::OnChangeSpeed()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
UpdateData();
if (Speed<=0.001f)
Speed=0.001f;
Start=Speed*Start;
End=Speed*End;
UpdateData(FALSE);
Main->setAnimTime (Start, End);
}
void CAnimationDlg::OnStart()
{
UpdateData ();
CurrentFrame=Start;
LastFrame=Start;
UICurrentFrame=(int)CurrentFrame;
UpdateData (FALSE);
updateBar ();
}
void CAnimationDlg::OnChangeStartEdit()
{
// TODO: If this is a RICHEDIT control, the control will not
// send this notification unless you override the CDialog::OnInitDialog()
// function and call CRichEditCtrl().SetEventMask()
// with the ENM_CHANGE flag ORed into the mask.
// Update values
UpdateData ();
// Clamp current frame
if (End<Start)
End=Start;
if (CurrentFrame<Start)
{
CurrentFrame=Start;
LastFrame=Start;
}
UICurrentFrame=(int)CurrentFrame;
// Update
UpdateData (FALSE);
Main->setAnimTime (Start, End);
}
void CAnimationDlg::OnHScroll(UINT nSBCode, UINT nPos, CScrollBar* pScrollBar)
{
// TODO: Add your message handler code here and/or call default
// Drag the time line ?
if (pScrollBar==GetDlgItem (IDC_TIME_LINE))
{
// Update values
UpdateData ();
// Setup current pos
CurrentFrame=(float)TimeLineCtrl.GetPos()*(End-Start)/65535.f+Start;
CurrentFrame=(float)floor(CurrentFrame+0.5f);
LastFrame=CurrentFrame;
UICurrentFrame=(int)CurrentFrame;
// Update values
UpdateData (FALSE);
}
CDialog::OnHScroll(nSBCode, nPos, pScrollBar);
}
void CAnimationDlg::handle ()
{
// New time
uint64 newTime=NLMISC::CTime::getLocalTime ();
// Forward or rewind ?
bool forward=(((CButton*)GetDlgItem (IDC_FFW))->GetState()&BST_PUSHED)!=0;
bool rewind=(((CButton*)GetDlgItem (IDC_FRW))->GetState()&BST_PUSHED)!=0;
// If play, back last frame
if (Playing)
LastFrame=CurrentFrame;
if (forward||rewind||Playing)
{
UpdateData ();
// Delta time
uint deltaTime=(uint)(newTime-LastTime);
if (forward)
{
// Fast forward
CurrentFrame+=(float)((float)deltaTime*SPEED_FOREWARD*Speed/1000.0);
}
else if (rewind)
{
// Fast rewind
CurrentFrame-=(float)((float)deltaTime*SPEED_FOREWARD*Speed/1000.0);
}
else
{
// Compute new time
if (Playing)
{
CurrentFrame+=(float)((float)deltaTime*Speed/1000.0);
}
}
// Loop
if (Loop&&(!forward)&&(!rewind)&&Playing)
{
float backup = CurrentFrame;
CurrentFrame=(float)fmod ((CurrentFrame-Start), End-Start)+Start;
if (backup!=CurrentFrame)
{
LastFrame = CurrentFrame;
Main->enableFXs(false);
Main->enableFXs(true);
}
}
// Clamp time
if (CurrentFrame>End)
{
CurrentFrame=End;
LastFrame=CurrentFrame;
UpdateData (FALSE);
// Stop animation
OnStop ();
}
if (CurrentFrame<Start)
{
CurrentFrame=Start;
LastFrame=CurrentFrame;
UpdateData (FALSE);
// Stop animation
OnStop ();
}
UICurrentFrame=(int)CurrentFrame;
UpdateData (FALSE);
updateBar ();
}
// If not play, copy current frame
if (!Playing)
LastFrame=CurrentFrame;
// Setup new time
LastTime=newTime;
}
BOOL CAnimationDlg::OnInitDialog()
{
CDialog::OnInitDialog();
// Stop
LastTime=NLMISC::CTime::getLocalTime ();
StopCtrl.SetCheck (1);
// Set time line range
TimeLineCtrl.SetRangeMin (0);
TimeLineCtrl.SetRangeMax (65535);
// Update the time line
updateBar ();
return TRUE; // return TRUE unless you set the focus to a control
// EXCEPTION: OCX Property Pages should return FALSE
}
void CAnimationDlg::setAnimTime (float animStart, float animEnd)
{
UpdateData();
Start=animStart;
End=animEnd;
UpdateData(FALSE);
updateBar ();
}
void CAnimationDlg::updateBar ()
{
// Update value
UpdateData();
// Set cursor position
int position;
if (fabs (End-Start)<0.00001f)
position=0;
else
position=(int)((CurrentFrame-Start)*65535.f/(End-Start));
clamp (position, 0, 65535);
TimeLineCtrl.SetPos(position);
// Update value
UpdateData (FALSE);
}
NL3D::TAnimationTime CAnimationDlg::getTime ()
{
// Return current time in second
return CurrentFrame/Speed;
}
NL3D::TAnimationTime CAnimationDlg::getLastTime ()
{
// Return current time in second
return LastFrame/Speed;
}
void CAnimationDlg::OnDestroy()
{
setRegisterWindowState (this, REGKEY_OBJ_VIEW_ANIMATION_DLG);
CDialog::OnDestroy();
}
void CAnimationDlg::setCurrentFrame (float currentFrame)
{
// Update values
UpdateData ();
// Setup current pos
CurrentFrame=currentFrame;
LastFrame=CurrentFrame;
UICurrentFrame=(int)CurrentFrame;
// Update values
UpdateData (FALSE);
updateBar ();
}
BOOL CAnimationDlg::EnableWindow(BOOL enable /*=TRUE*/)
{
PlayCtrl.EnableWindow(Playing && enable);
StopCtrl.EnableWindow(FALSE);
FRWCtrl.EnableWindow(enable);
FFWCtrl.EnableWindow(enable);
TimeLineCtrl.EnableWindow(enable);
PlayCtrl.EnableWindow(enable);
StopCtrl.EnableWindow(enable);
GetDlgItem(IDC_END)->EnableWindow(enable);
GetDlgItem(IDC_START)->EnableWindow(enable);
GetDlgItem(IDC_LOOP)->EnableWindow(enable);
GetDlgItem(IDC_START_EDIT)->EnableWindow(enable);
GetDlgItem(IDC_CURRENT_FRAME)->EnableWindow(enable);
GetDlgItem(IDC_SPEED)->EnableWindow(enable);
GetDlgItem(IDC_END_EDIT)->EnableWindow(enable);
return TRUE;
}