changed: auto add updateData callback to stages so that stagedata can be updated...
[opensg.git] / Source / WindowSystem / Carbon / testWindowCarbon.cpp
blob43fb800ab8e5f5d201b1a8ae0b12628b38119068
1 #include "OSGConfig.h"
3 #include <iostream>
5 #include <AGL/agl.h>
7 #ifdef check
8 # undef check
9 #endif
11 #include "OSGFieldContainerFactory.h"
12 #include "OSGVector.h"
13 #include "OSGQuaternion.h"
14 #include "OSGMatrix.h"
15 #include "OSGMatrixUtility.h"
16 #include "OSGBoxVolume.h"
17 #include "OSGNode.h"
18 #include "OSGGroup.h"
19 #include "OSGTransform.h"
20 #include "OSGSimpleGeometry.h"
21 #include "OSGAction.h"
22 #include "OSGRenderAction.h"
23 #include "OSGSceneFileHandler.h"
24 #include "OSGDirectionalLight.h"
26 #include "OSGViewport.h"
27 #include "OSGCamera.h"
28 #include "OSGWindow.h"
29 #include "OSGCarbonWindow.h"
30 #include "OSGCamera.h"
31 #include "OSGPerspectiveCamera.h"
32 #include "OSGSolidBackground.h"
34 #include "OSGTrackball.h"
36 OSG::CarbonWindowUnrecPtr win;
38 OSG::RenderActionRefPtr ract;
39 OSG::NodeRecPtr root;
40 OSG::NodeRecPtr file;
41 OSG::ViewportRecPtr vp;
42 OSG::TransformRecPtr cam_trans;
43 OSG::Trackball tball;
44 OSG::PerspectiveCameraRecPtr cam;
46 bool stopIt = false;
47 int lastx=0, lasty=0;
49 #if !defined(__LP64__)
51 void redraw ( void )
53 OSG::Matrix m1, m2, m3;
54 OSG::Quaternion q1;
56 tball.getRotation().getValue(m3);
57 q1.setValue(m3);
58 m1.setRotate(q1);
59 m2.setTranslate( tball.getPosition() );
60 m1.mult( m2 );
61 cam_trans->editSFMatrix()->setValue( m1 );
63 OSG::Thread::getCurrentChangeList()->commitChanges();
65 win->render(ract);
68 static OSStatus handleMouseEvent(EventHandlerCallRef nextHandler, EventRef event, void *userData)
70 OSStatus err;
71 OSG::Real32 w,h,a,b,c,d;
73 // Get the window
74 WindowRef window;
75 err = GetEventParameter(event, kEventParamWindowRef, typeWindowRef, 0, sizeof(window), 0, &window);
76 if (err != noErr)
77 return err;
79 // Get the window rectangle
80 Rect portRect;
81 GetWindowPortBounds(window, &portRect);
83 // Get the pressed mouse button
84 EventMouseButton mouseButton;
85 err = GetEventParameter(event, kEventParamMouseButton, typeMouseButton, 0, sizeof(mouseButton), 0, &mouseButton);
86 if (err != noErr)
87 return err;
89 // Get the modifier keys
90 ::UInt32 modifierKeys;
91 err = GetEventParameter(event, kEventParamKeyModifiers, typeUInt32, 0, sizeof(modifierKeys), 0, &modifierKeys);
92 if (err != noErr)
93 return err;
95 // Traditionally, Apple mice just have one button. It is common practice to simulate
96 // the middle and the right button by pressing the option or the control key.
97 if (mouseButton == kEventMouseButtonPrimary)
99 if (modifierKeys & optionKey)
100 mouseButton = kEventMouseButtonTertiary;
101 if (modifierKeys & controlKey)
102 mouseButton = kEventMouseButtonSecondary;
105 // Get the location of the mouse pointer
106 ::Point location;
107 err = GetEventParameter(event, kEventParamMouseLocation, typeQDPoint, 0, sizeof(location), 0, &location);
108 if (err != noErr)
109 return err;
111 // The location of the mouse pointer is in screen coordinates, so
112 // we have to transform it into the local coordinate system of the
113 // window content area.
114 SetPortWindowPort(window);
115 GlobalToLocal(&location);
117 // Handle the different kinds of events
118 ::UInt32 eventKind = GetEventKind(event);
119 switch (eventKind)
121 // mouse button pressed
122 case kEventMouseDown:
123 lastx = location.h;
124 lasty = location.v;
125 switch (mouseButton)
127 case kEventMouseButtonPrimary: // left button
128 break;
129 case kEventMouseButtonSecondary: // right button
130 tball.setAutoPositionNeg(true);
131 break;
132 case kEventMouseButtonTertiary: // middle button
133 tball.setAutoPosition(true);
134 break;
136 break;
138 // mouse button released
139 case kEventMouseUp:
140 switch (mouseButton)
142 case kEventMouseButtonPrimary: // left button
143 break;
144 case kEventMouseButtonSecondary: // right button
145 tball.setAutoPositionNeg(false);
146 break;
147 case kEventMouseButtonTertiary: // middle button
148 tball.setAutoPosition(false);
149 break;
151 break;
153 // mouse moved while a button is pressed
154 case kEventMouseDragged:
155 w = win->getWidth();
156 h = win->getHeight();
157 a = -2. * ( lastx / w - .5 );
158 b = -2. * ( .5 - lasty / h );
159 c = -2. * ( location.h / w - .5 );
160 d = -2. * ( .5 - location.v / h );
161 switch (mouseButton)
163 case kEventMouseButtonPrimary: // left button
164 tball.updateRotation( a, b, c, d );
165 break;
166 case kEventMouseButtonSecondary: // right button
167 tball.updatePositionNeg( a, b, c, d );
168 break;
169 case kEventMouseButtonTertiary: // middle button
170 tball.updatePosition( a, b, c, d );
171 break;
173 lastx = location.h;
174 lasty = location.v;
176 // Redraw the whole window
177 InvalWindowRect(window, &portRect);
179 break;
182 // We have to return eventNotHandledErr, otherwise the system is
183 // not able to operate the menu and the window border
184 return eventNotHandledErr;
187 static OSStatus handleKeyEvent(EventHandlerCallRef nextHandler, EventRef event, void *userData)
189 OSStatus err;
191 // Try to determine the size of the text input
192 ::UInt32 actualSize;
193 err = GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, 0, 0, &actualSize, 0);
194 if (err != noErr)
195 return err;
197 // The input can actually consist of more than one character.
198 // We are only interested in single character input
199 if (actualSize == sizeof(UniChar))
201 // Get the character unicode
202 UniChar c;
203 err = GetEventParameter(event, kEventParamTextInputSendText, typeUnicodeText, 0, sizeof(UniChar), 0, &c);
204 if (err != noErr)
205 return err;
207 // Handle different keyboard commands
208 aglSetCurrentContext(win->getContext());
209 switch (c)
211 case kEscapeCharCode:
212 QuitApplicationEventLoop();
213 break;
214 case 'a':
215 glDisable( GL_LIGHTING );
216 redraw();
217 break;
218 case 's':
219 glEnable( GL_LIGHTING );
220 redraw();
221 break;
222 case 'z':
223 glPolygonMode( GL_FRONT_AND_BACK, GL_POINT);
224 redraw();
225 break;
226 case 'x':
227 glPolygonMode( GL_FRONT_AND_BACK, GL_LINE);
228 redraw();
229 break;
230 case 'c':
231 glPolygonMode( GL_FRONT_AND_BACK, GL_FILL);
232 redraw();
233 break;
237 return noErr;
240 static OSStatus handleWindowEvent(EventHandlerCallRef nextHandler, EventRef event, void *userData)
242 OSStatus err;
244 // Get the window
245 WindowRef window;
246 err = GetEventParameter(event, kEventParamDirectObject, typeWindowRef, 0, sizeof(window), 0, &window);
247 if (err != noErr)
248 return err;
250 // Handle the different kinds of events
251 ::UInt32 eventKind = GetEventKind(event);
252 switch (eventKind)
254 // Quit the application when the user closes the window
255 case kEventWindowClose:
256 QuitApplicationEventLoop();
257 return noErr;
259 // Draw the contents of the window
260 case kEventWindowDrawContent:
261 redraw();
262 return noErr;
264 case kEventWindowBoundsChanged:
266 // Update the GL context
267 aglUpdateContext(win->getContext());
269 // Find out if we have a move or a resize situation
270 ::UInt32 attributes;
271 GetEventParameter(event, kEventParamAttributes, typeUInt32, 0, sizeof(attributes), 0, &attributes);
273 if ((attributes & kWindowBoundsChangeSizeChanged) != 0)
275 // Get the new bounds of the window
276 Rect bounds;
277 GetEventParameter(event, kEventParamCurrentBounds, typeQDRectangle, 0, sizeof(Rect), 0, &bounds);
279 // Resize the OpenSG Window
280 GLsizei width = bounds.right - bounds.left;
281 GLsizei height = bounds.bottom - bounds.top;
282 win->resize(width, height);
284 // Redraw the whole window
285 Rect portRect;
286 GetWindowPortBounds(window, &portRect);
287 InvalWindowRect(window, &portRect);
290 return noErr;
293 default:
294 return eventNotHandledErr;
298 static pascal OSStatus eventHandler(EventHandlerCallRef nextHandler, EventRef event, void *userData)
300 ::UInt32 eventClass = GetEventClass(event);
301 switch (eventClass)
303 // Mouse events
304 case kEventClassMouse:
305 return handleMouseEvent(nextHandler, event, userData);
307 // Key press events
308 case kEventClassTextInput:
309 return handleKeyEvent(nextHandler, event, userData);
311 // Window events
312 case kEventClassWindow:
313 return handleWindowEvent(nextHandler, event, userData);
315 default:
316 return eventNotHandledErr;
320 // A magic method that allows applications to react to events even
321 // when they are not organized in a bundle
322 void osx_AllowForeground()
324 ProcessSerialNumber psn = { 0, kCurrentProcess };
325 TransformProcessType(&psn, kProcessTransformToForegroundApplication);
326 SetFrontProcess(&psn);
329 int doMain (int argc, char **argv)
331 osx_AllowForeground();
333 // OSG init
335 OSG::osgInit(argc, argv);
337 // create the graph
339 // beacon for camera and light
340 OSG::NodeUnrecPtr b1n = OSG::Node::create();
341 OSG::GroupUnrecPtr b1 = OSG::Group::create();
342 b1n->setCore( b1 );
344 // transformation
345 OSG::NodeUnrecPtr t1n = OSG::Node::create();
346 OSG::TransformUnrecPtr t1 = OSG::Transform::create();
347 t1n->setCore( t1 );
348 t1n->addChild( b1n );
350 cam_trans = t1;
352 // light
354 OSG::NodeUnrecPtr dlight = OSG::Node::create();
355 OSG::DirectionalLightUnrecPtr dl = OSG::DirectionalLight::create();
357 dlight->setCore( dl );
359 dl->setAmbient( .0, .0, .0, 1 );
360 dl->setDiffuse( .8, .8, .8, .8 );
361 dl->setDirection(0,0,1);
362 dl->setBeacon( b1n);
364 // root
365 root = OSG::Node::create();
366 OSG::GroupUnrecPtr gr1 = OSG::Group::create();
368 root->setCore( gr1 );
369 root->addChild( t1n );
370 root->addChild( dlight );
372 // Load the file
374 OSG::NodeUnrecPtr file = NULL;
376 if ( argc > 1 )
377 file = OSG::SceneFileHandler::the()->read(argv[1]);
379 if ( file == NULL )
381 std::cerr << "Couldn't load file, ignoring" << std::endl;
382 file = OSG::makeTorus( .5, 2, 16, 16 );
385 OSG::Thread::getCurrentChangeList()->commitChanges();
386 file->updateVolume();
388 OSG::Vec3f min,max;
389 file->getVolume().getBounds( min, max );
391 std::cout << "Volume: from " << min << " to " << max << std::endl;
393 dlight->addChild( file );
395 std::cerr << "Tree: " << std::endl;
396 //root->dump();
398 // Camera
399 cam = OSG::PerspectiveCamera::create();
401 cam->setBeacon( b1n );
402 cam->setFov( OSG::osgDegree2Rad( 90 ) );
403 cam->setNear( 0.1 );
404 cam->setFar( 100000 );
406 // Background
407 OSG::SolidBackgroundUnrecPtr bkgnd = OSG::SolidBackground::create();
409 bkgnd->setColor(OSG::Color3f(0,0,1));
411 // Viewport
413 vp = OSG::Viewport::create();
414 vp->setCamera( cam );
415 vp->setBackground( bkgnd );
416 vp->setRoot( root );
417 vp->setSize( 0,0, 1,1 );
419 // Action
421 ract = OSG::RenderAction::create();
423 // tball
425 OSG::Vec3f pos;
426 pos.setValues(min[0] + ((max[0] - min[0]) * 0.5),
427 min[1] + ((max[1] - min[1]) * 0.5),
428 max[2] + ( max[2] - min[2] ) * 1.5 );
430 float scale = (max[2] - min[2] + max[1] - min[1] + max[0] - min[0]) / 6;
432 OSG::Pnt3f tCenter(min[0] + (max[0] - min[0]) / 2,
433 min[1] + (max[1] - min[1]) / 2,
434 min[2] + (max[2] - min[2]) / 2);
436 tball.setMode( OSG::Trackball::OSGObject );
437 tball.setStartPosition( pos, true );
438 tball.setSum( true );
439 tball.setTranslationMode( OSG::Trackball::OSGFree );
440 tball.setTranslationScale(scale);
441 tball.setRotationCenter(tCenter);
443 // Carbon init
445 // Create window
446 WindowAttributes windowAttrs =
447 kWindowStandardDocumentAttributes |
448 kWindowLiveResizeAttribute |
449 kWindowStandardHandlerAttribute;
450 Rect contentRect;
451 SetRect(&contentRect, 0, 0, 300, 300);
452 WindowRef window;
453 CreateNewWindow(kDocumentWindowClass, windowAttrs, &contentRect, &window);
454 SetWindowTitleWithCFString(window, CFSTR("testWindowCarbon"));
456 // Install event handler
457 EventHandlerUPP eventHandlerUPP = NewEventHandlerUPP(eventHandler);
458 EventTypeSpec eventList[] =
460 { kEventClassTextInput, kEventTextInputUnicodeForKeyEvent },
461 { kEventClassMouse, kEventMouseDown },
462 { kEventClassMouse, kEventMouseUp },
463 { kEventClassMouse, kEventMouseDragged },
464 { kEventClassWindow, kEventWindowClose },
465 { kEventClassWindow, kEventWindowDrawContent },
466 { kEventClassWindow, kEventWindowBoundsChanged }
468 InstallWindowEventHandler(window, eventHandlerUPP, GetEventTypeCount(eventList), eventList, /*this*/0, 0);
470 // Initialize OpenGL
471 GLint attribs[] = { AGL_RGBA, AGL_DOUBLEBUFFER, AGL_DEPTH_SIZE, 16, AGL_NONE };
472 AGLPixelFormat pixelFormat = aglChoosePixelFormat(0, 0, attribs);
473 if (pixelFormat == 0)
474 std::cerr << "Cannot choose pixel format" << std::endl;
475 AGLContext context = aglCreateContext(pixelFormat, 0);
476 aglDestroyPixelFormat(pixelFormat);
477 if (context == 0)
478 std::cerr << "Cannot create context" << std::endl;
479 aglSetDrawable(context, GetWindowPort(window));
481 // Create OpenSG window
482 win = OSG::CarbonWindow::create();
483 win->addPort( vp );
484 win->setContext ( context );
485 win->init();
486 win->resize( 300, 300 );
488 // Show window
489 RepositionWindow(window, 0, kWindowCascadeOnMainScreen);
490 ShowWindow(window);
492 win->activate();
494 // do some OpenGL init. Will move into State Chunks later.
496 glEnable( GL_DEPTH_TEST );
497 glEnable( GL_LIGHTING );
498 glEnable( GL_LIGHT0 );
501 // Main loop ( event dispatching )
502 RunApplicationEventLoop();
504 // Cleanup
505 aglDestroyContext(context);
506 DisposeWindow(window);
507 DisposeEventHandlerUPP(eventHandlerUPP);
509 ract = NULL;
510 win = NULL;
511 root = NULL;
512 file = NULL;
513 vp = NULL;
514 cam_trans = NULL;
515 cam = NULL;
517 return 0;
520 int main (int argc, char **argv)
522 doMain(argc, argv);
524 OSG::osgExit();
526 return 0;
529 #else
530 int main (int argc, char **argv)
533 fprintf(stderr, "Carbon not available in 64bit\n");
535 #endif