Re: [Plib-users] (cory vs. pui) The attack of setValuator
Brought to you by:
sjbaker
|
From: cory b. <co...@gm...> - 2008-06-12 20:53:18
|
Here is the code:
//#include <memory.h>
#include <stdio.h>
#include <sstream>
#include <simgear/compiler.h>
#include <GL/glut.h>
//#include SG_GLUT_H
#include <plib/fnt.h>
#include <plib/pu.h>
#include <string>
#include <simgear/io/sg_socket.hxx>
#include <simgear/io/sg_serial.hxx>
#include <simgear/io/sg_file.hxx>
#include "SSAircraft.hxx"
#include "SSPid.hxx"
using namespace std;
//defines
#define DECIMALS 6
#define KEY_ESCAPE 27
#define GAIN_MIN -1 //gain values for sliders MIN should be 0 or less
#define GAIN_MAX 1
#define DEG_MIN -180 //target value limiters
#define DEG_MAX 180
//pui gui constants
#define WINDOW_X 360 //window width
#define WINDOW_Y 300 //window height
#define PUI_X_OFFSET 0
#define PUI_Y_OFFSET 0
#define PUI_CTRL_X_OFFSET PUI_BUTTON_WIDTH + PUI_X_GAP * 2
#define PUI_CTRL_WIDTH PUI_ARROW_WIDTH * 2 + PUI_TEXT_WIDTH + PUI_X_GAP * 2
#define PUI_LABEL_X_OFFSET
#define PUI_X_GAP 10
#define PUI_Y_GAP 20
#define PUI_TEXT_WIDTH 80
#define PUI_TEXT_HEIGHT 30
#define PUI_ARROW_WIDTH 30
#define PUI_ARROW_HEIGHT 30
#define PUI_BUTTON_WIDTH 120
#define PUI_BUTTON_HEIGHT 30
#define PUI_RADIO_WIDTH 100
#define PUI_RADIO_HEIGHT 60
//global items
//objects
SGIOChannel *in_channel, *out_channel, *log_file;
SSAircraft *sim_craft = new SSAircraft();
SSPid *aileron_pid = new SSPid();
SSPid *elevator_pid = new SSPid();
//vars
bool logging = false;
bool pauseSoftSim = true;
char inport[ 256 ] = "5500";
char outport[ 256 ] = "5501";
int sock;
float update = 1.0f;
char out_file[ 1024 ] = "sLog.csv";
char save_buf[ 2 * 2048 ];
int save_len = 0;
//pui widgets from PLIB library
puFrame *gui_frame;
//radio buttons
char *controller_selector_labels[] = { "Roll", "Pitch", NULL };
puButtonBox *controller_selector;
//plain old buttons
puButton *pause_button, *log_button;
//arrow buttons for adjusting control values
puArrowButton *kp_arrow_l, *kp_arrow_r,
*ki_arrow_l, *ki_arrow_r,
*kd_arrow_l, *kd_arrow_r,
*target_arrow_l, *target_arrow_r;
//text input boxes
puInput *kp_text, *ki_text, *kd_text, *target_text, *hertz_text;
char *valid_input = "-.0123456789"; //valid input mask for text boxes
char kp_str[ PUSTRING_MAX ],
ki_str[ PUSTRING_MAX ],
kd_str[ PUSTRING_MAX ],
target_str[ PUSTRING_MAX ];
//labels
puText *roll_err_label, *pitch_err_label, *udp_label;
char roll_text[ PUSTRING_MAX ], pitch_text[ PUSTRING_MAX ];
//function prototypes
void timer( int value );
bool parse_fgear_data( char *buf );
void redrawWindow( void );
void reshapeWindow( int w, int h );
string command_output( void );
void processNormalKeys( unsigned char key, int x, int y );
void init_pui_widgets( void );
void pui_callback( puObject *pob );
void gui_update( SSPid *pid );
void processMousefn ( int button, int updown, int x, int y );
void processMotionfn ( int x, int y );
int main( int argc, char **argv ) {
//glut setup
glutInit( &argc, argv );
glutInitDisplayMode( GLUT_DEPTH | GLUT_DOUBLE | GLUT_RGB );
glutInitWindowPosition( 100, 100 );
glutInitWindowSize( WINDOW_X, WINDOW_Y );
glutCreateWindow( "SoftSim" );
glutDisplayFunc( redrawWindow );
glutReshapeFunc( reshapeWindow );
glutIdleFunc( redrawWindow );
glutMouseFunc ( processMousefn ); // process mouse clicks
glutMotionFunc ( processMotionfn ); // process mouse moves
glutPassiveMotionFunc ( processMotionfn );
glutKeyboardFunc( processNormalKeys );
glEnable( GL_DEPTH_TEST ); // enable depth testing
//this takes care of timing for the program
glutTimerFunc( ( int )( 1000.0f/update ), timer, 0 );
//set up networking
in_channel = new SGSocket( "", inport, "udp" );
out_channel = new SGSocket( "", outport, "udp" );
in_channel->open( SG_IO_IN );
out_channel->open( SG_IO_OUT );
//set up logging
string f_name = out_file;
log_file = new SGFile( f_name );
log_file->open( SG_IO_OUT );
//initialize PID controllers
//the gains are some that work ok with the default plane
aileron_pid->set_gains( 0.06, 0.004, -0.04 );
aileron_pid->set_reference( 0 );
aileron_pid->set_limits( -1, 1 );
elevator_pid->set_gains( -0.05, -0.001, 0 );
elevator_pid->set_reference( 0 );
elevator_pid->set_limits( -1, 1 );
//setup all the buttons and gui stuff
init_pui_widgets();
//start glut
glutMainLoop();
//clean up
in_channel->close();
out_channel->close();
log_file->close();
return 0;
}
void timer( int value ) {
char buffer[ 512 ];
size_t found;
string log_str; //string to log to file
int length;
//do if not paused
if ( !pauseSoftSim ){
//read incoming data
while ( ( length = in_channel->readline( buffer, 512 ) ) > 0 ) {
parse_fgear_data( buffer );
if ( logging ) {
//prepare log string
log_str = buffer;
//find \n char and replace with comma
found=log_str.find( '\n' );
if ( found!=string::npos ) {
log_str.replace( found, 1, "," );
}
}
}
string command_str = command_output();
//send outgoing data
out_channel->write( command_str.c_str(), command_str.size() );
//log to file
if ( logging ) {
//don't log if no data from udp
if ( log_str.length () > 0 ) {
log_str.append( command_str );
log_file->writestring( log_str.c_str() );
//cout << command_str.c_str() << endl;
//cout << log_str << endl;
}
}
//make some updates
system( "clear" ); //this is not portable. I should probably
//be using the ncurses library
cout.precision( DECIMALS );
cout << "Roll error: " << aileron_pid->get_error() << endl;
cout << "Pitch error: " << elevator_pid->get_error() << endl;
}
glutTimerFunc( ( int )( 1000.0f/update ), timer, value );
}
//parse incoming data from flight gear
bool parse_fgear_data( char *buf )
{
//variables
//control
double aileron, elevator, rudder, throttle;
//position
double latitudeDegree, longitudeDegree, altitude;
//attitude
double headingDegree, rollDegree, pitchDegree, sideSlip;
//speed / accel
double airspeed, verticalSpd, xAccel, yAccel, zAccel;
//printf("%s\n", buf);
string msg = buf;
string::size_type begin, end;
begin = 0;
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
//aileron
aileron = atof( msg.substr( begin, end ).c_str() );
begin = end + 1;
//elevator
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
elevator = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//rudder
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
rudder = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//throttle
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
throttle = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//latitude
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
latitudeDegree = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//longitude
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
longitudeDegree = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//altitude
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
altitude = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//roll
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
rollDegree = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//pitch
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
pitchDegree = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//heading
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
headingDegree = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//side slip
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
sideSlip = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//airspeed
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
airspeed = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//vertical speed
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
verticalSpd = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//x accel
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
xAccel = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//y accel
end = msg.find( ",", begin );
if ( end == string::npos ) {
return false;
}
yAccel = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//z accel
end = msg.find( "\n", begin );
if ( end == string::npos ) {
return false;
}
zAccel = atof( msg.substr( begin, end - begin ).c_str() );
begin = end + 1;
//set aircraft values
sim_craft->set_aileron( aileron );
sim_craft->set_elevator( elevator );
sim_craft->set_rudder( rudder );
sim_craft->set_throttle( throttle );
sim_craft->set_latitude( latitudeDegree );
sim_craft->set_longitude( longitudeDegree );
sim_craft->set_altitude( altitude );
sim_craft->set_roll( rollDegree );
sim_craft->set_pitch( pitchDegree );
sim_craft->set_heading( headingDegree );
sim_craft->set_sideslip( sideSlip );
sim_craft->set_airspeed( airspeed );
sim_craft->set_vert_speed( verticalSpd );
sim_craft->set_xaccel( xAccel );
sim_craft->set_yaccel( yAccel );
sim_craft->set_zaccel( zAccel );
return true;
}
string command_output( void ) {
stringstream s;
s.precision( DECIMALS );
s << aileron_pid->update( sim_craft->get_roll() ) << ","
<< elevator_pid->update( sim_craft->get_pitch() ) << endl;
/*
s << sim_craft->get_aileron() << ","
<< sim_craft->get_elevator() << ","
<< sim_craft->get_rudder() << ","
<< sim_craft->get_throttle() << endl;
*/
//cout << s.str() << endl;
return s.str();
}
void redrawWindow( void ) {
puDisplay();
glutSwapBuffers();
glutPostRedisplay();
}
void reshapeWindow( int w, int h ) {
//I am trying to preven window resizing, but this doesn't seem to work
glutReshapeWindow( WINDOW_X, WINDOW_Y ); //set window back to initial size
}
void processMousefn ( int button, int updown, int x, int y ) {
// Invoke the PUI mouse function
puMouse ( button, updown, x, y ) ;
glutPostRedisplay () ;
}
void processMotionfn ( int x, int y ){
// Invoke the PUI mouse motion function
puMouse ( x, y ) ;
glutPostRedisplay () ;
}
void processNormalKeys(unsigned char key, int x, int y) {
// Invoke the PUI keyboard function
puKeyboard ( key, PU_DOWN ) ;
glutPostRedisplay() ;
}
/**********************************************************************
* Initialize pui controls
*********************************************************************/
void init_pui_widgets( void ) {
int curx = PUI_X_GAP * 4 + PUI_ARROW_WIDTH * 2 + PUI_TEXT_WIDTH;
int cury = PUI_RADIO_HEIGHT + PUI_Y_GAP * 2;
puInit();
gui_frame = new puFrame( PUI_X_OFFSET,
PUI_Y_OFFSET,
PUI_X_OFFSET + WINDOW_X,
PUI_Y_OFFSET + WINDOW_Y );
//log button
log_button = new puButton( curx, cury, "Log: sLog.csv");
log_button->setSize( PUI_BUTTON_WIDTH, PUI_BUTTON_HEIGHT );
log_button->setValue( 0 ); //logging off by default
log_button->setCallback( pui_callback );
cury += PUI_Y_GAP + PUI_BUTTON_HEIGHT;
//pause button
pause_button = new puButton( curx, cury, "Pause" );
pause_button->setSize( PUI_BUTTON_WIDTH, PUI_BUTTON_HEIGHT );
pause_button->setValue( 1 ); //pause by default
pause_button->setCallback( pui_callback );
curx = PUI_X_GAP;
cury = PUI_Y_GAP;
//radio buttons
controller_selector = new puButtonBox ( curx, cury,
curx + PUI_RADIO_WIDTH,
cury + PUI_RADIO_HEIGHT,
controller_selector_labels, 1 ); //value corresponds to index
of item in labels array
controller_selector->setCallback( pui_callback );
cury += PUI_RADIO_HEIGHT + PUI_Y_GAP;
//kd items
kd_arrow_l = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_LEFT );
kd_arrow_l->setCallback( pui_callback );
curx += PUI_ARROW_WIDTH + PUI_X_GAP;
//kd_text
kd_text = new puInput ( curx, cury,
curx + PUI_TEXT_WIDTH,
cury + PUI_TEXT_HEIGHT ) ;
kd_text->setValidData( valid_input );
sprintf( kd_str, "%.3f", aileron_pid->get_kd() ); //format label
kd_text->setValue( kd_str ); //set value to aileron gains since roll
is selected by default
kd_text->setLabel( "Kd" );
kd_text->setLabelPlace( PUPLACE_TOP_CENTERED );
kd_text->setCallback( pui_callback );
curx += PUI_TEXT_WIDTH + PUI_X_GAP;
kd_arrow_r = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_RIGHT );
kd_arrow_r->setCallback( pui_callback );
curx = PUI_X_GAP;
cury += PUI_ARROW_HEIGHT + PUI_Y_GAP;
//ki items
ki_arrow_l = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_LEFT );
ki_arrow_l->setCallback( pui_callback );
curx += PUI_ARROW_WIDTH + PUI_X_GAP;
//ki_text
ki_text = new puInput ( curx, cury,
curx + PUI_TEXT_WIDTH,
cury + PUI_TEXT_HEIGHT ) ;
ki_text->setValidData( valid_input );
sprintf( ki_str, "%.3f", aileron_pid->get_ki() ); //format label
ki_text->setValue( ki_str ); //set value to aileron gains since roll
is selected by default
ki_text->setLabel( "Ki" );
ki_text->setLabelPlace( PUPLACE_TOP_CENTERED );
ki_text->setCallback( pui_callback );
curx += PUI_TEXT_WIDTH + PUI_X_GAP;
ki_arrow_r = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_RIGHT );
ki_arrow_r->setCallback( pui_callback );
curx = PUI_X_GAP;
cury += PUI_ARROW_HEIGHT + PUI_Y_GAP;
//kp items
kp_arrow_l = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_LEFT );
kp_arrow_l->setCallback( pui_callback );
curx += PUI_ARROW_WIDTH + PUI_X_GAP;
//kp_text
kp_text = new puInput ( curx, cury,
curx + PUI_TEXT_WIDTH,
cury + PUI_TEXT_HEIGHT ) ;
kp_text->setValidData( valid_input );
sprintf( kp_str, "%.3f", aileron_pid->get_kp() ); //format label
kp_text->setValue( kp_str ); //set value to aileron gains since roll
is selected by default
kp_text->setLabel( "Kp" );
kp_text->setLabelPlace( PUPLACE_TOP_CENTERED );
kp_text->setCallback( pui_callback );
curx += PUI_TEXT_WIDTH + PUI_X_GAP;
kp_arrow_r = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_RIGHT );
kp_arrow_r->setCallback( pui_callback );
curx = PUI_X_GAP;
cury += PUI_ARROW_HEIGHT + PUI_Y_GAP;
//target items
target_arrow_l = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_LEFT );
target_arrow_l->setCallback( pui_callback );
curx += PUI_ARROW_WIDTH + PUI_X_GAP;
//target_text
target_text = new puInput ( curx, cury,
curx + PUI_TEXT_WIDTH,
cury + PUI_TEXT_HEIGHT ) ;
target_text->setValidData( valid_input );
sprintf( target_str, "%.3f", aileron_pid->get_reference() ); //format label
target_text->setValue( target_str ); //set value to aileron gains
since roll is selected by default
target_text->setLabel( "Target" );
target_text->setLabelPlace( PUPLACE_TOP_CENTERED );
target_text->setCallback( pui_callback );
curx += PUI_TEXT_WIDTH + PUI_X_GAP;
target_arrow_r = new puArrowButton ( curx, cury,
curx + PUI_ARROW_WIDTH,
cury + PUI_ARROW_HEIGHT,
PUARROW_RIGHT );
target_arrow_r->setCallback( pui_callback );
curx += PUI_ARROW_WIDTH + PUI_X_GAP;
cury -= PUI_ARROW_HEIGHT - PUI_Y_GAP;
//labels
roll_err_label = new puText ( curx, cury ) ;
roll_err_label->setLabel( "Roll error: 0.000" );
cury += PUI_ARROW_HEIGHT;
pitch_err_label = new puText ( curx, cury ) ;
pitch_err_label->setLabel( "Pitch error: 0.000" );
curx = PUI_RADIO_WIDTH + PUI_X_GAP * 2;
cury = PUI_Y_GAP;
udp_label = new puText ( curx, cury ) ;
udp_label->setLabel( "UDP in: 5500 | UDP out: 5501" );
//hertz text input
hertz_text = new puInput ( curx, cury,
curx + PUI_TEXT_WIDTH,
cury + PUI_TEXT_HEIGHT ) ;
//hertz_text->setValidData( valid_input );
hertz_text->setValuator( &update );
hertz_text->setLabel( "Hertz" );
hertz_text->setLabelPlace( PUPLACE_TOP_CENTERED );
//hertz_text->setCallback( pui_callback );
}
/**********************************************************************
* pui callback
*********************************************************************/
void pui_callback( puObject *pob ){
const float interval = 0.001; //increment or decrement interval
//this will be 0 for roll and 1 for pitch
int val = controller_selector->getValue();
bool aileron;
if ( val == 0 ) {
aileron = true;
} else {
aileron = false;
}
if ( pob == log_button ) { //toggle logging
logging = log_button->getValue();
//cout << "log_button" << endl;
} else if ( pob == pause_button ) { //toggle pause
pauseSoftSim = pause_button->getValue();
//cout << "pause_button" << endl;
} else if ( pob == controller_selector ) { //update gui
if ( aileron ) { //update for ailerons
gui_update( aileron_pid );
} else { //update for elevator
gui_update( elevator_pid );
}
} else if ( pob == kp_arrow_l ) { //decrement kp
if ( aileron ) {
aileron_pid->set_kp( aileron_pid->get_kp() - interval );
gui_update( aileron_pid );
} else {
elevator_pid->set_kp( elevator_pid->get_kp() - interval );
gui_update( elevator_pid );
}
} else if ( pob == kp_arrow_r ) { //increment kp
if ( aileron ) {
aileron_pid->set_kp( aileron_pid->get_kp() + interval );
gui_update( aileron_pid );
} else {
elevator_pid->set_kp( elevator_pid->get_kp() + interval );
gui_update( elevator_pid );
}
} else if ( pob == ki_arrow_l ) { //decrement ki
if ( aileron ) {
aileron_pid->set_ki( aileron_pid->get_ki() - interval );
gui_update( aileron_pid );
} else {
elevator_pid->set_ki( elevator_pid->get_ki() - interval );
gui_update( elevator_pid );
}
} else if ( pob == ki_arrow_r ) { //increment ki
if ( aileron ) {
aileron_pid->set_ki( aileron_pid->get_ki() + interval );
gui_update( aileron_pid );
} else {
elevator_pid->set_ki( elevator_pid->get_ki() + interval );
gui_update( elevator_pid );
}
} else if ( pob == kd_arrow_l ) { //decrement kd
if ( aileron ) {
aileron_pid->set_kd( aileron_pid->get_kd() - interval );
gui_update( aileron_pid );
} else {
elevator_pid->set_kd( elevator_pid->get_kd() - interval );
gui_update( elevator_pid );
}
} else if ( pob == kd_arrow_r ) { //increment kd
if ( aileron ) {
aileron_pid->set_kd( aileron_pid->get_kd() + interval );
gui_update( aileron_pid );
} else {
elevator_pid->set_kd( elevator_pid->get_kd() + interval );
gui_update( elevator_pid );
}
} else if ( pob == target_arrow_l ) { //decrement target
if ( aileron ) {
aileron_pid->set_reference( aileron_pid->get_reference() - 1 );
gui_update( aileron_pid );
} else {
elevator_pid->set_reference( elevator_pid->get_reference() - 1 );
gui_update( elevator_pid );
}
} else if ( pob == target_arrow_r ) { //increment target
if ( aileron ) {
aileron_pid->set_reference( aileron_pid->get_reference() + 1 );
gui_update( aileron_pid );
} else {
elevator_pid->set_reference( elevator_pid->get_reference() + 1 );
gui_update( elevator_pid );
}
} else {
cout << "Unknown callback to pui_callback" << endl;
}
}
void gui_update( SSPid *pid ) {
sprintf( kp_str, "%.3f", pid->get_kp() ); //format label
kp_text->setValue( kp_str );
sprintf( ki_str, "%.3f", pid->get_ki() ); //format label
ki_text->setValue( ki_str );
sprintf( kd_str, "%.3f", pid->get_kd() ); //format label
kd_text->setValue( kd_str );
sprintf( target_str, "%.3f", pid->get_reference() ); //format label
target_text->setValue( target_str );
}
On Thu, Jun 12, 2008 at 4:42 PM, Fay John F Dr CTR USAF 46 SK
<joh...@eg...> wrote:
> Hmmm ... unless somebody else steps in, please forward me a copy of the
> offending code. I've tried putting in your code snippet and the program
> works just fine for me, so evidently something else is going on.
>
> John F. Fay
> Technical Fellow
> Jacobs Technology TEAS Group
> 850-883-1294
>
> -----Original Message-----
> From: pli...@li...
> [mailto:pli...@li...] On Behalf Of cory
> barton
> Sent: Thursday, June 12, 2008 3:19 PM
> To: PLIB Users
> Subject: [Plib-users] (cory vs. pui) The attack of setValuator
>
> I found the following in the PUI documentation today:
> There are many occasions when you'd really like to have the PUI widget
> directly drive and/or reflect the value of some memory location in the
> application code. These calls let you do that:
>
> void puObject::setValuator ( int *i ) ;
> void puObject::setValuator ( float *f ) ;
> void puObject::setValuator ( char *s ) ;
>
>
> Once you make one of these calls, PUI will automatically update the
> memory location indicated with the current value of the widget
> whenever it changes - and also update the appearance of the widget to
> reflect the value stored in that memory location whenever the widget
> is redrawn. This is often a lot more convenient than using a callback
> function to register changes in the widget's value.
>
> So I tried it out:
> //global variable
> float update = 1.0f;
>
> //initialize my puInput inside a function
> //hertz text input
> hertz_text = new puInput ( curx, cury,
> curx +
> PUI_TEXT_WIDTH,
> cury +
> PUI_TEXT_HEIGHT ) ;
> hertz_text->setValuator( &update );
> hertz_text->setLabel( "Hertz" );
> hertz_text->setLabelPlace( PUPLACE_TOP_CENTERED );
>
>
> This compiles, and runs.
>
> It seems to work correctly as long as I do not remove all of the
> characters from the puInput box. However if I am trying to change the
> value, when I am typing in the new value, if the new value ever
> becomes a non valid float value, then the program crashes. For example
> if I want to change 1.0 to 2.0 and I delete 1.0 so I can type 2.0,
> then instant crash. I can change from 1.0 to 2.0 if I type the 2 after
> the 1, and then erase the 1.
>
> Searching the mail archives and googling didn't help, so I am posting
> here.
>
> I suspect either my weak understanding of pointers means that I am
> passing an incorrect argument to the setValuator function, or maybe
> the puInput object is writing invalid data to the update variable.
>
> Please let me know how to fix this.
>
> thanks,
>
> Cory
>
> ------------------------------------------------------------------------
> -
> Check out the new SourceForge.net Marketplace.
> It's the best place to buy or sell services for
> just about anything Open Source.
> http://sourceforge.net/services/buy/index.php
> _______________________________________________
> plib-users mailing list
> pli...@li...
> https://lists.sourceforge.net/lists/listinfo/plib-users
>
> -------------------------------------------------------------------------
> Check out the new SourceForge.net Marketplace.
> It's the best place to buy or sell services for
> just about anything Open Source.
> http://sourceforge.net/services/buy/index.php
> _______________________________________________
> plib-users mailing list
> pli...@li...
> https://lists.sourceforge.net/lists/listinfo/plib-users
>
|