Added aqua_speed for rite geo 50 tryker
[ryzomcore.git] / nel / tools / 3d / object_viewer / sound_anim_view.cpp
bloba7c039e1cca25002e85fddebad12f9f37bff8f1e
1 // NeL - MMORPG Framework <http://dev.ryzom.com/projects/nel/>
2 // Copyright (C) 2010 Winch Gate Property Limited
3 //
4 // This source file has been modified by the following contributors:
5 // Copyright (C) 2019 Jan BOON (Kaetemi) <jan.boon@kaetemi.be>
6 //
7 // This program is free software: you can redistribute it and/or modify
8 // it under the terms of the GNU Affero General Public License as
9 // published by the Free Software Foundation, either version 3 of the
10 // License, or (at your option) any later version.
12 // This program is distributed in the hope that it will be useful,
13 // but WITHOUT ANY WARRANTY; without even the implied warranty of
14 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 // GNU Affero General Public License for more details.
17 // You should have received a copy of the GNU Affero General Public License
18 // along with this program. If not, see <http://www.gnu.org/licenses/>.
20 #include "std_afx.h"
21 #include "sound_anim_view.h"
22 #include "sound_anim_dlg.h"
23 #include "object_viewer.h"
25 #include "nel/sound/sound_animation.h"
26 #include "nel/sound/sound_anim_manager.h"
27 #include "nel/sound/sound_anim_marker.h"
29 using namespace std;
30 using namespace NLMISC;
31 using namespace NL3D;
32 using namespace NLSOUND;
35 IMPLEMENT_DYNCREATE(CSoundAnimView, CWnd)
39 BEGIN_MESSAGE_MAP(CSoundAnimView, CWnd)
40 //{{AFX_MSG_MAP(CSoundAnimView)
41 ON_WM_LBUTTONDOWN()
42 ON_WM_LBUTTONUP()
43 ON_WM_MOUSEMOVE()
44 ON_WM_PAINT()
45 //}}AFX_MSG_MAP
46 END_MESSAGE_MAP()
48 bool CSoundAnimView::_Registered = false;
49 CString CSoundAnimView::_WndClass;
50 uint CSoundAnimView::_WndId = 0;
51 const uint CSoundAnimView::_ZoomCount = 7;
52 float CSoundAnimView::_ZoomValue[] = { 0.1f, 0.25f, 0.5f, 1.0f, 2.0f, 4.0f, 10.0f };
53 const float CSoundAnimView::_Scale = 200.0f; // 1 second equals 200 pixels
54 CFont CSoundAnimView::_Font;
55 CBrush CSoundAnimView::_FillBrush;
56 CBrush CSoundAnimView::_MarkerBrush;
57 CBrush CSoundAnimView::_SelectBrush;
58 CPen CSoundAnimView::_RedPen;
61 // ***************************************************************************
63 bool CSoundAnimView::registerClass()
65 if (_Registered)
67 return true;
70 _WndClass = AfxRegisterWndClass(CS_VREDRAW | CS_HREDRAW, ::LoadCursor(NULL, IDC_ARROW), (HBRUSH) ::GetStockObject(WHITE_BRUSH));
72 // Do some additional initialization of static veriables
73 _Font.CreateFont(14, 0, 0, 0, FW_NORMAL, FALSE, FALSE, 0, ANSI_CHARSET, OUT_DEFAULT_PRECIS, CLIP_DEFAULT_PRECIS, DEFAULT_QUALITY, DEFAULT_PITCH | FF_SWISS, _T("Arial"));
74 _FillBrush.CreateSolidBrush(RGB(230, 245, 245));
75 _MarkerBrush.CreateSolidBrush(RGB(0, 0, 0));
76 _SelectBrush.CreateSolidBrush(RGB(0, 210, 210));
77 _RedPen.CreatePen(PS_SOLID, 1, RGB(255, 0, 0));
79 _Registered = true;
81 return true;
85 // ***************************************************************************
87 void CSoundAnimView::Create(CObjectViewer* objView, CAnimationDlg* animDlg, CSoundAnimDlg* sndDlg, const RECT& rect)
89 registerClass();
91 _ObjView = objView;
92 _AnimationDlg = animDlg;
93 _SoundAnimDlg = sndDlg;
94 _Zoom = 1.0f;
95 _Cursor = 0;
96 _TimeStart = 0.0f;
97 _TimeEnd = 0.0f;
98 _TimeOffset = 0.0f;
99 _PixelsTotal = 0;
100 _PixelsOffset = 0;
101 _PixelsViewH = rect.right - rect.left;
102 _PixelsViewV = rect.bottom - rect.top;
103 _Dragging = false;
104 _SelectedAnim = 0;
105 _SelectedMarker = 0;
107 // Find the zoom index dynamically so we can change the _ZoomValue array
108 // withou risk of using a bad _ZoomIndex
109 for (uint i = 0; i < _ZoomCount; i++)
111 if (_ZoomValue[i] == 1.0f)
113 _ZoomIndex = i;
114 break;
119 CWnd::Create((LPCTSTR) _WndClass, _T("Sound Animation"), WS_CHILD | WS_VISIBLE, rect, (CWnd*) sndDlg, ++_WndId);
122 // ********************************************************
124 void CSoundAnimView::changeTimeScale()
126 _PixelsTotal = timeToPixel(_TimeEnd - _TimeStart);
127 _PixelsOffset = timeToPixel(_TimeOffset - _TimeStart);
130 if (_PixelsTotal < _PixelsViewH)
132 _PixelsOffset = 0;
133 _TimeOffset = _TimeStart;
134 _SoundAnimDlg->updateScroll(0, 0, 0);
136 else if (_PixelsOffset + _PixelsViewH > _PixelsTotal)
138 _PixelsOffset = _PixelsTotal - _PixelsViewH;
139 _TimeOffset = _TimeStart + pixelToTime(_PixelsOffset);
140 _SoundAnimDlg->updateScroll(_PixelsOffset, 0, _PixelsTotal - _PixelsViewH);
142 else
144 _SoundAnimDlg->updateScroll(_PixelsOffset, 0, _PixelsTotal - _PixelsViewH);
147 Invalidate();
150 // ********************************************************
152 void CSoundAnimView::changeScroll(uint curpos)
154 _PixelsOffset = curpos;
155 _TimeOffset = _TimeStart + pixelToTime(_PixelsOffset);
156 Invalidate();
159 // ********************************************************
161 void CSoundAnimView::zoomIn()
163 if (_ZoomIndex < _ZoomCount - 1)
165 _ZoomIndex++;
166 _Zoom = _ZoomValue[_ZoomIndex];
169 changeTimeScale();
172 // ********************************************************
174 void CSoundAnimView::zoomOut()
176 if (_ZoomIndex > 0)
178 _ZoomIndex--;
179 _Zoom = _ZoomValue[_ZoomIndex];
182 changeTimeScale();
185 // ********************************************************
187 void CSoundAnimView::setAnimTime(float animStart, float animEnd)
189 _TimeStart = animStart / _AnimationDlg->getSpeed();
190 _TimeEnd = animEnd / _AnimationDlg->getSpeed();
192 changeTimeScale();
195 // ********************************************************
197 void CSoundAnimView::mark()
199 insertMarkerAt(_AnimationDlg->getTime());
202 // ********************************************************
204 void CSoundAnimView::save()
206 CAnimationVector::iterator iter;
207 for (iter = _Animations.begin(); iter != _Animations.end(); iter++)
209 CSoundAnimationHolder &h = *iter;
210 CSoundAnimation* anim = h._Anim;
212 if (anim->isDirty())
214 string filename = anim->getFilename();
216 // Ask user for filename
217 if (filename.empty())
219 filename.append(anim->getName()).append(".sound_anim");
221 // Create a dialog
222 TCHAR BASED_CODE szFilter[] = _T("NeL Sound Animations (*.sound_anim)|*.sound_anim|All Files (*.*)|*.*||");
223 CFileDialog fileDlg(FALSE, _T(".sound_anim"), nlUtf8ToTStr(filename), OFN_HIDEREADONLY | OFN_OVERWRITEPROMPT, szFilter);
225 if (fileDlg.DoModal() == IDOK)
227 filename = tStrToUtf8(fileDlg.GetPathName());
229 else
231 continue;
235 // Open the file
238 CSoundAnimManager::instance()->saveAnimation(anim, filename);
240 catch (const Exception& e)
242 MessageBox(nlUtf8ToTStr(e.what()), _T("NeL object viewer"), MB_OK | MB_ICONEXCLAMATION);
248 Invalidate();
251 // ********************************************************
253 void CSoundAnimView::deleteMarker()
255 if (_SelectedMarker != 0)
257 _SelectedAnim._Anim->removeMarker(_SelectedMarker);
258 _SelectedAnim._Anim->setDirty(true);
259 Invalidate();
263 // ********************************************************
265 bool CSoundAnimView::getAnimationAt(CSoundAnimationHolder& holder, float time)
267 CAnimationVector::iterator iter;
268 for (iter = _Animations.begin(); iter != _Animations.end(); iter++)
270 CSoundAnimationHolder &h = *iter;
271 if ((h._AnimStart <= time) && (time < h._AnimEnd))
273 holder = h;
274 return true;
278 return false;
281 // ********************************************************
283 void CSoundAnimView::refresh(BOOL update)
285 _Animations.clear();
287 uint selected = _ObjView->getEditedObject();
288 if (selected == 0xffffffff)
290 return;
293 CSoundAnimManager* animManager = CSoundAnimManager::instance();
295 // Make sure the sound anim manager is already instanciated
296 if (animManager == 0)
298 return;
301 CInstanceInfo *instanceInfo = _ObjView->getInstance(selected);
303 // Some animation in the list ?
304 if (!instanceInfo->Saved.PlayList.empty())
306 // Accumul time
307 float startTime = 0;
308 float endTime = 0;
310 // Get start time of the animation that starts before the current time
311 for (uint index = 0; index < instanceInfo->Saved.PlayList.size(); index++)
313 // Pointer on the animation
314 string& name = instanceInfo->Saved.PlayList[index];
315 CAnimation *anim = instanceInfo->AnimationSet.getAnimation (instanceInfo->AnimationSet.getAnimationIdByName(name));
317 // Add start time
318 startTime = endTime;
319 endTime = startTime + anim->getEndTime() - anim->getBeginTime();
321 CSoundAnimation* soundAnim = animManager->findAnimation(name);
323 if (soundAnim == 0)
325 bool needCreate = false;
328 TSoundAnimId res = animManager->loadAnimation(name);
329 if(res == CSoundAnimationNoId)
330 needCreate = true;
331 else
332 soundAnim = animManager->findAnimation(name);
334 catch (const exception& e)
336 nlwarning("Couldn't find sound animation <%s>: %s", name.c_str(), e.what());
337 needCreate = true;
339 if(needCreate)
341 animManager->createAnimation(name);
342 soundAnim = animManager->findAnimation(name);
346 CSoundAnimationHolder holder(soundAnim, startTime, endTime);
348 _Animations.push_back(holder);
352 Invalidate();
355 // ********************************************************
357 void CSoundAnimView::updateCursor()
359 sint cursor = timeToPixel(_AnimationDlg->getTime());
361 if (cursor != _Cursor)
363 RECT r;
365 r.left = (cursor < _Cursor)? cursor : _Cursor;
366 r.right = (cursor < _Cursor)? _Cursor + 1 : cursor + 1;
367 r.top = 0;
368 r.bottom = _PixelsViewV;
370 // correct for offset
371 r.left -= _PixelsOffset;
372 r.right -= _PixelsOffset;
374 InvalidateRect(&r);
376 _Cursor = cursor;
380 // ********************************************************
382 CSoundAnimMarker* CSoundAnimView::getMarkerAt(CPoint point)
384 CSoundAnimationHolder holder;
387 //nldebug("TIME=%f", pixelToTime(_PixelsOffset + point.x));
389 if (getAnimationAt(holder, pixelToTime(_PixelsOffset + point.x)))
391 CSoundAnimation* anim = holder._Anim;
392 float offset = holder._AnimStart;
393 uint32 nmarkers = anim->countMarkers();
395 for (uint32 i = 0; i < nmarkers; i++)
397 CSoundAnimMarker* marker = anim->getMarker(i);
398 uint pixel = timeToPixel(offset + marker->getTime()) - _PixelsOffset;
400 ::CRect r;
401 r.left = pixel - 4;
402 r.right = pixel + 5;
403 r.top = 0;
404 r.bottom = _PixelsViewV;
406 if (r.PtInRect(point))
408 return marker;
412 return 0;
415 // ********************************************************
417 void CSoundAnimView::insertMarkerAt(float time)
419 CSoundAnimationHolder holder;
421 if (getAnimationAt(holder, time))
423 CSoundAnimation* anim = holder._Anim;
425 CSoundAnimMarker* marker = new CSoundAnimMarker((float)(time - holder._AnimStart));
426 anim->addMarker(marker);
427 anim->setDirty(true);
429 _SelectedMarker = marker;
430 _SelectedAnim = holder;
431 _SoundAnimDlg->selectMarker(marker);
434 Invalidate();
437 // ***************************************************************************
439 void CSoundAnimView::OnLButtonDown(UINT nFlags, CPoint point)
441 CSoundAnimMarker* marker = getMarkerAt(point);
443 if (marker != 0)
445 float time = pixelToTime(_PixelsOffset + point.x);
446 _Dragging = true;
447 _DragStartPoint = point;
448 _DragStartTime = marker->getTime();
449 _SelectedMarker = marker;
450 getAnimationAt(_SelectedAnim, time);
452 else
454 _SelectedMarker = 0;
455 _SelectedAnim = 0;
459 // ***************************************************************************
461 void CSoundAnimView::OnLButtonUp(UINT nFlags, CPoint point)
463 float time = pixelToTime(point.x);
465 if (nFlags == MK_CONTROL)
467 insertMarkerAt(time);
469 else if (nFlags == 0)
471 _SoundAnimDlg->selectMarker(_SelectedMarker);
472 if (_Dragging)
474 _Dragging = false;
478 Invalidate();
481 // ********************************************************
483 void CSoundAnimView::OnLButtonDblClk(UINT nFlags, CPoint point)
485 float time = pixelToTime(point.x);
486 CSoundAnimationHolder holder;
488 if (getAnimationAt(holder, time))
490 nlwarning("CSoundAnimView::OnLButtonDblClk: x=%d, t=%.3f", point.x, time);
494 // ***************************************************************************
496 void CSoundAnimView::OnMouseMove(UINT nFlags, CPoint point)
498 if (_Dragging && (_SelectedMarker != 0) && (point.x != _DragStartPoint.x))
500 sint32 deltaPx = point.x - _DragStartPoint.x;
501 float newTime = _DragStartTime + pixelToTime(point.x - _DragStartPoint.x);
502 clamp(newTime, 0.0f, _SelectedAnim._AnimEnd - _SelectedAnim._AnimStart);
503 _SelectedMarker->setTime(newTime);
504 _SelectedAnim._Anim->setDirty(true);
505 Invalidate();
509 // ***************************************************************************
511 void CSoundAnimView::OnPaint()
513 PAINTSTRUCT ps;
514 CDC* dc = BeginPaint(&ps);
516 RECT r;
517 GetClientRect(&r);
518 dc->Rectangle(&r);
520 // Shift the origin according to the scroll offset
521 CPoint p = dc->GetViewportOrg();
522 p.Offset(- (sint) _PixelsOffset, 0);
523 dc->SetViewportOrg(p);
526 CAnimationVector::iterator iter;
527 sint lastPixel = 0;
529 dc->MoveTo(0, _PixelsViewV - 15);
530 dc->LineTo(_PixelsTotal, _PixelsViewV - 15);
532 for (iter = _Animations.begin(); iter != _Animations.end(); iter++)
534 CSoundAnimationHolder &holder = *iter;
536 if (holder._Anim == NULL) continue;
538 dc->MoveTo(timeToPixel(holder._AnimStart), 0);
539 dc->LineTo(timeToPixel(holder._AnimStart), _PixelsViewV);
541 r.left = timeToPixel(holder._AnimStart) + 3;
542 r.right = timeToPixel(holder._AnimEnd) - 3;
543 r.top = 0;
544 r.bottom = 20;
546 CGdiObject* oldFont = (CGdiObject*) dc->SelectObject(&_Font);
547 _StringBuffer.erase();
548 _StringBuffer.append(holder._Anim->getName());
549 if (holder._Anim->isDirty())
551 _StringBuffer.append("*");
553 dc->DrawText(_StringBuffer.c_str(), &r, DT_VCENTER | DT_LEFT | DT_SINGLELINE);
554 dc->SelectObject(oldFont);
556 lastPixel = timeToPixel(holder._AnimEnd);
558 // Draw the markers of the animation
559 CSoundAnimation* anim = holder._Anim;
560 float offset = holder._AnimStart;
561 uint32 nmarkers = anim->countMarkers();
562 for (uint32 i = 0; i < nmarkers; i++)
564 CSoundAnimMarker* marker = anim->getMarker(i);
565 sint pixel = timeToPixel(offset + marker->getTime());
567 r.left = pixel - 3;
568 r.right = pixel + 3;
569 r.top = _PixelsViewV - 20 ;
570 r.bottom = _PixelsViewV - 10;
572 dc->FillRect(&r, (_SelectedMarker == marker)? &_SelectBrush : &_MarkerBrush);
576 dc->MoveTo(lastPixel, 0);
577 dc->LineTo(lastPixel, _PixelsViewV);
580 if (lastPixel < (sint) _PixelsViewH)
582 r.left = lastPixel + 1;
583 r.right = _PixelsViewH - 1;
584 r.top = 1;
585 r.bottom = _PixelsViewV - 1;
586 dc->FillRect(&r, &_FillBrush);
589 CPen* oldPen = (CPen*) dc->SelectObject(&_RedPen);
590 dc->MoveTo(_Cursor, 0);
591 dc->LineTo(_Cursor, _PixelsViewV);
592 dc->SelectObject(oldPen);
594 EndPaint(&ps);
598 #ifdef _DEBUG
600 // ***************************************************************************
602 void CSoundAnimView::AssertValid() const
604 CWnd::AssertValid();
607 // ***************************************************************************
609 void CSoundAnimView::Dump(CDumpContext& dc) const
611 CWnd::Dump(dc);
614 #endif //_DEBUG