add a Reorder Ships and Wings editor to FRED

Accessible from the Tools menu, this dialog lists all ships or all
wings (selectable via a drop-down) and provides Move to top/up/down/
bottom buttons.  Moves are applied immediately via the slot
reassignment utilities in missioneditor/common.h, using adjacent swaps
so the relative order of other entries is preserved.

Co-Authored-By: Claude Fable 5 <[email protected]>
This commit is contained in:
Goober5000andClaude Fable 5 committed 2026-07-20 23:15:16 -04:00
1 parent 175f414c03
commit 52763935c7
7 files changed
+261 -9

No files matched your search

+2
View File
@@ -105,6 +105,8 @@ set(FRED2_SOURCES
propdlg.h
reinforcementeditordlg.cpp
reinforcementeditordlg.h
reorderdlg.cpp
reorderdlg.h
resource.h
restrictpaths.cpp
restrictpaths.h
+23
View File
@@ -412,6 +412,7 @@ BEGIN
BEGIN
MENUITEM "&Voice Acting Manager", ID_EDITORS_VOICE
MENUITEM "Set Global Ship Flags", 33073
MENUITEM "Reorder Ships and Wings", ID_REORDER
MENUITEM "Calculate Relative Coordinates", 33030
MENUITEM "Music Player", ID_MUSIC_PLAYER
MENUITEM "Mission Statistics\tCtrl+Shift+D", 33067
@@ -2046,6 +2047,19 @@ BEGIN
EDITTEXT IDC_ORIENTATION_H,255,81,49,14,ES_READONLY
END
IDD_REORDER DIALOG 0, 0, 185, 191
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Reorder Ships and Wings"
FONT 8, "MS Sans Serif"
BEGIN
COMBOBOX IDC_REORDER_TYPE,7,7,98,114,CBS_DROPDOWNLIST | WS_VSCROLL | WS_TABSTOP
LISTBOX IDC_REORDER_LIST,7,25,98,159,LBS_NOINTEGRALHEIGHT | WS_VSCROLL | WS_TABSTOP
PUSHBUTTON "Move to top",IDC_REORDER_MOVE_TO_TOP,112,25,66,14
PUSHBUTTON "Move up",IDC_REORDER_MOVE_UP,112,43,66,14
PUSHBUTTON "Move down",IDC_REORDER_MOVE_DOWN,112,61,66,14
PUSHBUTTON "Move to bottom",IDC_REORDER_MOVE_TO_BOTTOM,112,79,66,14
END
IDD_SHIELD_SYS DIALOG 0, 0, 192, 106
STYLE DS_SETFONT | DS_MODALFRAME | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Shield System Editor"
@@ -2945,6 +2959,14 @@ BEGIN
BOTTOMMARGIN, 87
END
IDD_REORDER, DIALOG
BEGIN
LEFTMARGIN, 7
RIGHTMARGIN, 178
TOPMARGIN, 7
BOTTOMMARGIN, 184
END
IDD_SHIELD_SYS, DIALOG
BEGIN
LEFTMARGIN, 7
@@ -3815,6 +3837,7 @@ END
STRINGTABLE
BEGIN
ID_CALC_RELATIVE_COORDS "Calculate orientation and distance relative to an origin object"
ID_REORDER "Change the order in which ships and wings are stored in the mission"
ID_EDITORS_ADJUST_GRID "Adjust the orientation and level of the grid"
ID_EDITORS_SHIELD_SYS "Editor for availability of shield system for ships"
ID_ALIGN_OBJ "Align object (or camera if no objects are marked) X/Y/Z axes with the global axes that are closest"
+9
View File
@@ -62,6 +62,7 @@
#include "sound/audiostr.h"
#include "mission/missiongrid.h"
#include "calcrelativecoordsdlg.h"
#include "reorderdlg.h"
#include "musicplayerdlg.h"
#include "volumetricsdlg.h"
#include "customdatadlg.h"
@@ -342,6 +343,7 @@ BEGIN_MESSAGE_MAP(CFREDView, CView)
ON_UPDATE_COMMAND_UI(ID_LOOKAT_OBJ, OnUpdateLookatObj)
ON_COMMAND(ID_EDITORS_ADJUST_GRID, OnEditorsAdjustGrid)
ON_COMMAND(ID_CALC_RELATIVE_COORDS, OnCalcRelativeCoords)
ON_COMMAND(ID_REORDER, OnReorder)
ON_COMMAND(ID_MUSIC_PLAYER, OnMusicPlayer)
ON_COMMAND(ID_EDITORS_SHIELD_SYS, OnEditorsShieldSys)
ON_COMMAND(ID_LEVEL_OBJ, OnLevelObj)
@@ -4480,6 +4482,13 @@ void CFREDView::OnCalcRelativeCoords()
dlg.DoModal();
}
void CFREDView::OnReorder()
{
reorder_dlg dlg;
dlg.DoModal();
}
void CFREDView::OnMusicPlayer()
{
Assertion(Music_player_dialog.GetSafeHwnd(), "Unable to create music player window!");
+1
View File
@@ -301,6 +301,7 @@ protected:
afx_msg void OnUpdateLookatObj(CCmdUI* pCmdUI);
afx_msg void OnEditorsAdjustGrid();
afx_msg void OnCalcRelativeCoords();
afx_msg void OnReorder();
afx_msg void OnMusicPlayer();
afx_msg void OnEditorsShieldSys();
afx_msg void OnLevelObj();
+176
View File
@@ -0,0 +1,176 @@
// reorderdlg.cpp : implementation file
//
#include "stdafx.h"
#include "FRED.h"
#include "freddoc.h"
#include "management.h"
#include "reorderdlg.h"
#include "missioneditor/common.h"
#include "ship/ship.h"
#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[] = __FILE__;
#endif
reorder_dlg::reorder_dlg(CWnd *pParent /*=nullptr*/)
: CDialog(reorder_dlg::IDD, pParent)
{
//{{AFX_DATA_INIT(reorder_dlg)
//}}AFX_DATA_INIT
}
void reorder_dlg::DoDataExchange(CDataExchange *pDX)
{
CDialog::DoDataExchange(pDX);
//{{AFX_DATA_MAP(reorder_dlg)
DDX_Control(pDX, IDC_REORDER_TYPE, m_type_combo);
DDX_Control(pDX, IDC_REORDER_LIST, m_list);
//}}AFX_DATA_MAP
}
BEGIN_MESSAGE_MAP(reorder_dlg, CDialog)
//{{AFX_MSG_MAP(reorder_dlg)
ON_CBN_SELCHANGE(IDC_REORDER_TYPE, OnSelchangeReorderType)
ON_LBN_SELCHANGE(IDC_REORDER_LIST, OnSelchangeReorderList)
ON_BN_CLICKED(IDC_REORDER_MOVE_TO_TOP, OnMoveToTop)
ON_BN_CLICKED(IDC_REORDER_MOVE_UP, OnMoveUp)
ON_BN_CLICKED(IDC_REORDER_MOVE_DOWN, OnMoveDown)
ON_BN_CLICKED(IDC_REORDER_MOVE_TO_BOTTOM, OnMoveToBottom)
//}}AFX_MSG_MAP
END_MESSAGE_MAP()
BOOL reorder_dlg::OnInitDialog()
{
CDialog::OnInitDialog();
m_type_combo.AddString("Ships");
m_type_combo.AddString("Wings");
m_type_combo.SetCurSel(0);
populate_list();
update_buttons();
return TRUE;
}
bool reorder_dlg::ships_selected() const
{
return m_type_combo.GetCurSel() == 0;
}
void reorder_dlg::populate_list()
{
m_list.ResetContent();
m_slots.clear();
if (ships_selected())
{
for (int i = 0; i < MAX_SHIPS; ++i)
{
if (Ships[i].objnum >= 0)
{
m_list.AddString(Ships[i].ship_name);
m_slots.push_back(i);
}
}
}
else
{
for (int i = 0; i < MAX_WINGS; ++i)
{
if (Wings[i].wave_count > 0)
{
m_list.AddString(Wings[i].name);
m_slots.push_back(i);
}
}
}
}
void reorder_dlg::update_buttons()
{
int pos = m_list.GetCurSel();
int count = (int)m_slots.size();
bool can_move_up = (pos > 0);
bool can_move_down = (pos >= 0 && pos < count - 1);
GetDlgItem(IDC_REORDER_MOVE_TO_TOP)->EnableWindow(can_move_up);
GetDlgItem(IDC_REORDER_MOVE_UP)->EnableWindow(can_move_up);
GetDlgItem(IDC_REORDER_MOVE_DOWN)->EnableWindow(can_move_down);
GetDlgItem(IDC_REORDER_MOVE_TO_BOTTOM)->EnableWindow(can_move_down);
}
void reorder_dlg::move_selected(bool up, bool all_the_way)
{
int pos = m_list.GetCurSel();
int count = (int)m_slots.size();
if (pos < 0 || pos >= count)
return;
int target;
if (up)
target = all_the_way ? 0 : pos - 1;
else
target = all_the_way ? count - 1 : pos + 1;
if (target < 0 || target >= count || target == pos)
return;
// Rotate the item to the target position, which preserves the relative
// order of everything else in the list.
if (ships_selected())
{
FredShipSlotConfig cfg;
cfg.fred_alt_names = Fred_alt_names;
cfg.fred_callsigns = Fred_callsigns;
cfg.cur_ship = &cur_ship;
rotate_ship_slots(m_slots, pos, target, cfg);
}
else
{
FredWingSlotConfig cfg;
cfg.wing_objects = wing_objects;
cfg.cur_wing = &cur_wing;
rotate_wing_slots(m_slots, pos, target, cfg);
}
set_modified();
populate_list();
m_list.SetCurSel(target);
update_buttons();
}
void reorder_dlg::OnSelchangeReorderType()
{
populate_list();
update_buttons();
}
void reorder_dlg::OnSelchangeReorderList()
{
update_buttons();
}
void reorder_dlg::OnMoveToTop()
{
move_selected(true, true);
}
void reorder_dlg::OnMoveUp()
{
move_selected(true, false);
}
void reorder_dlg::OnMoveDown()
{
move_selected(false, false);
}
void reorder_dlg::OnMoveToBottom()
{
move_selected(false, true);
}
+40
View File
@@ -0,0 +1,40 @@
// reorderdlg.h : header file
#ifndef _REORDERDLG_H
#define _REORDERDLG_H
class reorder_dlg : public CDialog
{
public:
reorder_dlg(CWnd *pParent = nullptr);
// Dialog Data
//{{AFX_DATA(reorder_dlg)
enum { IDD = IDD_REORDER };
CComboBox m_type_combo;
CListBox m_list;
//}}AFX_DATA
protected:
virtual void DoDataExchange(CDataExchange *pDX); // DDX/DDV support
//{{AFX_MSG(reorder_dlg)
virtual BOOL OnInitDialog();
afx_msg void OnSelchangeReorderType();
afx_msg void OnSelchangeReorderList();
afx_msg void OnMoveToTop();
afx_msg void OnMoveUp();
afx_msg void OnMoveDown();
afx_msg void OnMoveToBottom();
//}}AFX_MSG
DECLARE_MESSAGE_MAP()
bool ships_selected() const;
void populate_list();
void update_buttons();
void move_selected(bool up, bool all_the_way);
// occupied Ships[] or Wings[] slot indexes, in list order
SCP_vector<int> m_slots;
};
#endif // _REORDERDLG_H
+10 -9
View File
@@ -1491,14 +1491,6 @@
#define ID_EDITORS_WAYPOINT 32979
#define ID_VIEW_OUTLINES 32980
#define ID_NEW_SHIP_TYPE 32981
#define ID_NEW_PROP_TYPE 33104
#define ID_STATIC_SHIP_LABEL 33105
#define ID_STATIC_PROP_LABEL 33106
#define ID_OUTLINE_LOD_0 33107
#define ID_OUTLINE_LOD_1 33108
#define ID_OUTLINE_LOD_2 33109
#define ID_OUTLINE_LOD_3 33110
#define ID_OUTLINE_LOD_4 33111
#define ID_VIEW_OUTLINES_ON_SELECTED 32982
#define ID_SHOW_STARFIELD 32983
#define ID_ASTEROID_EDITOR 32984
@@ -1613,6 +1605,15 @@
#define ID_MISC_POINTUSINGUVEC 33101
#define ID_MUSIC_PLAYER 33102
#define ID_EDITORS_VOLUMETRICS 33103
#define ID_NEW_PROP_TYPE 33104
#define ID_STATIC_SHIP_LABEL 33105
#define ID_STATIC_PROP_LABEL 33106
#define ID_OUTLINE_LOD_0 33107
#define ID_OUTLINE_LOD_1 33108
#define ID_OUTLINE_LOD_2 33109
#define ID_OUTLINE_LOD_3 33110
#define ID_OUTLINE_LOD_4 33111
#define ID_REORDER 33112
#define ID_INDICATOR_MODE 59142
#define ID_INDICATOR_LEFT 59143
#define ID_INDICATOR_RIGHT 59144
@@ -1626,7 +1627,7 @@
#define _APS_3D_CONTROLS 1
#define _APS_NEXT_RESOURCE_VALUE 340
#define _APS_NEXT_CONTROL_VALUE 1747
#define _APS_NEXT_COMMAND_VALUE 33112
#define _APS_NEXT_COMMAND_VALUE 33113
#define _APS_NEXT_SYMED_VALUE 105
#endif
#endif