diff options
Diffstat (limited to 'libraries/ode-0.9\/drawstuff/src/osx.cpp')
-rwxr-xr-x | libraries/ode-0.9\/drawstuff/src/osx.cpp | 542 |
1 files changed, 542 insertions, 0 deletions
diff --git a/libraries/ode-0.9\/drawstuff/src/osx.cpp b/libraries/ode-0.9\/drawstuff/src/osx.cpp new file mode 100755 index 0000000..fcecba9 --- /dev/null +++ b/libraries/ode-0.9\/drawstuff/src/osx.cpp | |||
@@ -0,0 +1,542 @@ | |||
1 | /************************************************************************* | ||
2 | * * | ||
3 | * Open Dynamics Engine, Copyright (C) 2001,2002 Russell L. Smith. * | ||
4 | * All rights reserved. Email: russ@q12.org Web: www.q12.org * | ||
5 | * * | ||
6 | * This library is free software; you can redistribute it and/or * | ||
7 | * modify it under the terms of EITHER: * | ||
8 | * (1) The GNU Lesser General Public License as published by the Free * | ||
9 | * Software Foundation; either version 2.1 of the License, or (at * | ||
10 | * your option) any later version. The text of the GNU Lesser * | ||
11 | * General Public License is included with this library in the * | ||
12 | * file LICENSE.TXT. * | ||
13 | * (2) The BSD-style license that is included with this library in * | ||
14 | * the file LICENSE-BSD.TXT. * | ||
15 | * * | ||
16 | * This library is distributed in the hope that it will be useful, * | ||
17 | * but WITHOUT ANY WARRANTY; without even the implied warranty of * | ||
18 | * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the files * | ||
19 | * LICENSE.TXT and LICENSE-BSD.TXT for more details. * | ||
20 | * * | ||
21 | *************************************************************************/ | ||
22 | |||
23 | // Platform-specific code for Mac OS X using Carbon+AGL | ||
24 | // | ||
25 | // Created using x11.cpp and the window-initialization -routines from GLFW | ||
26 | // as reference. | ||
27 | // Not thoroughly tested and is certain to contain deficiencies and bugs | ||
28 | |||
29 | #include <ode/config.h> | ||
30 | #include <stdlib.h> | ||
31 | #include <string.h> | ||
32 | #include <stdarg.h> | ||
33 | |||
34 | #ifdef HAVE_SYS_TIME_H | ||
35 | #include <sys/time.h> | ||
36 | #endif | ||
37 | |||
38 | #include <drawstuff/drawstuff.h> | ||
39 | #include <drawstuff/version.h> | ||
40 | #include "internal.h" | ||
41 | |||
42 | #include <Carbon/Carbon.h> | ||
43 | #include <AGL/agl.h> | ||
44 | |||
45 | // Global variables | ||
46 | |||
47 | static bool running = true; // 1 if simulation running | ||
48 | static bool paused = false; // 1 if in `pause' mode | ||
49 | static bool singlestep = false; // 1 if single step key pressed | ||
50 | static bool writeframes = false; // 1 if frame files to be written | ||
51 | |||
52 | static int windowWidth = -1; | ||
53 | static int windowHeight = -1; | ||
54 | static UInt32 modifierMask = 0; | ||
55 | static int mouseButtonMode = 0; | ||
56 | static bool mouseWithOption = false; // Set if dragging the mouse with alt pressed | ||
57 | static bool mouseWithControl = false; // Set if dragging the mouse with ctrl pressed | ||
58 | |||
59 | static dsFunctions* functions = NULL; | ||
60 | static WindowRef windowReference; | ||
61 | static AGLContext aglContext; | ||
62 | |||
63 | static EventHandlerUPP mouseUPP = NULL; | ||
64 | static EventHandlerUPP keyboardUPP = NULL; | ||
65 | static EventHandlerUPP windowUPP = NULL; | ||
66 | |||
67 | // Describes the window-events we are interested in | ||
68 | EventTypeSpec OSX_WINDOW_EVENT_TYPES[] = { | ||
69 | { kEventClassWindow, kEventWindowBoundsChanged }, | ||
70 | { kEventClassWindow, kEventWindowClose }, | ||
71 | { kEventClassWindow, kEventWindowDrawContent } | ||
72 | }; | ||
73 | |||
74 | // Describes the mouse-events we are interested in | ||
75 | EventTypeSpec OSX_MOUSE_EVENT_TYPES[] = { | ||
76 | { kEventClassMouse, kEventMouseDown }, | ||
77 | { kEventClassMouse, kEventMouseUp }, | ||
78 | { kEventClassMouse, kEventMouseMoved }, | ||
79 | { kEventClassMouse, kEventMouseDragged } | ||
80 | }; | ||
81 | |||
82 | // Describes the key-events we are interested in | ||
83 | EventTypeSpec OSX_KEY_EVENT_TYPES[] = { | ||
84 | { kEventClassKeyboard, kEventRawKeyDown }, | ||
85 | // { kEventClassKeyboard, kEventRawKeyUp }, | ||
86 | { kEventClassKeyboard, kEventRawKeyModifiersChanged } | ||
87 | }; | ||
88 | |||
89 | //*************************************************************************** | ||
90 | // error handling for unix | ||
91 | |||
92 | static void printMessage (char *msg1, char *msg2, va_list ap) | ||
93 | { | ||
94 | fflush (stderr); | ||
95 | fflush (stdout); | ||
96 | fprintf (stderr,"\n%s: ",msg1); | ||
97 | vfprintf (stderr,msg2,ap); | ||
98 | fprintf (stderr,"\n"); | ||
99 | fflush (stderr); | ||
100 | } | ||
101 | |||
102 | extern "C" void dsError (char *msg, ...) | ||
103 | { | ||
104 | va_list ap; | ||
105 | va_start (ap,msg); | ||
106 | printMessage ("Error",msg,ap); | ||
107 | exit (1); | ||
108 | } | ||
109 | |||
110 | |||
111 | extern "C" void dsDebug (char *msg, ...) | ||
112 | { | ||
113 | va_list ap; | ||
114 | va_start (ap,msg); | ||
115 | printMessage ("INTERNAL ERROR",msg,ap); | ||
116 | // *((char *)0) = 0; ... commit SEGVicide ? | ||
117 | abort(); | ||
118 | } | ||
119 | |||
120 | extern "C" void dsPrint (char *msg, ...) | ||
121 | { | ||
122 | va_list ap; | ||
123 | va_start (ap,msg); | ||
124 | vprintf (msg,ap); | ||
125 | } | ||
126 | |||
127 | static void captureFrame( int num ){ | ||
128 | |||
129 | fprintf( stderr,"\rcapturing frame %04d", num ); | ||
130 | unsigned char buffer[windowWidth*windowHeight][3]; | ||
131 | glReadPixels( 0, 0, windowWidth, windowHeight, GL_RGB, GL_UNSIGNED_BYTE, &buffer ); | ||
132 | char s[100]; | ||
133 | sprintf (s,"frame%04d.ppm",num); | ||
134 | FILE *f = fopen (s,"wb"); | ||
135 | if( !f ){ | ||
136 | dsError( "can't open \"%s\" for writing", s ); | ||
137 | } | ||
138 | fprintf( f,"P6\n%d %d\n255\n", windowWidth, windowHeight ); | ||
139 | for( int y=windowHeight-1; y>-1; y-- ){ | ||
140 | fwrite( buffer[y*windowWidth], 3*windowWidth, 1, f ); | ||
141 | } | ||
142 | fclose (f); | ||
143 | } | ||
144 | |||
145 | extern "C" void dsStop(){ | ||
146 | |||
147 | running = false; | ||
148 | } | ||
149 | |||
150 | extern "C" double dsElapsedTime() | ||
151 | { | ||
152 | #if HAVE_GETTIMEOFDAY | ||
153 | static double prev=0.0; | ||
154 | timeval tv ; | ||
155 | |||
156 | gettimeofday(&tv, 0); | ||
157 | double curr = tv.tv_sec + (double) tv.tv_usec / 1000000.0 ; | ||
158 | if (!prev) | ||
159 | prev=curr; | ||
160 | double retval = curr-prev; | ||
161 | prev=curr; | ||
162 | if (retval>1.0) retval=1.0; | ||
163 | if (retval<dEpsilon) retval=dEpsilon; | ||
164 | return retval; | ||
165 | #else | ||
166 | return 0.01666; // Assume 60 fps | ||
167 | #endif | ||
168 | } | ||
169 | |||
170 | OSStatus osxKeyEventHandler( EventHandlerCallRef handlerCallRef, EventRef event, void *userData ){ | ||
171 | |||
172 | UInt32 keyCode; | ||
173 | UInt32 state = 0; | ||
174 | void* KCHR = NULL; | ||
175 | char charCode = 0; | ||
176 | char uppercase = 0; | ||
177 | |||
178 | switch( GetEventKind( event ) ){ | ||
179 | case kEventRawKeyDown: | ||
180 | if( GetEventParameter( event, kEventParamKeyCode, typeUInt32, NULL, sizeof( UInt32 ), NULL, &keyCode ) != noErr ){ | ||
181 | break; | ||
182 | } | ||
183 | KCHR = (void *)GetScriptVariable( smCurrentScript, smKCHRCache ); | ||
184 | charCode = (char)KeyTranslate( KCHR, keyCode, &state ); | ||
185 | uppercase = charCode; | ||
186 | UppercaseText( &uppercase, 1, smSystemScript ); | ||
187 | //printf( "Character %d [%c] [%c] modifiers [%d]\n", charCode, charCode, uppercase, modifierMask ); | ||
188 | |||
189 | if( modifierMask == 0 ){ | ||
190 | if( charCode >= ' ' && charCode <= 126 && functions -> command ){ | ||
191 | functions -> command( charCode ); | ||
192 | } | ||
193 | } | ||
194 | else if( ( modifierMask & controlKey ) ){ | ||
195 | // ctrl+key was pressed | ||
196 | switch(uppercase ){ | ||
197 | case 'T': | ||
198 | dsSetTextures( !dsGetTextures() ); | ||
199 | break; | ||
200 | case 'S': | ||
201 | dsSetShadows( !dsGetShadows() ); | ||
202 | break; | ||
203 | case 'X': | ||
204 | running = false; | ||
205 | break; | ||
206 | case 'P': | ||
207 | paused = !paused; | ||
208 | singlestep = false; | ||
209 | break; | ||
210 | case 'O': | ||
211 | if( paused ){ | ||
212 | singlestep = true; | ||
213 | } | ||
214 | break; | ||
215 | case 'V': { | ||
216 | float xyz[3],hpr[3]; | ||
217 | dsGetViewpoint( xyz,hpr ); | ||
218 | printf( "Viewpoint = (%.4f,%.4f,%.4f,%.4f,%.4f,%.4f)\n", xyz[0], xyz[1], xyz[2], hpr[0], hpr[1], hpr[2] ); | ||
219 | break; | ||
220 | } | ||
221 | case 'W': | ||
222 | writeframes = !writeframes; | ||
223 | if( writeframes ){ | ||
224 | printf( "Now writing frames to PPM files\n" ); | ||
225 | } | ||
226 | break; | ||
227 | } | ||
228 | |||
229 | } | ||
230 | return noErr; | ||
231 | case kEventRawKeyModifiersChanged: | ||
232 | if( GetEventParameter( event, kEventParamKeyModifiers, typeUInt32, NULL, sizeof( UInt32 ), NULL, &modifierMask ) == noErr ){ | ||
233 | if( ( mouseWithOption && !( modifierMask & optionKey ) ) || ( mouseWithControl && !( modifierMask & controlKey ) ) ){ | ||
234 | // The mouse was being dragged using either the command-key or the option-key modifier to emulate | ||
235 | // the right button or both left + right. | ||
236 | // Now the modifier-key has been released so the mouseButtonMode must be changed accordingly | ||
237 | // The following releases the right-button. | ||
238 | mouseButtonMode &= (~4); | ||
239 | mouseWithOption = false; | ||
240 | mouseWithControl = false; | ||
241 | } | ||
242 | return noErr; | ||
243 | } | ||
244 | break; | ||
245 | } | ||
246 | return eventNotHandledErr; | ||
247 | } | ||
248 | |||
249 | OSStatus osxMouseEventHandler( EventHandlerCallRef handlerCallRef, EventRef event, void *userData ){ | ||
250 | |||
251 | bool buttonDown = false; | ||
252 | HIPoint mouseLocation; | ||
253 | |||
254 | switch( GetEventKind( event ) ){ | ||
255 | |||
256 | case kEventMouseDown: | ||
257 | buttonDown = true; | ||
258 | case kEventMouseUp: | ||
259 | if( GetEventParameter( event, kEventParamWindowMouseLocation, typeHIPoint, NULL, sizeof( HIPoint ), NULL, &mouseLocation ) != noErr ){ | ||
260 | break; | ||
261 | } | ||
262 | EventMouseButton button; | ||
263 | if( GetEventParameter( event, kEventParamMouseButton, typeMouseButton, NULL, sizeof( EventMouseButton ), NULL, &button ) == noErr ){ | ||
264 | |||
265 | if( button == kEventMouseButtonPrimary ){ | ||
266 | if( modifierMask & controlKey ){ | ||
267 | // Ctrl+button == right | ||
268 | button = kEventMouseButtonSecondary; | ||
269 | mouseWithControl = true; | ||
270 | } | ||
271 | else if( modifierMask & optionKey ){ | ||
272 | // Alt+button == left+right | ||
273 | mouseButtonMode = 5; | ||
274 | mouseWithOption = true; | ||
275 | return noErr; | ||
276 | } | ||
277 | } | ||
278 | if( buttonDown ){ | ||
279 | if( button == kEventMouseButtonPrimary ) mouseButtonMode |= 1; // Left | ||
280 | if( button == kEventMouseButtonTertiary ) mouseButtonMode |= 2; // Middle | ||
281 | if( button == kEventMouseButtonSecondary ) mouseButtonMode |= 4; // Right | ||
282 | } | ||
283 | else{ | ||
284 | if( button == kEventMouseButtonPrimary ) mouseButtonMode &= (~1); // Left | ||
285 | if( button == kEventMouseButtonTertiary ) mouseButtonMode &= (~2); // Middle | ||
286 | if( button == kEventMouseButtonSecondary ) mouseButtonMode &= (~4);// Right | ||
287 | } | ||
288 | return noErr; | ||
289 | } | ||
290 | break; | ||
291 | case kEventMouseMoved: | ||
292 | // NO-OP | ||
293 | return noErr; | ||
294 | case kEventMouseDragged: | ||
295 | // Carbon provides mouse-position deltas, so we don't have to store the old state ourselves | ||
296 | if( GetEventParameter( event, kEventParamMouseDelta, typeHIPoint, NULL, sizeof( HIPoint ), NULL, &mouseLocation ) == noErr ){ | ||
297 | //printf( "Mode %d\n", mouseButtonMode ); | ||
298 | dsMotion( mouseButtonMode, (int)mouseLocation.x, (int)mouseLocation.y ); | ||
299 | return noErr; | ||
300 | } | ||
301 | break; | ||
302 | case kEventMouseWheelMoved: | ||
303 | // NO-OP | ||
304 | break; | ||
305 | } | ||
306 | return eventNotHandledErr; | ||
307 | } | ||
308 | |||
309 | static void osxCloseMainWindow(){ | ||
310 | |||
311 | if( windowUPP != NULL ){ | ||
312 | DisposeEventHandlerUPP( windowUPP ); | ||
313 | windowUPP = NULL; | ||
314 | } | ||
315 | |||
316 | if( aglContext != NULL ){ | ||
317 | aglSetCurrentContext( NULL ); | ||
318 | aglSetDrawable( aglContext, NULL ); | ||
319 | aglDestroyContext( aglContext ); | ||
320 | aglContext = NULL; | ||
321 | } | ||
322 | |||
323 | if( windowReference != NULL ){ | ||
324 | ReleaseWindow( windowReference ); | ||
325 | windowReference = NULL; | ||
326 | } | ||
327 | } | ||
328 | |||
329 | OSStatus osxWindowEventHandler( EventHandlerCallRef handlerCallRef, EventRef event, void *userData ){ | ||
330 | |||
331 | //printf( "WindowEvent\n" ); | ||
332 | switch( GetEventKind(event) ){ | ||
333 | case kEventWindowBoundsChanged: | ||
334 | WindowRef window; | ||
335 | GetEventParameter( event, kEventParamDirectObject, typeWindowRef, NULL, sizeof(WindowRef), NULL, &window ); | ||
336 | Rect rect; | ||
337 | GetWindowPortBounds( window, &rect ); | ||
338 | windowWidth = rect.right; | ||
339 | windowHeight = rect.bottom; | ||
340 | aglUpdateContext( aglContext ); | ||
341 | break; | ||
342 | case kEventWindowClose: | ||
343 | osxCloseMainWindow(); | ||
344 | exit( 0 ); | ||
345 | return noErr; | ||
346 | case kEventWindowDrawContent: | ||
347 | // NO-OP | ||
348 | break; | ||
349 | } | ||
350 | |||
351 | return eventNotHandledErr; | ||
352 | } | ||
353 | |||
354 | static void osxCreateMainWindow( int width, int height ){ | ||
355 | |||
356 | int redbits = 4; | ||
357 | int greenbits = 4; | ||
358 | int bluebits = 4; | ||
359 | int alphabits = 4; | ||
360 | int depthbits = 16; | ||
361 | |||
362 | OSStatus error; | ||
363 | |||
364 | // create pixel format attribute list | ||
365 | |||
366 | GLint pixelFormatAttributes[256]; | ||
367 | int numAttrs = 0; | ||
368 | |||
369 | pixelFormatAttributes[numAttrs++] = AGL_RGBA; | ||
370 | pixelFormatAttributes[numAttrs++] = AGL_DOUBLEBUFFER; | ||
371 | |||
372 | pixelFormatAttributes[numAttrs++] = AGL_RED_SIZE; | ||
373 | pixelFormatAttributes[numAttrs++] = redbits; | ||
374 | pixelFormatAttributes[numAttrs++] = AGL_GREEN_SIZE; | ||
375 | pixelFormatAttributes[numAttrs++] = greenbits; | ||
376 | pixelFormatAttributes[numAttrs++] = AGL_BLUE_SIZE; | ||
377 | pixelFormatAttributes[numAttrs++] = bluebits; | ||
378 | pixelFormatAttributes[numAttrs++] = AGL_ALPHA_SIZE; | ||
379 | pixelFormatAttributes[numAttrs++] = alphabits; | ||
380 | pixelFormatAttributes[numAttrs++] = AGL_DEPTH_SIZE; | ||
381 | pixelFormatAttributes[numAttrs++] = depthbits; | ||
382 | |||
383 | pixelFormatAttributes[numAttrs++] = AGL_NONE; | ||
384 | |||
385 | // create pixel format. | ||
386 | |||
387 | AGLDevice mainMonitor = GetMainDevice(); | ||
388 | AGLPixelFormat pixelFormat = aglChoosePixelFormat( &mainMonitor, 1, pixelFormatAttributes ); | ||
389 | if( pixelFormat == NULL ){ | ||
390 | return; | ||
391 | } | ||
392 | |||
393 | aglContext = aglCreateContext( pixelFormat, NULL ); | ||
394 | |||
395 | aglDestroyPixelFormat( pixelFormat ); | ||
396 | |||
397 | if( aglContext == NULL ){ | ||
398 | osxCloseMainWindow(); | ||
399 | return; | ||
400 | } | ||
401 | |||
402 | Rect windowContentBounds; | ||
403 | windowContentBounds.left = 0; | ||
404 | windowContentBounds.top = 0; | ||
405 | windowContentBounds.right = width; | ||
406 | windowContentBounds.bottom = height; | ||
407 | |||
408 | int windowAttributes = kWindowCloseBoxAttribute | ||
409 | | kWindowFullZoomAttribute | ||
410 | | kWindowCollapseBoxAttribute | ||
411 | | kWindowResizableAttribute | ||
412 | | kWindowStandardHandlerAttribute | ||
413 | | kWindowLiveResizeAttribute; | ||
414 | |||
415 | error = CreateNewWindow( kDocumentWindowClass, windowAttributes, &windowContentBounds, &windowReference ); | ||
416 | if( ( error != noErr ) || ( windowReference == NULL ) ){ | ||
417 | osxCloseMainWindow(); | ||
418 | return; | ||
419 | } | ||
420 | |||
421 | windowUPP = NewEventHandlerUPP( osxWindowEventHandler ); | ||
422 | |||
423 | error = InstallWindowEventHandler( windowReference, windowUPP,GetEventTypeCount( OSX_WINDOW_EVENT_TYPES ), OSX_WINDOW_EVENT_TYPES, NULL, NULL ); | ||
424 | if( error != noErr ){ | ||
425 | osxCloseMainWindow(); | ||
426 | return; | ||
427 | } | ||
428 | |||
429 | // The process-type must be changed for a ForegroundApplication | ||
430 | // Unless it is a foreground-process, the application will not show in the dock or expose and the window | ||
431 | // will not behave properly. | ||
432 | ProcessSerialNumber currentProcess; | ||
433 | GetCurrentProcess( ¤tProcess ); | ||
434 | TransformProcessType( ¤tProcess, kProcessTransformToForegroundApplication ); | ||
435 | SetFrontProcess( ¤tProcess ); | ||
436 | |||
437 | SetWindowTitleWithCFString( windowReference, CFSTR( "ODE - Drawstuff" ) ); | ||
438 | RepositionWindow( windowReference, NULL, kWindowCenterOnMainScreen ); | ||
439 | |||
440 | ShowWindow( windowReference ); | ||
441 | |||
442 | if( !aglSetDrawable( aglContext, GetWindowPort( windowReference ) ) ){ | ||
443 | osxCloseMainWindow(); | ||
444 | return; | ||
445 | } | ||
446 | |||
447 | if( !aglSetCurrentContext( aglContext ) ){ | ||
448 | osxCloseMainWindow(); | ||
449 | } | ||
450 | |||
451 | windowWidth = width; | ||
452 | windowHeight = height; | ||
453 | } | ||
454 | |||
455 | int osxInstallEventHandlers(){ | ||
456 | |||
457 | OSStatus error; | ||
458 | |||
459 | mouseUPP = NewEventHandlerUPP( osxMouseEventHandler ); | ||
460 | |||
461 | error = InstallEventHandler( GetApplicationEventTarget(), mouseUPP, GetEventTypeCount( OSX_MOUSE_EVENT_TYPES ), OSX_MOUSE_EVENT_TYPES, NULL, NULL ); | ||
462 | if( error != noErr ){ | ||
463 | return GL_FALSE; | ||
464 | } | ||
465 | |||
466 | keyboardUPP = NewEventHandlerUPP( osxKeyEventHandler ); | ||
467 | |||
468 | error = InstallEventHandler( GetApplicationEventTarget(), keyboardUPP, GetEventTypeCount( OSX_KEY_EVENT_TYPES ), OSX_KEY_EVENT_TYPES, NULL, NULL ); | ||
469 | if( error != noErr ){ | ||
470 | return GL_FALSE; | ||
471 | } | ||
472 | |||
473 | return GL_TRUE; | ||
474 | } | ||
475 | |||
476 | extern void dsPlatformSimLoop( int givenWindowWidth, int givenWindowHeight, dsFunctions *fn, int givenPause ){ | ||
477 | |||
478 | functions = fn; | ||
479 | |||
480 | paused = givenPause; | ||
481 | |||
482 | osxCreateMainWindow( givenWindowWidth, givenWindowHeight ); | ||
483 | osxInstallEventHandlers(); | ||
484 | |||
485 | dsStartGraphics( windowWidth, windowHeight, fn ); | ||
486 | |||
487 | static bool firsttime=true; | ||
488 | if( firsttime ) | ||
489 | { | ||
490 | fprintf | ||
491 | ( | ||
492 | stderr, | ||
493 | "\n" | ||
494 | "Simulation test environment v%d.%02d\n" | ||
495 | " Ctrl-P : pause / unpause (or say `-pause' on command line).\n" | ||
496 | " Ctrl-O : single step when paused.\n" | ||
497 | " Ctrl-T : toggle textures (or say `-notex' on command line).\n" | ||
498 | " Ctrl-S : toggle shadows (or say `-noshadow' on command line).\n" | ||
499 | " Ctrl-V : print current viewpoint coordinates (x,y,z,h,p,r).\n" | ||
500 | " Ctrl-W : write frames to ppm files: frame/frameNNN.ppm\n" | ||
501 | " Ctrl-X : exit.\n" | ||
502 | "\n" | ||
503 | "Change the camera position by clicking + dragging in the window.\n" | ||
504 | " Left button - pan and tilt.\n" | ||
505 | " Right button (or Ctrl + button) - forward and sideways.\n" | ||
506 | " Left + Right button (or middle button, or Alt + button) - sideways and up.\n" | ||
507 | "\n",DS_VERSION >> 8,DS_VERSION & 0xff | ||
508 | ); | ||
509 | firsttime = false; | ||
510 | } | ||
511 | |||
512 | if( fn -> start ) fn->start(); | ||
513 | |||
514 | int frame = 1; | ||
515 | running = true; | ||
516 | while( running ){ | ||
517 | // read in and process all pending events for the main window | ||
518 | EventRef event; | ||
519 | EventTargetRef eventDispatcher = GetEventDispatcherTarget(); | ||
520 | while( ReceiveNextEvent( 0, NULL, 0.0, TRUE, &event ) == noErr ){ | ||
521 | SendEventToEventTarget( event, eventDispatcher ); | ||
522 | ReleaseEvent( event ); | ||
523 | } | ||
524 | |||
525 | dsDrawFrame( windowWidth, windowHeight, fn, paused && !singlestep ); | ||
526 | singlestep = false; | ||
527 | |||
528 | glFlush(); | ||
529 | aglSwapBuffers( aglContext ); | ||
530 | |||
531 | // capture frames if necessary | ||
532 | if( !paused && writeframes ){ | ||
533 | captureFrame( frame ); | ||
534 | frame++; | ||
535 | } | ||
536 | } | ||
537 | |||
538 | if( fn->stop ) fn->stop(); | ||
539 | dsStopGraphics(); | ||
540 | |||
541 | osxCloseMainWindow(); | ||
542 | } | ||