1 /////////////////////////////////////////////////////////////////////////////
2 // Name: qtexport.cpp
3 // Purpose:
4 // Author: Brett Bode
5 // Modified by:
6 // Created: Fri 23 Feb 08:44:29 2007
7 // RCS-ID:
8 // Copyright: (c) 2007 Iowa State University
9 // Licence:
10 /////////////////////////////////////////////////////////////////////////////
11
12 #if defined(__GNUG__) && !defined(NO_GCC_PRAGMA)
13 #pragma implementation "qtexport.h"
14 #endif
15
16 // For compilers that support precompilation, includes "wx/wx.h".
17 #include "wx/wxprec.h"
18
19 #ifdef __BORLANDC__
20 #pragma hdrstop
21 #endif
22
23 #ifndef WX_PRECOMP
24 #include "wx/wx.h"
25 #endif
26
27 ////@begin includes
28 ////@end includes
29
30 #include "Globals.h"
31 #include "qtexport.h"
32 #include "energyplotdialog.h"
33
34 ////@begin XPM images
35 ////@end XPM images
36
37 /*!
38 * QTExport type definition
39 */
40
IMPLEMENT_DYNAMIC_CLASS(QTExport,wxDialog)41 IMPLEMENT_DYNAMIC_CLASS( QTExport, wxDialog )
42
43 /*!
44 * QTExport event table definition
45 */
46
47 BEGIN_EVENT_TABLE( QTExport, wxDialog )
48
49 ////@begin QTExport event table entries
50 EVT_RADIOBOX( ID_QT_MOVIE_RADIO, QTExport::OnQtMovieRadioSelected )
51
52 ////@end QTExport event table entries
53
54 END_EVENT_TABLE()
55
56 /*!
57 * QTExport constructors
58 */
59
60 QTExport::QTExport()
61 {
62 Init();
63 }
64
QTExport(wxWindow * parent,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)65 QTExport::QTExport( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
66 {
67 Init();
68 Create(parent, id, caption, pos, size, style);
69 }
70
71 /*!
72 * QTExport creator
73 */
74
Create(wxWindow * parent,wxWindowID id,const wxString & caption,const wxPoint & pos,const wxSize & size,long style)75 bool QTExport::Create( wxWindow* parent, wxWindowID id, const wxString& caption, const wxPoint& pos, const wxSize& size, long style )
76 {
77 ////@begin QTExport creation
78 SetExtraStyle(wxWS_EX_BLOCK_EVENTS);
79 wxDialog::Create( parent, id, caption, pos, size, style );
80
81 CreateControls();
82 if (GetSizer())
83 {
84 GetSizer()->SetSizeHints(this);
85 }
86 Centre();
87 ////@end QTExport creation
88 return true;
89 }
90
91 /*!
92 * QTExport destructor
93 */
94
~QTExport()95 QTExport::~QTExport()
96 {
97 ////@begin QTExport destruction
98 ////@end QTExport destruction
99 }
100
101 /*!
102 * Member initialisation
103 */
104
Init()105 void QTExport::Init()
106 {
107 ////@begin QTExport member initialisation
108 mMovieType = NULL;
109 mEPlotCheck = NULL;
110 mQTChoice = NULL;
111 mKeyFrameEdit = NULL;
112 ////@end QTExport member initialisation
113 }
114 /*!
115 * Control creation for QTExport
116 */
117
CreateControls()118 void QTExport::CreateControls()
119 {
120 ////@begin QTExport content construction
121 QTExport* itemDialog1 = this;
122
123 wxBoxSizer* itemBoxSizer2 = new wxBoxSizer(wxVERTICAL);
124 itemDialog1->SetSizer(itemBoxSizer2);
125
126 wxString mMovieTypeStrings[] = {
127 _("&Frame Animation"),
128 _("&Normal Mode animation")
129 };
130 mMovieType = new wxRadioBox( itemDialog1, ID_QT_MOVIE_RADIO, _("Type of Movie"), wxDefaultPosition, wxDefaultSize, 2, mMovieTypeStrings, 0, wxRA_SPECIFY_ROWS );
131 mMovieType->SetSelection(0);
132 itemBoxSizer2->Add(mMovieType, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
133
134 mEPlotCheck = new wxCheckBox( itemDialog1, ID_EPLOT_CHECK, _("Include Energy Plot"), wxDefaultPosition, wxDefaultSize, 0 );
135 mEPlotCheck->SetValue(false);
136 if (ShowToolTips())
137 mEPlotCheck->SetToolTip(_("click to display the energy plot next to the animation for the frame animation."));
138 itemBoxSizer2->Add(mEPlotCheck, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
139
140 wxStaticLine* itemStaticLine5 = new wxStaticLine( itemDialog1, wxID_STATIC, wxDefaultPosition, wxDefaultSize, wxLI_HORIZONTAL );
141 itemBoxSizer2->Add(itemStaticLine5, 0, wxGROW|wxALL, 5);
142
143 wxBoxSizer* itemBoxSizer6 = new wxBoxSizer(wxHORIZONTAL);
144 itemBoxSizer2->Add(itemBoxSizer6, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
145
146 wxStaticText* itemStaticText7 = new wxStaticText( itemDialog1, wxID_STATIC, _("QuickTime Compressor:"), wxDefaultPosition, wxDefaultSize, 0 );
147 itemBoxSizer6->Add(itemStaticText7, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
148
149 wxString mQTChoiceStrings[] = {
150 _("Cinepak"),
151 _("Graphics"),
152 _("Animation"),
153 _("MPEG4")
154 };
155 mQTChoice = new wxChoice( itemDialog1, ID_QT_COMPRESSOR_CHOICE, wxDefaultPosition, wxDefaultSize, 4, mQTChoiceStrings, 0 );
156 itemBoxSizer6->Add(mQTChoice, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
157
158 wxBoxSizer* itemBoxSizer9 = new wxBoxSizer(wxHORIZONTAL);
159 itemBoxSizer2->Add(itemBoxSizer9, 0, wxALIGN_CENTER_HORIZONTAL|wxALL, 5);
160
161 wxStaticText* itemStaticText10 = new wxStaticText( itemDialog1, wxID_STATIC, _("Key frame rate:"), wxDefaultPosition, wxDefaultSize, 0 );
162 itemBoxSizer9->Add(itemStaticText10, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
163
164 mKeyFrameEdit = new wxTextCtrl( itemDialog1, ID_KEY_FRAME_EDIT, _T(""), wxDefaultPosition, wxDefaultSize, 0 );
165 if (ShowToolTips())
166 mKeyFrameEdit->SetToolTip(_("0 or 1 will produce a key frame every frame, higher values will result in smaller files, but lower quality."));
167 itemBoxSizer9->Add(mKeyFrameEdit, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
168
169 wxBoxSizer* itemBoxSizer12 = new wxBoxSizer(wxHORIZONTAL);
170 itemBoxSizer2->Add(itemBoxSizer12, 0, wxALIGN_RIGHT|wxALL, 5);
171
172 wxButton* itemButton13 = new wxButton( itemDialog1, wxID_CANCEL, _("&Cancel"), wxDefaultPosition, wxDefaultSize, 0 );
173 itemBoxSizer12->Add(itemButton13, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
174
175 wxButton* itemButton14 = new wxButton( itemDialog1, wxID_OK, _("&OK"), wxDefaultPosition, wxDefaultSize, 0 );
176 itemButton14->SetDefault();
177 itemBoxSizer12->Add(itemButton14, 0, wxALIGN_CENTER_VERTICAL|wxALL, 5);
178
179 ////@end QTExport content construction
180 mQTChoice->SetSelection(3);
181 mKeyFrameEdit->SetValue(_T("2"));
182 }
183
184 /*!
185 * wxEVT_COMMAND_RADIOBOX_SELECTED event handler for ID_QT_MOVIE_RADIO
186 */
187
OnQtMovieRadioSelected(wxCommandEvent & event)188 void QTExport::OnQtMovieRadioSelected( wxCommandEvent& event )
189 {
190 mEPlotCheck->Enable(mMovieType->GetSelection() == 0);
191 event.Skip();
192 }
193
194 /*!
195 * Should we show tooltips?
196 */
197
ShowToolTips()198 bool QTExport::ShowToolTips()
199 {
200 return true;
201 }
202
203 /*!
204 * Get bitmap resources
205 */
206
GetBitmapResource(const wxString & name)207 wxBitmap QTExport::GetBitmapResource( const wxString& name )
208 {
209 // Bitmap retrieval
210 ////@begin QTExport bitmap retrieval
211 wxUnusedVar(name);
212 return wxNullBitmap;
213 ////@end QTExport bitmap retrieval
214 }
215
216 /*!
217 * Get icon resources
218 */
219
GetIconResource(const wxString & name)220 wxIcon QTExport::GetIconResource( const wxString& name )
221 {
222 // Icon retrieval
223 ////@begin QTExport icon retrieval
224 wxUnusedVar(name);
225 return wxNullIcon;
226 ////@end QTExport icon retrieval
227 }
228
EnableFrameMovie(bool state)229 void QTExport::EnableFrameMovie(bool state) {
230 if (state) {
231 mMovieType->SetSelection(0);
232 mMovieType->Enable(0, true);
233 mEPlotCheck->Enable(true);
234 } else {
235 mMovieType->SetSelection(1);
236 mMovieType->Enable(0, false);
237 mEPlotCheck->Enable(false);
238 }
239 }
SetMovieChoice(int v)240 void QTExport::SetMovieChoice(int v) {
241 mMovieType->SetSelection(v);
242 }
EnableModeMovie(bool state)243 void QTExport::EnableModeMovie(bool state) {
244 mMovieType->SetSelection(0);
245 mMovieType->Enable(1, state);
246 }
247
GetMovieChoice(void) const248 int QTExport::GetMovieChoice(void) const {
249 return mMovieType->GetSelection();
250 }
AddEnergyPlot(void) const251 bool QTExport::AddEnergyPlot(void) const {
252 return mEPlotCheck->IsChecked();
253 }
GetCompressorChoice(void) const254 int QTExport::GetCompressorChoice(void) const {
255 return mQTChoice->GetSelection();
256 }
GetKeyFrameRate(void) const257 int QTExport::GetKeyFrameRate(void) const {
258 long result = 0;
259 wxString val = mKeyFrameEdit->GetValue();
260 val.ToLong(&result);
261 return result;
262 }
263
264 #ifdef __MAC_USE_QUICKTIME__
265 #include "GlobalExceptions.h"
266 #include "Progress.h"
267 #include "MoleculeData.h"
268 #include "MolDisplayWin.h"
269 #include <QuickTime/Movies.h>
270
271 #if wxCHECK_VERSION(2, 9, 0)
272 #include <wx/osx/private.h>
273 //This is a gross hack to get access to the picHandle in the wxBitmapRefData class
274 //that is no longer provided in the wx headers
275 class wxBitmapRefData {
276 public:
277 PicHandle GetPictHandle();
278 };
279 #else
280 #include <wx/mac/carbon/private.h>
281 #endif
282
283 typedef struct qtData {
284 Media theMedia;
285 ImageDescriptionHandle imageDesc;
286 ImageSequence seqID;
287 Rect DisplayRect;
288 Rect FullRect;
289 };
290
WriteQTMovie(wxString & filepath)291 void MolDisplayWin::WriteQTMovie(wxString & filepath) {
292 //Create a QuickTime movie using the standard animation codecs with normal quality, and
293 //temporal compression. The final file is flattened for cross platform compatability
294
295 QTExport * QTOptions = new QTExport(this);
296 //setup controls for the current data
297 if (MainData->GetNumFrames() > 1) { //default to frame animation
298 QTOptions->SetMovieChoice(0);
299 } else {
300 QTOptions->EnableFrameMovie(false);
301 }
302 if (MainData->cFrame->GetNumberNormalModes() <= 0) {
303 QTOptions->EnableModeMovie(false);
304 }
305
306 if (QTOptions->ShowModal() != wxID_OK) {
307 //user cancelled the operation
308 QTOptions->Destroy();
309 return;
310 }
311 //retrieve the value of each option
312 int MovieType = QTOptions->GetMovieChoice();
313 bool IncludeEPlot = QTOptions->AddEnergyPlot();
314 int compressorChoice = QTOptions->GetCompressorChoice();
315 int keyFrameRate = QTOptions->GetKeyFrameRate();
316 if (keyFrameRate < 0) keyFrameRate = 0;
317
318 QTOptions->Destroy();
319
320 CodecType mCodec;
321 switch (compressorChoice) {
322 case 0:
323 mCodec = kCinepakCodecType;
324 break;
325 case 1:
326 mCodec = kGraphicsCodecType;
327 break;
328 case 2:
329 mCodec = kAnimationCodecType;
330 break;
331 case 3:
332 default:
333 mCodec = kMPEG4VisualCodecType;
334 }
335
336 OSStatus s;
337 OSErr myErr = myErr;
338 FSSpec targetSpec;
339 //ugh I need to get an FSSpec to hand to quicktime, but these calls only seem to work if
340 //the file already exists...
341 const char * t = filepath.mb_str(wxConvUTF8);
342 FILE * temp = fopen(t, "wb");
343 fclose(temp);
344
345 #ifdef __WXOSX_COCOA__
346 //This function is not found in the wxCocoa implementation, it is probably possible to work around it
347 //Otherwise the code appears to link and run currently. However, it is probably better to redue the
348 //code to use the Cocoa qtKit framework rather than the old Carbon QT library.
349
350 //This path is not tested as the current Cocoa code does not properly support the extended save dialog.
351 // void wxMacFilename2FSSpec( const wxString& path , FSSpec *spec )
352 {
353 OSStatus err = noErr;
354 FSRef fsRef;
355 wxMacPathToFSRef( filepath , &fsRef );
356 err = FSGetCatalogInfo(&fsRef, kFSCatInfoNone, NULL, NULL, &targetSpec, NULL);
357 verify_noerr( err );
358 }
359 #else
360 wxMacFilename2FSSpec(filepath, &targetSpec);
361 #endif
362
363 Movie theMovie = NULL;
364
365 FSSpec tempSpec = targetSpec;
366 strcpy((char *) &(tempSpec.name[1]), "MacMolPlt8933tempMovie");
367 tempSpec.name[0] = 22;
368
369 BeginOperation();
370 ProgressInd->ChangeText("Creating movie...");
371
372 myErr = EnterMovies(); //initialize the quicktime manager
373 if (myErr != noErr) {
374 FinishOperation();
375 MessageAlert("Error initializing QuickTime!");
376 return;
377 }
378 //Create the movie file and initialize file data
379 //Use Quicktime creator code 'TVOD' instead of simpletext 'ttxt'
380 short resRefNum = 0;
381 short resId = 0;
382 myErr = CreateMovieFile(&tempSpec, 'TVOD', smCurrentScript, createMovieFileDeleteCurFile,
383 &resRefNum, &theMovie);
384 if (myErr != noErr) {
385 MessageAlert("Error creating movie file!");
386 } else {
387 bool KillEPlot = false;
388 int width, height, savedEPlotWidth, savedEPlotHeight;
389 glCanvas->GetClientSize(&width, &height);
390 Rect lDisplayRect={0,0,0,0};
391 lDisplayRect.right = width;
392 lDisplayRect.bottom = height;
393 Rect gRect = lDisplayRect;
394
395 Rect EPlotRect = lDisplayRect;
396 //If we are including an energy plot add space for it here
397 if (IncludeEPlot && (MovieType == 0)) {
398 EPlotRect.left = EPlotRect.right;
399 EPlotRect.right = EPlotRect.left + height;
400 if (!energyPlotWindow) {
401 energyPlotWindow = new EnergyPlotDialog(this);
402 KillEPlot = true;
403 } else {
404 energyPlotWindow->GetSize(&savedEPlotWidth, &savedEPlotHeight);
405 }
406 gRect.right += height;
407 width += height;
408 energyPlotWindow->Show(false);
409 energyPlotWindow->SetSize(height, height);
410 energyPlotWindow->Update(); //This is needed to initialise the window if we just created it
411 }
412
413 LocalToGlobal ((Point *) &(gRect.top));
414 LocalToGlobal ((Point *) &(gRect.bottom));
415 WindowRef TempWindow;
416 s = CreateNewWindow(kDocumentWindowClass, kWindowNoAttributes, &gRect, &TempWindow);
417 if (s == noErr) {
418 //Create the video track
419 Track theTrack = NewMovieTrack (theMovie, FixRatio(width,1),
420 FixRatio(height,1), kNoVolume);
421 if ((noErr == GetMoviesError())&&theTrack) {
422 Media theMedia = NewTrackMedia (theTrack, VideoMediaType,
423 60, // Video Time Scale
424 NULL, 0);
425 if ((noErr == GetMoviesError())&&theMedia) {
426 myErr = BeginMediaEdits (theMedia);
427 if (myErr == noErr) {
428 //create the actual movie frames
429 GWorldPtr lgWorld=NULL;
430
431 if (! NewGWorld (&lgWorld, 0, &gRect, (CTabHandle) NULL, (GDHandle) NULL,
432 (GWorldFlags) (pixPurge + useTempMem))) {
433 long MaxCompressedSize;
434 ImageSequence seqID;
435 ImageDescriptionHandle imageDesc = (ImageDescriptionHandle)NewHandle(4);
436 PixMapHandle myPixMap = GetPortPixMap(lgWorld);
437 LockPixels (myPixMap);
438 myErr = CompressSequenceBegin(&seqID, myPixMap, NULL, &gRect, &gRect, 0,
439 mCodec, bestCompressionCodec, codecNormalQuality, codecNormalQuality, keyFrameRate, NULL,
440 codecFlagUpdatePreviousComp, imageDesc);
441 GetMaxCompressionSize (myPixMap, &gRect,
442 0, codecNormalQuality, mCodec, (CompressorComponent) anyCodec, &MaxCompressedSize);
443 Handle Buffer = TempNewHandle(MaxCompressedSize, &myErr);
444 if (!Buffer)
445 Buffer = NewHandle(MaxCompressedSize);
446 if (Buffer) {
447 qtData myqtData = {theMedia, imageDesc, seqID, lDisplayRect, gRect};
448 if (MovieType == 0) {
449 CreateFrameMovie(lgWorld, Buffer, myqtData, IncludeEPlot);
450 } else {
451 CreateModeMovie(lgWorld, Buffer, myqtData);
452 }
453 DisposeHandle(Buffer);
454 }
455 myErr = CDSequenceEnd(seqID);
456 if (lgWorld != NULL) DisposeGWorld (lgWorld);
457 if (imageDesc) DisposeHandle((Handle) imageDesc);
458 }
459
460 myErr = EndMediaEdits (theMedia);
461 }
462 myErr = InsertMediaIntoTrack (theTrack, 0,/* track start time */
463 0, /* media start time */
464 GetMediaDuration (theMedia),
465 FixRatio(1,1));
466 }
467 myErr = AddMovieResource (theMovie, resRefNum, &resId, NULL);
468 }
469 if (resRefNum) {
470 //Create the actual file as a flat data fork so it can be placed on the www
471 ProgressInd->ChangeText("Flattening movie�");
472 FlattenMovie(theMovie, flattenAddMovieToDataFork, &targetSpec, 'TVOD', smCurrentScript,
473 createMovieFileDeleteCurFile, &resId, NULL);
474 CloseMovieFile (resRefNum);
475 }
476 DisposeWindow(TempWindow);
477 }
478 DisposeMovie (theMovie);
479 DeleteMovieFile (&tempSpec); //delete the temp file after disposing of the movie
480
481 if (energyPlotWindow) {
482 if (KillEPlot) {
483 delete energyPlotWindow;
484 energyPlotWindow = NULL;
485 } else {
486 energyPlotWindow->SetSize(savedEPlotWidth, savedEPlotHeight);
487 energyPlotWindow->FrameChanged();
488 energyPlotWindow->Show(true);
489 }
490 }
491 }
492 ExitMovies(); //Close out quicktime as we are done with it for now
493 FinishOperation();
494 }
CreateFrameMovie(GWorldPtr lgWorld,Handle CompressedData,const qtData & myqtData,bool IncludeEPlot)495 void MolDisplayWin::CreateFrameMovie(GWorldPtr lgWorld, Handle CompressedData,
496 const qtData & myqtData, bool IncludeEPlot) {
497 OSErr myErr;
498 long AnimateTime = Prefs->GetAnimateTime();
499 if (AnimateTime <= 0) AnimateTime = 1;
500 long SavedFrameNum = MainData->GetCurrentFrame();
501 Rect lDisplayRect = myqtData.DisplayRect;
502 Rect EPlotRect;
503 EPlotRect = myqtData.DisplayRect;
504 EPlotRect.left = EPlotRect.right;
505 EPlotRect.right = myqtData.FullRect.right;
506 ProgressInd->SetScaleFactor(100.0/((float) MainData->NumFrames));
507
508 for (long i=1; i<=MainData->NumFrames; i++) {
509 ProgressInd->UpdateProgress(i);
510 MainData->SetCurrentFrame(i);
511 //Check for and update any surfaces depending on the screen plane
512 Surface * temp = MainData->cFrame->SurfaceList;
513 while (temp) {
514 temp->RotateEvent(MainData);
515 temp = temp->GetNextSurface();
516 }
517 MainData->ResetRotation();
518 ReleaseLists();
519 DrawGL();
520
521 // create a pict of the current molecule display
522 wxImage mImage = glCanvas->getImage(0,0);
523 wxBitmap * mBitmap = new wxBitmap(mImage);
524 //The following utilizes a Mac specific internal pair of calls
525 //to get a PicHandle from a wxBitmap.
526 wxBitmapRefData * mBitmapData = mBitmap->GetBitmapData();
527 PicHandle tempPict = mBitmapData->GetPictHandle();
528
529 CGrafPtr lSavedPort;
530 GDHandle lSavedGDH;
531 long dataSize;
532 unsigned char similarity;
533
534 if (tempPict) { //Got a PICT, draw it into the GWorld
535 HLock(CompressedData);
536 Ptr compressedDataPtr = *CompressedData;
537 GetGWorld (&lSavedPort, &lSavedGDH);
538 SetGWorld (lgWorld, NULL);
539
540 EraseRect(&lDisplayRect);
541 DrawPicture(tempPict, &(lDisplayRect));
542
543 delete mBitmap;
544
545 if (IncludeEPlot) {
546 energyPlotWindow->FrameChanged();
547 wxBitmap * ePlotBitMap = NULL;
548 energyPlotWindow->CopyToBitMap(&ePlotBitMap);
549 if (ePlotBitMap) {
550 wxBitmapRefData * mBitmapData = mBitmap->GetBitmapData();
551 PicHandle tempPict = mBitmapData->GetPictHandle();
552 if (tempPict) {
553 SetGWorld (lgWorld, NULL);
554
555 EraseRect(&EPlotRect);
556 DrawPicture(tempPict, &(EPlotRect));
557 }
558 delete ePlotBitMap;
559 }
560 }
561
562 SetGWorld (lSavedPort, lSavedGDH);
563
564 PixMapHandle myPixMap = GetPortPixMap(lgWorld);
565 myErr = CompressSequenceFrame(myqtData.seqID, myPixMap, &(myqtData.FullRect),
566 codecFlagUpdatePreviousComp, compressedDataPtr, &dataSize, &similarity, NULL);
567
568 TimeValue test;//I don't use this value, but Carbon requires it
569 myErr = AddMediaSample(myqtData.theMedia, CompressedData, 0, /* no offset in data */
570 dataSize, AnimateTime,
571 (SampleDescriptionHandle)myqtData.imageDesc, 1, /* one sample */
572 0, /* self-contained samples */
573 &test);
574 }
575 }
576 MainData->SetCurrentFrame(SavedFrameNum);
577 MainData->ResetRotation();
578 ReleaseLists();
579 DrawGL();
580 }
CreateModeMovie(GWorldPtr lgWorld,Handle CompressedData,const qtData & myqtData)581 void MolDisplayWin::CreateModeMovie(GWorldPtr lgWorld, Handle CompressedData,
582 const qtData & myqtData) {
583 float offsetFactor;
584 bool savedrawmode=false;
585 Rect lDisplayRect = myqtData.DisplayRect;
586
587 if (!MainData->cFrame->Vibs) return;
588 Frame * lFrame = MainData->cFrame;
589 if (MainData->GetDrawMode()) {
590 savedrawmode = true;
591 if (!Prefs->GetAnimateMode()) MainData->SetDrawMode(false);
592 }
593 long cmode = (lFrame->NumAtoms)*(lFrame->Vibs->CurrentMode);
594 offsetFactor = 1.0/(4.5*Prefs->GetAnimationSpeed());
595 float VectorScale = Prefs->GetVectorScale();
596 long AnimationSpeed = Prefs->GetAnimationSpeed();
597 CPoint3D * ModeOffset = new CPoint3D[lFrame->NumAtoms];
598 CPoint3D * SavedAtoms = new CPoint3D[lFrame->NumAtoms];
599 if (!ModeOffset || !SavedAtoms) {
600 return; //insufficient memory
601 }
602 mpAtom * lAtoms = lFrame->Atoms;
603 long iatm;
604 for (iatm=0; iatm<(lFrame->NumAtoms); iatm++) {
605 SavedAtoms[iatm] = lAtoms[iatm].Position;
606 ModeOffset[iatm] = lFrame->Vibs->NormMode[iatm+cmode];
607 ModeOffset[iatm] *= VectorScale;
608 }
609 MainData->ResetRotation();
610 ReleaseLists();
611 DrawGL();
612
613 OSErr myErr;
614 long npoint = 0;
615 long inc = 1;
616 ProgressInd->SetScaleFactor(100.0/((float) 4*AnimationSpeed));
617 for (long i=0; i<4*AnimationSpeed; i++) {
618 ProgressInd->UpdateProgress(i);
619 if ((npoint==AnimationSpeed)||(npoint==-AnimationSpeed)) {
620 inc *= -1;
621 offsetFactor *= -1.0;
622 }
623 npoint += inc;
624
625 // create a pict of the current molecule display
626 wxImage mImage = glCanvas->getImage(0,0);
627 wxBitmap * mBitmap = new wxBitmap(mImage);
628 //The following utilizes a Mac specific internal pair of calls
629 //to get a PicHandle from a wxBitmap.
630 wxBitmapRefData * mBitmapData = mBitmap->GetBitmapData();
631 PicHandle tempPict = mBitmapData->GetPictHandle();
632
633 CGrafPtr lSavedPort;
634 GDHandle lSavedGDH;
635 long dataSize;
636 unsigned char similarity;
637
638 if (tempPict) { //Got a PICT, draw it into the GWorld
639 HLock(CompressedData);
640 Ptr compressedDataPtr = *CompressedData;
641
642 GetGWorld (&lSavedPort, &lSavedGDH);
643 SetGWorld (lgWorld, NULL);
644
645 EraseRect(&lDisplayRect);
646 DrawPicture(tempPict, &(lDisplayRect));
647
648 delete mBitmap;
649
650 SetGWorld (lSavedPort, lSavedGDH);
651
652 PixMapHandle myPixMap = GetPortPixMap(lgWorld);
653 myErr = CompressSequenceFrame(myqtData.seqID, myPixMap, &lDisplayRect,
654 codecFlagUpdatePreviousComp, compressedDataPtr, &dataSize, &similarity, NULL);
655
656 TimeValue test;//I don't use this value, but Carbon requires it
657 myErr = AddMediaSample(myqtData.theMedia, CompressedData, 0, /* no offset in data */
658 dataSize, 1,
659 (SampleDescriptionHandle)myqtData.imageDesc, 1, /* one sample */
660 0, /* self-contained samples */
661 &test);
662 }
663 for (iatm=0; iatm<(lFrame->NumAtoms); iatm++) {
664 lAtoms[iatm].Position.x += offsetFactor*(ModeOffset[iatm].x);
665 lAtoms[iatm].Position.y += offsetFactor*(ModeOffset[iatm].y);
666 lAtoms[iatm].Position.z += offsetFactor*(ModeOffset[iatm].z);
667 }
668
669 MainData->ResetRotation();
670 ReleaseLists();
671 DrawGL();
672 }
673 for (iatm=0; iatm<(lFrame->NumAtoms); iatm++) {
674 lAtoms[iatm].Position = SavedAtoms[iatm];
675 }
676 MainData->ResetRotation();
677
678 if (ModeOffset) delete [] ModeOffset;
679 if (SavedAtoms) delete [] SavedAtoms;
680 MainData->SetDrawMode(savedrawmode);
681 ReleaseLists();
682 DrawGL();
683 }
684
685 #endif
686