/*========================================================================= Program: ParaView Module: vtkPVKeyFrameCueManipulator.cxx Copyright (c) Kitware, Inc. All rights reserved. See Copyright.txt or http://www.paraview.org/HTML/Copyright.html for details. This software is distributed WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the above copyright notice for more information. =========================================================================*/ #include "vtkPVKeyFrameCueManipulator.h" #include "vtkCommand.h" #include "vtkObjectFactory.h" #include "vtkPVKeyFrame.h" #include //**************************************************************************** class vtkPVKeyFrameCueManipulatorObserver : public vtkCommand { public: static vtkPVKeyFrameCueManipulatorObserver* New() { return new vtkPVKeyFrameCueManipulatorObserver; } void SetKeyFrameAnimationCueManipulatorProxy( vtkPVKeyFrameCueManipulator* proxy) { this->KeyFrameAnimationCueManipulatorProxy = proxy; } virtual void Execute(vtkObject* obj, unsigned long event, void* calldata) { if (this->KeyFrameAnimationCueManipulatorProxy) { this->KeyFrameAnimationCueManipulatorProxy->ExecuteEvent(obj, event, calldata); } } protected: vtkPVKeyFrameCueManipulatorObserver() { this->KeyFrameAnimationCueManipulatorProxy = 0; } vtkPVKeyFrameCueManipulator* KeyFrameAnimationCueManipulatorProxy; }; //---------------------------------------------------------------------------- class vtkPVKeyFrameCueManipulatorInternals { public: typedef std::vector KeyFrameVector; KeyFrameVector KeyFrames; }; //**************************************************************************** vtkStandardNewMacro(vtkPVKeyFrameCueManipulator); //---------------------------------------------------------------------------- vtkPVKeyFrameCueManipulator::vtkPVKeyFrameCueManipulator() { this->Internals = new vtkPVKeyFrameCueManipulatorInternals; this->Observer = vtkPVKeyFrameCueManipulatorObserver::New(); this->Observer->SetKeyFrameAnimationCueManipulatorProxy(this); this->SendEndEvent = 0; this->LastAddedKeyFrameIndex = 0; } //---------------------------------------------------------------------------- vtkPVKeyFrameCueManipulator::~vtkPVKeyFrameCueManipulator() { this->RemoveAllKeyFrames(); delete this->Internals; this->Observer->Delete(); } //---------------------------------------------------------------------------- void vtkPVKeyFrameCueManipulator::Initialize(vtkPVAnimationCue*) { this->SendEndEvent = 1; } //---------------------------------------------------------------------------- void vtkPVKeyFrameCueManipulator::Finalize(vtkPVAnimationCue* cue) { if (this->SendEndEvent) { this->UpdateValue(1.0, cue); } } //---------------------------------------------------------------------------- int vtkPVKeyFrameCueManipulator::AddKeyFrame(vtkPVKeyFrame* keyframe) { int index = this->AddKeyFrameInternal(keyframe); if (index != -1) { keyframe->AddObserver(vtkCommand::ModifiedEvent, this->Observer); keyframe->Register(this); //this->UpdateKeyTimeDomains(); } this->LastAddedKeyFrameIndex = index; this->Modified(); return index; } //---------------------------------------------------------------------------- void vtkPVKeyFrameCueManipulator::RemoveKeyFrame(vtkPVKeyFrame* keyframe) { if (this->RemoveKeyFrameInternal(keyframe)) { keyframe->RemoveObservers(vtkCommand::ModifiedEvent, this->Observer); keyframe->UnRegister(this); //this->UpdateKeyTimeDomains(); } this->Modified(); } //---------------------------------------------------------------------------- void vtkPVKeyFrameCueManipulator::RemoveAllKeyFrames() { vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator iter; for (iter = this->Internals->KeyFrames.begin(); iter != this->Internals->KeyFrames.end(); iter++) { (*iter)->RemoveObservers(vtkCommand::ModifiedEvent, this->Observer); (*iter)->UnRegister(this); } this->Internals->KeyFrames.clear(); this->Modified(); } //---------------------------------------------------------------------------- unsigned int vtkPVKeyFrameCueManipulator::GetNumberOfKeyFrames() { return static_cast(this->Internals->KeyFrames.size()); } //---------------------------------------------------------------------------- vtkPVKeyFrame* vtkPVKeyFrameCueManipulator::GetKeyFrame(double time) { vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator iter; for (iter = this->Internals->KeyFrames.begin(); iter != this->Internals->KeyFrames.end(); iter++) { if ( (*iter)->GetKeyTime() == time) { return *iter; } } return NULL; } //---------------------------------------------------------------------------- vtkPVKeyFrame* vtkPVKeyFrameCueManipulator::GetStartKeyFrame(double time) { // we use the fact that we have maintained the vector in sorted order. vtkPVKeyFrame* proxy = NULL; vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator it = this->Internals->KeyFrames.begin(); for (; it != this->Internals->KeyFrames.end(); it++) { double cur_time = (*it)->GetKeyTime(); if ( cur_time == time) { return *it; } if ( cur_time > time) { return proxy; } proxy = *it;; } return NULL; } //---------------------------------------------------------------------------- vtkPVKeyFrame* vtkPVKeyFrameCueManipulator::GetEndKeyFrame(double time) { vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator it = this->Internals->KeyFrames.begin(); for (; it != this->Internals->KeyFrames.end(); it++) { if ( (*it)->GetKeyTime() >= time) { return *it; } } return NULL; } //---------------------------------------------------------------------------- void vtkPVKeyFrameCueManipulator::UpdateValue(double currenttime, vtkPVAnimationCue* cue) { if (!cue) { vtkErrorMacro("UpdateValue called with invalid arguments"); return; } if (this->GetNumberOfKeyFrames() < 2) { //vtkErrorMacro("Too few keyframe to animate."); return; } vtkPVKeyFrame* startKF = this->GetStartKeyFrame(currenttime); vtkPVKeyFrame* endKF = this->GetEndKeyFrame(currenttime); if (endKF && startKF == NULL) { // This means that we are at a time location before the first keyframe in // this cue. In that case, simply duplicate the first key-frame as the // chosen one. endKF->UpdateValue(0, cue, endKF); this->InvokeEvent(vtkPVCueManipulator::StateModifiedEvent); } if (startKF && endKF) { // normalized time to the range between start key frame and end key frame. double ctime = 0; double tmin = startKF->GetKeyTime(); double tmax = endKF->GetKeyTime(); if (tmin != tmax) { ctime = (currenttime - tmin)/ (tmax-tmin); } startKF->UpdateValue(ctime, cue, endKF); this->InvokeEvent(vtkPVCueManipulator::StateModifiedEvent); } // check to see if the curtime has crossed the last key frame and if // we should make the state of the property as left by the last key frame. else if (this->SendEndEvent) { int num = this->GetNumberOfKeyFrames(); vtkPVKeyFrame* lastKF = this->GetKeyFrameAtIndex(num-1); if (currenttime >= lastKF->GetKeyTime()) { lastKF->UpdateValue(0, cue,lastKF); this->SendEndEvent = 0; this->InvokeEvent(vtkPVCueManipulator::StateModifiedEvent); } } } //---------------------------------------------------------------------------- vtkPVKeyFrame* vtkPVKeyFrameCueManipulator::GetNextKeyFrame( vtkPVKeyFrame* keyFrame) { vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator it = this->Internals->KeyFrames.begin(); for (; it != this->Internals->KeyFrames.end(); it++) { if ( *it == keyFrame) { it++; if (it != this->Internals->KeyFrames.end()) { return (*it); } break; } } return NULL; } //---------------------------------------------------------------------------- vtkPVKeyFrame* vtkPVKeyFrameCueManipulator::GetPreviousKeyFrame( vtkPVKeyFrame* keyFrame) { vtkPVKeyFrame* proxy = NULL; vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator it = this->Internals->KeyFrames.begin(); for (; it != this->Internals->KeyFrames.end(); it++) { if ( *it == keyFrame) { return proxy; } proxy = *it; } return NULL; } //---------------------------------------------------------------------------- vtkPVKeyFrame* vtkPVKeyFrameCueManipulator::GetKeyFrameAtIndex(int index) { if (index < 0 || index >= static_cast(this->GetNumberOfKeyFrames())) { vtkErrorMacro("Index beyond range"); return NULL; } return this->Internals->KeyFrames[index]; } //---------------------------------------------------------------------------- void vtkPVKeyFrameCueManipulator::ExecuteEvent( vtkObject* obj, unsigned long event, void* ) { vtkPVKeyFrame* keyframe = vtkPVKeyFrame::SafeDownCast(obj); if (keyframe && event == vtkCommand::ModifiedEvent) { // Check if the keyframe position has changed. vtkPVKeyFrame* prev = this->GetPreviousKeyFrame(keyframe); vtkPVKeyFrame* next = this->GetNextKeyFrame(keyframe); double keytime = keyframe->GetKeyTime(); if ( (next && keytime > next->GetKeyTime()) || (prev && keytime < prev->GetKeyTime())) { // Position of keyframe has changed. this->RemoveKeyFrameInternal(keyframe); this->AddKeyFrameInternal(keyframe); } } //this->UpdateKeyTimeDomains(); this->Modified(); } //---------------------------------------------------------------------------- int vtkPVKeyFrameCueManipulator::AddKeyFrameInternal(vtkPVKeyFrame* keyframe) { double time = keyframe->GetKeyTime(); int index = 0; vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator iter; for (iter = this->Internals->KeyFrames.begin(); iter != this->Internals->KeyFrames.end(); iter++, index++) { if ( *iter == keyframe) { vtkErrorMacro("Keyframe already exists"); return -1; } if ( (*iter)->GetKeyTime() > time ) { break; } } this->Internals->KeyFrames.insert(iter, keyframe); return index; } //---------------------------------------------------------------------------- int vtkPVKeyFrameCueManipulator::RemoveKeyFrameInternal(vtkPVKeyFrame* kf) { vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator iter; for (iter = this->Internals->KeyFrames.begin(); iter != this->Internals->KeyFrames.end(); iter++) { if ( *iter == kf) { this->Internals->KeyFrames.erase(iter); return 1; } } return 0; } //---------------------------------------------------------------------------- #ifdef FIXME void vtkPVKeyFrameCueManipulator::UpdateKeyTimeDomains() { vtkPVKeyFrameCueManipulatorInternals::KeyFrameVector:: iterator iter; unsigned int numFrames = this->Internals->KeyFrames.size(); for (unsigned int cc=0; cc < numFrames; ++cc) { vtkPVKeyFrame* kf = this->Internals->KeyFrames[cc]; vtkPVKeyFrame* prev = (cc>0)? this->Internals->KeyFrames[cc-1] : NULL; vtkPVKeyFrame* next = (cc+1Internals->KeyFrames[cc+1]: NULL; double min = (prev)? prev->GetKeyTime() : 0.0; double max = (next)? next->GetKeyTime() : 1.0; vtkSMProperty* keyTimeProp = kf->GetProperty("KeyTime"); if (!keyTimeProp) { vtkWarningMacro("KeyFrameProxy should have a KeyTime property."); continue; } vtkSMDoubleRangeDomain* dr = vtkSMDoubleRangeDomain::SafeDownCast( keyTimeProp->GetDomain("range")); if (dr) { int exists; if (dr->GetMinimum(0, exists) != min || !exists) { dr->AddMinimum(0, min); } if (dr->GetMaximum(0, exists) != max || !exists) { dr->AddMaximum(0, max); } } } } #endif //---------------------------------------------------------------------------- void vtkPVKeyFrameCueManipulator::PrintSelf(ostream& os, vtkIndent indent) { this->Superclass::PrintSelf(os, indent); os << indent << "LastAddedKeyFrameIndex: " << this->LastAddedKeyFrameIndex << endl; }