Skip to content

Commit 0d4c222

Browse files
authored
QtFRED Debriefing Dialog (#7018)
* qtfred debriefing dialog * explicit flags * clang
1 parent 22b5f81 commit 0d4c222

File tree

9 files changed

+1001
-1
lines changed

9 files changed

+1001
-1
lines changed

qtfred/source_groups.cmake

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -48,6 +48,8 @@ add_file_folder("Source/Mission/Dialogs"
4848
src/mission/dialogs/CampaignEditorDialogModel.h
4949
src/mission/dialogs/CommandBriefingDialogModel.cpp
5050
src/mission/dialogs/CommandBriefingDialogModel.h
51+
src/mission/dialogs/DebriefingDialogModel.cpp
52+
src/mission/dialogs/DebriefingDialogModel.h
5153
src/mission/dialogs/FictionViewerDialogModel.cpp
5254
src/mission/dialogs/FictionViewerDialogModel.h
5355
src/mission/dialogs/FormWingDialogModel.cpp
@@ -146,6 +148,8 @@ add_file_folder("Source/UI/Dialogs"
146148
src/ui/dialogs/CampaignEditorDialog.cpp
147149
src/ui/dialogs/CommandBriefingDialog.cpp
148150
src/ui/dialogs/CommandBriefingDialog.h
151+
src/ui/dialogs/DebriefingDialog.cpp
152+
src/ui/dialogs/DebriefingDialog.h
149153
src/ui/dialogs/FictionViewerDialog.cpp
150154
src/ui/dialogs/FictionViewerDialog.h
151155
src/ui/dialogs/FormWingDialog.cpp
@@ -275,6 +279,7 @@ add_file_folder("UI"
275279
ui/CustomDataDialog.ui
276280
ui/CustomStringsDialog.ui
277281
ui/CustomWingNamesDialog.ui
282+
ui/DebriefingDialog.ui
278283
ui/FictionViewerDialog.ui
279284
ui/FormWingDialog.ui
280285
ui/FredView.ui
Lines changed: 308 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,308 @@
1+
#include "DebriefingDialogModel.h"
2+
#include "missionui/missioncmdbrief.h" //TODO remove?
3+
#include "mission/missionparse.h" //TODO remove?
4+
#include "gamesnd/eventmusic.h"
5+
#include "sound/audiostr.h"
6+
#include <QMessageBox>
7+
8+
namespace fso::fred::dialogs {
9+
10+
DebriefingDialogModel::DebriefingDialogModel(QObject* parent, EditorViewport* viewport)
11+
: AbstractDialogModel(parent, viewport)
12+
{
13+
initializeData();
14+
}
15+
16+
bool DebriefingDialogModel::apply()
17+
{
18+
stopSpeech();
19+
20+
for (int i = 0; i < MAX_TVT_TEAMS; i++) {
21+
Debriefings[i] = _wipDebriefing[i];
22+
}
23+
24+
Mission_music[SCORE_DEBRIEFING_SUCCESS] = _successMusic;
25+
Mission_music[SCORE_DEBRIEFING_AVERAGE] = _averageMusic;
26+
Mission_music[SCORE_DEBRIEFING_FAILURE] = _failureMusic;
27+
28+
return true;
29+
}
30+
31+
void DebriefingDialogModel::reject()
32+
{
33+
stopSpeech();
34+
35+
}
36+
37+
void DebriefingDialogModel::initializeData()
38+
{
39+
initializeTeamList();
40+
41+
// Make a working copy
42+
for (int i = 0; i < MAX_TVT_TEAMS; i++) {
43+
_wipDebriefing[i] = Debriefings[i];
44+
}
45+
46+
_successMusic = Mission_music[SCORE_DEBRIEFING_SUCCESS];
47+
_averageMusic = Mission_music[SCORE_DEBRIEFING_AVERAGE];
48+
_failureMusic = Mission_music[SCORE_DEBRIEFING_FAILURE];
49+
50+
_currentTeam = 0;
51+
_currentStage = 0;
52+
}
53+
54+
void DebriefingDialogModel::gotoPreviousStage()
55+
{
56+
if (_currentStage <= 0) {
57+
_currentStage = 0;
58+
return;
59+
}
60+
61+
stopSpeech();
62+
_currentStage--;
63+
}
64+
65+
void DebriefingDialogModel::gotoNextStage()
66+
{
67+
if (_currentStage >= MAX_DEBRIEF_STAGES - 1) {
68+
_currentStage = MAX_DEBRIEF_STAGES - 1;
69+
return;
70+
}
71+
72+
if (_currentStage >= _wipDebriefing[_currentTeam].num_stages - 1) {
73+
_currentStage = _wipDebriefing[_currentTeam].num_stages - 1;
74+
return;
75+
}
76+
77+
_currentStage++;
78+
stopSpeech();
79+
}
80+
81+
void DebriefingDialogModel::addStage()
82+
{
83+
stopSpeech();
84+
85+
if (_wipDebriefing[_currentTeam].num_stages >= MAX_DEBRIEF_STAGES) {
86+
_wipDebriefing[_currentTeam].num_stages = MAX_DEBRIEF_STAGES;
87+
_currentStage = _wipDebriefing[_currentTeam].num_stages - 1;
88+
return;
89+
}
90+
91+
_wipDebriefing[_currentTeam].num_stages++;
92+
_currentStage = _wipDebriefing[_currentTeam].num_stages - 1;
93+
_wipDebriefing[_currentTeam].stages[_currentStage].text = "<Text here>";
94+
_wipDebriefing[_currentTeam].stages[_currentStage].recommendation_text = "<Recommendation text here>";
95+
strcpy_s(_wipDebriefing[_currentTeam].stages[_currentStage].voice, "none.wav"); // Really? Seeding with none.wav is gross
96+
_wipDebriefing[_currentTeam].stages[_currentStage].formula = -1;
97+
98+
set_modified();
99+
}
100+
101+
// copies the current stage as the next stage and then moves the rest of the stages over.
102+
void DebriefingDialogModel::insertStage()
103+
{
104+
stopSpeech();
105+
106+
if (_wipDebriefing[_currentTeam].num_stages >= MAX_DEBRIEF_STAGES) {
107+
_wipDebriefing[_currentTeam].num_stages = MAX_DEBRIEF_STAGES;
108+
set_modified();
109+
return;
110+
}
111+
112+
_wipDebriefing[_currentTeam].num_stages++;
113+
114+
for (int i = _wipDebriefing[_currentTeam].num_stages - 1; i > _currentStage; i--) {
115+
_wipDebriefing[_currentTeam].stages[i] = _wipDebriefing[_currentTeam].stages[i - 1];
116+
}
117+
118+
// Future TODO: Add a QtFRED Option to clear the inserted stage instead of copying the current one.
119+
120+
set_modified();
121+
}
122+
123+
void DebriefingDialogModel::deleteStage()
124+
{
125+
stopSpeech();
126+
127+
// Clear everything if we were on the last stage.
128+
if (_wipDebriefing[_currentTeam].num_stages <= 1) {
129+
_wipDebriefing[_currentTeam].num_stages = 0;
130+
_wipDebriefing[_currentTeam].stages[0].text.clear();
131+
_wipDebriefing[_currentTeam].stages[0].recommendation_text.clear();
132+
memset(_wipDebriefing[_currentTeam].stages[0].voice, 0, CF_MAX_FILENAME_LENGTH);
133+
_wipDebriefing[_currentTeam].stages[0].formula = -1;
134+
set_modified();
135+
return;
136+
}
137+
138+
// copy the stages backwards until we get to the stage we're on
139+
for (int i = _currentStage; i + 1 < _wipDebriefing[_currentTeam].num_stages; i++) {
140+
_wipDebriefing[_currentTeam].stages[i] = _wipDebriefing[_currentTeam].stages[i + 1];
141+
}
142+
143+
_wipDebriefing[_currentTeam].num_stages--;
144+
145+
// Clear the tail
146+
const int tail = _wipDebriefing[_currentTeam].num_stages; // index of the old last element
147+
_wipDebriefing[_currentTeam].stages[tail].text.clear();
148+
_wipDebriefing[_currentTeam].stages[tail].recommendation_text.clear();
149+
std::memset(_wipDebriefing[_currentTeam].stages[tail].voice, 0, CF_MAX_FILENAME_LENGTH);
150+
_wipDebriefing[_currentTeam].stages[tail].formula = -1;
151+
152+
// make sure that the current stage is valid.
153+
if (_wipDebriefing[_currentTeam].num_stages <= _currentStage) {
154+
_currentStage = _wipDebriefing[_currentTeam].num_stages - 1;
155+
}
156+
157+
set_modified();
158+
}
159+
160+
void DebriefingDialogModel::testSpeech()
161+
{
162+
// May cause unloading/reloading but it's just the mission editor
163+
// we don't need to keep all the waves loaded only to have to unload them
164+
// later anyway. This ensures we have one wave loaded and stopSpeech always unloads it
165+
166+
stopSpeech();
167+
168+
_waveId = audiostream_open(_wipDebriefing[_currentTeam].stages[_currentStage].voice, ASF_EVENTMUSIC);
169+
audiostream_play(_waveId, 1.0f, 0);
170+
}
171+
172+
void DebriefingDialogModel::copyToOtherTeams()
173+
{
174+
stopSpeech();
175+
176+
for (int i = 0; i < MAX_TVT_TEAMS; i++) {
177+
if (i != _currentTeam) {
178+
_wipDebriefing[i] = _wipDebriefing[_currentTeam];
179+
}
180+
}
181+
set_modified();
182+
}
183+
184+
const SCP_vector<std::pair<SCP_string, int>>& DebriefingDialogModel::getTeamList()
185+
{
186+
return _teamList;
187+
}
188+
189+
bool DebriefingDialogModel::getMissionIsMultiTeam()
190+
{
191+
return The_mission.game_type & MISSION_TYPE_MULTI_TEAMS;
192+
}
193+
194+
void DebriefingDialogModel::stopSpeech()
195+
{
196+
if (_waveId >= -1) {
197+
audiostream_close_file(_waveId, false);
198+
_waveId = -1;
199+
}
200+
}
201+
202+
void DebriefingDialogModel::initializeTeamList()
203+
{
204+
_teamList.clear();
205+
for (auto& team : Mission_event_teams_tvt) {
206+
_teamList.emplace_back(team.first, team.second);
207+
}
208+
}
209+
210+
int DebriefingDialogModel::getCurrentTeam() const
211+
{
212+
return _currentTeam;
213+
}
214+
215+
void DebriefingDialogModel::setCurrentTeam(int teamIn)
216+
{
217+
modify(_currentTeam, teamIn);
218+
};
219+
220+
int DebriefingDialogModel::getCurrentStage() const
221+
{
222+
return _currentStage;
223+
}
224+
225+
int DebriefingDialogModel::getTotalStages()
226+
{
227+
return _wipDebriefing[_currentTeam].num_stages;
228+
}
229+
230+
SCP_string DebriefingDialogModel::getStageText()
231+
{
232+
return _wipDebriefing[_currentTeam].stages[_currentStage].text;
233+
}
234+
235+
void DebriefingDialogModel::setStageText(const SCP_string& text)
236+
{
237+
modify(_wipDebriefing[_currentTeam].stages[_currentStage].text, text);
238+
}
239+
240+
SCP_string DebriefingDialogModel::getRecommendationText()
241+
{
242+
return _wipDebriefing[_currentTeam].stages[_currentStage].recommendation_text;
243+
}
244+
245+
void DebriefingDialogModel::setRecommendationText(const SCP_string& text)
246+
{
247+
modify(_wipDebriefing[_currentTeam].stages[_currentStage].recommendation_text, text);
248+
}
249+
250+
SCP_string DebriefingDialogModel::getSpeechFilename()
251+
{
252+
return _wipDebriefing[_currentTeam].stages[_currentStage].voice;
253+
}
254+
255+
void DebriefingDialogModel::setSpeechFilename(const SCP_string& speechFilename)
256+
{
257+
strcpy_s(_wipDebriefing[_currentTeam].stages[_currentStage].voice, speechFilename.c_str());
258+
set_modified();
259+
}
260+
261+
int DebriefingDialogModel::getFormula() const
262+
{
263+
return _wipDebriefing[_currentTeam].stages[_currentStage].formula;
264+
}
265+
266+
void DebriefingDialogModel::setFormula(int formula)
267+
{
268+
modify(_wipDebriefing[_currentTeam].stages[_currentStage].formula, formula);
269+
}
270+
271+
SCP_vector<SCP_string> DebriefingDialogModel::getMusicList()
272+
{
273+
SCP_vector<SCP_string> music_list;
274+
music_list.emplace_back("None");
275+
276+
for (const auto& sm : Spooled_music) {
277+
music_list.emplace_back(sm.name);
278+
}
279+
280+
return music_list;
281+
}
282+
283+
int DebriefingDialogModel::getSuccessMusicTrack() const
284+
{
285+
return _successMusic;
286+
}
287+
void DebriefingDialogModel::setSuccessMusicTrack(int trackIndex)
288+
{
289+
modify(_successMusic, trackIndex);
290+
}
291+
int DebriefingDialogModel::getAverageMusicTrack() const
292+
{
293+
return _averageMusic;
294+
}
295+
void DebriefingDialogModel::setAverageMusicTrack(int trackIndex)
296+
{
297+
modify(_averageMusic, trackIndex);
298+
}
299+
int DebriefingDialogModel::getFailureMusicTrack() const
300+
{
301+
return _failureMusic;
302+
}
303+
void DebriefingDialogModel::setFailureMusicTrack(int trackIndex)
304+
{
305+
modify(_failureMusic, trackIndex);
306+
}
307+
308+
} // namespace fso::fred::dialogs

0 commit comments

Comments
 (0)