// 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; }