From f5ba29cb46af4a5d592450384722a954a542346d Mon Sep 17 00:00:00 2001 From: Goober5000 Date: Fri, 2 Jan 2026 00:05:06 -0500 Subject: [PATCH] allow more granular background orientations Since bitmaps, suns, and skyboxes store their coordinates as floating-point numbers, we can allow mission designers to specify floating-point numbers in the FRED UI. This PR modifies the dialogs in FRED and QtFRED to allow two decimal places for pitch, bank, and heading. Implements #7170. --- code/math/floating.h | 16 ++ fred2/bgbitmapdlg.cpp | 153 +++++++++--------- fred2/bgbitmapdlg.h | 22 +-- fred2/fred.rc | 42 ++--- qtfred/source_groups.cmake | 24 +-- .../dialogs/BackgroundEditorDialogModel.cpp | 92 +++++------ .../dialogs/BackgroundEditorDialogModel.h | 35 ++-- .../src/ui/dialogs/BackgroundEditorDialog.cpp | 48 +++--- .../src/ui/dialogs/BackgroundEditorDialog.h | 16 +- .../ui/widgets/IntegerSnapDoubleSpinBox.cpp | 63 ++++++++ .../src/ui/widgets/IntegerSnapDoubleSpinBox.h | 18 +++ qtfred/ui/BackgroundEditor.ui | 63 ++++++-- 12 files changed, 361 insertions(+), 231 deletions(-) create mode 100644 qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.cpp create mode 100644 qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.h diff --git a/code/math/floating.h b/code/math/floating.h index c5a42fbc2b4..221aa654e3e 100644 --- a/code/math/floating.h +++ b/code/math/floating.h @@ -16,6 +16,8 @@ #include #include +#include "globalincs/pstypes.h" // for PI + extern float frand(); extern int rand_chance(float frametime, float chance = 1.0f); float frand_range(float min, float max); @@ -51,6 +53,20 @@ inline bool fl_is_nan(float fl) { // convert a measurement in radians to degrees #define fl_degrees(fl) (static_cast((fl) * (180.0f / PI))) +constexpr float DEGREE_UB = 359.99f; // upper bound in degrees when rounding to 100ths place + +// convert a measurement in radians to degrees, rounding to the nearest .01 (used in FRED) +constexpr float fl_degrees_100ths(float fl) +{ + float val = fl_degrees(fl); + + float new_val = fl2ir(val * 100.0f) / 100.0f; + if (new_val > DEGREE_UB) + new_val -= 360.0f; + + return new_val; +} + // sees if a floating point number is within a certain threshold (by default, epsilon) of zero inline bool fl_near_zero(float a, float e = std::numeric_limits::epsilon()) { diff --git a/fred2/bgbitmapdlg.cpp b/fred2/bgbitmapdlg.cpp index bcf1df20c37..8927d127be2 100644 --- a/fred2/bgbitmapdlg.cpp +++ b/fred2/bgbitmapdlg.cpp @@ -58,22 +58,22 @@ bg_bitmap_dlg::bg_bitmap_dlg(CWnd* pParent) : CDialog(bg_bitmap_dlg::IDD, pParen m_toggle_trails = FALSE; m_corrected_angles_in_mission_file = FALSE; - s_pitch = 0; - s_bank = 0; - s_heading = 0; + s_pitch = 0.f; + s_bank = 0.f; + s_heading = 0.f; s_scale = 1.0f; s_index = -1; - b_pitch = 0; - b_bank = 0; - b_heading = 0; + b_pitch = 0.f; + b_bank = 0.f; + b_heading = 0.f; b_scale_x = 1.0f; b_scale_y = 1.0f; b_div_x = 1; b_div_y = 1; b_index = -1; m_skybox_model = _T(""); - m_skybox_pitch = 0; - m_skybox_bank = 0; - m_skybox_heading = 0; + m_skybox_pitch = 0.f; + m_skybox_bank = 0.f; + m_skybox_heading = 0.f; m_sky_flag_1 = The_mission.skybox_flags & MR_NO_LIGHTING ? 1 : 0; m_sky_flag_2 = The_mission.skybox_flags & MR_ALL_XPARENT ? 1 : 0; m_sky_flag_3 = The_mission.skybox_flags & MR_NO_ZBUFFER ? 1 : 0; @@ -108,20 +108,20 @@ void bg_bitmap_dlg::DoDataExchange(CDataExchange* pDX) DDX_Check(pDX, IDC_NEB2_TOGGLE_TRAILS, m_toggle_trails); DDX_Text(pDX, IDC_SUN1, s_name); DDX_Text(pDX, IDC_SUN1_P, s_pitch); - DDV_MinMaxInt(pDX, s_pitch, 0, 359); + DDV_MinMaxFloat(pDX, s_pitch, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SUN1_B, s_bank); - DDV_MinMaxInt(pDX, s_bank, 0, 359); + DDV_MinMaxFloat(pDX, s_bank, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SUN1_H, s_heading); - DDV_MinMaxInt(pDX, s_heading, 0, 359); + DDV_MinMaxFloat(pDX, s_heading, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SUN1_SCALE, s_scale); DDV_MinMaxFloat(pDX, s_scale, 0.1f, 50.0f); DDX_Text(pDX, IDC_SBITMAP, b_name); DDX_Text(pDX, IDC_SBITMAP_P, b_pitch); - DDV_MinMaxInt(pDX, b_pitch, 0, 359); + DDV_MinMaxFloat(pDX, b_pitch, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SBITMAP_B, b_bank); - DDV_MinMaxInt(pDX, b_bank, 0, 359); + DDV_MinMaxFloat(pDX, b_bank, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SBITMAP_H, b_heading); - DDV_MinMaxInt(pDX, b_heading, 0, 359); + DDV_MinMaxFloat(pDX, b_heading, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SBITMAP_SCALE_X, b_scale_x); DDV_MinMaxFloat(pDX, b_scale_x, .001f, 18.0f); DDX_Text(pDX, IDC_SBITMAP_SCALE_Y, b_scale_y); @@ -132,11 +132,11 @@ void bg_bitmap_dlg::DoDataExchange(CDataExchange* pDX) DDV_MinMaxInt(pDX, b_div_y, 1, 5); DDX_Text(pDX, IDC_SKYBOX_FNAME, m_skybox_model); DDX_Text(pDX, IDC_SKYBOX_P, m_skybox_pitch); - DDV_MinMaxInt(pDX, m_skybox_pitch, 0, 359); + DDV_MinMaxFloat(pDX, m_skybox_pitch, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SKYBOX_B, m_skybox_bank); - DDV_MinMaxInt(pDX, m_skybox_bank, 0, 359); + DDV_MinMaxFloat(pDX, m_skybox_bank, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_SKYBOX_H, m_skybox_heading); - DDV_MinMaxInt(pDX, m_skybox_heading, 0, 359); + DDV_MinMaxFloat(pDX, m_skybox_heading, 0.f, DEGREE_UB); DDX_Text(pDX, IDC_ENVMAP, m_envmap); DDX_Check(pDX, IDC_SKY_FLAG_NO_LIGHTING, m_sky_flag_1); DDX_Check(pDX, IDC_SKY_FLAG_XPARENT, m_sky_flag_2); @@ -209,7 +209,6 @@ BEGIN_MESSAGE_MAP(bg_bitmap_dlg, CDialog) //}}AFX_MSG_MAP END_MESSAGE_MAP() -const static float delta = .00001f; ///////////////////////////////////////////////////////////////////////////// // bg_bitmap_dlg message handlers @@ -271,9 +270,9 @@ void bg_bitmap_dlg::create() angles skybox_angles; vm_extract_angles_matrix(&skybox_angles, &The_mission.skybox_orientation); - m_skybox_pitch = fl2ir(fl_degrees(skybox_angles.p)); - m_skybox_bank = fl2ir(fl_degrees(skybox_angles.b)); - m_skybox_heading = fl2ir(fl_degrees(skybox_angles.h)); + m_skybox_pitch = fl_degrees_100ths(skybox_angles.p); + m_skybox_bank = fl_degrees_100ths(skybox_angles.b); + m_skybox_heading = fl_degrees_100ths(skybox_angles.h); //make sure angle values are in the 0-359 degree range if (m_skybox_pitch < 0) m_skybox_pitch += 360; @@ -760,9 +759,9 @@ void bg_bitmap_dlg::sun_data_save_current() // store the data strcpy_s(sle->filename, s_name); - sle->ang.p = (float) fl_radians(s_pitch); - sle->ang.b = (float) fl_radians(s_bank); - sle->ang.h = (float) fl_radians(s_heading); + sle->ang.p = fl_radians(s_pitch); + sle->ang.b = fl_radians(s_bank); + sle->ang.h = fl_radians(s_heading); sle->scale_x = (float) s_scale; sle->scale_y = 1.0f; sle->div_x = 1; @@ -786,14 +785,14 @@ void bg_bitmap_dlg::OnSunChange() starfield_list_entry *sle = &background->suns[s_index]; s_name = CString(sle->filename); - s_pitch = fl2ir(fl_degrees(sle->ang.p) + delta); - s_bank = fl2ir(fl_degrees(sle->ang.b) + delta); - s_heading = fl2ir(fl_degrees(sle->ang.h) + delta); + s_pitch = fl_degrees_100ths(sle->ang.p); + s_bank = fl_degrees_100ths(sle->ang.b); + s_heading = fl_degrees_100ths(sle->ang.h); s_scale = sle->scale_x; // make sure angles are in the 0-359 degree range; // an angle of 6.28318310, which is less than 6.28318548, - // is converted to 359.999847, which is rounded to 360 + // is converted to 359.999847, which (if converted to int) is rounded to 360 if (s_pitch >= 360) s_pitch -= 360; if (s_bank >= 360) s_bank -= 360; if (s_heading >= 360) s_heading -= 360; @@ -931,9 +930,9 @@ void bg_bitmap_dlg::bitmap_data_save_current() // store the data strcpy_s(sle->filename, b_name); - sle->ang.p = (float) fl_radians(b_pitch); - sle->ang.b = (float) fl_radians(b_bank); - sle->ang.h = (float) fl_radians(b_heading); + sle->ang.p = fl_radians(b_pitch); + sle->ang.b = fl_radians(b_bank); + sle->ang.h = fl_radians(b_heading); sle->scale_x = (float) b_scale_x; sle->scale_y = (float) b_scale_y; sle->div_x = b_div_x; @@ -957,9 +956,9 @@ void bg_bitmap_dlg::OnBitmapChange() starfield_list_entry *sle = &background->bitmaps[b_index]; b_name = CString(sle->filename); - b_pitch = fl2ir(fl_degrees(sle->ang.p) + delta); - b_bank = fl2ir(fl_degrees(sle->ang.b) + delta); - b_heading = fl2ir(fl_degrees(sle->ang.h) + delta); + b_pitch = fl_degrees_100ths(sle->ang.p); + b_bank = fl_degrees_100ths(sle->ang.b); + b_heading = fl_degrees_100ths(sle->ang.h); b_scale_x = sle->scale_x; b_scale_y = sle->scale_y; b_div_x = sle->div_x; @@ -1053,37 +1052,44 @@ void bg_bitmap_dlg::OnBitmapDropdownChange() } } -void bg_bitmap_dlg::get_data_spinner(NM_UPDOWN* pUD, int id, int *var, int min, int max) +void bg_bitmap_dlg::get_data_spinner(NM_UPDOWN* pUD, int id, float *var, float min, float max) { + float old_val = *var; + if (pUD->iDelta > 0) { - (*var)--; + *var = std::floor(*var); + if (fl_equal(*var, old_val)) + (*var)--; //go min->max - if (*var == (min-1)) + if (*var < min) { - *var = max; + *var = std::floor(max); } - - this->SetDlgItemInt(id, *var); } - else + else { - (*var)++; + *var = std::ceil(*var); + if (fl_equal(*var, old_val)) + (*var)++; //go max->min - if (*var == (max+1)) + if (*var > max) { - *var=min; + *var = std::ceil(min); } - - this->SetDlgItemInt(id, *var); } -} + // there is no SetDlgItemFloat, so let's treat it as int + // (note, there will be no fractional part here, unless we later decide to use a fractional increment) + this->SetDlgItemInt(id, static_cast(*var)); +} -void bg_bitmap_dlg::get_data_float(int id, float *var, float min, float max) +void bg_bitmap_dlg::get_data_float(int id, float *var, float min, float max, int precision) { + Assertion(precision >= 1 && precision <= 3, "Precision must be between 1 and 3!"); + char buf[16]; char max_ch[16]; char min_ch[16]; @@ -1091,8 +1097,8 @@ void bg_bitmap_dlg::get_data_float(int id, float *var, float min, float max) this->GetDlgItemText(id, buf, 16); *var = (float)atof(buf); - sprintf(max_ch,"%.3f",max); - sprintf(min_ch,"%.3f",min); + sprintf(max_ch, "%.*f", precision, max); + sprintf(min_ch, "%.*f", precision, min); CString error_msg = "Please enter a number between "; error_msg += min_ch; error_msg += " and "; @@ -1148,7 +1154,7 @@ void bg_bitmap_dlg::OnDeltaposSbitmapPSpin(NMHDR* pNMHDR, LRESULT* pResult) NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; if (b_index < 0) return; - get_data_spinner(pNMUpDown, IDC_SBITMAP_P, &b_pitch, 0, 359); + get_data_spinner(pNMUpDown, IDC_SBITMAP_P, &b_pitch, 0.f, DEGREE_UB); OnBitmapChange(); *pResult = 0; } @@ -1158,7 +1164,7 @@ void bg_bitmap_dlg::OnDeltaposSbitmapBSpin(NMHDR* pNMHDR, LRESULT* pResult) NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; if (b_index < 0) return; - get_data_spinner(pNMUpDown, IDC_SBITMAP_B, &b_bank, 0, 359); + get_data_spinner(pNMUpDown, IDC_SBITMAP_B, &b_bank, 0.f, DEGREE_UB); OnBitmapChange(); *pResult = 0; } @@ -1168,7 +1174,7 @@ void bg_bitmap_dlg::OnDeltaposSbitmapHSpin(NMHDR* pNMHDR, LRESULT* pResult) NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; if (b_index < 0) return; - get_data_spinner(pNMUpDown, IDC_SBITMAP_H, &b_heading, 0, 359); + get_data_spinner(pNMUpDown, IDC_SBITMAP_H, &b_heading, 0.f, DEGREE_UB); OnBitmapChange(); *pResult = 0; } @@ -1176,14 +1182,14 @@ void bg_bitmap_dlg::OnDeltaposSbitmapHSpin(NMHDR* pNMHDR, LRESULT* pResult) void bg_bitmap_dlg::OnKillfocusSbitmapScaleX() { if (b_index < 0) return; - get_data_float(IDC_SBITMAP_SCALE_X, &b_scale_x, 0.001f, 18.0f); + get_data_float(IDC_SBITMAP_SCALE_X, &b_scale_x, 0.001f, 18.0f, 3); OnBitmapChange(); } void bg_bitmap_dlg::OnKillfocusSbitmapScaleY() { if (b_index < 0) return; - get_data_float(IDC_SBITMAP_SCALE_Y, &b_scale_y, 0.001f, 18.0f); + get_data_float(IDC_SBITMAP_SCALE_Y, &b_scale_y, 0.001f, 18.0f, 3); OnBitmapChange(); } @@ -1204,21 +1210,21 @@ void bg_bitmap_dlg::OnKillfocusSbitmapDivY() void bg_bitmap_dlg::OnKillfocusSbitmapP() { if (b_index < 0) return; - get_data_int(IDC_SBITMAP_P, &b_pitch, 0, 359); + get_data_float(IDC_SBITMAP_P, &b_pitch, 0.f, DEGREE_UB, 2); OnBitmapChange(); } void bg_bitmap_dlg::OnKillfocusSbitmapB() { if (b_index < 0) return; - get_data_int(IDC_SBITMAP_B, &b_bank, 0, 359); + get_data_float(IDC_SBITMAP_B, &b_bank, 0.f, DEGREE_UB, 2); OnBitmapChange(); } void bg_bitmap_dlg::OnKillfocusSbitmapH() { if (b_index < 0) return; - get_data_int(IDC_SBITMAP_H, &b_heading, 0, 359); + get_data_float(IDC_SBITMAP_H, &b_heading, 0.f, DEGREE_UB, 2); OnBitmapChange(); } @@ -1227,8 +1233,7 @@ void bg_bitmap_dlg::OnDeltaposSun1PSpin(NMHDR* pNMHDR, LRESULT* pResult) NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; if (s_index < 0) return; - //G5K - why? pNMUpDown->iDelta *= -1; - get_data_spinner(pNMUpDown, IDC_SUN1_P, &s_pitch, 0, 359); + get_data_spinner(pNMUpDown, IDC_SUN1_P, &s_pitch, 0.f, DEGREE_UB); OnSunChange(); *pResult = 0; } @@ -1238,8 +1243,7 @@ void bg_bitmap_dlg::OnDeltaposSun1BSpin(NMHDR* pNMHDR, LRESULT* pResult) NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; if (s_index < 0) return; - //G5K - why? pNMUpDown->iDelta *= -1; - get_data_spinner(pNMUpDown, IDC_SUN1_B, &s_bank, 0, 359); + get_data_spinner(pNMUpDown, IDC_SUN1_B, &s_bank, 0.f, DEGREE_UB); OnSunChange(); *pResult = 0; } @@ -1249,8 +1253,7 @@ void bg_bitmap_dlg::OnDeltaposSun1HSpin(NMHDR* pNMHDR, LRESULT* pResult) NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; if (s_index < 0) return; - //G5K - why? pNMUpDown->iDelta *= -1; - get_data_spinner(pNMUpDown, IDC_SUN1_H, &s_heading, 0, 359); + get_data_spinner(pNMUpDown, IDC_SUN1_H, &s_heading, 0.f, DEGREE_UB); OnSunChange(); *pResult = 0; } @@ -1258,28 +1261,28 @@ void bg_bitmap_dlg::OnDeltaposSun1HSpin(NMHDR* pNMHDR, LRESULT* pResult) void bg_bitmap_dlg::OnKillfocusSun1P() { if (s_index < 0) return; - get_data_int(IDC_SUN1_P, &s_pitch, 0, 359); + get_data_float(IDC_SUN1_P, &s_pitch, 0.f, DEGREE_UB, 2); OnSunChange(); } void bg_bitmap_dlg::OnKillfocusSun1H() { if (s_index < 0) return; - get_data_int(IDC_SUN1_H, &s_heading, 0, 359); + get_data_float(IDC_SUN1_H, &s_heading, 0.f, DEGREE_UB, 2); OnSunChange(); } void bg_bitmap_dlg::OnKillfocusSun1B() { if (s_index < 0) return; - get_data_int(IDC_SUN1_B, &s_bank, 0, 359); + get_data_float(IDC_SUN1_B, &s_bank, 0.f, DEGREE_UB, 2); OnSunChange(); } void bg_bitmap_dlg::OnKillfocusSun1Scale() { if (s_index < 0) return; - get_data_float(IDC_SUN1_SCALE, &s_scale, 0.1f, 50.0f); + get_data_float(IDC_SUN1_SCALE, &s_scale, 0.1f, 50.0f, 3); OnSunChange(); } @@ -1287,7 +1290,7 @@ void bg_bitmap_dlg::OnDeltaposSkyboxPSpin(NMHDR* pNMHDR, LRESULT* pResult) { NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; - get_data_spinner(pNMUpDown, IDC_SKYBOX_P, &m_skybox_pitch, 0, 359); + get_data_spinner(pNMUpDown, IDC_SKYBOX_P, &m_skybox_pitch, 0.f, DEGREE_UB); OnOrientationChange(); *pResult = 0; } @@ -1296,7 +1299,7 @@ void bg_bitmap_dlg::OnDeltaposSkyboxBSpin(NMHDR* pNMHDR, LRESULT* pResult) { NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; - get_data_spinner(pNMUpDown, IDC_SKYBOX_B, &m_skybox_bank, 0, 359); + get_data_spinner(pNMUpDown, IDC_SKYBOX_B, &m_skybox_bank, 0.f, DEGREE_UB); OnOrientationChange(); *pResult = 0; } @@ -1305,26 +1308,26 @@ void bg_bitmap_dlg::OnDeltaposSkyboxHSpin(NMHDR* pNMHDR, LRESULT* pResult) { NM_UPDOWN* pNMUpDown = (NM_UPDOWN*)pNMHDR; - get_data_spinner(pNMUpDown, IDC_SKYBOX_H, &m_skybox_heading, 0, 359); + get_data_spinner(pNMUpDown, IDC_SKYBOX_H, &m_skybox_heading, 0.f, DEGREE_UB); OnOrientationChange(); *pResult = 0; } void bg_bitmap_dlg::OnKillfocusSkyboxP() { - get_data_int(IDC_SKYBOX_P, &m_skybox_pitch, 0, 359); + get_data_float(IDC_SKYBOX_P, &m_skybox_pitch, 0.f, DEGREE_UB, 2); OnOrientationChange(); } void bg_bitmap_dlg::OnKillfocusSkyboxB() { - get_data_int(IDC_SKYBOX_B, &m_skybox_bank, 0, 359); + get_data_float(IDC_SKYBOX_B, &m_skybox_bank, 0.f, DEGREE_UB, 2); OnOrientationChange(); } void bg_bitmap_dlg::OnKillfocusSkyboxH() { - get_data_int(IDC_SKYBOX_H, &m_skybox_heading, 0, 359); + get_data_float(IDC_SKYBOX_H, &m_skybox_heading, 0.f, DEGREE_UB, 2); OnOrientationChange(); } diff --git a/fred2/bgbitmapdlg.h b/fred2/bgbitmapdlg.h index 4049aafc563..9f69b2cdb19 100644 --- a/fred2/bgbitmapdlg.h +++ b/fred2/bgbitmapdlg.h @@ -33,9 +33,9 @@ class bg_bitmap_dlg : public CDialog void bitmap_data_close(); void bitmap_data_save_current(); - void get_data_spinner(NM_UPDOWN* pUD, int id, int *var, int min, int max); + void get_data_spinner(NM_UPDOWN* pUD, int id, float *var, float min, float max); void get_data_int(int id, int *var, int min, int max); - void get_data_float(int id, float *var, float max, float min); + void get_data_float(int id, float *var, float min, float max, int precision); afx_msg void OnClose(); @@ -66,15 +66,15 @@ class bg_bitmap_dlg : public CDialog int m_fog_b; CString m_storm_name; CString s_name; - int s_pitch; - int s_bank; - int s_heading; + float s_pitch; + float s_bank; + float s_heading; float s_scale; int s_index; CString b_name; - int b_pitch; - int b_bank; - int b_heading; + float b_pitch; + float b_bank; + float b_heading; float b_scale_x; float b_scale_y; int b_div_x; @@ -88,9 +88,9 @@ class bg_bitmap_dlg : public CDialog int m_sky_flag_6; CString m_skybox_model; CString m_envmap; - int m_skybox_pitch; - int m_skybox_bank; - int m_skybox_heading; + float m_skybox_pitch; + float m_skybox_bank; + float m_skybox_heading; float m_neb_near_multi; float m_neb_far_multi; int m_light_profile_index; diff --git a/fred2/fred.rc b/fred2/fred.rc index a548547acf6..3d198b2f171 100644 --- a/fred2/fred.rc +++ b/fred2/fred.rc @@ -1461,12 +1461,12 @@ BEGIN PUSHBUTTON "Add",IDC_ADD_SBITMAP,14,147,41,14 PUSHBUTTON "Delete",IDC_DEL_SBITMAP,76,147,40,14 COMBOBOX IDC_SBITMAP,123,37,83,265,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - EDITTEXT IDC_SBITMAP_P,135,58,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin4",IDC_SBITMAP_P_SPIN,"msctls_updown32",UDS_ARROWKEYS,160,58,11,14 - EDITTEXT IDC_SBITMAP_B,135,74,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin3",IDC_SBITMAP_B_SPIN,"msctls_updown32",UDS_ARROWKEYS,160,74,11,14 - EDITTEXT IDC_SBITMAP_H,135,90,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin2",IDC_SBITMAP_H_SPIN,"msctls_updown32",UDS_ARROWKEYS,160,90,11,14 + EDITTEXT IDC_SBITMAP_P,135,58,31,14,ES_AUTOHSCROLL + CONTROL "Spin4",IDC_SBITMAP_P_SPIN,"msctls_updown32",UDS_ARROWKEYS,168,58,11,14 + EDITTEXT IDC_SBITMAP_B,135,74,31,14,ES_AUTOHSCROLL + CONTROL "Spin3",IDC_SBITMAP_B_SPIN,"msctls_updown32",UDS_ARROWKEYS,168,74,11,14 + EDITTEXT IDC_SBITMAP_H,135,90,31,14,ES_AUTOHSCROLL + CONTROL "Spin2",IDC_SBITMAP_H_SPIN,"msctls_updown32",UDS_ARROWKEYS,168,90,11,14 EDITTEXT IDC_SBITMAP_SCALE_X,127,120,36,14,ES_AUTOHSCROLL EDITTEXT IDC_SBITMAP_SCALE_Y,165,120,40,14,ES_AUTOHSCROLL EDITTEXT IDC_SBITMAP_DIV_X,127,148,36,14,ES_AUTOHSCROLL | ES_NUMBER @@ -1475,13 +1475,13 @@ BEGIN PUSHBUTTON "Add",IDC_ADD_SUN,229,127,41,14 PUSHBUTTON "Delete",IDC_DEL_SUN,295,127,40,14 COMBOBOX IDC_SUN1,338,36,71,265,CBS_DROPDOWNLIST | CBS_SORT | WS_VSCROLL | WS_TABSTOP - EDITTEXT IDC_SUN1_P,349,56,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin4",IDC_SUN1_P_SPIN,"msctls_updown32",UDS_ARROWKEYS,373,56,11,14 - EDITTEXT IDC_SUN1_B,349,71,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin3",IDC_SUN1_B_SPIN,"msctls_updown32",UDS_ARROWKEYS,373,71,11,14 - EDITTEXT IDC_SUN1_H,349,87,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "Spin2",IDC_SUN1_H_SPIN,"msctls_updown32",UDS_ARROWKEYS,373,87,11,14 - EDITTEXT IDC_SUN1_SCALE,362,105,23,14,ES_AUTOHSCROLL + EDITTEXT IDC_SUN1_P,349,56,31,14,ES_AUTOHSCROLL + CONTROL "Spin4",IDC_SUN1_P_SPIN,"msctls_updown32",UDS_ARROWKEYS,381,56,11,14 + EDITTEXT IDC_SUN1_B,349,71,31,14,ES_AUTOHSCROLL + CONTROL "Spin3",IDC_SUN1_B_SPIN,"msctls_updown32",UDS_ARROWKEYS,381,71,11,14 + EDITTEXT IDC_SUN1_H,349,87,31,14,ES_AUTOHSCROLL + CONTROL "Spin2",IDC_SUN1_H_SPIN,"msctls_updown32",UDS_ARROWKEYS,381,87,11,14 + EDITTEXT IDC_SUN1_SCALE,362,105,31,14,ES_AUTOHSCROLL CONTROL "Full Nebula",IDC_FULLNEB,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,14,186,62,10 EDITTEXT IDC_NEB2_INTENSITY,68,201,63,12,ES_AUTOHSCROLL COMBOBOX IDC_NEB2_TEXTURE,68,217,63,88,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP @@ -1546,15 +1546,15 @@ BEGIN EDITTEXT IDC_NEB2_FAR_MULTIPLIER,53,279,25,14,ES_AUTOHSCROLL CONTROL "No Glowmaps",IDC_SKY_FLAG_NO_GLOW,"Button",BS_AUTOCHECKBOX | WS_TABSTOP,351,290,60,10 GROUPBOX "Skybox",IDC_STATIC,220,219,206,91 - EDITTEXT IDC_SKYBOX_P,237,253,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKYBOX_P_SPIN,"msctls_updown32",UDS_ARROWKEYS,262,253,11,14 - EDITTEXT IDC_SKYBOX_B,295,253,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKYBOX_B_SPIN,"msctls_updown32",UDS_ARROWKEYS,320,253,11,14 - EDITTEXT IDC_SKYBOX_H,351,252,23,14,ES_AUTOHSCROLL | ES_NUMBER - CONTROL "",IDC_SKYBOX_H_SPIN,"msctls_updown32",UDS_ARROWKEYS,376,252,11,14 + EDITTEXT IDC_SKYBOX_P,237,253,31,14,ES_AUTOHSCROLL + CONTROL "",IDC_SKYBOX_P_SPIN,"msctls_updown32",UDS_ARROWKEYS,270,253,11,14 + EDITTEXT IDC_SKYBOX_B,303,253,31,14,ES_AUTOHSCROLL + CONTROL "",IDC_SKYBOX_B_SPIN,"msctls_updown32",UDS_ARROWKEYS,336,253,11,14 + EDITTEXT IDC_SKYBOX_H,367,252,31,14,ES_AUTOHSCROLL + CONTROL "",IDC_SKYBOX_H_SPIN,"msctls_updown32",UDS_ARROWKEYS,400,252,11,14 LTEXT "P",IDC_STATIC,227,256,8,8 - LTEXT "B",IDC_STATIC,285,256,8,8 - LTEXT "H",IDC_STATIC,341,255,8,8 + LTEXT "B",IDC_STATIC,293,256,8,8 + LTEXT "H",IDC_STATIC,357,255,8,8 GROUPBOX "Old Nebula",IDC_STATIC,5,306,210,64 LISTBOX IDC_NEB2_POOF_LIST,142,190,67,54,LBS_EXTENDEDSEL | LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP CONTROL "Display bg bitmaps in nebula",IDC_NEB2_BACKGROUND_BITMAPS, diff --git a/qtfred/source_groups.cmake b/qtfred/source_groups.cmake index 4e5706d6e5e..a67167de20e 100644 --- a/qtfred/source_groups.cmake +++ b/qtfred/source_groups.cmake @@ -248,20 +248,26 @@ add_file_folder("Source/UI/Util" ) add_file_folder("Source/UI/Widgets" - src/ui/widgets/CampaignMissionGraph.cpp + src/ui/widgets/bankTree.cpp + src/ui/widgets/bankTree.h + src/ui/widgets/CampaignMissionGraph.cpp src/ui/widgets/CampaignMissionGraph.h - src/ui/widgets/ColorComboBox.cpp - src/ui/widgets/ColorComboBox.h - src/ui/widgets/LineEditDelegate.cpp - src/ui/widgets/LineEditDelegate.h + src/ui/widgets/ColorComboBox.cpp + src/ui/widgets/ColorComboBox.h src/ui/widgets/FlagList.cpp src/ui/widgets/FlagList.h + src/ui/widgets/IntegerSnapDoubleSpinBox.cpp + src/ui/widgets/IntegerSnapDoubleSpinBox.h + src/ui/widgets/LineEditDelegate.cpp + src/ui/widgets/LineEditDelegate.h src/ui/widgets/NoWheelComboBox.cpp src/ui/widgets/NoWheelComboBox.h src/ui/widgets/NoWheelSpinBox.cpp src/ui/widgets/NoWheelSpinBox.h - src/ui/widgets/renderwidget.cpp - src/ui/widgets/renderwidget.h + src/ui/widgets/PersonaColorComboBox.cpp + src/ui/widgets/PersonaColorComboBox.h + src/ui/widgets/renderwidget.cpp + src/ui/widgets/renderwidget.h src/ui/widgets/sexp_tree.cpp src/ui/widgets/sexp_tree.h src/ui/widgets/ShipFlagCheckbox.h @@ -270,10 +276,6 @@ add_file_folder("Source/UI/Widgets" src/ui/widgets/SimpleListSelectDialog.h src/ui/widgets/weaponList.cpp src/ui/widgets/weaponList.h - src/ui/widgets/bankTree.cpp - src/ui/widgets/bankTree.h - src/ui/widgets/PersonaColorComboBox.cpp - src/ui/widgets/PersonaColorComboBox.h ) add_file_folder("UI" diff --git a/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.cpp b/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.cpp index eb9739258c4..b6044c56f56 100644 --- a/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.cpp +++ b/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.cpp @@ -10,7 +10,6 @@ #include "lighting/lighting_profiles.h" // TODO move this to common for both FREDs. -const static float delta = .00001f; const static float default_nebula_range = 3000.0f; extern void parse_one_background(background_t* background); @@ -404,64 +403,64 @@ void BackgroundEditorDialogModel::setBitmapName(const SCP_string& name) } } -int BackgroundEditorDialogModel::getBitmapPitch() const +float BackgroundEditorDialogModel::getBitmapPitch() const { auto* bm = getActiveBitmap(); if (!bm) return 0; - return fl2ir(fl_degrees(bm->ang.p) + delta); + return fl_degrees_100ths(bm->ang.p); } -void BackgroundEditorDialogModel::setBitmapPitch(int deg) +void BackgroundEditorDialogModel::setBitmapPitch(float deg) { auto* bm = getActiveBitmap(); if (!bm) return; - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); modify(bm->ang.p, fl_radians(deg)); refreshBackgroundPreview(); } -int BackgroundEditorDialogModel::getBitmapBank() const +float BackgroundEditorDialogModel::getBitmapBank() const { auto* bm = getActiveBitmap(); if (!bm) return 0; - return fl2ir(fl_degrees(bm->ang.b) + delta); + return fl_degrees_100ths(bm->ang.b); } -void BackgroundEditorDialogModel::setBitmapBank(int deg) +void BackgroundEditorDialogModel::setBitmapBank(float deg) { auto* bm = getActiveBitmap(); if (!bm) return; - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); modify(bm->ang.b, fl_radians(deg)); refreshBackgroundPreview(); } -int BackgroundEditorDialogModel::getBitmapHeading() const +float BackgroundEditorDialogModel::getBitmapHeading() const { auto* bm = getActiveBitmap(); if (!bm) return 0; - return fl2ir(fl_degrees(bm->ang.h) + delta); + return fl_degrees_100ths(bm->ang.h); } -void BackgroundEditorDialogModel::setBitmapHeading(int deg) +void BackgroundEditorDialogModel::setBitmapHeading(float deg) { auto* bm = getActiveBitmap(); if (!bm) return; - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); modify(bm->ang.h, fl_radians(deg)); refreshBackgroundPreview(); @@ -655,42 +654,42 @@ void BackgroundEditorDialogModel::setSunName(const SCP_string& name) refreshBackgroundPreview(); } -int BackgroundEditorDialogModel::getSunPitch() const +float BackgroundEditorDialogModel::getSunPitch() const { auto* s = getActiveSun(); if (!s) return 0; - return fl2ir(fl_degrees(s->ang.p) + delta); + return fl_degrees_100ths(s->ang.p); } -void BackgroundEditorDialogModel::setSunPitch(int deg) +void BackgroundEditorDialogModel::setSunPitch(float deg) { auto* s = getActiveSun(); if (!s) return; - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); modify(s->ang.p, fl_radians(deg)); refreshBackgroundPreview(); } -int BackgroundEditorDialogModel::getSunHeading() const +float BackgroundEditorDialogModel::getSunHeading() const { auto* s = getActiveSun(); if (!s) return 0; - return fl2ir(fl_degrees(s->ang.h) + delta); + return fl_degrees_100ths(s->ang.h); } -void BackgroundEditorDialogModel::setSunHeading(int deg) +void BackgroundEditorDialogModel::setSunHeading(float deg) { auto* s = getActiveSun(); if (!s) return; - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); modify(s->ang.h, fl_radians(deg)); refreshBackgroundPreview(); } @@ -1012,7 +1011,7 @@ int BackgroundEditorDialogModel::getOldNebulaPitch() void BackgroundEditorDialogModel::setOldNebulaPitch(int deg) { - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getIntOrientLimit().first, getIntOrientLimit().second); if (Nebula_pitch != deg) { Nebula_pitch = deg; modify(Nebula_pitch, deg); @@ -1026,7 +1025,7 @@ int BackgroundEditorDialogModel::getOldNebulaBank() void BackgroundEditorDialogModel::setOldNebulaBank(int deg) { - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getIntOrientLimit().first, getIntOrientLimit().second); if (Nebula_bank != deg) { Nebula_bank = deg; modify(Nebula_bank, deg); @@ -1040,7 +1039,7 @@ int BackgroundEditorDialogModel::getOldNebulaHeading() void BackgroundEditorDialogModel::setOldNebulaHeading(int deg) { - CLAMP(deg, getOrientLimit().first, getOrientLimit().second); + CLAMP(deg, getIntOrientLimit().first, getIntOrientLimit().second); if (Nebula_heading != deg) { Nebula_heading = deg; modify(Nebula_heading, deg); @@ -1213,22 +1212,21 @@ void BackgroundEditorDialogModel::setSkyboxForceClamp(bool on) set_modified(); } -int BackgroundEditorDialogModel::getSkyboxPitch() +float BackgroundEditorDialogModel::getSkyboxPitch() { angles a; vm_extract_angles_matrix(&a, &The_mission.skybox_orientation); - int d = static_cast(fl2ir(fl_degrees(a.p))); - d = (d % 360 + 360) % 360; // wrap to [0, 359] - return d; + return fl_degrees_100ths(a.p); } -void BackgroundEditorDialogModel::setSkyboxPitch(int deg) +void BackgroundEditorDialogModel::setSkyboxPitch(float deg) { - CLAMP(deg, 0, 359); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); + const float deg_100ths = fl2ir(deg * 100.0f) / 100.0f; angles a; vm_extract_angles_matrix(&a, &The_mission.skybox_orientation); - const int cur = static_cast(fl2ir(fl_degrees(a.p))); - if (cur != deg) { + const float cur = fl_degrees_100ths(a.p); + if (!fl_equal(cur, deg_100ths)) { a.p = fl_radians(static_cast(deg)); vm_angles_2_matrix(&The_mission.skybox_orientation, &a); set_modified(); @@ -1236,22 +1234,21 @@ void BackgroundEditorDialogModel::setSkyboxPitch(int deg) } } -int BackgroundEditorDialogModel::getSkyboxBank() +float BackgroundEditorDialogModel::getSkyboxBank() { angles a; vm_extract_angles_matrix(&a, &The_mission.skybox_orientation); - int d = static_cast(fl2ir(fl_degrees(a.b))); - d = (d % 360 + 360) % 360; // wrap to [0, 359] - return d; + return fl_degrees_100ths(a.b); } -void BackgroundEditorDialogModel::setSkyboxBank(int deg) +void BackgroundEditorDialogModel::setSkyboxBank(float deg) { - CLAMP(deg, 0, 359); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); + const float deg_100ths = fl2ir(deg * 100.0f) / 100.0f; angles a; vm_extract_angles_matrix(&a, &The_mission.skybox_orientation); - const int cur = static_cast(fl2ir(fl_degrees(a.b))); - if (cur != deg) { + const float cur = fl_degrees_100ths(a.b); + if (!fl_equal(cur, deg_100ths)) { a.b = fl_radians(static_cast(deg)); vm_angles_2_matrix(&The_mission.skybox_orientation, &a); set_modified(); @@ -1259,22 +1256,21 @@ void BackgroundEditorDialogModel::setSkyboxBank(int deg) } } -int BackgroundEditorDialogModel::getSkyboxHeading() +float BackgroundEditorDialogModel::getSkyboxHeading() { angles a; vm_extract_angles_matrix(&a, &The_mission.skybox_orientation); - int d = static_cast(fl2ir(fl_degrees(a.h))); - d = (d % 360 + 360) % 360; // wrap to [0, 359] - return d; + return fl_degrees_100ths(a.h); } -void BackgroundEditorDialogModel::setSkyboxHeading(int deg) +void BackgroundEditorDialogModel::setSkyboxHeading(float deg) { - CLAMP(deg, 0, 359); + CLAMP(deg, getFloatOrientLimit().first, getFloatOrientLimit().second); + const float deg_100ths = fl2ir(deg * 100.0f) / 100.0f; angles a; vm_extract_angles_matrix(&a, &The_mission.skybox_orientation); - const int cur = static_cast(fl2ir(fl_degrees(a.h))); - if (cur != deg) { + const float cur = fl_degrees_100ths(a.h); + if (!fl_equal(cur, deg_100ths)) { a.h = fl_radians(static_cast(deg)); vm_angles_2_matrix(&The_mission.skybox_orientation, &a); set_modified(); diff --git a/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.h b/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.h index 8d450ae654b..24308687863 100644 --- a/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.h +++ b/qtfred/src/mission/dialogs/BackgroundEditorDialogModel.h @@ -22,7 +22,8 @@ class BackgroundEditorDialogModel : public AbstractDialogModel { void reject() override; // limits - static std::pair getOrientLimit() { return {0, 359}; } + static std::pair getIntOrientLimit() { return {0, 359}; } + static std::pair getFloatOrientLimit() { return {0.f, DEGREE_UB}; } static std::pair getBitmapScaleLimit() { return {0.001f, 18.0f}; } static std::pair getSunScaleLimit() { return {0.1f, 50.0f}; } static std::pair getDivisionLimit() { return {1, 5}; } @@ -51,12 +52,12 @@ class BackgroundEditorDialogModel : public AbstractDialogModel { void removeMissionBitmap(); SCP_string getBitmapName() const; void setBitmapName(const SCP_string& name); - int getBitmapPitch() const; - void setBitmapPitch(int deg); - int getBitmapBank() const; - void setBitmapBank(int deg); - int getBitmapHeading() const; - void setBitmapHeading(int deg); + float getBitmapPitch() const; + void setBitmapPitch(float deg); + float getBitmapBank() const; + void setBitmapBank(float deg); + float getBitmapHeading() const; + void setBitmapHeading(float deg); float getBitmapScaleX() const; void setBitmapScaleX(float v); float getBitmapScaleY() const; @@ -75,10 +76,10 @@ class BackgroundEditorDialogModel : public AbstractDialogModel { void removeMissionSun(); SCP_string getSunName() const; void setSunName(const SCP_string& name); - int getSunPitch() const; - void setSunPitch(int deg); - int getSunHeading() const; - void setSunHeading(int deg); + float getSunPitch() const; + void setSunPitch(float deg); + float getSunHeading() const; + void setSunHeading(float deg); float getSunScale() const; // uses scale_x for both x and y void setSunScale(float v); @@ -150,12 +151,12 @@ class BackgroundEditorDialogModel : public AbstractDialogModel { void setSkyboxNoGlowmaps(bool on); static bool getSkyboxForceClamp(); void setSkyboxForceClamp(bool on); - static int getSkyboxPitch(); - void setSkyboxPitch(int deg); - static int getSkyboxBank(); - void setSkyboxBank(int deg); - static int getSkyboxHeading(); - void setSkyboxHeading(int deg); + static float getSkyboxPitch(); + void setSkyboxPitch(float deg); + static float getSkyboxBank(); + void setSkyboxBank(float deg); + static float getSkyboxHeading(); + void setSkyboxHeading(float deg); // misc group static SCP_vector getLightingProfileOptions(); diff --git a/qtfred/src/ui/dialogs/BackgroundEditorDialog.cpp b/qtfred/src/ui/dialogs/BackgroundEditorDialog.cpp index 74c890af53c..4ffd97227e5 100644 --- a/qtfred/src/ui/dialogs/BackgroundEditorDialog.cpp +++ b/qtfred/src/ui/dialogs/BackgroundEditorDialog.cpp @@ -33,16 +33,16 @@ void BackgroundEditorDialog::initializeUi() updateBackgroundControls(); // Bitmaps - ui->bitmapPitchSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); - ui->bitmapBankSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); - ui->bitmapHeadingSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); + ui->bitmapPitchSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); + ui->bitmapBankSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); + ui->bitmapHeadingSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); ui->bitmapScaleXDoubleSpinBox->setRange(_model->getBitmapScaleLimit().first, _model->getBitmapScaleLimit().second); ui->bitmapScaleYDoubleSpinBox->setRange(_model->getBitmapScaleLimit().first, _model->getBitmapScaleLimit().second); ui->bitmapDivXSpinBox->setRange(_model->getDivisionLimit().first, _model->getDivisionLimit().second); ui->bitmapDivYSpinBox->setRange(_model->getDivisionLimit().first, _model->getDivisionLimit().second); - ui->skyboxPitchSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); - ui->skyboxBankSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); - ui->skyboxHeadingSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); + ui->skyboxPitchSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); + ui->skyboxBankSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); + ui->skyboxHeadingSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); const auto& names = _model->getAvailableBitmapNames(); @@ -53,8 +53,8 @@ void BackgroundEditorDialog::initializeUi() refreshBitmapList(); // Suns - ui->sunPitchSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); - ui->sunHeadingSpin->setRange(_model->getOrientLimit().first, _model->getOrientLimit().second); + ui->sunPitchSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); + ui->sunHeadingSpin->setRange(_model->getFloatOrientLimit().first, _model->getFloatOrientLimit().second); ui->sunScaleDoubleSpinBox->setRange(_model->getSunScaleLimit().first, _model->getSunScaleLimit().second); const auto& sun_names = _model->getAvailableSunNames(); @@ -493,19 +493,19 @@ void BackgroundEditorDialog::on_bitmapTypeCombo_currentIndexChanged(int index) refreshBitmapList(); } -void BackgroundEditorDialog::on_bitmapPitchSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_bitmapPitchSpin_valueChanged(double arg1) { - _model->setBitmapPitch(arg1); + _model->setBitmapPitch(static_cast(arg1)); } -void BackgroundEditorDialog::on_bitmapBankSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_bitmapBankSpin_valueChanged(double arg1) { - _model->setBitmapBank(arg1); + _model->setBitmapBank(static_cast(arg1)); } -void BackgroundEditorDialog::on_bitmapHeadingSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_bitmapHeadingSpin_valueChanged(double arg1) { - _model->setBitmapHeading(arg1); + _model->setBitmapHeading(static_cast(arg1)); } void BackgroundEditorDialog::on_bitmapScaleXDoubleSpinBox_valueChanged(double arg1) @@ -605,14 +605,14 @@ void BackgroundEditorDialog::on_sunSelectionCombo_currentIndexChanged(int index) refreshSunList(); } -void BackgroundEditorDialog::on_sunPitchSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_sunPitchSpin_valueChanged(double arg1) { - _model->setSunPitch(arg1); + _model->setSunPitch(static_cast(arg1)); } -void BackgroundEditorDialog::on_sunHeadingSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_sunHeadingSpin_valueChanged(double arg1) { - _model->setSunHeading(arg1); + _model->setSunHeading(static_cast(arg1)); } void BackgroundEditorDialog::on_sunScaleDoubleSpinBox_valueChanged(double arg1) @@ -864,19 +864,19 @@ void BackgroundEditorDialog::on_skyboxEdit_textChanged(const QString& arg1) updateSkyboxControls(); } -void BackgroundEditorDialog::on_skyboxPitchSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_skyboxPitchSpin_valueChanged(double arg1) { - _model->setSkyboxPitch(arg1); + _model->setSkyboxPitch(static_cast(arg1)); } -void BackgroundEditorDialog::on_skyboxBankSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_skyboxBankSpin_valueChanged(double arg1) { - _model->setSkyboxBank(arg1); + _model->setSkyboxBank(static_cast(arg1)); } -void BackgroundEditorDialog::on_skyboxHeadingSpin_valueChanged(int arg1) +void BackgroundEditorDialog::on_skyboxHeadingSpin_valueChanged(double arg1) { - _model->setSkyboxHeading(arg1); + _model->setSkyboxHeading(static_cast(arg1)); } void BackgroundEditorDialog::on_skyboxNoLightingCheckBox_toggled(bool checked) diff --git a/qtfred/src/ui/dialogs/BackgroundEditorDialog.h b/qtfred/src/ui/dialogs/BackgroundEditorDialog.h index 60a8d526fed..c1b3ef85929 100644 --- a/qtfred/src/ui/dialogs/BackgroundEditorDialog.h +++ b/qtfred/src/ui/dialogs/BackgroundEditorDialog.h @@ -32,9 +32,9 @@ private slots: // Bitmaps void on_bitmapListWidget_currentRowChanged(int row); void on_bitmapTypeCombo_currentIndexChanged(int index); - void on_bitmapPitchSpin_valueChanged(int arg1); - void on_bitmapBankSpin_valueChanged(int arg1); - void on_bitmapHeadingSpin_valueChanged(int arg1); + void on_bitmapPitchSpin_valueChanged(double arg1); + void on_bitmapBankSpin_valueChanged(double arg1); + void on_bitmapHeadingSpin_valueChanged(double arg1); void on_bitmapScaleXDoubleSpinBox_valueChanged(double arg1); void on_bitmapScaleYDoubleSpinBox_valueChanged(double arg1); void on_bitmapDivXSpinBox_valueChanged(int arg1); @@ -46,8 +46,8 @@ private slots: // Suns void on_sunListWidget_currentRowChanged(int row); void on_sunSelectionCombo_currentIndexChanged(int index); - void on_sunPitchSpin_valueChanged(int arg1); - void on_sunHeadingSpin_valueChanged(int arg1); + void on_sunPitchSpin_valueChanged(double arg1); + void on_sunHeadingSpin_valueChanged(double arg1); void on_sunScaleDoubleSpinBox_valueChanged(double arg1); void on_addSunButton_clicked(); void on_changeSunButton_clicked(); @@ -83,9 +83,9 @@ private slots: // Skybox void on_skyboxModelButton_clicked(); void on_skyboxEdit_textChanged(const QString& arg1); - void on_skyboxPitchSpin_valueChanged(int arg1); - void on_skyboxBankSpin_valueChanged(int arg1); - void on_skyboxHeadingSpin_valueChanged(int arg1); + void on_skyboxPitchSpin_valueChanged(double arg1); + void on_skyboxBankSpin_valueChanged(double arg1); + void on_skyboxHeadingSpin_valueChanged(double arg1); void on_skyboxNoLightingCheckBox_toggled(bool checked); void on_noLightingCheckBox_toggled(bool checked); void on_transparentCheckBox_toggled(bool checked); diff --git a/qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.cpp b/qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.cpp new file mode 100644 index 00000000000..1cb09149ff9 --- /dev/null +++ b/qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.cpp @@ -0,0 +1,63 @@ +#include "IntegerSnapDoubleSpinBox.h" + +#include +#include + +#include "math/floating.h" + +namespace fso::fred +{ + +IntegerSnapDoubleSpinBox::IntegerSnapDoubleSpinBox(QWidget* parent) : QDoubleSpinBox(parent) +{} + +void IntegerSnapDoubleSpinBox::stepBy(int steps) +{ + if (steps == 0) + return; + double old_val = value(); + + double new_val; + if (steps < 0) + { + new_val = std::floor(old_val); + if (fl_equal(new_val, old_val)) + new_val -= singleStep(); + + //go min->max + if (new_val < minimum()) + { + if (wrapping()) + new_val = std::floor(maximum()); + else + new_val = std::ceil(minimum()); + } + + ++steps; + } + else + { + new_val = std::ceil(old_val); + if (fl_equal(new_val, old_val)) + new_val += singleStep(); + + //go max->min + if (new_val > maximum()) + { + if (wrapping()) + new_val = std::ceil(minimum()); + else + new_val = std::floor(maximum()); + } + + --steps; + } + setValue(new_val); + + // we might have more steps + if (steps != 0) + QDoubleSpinBox::stepBy(steps); +} + +} // namespace fso::fred + diff --git a/qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.h b/qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.h new file mode 100644 index 00000000000..6f1df7c0074 --- /dev/null +++ b/qtfred/src/ui/widgets/IntegerSnapDoubleSpinBox.h @@ -0,0 +1,18 @@ +#pragma once +#include + +namespace fso::fred +{ + +class IntegerSnapDoubleSpinBox : public QDoubleSpinBox +{ + Q_OBJECT + + public: + explicit IntegerSnapDoubleSpinBox(QWidget* parent = nullptr); + + protected: + void stepBy(int steps) override; +}; + +} // namespace fso::fred diff --git a/qtfred/ui/BackgroundEditor.ui b/qtfred/ui/BackgroundEditor.ui index 7303acef3d6..e9e1d128ca5 100644 --- a/qtfred/ui/BackgroundEditor.ui +++ b/qtfred/ui/BackgroundEditor.ui @@ -147,12 +147,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -164,12 +167,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -181,12 +187,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -312,12 +321,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -329,12 +341,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -869,12 +884,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -886,12 +904,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -903,12 +924,15 @@ - + true - 16777215 + 16777215.000000000000000 + + + 1.000000000000000 @@ -1039,6 +1063,13 @@ + + + fso::fred::IntegerSnapDoubleSpinBox + QDoubleSpinBox +
ui/widgets/IntegerSnapDoubleSpinBox.h
+
+