4 * Simple PUI wrapper around sgVec3 class
6 * Created by: Norman Vine [NHV]
7 * nhv@yahoo.com, nhv@cape.com
11 * Started 12:53 01/28/2001
15 #include "sgVec3Slider.hxx"
16 #include <Main/fg_props.hxx>
17 #include <simgear/sg_inlines.h>
19 class FloatSlider : public puSlider
34 FloatSlider ( int x, int y, int sz, float f, const char *title,
35 float max = 100.0f, float min = 0.0f);
39 static void adj( puObject *);
42 sprintf( _text, "%05.2f", MyValue );
45 float get() { return( MyValue ); }
47 // calc actual "setting" by multiplying the pui fraction by highest value setable
48 void set() { MyValue = maxValue * TmpValue; }
50 float *getTmp() { return( &TmpValue ); }
52 // adjust the TmpValue back to 0 to 1 range of pui widget
53 void setTmp() { TmpValue += 0.0f; }
55 void incTmp() { TmpValue += 0.0001f; setTmp(); }
56 void decTmp() { TmpValue -= 0.0001f; setTmp(); }
58 // adjust actual "setting" value back to fraction for pui widget
59 void init( float f ) {
60 if (f > maxValue) f = maxValue;
61 if (f < minValue) f = minValue;
62 Adjust = 1.0f / maxValue;
67 void reinit() { init( origValue ); }
68 void cancel() { MyValue = TmpValue; }
69 void reset () { init( origValue ); }
73 void FloatSlider::adj( puObject *hs )
75 FloatSlider *slider = (FloatSlider *)hs;
76 slider->getValue ( slider->getTmp() );
82 FloatSlider::FloatSlider ( int x, int y, int sz, float f, const char *title,
83 float max, float min ) : puSlider( x, y, sz, FALSE )
90 setCBMode ( PUSLIDER_DELTA ) ;
91 strcpy ( _title, title);
93 setLabelPlace ( PUPLACE_LEFT );
95 // setLegendPlace( PUPLACE_RIGHT );
99 class FloatDial : public puDial
114 FloatDial ( int x, int y, int sz, float f, const char *title,
115 float max = 180.0f, float min = -180.0f );
119 static void adj( puObject *);
122 sprintf( _text, "%05.2f", MyValue );
125 float get() { return( MyValue ); }
127 // calc actual "setting" by multiplying the pui fraction by highest value setable
128 // in this case we're also turning a 0 to 1 range into a -.05 to +.05 before converting
129 void set() { MyValue = ((2.0*maxValue) * (TmpValue - 0.5f)) - maxValue; }
131 float *getTmp() { return( &TmpValue ); }
133 // adjust the TmpValue back to 0 to 1 range of pui widget
134 void setTmp() { TmpValue += 0.5f; }
136 void incTmp() { TmpValue += 0.0001f; setTmp(); }
137 void decTmp() { TmpValue -= 0.0001f; setTmp(); }
139 // adjust actual "setting" value back to fraction for pui widget
140 // double the range from -max <-> max
141 void init( float f ) {
142 if (f > maxValue) f = maxValue;
143 if (f < minValue) f = minValue;
144 Adjust = 0.5f / maxValue;
145 setValue((f * Adjust) + 0.5f);
149 void reinit() { init( origValue ); }
150 void cancel() { MyValue = TmpValue; }
151 void reset () { init( origValue ); }
155 void FloatDial::adj( puObject *hs )
157 FloatDial *dial = (FloatDial *)hs;
158 dial->getValue ( dial->getTmp() );
164 FloatDial::FloatDial ( int x, int y, int sz, float f, const char *title,
165 float max, float min ) : puDial( x, y, sz )
172 setCBMode ( PUSLIDER_DELTA ) ;
173 strcpy ( _title, title);
175 setLabelPlace ( PUPLACE_LEFT );
177 // setLegendPlace( PUPLACE_RIGHT );
181 /***********************************************/
183 class sgVec3Slider : public puDialogBox
185 static void handle_arrow(puObject *p_obj);
186 static void heading_adj(puObject *p_obj);
187 static void pitch_adj(puObject *p_obj);
188 static void radius_adj(puObject *p_obj);
189 static void goAway(puObject *p_obj);
190 static void reset(puObject *p_obj);
191 static void cancel(puObject *p_obj);
200 puOneShot *ResetButton;
201 puOneShot *CancelButton;
202 puArrowButton *right_arrow;
203 puArrowButton *left_arrow;
208 sgVec3Slider ( int x, int y, sgVec3 vec,
209 const char *title = "Vector Adjuster",
210 const char *Xtitle = "Heading",
211 const char *Ytitle = "Pitch",
212 const char *Ztitle = "Radius " );
217 // calc the property Vec with the actual point on sphere
220 Vec3FromHeadingPitchRadius( Vec,
226 // return the offset vector according to current widget values
233 // save the Vector before pushing dialog (for cancel button)
234 sgVec3 *getStashVec() { return &SaveVec; }
236 SaveVec[2] = HS0->get();
237 SaveVec[1] = HS1->get();
238 SaveVec[0] = HS2->get();
241 // functions to return pointers to protected pui widget instances
242 FloatDial *getHS0() { return HS0; }
243 FloatDial *getHS1() { return HS1; }
244 FloatSlider *getHS2() { return HS2; }
246 static void adjust(puObject *p_obj);
250 sgVec3Slider::sgVec3Slider ( int x, int y, sgVec3 cart, const char *title,
253 const char *Ztitle ): puDialogBox ( x, y )
255 puFont LegendFont, LabelFont;
256 puGetDefaultFonts ( &LegendFont, &LabelFont );
259 HeadingPitchRadiusFromVec3( Vec, cart);
261 sgSetVec3(vec, Vec[0], Vec[1], Vec[2]);
263 int labelW = LabelFont.getStringWidth(Xtitle);
264 labelW = SG_MAX2( labelW, LabelFont.getStringWidth(Ytitle));
265 labelW = SG_MAX2( labelW, LabelFont.getStringWidth(Ztitle));
268 sgCopyVec3(SaveVec, vec);
269 sgCopyVec3(Vec, vec);
270 strcpy( Label, title );
273 int slider_x = 70+fudge;
275 int slider_width = 270;
276 int dialer_x = 70+fudge;
278 int dialer_size = 100;
280 int horiz_slider_height = LabelFont.getStringHeight()
281 + LabelFont.getStringDescender()
282 + PUSTR_TGAP + PUSTR_BGAP + 5;
284 int DialogWidth = slider_width + 20 + fudge + labelW;
285 int DialogHeight = dialer_size + 115 + nSliders * horiz_slider_height;
289 horiz_slider_height += 10;
291 new puFrame ( 0, 0, DialogWidth, DialogHeight );
293 setLabelPlace( PUPLACE_DEFAULT /*PUPLACE_CENTERED*/ );
297 HS0 = new FloatDial ( dialer_x, dialer_y, dialer_size, vec[0], Xtitle, 180.0f, -180.0f );
298 dialer_x = dialer_x + 170;
299 HS0->setUserData (this);
300 HS0->setCallback ( heading_adj ) ;
303 HS1 = new FloatDial ( dialer_x, dialer_y, dialer_size, vec[1], Ytitle, 89.99f, -89.99f );
304 HS1->setUserData (this);
305 HS1->setCallback ( pitch_adj ) ;
308 HS2 = new FloatSlider ( slider_x+20, slider_y, slider_width-40, vec[2], Ztitle, 100.0f, 0.0f );
309 HS2->setUserData (this);
310 HS2->setCallback ( radius_adj );
312 right_arrow = new puArrowButton ( slider_x + slider_width - 20, slider_y + 1, slider_x + slider_width, slider_y+21, PUARROW_RIGHT ) ;
313 right_arrow->setUserData ( HS2 ) ;
314 right_arrow->setCallback ( handle_arrow ) ;
316 left_arrow = new puArrowButton ( slider_x, slider_y + 1, slider_x+20, slider_y+21, PUARROW_LEFT ) ;
317 left_arrow->setUserData ( HS2 ) ;
318 left_arrow->setCallback ( handle_arrow ) ;
320 TitleText = new puText( 130, DialogHeight - 40);
321 TitleText->setLabel("Pilot Offset");
323 OkButton = new puOneShot ( 70+fudge, 20, 120+fudge, 50 );
324 OkButton-> setUserData( this );
325 OkButton-> setLegend ( gui_msg_OK );
326 OkButton-> makeReturnDefault ( TRUE );
327 OkButton-> setCallback ( goAway );
329 CancelButton = new puOneShot ( 130+fudge, 20, 210+fudge, 50 );
330 CancelButton-> setUserData( this );
331 CancelButton-> setLegend ( gui_msg_CANCEL );
332 CancelButton-> setCallback ( cancel );
334 // renabling this button requires binding in the sim/view[?]/config/?-offset-m values
335 // ResetButton = new puOneShot ( 220+fudge, 20, 280+fudge, 50 );
336 // ResetButton-> setUserData( this );
337 // ResetButton-> setLegend ( gui_msg_RESET );
338 // ResetButton-> setCallback ( reset );
340 FG_FINALIZE_PUI_DIALOG( this );
343 void sgVec3Slider::handle_arrow(puObject *arrow)
345 FloatSlider *slider = (FloatSlider *) arrow->getUserData();
346 if (((puArrowButton *)arrow)->getArrowType() == PUARROW_RIGHT)
351 slider->init( slider->get() );
352 sgVec3Slider *me = (sgVec3Slider *)slider->getUserData();
356 void sgVec3Slider::heading_adj(puObject *p_obj)
358 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
359 me->HS0->adj((puObject *)me ->HS0 );
363 void sgVec3Slider::pitch_adj(puObject *p_obj)
365 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
366 me->HS1->adj((puObject *)me ->HS1 );
370 void sgVec3Slider::radius_adj(puObject *p_obj)
372 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
373 me ->HS2-> adj((puObject *)me ->HS2 );
377 void sgVec3Slider::goAway(puObject *p_obj)
379 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
380 FG_POP_PUI_DIALOG( me );
383 void sgVec3Slider::reset(puObject *p_obj)
385 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
391 void sgVec3Slider::cancel(puObject *p_obj)
394 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
395 sgVec3 *pvec = me -> getStashVec();
396 sgCopyVec3( vec, *pvec );
397 me->HS0->init(vec[2]);
398 me->HS1->init(vec[1]);
399 me->HS2->init(vec[0]);
401 FG_POP_PUI_DIALOG( me );
404 void sgVec3Slider::adjust(puObject *p_obj)
406 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
413 fgGetFloat("/sim/current-view/x-offset-m"),
414 fgGetFloat("/sim/current-view/y-offset-m"),
415 fgGetFloat("/sim/current-view/z-offset-m")
418 HeadingPitchRadiusFromVec3( me->Vec, cart);
420 me -> getHS0() -> init(me->Vec[0]);
421 me -> getHS1() -> init(me->Vec[1]);
422 me -> getHS2() -> init(me->Vec[2]);
424 me -> getHS0() -> adj((puObject *)me -> getHS0());
425 me -> getHS1() -> adj((puObject *)me -> getHS1());
426 me -> getHS2() -> adj((puObject *)me -> getHS2());
430 void sgVec3SliderAdjust( puObject *p_obj )
432 sgVec3Slider *me = (sgVec3Slider *)p_obj -> getUserData();
434 FG_PUSH_PUI_DIALOG( me );
437 // These are globals for now
438 static puObject *PO_vec = 0;
440 void PilotOffsetInit() {
443 fgGetFloat("/sim/current-view/x-offset-m"),
444 fgGetFloat("/sim/current-view/y-offset-m"),
445 fgGetFloat("/sim/current-view/z-offset-m")
447 PilotOffsetInit(cart);
450 void PilotOffsetInit( sgVec3 cart )
452 // Only one of these things for now
454 sgVec3Slider *PO = new sgVec3Slider ( 200, 200, cart, "Pilot Offset" );
456 // Bindings for Pilot Offset
457 fgTie("/sim/current-view/x-offset-m", getPilotXOffset, setPilotXOffset);
458 fgTie("/sim/current-view/y-offset-m", getPilotYOffset, setPilotYOffset);
459 fgTie("/sim/current-view/z-offset-m", getPilotZOffset, setPilotZOffset);
463 void PilotOffsetAdjust( puObject * )
468 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
471 FG_PUSH_PUI_DIALOG( me );
474 // external to get pilot offset vector for viewer
475 sgVec3 *PilotOffsetGet()
480 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
481 return( me -> getVec() );
484 // external function used to tie to FG properties
485 float PilotOffsetGetSetting(int opt)
491 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
493 sgCopyVec3(vec, (float *) me->getVec());
494 if( opt == 0 ) setting = vec[0];
495 if( opt == 1 ) setting = vec[1];
496 if( opt == 2 ) setting = vec[2];
500 // external function used to tie to FG properties
501 void PilotOffsetSet(int opt, float setting)
506 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
510 sgCopyVec3(vec, (float *) me->getVec());
511 if( opt == 0 ) vec[0] = setting;
512 if( opt == 1 ) vec[1] = setting;
513 if( opt == 2 ) vec[2] = setting;
514 HeadingPitchRadiusFromVec3 ( HPR, vec );
515 me -> getHS0() -> init( HPR[0] );
516 me -> getHS1() -> init( HPR[1] );
517 me -> getHS2() -> init( HPR[2] );
522 // Calculate vector of point on sphere:
523 // input Heading == longitude of point on sphere
524 // input Pitch == latitude of point on sphere
525 // input Radius == radius of sphere
527 #define MIN_VIEW_OFFSET 0.001
528 void Vec3FromHeadingPitchRadius ( sgVec3 vec3, float heading, float pitch,
531 double ch, sh, cp, sp;
533 if ( heading == SG_ZERO )
540 sh = sin( (double)( heading * SG_DEGREES_TO_RADIANS )) ;
541 ch = cos( (double)( heading * SG_DEGREES_TO_RADIANS )) ;
544 if ( pitch == SG_ZERO )
551 sp = sin( (double)( pitch * SG_DEGREES_TO_RADIANS )) ;
552 cp = cos( (double)( pitch * SG_DEGREES_TO_RADIANS )) ;
555 if ( radius < MIN_VIEW_OFFSET )
556 radius = MIN_VIEW_OFFSET ;
558 vec3[2] = (SGfloat)( ch * cp ) * radius ; // X
559 vec3[1] = (SGfloat)( sh * cp ) * radius ; // Y
560 vec3[0] = (SGfloat)( sp ) * radius ; // Z
563 // Convert to speherical coordinates for the dials
565 void HeadingPitchRadiusFromVec3 ( sgVec3 hpr, sgVec3 vec3 )
578 if (fabs(y) < 0.001f)
581 Zx = sqrt(y*y + z*z);
583 hpr[2] = sqrt(x*x + y*y + z*z);
589 hpr[1] = acos(Pr) * SGD_RADIANS_TO_DEGREES;
594 hpr[0] = (SGD_PI - asin(y/Zx)) * SGD_RADIANS_TO_DEGREES;
596 hpr[0] = asin(y/Zx) * SGD_RADIANS_TO_DEGREES;
598 hpr[0] = 180 - hpr[0];