2121static char THIS_FILE[] = __FILE__;
2222#endif
2323
24- const float input_threshold = 0 .01f ; // smallest increment of input box
24+ constexpr auto INPUT_THRESHOLD = 0 .01f ; // smallest increment of input box
25+ constexpr auto INPUT_FORMAT = " %.01f" ;
2526
2627// ///////////////////////////////////////////////////////////////////////////
2728// orient_editor dialog
@@ -45,15 +46,15 @@ orient_editor::orient_editor(CWnd* pParent /*=NULL*/)
4546
4647 Assert (query_valid_object ());
4748 auto pos = &Objects[cur_object_index].pos ;
48- m_position_x.Format (" %.01f " , pos->xyz .x );
49- m_position_y.Format (" %.01f " , pos->xyz .y );
50- m_position_z.Format (" %.01f " , pos->xyz .z );
49+ m_position_x.Format (INPUT_FORMAT , pos->xyz .x );
50+ m_position_y.Format (INPUT_FORMAT , pos->xyz .y );
51+ m_position_z.Format (INPUT_FORMAT , pos->xyz .z );
5152
5253 angles ang;
5354 vm_extract_angles_matrix (&ang, &Objects[cur_object_index].orient );
54- m_orientation_p.Format (" %.01f " , to_degrees (ang.p ));
55- m_orientation_b.Format (" %.01f " , to_degrees (ang.b ));
56- m_orientation_h.Format (" %.01f " , to_degrees (ang.h ));
55+ m_orientation_p.Format (INPUT_FORMAT , to_degrees (ang.p ));
56+ m_orientation_b.Format (INPUT_FORMAT , to_degrees (ang.b ));
57+ m_orientation_h.Format (INPUT_FORMAT , to_degrees (ang.h ));
5758}
5859
5960void orient_editor::DoDataExchange (CDataExchange* pDX)
@@ -182,29 +183,47 @@ BOOL orient_editor::OnInitDialog()
182183 return TRUE ;
183184}
184185
185- bool orient_editor::close (float val, const CString &str)
186+ /* *
187+ * Checks whether the position value is close enough to the input string value that we can assume the input has not changed.
188+ */
189+ bool orient_editor::is_close (float val, const CString &input_str) const
186190{
187- float diff = val - convert (str);
188- return diff > -input_threshold && diff < input_threshold;
191+ val = perform_input_rounding (val);
192+ float input_val = convert (input_str);
193+
194+ float diff = val - input_val;
195+ return abs (diff) < INPUT_THRESHOLD;
196+ }
197+
198+ /* *
199+ * Checks whether the angle value is close enough to the input string value that we can assume the input has not changed.
200+ */
201+ bool orient_editor::is_angle_close (float rad, const CString &input_str) const
202+ {
203+ float deg = perform_input_rounding (to_degrees (rad));
204+ float input_deg = normalize_degrees (convert (input_str));
205+
206+ float diff = deg - input_deg;
207+ return abs (diff) < INPUT_THRESHOLD;
189208}
190209
191210bool orient_editor::query_modified ()
192211{
193- if (!close (Objects[cur_object_index].pos .xyz .x , m_position_x))
212+ if (!is_close (Objects[cur_object_index].pos .xyz .x , m_position_x))
194213 return true ;
195- if (!close (Objects[cur_object_index].pos .xyz .y , m_position_y))
214+ if (!is_close (Objects[cur_object_index].pos .xyz .y , m_position_y))
196215 return true ;
197- if (!close (Objects[cur_object_index].pos .xyz .z , m_position_z))
216+ if (!is_close (Objects[cur_object_index].pos .xyz .z , m_position_z))
198217 return true ;
199218
200219 angles ang;
201220 vm_extract_angles_matrix (&ang, &Objects[cur_object_index].orient );
202221
203- if (!close ( to_degrees ( ang.p ) , m_orientation_p))
222+ if (!is_angle_close ( ang.p , m_orientation_p))
204223 return true ;
205- if (!close ( to_degrees ( ang.b ) , m_orientation_b))
224+ if (!is_angle_close ( ang.b , m_orientation_b))
206225 return true ;
207- if (!close ( to_degrees ( ang.h ) , m_orientation_h))
226+ if (!is_angle_close ( ang.h , m_orientation_h))
208227 return true ;
209228
210229 if (((CButton *) GetDlgItem (IDC_POINT_TO_CHECKBOX))->GetCheck () == TRUE )
@@ -224,7 +243,7 @@ void orient_editor::OnOK()
224243
225244 // there's enough difference in our position that we're changing it
226245 cur_pos = &Objects[cur_object_index].pos ;
227- if (!close (cur_pos->xyz .x , m_position_x) || !close (cur_pos->xyz .y , m_position_y) || !close (cur_pos->xyz .z , m_position_z))
246+ if (!is_close (cur_pos->xyz .x , m_position_x) || !is_close (cur_pos->xyz .y , m_position_y) || !is_close (cur_pos->xyz .z , m_position_z))
228247 {
229248 vec3d pos;
230249 pos.xyz .x = convert (m_position_x);
@@ -237,7 +256,7 @@ void orient_editor::OnOK()
237256
238257 // there's enough difference in our orientation that we're changing it
239258 vm_extract_angles_matrix (&ang, &Objects[cur_object_index].orient );
240- if (!close ( to_degrees ( ang.p ) , m_orientation_p) || !close ( to_degrees ( ang.b ) , m_orientation_b) || !close ( to_degrees ( ang.h ) , m_orientation_h))
259+ if (!is_angle_close ( ang.p , m_orientation_p) || !is_angle_close ( ang.b , m_orientation_b) || !is_angle_close ( ang.h , m_orientation_h))
241260 {
242261 ang.p = fl_radians (convert (m_orientation_p));
243262 ang.b = fl_radians (convert (m_orientation_b));
@@ -354,6 +373,11 @@ void orient_editor::actually_point_object(object *ptr)
354373float orient_editor::to_degrees (float rad)
355374{
356375 float deg = fl_degrees (rad);
376+ return normalize_degrees (deg);
377+ }
378+
379+ float orient_editor::normalize_degrees (float deg)
380+ {
357381 while (deg < -180 .0f )
358382 deg += 180 .0f ;
359383 while (deg > 180 .0f )
@@ -364,7 +388,10 @@ float orient_editor::to_degrees(float rad)
364388 return deg;
365389}
366390
367- float orient_editor::convert (const CString &str)
391+ /* *
392+ * Extract a float from the CString, being mindful of any comma separators.
393+ */
394+ float orient_editor::convert (const CString &str) const
368395{
369396 char buf[256 ];
370397 size_t i, j, len;
@@ -379,6 +406,18 @@ float orient_editor::convert(const CString &str)
379406 return (float ) atof (buf);
380407}
381408
409+ /* *
410+ * Perform rounding of the float value by loading it into the input box format string and parsing it again.
411+ * This accounts for not only decimal rounding to the precision of the input box, but also floating point rounding due to inexact fractions such as 1/10.
412+ * See also GitHub PR #4475.
413+ */
414+ float orient_editor::perform_input_rounding (float val) const
415+ {
416+ CString str;
417+ str.Format (INPUT_FORMAT, val);
418+ return convert (str);
419+ }
420+
382421void orient_editor::OnPointTo ()
383422{
384423 UpdateData (TRUE );
0 commit comments