Permalink
Switch branches/tags
Find file Copy path
Fetching contributors…
Cannot retrieve contributors at this time
581 lines (458 sloc) 16.4 KB
/****************************************************************************
GLUI User Interface Toolkit
---------------------------
glui_translation - GLUI_Translation control class
--------------------------------------------------
Copyright (c) 1998 Paul Rademacher
WWW: https://github.com/libglui/glui
Issues: https://github.com/libglui/glui/issues
This software is provided 'as-is', without any express or implied
warranty. In no event will the authors be held liable for any damages
arising from the use of this software.
Permission is granted to anyone to use this software for any purpose,
including commercial applications, and to alter it and redistribute it
freely, subject to the following restrictions:
1. The origin of this software must not be misrepresented; you must not
claim that you wrote the original software. If you use this software
in a product, an acknowledgment in the product documentation would be
appreciated but is not required.
2. Altered source versions must be plainly marked as such, and must not be
misrepresented as being the original software.
3. This notice may not be removed or altered from any source distribution.
*****************************************************************************/
#include "GL/glui.h"
#include "glui_internal.h"
#include "algebra3.h"
#include "tinyformat.h"
#include <algorithm>
/********************** GLUI_Translation::GLUI_Translation() ***/
GLUI_Translation::GLUI_Translation(
GLUI_Node *parent, const GLUI_String &name,
int trans_t, float *value_ptr,
int id, GLUI_CB cb )
{
common_init();
set_ptr_val( value_ptr );
user_id = id;
set_name( name );
callback = cb;
parent->add_control( this );
//init_live();
trans_type = trans_t;
if ( trans_type == GLUI_TRANSLATION_XY ) {
float_array_size = 2;
}
else if ( trans_type == GLUI_TRANSLATION_X ) {
float_array_size = 1;
}
else if ( trans_type == GLUI_TRANSLATION_Y ) {
float_array_size = 1;
}
else if ( trans_type == GLUI_TRANSLATION_Z ) {
float_array_size = 1;
}
init_live();
}
void GLUI_Translation::common_init()
{
locked = GLUI_TRANSLATION_LOCK_NONE;
name = tfm::format("Translation: %p", this);
w = GLUI_MOUSE_INTERACTION_WIDTH;
h = GLUI_MOUSE_INTERACTION_HEIGHT;
can_activate = true;
live_type = GLUI_LIVE_FLOAT_ARRAY;
float_array_size = 0;
alignment = GLUI_ALIGN_CENTER;
trans_type = GLUI_TRANSLATION_XY;
scale_factor = 1.0;
quadObj = NULL;
trans_mouse_code = GLUI_TRANSLATION_MOUSE_NONE;
}
/********************** GLUI_Translation::iaction_mouse_down_handler() ***/
/* These are really in local coords (5/10/99) */
int GLUI_Translation::iaction_mouse_down_handler( int local_x,
int local_y )
{
int center_x, center_y;
down_x = local_x;
down_y = local_y;
if ( trans_type == GLUI_TRANSLATION_XY ) {
orig_x = float_array_val[0];
orig_y = float_array_val[1];
/** Check if the Alt key is down, which means lock to an axis **/
center_x = w/2;
center_y = (h-18)/2;
if ( glui->curr_modifiers & GLUT_ACTIVE_ALT ) {
if ( ABS(local_y-center_y) > ABS(local_x-center_x) ) {
locked = GLUI_TRANSLATION_LOCK_Y;
glutSetCursor( GLUT_CURSOR_UP_DOWN );
}
else {
locked = GLUI_TRANSLATION_LOCK_X;
glutSetCursor( GLUT_CURSOR_LEFT_RIGHT );
}
}
else {
locked = GLUI_TRANSLATION_LOCK_NONE;
glutSetCursor( GLUT_CURSOR_SPRAY );
}
}
else if ( trans_type == GLUI_TRANSLATION_X ) {
glutSetCursor( GLUT_CURSOR_LEFT_RIGHT );
orig_x = float_array_val[0];
}
else if ( trans_type == GLUI_TRANSLATION_Y ) {
glutSetCursor( GLUT_CURSOR_UP_DOWN );
orig_y = float_array_val[0];
}
else if ( trans_type == GLUI_TRANSLATION_Z ) {
glutSetCursor( GLUT_CURSOR_UP_DOWN );
orig_z = float_array_val[0];
}
trans_mouse_code = 1;
redraw();
return false;
}
/*********************** GLUI_Translation::iaction_mouse_up_handler() **********/
int GLUI_Translation::iaction_mouse_up_handler( int local_x, int local_y,
bool inside )
{
trans_mouse_code = GLUI_TRANSLATION_MOUSE_NONE;
locked = GLUI_TRANSLATION_LOCK_NONE;
redraw();
return false;
}
/******************* GLUI_Translation::iaction_mouse_held_down_handler() ******/
int GLUI_Translation::iaction_mouse_held_down_handler( int local_x, int local_y,
bool inside)
{
float x_off, y_off;
float off_array[2];
x_off = scale_factor * (float)(local_x - down_x);
y_off = -scale_factor * (float)(local_y - down_y);
if ( glui->curr_modifiers & GLUT_ACTIVE_SHIFT ) {
x_off *= 100.0f;
y_off *= 100.0f;
}
else if ( glui->curr_modifiers & GLUT_ACTIVE_CTRL ) {
x_off *= .01f;
y_off *= .01f;
}
if ( trans_type == GLUI_TRANSLATION_XY ) {
if ( locked == GLUI_TRANSLATION_LOCK_X )
y_off = 0.0;
else if ( locked == GLUI_TRANSLATION_LOCK_Y )
x_off = 0.0;
off_array[0] = x_off + orig_x;
off_array[1] = y_off + orig_y;
}
else if ( trans_type == GLUI_TRANSLATION_X ) {
off_array[0] = x_off + orig_x;
}
else if ( trans_type == GLUI_TRANSLATION_Y ) {
off_array[0] = y_off + orig_y;
}
else if ( trans_type == GLUI_TRANSLATION_Z ) {
off_array[0] = y_off + orig_z;
}
set_float_array_val( (float*) &off_array[0] );
return false;
}
/******************** GLUI_Translation::iaction_draw_active_area_persp() **************/
void GLUI_Translation::iaction_draw_active_area_persp()
{
}
/******************** GLUI_Translation::iaction_draw_active_area_ortho() **********/
void GLUI_Translation::iaction_draw_active_area_ortho()
{
/********* Draw emboss circles around arcball control *********/
float radius;
radius = (float)(h-22)/2.0; /* MIN((float)w/2.0, (float)h/2.0); */
glLineWidth( 1.0 );
draw_emboss_box( (int) -radius-2, (int)radius+2,
(int)-radius-2, (int)radius+2 );
glMatrixMode( GL_MODELVIEW );
glPushMatrix();
glTranslatef( .5, .5, .5 );
/* glScalef( radius-1.0, radius-1.0, radius-1.0 ); */
if ( trans_type == GLUI_TRANSLATION_Z )
draw_2d_z_arrows((int)radius-1);
else if ( trans_type == GLUI_TRANSLATION_XY )
draw_2d_xy_arrows((int)radius-1);
else if ( trans_type == GLUI_TRANSLATION_X )
draw_2d_x_arrows((int)radius-1);
else if ( trans_type == GLUI_TRANSLATION_Y )
draw_2d_y_arrows((int)radius-1);
glPopMatrix();
}
/******************************** GLUI_Translation::iaction_dump() **********/
void GLUI_Translation::iaction_dump( FILE *output )
{
}
/******************** GLUI_Translation::iaction_special_handler() **********/
int GLUI_Translation::iaction_special_handler( int key,int modifiers )
{
return false;
}
/*************************** GLUI_Translation::draw_2d_z_arrows() **************/
void GLUI_Translation::draw_2d_z_arrows( int radius )
{
if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
draw_2d_arrow(radius, true, 2);
draw_2d_arrow(radius, true, 0);
}
else {
draw_2d_arrow(radius, false, 2);
draw_2d_arrow(radius, false, 0);
}
}
/*************************** GLUI_Translation::draw_2d_x_arrows() **************/
void GLUI_Translation::draw_2d_x_arrows( int radius )
{
if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
draw_2d_arrow(radius, true, 1);
draw_2d_arrow(radius, true, 3);
}
else {
draw_2d_arrow(radius, false, 1);
draw_2d_arrow(radius, false, 3);
}
}
/*************************** GLUI_Translation::draw_2d_y_arrows() **************/
void GLUI_Translation::draw_2d_y_arrows( int radius )
{
if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
draw_2d_arrow(radius, true, 0);
draw_2d_arrow(radius, true, 2);
}
else {
draw_2d_arrow(radius, false, 0);
draw_2d_arrow(radius, false, 2);
}
}
/************************** GLUI_Translation::draw_2d_xy_arrows() **************/
void GLUI_Translation::draw_2d_xy_arrows( int radius)
{
if ( trans_mouse_code != GLUI_TRANSLATION_MOUSE_NONE ) {
if ( locked == GLUI_TRANSLATION_LOCK_X ) {
draw_2d_arrow(radius, false, 0);
draw_2d_arrow(radius, false, 2);
draw_2d_arrow(radius, true, 1);
draw_2d_arrow(radius, true, 3);
}
else if ( locked == GLUI_TRANSLATION_LOCK_Y ) {
draw_2d_arrow(radius, false, 1);
draw_2d_arrow(radius, false, 3);
draw_2d_arrow(radius, true, 0);
draw_2d_arrow(radius, true, 2);
}
else {
draw_2d_arrow(radius, true, 0);
draw_2d_arrow(radius, true, 1);
draw_2d_arrow(radius, true, 2);
draw_2d_arrow(radius, true, 3);
}
}
else {
draw_2d_arrow(radius, false, 0);
draw_2d_arrow(radius, false, 1);
draw_2d_arrow(radius, false, 2);
draw_2d_arrow(radius, false, 3);
}
return;
}
/*************************** GLUI_Translation::draw_2d_arrow() **************/
/* ori: 0=up, 1=left, 2=down, 3=right */
/* */
/* */
/* 0, y2 */
/* / \ */
/* / \ */
/* / \ */
/* / \ */
/* / \ */
/* / \ */
/* / \ */
/* / \ */
/* -x2,y1 -x1b,y1 x1b,y1 x2,y1 */
/* | | */
/* | | */
/* | | */
/* | | */
/* | | */
/* -x1a,y0 x1a,y0 */
/* */
void GLUI_Translation::draw_2d_arrow( int radius, int filled, int orientation )
{
float x1 = .2, x2 = .4, y1 = .54, y2 = .94, y0;
float x1a, x1b;
/*
vec3 col1( 0.0, 0.0, 0.0 ), col2( .45, .45, .45 ),
col3( .7, .7, .7 ), col4( 1.0, 1.0, 1.0 );
vec3 c1, c2, c3, c4, c5, c6;
*/
vec3 white(1.0,1.0,1.0), black(0.0,0.0,0.0), gray(.45,.45,.45),
bkgd(.7,.7,.7);
int c_off=0; /* color index offset */
if ( glui )
bkgd.set(glui->bkgd_color_f[0],
glui->bkgd_color_f[1],
glui->bkgd_color_f[2]);
/* bkgd[0] = 255.0; bkgd[1] = 0; */
/** The following 8 colors define the shading of an octagon, in
clockwise order, starting from the upstroke on the left **/
/** This is for an outside and inside octagons **/
vec3 colors_out[]={white, white, white, gray, black, black, black, gray};
vec3 colors_in[] ={bkgd,white,bkgd,gray,gray,gray,gray,gray};
#define SET_COL_OUT(i) glColor3fv((float*) &colors_out[(i)%8][0]);
#define SET_COL_IN(i) glColor3fv((float*) &colors_in[(i)%8][0]);
x1 = (float)radius * .2;
x2 = x1 * 2;
y1 = (float)radius * .54;
y2 = y1 + x2;
x1a = x1;
x1b = x1;
glMatrixMode(GL_MODELVIEW);
glPushMatrix();
#define DRAW_SEG( xa,ya,xb,yb ) glVertex2f(xa,ya); glVertex2f(xb,yb);
glScalef( -1.0, 1.0, 1.0 );
if ( orientation == 2 ) {
c_off = 4;
}
else if ( orientation == 0 ) {
c_off = 0;
glRotatef( 180.0, 0.0, 0.0, 1.0 );
}
else if ( orientation == 1 ) {
c_off = 2;
glRotatef( 90.0, 0.0, 0.0, 1.0 );
}
else if ( orientation == 3 ) {
c_off = 6;
glRotatef( -90.0, 0.0, 0.0, 1.0 );
}
if ( trans_type == GLUI_TRANSLATION_Z )
y0 = 0.0;
else if ( trans_type == GLUI_TRANSLATION_XY )
y0 = x1;
else
y0 = 0.0;
if ( trans_type == GLUI_TRANSLATION_Z ) {
if ( orientation == 0 ) {
y1 += 2.0;
y2 += 0.0;
x1b -= 2.0;
x2 -= 2.0;
x1a += 2.0;
}
else if ( orientation == 2 ) {
y1 -= 6.0;
x1a += 2.0;
x1b += 4.0;
x2 += 6.0;
}
}
/*** Fill in inside of arrow ***/
if ( NOT filled ) { /*** Means button is up - control is not clicked ***/
/*glColor3f( .8, .8, .8 ); */
set_to_bkgd_color();
glColor3f( bkgd[0]+.07, bkgd[1]+.07, bkgd[2]+.07 );
}
else { /*** Button is down on control ***/
glColor3f( .6, .6, .6 );
c_off += 4; /* Indents the shadows - goes from a raised look to embossed */
}
/*** Check if control is enabled or not ***/
if ( NOT enabled ) {
set_to_bkgd_color();
/*c_off += 4; -- Indents the shadows - goes from a raised look to embossed */
colors_out[0] = colors_out[1] = colors_out[2] = colors_out[7] = gray;
colors_out[3] = colors_out[4] = colors_out[5] = colors_out[6] = white;
colors_in[0] = colors_in[1] = colors_in[2] = colors_in[7] = white;
colors_in[3] = colors_in[4] = colors_in[5] = colors_in[6] = gray;
}
glBegin( GL_POLYGON );
glVertex2f( 0.0, 0.0 ); glVertex2f( -x1a, 0.0 );
glVertex2f( -x1a, 0.0 ); glVertex2f( -x1b, y1 );
glVertex2f( x1b, y1); glVertex2f( x1a, 0.0 );
glVertex2f( x1a, 0.0 ); glVertex2f( 0.0, 0.0 );
glEnd();
glBegin( GL_TRIANGLES );
glVertex2f( -x2, y1 ); glVertex2f( 0.0, y2 ); glVertex2f( x2, y1 );
glEnd();
glLineWidth( 1.0 );
/*** Draw arrow outline ***/
glBegin( GL_LINES );
SET_COL_IN(1+c_off); DRAW_SEG( 0.0, y2-1.0, -x2, y1-1.0 );
SET_COL_IN(6+c_off); DRAW_SEG( -x2+2.0, y1+1.0, -x1b+1.0, y1+1.0 );
SET_COL_IN(0+c_off); DRAW_SEG( -x1b+1.0, y1+1.0, -x1a+1.0, y0 );
SET_COL_IN(3+c_off); DRAW_SEG( 0.0, y2-1.0, x2, y1-1.0 );
SET_COL_IN(6+c_off); DRAW_SEG( x2-1.0, y1+1.0, x1b-1.0, y1+1.0 );
SET_COL_IN(4+c_off); DRAW_SEG( x1b-1.0, y1+1.0, x1a-1.0, y0 );
SET_COL_OUT(0+c_off); DRAW_SEG( -x1a, y0, -x1b, y1 );
SET_COL_OUT(6+c_off); DRAW_SEG( -x1b, y1, -x2, y1 );
SET_COL_OUT(1+c_off); DRAW_SEG( -x2, y1, 0.0, y2 );
SET_COL_OUT(3+c_off); DRAW_SEG( 0.0, y2, x2, y1 );
SET_COL_OUT(6+c_off); DRAW_SEG( x2, y1, x1b, y1 );
SET_COL_OUT(4+c_off); DRAW_SEG( x1b, y1, x1a, y0 );
glEnd();
#undef DRAW_SEG
glPopMatrix();
}
/*************************** GLUI_Translation::get_mouse_code() *************/
int GLUI_Translation::get_mouse_code( int x, int y )
{
if ( x == 0 AND y < 0 )
return GLUI_TRANSLATION_MOUSE_DOWN;
else if ( x == 0 AND y > 0 )
return GLUI_TRANSLATION_MOUSE_UP;
else if ( x > 0 AND y == 0 )
return GLUI_TRANSLATION_MOUSE_LEFT;
else if ( x < 0 AND y == 0 )
return GLUI_TRANSLATION_MOUSE_RIGHT;
else if ( x < 0 AND y < 0 )
return GLUI_TRANSLATION_MOUSE_DOWN_LEFT;
else if ( x < 0 AND y > 0 )
return GLUI_TRANSLATION_MOUSE_DOWN_RIGHT;
else if ( x > 0 AND y < 0 )
return GLUI_TRANSLATION_MOUSE_UP_LEFT;
else if ( x > 0 AND y > 0 )
return GLUI_TRANSLATION_MOUSE_UP_RIGHT;
return GLUI_TRANSLATION_MOUSE_NONE;
}
/*********************************** GLUI_Translation::set_x() ******/
void GLUI_Translation::set_x( float val )
{
set_one_val( val, 0 );
}
/*********************************** GLUI_Translation::set_y() ******/
void GLUI_Translation::set_y( float val )
{
if ( trans_type == GLUI_TRANSLATION_XY )
set_one_val( val, 1 );
else
set_one_val( val, 0 );
}
/*********************************** GLUI_Translation::set_z() ******/
void GLUI_Translation::set_z( float val )
{
set_one_val( val, 0 );
}
/******************************* GLUI_Translation::set_one_val() ****/
void GLUI_Translation::set_one_val( float val, int index )
{
float *fp;
float_array_val[index] = val; /* set value in array */
/*** The code below is like output_live, except it only operates on
a single member of the float array (given by 'index') instead of
outputting the entire array ****/
if ( ptr_val == NULL OR NOT live_inited )
return;
fp = (float*) ptr_val;
fp[index] = float_array_val[index];
last_live_float_array[index] = float_array_val[index];
/** Update the main gfx window? **/
if ( this->glui != NULL ) {
this->glui->post_update_main_gfx();
}
}