Files
bullet3/Extras/glui/glui.cpp
erwin.coumans 352aed528e Added specialKeyboardUp handler to GLUI (why was it missing?)
Some cleanup for ForkLiftDemo
Enable textures for ConcavePhysicsDemo, 
Added scaling to BasicDemo to show small objects (20 centimeter)
Removed demos from 'AllBulletDemos': less (clutter) = more
2008-11-13 07:33:25 +00:00

2172 lines
58 KiB
C++

/****************************************************************************
GLUI User Interface Toolkit (LGPL)
---------------------------
glui.cpp
--------------------------------------------------
Copyright (c) 1998 Paul Rademacher
WWW: http://sourceforge.net/projects/glui/
Forums: http://sourceforge.net/forum/?group_id=92496
This library is free software; you can redistribute it and/or
modify it under the terms of the GNU Lesser General Public
License as published by the Free Software Foundation; either
version 2.1 of the License, or (at your option) any later version.
This library is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
Lesser General Public License for more details.
You should have received a copy of the GNU Lesser General Public
License along with this library; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*****************************************************************************/
#include "glui_internal_control.h"
/**
Note: moving this routine here from glui_add_controls.cpp prevents the linker
from touching glui_add_controls.o in non-deprecated programs, which
descreases the linked size of small GLUI programs substantially (100K+). (OSL 2006/06)
*/
void GLUI_Node::add_child_to_control(GLUI_Node *parent,GLUI_Control *child)
{
GLUI_Control *parent_control;
/*** Collapsible nodes have to be handled differently, b/c the first and
last children are swapped in and out ***/
parent_control = ((GLUI_Control*)parent);
if ( parent_control->collapsible == true ) {
if ( NOT parent_control->is_open ) {
/** Swap in the original first and last children **/
parent_control->child_head = parent_control->collapsed_node.child_head;
parent_control->child_tail = parent_control->collapsed_node.child_tail;
/*** Link this control ***/
child->link_this_to_parent_last( parent_control );
/** Swap the children back out ***/
parent_control->collapsed_node.child_head = parent_control->child_head;
parent_control->collapsed_node.child_tail = parent_control->child_tail;
parent_control->child_head = NULL;
parent_control->child_tail = NULL;
}
else {
child->link_this_to_parent_last( parent_control );
}
}
else {
child->link_this_to_parent_last( parent_control );
}
child->glui = (GLUI*) parent_control->glui;
child->update_size();
child->enabled = parent_control->enabled;
child->glui->refresh();
/** Now set the 'hidden' var based on the parent **/
if ( parent_control->hidden OR
(parent_control->collapsible AND NOT parent_control->is_open ) )
{
child->hidden = true;
}
}
/************************************ GLUI_Node::add_control() **************/
int GLUI_Node::add_control( GLUI_Control *child )
{
add_child_to_control(this,child);
return true;
}
/************************************ GLUI_Main::add_control() **************/
int GLUI_Main::add_control( GLUI_Node *parent, GLUI_Control *control )
{
add_child_to_control(parent,control);
return true;
}
/*** This object must be used to create a GLUI ***/
GLUI_Master_Object GLUI_Master;
/************************************ finish_drawing() ***********
Probably a silly routine. Called after all event handling callbacks.
*/
static void finish_drawing(void)
{
glFinish();
}
/************************************ GLUI_CB::operator()() ************/
void GLUI_CB::operator()(GLUI_Control*ctrl) const
{
if (idCB) idCB(ctrl->user_id);
if (objCB) objCB(ctrl);
}
/************************************************ GLUI::GLUI() **********/
int GLUI::init( const char *text, long flags, int x, int y, int parent_window )
{
int old_glut_window;
this->flags = flags;
window_name = text;
buffer_mode = buffer_back; ///< New smooth way
//buffer_mode = buffer_front; ///< Old flickery way (a bit faster).
/*** We copy over the current window callthroughs ***/
/*** (I think this might actually only be needed for subwindows) ***/
/* glut_keyboard_CB = GLUI_Master.glut_keyboard_CB;
glut_reshape_CB = GLUI_Master.glut_reshape_CB;
glut_special_CB = GLUI_Master.glut_special_CB;
glut_mouse_CB = GLUI_Master.glut_mouse_CB;*/
if ( (flags & GLUI_SUBWINDOW) != GLUI_SUBWINDOW ) { /* not a subwindow, creating a new top-level window */
old_glut_window = glutGetWindow();
create_standalone_window( window_name.c_str(), x, y );
setup_default_glut_callbacks();
if ( old_glut_window > 0 )
glutSetWindow( old_glut_window );
top_level_glut_window_id = glut_window_id;
}
else /* *is* a subwindow */
{
old_glut_window = glutGetWindow();
create_subwindow( parent_window, flags );
setup_default_glut_callbacks();
if ( old_glut_window > 0 )
glutSetWindow( old_glut_window );
top_level_glut_window_id = parent_window;
/*
glutReshapeFunc( glui_parent_window_reshape_func );
glutSpecialFunc( glui_parent_window_special_func );
glutKeyboardFunc( glui_parent_window_keyboard_func );
glutMouseFunc( glui_parent_window_mouse_func );
*/
}
return true;
}
/**************************** GLUI_Main::create_standalone_window() ********/
void GLUI_Main::create_standalone_window( const char *name, int x, int y )
{
glutInitWindowSize( 100, 100 );
if ( x >= 0 OR y >= 0 )
glutInitWindowPosition( x, y );
glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
glut_window_id = glutCreateWindow( name );
}
/******************************** GLUI_Main::create_subwindow() **********/
void GLUI_Main::create_subwindow( int parent_window, int window_alignment )
{
glut_window_id = glutCreateSubWindow(parent_window, 0,0, 100, 100);
this->parent_window = parent_window;
}
/**************************** GLUI_Main::setup_default_glut_callbacks() *****/
void GLUI_Main::setup_default_glut_callbacks( void )
{
glutDisplayFunc( glui_display_func );
glutReshapeFunc( glui_reshape_func );
glutKeyboardFunc( glui_keyboard_func );
glutSpecialFunc( glui_special_func );
glutMouseFunc( glui_mouse_func );
glutMotionFunc( glui_motion_func );
glutPassiveMotionFunc( glui_passive_motion_func );
glutEntryFunc( glui_entry_func );
glutVisibilityFunc( glui_visibility_func );
/* glutIdleFunc( glui_idle_func ); // FIXME! 100% CPU usage! */
}
/********************************************** glui_display_func() ********/
void glui_display_func(void)
{
GLUI *glui;
/* printf( "display func\n" ); */
glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
if ( glui ) {
glui->display();
/*
Do not do anything after the above line, b/c the GLUI
window might have just closed itself
*/
}
}
/********************************************** glui_reshape_func() ********/
void glui_reshape_func(int w,int h )
{
GLUI *glui;
GLUI_Glut_Window *glut_window;
int current_window;
/*printf( "glui_reshape_func(): %d w/h: %d/%d\n", glutGetWindow(), w, h ); */
current_window = glutGetWindow();
/*** First check if this is main glut window ***/
glut_window = GLUI_Master.find_glut_window( current_window );
if ( glut_window ) {
if (glut_window->glut_reshape_CB) glut_window->glut_reshape_CB(w,h);
/*** Now send reshape events to all subwindows ***/
glui = (GLUI*) GLUI_Master.gluis.first_child();
while(glui) {
if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
glui->parent_window == current_window ) {
glutSetWindow( glui->get_glut_window_id());
glui->reshape(w,h);
/* glui->check_subwindow_position(); */
}
glui = (GLUI*) glui->next();
}
}
else {
/*** A standalone GLUI window ***/
glui = GLUI_Master.find_glui_by_window_id( current_window );
if ( glui ) {
glui->reshape(w,h);
}
}
}
/********************************************** glui_keyboard_func() ********/
void glui_keyboard_func(unsigned char key, int x, int y)
{
GLUI *glui;
int current_window;
GLUI_Glut_Window *glut_window;
current_window = glutGetWindow();
glut_window = GLUI_Master.find_glut_window( current_window );
/*printf( "key: %d\n", current_window ); */
if ( glut_window ) { /** Was event in a GLUT window? **/
if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) {
glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
GLUI_Master.active_control_glui->keyboard(key,x,y);
finish_drawing();
glutSetWindow( current_window );
}
else {
if (glut_window->glut_keyboard_CB)
glut_window->glut_keyboard_CB( key, x, y );
}
}
else { /*** Nope, event was in a standalone GLUI window **/
glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
if ( glui ) {
glui->keyboard(key,x,y);
finish_drawing();
}
}
}
void glui_special_up_func(int key, int x, int y)
{
GLUI *glui;
int current_window;
GLUI_Glut_Window *glut_window;
current_window = glutGetWindow();
glut_window = GLUI_Master.find_glut_window( current_window );
if (glut_window) /** Was event in a GLUT window? **/
{
if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control )
{
glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
GLUI_Master.active_control_glui->special_up(key,x,y);
finish_drawing();
glutSetWindow( current_window );
}
else
{
if (glut_window->glut_special_up_CB)
glut_window->glut_special_up_CB( key, x, y );
}
}
else /*** Nope, event was in a standalone GLUI window **/
{
glui = GLUI_Master.find_glui_by_window_id(glutGetWindow());
if ( glui )
{
glui->special_up(key,x,y);
finish_drawing();
}
}
}
/************************************************ glui_special_func() ********/
void glui_special_func(int key, int x, int y)
{
GLUI *glui;
int current_window;
GLUI_Glut_Window *glut_window;
current_window = glutGetWindow();
glut_window = GLUI_Master.find_glut_window( current_window );
if (glut_window) /** Was event in a GLUT window? **/
{
if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control )
{
glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
GLUI_Master.active_control_glui->special(key,x,y);
finish_drawing();
glutSetWindow( current_window );
}
else
{
if (glut_window->glut_special_CB)
glut_window->glut_special_CB( key, x, y );
}
}
else /*** Nope, event was in a standalone GLUI window **/
{
glui = GLUI_Master.find_glui_by_window_id(glutGetWindow());
if ( glui )
{
glui->special(key,x,y);
finish_drawing();
}
}
}
/********************************************** glui_mouse_func() ********/
void glui_mouse_func(int button, int state, int x, int y)
{
GLUI *glui;
int current_window;
GLUI_Glut_Window *glut_window;
current_window = glutGetWindow();
glut_window = GLUI_Master.find_glut_window( current_window );
if ( glut_window ) { /** Was event in a GLUT window? **/
if ( GLUI_Master.active_control_glui != NULL )
GLUI_Master.active_control_glui->deactivate_current_control();
if (glut_window->glut_mouse_CB)
glut_window->glut_mouse_CB( button, state, x, y );
finish_drawing();
}
else { /** Nope - event was in a GLUI standalone window **/
glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
if ( glui ) {
glui->passive_motion( 0,0 );
glui->mouse( button, state, x, y );
finish_drawing();
}
}
}
/********************************************** glui_motion_func() ********/
void glui_motion_func(int x, int y)
{
GLUI *glui;
glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
if ( glui ) {
glui->motion(x,y);
finish_drawing();
}
}
/**************************************** glui_passive_motion_func() ********/
void glui_passive_motion_func(int x, int y)
{
GLUI *glui;
glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
if ( glui ) {
glui->passive_motion(x,y);
finish_drawing();
}
}
/********************************************** glui_entry_func() ********/
void glui_entry_func(int state)
{
GLUI *glui;
glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
if ( glui ) {
glui->entry(state);
}
}
/******************************************** glui_visibility_func() ********/
void glui_visibility_func(int state)
{
GLUI *glui;
/* printf( "IN GLUI VISIBILITY()\n" ); */
/* fflush( stdout ); */
glui = GLUI_Master.find_glui_by_window_id( glutGetWindow() );
if ( glui ) {
glui->visibility(state);
}
}
/********************************************** glui_idle_func() ********/
/* Send idle event to each glui, then to the main window */
void glui_idle_func(void)
{
GLUI *glui;
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
glui->idle();
finish_drawing();
glui = (GLUI*) glui->next();
}
if ( GLUI_Master.glut_idle_CB ) {
/*** We set the current glut window before calling the user's
idle function, even though glut explicitly says the window id is
undefined in an idle callback. ***/
/** Check what the current window is first ***/
/*** Arbitrarily set the window id to the main gfx window of the
first glui window ***/
/* int current_window, new_window; */
/* current_window = glutGetWindow(); */
/* if (GLUI_Master.gluis.first_child() != NULL ) { */
/* new_window = ((GLUI_Main*)GLUI_Master.gluis.first_child())-> */
/* main_gfx_window_id; */
/* if ( new_window > 0 AND new_window != old_window ) { */
/* --- Window is changed only if its not already the current window ---*/
/* glutSetWindow( new_window ); */
/* } */
/*} */
GLUI_Master.glut_idle_CB();
}
}
/*********************************** GLUI_Master_Object::GLUI_Master_Object() ******/
GLUI_Master_Object::GLUI_Master_Object()
: glui_id_counter(1),
glut_idle_CB(NULL)
{
}
GLUI_Master_Object::~GLUI_Master_Object()
{
}
/*********************************** GLUI_Master_Object::create_glui() ******/
GLUI *GLUI_Master_Object::create_glui( const char *name, long flags,int x,int y )
{
GLUI *new_glui = new GLUI;
new_glui->init( name, flags, x, y, -1 );
new_glui->link_this_to_parent_last( &this->gluis );
return new_glui;
}
/************************** GLUI_Master_Object::create_glui_subwindow() ******/
GLUI *GLUI_Master_Object::create_glui_subwindow( int parent_window,
long flags )
{
GLUI *new_glui = new GLUI;
GLUI_String new_name;
glui_format_str( new_name, "subwin_%p", this );
new_glui->init( new_name.c_str(), flags | GLUI_SUBWINDOW, 0,0,
parent_window );
new_glui->main_panel->set_int_val( GLUI_PANEL_EMBOSSED );
new_glui->link_this_to_parent_last( &this->gluis );
return new_glui;
}
/********************** GLUI_Master_Object::find_glui_by_window_id() ********/
GLUI *GLUI_Master_Object::find_glui_by_window_id( int window_id )
{
GLUI_Node *node;
node = gluis.first_child();
while( node ) {
if ( ((GLUI*)node)->get_glut_window_id() == window_id )
return (GLUI*) node;
node = node->next();
}
return NULL;
}
/******************************************** GLUI_Main::display() **********/
void GLUI_Main::display( void )
{
int win_w, win_h;
/* SUBTLE: on freeGLUT, the correct window is always already set.
But older versions of GLUT need this call, or else subwindows
don't update properly when resizing or damage-painting.
*/
glutSetWindow( glut_window_id );
/* Set up OpenGL state for widget drawing */
glDisable( GL_DEPTH_TEST );
glCullFace( GL_BACK );
glDisable( GL_CULL_FACE );
glDisable( GL_LIGHTING );
set_current_draw_buffer();
/**** This function is used as a special place to do 'safe' processing,
e.g., handling window close requests.
That is, we can't close the window directly in the callback, so
we set a flag, post a redisplay message (which eventually calls
this function), then close the window safely in here. ****/
if ( closing ) {
close_internal();
return;
}
/* if ( TEST_AND( this->flags, GLUI_SUBWINDOW ))
check_subwindow_position();
*/
win_w = glutGet( GLUT_WINDOW_WIDTH );
win_h = glutGet( GLUT_WINDOW_HEIGHT );
/*** Check here if the window needs resizing ***/
if ( win_w != main_panel->w OR win_h != main_panel->h ) {
glutReshapeWindow( main_panel->w, main_panel->h );
return;
}
/******* Draw GLUI window ******/
glClearColor( (float) bkgd_color.r / 255.0,
(float) bkgd_color.g / 255.0,
(float) bkgd_color.b / 255.0,
1.0 );
glClear( GL_COLOR_BUFFER_BIT ); /* | GL_DEPTH_BUFFER_BIT ); */
set_ortho_projection();
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
/*** Rotate image so y increases downward.
In normal OpenGL, y increases upward. ***/
glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
glRotatef( 180.0, 0.0, 1.0, 0.0 );
glRotatef( 180.0, 0.0, 0.0, 1.0 );
glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
// Recursively draw the main panel
// main_panel->draw_bkgd_box( 0, 0, win_w, win_h );
main_panel->draw_recursive( 0, 0 );
switch (buffer_mode) {
case buffer_front: /* Make sure drawing gets to screen */
glFlush();
break;
case buffer_back: /* Bring back buffer to front */
glutSwapBuffers();
break;
}
}
/*************************************** _glutBitmapWidthString() **********/
int _glutBitmapWidthString( void *font, const char *s )
{
const char *p = s;
int width = 0;
while( *p != '\0' ) {
width += glutBitmapWidth( font, *p );
p++;
}
return width;
}
/************************************ _glutBitmapString *********************/
/* Displays the contents of a string using GLUT's bitmap character function */
/* Does not handle newlines */
void _glutBitmapString( void *font, const char *s )
{
const char *p = s;
while( *p != '\0' ) {
glutBitmapCharacter( font, *p );
p++;
}
}
/****************************** GLUI_Main::reshape() **************/
void GLUI_Main::reshape( int reshape_w, int reshape_h )
{
int new_w, new_h;
pack_controls();
new_w = main_panel->w;/* + 1; */
new_h = main_panel->h;/* + 1; */
if ( reshape_w != new_w OR reshape_h != new_h ) {
this->w = new_w;
this->h = new_h;
glutReshapeWindow( new_w, new_h );
}
else {
}
if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
check_subwindow_position();
/***** if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
}
****/
}
glViewport( 0, 0, new_w, new_h );
/* printf( "%d: %d\n", glutGetWindow(), this->flags ); */
glutPostRedisplay();
}
/****************************** GLUI_Main::keyboard() **************/
void GLUI_Main::keyboard(unsigned char key, int x, int y)
{
GLUI_Control *new_control;
curr_modifiers = glutGetModifiers();
/*** If it's a tab or shift tab, we don't pass it on to the controls.
Instead, we use it to cycle through active controls ***/
if ( key == '\t' AND !mouse_button_down AND
(!active_control || !active_control->wants_tabs())) {
if ( curr_modifiers & GLUT_ACTIVE_SHIFT ) {
new_control = find_prev_control( active_control );
}
else {
new_control = find_next_control( active_control );
}
/* if ( new_control )
printf( "new_control: %s\n", new_control->name );
*/
deactivate_current_control();
activate_control( new_control, GLUI_ACTIVATE_TAB );
}
else if ( key == ' ' AND active_control
AND active_control->spacebar_mouse_click ) {
/*** If the user presses the spacebar, and a non-edittext control
is active, we send it a mouse down event followed by a mouse up
event (simulated mouse-click) ***/
active_control->mouse_down_handler( 0, 0 );
active_control->mouse_up_handler( 0, 0, true );
} else {
/*** Pass the keystroke onto the active control, if any ***/
if ( active_control != NULL )
active_control->key_handler( key, curr_modifiers );
}
}
void GLUI_Main::special_up(int key, int x, int y)
{
curr_modifiers = glutGetModifiers();
/*** Pass the keystroke onto the active control, if any ***/
if ( active_control != NULL )
active_control->special_up_handler( key, glutGetModifiers() );
}
/****************************** GLUI_Main::special() **************/
void GLUI_Main::special(int key, int x, int y)
{
curr_modifiers = glutGetModifiers();
/*** Pass the keystroke onto the active control, if any ***/
if ( active_control != NULL )
active_control->special_handler( key, glutGetModifiers() );
}
/****************************** GLUI_Main::mouse() **************/
void GLUI_Main::mouse(int button, int state, int x, int y)
{
int callthrough;
GLUI_Control *control;
/* printf( "MOUSE: %d %d\n", button, state ); */
callthrough = true;
curr_modifiers = glutGetModifiers();
if ( button == GLUT_LEFT ) {
control = find_control( x, y );
/*if ( control ) printf( "control: %s\n", control->name.c_str() ); */
if ( mouse_button_down AND active_control != NULL AND
state == GLUT_UP )
{
/** We just released the mouse, which was depressed at some control **/
callthrough = active_control->
mouse_up_handler( x, y, control==active_control);
glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
if ( active_control AND
active_control->active_type == GLUI_CONTROL_ACTIVE_MOUSEDOWN AND 0)
{
/*** This is a control that needs to be deactivated when the
mouse button is released ****/
deactivate_current_control();
}
}
else {
if ( control ) {
if ( NOT mouse_button_down AND state == GLUT_DOWN ) {
/*** We just pressed the mouse down at some control ***/
if ( active_control != control ) {
if ( active_control != NULL ) {
/** There is an active control still - deactivate it ***/
deactivate_current_control();
}
}
if ( control->enabled ) {
activate_control( control, GLUI_ACTIVATE_MOUSE );
callthrough = control->mouse_down_handler( x, y );
}
}
}
}
if ( state == GLUT_DOWN )
mouse_button_down = true;
else if ( state == GLUT_UP )
mouse_button_down = false;
}
/**
NO CALLTHROUGH NEEDED FOR MOUSE EVENTS
if ( callthrough AND glut_mouse_CB )
glut_mouse_CB( button, state, x, y );
**/
callthrough=callthrough; /* To get rid of compiler warnings */
}
/****************************** GLUI_Main::motion() **************/
void GLUI_Main::motion(int x, int y)
{
int callthrough;
GLUI_Control *control;
/* printf( "MOTION: %d %d\n", x, y ); */
callthrough = true;
control = find_control(x,y);
if ( mouse_button_down AND active_control != NULL ) {
callthrough =
active_control->mouse_held_down_handler(x,y,control==active_control);
}
/**
NO CALLTHROUGH NEEDED FOR MOUSE EVENTS
if ( callthrough AND glut_motion_CB )
glut_motion_CB(x,y);
**/
callthrough=callthrough; /* To get rid of compiler warnings */
}
/*********************** GLUI_Main::passive_motion() **************/
void GLUI_Main::passive_motion(int x, int y)
{
GLUI_Control *control;
control = find_control( x, y );
/* printf( "%p %p\n", control, mouse_over_control ); */
if ( control != mouse_over_control ) {
if ( mouse_over_control ) {
mouse_over_control->mouse_over( false, x, y );
}
if ( control ) {
control->mouse_over( true, x, y );
mouse_over_control = control;
}
}
/*
if ( curr_cursor != GLUT_CURSOR_INHERIT ) {
curr_cursor = GLUT_CURSOR_INHERIT;
glutSetCursor( GLUT_CURSOR_INHERIT );
}*/
}
/****************************** GLUI_Main::entry() **************/
void GLUI_Main::entry(int state)
{
/*if ( NOT active_control OR ( active_control AND ( active_control->type == GLUI_CONTROL_EDITTEXT
OR active_control->type == GLUI_CONTROL_SPINNER) ) )*/
glutSetCursor( GLUT_CURSOR_LEFT_ARROW );
}
/****************************** GLUI_Main::visibility() **************/
void GLUI_Main::visibility(int state)
{
}
/****************************** GLUI_Main::idle() **************/
void GLUI_Main::idle(void)
{
/*** Pass the idle event onto the active control, if any ***/
/* printf( "IDLE \t" ); */
if ( active_control != NULL ) {
/* First we check if the control actually needs the idle right now.
Otherwise, let's avoid wasting cycles and OpenGL context switching */
if ( active_control->needs_idle() ) {
/*** Set the current glut window to the glui window */
/*** But don't change the window if we're already at that window ***/
if ( glut_window_id > 0 AND glutGetWindow() != glut_window_id ) {
glutSetWindow( glut_window_id );
}
active_control->idle();
}
}
}
int GLUI_Main::needs_idle( void )
{
return active_control != NULL && active_control->needs_idle();
}
/******************************************* GLUI_Main::find_control() ******/
GLUI_Control *GLUI_Main::find_control( int x, int y )
{
GLUI_Control *node, *last_container;
last_container = NULL;
node = main_panel;
while( node != NULL ) {
if ( !node->dynamicCastGLUI_Column() AND
PT_IN_BOX( x, y,
node->x_abs, node->x_abs + node->w,
node->y_abs, node->y_abs + node->h )
)
{
/*** Point is inside current node ***/
if ( node->first_child() == NULL ) {
/*** SPECIAL CASE: for edittext boxes, we make sure click is
in box, and not on name string. This should be generalized
for all controls later... ***/
if ( node->dynamicCastGLUI_EditText() ) {
if ( x < node->x_abs + ((GLUI_EditText*)node)->text_x_offset )
return (GLUI_Control*) node->parent();
}
return node; /* point is inside this node, and node has no children,
so return this node as the selected node */
}
else {
/*** This is a container class ***/
last_container = node;
node = (GLUI_Control*) node->first_child(); /* Descend into child */
}
}
else {
node = (GLUI_Control*) node->next();
}
}
/** No leaf-level nodes found to accept the mouse click, so
return the last container control found which DOES accept the click **/
if ( last_container ) {
/* printf( "ctrl: '%s'\n", last_container->name ); */
return last_container;
}
else {
return NULL;
}
}
/************************************* GLUI_Main::pack_controls() ***********/
void GLUI_Main::pack_controls( void )
{
main_panel->pack(0,0);
/**** Now align controls within their bounds ****/
align_controls( main_panel );
/*** If this is a subwindow, expand panel to fit parent window ***/
if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
int parent_h, parent_w;
int orig_window;
orig_window = glutGetWindow();
glutSetWindow( this->top_level_glut_window_id );
parent_h = glutGet( GLUT_WINDOW_HEIGHT );
parent_w = glutGet( GLUT_WINDOW_WIDTH );
glutSetWindow( orig_window );
/* printf( "%d %d\n", parent_h, parent_w ); */
if ( 1 ) {
if ( TEST_AND(this->flags,GLUI_SUBWINDOW_TOP )) {
main_panel->w = MAX( main_panel->w, parent_w );
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
main_panel->h = MAX( main_panel->h, parent_h );
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
main_panel->w = MAX( main_panel->w, parent_w );
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
main_panel->h = MAX( main_panel->h, parent_h );
}
}
}
this->w = main_panel->w;
this->h = main_panel->h;
}
/************************************ GLUI_Main::align_controls() **********/
void GLUI_Main::align_controls( GLUI_Control *control )
{
GLUI_Control *child;
control->align();
child = (GLUI_Control*) control->first_child();
while( child != NULL ) {
align_controls( child );
child = (GLUI_Control*)child->next();
}
}
/*********************************** GLUI::set_main_gfx_window() ************/
void GLUI::set_main_gfx_window( int window_id )
{
main_gfx_window_id = window_id;
}
/********************************* GLUI_Main::post_update_main_gfx() ********/
void GLUI_Main::post_update_main_gfx( void )
{
int old_window;
if ( main_gfx_window_id > 0 ) {
old_window = glutGetWindow();
glutSetWindow( main_gfx_window_id );
glutPostRedisplay();
if( old_window > 0 )
glutSetWindow( old_window );
}
}
/********************************* GLUI_Main::should_redraw_now() ********/
/** Return true if this control should redraw itself immediately (front buffer);
Or queue up a redraw and return false if it shouldn't (back buffer).
Called from GLUI_Control::redraw.
*/
bool GLUI_Main::should_redraw_now(GLUI_Control *ctl)
{
switch (buffer_mode) {
case buffer_front: return true; /* always draw in front-buffer mode */
case buffer_back: {
int orig = ctl->set_to_glut_window();
glutPostRedisplay(); /* redraw soon */
ctl->restore_window(orig);
return false; /* don't draw now. */
}
}
return false; /* never executed */
}
/********************************* GLUI_Main::set_current_draw_buffer() ********/
int GLUI_Main::set_current_draw_buffer( void )
{
/* Save old buffer */
GLint state;
glGetIntegerv( GL_DRAW_BUFFER, &state );
/* Switch to new buffer */
switch (buffer_mode) {
case buffer_front: glDrawBuffer(GL_FRONT); break;
case buffer_back: glDrawBuffer(GL_BACK); break; /* might not be needed... */
}
return (int)state;
}
/********************************* GLUI_Main::restore_draw_buffer() **********/
void GLUI_Main::restore_draw_buffer( int buffer_state )
{
glDrawBuffer( buffer_state );
}
/******************************************** GLUI_Main::GLUI_Main() ********/
GLUI_Main::GLUI_Main( void )
{
mouse_button_down = false;
w = 0;
h = 0;
active_control = NULL;
mouse_over_control = NULL;
main_gfx_window_id = -1;
glut_window_id = -1;
curr_modifiers = 0;
closing = false;
parent_window = -1;
glui_id = GLUI_Master.glui_id_counter;
GLUI_Master.glui_id_counter++;
font = GLUT_BITMAP_HELVETICA_12;
curr_cursor = GLUT_CURSOR_LEFT_ARROW;
int r=200, g=200, b=200;
bkgd_color.set( r,g,b );
bkgd_color_f[0] = r / 255.0;
bkgd_color_f[1] = g / 255.0;
bkgd_color_f[2] = b / 255.0;
/*** Create the main panel ***/
main_panel = new GLUI_Panel;
main_panel->set_int_val( GLUI_PANEL_NONE );
main_panel->glui = (GLUI*) this;
main_panel->name = "\0";
}
/************************************ GLUI_Main::draw_raised_box() **********/
void GLUI_Main::draw_raised_box( int x, int y, int w, int h )
{
w = w+x;
h = h+y;
glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b );
glBegin( GL_LINE_LOOP );
glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 );
glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
glEnd();
glColor3d( 1.0, 1.0, 1.0 );
glBegin( GL_LINE_STRIP );
glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y );
glEnd();
glColor3d( 0.0, 0.0, 0.0 );
glBegin( GL_LINE_STRIP );
glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h );
glEnd();
glColor3d( .5, .5, .5 );
glBegin( GL_LINE_STRIP );
glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
glEnd();
}
/************************************ GLUI_Main::draw_lowered_box() **********/
/* Not quite perfect... **/
void GLUI_Main::draw_lowered_box( int x, int y, int w, int h )
{
w = w+x;
h = h+y;
glColor3ub( bkgd_color.r, bkgd_color.g, bkgd_color.b );
glBegin( GL_LINE_LOOP );
glVertex2i( x+1, y+1 ); glVertex2i( w-1, y+1 );
glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
glEnd();
glColor3d( 0.0, 0.0, 0.0 );
glBegin( GL_LINE_STRIP );
glVertex2i( x, h ); glVertex2i( x, y ); glVertex2i( w, y );
glEnd();
glColor3d( 1.0, 1.0, 1.0 );
glBegin( GL_LINE_STRIP );
glVertex2i( w, y ); glVertex2i( w, h ); glVertex2i( x, h );
glEnd();
glColor3d( .5, .5, .5 );
glBegin( GL_LINE_STRIP );
glVertex2i( w-1, y+1 ); glVertex2i( w-1, h-1 ); glVertex2i( x+1, h-1 );
glEnd();
}
/************************************* GLUI_Main::activate_control() *********/
void GLUI_Main::activate_control( GLUI_Control *control, int how )
{
/** Are we not activating a control in the same window as the
previous active control? */
if ( GLUI_Master.active_control_glui AND
this != (GLUI_Main*) GLUI_Master.active_control_glui ) {
GLUI_Master.active_control_glui->deactivate_current_control();
}
/******* Now activate it *****/
if ( control != NULL AND control->can_activate AND control->enabled ) {
active_control = control;
control->activate(how);
/*if ( NOT active_control->is_container OR */
/* active_control->type == GLUI_CONTROL_ROLLOUT) { */
active_control->redraw();
/*} */
}
else {
active_control = NULL;
}
/* printf( "activate: %d\n", glutGetWindow() ); */
GLUI_Master.active_control = active_control;
GLUI_Master.active_control_glui = (GLUI*) this;
}
/************************* GLUI_Main::deactivate_current_control() **********/
void GLUI_Main::deactivate_current_control( void )
{
int orig;
if ( active_control != NULL ) {
orig = active_control->set_to_glut_window();
active_control->deactivate();
/** If this isn't a container control, then redraw it in its
deactivated state. Container controls, such as panels, look
the same activated or not **/
/*if ( NOT active_control->is_container OR */
/* active_control->type == GLUI_CONTROL_ROLLOUT ) { */
active_control->redraw();
/*} */
active_control->restore_window( orig );
active_control = NULL;
}
/* printf( "deactivate: %d\n", glutGetWindow() ); */
GLUI_Master.active_control = NULL;
GLUI_Master.active_control_glui = NULL;
}
/****************************** GLUI_Main::find_next_control() **************/
GLUI_Control *GLUI_Main::find_next_control_( GLUI_Control *control )
{
/*** THIS IS NOT find_next_control()! This is an unused older
version (look at the underscore at the end) ***/
if ( control == NULL )
return find_next_control_rec( main_panel );
else
return find_next_control_rec( control );
}
/****************************** GLUI_Main::find_next_control() **************/
GLUI_Control *GLUI_Main::find_next_control_rec( GLUI_Control *control )
{
GLUI_Control *child = NULL, *rec_control, *sibling;
/*** Recursively investigate children ***/
child = (GLUI_Control*) control->first_child();
if ( child ) {
/*** If we can activate the first child, then do so ***/
if ( child->can_activate AND child->enabled )
return child;
else /*** Recurse into first child ***/
rec_control = find_next_control_rec( child );
if ( rec_control )
return rec_control;
}
/*** At this point, either we don't have children, or the child cannot
be activated. So let's try the next sibling ***/
sibling = (GLUI_Control*) control->next();
if ( sibling ) {
if ( sibling->can_activate AND sibling->enabled )
return sibling;
else /*** Recurse into sibling ***/
rec_control = find_next_control_rec( sibling );
if ( rec_control )
return rec_control;
}
return NULL;
}
/****************************** GLUI_Main::find_next_control() **************/
GLUI_Control *GLUI_Main::find_next_control( GLUI_Control *control )
{
GLUI_Control *tmp_control = NULL;
int back_up;
if ( control == NULL )
control = main_panel;
while( control != NULL ) {
/** see if this control has a child **/
tmp_control = (GLUI_Control*) control->first_child();
if ( tmp_control != NULL ) {
if ( tmp_control->can_activate AND tmp_control->enabled )
return tmp_control;
control = tmp_control; /* Descend into child */
continue;
}
/*** At this point, control has no children ***/
/** see if this control has a next sibling **/
tmp_control = (GLUI_Control*) control->next();
if ( tmp_control != NULL ) {
if ( tmp_control->can_activate AND tmp_control->enabled )
return tmp_control;
control = tmp_control;
continue;
}
/** back up until we find a sibling of an ancestor **/
back_up = true;
while ( control->parent() AND back_up ) {
control = (GLUI_Control*) control->parent();
if ( control->next() ) {
control = (GLUI_Control*) control->next();
if ( control->can_activate AND control->enabled )
return control;
else
back_up = false;
/*** if ( control->is_container ) {
tmp_control = control;
control = NULL;
break;
}
else {
back_up = false;
}
***/
}
}
/** Check if we've cycled back to the top... if so, return NULL **/
if ( control == main_panel ) {
return NULL;
}
}
/*
if ( tmp_control != NULL AND tmp_control->can_activate AND
tmp_control->enabled ) {
return tmp_control;
}*/
return NULL;
}
/****************************** GLUI_Main::find_prev_control() **************/
GLUI_Control *GLUI_Main::find_prev_control( GLUI_Control *control )
{
GLUI_Control *tmp_control, *next_control;
if ( control == NULL ) { /* here we find the last valid control */
next_control = main_panel;
do {
tmp_control = next_control;
next_control = find_next_control( tmp_control );
} while( next_control != NULL );
return tmp_control;
}
else { /* here we find the actual previous control */
next_control = main_panel;
do {
tmp_control = next_control;
next_control = find_next_control( tmp_control );
} while( next_control != NULL AND next_control != control );
if ( next_control == NULL OR tmp_control == main_panel )
return NULL;
else
return tmp_control;
}
}
/************************* GLUI_Master_Object::set_glutIdleFunc() ***********/
void GLUI_Master_Object::set_glutIdleFunc(void (*f)(void))
{
glut_idle_CB = f;
GLUI_Master.glui_setIdleFuncIfNecessary();
}
/**************************************** GLUI::disable() ********************/
void GLUI::disable( void )
{
deactivate_current_control();
main_panel->disable();
}
/******************************************** GLUI::sync_live() **************/
void GLUI::sync_live( void )
{
main_panel->sync_live(true, true);
}
/********************************* GLUI_Master_Object::sync_live_all() *****/
void GLUI_Master_Object::sync_live_all( void )
{
GLUI *glui;
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
glui->sync_live(); /** sync it **/
glui = (GLUI*) glui->next();
}
}
/************************************* GLUI_Master_Object::close() **********/
void GLUI_Master_Object::close_all( void )
{
GLUI *glui;
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
glui->close(); /** Set flag to close **/
glui = (GLUI*) glui->next();
}
}
/************************************* GLUI_Main::close_internal() **********/
void GLUI_Main::close_internal( void )
{
glutDestroyWindow(glutGetWindow()); /** Close this window **/
this->unlink();
if ( GLUI_Master.active_control_glui == this ) {
GLUI_Master.active_control = NULL;
GLUI_Master.active_control_glui = NULL;
}
if ( parent_window != -1 ) {
glutSetWindow( parent_window );
int win_w = glutGet( GLUT_WINDOW_WIDTH );
int win_h = glutGet( GLUT_WINDOW_HEIGHT );
glutReshapeWindow(win_w+1, win_h);
glutReshapeWindow(win_w-1, win_h);
}
delete this->main_panel;
delete this;
}
/************************************************** GLUI::close() **********/
void GLUI::close( void )
{
int old_glut_window;
closing = true;
old_glut_window = glutGetWindow();
glutSetWindow( get_glut_window_id() );
glutPostRedisplay();
glutSetWindow( old_glut_window );
}
/************************** GLUI_Main::check_subwindow_position() **********/
void GLUI_Main::check_subwindow_position( void )
{
/*** Reposition this window if subwindow ***/
if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
int parent_w, parent_h, new_x, new_y;
int old_window = glutGetWindow();
glutSetWindow( glut_window_id );
glutSetWindow( glutGet( GLUT_WINDOW_PARENT ));
parent_w = glutGet( GLUT_WINDOW_WIDTH );
parent_h = glutGet( GLUT_WINDOW_HEIGHT );
glutSetWindow( glut_window_id );
if ( TEST_AND(this->flags,GLUI_SUBWINDOW_RIGHT )) {
new_x = parent_w - this->w;
new_y = 0;
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_LEFT )) {
new_x = 0;
new_y = 0;
}
else if ( TEST_AND(this->flags,GLUI_SUBWINDOW_BOTTOM )) {
new_x = 0;
new_y = parent_h - this->h;
}
else { /*** GLUI_SUBWINDOW_TOP ***/
new_x = 0;
new_y = 0;
}
/** Now make adjustments based on presence of other subwindows **/
GLUI *curr_glui;
curr_glui = (GLUI*) GLUI_Master.gluis.first_child();
while( curr_glui ) {
if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND
curr_glui->parent_window == this->parent_window ) {
if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
}
else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
}
else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
}
else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) AND
( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) OR
TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) ) ) {
/** If we are a RIGHT or LEFT subwindow, and there exists some
TOP subwindow, bump our position down **/
new_y += curr_glui->h;
}
/** CHeck multiple subwins at same position **/
/** We check the glui_id's: only the glui with the higher
ID number (meaning it was created later) gets bumped over **/
if ( curr_glui != this AND this->glui_id > curr_glui->glui_id ) {
if ( TEST_AND( this->flags,GLUI_SUBWINDOW_LEFT ) AND
TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
new_x += curr_glui->w;
}
else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_TOP ) AND
TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) {
new_y += curr_glui->h;
}
else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_BOTTOM ) AND
TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
new_y -= curr_glui->h;
}
else if ( TEST_AND( this->flags,GLUI_SUBWINDOW_RIGHT ) AND
TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
new_x -= curr_glui->w;
}
}
}
curr_glui = (GLUI*) curr_glui->next();
}
CLAMP( new_x, 0, new_x );
CLAMP( new_y, 0, new_y );
glutPositionWindow( new_x, new_y );
/* glutPostRedisplay(); */
glutSetWindow( old_window );
}
}
/********************************* GLUI_Master_Object::reshape() **********/
/* This gets called by the user from a GLUT reshape callback. So we look */
/* for subwindows that belong to the current window */
void GLUI_Master_Object::reshape( void )
{
GLUI *glui;
int current_window;
current_window = glutGetWindow();
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
glui->parent_window == current_window ) {
glutSetWindow( glui->get_glut_window_id());
glui->check_subwindow_position();
}
glui = (GLUI*) glui->next();
}
glutSetWindow(current_window);
}
/**************************** GLUI_Master_Object::set_glutReshapeFunc() *****/
void GLUI_Master_Object::set_glutReshapeFunc(void (*f)(int width, int height))
{
glutReshapeFunc( glui_reshape_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_RESHAPE, (void*) f);
}
/**************************** GLUI_Master_Object::set_glutKeyboardFunc() ****/
void GLUI_Master_Object::set_glutKeyboardFunc(void (*f)(unsigned char key,
int x, int y))
{
glutKeyboardFunc( glui_keyboard_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_KEYBOARD, (void*) f);
}
/*********************** GLUI_Master_Object::set_glutSpecialFunc() **********/
void GLUI_Master_Object::set_glutSpecialUpFunc(void (*f)(int key,
int x, int y))
{
glutSpecialUpFunc( glui_special_up_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL_UP, (void*) f);
}
void GLUI_Master_Object::set_glutSpecialFunc(void (*f)(int key,
int x, int y))
{
glutSpecialFunc( glui_special_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_SPECIAL, (void*) f);
}
/*********************** GLUI_Master_Object::set_glutMouseFunc() **********/
void GLUI_Master_Object::set_glutMouseFunc(void (*f)(int button, int state,
int x, int y))
{
glutMouseFunc( glui_mouse_func );
add_cb_to_glut_window( glutGetWindow(), GLUI_GLUT_MOUSE, (void*) f);
}
/****************************** glui_parent_window_reshape_func() **********/
/* This is the reshape callback for a window that contains subwindows */
void glui_parent_window_reshape_func( int w, int h )
{
int current_window;
GLUI *glui;
int first = true;
/* printf( "glui_parent_window_reshape_func: %d\n", glutGetWindow() ); */
current_window = glutGetWindow();
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
glui->parent_window == current_window ) {
glutSetWindow( glui->get_glut_window_id());
glui->check_subwindow_position();
glutSetWindow( current_window );
if ( first ) {
if (glui->glut_reshape_CB) glui->glut_reshape_CB( w, h );
first = false;
}
}
glui = (GLUI*) glui->next();
}
}
/****************************** glui_parent_window_keyboard_func() **********/
void glui_parent_window_keyboard_func(unsigned char key, int x, int y)
{
/* printf( "glui_parent_window_keyboard_func: %d\n", glutGetWindow() ); */
int current_window;
GLUI *glui;
current_window = glutGetWindow();
if ( GLUI_Master.active_control_glui AND GLUI_Master.active_control ) {
glutSetWindow( GLUI_Master.active_control_glui->get_glut_window_id() );
GLUI_Master.active_control_glui->keyboard(key,x,y);
glutSetWindow( current_window );
}
else {
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
glui->parent_window == current_window AND
glui->glut_keyboard_CB )
{
glui->glut_keyboard_CB( key, x, y );
break;
}
glui = (GLUI*) glui->next();
}
}
}
/****************************** glui_parent_window_special_func() **********/
void glui_parent_window_special_func(int key, int x, int y)
{
/*printf( "glui_parent_window_special_func: %d\n", glutGetWindow() ); */
int current_window;
GLUI *glui;
/** If clicking in the main area of a window w/subwindows,
deactivate any current control **/
if ( GLUI_Master.active_control_glui != NULL )
GLUI_Master.active_control_glui->deactivate_current_control();
/*** Now pass on the mouse event ***/
current_window = glutGetWindow();
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
glui->parent_window == current_window )
{
glutSetWindow( glui->get_glut_window_id());
if (glui->glut_special_CB) glui->glut_special_CB( key, x, y );
break;
}
glui = (GLUI*) glui->next();
}
}
/****************************** glui_parent_window_mouse_func() **********/
void glui_parent_window_mouse_func(int button, int state, int x, int y)
{
int current_window;
GLUI *glui;
/** If clicking in the main area of a window w/subwindows,
deactivate any current control **/
if ( GLUI_Master.active_control_glui != NULL )
GLUI_Master.active_control_glui->deactivate_current_control();
/*** Now pass on the mouse event ***/
current_window = glutGetWindow();
glui = (GLUI*) GLUI_Master.gluis.first_child();
while( glui ) {
if ( TEST_AND( glui->flags, GLUI_SUBWINDOW) AND
glui->parent_window == current_window AND
glui->glut_mouse_CB)
{
glutSetWindow( glui->get_glut_window_id());
glui->glut_mouse_CB( button, state, x, y );
break;
}
glui = (GLUI*) glui->next();
}
}
/************************** GLUI_Master_Object::find_glut_window() **********/
GLUI_Glut_Window *GLUI_Master_Object::find_glut_window( int window_id )
{
GLUI_Glut_Window *window;
window = (GLUI_Glut_Window*) glut_windows.first_child();
while( window ) {
if ( window->glut_window_id == window_id )
return window;
window = (GLUI_Glut_Window*) window->next();
}
/*** Window not found - return NULL ***/
return NULL;
}
/******************** GLUI_Master_Object::add_cb_to_glut_window() **********/
void GLUI_Master_Object::add_cb_to_glut_window(int window_id,
int cb_type,void *cb)
{
GLUI_Glut_Window *window;
window = find_glut_window( window_id );
if ( NOT window ) {
/*** Allocate new window structure ***/
window = new GLUI_Glut_Window;
window->glut_window_id = window_id;
window->link_this_to_parent_last( (GLUI_Node*) &this->glut_windows );
}
switch( cb_type ) {
case GLUI_GLUT_RESHAPE:
window->glut_reshape_CB = (void(*)(int,int)) cb;
break;
case GLUI_GLUT_DISPLAY:
window->glut_display_CB = (void(*)()) cb;
break;
case GLUI_GLUT_KEYBOARD:
window->glut_keyboard_CB = (void(*)(unsigned char,int,int)) cb;
break;
case GLUI_GLUT_SPECIAL:
window->glut_special_CB = (void(*)(int,int,int)) cb;
break;
case GLUI_GLUT_SPECIAL_UP:
window->glut_special_up_CB = (void(*)(int,int,int)) cb;
break;
case GLUI_GLUT_MOUSE:
window->glut_mouse_CB = (void(*)(int,int,int,int)) cb;
break;
case GLUI_GLUT_MOTION:
window->glut_motion_CB = (void(*)(int,int)) cb;
break;
case GLUI_GLUT_PASSIVE_MOTION:
window->glut_passive_motion_CB = (void(*)(int,int)) cb;
break;
case GLUI_GLUT_ENTRY:
window->glut_entry_CB = (void(*)(int)) cb;
break;
case GLUI_GLUT_VISIBILITY:
window->glut_visibility_CB= (void(*)(int)) cb;
break;
}
}
/************* GLUI_Master_Object::set_left_button_glut_menu_control() *****/
void GLUI_Master_Object::set_left_button_glut_menu_control(
GLUI_Control *control )
{
curr_left_button_glut_menu = control;
}
/******************************* GLUI_Main::set_ortho_projection() **********/
void GLUI_Main::set_ortho_projection( void )
{
int win_h, win_w;
win_w = glutGet( GLUT_WINDOW_WIDTH );
win_h = glutGet( GLUT_WINDOW_HEIGHT );
glMatrixMode( GL_PROJECTION );
glLoadIdentity();
/* gluOrtho2D( 0.0, (float) win_w, 0.0, (float) win_h ); */
glOrtho( 0.0, (float)win_w, 0.0, (float) win_h, -1000.0, 1000.0 );
glMatrixMode( GL_MODELVIEW );
return; /****-----------------------------------------------***/
glMatrixMode( GL_MODELVIEW );
glLoadIdentity();
/*** Rotate image so y increases upwards, contrary to OpenGL axes ***/
glTranslatef( (float) win_w/2.0, (float) win_h/2.0, 0.0 );
glRotatef( 180.0, 0.0, 1.0, 0.0 );
glRotatef( 180.0, 0.0, 0.0, 1.0 );
glTranslatef( (float) -win_w/2.0, (float) -win_h/2.0, 0.0 );
}
/******************************* GLUI_Main::set_viewport() **********/
void GLUI_Main::set_viewport( void )
{
glViewport( 0, 0, main_panel->w, main_panel->h );
}
/****************************** GLUI_Main::refresh() ****************/
void GLUI_Main::refresh( void )
{
int orig;
/****** GLUI_Glut_Window *glut_window;
int current_window;
current_window = glutGetWindow();
glut_window = GLUI_Master.find_glut_window( current_window );
if ( glut_window ) {
glut_window->glut_reshape_CB(w,h);
******/
orig = glutGetWindow();
pack_controls();
if ( glut_window_id > 0 )
glutSetWindow( glut_window_id );
if ( TEST_AND( this->flags, GLUI_SUBWINDOW ) ) {
/*** GLUI subwindow ***/
check_subwindow_position();
}
else {
/*** Standalone GLUI window ***/
glutReshapeWindow( this->h, this->w );
}
glutPostRedisplay();
glutSetWindow( orig);
}
/***************** GLUI_Master_Object::get_main_gfx_viewport() ***********/
void GLUI_Master_Object::get_viewport_area( int *x, int *y,
int *w, int *h )
{
GLUI *curr_glui;
int curr_x, curr_y, curr_w, curr_h;
int curr_window;
curr_window = glutGetWindow();
curr_x = 0;
curr_y = 0;
curr_w = glutGet( GLUT_WINDOW_WIDTH );
curr_h = glutGet( GLUT_WINDOW_HEIGHT );
curr_glui = (GLUI*) gluis.first_child();
while( curr_glui ) {
if ( TEST_AND( curr_glui->flags, GLUI_SUBWINDOW) AND
curr_glui->parent_window == curr_window ) {
/* printf( "%s -> %d %d %d\n", curr_glui->window_name.c_str(), curr_glui->flags,
curr_glui->w, curr_glui->h );*/
if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_LEFT ) ) {
curr_x += curr_glui->w;
curr_w -= curr_glui->w;
}
else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_BOTTOM ) ) {
curr_y += curr_glui->h;
curr_h -= curr_glui->h;
}
else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_RIGHT ) ) {
curr_w -= curr_glui->w;
}
else if ( TEST_AND( curr_glui->flags,GLUI_SUBWINDOW_TOP ) ) {
curr_h -= curr_glui->h;
}
}
curr_glui = (GLUI*) curr_glui->next();
}
curr_x = MAX( 0, curr_x );
curr_y = MAX( 0, curr_y );
curr_w = MAX( 0, curr_w );
curr_h = MAX( 0, curr_h );
*x = curr_x;
*y = curr_y;
*w = curr_w;
*h = curr_h;
}
/*****************GLUI_Master_Object::auto_set_main_gfx_viewport() **********/
void GLUI_Master_Object::auto_set_viewport( void )
{
int x, y, w, h;
get_viewport_area( &x, &y, &w, &h );
glViewport( MAX(x,0), MAX(y,0), MAX(w,0), MAX(h,0) );
}
/***************************************** GLUI::show() **********************/
void GLUI::show( void )
{
int orig_window;
orig_window = main_panel->set_to_glut_window();
glutShowWindow();
main_panel->restore_window(orig_window);
}
/***************************************** GLUI::hide() **********************/
void GLUI::hide( void )
{
int orig_window;
this->deactivate_current_control();
orig_window = main_panel->set_to_glut_window();
glutHideWindow();
main_panel->restore_window(orig_window);
}
/**************** GLUI_DrawingSentinal **************/
GLUI_DrawingSentinal::GLUI_DrawingSentinal(GLUI_Control *c_)
:c(c_)
{
orig_win = c->set_to_glut_window();
orig_buf = c->glui->set_current_draw_buffer();
}
GLUI_DrawingSentinal::~GLUI_DrawingSentinal() {
c->glui->restore_draw_buffer(orig_buf);
c->restore_window(orig_win);
}
void GLUI_Master_Object::glui_setIdleFuncIfNecessary( void )
{
GLUI *glui;
glui = (GLUI*) GLUI_Master.gluis.first_child();
int necessary;
if (this->glut_idle_CB)
necessary = true;
else {
necessary = false;
while( glui ) {
if( glui->needs_idle() ) {
necessary = true;
break;
}
glui = (GLUI*) glui->next();
}
}
if( necessary )
glutIdleFunc( glui_idle_func );
else
glutIdleFunc( NULL );
}