1 /*
2 PLIB - A Suite of Portable Game Libraries
3 Copyright (C) 1998,2002 Steve Baker
4
5 This library is free software; you can redistribute it and/or
6 modify it under the terms of the GNU Library General Public
7 License as published by the Free Software Foundation; either
8 version 2 of the License, or (at your option) any later version.
9
10 This library is distributed in the hope that it will be useful,
11 but WITHOUT ANY WARRANTY; without even the implied warranty of
12 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
13 Library General Public License for more details.
14
15 You should have received a copy of the GNU Library General Public
16 License along with this library; if not, write to the Free Software
17 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
18
19 For further information visit http://plib.sourceforge.net
20
21 $Id: pu.cxx 2030 2005-05-23 21:24:26Z fayjf $
22 */
23
24 #include "puLocal.h"
25
26 #if defined(UL_AGL)
27 # include <agl.h>
28 #elif defined(UL_CGL)
29 # include <OpenGL/CGLCurrent.h>
30 #elif defined(UL_GLX)
31 # include <GL/glx.h>
32 #endif
33
34
35 int puRefresh = TRUE ;
36
37
38 static puGetWindowCallback cbGetWindow;
39 static puSetWindowCallback cbSetWindow;
40 static puGetWindowSizeCallback cbGetWindowSize;
41 static puSetWindowSizeCallback cbSetWindowSize;
42
43
puSetWindowFuncs(puGetWindowCallback getWindow,puSetWindowCallback setWindow,puGetWindowSizeCallback getWindowSize,puSetWindowSizeCallback setWindowSize)44 void puSetWindowFuncs ( puGetWindowCallback getWindow,
45 puSetWindowCallback setWindow,
46 puGetWindowSizeCallback getWindowSize,
47 puSetWindowSizeCallback setWindowSize )
48 {
49 cbGetWindow = getWindow;
50 cbSetWindow = setWindow;
51 cbGetWindowSize = getWindowSize;
52 cbSetWindowSize = setWindowSize;
53 }
54
55
puGetWindow()56 int puGetWindow ()
57 {
58 if ( !cbGetWindow )
59 ulSetError ( UL_FATAL, "puGetWindow: Callbacks not initialized." ) ;
60 return ( *cbGetWindow ) () ;
61 }
62
puSetWindow(int window)63 void puSetWindow ( int window )
64 {
65 if ( !cbSetWindow )
66 ulSetError ( UL_WARNING, "puSetWindow: Cannot set window (null callback)." ) ;
67 else
68 ( *cbSetWindow ) ( window ) ;
69 }
70
puGetWindowSize(int * width,int * height)71 void puGetWindowSize ( int *width, int *height )
72 {
73 if ( !cbGetWindowSize )
74 ulSetError ( UL_FATAL, "puGetWindowSize: Callbacks not initialized." ) ;
75 ( *cbGetWindowSize ) ( width, height ) ;
76 }
77
puSetWindowSize(int width,int height)78 void puSetWindowSize ( int width, int height )
79 {
80 if ( !cbSetWindowSize )
81 ulSetError ( UL_WARNING, "puSetWindowSize: Cannot change size (null callback)." ) ;
82 else
83 ( *cbSetWindowSize ) ( width, height ) ;
84 }
85
puGetWindowWidth()86 int puGetWindowWidth ()
87 {
88 int w, h ;
89 puGetWindowSize ( &w, &h ) ;
90 return w ;
91 }
92
puGetWindowHeight()93 int puGetWindowHeight ()
94 {
95 int w, h ;
96 puGetWindowSize ( &w, &h ) ;
97 return h ;
98 }
99
100
101
glIsValidContext(void)102 static bool glIsValidContext ( void )
103 {
104 #if defined(UL_WGL)
105 return ( wglGetCurrentContext () != NULL ) ;
106 #elif defined(UL_AGL)
107 return ( aglGetCurrentContext () != NULL ) ;
108 #elif defined(UL_CGL)
109 return ( CGLGetCurrentContext () != NULL ) ;
110 #elif defined(UL_GLX)
111 return ( glXGetCurrentContext () != NULL ) ;
112 #else
113 return true ;
114 #endif
115 }
116
117
118 static int _puCursor_enable = FALSE ;
119 static int _puCursor_x = 0 ;
120 static int _puCursor_y = 0 ;
121 static float _puCursor_bgcolour [4] = { 1.0f, 1.0f, 1.0f, 1.0f } ;
122 static float _puCursor_fgcolour [4] = { 0.0f, 0.0f, 0.0f, 1.0f } ;
123
puHideCursor(void)124 void puHideCursor ( void ) { _puCursor_enable = FALSE ; }
puShowCursor(void)125 void puShowCursor ( void ) { _puCursor_enable = TRUE ; }
puCursorIsHidden(void)126 int puCursorIsHidden ( void ) { return ! _puCursor_enable ; }
127
puCursor(int x,int y)128 void puCursor ( int x, int y )
129 {
130 _puCursor_x = x ;
131 _puCursor_y = y ;
132 }
133
134
puDrawCursor(int x,int y)135 static void puDrawCursor ( int x, int y )
136 {
137 glColor4fv ( _puCursor_bgcolour ) ;
138
139 glBegin ( GL_TRIANGLES ) ;
140 glVertex2i ( x, y ) ;
141 glVertex2i ( x + 13, y - 4 ) ;
142 glVertex2i ( x + 4, y - 13 ) ;
143
144 glVertex2i ( x + 8, y - 3 ) ;
145 glVertex2i ( x + 17, y - 12 ) ;
146 glVertex2i ( x + 12, y - 17 ) ;
147
148 glVertex2i ( x + 12, y - 17 ) ;
149 glVertex2i ( x + 3, y - 8 ) ;
150 glVertex2i ( x + 8, y - 3 ) ;
151 glEnd () ;
152
153 glColor4fv ( _puCursor_fgcolour ) ;
154
155 glBegin ( GL_TRIANGLES ) ;
156 glVertex2i ( x+1, y-1 ) ;
157 glVertex2i ( x + 11, y - 4 ) ;
158 glVertex2i ( x + 4, y - 11 ) ;
159
160 glVertex2i ( x + 8, y - 5 ) ;
161 glVertex2i ( x + 15, y - 12 ) ;
162 glVertex2i ( x + 12, y - 15 ) ;
163
164 glVertex2i ( x + 12, y - 15 ) ;
165 glVertex2i ( x + 5, y - 8 ) ;
166 glVertex2i ( x + 8, y - 5 ) ;
167 glEnd () ;
168 }
169
170
171 // Pointer to linked list of objects to delete
172 // as a result of keyboarding or mouse clicking
173
174 static puObject *objects_to_delete = NULL;
175
176
puDeleteObject(puObject * ob)177 void puDeleteObject ( puObject *ob )
178 {
179 if ( ob == NULL )
180 return ;
181
182 puGroup *parent = ob->getParent () ;
183
184 /* Add object to linked list to be deleted */
185 if ( objects_to_delete == NULL )
186 objects_to_delete = ob ;
187 else
188 {
189 /* Ensure that objects are deleted in the order of puDeleteObject calls */
190
191 puObject *last ;
192
193 for ( last = objects_to_delete ;
194 last -> getNextObject() != NULL ;
195 last = last -> getNextObject() )
196 /* Find last object. */ ;
197
198 last -> setNextObject ( ob ) ;
199 }
200
201 /* Remove from parent interface */
202
203 if ( parent != ob && parent != NULL )
204 parent -> remove ( ob ) ; /* Sets object's next and previous pointers to null as well */
205 }
206
207
puCleanUpJunk(void)208 void puCleanUpJunk ( void )
209 {
210 puObject * local_objects_to_delete = objects_to_delete ;
211 objects_to_delete = NULL ;
212 /* Step through the linked list of objects to delete, removing them. */
213 while ( local_objects_to_delete != NULL )
214 {
215 puObject *next_ob = local_objects_to_delete -> getNextObject() ;
216 delete local_objects_to_delete ;
217 local_objects_to_delete = next_ob ;
218
219 /* If we've reached the end of the list, start over (in case we've deleted a group and
220 * it has put new widgets on the delete list)
221 */
222 if ( local_objects_to_delete == NULL )
223 {
224 local_objects_to_delete = objects_to_delete ;
225 objects_to_delete = NULL ;
226 }
227 }
228 }
229
230
231 static puObject *active_widget ; /* Widget which is currently receiving user input */
232 static char *input_paste_buffer ; /* Cut/Copy/Paste buffer for input widgets */
233
234 static int firsttime = TRUE ;
235
puRealInit(void)236 void puRealInit ( void )
237 {
238 if ( firsttime )
239 {
240 if ( ! glIsValidContext () )
241 {
242 ulSetError ( UL_FATAL,
243 "puInit called without a valid OpenGL context.");
244 }
245
246 new puInterface ( 0, 0 ) ;
247
248 active_widget = NULL ;
249 input_paste_buffer = NULL ;
250
251 firsttime = FALSE ;
252 }
253 }
254
puExit(void)255 void puExit ( void )
256 {
257 if ( firsttime )
258 ulSetError ( UL_FATAL, "puExit called without a previous call to puInit." ) ;
259
260 delete puGetBaseLiveInterface () ;
261 firsttime = TRUE ;
262 }
263
puSetOpenGLState(void)264 static void puSetOpenGLState ( void )
265 {
266 int w, h ;
267
268 puGetWindowSize ( &w, &h ) ;
269
270 glPushAttrib ( GL_ENABLE_BIT | GL_VIEWPORT_BIT | GL_TRANSFORM_BIT | GL_LIGHTING_BIT ) ;
271
272 glDisable ( GL_LIGHTING ) ;
273 glDisable ( GL_FOG ) ;
274 glDisable ( GL_TEXTURE_2D ) ;
275 glDisable ( GL_DEPTH_TEST ) ;
276 glDisable ( GL_CULL_FACE ) ;
277
278 glViewport ( 0, 0, w, h ) ;
279
280 glMatrixMode ( GL_PROJECTION ) ;
281 glPushMatrix () ;
282 glLoadIdentity () ;
283 glOrtho ( 0, w, 0, h, -1, 1 ) ;
284 glMatrixMode ( GL_MODELVIEW ) ;
285 glPushMatrix () ;
286 glLoadIdentity () ;
287 }
288
puRestoreOpenGLState(void)289 static void puRestoreOpenGLState ( void )
290 {
291 glMatrixMode ( GL_PROJECTION ) ;
292 glPopMatrix () ;
293 glMatrixMode ( GL_MODELVIEW ) ;
294 glPopMatrix () ;
295 glPopAttrib () ;
296 }
297
298
puDisplay(void)299 void puDisplay ( void )
300 {
301 puCleanUpJunk () ;
302
303 puSetOpenGLState () ;
304 puGetUltimateLiveInterface () -> draw ( 0, 0 ) ;
305
306 int h = puGetWindowHeight () ;
307
308 if ( _puCursor_enable )
309 puDrawCursor ( _puCursor_x,
310 h - _puCursor_y ) ;
311
312 puRestoreOpenGLState () ;
313
314 puRefresh = FALSE ;
315 }
316
317
puDisplay(int window_number)318 void puDisplay ( int window_number ) /* Deprecated */
319 {
320 if ( window_number == puGetWindow () )
321 puDisplay () ;
322 }
323
324
puKeyboard(int key,int updown,int,int)325 int puKeyboard ( int key, int updown, int, int )
326 {
327 return puKeyboard ( key, updown ) ;
328 }
329
330
puKeyboard(int key,int updown)331 int puKeyboard ( int key, int updown )
332 {
333 int return_value = puGetBaseLiveInterface () -> checkKey ( key, updown ) ;
334
335 puCleanUpJunk () ;
336
337 return return_value ;
338 }
339
340
341 static int last_buttons = 0 ;
342 static int pu_mouse_x = 0 ;
343 static int pu_mouse_y = 0 ;
344 static int pu_mouse_offset_x = 0 ;
345 static int pu_mouse_offset_y = 0 ;
346
puGetPressedButton()347 int puGetPressedButton ()
348 {
349 return last_buttons ;
350 }
351
puMouse(int button,int updown,int x,int y)352 int puMouse ( int button, int updown, int x, int y )
353 {
354 puCursor ( x, y ) ;
355
356 int h = puGetWindowHeight () ;
357
358 if ( updown == PU_DOWN )
359 last_buttons |= ( 1 << button ) ;
360 else
361 last_buttons &= ~( 1 << button ) ;
362
363 pu_mouse_x = x ;
364 pu_mouse_y = h - y ;
365
366 puObject *active = puActiveWidget () ;
367
368 if ( ( last_buttons != 0 ) && ( active != NULL ) )
369 {
370 int x_offset, y_offset ;
371 active -> getAbsolutePosition ( &x_offset, &y_offset ) ;
372
373 x_offset -= active -> getABox () -> min [0] ;
374 y_offset -= active -> getABox () -> min [1] ;
375
376 if ( ( ! active -> isHit ( pu_mouse_x - x_offset, pu_mouse_y - y_offset ) ) &&
377 ( active -> getWhenToDeactivate () == PUDEACTIVATE_ON_MOUSE_CLICK ) )
378 {
379 active -> invokeDownCallback () ;
380 puDeactivateWidget () ;
381 }
382 }
383
384 int return_value = puGetBaseLiveInterface () -> checkHit ( button,
385 updown, pu_mouse_x, pu_mouse_y ) ;
386
387 puCleanUpJunk () ;
388
389 return return_value ;
390 }
391
392
puMouse(int x,int y)393 int puMouse ( int x, int y )
394 {
395 puCursor ( x, y ) ;
396
397 // Pick buttons in order of descending priority: Left, Right, Middle
398 int button =
399 (last_buttons & (1<<PU_LEFT_BUTTON )) ? PU_LEFT_BUTTON :
400 (last_buttons & (1<<PU_MIDDLE_BUTTON)) ? PU_MIDDLE_BUTTON :
401 (last_buttons & (1<<PU_RIGHT_BUTTON )) ? PU_RIGHT_BUTTON : PU_NOBUTTON ;
402
403 int h = puGetWindowHeight () ;
404
405 pu_mouse_x = x ;
406 pu_mouse_y = h - y ;
407
408 /*
409 When you drag over an ACTIVE widget, you don't
410 affect any other widgets until you release the
411 mouse button.
412 */
413 if ( puActiveWidget () )
414 {
415 if ( puActiveWidget()->checkHit(button, PU_DRAG, pu_mouse_x - pu_mouse_offset_x,
416 pu_mouse_y - pu_mouse_offset_y) )
417 return TRUE ;
418 else
419 return FALSE ;
420 }
421
422 int return_value = puGetBaseLiveInterface () -> checkHit ( button,
423 PU_DRAG, pu_mouse_x, pu_mouse_y ) ;
424
425 puCleanUpJunk () ;
426
427 return return_value ;
428 }
429
puMoveToLast(puObject * ob)430 void puMoveToLast (puObject *ob)
431 {
432 puGroup *parent = ob -> getParent () ;
433
434 /* If no parent interface, return. */
435
436 if ( ! parent ) return;
437
438 /* Remove "ob" from present place in the "dlist" list */
439
440 parent -> remove (ob) ;
441
442 /* Place at the end of the list */
443
444 parent -> add (ob) ;
445
446 /*
447 Now repeat the process for the parent interface so that the interface will
448 be drawn last of all interfaces.
449 */
450
451 puMoveToLast ( parent );
452 }
453
puDeactivateWidget(void)454 void puDeactivateWidget ( void ) { active_widget = NULL ; }
puSetActiveWidget(puObject * w,int x,int y)455 void puSetActiveWidget ( puObject *w, int x, int y )
456 {
457 active_widget = w ;
458 pu_mouse_offset_x = pu_mouse_x - x ;
459 pu_mouse_offset_y = pu_mouse_y - y ;
460 }
461
puActiveWidget(void)462 puObject *puActiveWidget ( void ) { return active_widget ; }
463
puSetPasteBuffer(const char * ch)464 void puSetPasteBuffer ( const char *ch )
465 {
466 delete [] input_paste_buffer ;
467 input_paste_buffer = ulStrDup ( ch ) ;
468 }
469
puGetPasteBuffer(void)470 char *puGetPasteBuffer ( void ) { return input_paste_buffer ; }
471
puNeedRefresh(void)472 int puNeedRefresh ( void ) { return puRefresh ; }
puPostRefresh(void)473 void puPostRefresh ( void ) { puRefresh = TRUE ; }
474
475
puSetResizeMode(int mode)476 void puSetResizeMode ( int mode )
477 {
478 static int last = 0;
479 if ( last == 0 && mode != 0 )
480 ulSetError ( UL_WARNING, "puSetResizeMode is deprecated!" ) ;
481 last = mode ;
482 }
483