Skip to content

Commit 5acc748

Browse files
authored
Qtfred head ani picker (#7312)
* add head animation picker dialog for event messages * get animations working all previewing all head anis cleanup * reorganize files * make these static * no const * more static * updated var name * missed one
1 parent 54f0b41 commit 5acc748

8 files changed

Lines changed: 640 additions & 43 deletions

File tree

qtfred/source_groups.cmake

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -245,6 +245,10 @@ add_file_folder("Source/UI/Dialogs/ShipEditor"
245245
src/ui/dialogs/ShipEditor/WeaponsTBLViewer.cpp
246246
src/ui/dialogs/ShipEditor/WeaponsTBLViewer.h
247247
)
248+
add_file_folder("Source/UI/Dialogs/EventEditor"
249+
src/ui/dialogs/EventEditor/HeadAnimationPickerDialog.cpp
250+
src/ui/dialogs/EventEditor/HeadAnimationPickerDialog.h
251+
)
248252
add_file_folder("Source/UI/General"
249253
src/ui/dialogs/General/CheckBoxListDialog.cpp
250254
src/ui/dialogs/General/CheckBoxListDialog.h

qtfred/src/mission/dialogs/MissionEventsDialogModel.cpp

Lines changed: 34 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,6 +5,29 @@
55

66
namespace fso::fred::dialogs {
77

8+
SCP_vector<SCP_string> MissionEventsDialogModel::s_extra_head_anis;
9+
10+
void MissionEventsDialogModel::addExtraHeadAni(const SCP_string& name)
11+
{
12+
if (name.empty() || lcase_equal(name, "<none>") || lcase_equal(name, "none")) {
13+
return;
14+
}
15+
auto it = std::find(s_extra_head_anis.begin(), s_extra_head_anis.end(), name);
16+
if (it == s_extra_head_anis.end()) {
17+
s_extra_head_anis.push_back(name);
18+
}
19+
}
20+
21+
void MissionEventsDialogModel::clearBrowsedHeadAnis()
22+
{
23+
s_extra_head_anis.clear();
24+
}
25+
26+
const SCP_vector<SCP_string>& MissionEventsDialogModel::getExtraHeadAnis()
27+
{
28+
return s_extra_head_anis;
29+
}
30+
831
MissionEventsDialogModel::MissionEventsDialogModel(QObject* parent, fso::fred::EditorViewport* viewport, IEventTreeOps& tree_ops)
932
: AbstractDialogModel(parent, viewport), m_event_tree_ops(tree_ops)
1033
{
@@ -371,11 +394,20 @@ void MissionEventsDialogModel::initializeHeadAniList()
371394
m_head_ani_list.emplace_back(thisHead);
372395
}
373396

397+
// Include any anis discovered during this session
398+
for (const auto& extra : s_extra_head_anis) {
399+
auto it = std::find(m_head_ani_list.begin(), m_head_ani_list.end(), extra);
400+
if (it == m_head_ani_list.end()) {
401+
m_head_ani_list.emplace_back(extra);
402+
}
403+
}
404+
405+
// Scan the current mission's messages. Any head ANI not already in the list is added to the list
374406
for (auto& msg : m_messages) {
375407
if (msg.avi_info.name) {
376408
auto it = std::find(m_head_ani_list.begin(), m_head_ani_list.end(), msg.avi_info.name);
377409
if (it == m_head_ani_list.end()) {
378-
m_head_ani_list.emplace_back(msg.avi_info.name);
410+
addExtraHeadAni(msg.avi_info.name);
379411
}
380412
}
381413
}
@@ -647,7 +679,7 @@ void MissionEventsDialogModel::insertEvent()
647679
m_sig.insert(m_sig.begin() + pos, -1);
648680
auto& event = m_events[pos];
649681

650-
// Place after the previous root if it exists and is valid; otherwise we’ll fix index explicitly
682+
// Place after the previous root if it exists and is valid; otherwise we'll fix index explicitly
651683
int after = (pos > 0 && m_events[pos - 1].formula >= 0) ? m_events[pos - 1].formula : -1;
652684

653685
event.formula = m_event_tree_ops.build_default_root(event.name, after);

qtfred/src/mission/dialogs/MissionEventsDialogModel.h

Lines changed: 7 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -84,6 +84,11 @@ class MissionEventsDialogModel : public AbstractDialogModel {
8484
int getCurrentlySelectedMessage() const;
8585
const SCP_vector<SCP_string>& getHeadAniList();
8686
const SCP_vector<SCP_string>& getWaveList();
87+
88+
// Session-persistent list of head ANIs discovered outside the built-in defaults
89+
static void addExtraHeadAni(const SCP_string& name);
90+
static void clearBrowsedHeadAnis();
91+
static const SCP_vector<SCP_string>& getExtraHeadAnis();
8792
const SCP_vector<std::pair<SCP_string, int>>& getPersonaList();
8893
const SCP_vector<std::pair<SCP_string, int>>& getTeamList();
8994

@@ -199,6 +204,8 @@ class MissionEventsDialogModel : public AbstractDialogModel {
199204

200205
SCP_vector<SCP_string> m_head_ani_list;
201206
SCP_vector<SCP_string> m_wave_list;
207+
208+
static SCP_vector<SCP_string> s_extra_head_anis;
202209
SCP_vector<std::pair<SCP_string, int>> m_persona_list;
203210
SCP_vector<std::pair<SCP_string, int>> m_team_list;
204211
};

qtfred/src/ui/FredView.cpp

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -16,6 +16,7 @@
1616
#include <ui/dialogs/WingEditorDialog.h>
1717
#include <ui/dialogs/PropEditorDialog.h>
1818
#include <ui/dialogs/MissionEventsDialog.h>
19+
#include <mission/dialogs/MissionEventsDialogModel.h>
1920
#include <ui/dialogs/AsteroidEditorDialog.h>
2021
#include <ui/dialogs/VolumetricNebulaDialog.h>
2122
#include <ui/dialogs/BriefingEditorDialog.h>
@@ -341,6 +342,9 @@ void FredView::on_actionSave_As_Template_triggered(bool) {
341342
}
342343

343344
void FredView::on_mission_loaded(const std::string& filepath) {
345+
// Clear browsed head ANIs so the new mission's message scan starts fresh.
346+
fso::fred::dialogs::MissionEventsDialogModel::clearBrowsedHeadAnis();
347+
344348
QString filename = "Untitled";
345349
if (!filepath.empty()) {
346350
filename = QFileInfo(QString::fromStdString(filepath)).fileName();

0 commit comments

Comments
 (0)