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>
20 setPilotXOffset (float value)
22 PilotOffsetSet(0, value);
28 return( PilotOffsetGetSetting(0) );
33 setPilotYOffset (float value)
35 PilotOffsetSet(1, value);
41 return( PilotOffsetGetSetting(1) );
46 setPilotZOffset (float value)
48 PilotOffsetSet(2, value);
54 return( PilotOffsetGetSetting(2) );
58 class FloatSlider : public puSlider
73 FloatSlider ( int x, int y, int sz, float f, const char *title,
74 float max = 100.0f, float min = 0.0f);
78 static void adj( puObject *);
81 sprintf( _text, "%05.2f", MyValue );
84 float get() { return( MyValue ); }
86 // calc actual "setting" by multiplying the pui fraction by highest value setable
87 void set() { MyValue = maxValue * TmpValue; }
89 float *getTmp() { return( &TmpValue ); }
91 // adjust the TmpValue back to 0 to 1 range of pui widget
92 void setTmp() { TmpValue += 0.0f; }
94 void incTmp() { TmpValue += 0.0001f; setTmp(); }
95 void decTmp() { TmpValue -= 0.0001f; setTmp(); }
97 // adjust actual "setting" value back to fraction for pui widget
98 void init( float f ) {
99 if (f > maxValue) f = maxValue;
100 if (f < minValue) f = minValue;
101 Adjust = 1.0f / maxValue;
102 setValue(f * Adjust);
106 void reinit() { init( origValue ); }
107 void cancel() { MyValue = TmpValue; }
108 void reset () { init( origValue ); }
112 void FloatSlider::adj( puObject *hs )
114 FloatSlider *slider = (FloatSlider *)hs;
115 slider->getValue ( slider->getTmp() );
118 slider->updateText();
121 FloatSlider::FloatSlider ( int x, int y, int sz, float f, const char *title,
122 float max, float min ) : puSlider( x, y, sz, FALSE )
129 setCBMode ( PUSLIDER_DELTA ) ;
130 strcpy ( _title, title);
132 setLabelPlace ( PUPLACE_LEFT );
134 // setLegendPlace( PUPLACE_RIGHT );
138 class FloatDial : public puDial
153 FloatDial ( int x, int y, int sz, float f, const char *title,
154 float max = 180.0f, float min = -180.0f );
158 static void adj( puObject *);
161 sprintf( _text, "%05.2f", MyValue );
164 float get() { return( MyValue ); }
166 // calc actual "setting" by multiplying the pui fraction by highest value setable
167 // in this case we're also turning a 0 to 1 range into a -.05 to +.05 before converting
168 void set() { MyValue = ((2.0*maxValue) * (TmpValue - 0.5f)) - maxValue; }
170 float *getTmp() { return( &TmpValue ); }
172 // adjust the TmpValue back to 0 to 1 range of pui widget
173 void setTmp() { TmpValue += 0.5f; }
175 void incTmp() { TmpValue += 0.0001f; setTmp(); }
176 void decTmp() { TmpValue -= 0.0001f; setTmp(); }
178 // adjust actual "setting" value back to fraction for pui widget
179 // double the range from -max <-> max
180 void init( float f ) {
181 if (f > maxValue) f = maxValue;
182 if (f < minValue) f = minValue;
183 Adjust = 0.5f / maxValue;
184 setValue((f * Adjust) + 0.5f);
188 void reinit() { init( origValue ); }
189 void cancel() { MyValue = TmpValue; }
190 void reset () { init( origValue ); }
194 void FloatDial::adj( puObject *hs )
196 FloatDial *dial = (FloatDial *)hs;
197 dial->getValue ( dial->getTmp() );
203 FloatDial::FloatDial ( int x, int y, int sz, float f, const char *title,
204 float max, float min ) : puDial( x, y, sz )
211 setCBMode ( PUSLIDER_DELTA ) ;
212 strcpy ( _title, title);
214 setLabelPlace ( PUPLACE_LEFT );
216 // setLegendPlace( PUPLACE_RIGHT );
220 /***********************************************/
222 class sgVec3Slider : public puDialogBox
224 static void handle_arrow(puObject *p_obj);
225 static void heading_adj(puObject *p_obj);
226 static void pitch_adj(puObject *p_obj);
227 static void radius_adj(puObject *p_obj);
228 static void goAway(puObject *p_obj);
229 static void reset(puObject *p_obj);
230 static void cancel(puObject *p_obj);
239 puOneShot *ResetButton;
240 puOneShot *CancelButton;
241 puArrowButton *right_arrow;
242 puArrowButton *left_arrow;
247 sgVec3Slider ( int x, int y, sgVec3 vec,
248 const char *title = "Vector Adjuster",
249 const char *Xtitle = "Heading",
250 const char *Ytitle = "Pitch",
251 const char *Ztitle = "Radius " );
256 // calc the property Vec with the actual point on sphere
259 Vec3FromHeadingPitchRadius( Vec,
265 // return the offset vector according to current widget values
272 // save the Vector before pushing dialog (for cancel button)
273 sgVec3 *getStashVec() { return &SaveVec; }
275 SaveVec[2] = HS0->get();
276 SaveVec[1] = HS1->get();
277 SaveVec[0] = HS2->get();
280 // functions to return pointers to protected pui widget instances
281 FloatDial *getHS0() { return HS0; }
282 FloatDial *getHS1() { return HS1; }
283 FloatSlider *getHS2() { return HS2; }
285 static void adjust(puObject *p_obj);
289 sgVec3Slider::sgVec3Slider ( int x, int y, sgVec3 cart, const char *title,
292 const char *Ztitle ): puDialogBox ( x, y )
294 puFont LegendFont, LabelFont;
295 puGetDefaultFonts ( &LegendFont, &LabelFont );
298 HeadingPitchRadiusFromVec3( Vec, cart);
300 sgSetVec3(vec, Vec[0], Vec[1], Vec[2]);
302 int labelW = LabelFont.getStringWidth(Xtitle);
303 labelW = SG_MAX2( labelW, LabelFont.getStringWidth(Ytitle));
304 labelW = SG_MAX2( labelW, LabelFont.getStringWidth(Ztitle));
307 sgCopyVec3(SaveVec, vec);
308 sgCopyVec3(Vec, vec);
309 strcpy( Label, title );
312 int slider_x = 70+fudge;
314 int slider_width = 270;
315 int dialer_x = 70+fudge;
317 int dialer_size = 100;
319 int horiz_slider_height = LabelFont.getStringHeight()
320 + LabelFont.getStringDescender()
321 + PUSTR_TGAP + PUSTR_BGAP + 5;
323 int DialogWidth = slider_width + 20 + fudge + labelW;
324 int DialogHeight = dialer_size + 115 + nSliders * horiz_slider_height;
328 horiz_slider_height += 10;
330 new puFrame ( 0, 0, DialogWidth, DialogHeight );
332 setLabelPlace( PUPLACE_DEFAULT /*PUPLACE_CENTERED*/ );
336 HS0 = new FloatDial ( dialer_x, dialer_y, dialer_size, vec[0], Xtitle, 180.0f, -180.0f );
337 dialer_x = dialer_x + 170;
338 HS0->setUserData (this);
339 HS0->setCallback ( heading_adj ) ;
342 HS1 = new FloatDial ( dialer_x, dialer_y, dialer_size, vec[1], Ytitle, 89.99f, -89.99f );
343 HS1->setUserData (this);
344 HS1->setCallback ( pitch_adj ) ;
347 HS2 = new FloatSlider ( slider_x+20, slider_y, slider_width-40, vec[2], Ztitle, 100.0f, 0.0f );
348 HS2->setUserData (this);
349 HS2->setCallback ( radius_adj );
351 right_arrow = new puArrowButton ( slider_x + slider_width - 20, slider_y + 1, slider_x + slider_width, slider_y+21, PUARROW_RIGHT ) ;
352 right_arrow->setUserData ( HS2 ) ;
353 right_arrow->setCallback ( handle_arrow ) ;
355 left_arrow = new puArrowButton ( slider_x, slider_y + 1, slider_x+20, slider_y+21, PUARROW_LEFT ) ;
356 left_arrow->setUserData ( HS2 ) ;
357 left_arrow->setCallback ( handle_arrow ) ;
359 TitleText = new puText( 130, DialogHeight - 40);
360 TitleText->setLabel("Pilot Offset");
362 OkButton = new puOneShot ( 70+fudge, 20, 120+fudge, 50 );
363 OkButton-> setUserData( this );
364 OkButton-> setLegend ( gui_msg_OK );
365 OkButton-> makeReturnDefault ( TRUE );
366 OkButton-> setCallback ( goAway );
368 CancelButton = new puOneShot ( 130+fudge, 20, 210+fudge, 50 );
369 CancelButton-> setUserData( this );
370 CancelButton-> setLegend ( gui_msg_CANCEL );
371 CancelButton-> setCallback ( cancel );
373 // renabling this button requires binding in the sim/view[?]/config/?-offset-m values
374 // ResetButton = new puOneShot ( 220+fudge, 20, 280+fudge, 50 );
375 // ResetButton-> setUserData( this );
376 // ResetButton-> setLegend ( gui_msg_RESET );
377 // ResetButton-> setCallback ( reset );
379 FG_FINALIZE_PUI_DIALOG( this );
382 void sgVec3Slider::handle_arrow(puObject *arrow)
384 FloatSlider *slider = (FloatSlider *) arrow->getUserData();
385 if (((puArrowButton *)arrow)->getArrowType() == PUARROW_RIGHT)
390 slider->init( slider->get() );
391 sgVec3Slider *me = (sgVec3Slider *)slider->getUserData();
395 void sgVec3Slider::heading_adj(puObject *p_obj)
397 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
398 me->HS0->adj((puObject *)me ->HS0 );
402 void sgVec3Slider::pitch_adj(puObject *p_obj)
404 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
405 me->HS1->adj((puObject *)me ->HS1 );
409 void sgVec3Slider::radius_adj(puObject *p_obj)
411 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
412 me ->HS2-> adj((puObject *)me ->HS2 );
416 void sgVec3Slider::goAway(puObject *p_obj)
418 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
419 FG_POP_PUI_DIALOG( me );
422 void sgVec3Slider::reset(puObject *p_obj)
424 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
430 void sgVec3Slider::cancel(puObject *p_obj)
433 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
434 sgVec3 *pvec = me -> getStashVec();
435 sgCopyVec3( vec, *pvec );
436 me->HS0->init(vec[2]);
437 me->HS1->init(vec[1]);
438 me->HS2->init(vec[0]);
440 FG_POP_PUI_DIALOG( me );
443 void sgVec3Slider::adjust(puObject *p_obj)
445 sgVec3Slider *me = (sgVec3Slider *)p_obj->getUserData();
452 fgGetFloat("/sim/current-view/x-offset-m"),
453 fgGetFloat("/sim/current-view/y-offset-m"),
454 fgGetFloat("/sim/current-view/z-offset-m")
457 HeadingPitchRadiusFromVec3( me->Vec, cart);
459 me -> getHS0() -> init(me->Vec[0]);
460 me -> getHS1() -> init(me->Vec[1]);
461 me -> getHS2() -> init(me->Vec[2]);
463 me -> getHS0() -> adj((puObject *)me -> getHS0());
464 me -> getHS1() -> adj((puObject *)me -> getHS1());
465 me -> getHS2() -> adj((puObject *)me -> getHS2());
469 void sgVec3SliderAdjust( puObject *p_obj )
471 sgVec3Slider *me = (sgVec3Slider *)p_obj -> getUserData();
473 FG_PUSH_PUI_DIALOG( me );
476 // These are globals for now
477 static puObject *PO_vec = 0;
479 void PilotOffsetInit() {
482 fgGetFloat("/sim/current-view/x-offset-m"),
483 fgGetFloat("/sim/current-view/y-offset-m"),
484 fgGetFloat("/sim/current-view/z-offset-m")
486 PilotOffsetInit(cart);
489 void PilotOffsetInit( sgVec3 cart )
491 // Only one of these things for now
493 sgVec3Slider *PO = new sgVec3Slider ( 200, 200, cart, "Pilot Offset" );
495 // Bindings for Pilot Offset
496 fgTie("/sim/current-view/x-offset-m", getPilotXOffset, setPilotXOffset);
497 fgTie("/sim/current-view/y-offset-m", getPilotYOffset, setPilotYOffset);
498 fgTie("/sim/current-view/z-offset-m", getPilotZOffset, setPilotZOffset);
502 void PilotOffsetAdjust( puObject * )
507 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
510 FG_PUSH_PUI_DIALOG( me );
513 // external to get pilot offset vector for viewer
514 sgVec3 *PilotOffsetGet()
519 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
520 return( me -> getVec() );
523 // external function used to tie to FG properties
524 float PilotOffsetGetSetting(int opt)
530 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
532 sgCopyVec3(vec, (float *) me->getVec());
533 if( opt == 0 ) setting = vec[0];
534 if( opt == 1 ) setting = vec[1];
535 if( opt == 2 ) setting = vec[2];
539 // external function used to tie to FG properties
540 void PilotOffsetSet(int opt, float setting)
545 sgVec3Slider *me = (sgVec3Slider *)PO_vec -> getUserData();
549 sgCopyVec3(vec, (float *) me->getVec());
550 if( opt == 0 ) vec[0] = setting;
551 if( opt == 1 ) vec[1] = setting;
552 if( opt == 2 ) vec[2] = setting;
553 HeadingPitchRadiusFromVec3 ( HPR, vec );
554 me -> getHS0() -> init( HPR[0] );
555 me -> getHS1() -> init( HPR[1] );
556 me -> getHS2() -> init( HPR[2] );
561 // Calculate vector of point on sphere:
562 // input Heading == longitude of point on sphere
563 // input Pitch == latitude of point on sphere
564 // input Radius == radius of sphere
566 #define MIN_VIEW_OFFSET 0.001
567 void Vec3FromHeadingPitchRadius ( sgVec3 vec3, float heading, float pitch,
570 double ch, sh, cp, sp;
572 if ( heading == SG_ZERO )
579 sh = sin( (double)( heading * SG_DEGREES_TO_RADIANS )) ;
580 ch = cos( (double)( heading * SG_DEGREES_TO_RADIANS )) ;
583 if ( pitch == SG_ZERO )
590 sp = sin( (double)( pitch * SG_DEGREES_TO_RADIANS )) ;
591 cp = cos( (double)( pitch * SG_DEGREES_TO_RADIANS )) ;
594 if ( radius < MIN_VIEW_OFFSET )
595 radius = MIN_VIEW_OFFSET ;
597 vec3[2] = (SGfloat)( ch * cp ) * radius ; // X
598 vec3[1] = (SGfloat)( sh * cp ) * radius ; // Y
599 vec3[0] = (SGfloat)( sp ) * radius ; // Z
602 // Convert to speherical coordinates for the dials
604 void HeadingPitchRadiusFromVec3 ( sgVec3 hpr, sgVec3 vec3 )
617 if (fabs(y) < 0.001f)
620 Zx = sqrt(y*y + z*z);
622 hpr[2] = sqrt(x*x + y*y + z*z);
628 hpr[1] = acos(Pr) * SGD_RADIANS_TO_DEGREES;
633 hpr[0] = (SGD_PI - asin(y/Zx)) * SGD_RADIANS_TO_DEGREES;
635 hpr[0] = asin(y/Zx) * SGD_RADIANS_TO_DEGREES;
637 hpr[0] = 180 - hpr[0];