/
EffectEditor.cpp
302 lines (241 loc) · 7.46 KB
/
EffectEditor.cpp
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
#include "EffectEditor.h"
#include "iscenegraph.h"
#include "iregistry.h"
#include "entitylib.h"
#include "wxutil/TreeModel.h"
#include "ResponseEditor.h"
#include <iostream>
#include "i18n.h"
#include "gamelib.h"
#include "wxutil/ChoiceHelper.h"
#include <wx/choice.h>
#include <wx/checkbox.h>
#include <wx/stattext.h>
namespace ui
{
namespace
{
const char* const WINDOW_TITLE = N_("Edit Response Effect");
// The name of the _SELF entity as parsed by the response scripts
const char* const GKEY_ENTITY_SELF = "/stimResponseSystem/selfEntity";
}
EffectEditor::EffectEditor(wxWindow* parent,
StimResponse& response,
const unsigned int effectIndex,
StimTypes& stimTypes,
ui::ResponseEditor& editor) :
DialogBase(_(WINDOW_TITLE), parent),
_argTable(NULL),
_response(response),
_effectIndex(effectIndex),
_backup(_response.getResponseEffect(_effectIndex)),
_editor(editor),
_stimTypes(stimTypes)
{
SetSizer(new wxBoxSizer(wxVERTICAL));
// Create the widgets
populateWindow();
// Search the scenegraph for entities
populateEntityListStore();
// Initialise the widgets with the current data
ResponseEffect& effect = _response.getResponseEffect(_effectIndex);
// Setup the selectionfinder to search for the name string
wxutil::ChoiceHelper::SelectItemByStoredString(_effectTypeCombo, effect.getName());
_stateToggle->SetValue(effect.isActive());
// Parse the argument types from the effect and create the widgets
createArgumentWidgets(effect);
Layout();
Fit();
}
int EffectEditor::ShowModal()
{
int returnCode = DialogBase::ShowModal();
if (returnCode == wxID_OK)
{
save();
}
else
{
revert();
}
return returnCode;
}
void EffectEditor::populateWindow()
{
// Create the overall vbox
wxBoxSizer* vbox = new wxBoxSizer(wxVERTICAL);
// Pack everything into the main window
GetSizer()->Add(vbox, 1, wxEXPAND | wxALL, 12);
GetSizer()->Add(CreateStdDialogButtonSizer(wxOK | wxCANCEL), 0, wxALIGN_RIGHT | wxALL, 12);
_effectTypeCombo = new wxChoice(this, wxID_ANY);
// Connect the signal to get notified of further changes
_effectTypeCombo->Connect(wxEVT_CHOICE, wxCommandEventHandler(EffectEditor::onEffectTypeChange), NULL, this);
// Retrieve the map from the ResponseEffectTypes object
ResponseEffectTypeMap& effectTypes =
ResponseEffectTypes::Instance().getMap();
// Now populate the list store with all the possible effect types
for (ResponseEffectTypeMap::iterator i = effectTypes.begin();
i != effectTypes.end(); ++i)
{
// Store the effect name as client data
_effectTypeCombo->Append(i->second->getAttribute("editor_caption").getValue(),
new wxStringClientData(i->first));
}
wxBoxSizer* effectHBox = new wxBoxSizer(wxHORIZONTAL);
wxStaticText* effectLabel = new wxStaticText(this, wxID_ANY, _("Effect:"));
effectHBox->Add(effectLabel, 0, wxALIGN_CENTER_VERTICAL | wxRIGHT, 6);
effectHBox->Add(_effectTypeCombo);
vbox->Add(effectHBox, 0, wxBOTTOM | wxEXPAND, 6);
_stateToggle = new wxCheckBox(this, wxID_ANY, _("Active"));
_stateToggle->Connect(wxEVT_CHECKBOX, wxCommandEventHandler(EffectEditor::onStateToggle), NULL, this);
vbox->Add(_stateToggle, 0, wxBOTTOM, 6);
wxStaticText* argLabel = new wxStaticText(this, wxID_ANY, _("Arguments"));
argLabel->SetFont(argLabel->GetFont().Bold());
vbox->Add(argLabel, 0, wxBOTTOM, 6);
_argTable = new wxFlexGridSizer(3, 6, 12);
vbox->Add(_argTable, 0, wxEXPAND | wxLEFT, 12);
}
void EffectEditor::effectTypeChanged()
{
std::string newEffectName("");
// Get the currently selected effect name from the combo box
if (_effectTypeCombo->GetSelection() != wxNOT_FOUND)
{
wxStringClientData* data = dynamic_cast<wxStringClientData*>(
_effectTypeCombo->GetClientObject(_effectTypeCombo->GetSelection()));
assert(data != NULL);
newEffectName = data->GetData().ToStdString();
}
// Get the effect
ResponseEffect& effect = _response.getResponseEffect(_effectIndex);
// Set the name of the effect and trigger an argument list update
effect.setName(newEffectName);
effect.clearArgumentList();
effect.buildArgumentList();
// Rebuild the argument list basing on this new effect
createArgumentWidgets(effect);
}
void EffectEditor::createArgumentWidgets(ResponseEffect& effect)
{
ResponseEffect::ArgumentList& list = effect.getArguments();
// Remove all possible previous items from the list
_argumentItems.clear();
// Clear the old table
_argTable->DeleteWindows();
for (ResponseEffect::ArgumentList::iterator i = list.begin();
i != list.end(); ++i)
{
//int index = i->first;
ResponseEffect::Argument& arg = i->second;
ArgumentItemPtr item;
if (arg.type == "s")
{
// Create a new string argument item
item = ArgumentItemPtr(new StringArgument(this, arg));
}
else if (arg.type == "f")
{
// Create a new string argument item
item = ArgumentItemPtr(new FloatArgument(this, arg));
}
else if (arg.type == "v")
{
// Create a new vector argument item
item = ArgumentItemPtr(new VectorArgument(this, arg));
}
else if (arg.type == "e")
{
// Create a new string argument item
item = ArgumentItemPtr(new EntityArgument(this, arg, _entityChoices));
}
else if (arg.type == "b")
{
// Create a new bool item
item = ArgumentItemPtr(new BooleanArgument(this, arg));
}
else if (arg.type == "t")
{
// Create a new stim type item
item = ArgumentItemPtr(new StimTypeArgument(this, arg, _stimTypes));
}
if (item != NULL)
{
_argumentItems.push_back(item);
if (arg.type != "b")
{
// The label
_argTable->Add(item->getLabelWidget(), 0, wxALIGN_CENTER_VERTICAL);
// The edit widgets
_argTable->Add(item->getEditWidget(), 1, wxEXPAND);
}
else
{
// The label
_argTable->Add(new wxStaticText(this, wxID_ANY, ""), 0, wxALIGN_CENTER_VERTICAL);
// The edit widgets
_argTable->Add(item->getEditWidget(), 1, wxEXPAND);
}
// The help widgets
_argTable->Add(item->getHelpWidget(), 0, wxALIGN_CENTER_VERTICAL);
}
}
_argTable->Layout();
Layout();
Fit();
}
void EffectEditor::save()
{
// Request each argument item to save the content into the argument
for (std::size_t i = 0; i < _argumentItems.size(); ++i)
{
_argumentItems[i]->save();
}
// Call the update routine of the parent editor
_editor.update();
}
// Traverse the scenegraph to populate the tree model
void EffectEditor::populateEntityListStore()
{
_entityChoices.Clear();
std::string selfEntity = game::current::getValue<std::string>(GKEY_ENTITY_SELF);
// Append the name to the list store
_entityChoices.Add(selfEntity);
// Create a scenegraph walker to traverse the graph
class EntityFinder :
public scene::NodeVisitor
{
// List to add names to
wxArrayString& _list;
public:
// Constructor
EntityFinder(wxArrayString& list) :
_list(list)
{}
// Visit function
bool pre(const scene::INodePtr& node)
{
Entity* entity = Node_getEntity(node);
if (entity != NULL)
{
// Get the entity name and append it to the list store
_list.Add(entity->getKeyValue("name"));
return false; // don't traverse children if entity found
}
return true; // traverse children otherwise
}
} finder(_entityChoices);
GlobalSceneGraph().root()->traverse(finder);
}
void EffectEditor::revert()
{
_response.getResponseEffect(_effectIndex) = _backup;
}
void EffectEditor::onStateToggle(wxCommandEvent& ev)
{
_response.getResponseEffect(_effectIndex).setActive(_stateToggle->GetValue());
}
void EffectEditor::onEffectTypeChange(wxCommandEvent& ev)
{
effectTypeChanged();
}
} // namespace ui