/
EntityInspector.h
308 lines (242 loc) · 9.63 KB
/
EntityInspector.h
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
303
304
305
306
307
308
#pragma once
#include "PropertyEditor.h"
#include "ui/ientityinspector.h"
#include "iradiant.h"
#include "imap.h"
#include "icommandsystem.h"
#include "imapmerge.h"
#include "iselection.h"
#include "ientity.h"
#include "string/string.h"
#include "wxutil/menu/PopupMenu.h"
#include "wxutil/PanedPosition.h"
#include "wxutil/dataview/TreeView.h"
#include "wxutil/event/SingleIdleCallback.h"
#include <wx/event.h>
#include <wx/icon.h>
#include <sigc++/connection.h>
#include <map>
/* FORWARD DECLS */
class Entity;
class Selectable;
class EntityClassAttribute;
class wxCheckBox;
class wxStaticText;
class wxTextCtrl;
class wxBitmapButton;
class wxDataViewColumn;
namespace selection
{
class CollectiveSpawnargs;
class EntitySelection;
}
namespace ui
{
class PropertyEditorFactory;
/**
* The EntityInspector class represents the GTK dialog for editing properties
* on the selected game entity. The class is implemented as a singleton and
* contains a method to return the current instance.
*/
class EntityInspector final :
public IEntityInspector,
public selection::SelectionSystem::Observer,
public wxutil::SingleIdleCallback,
public Entity::Observer
{
public:
struct TreeColumns :
public wxutil::TreeModel::ColumnRecord
{
TreeColumns() :
name(add(wxutil::TreeModel::Column::IconText)),
value(add(wxutil::TreeModel::Column::String)),
isInherited(add(wxutil::TreeModel::Column::Boolean)),
hasHelpText(add(wxutil::TreeModel::Column::Boolean)),
booleanValue(add(wxutil::TreeModel::Column::Boolean)),
oldValue(add(wxutil::TreeModel::Column::String)),
newValue(add(wxutil::TreeModel::Column::String))
{}
wxutil::TreeModel::Column name;
wxutil::TreeModel::Column value;
wxutil::TreeModel::Column isInherited;
wxutil::TreeModel::Column hasHelpText;
wxutil::TreeModel::Column booleanValue;
wxutil::TreeModel::Column oldValue; // when displaying merge changes
wxutil::TreeModel::Column newValue; // when displaying merge changes
};
private:
std::unique_ptr<PropertyEditorFactory> _propertyEditorFactory;
// Tracking helpers to organise the selected entities and their key values
std::unique_ptr<selection::CollectiveSpawnargs> _spawnargs;
std::unique_ptr<selection::EntitySelection> _entitySelection;
// Main EntityInspector widget
wxPanel* _mainWidget;
// Frame to contain the Property Editor
wxPanel* _editorFrame;
// The checkbox for showing the eclass properties
wxCheckBox* _showInheritedCheckbox;
wxCheckBox* _showHelpColumnCheckbox;
// A label showing the primitive number
wxStaticText* _primitiveNumLabel;
// View and model for the keyvalue list
wxutil::TreeView* _keyValueTreeView;
TreeColumns _columns;
wxutil::TreeModel::Ptr _kvStore;
wxDataViewColumn* _booleanColumn;
wxDataViewColumn* _valueColumn;
wxDataViewColumn* _oldValueColumn;
wxDataViewColumn* _newValueColumn;
wxIcon _emptyIcon;
// Cache of wxDataViewItems pointing to keyvalue rows,
// so we can quickly find existing keys to change their values
typedef std::map<std::string, wxDataViewItem, string::ILess> TreeIterMap;
TreeIterMap _keyValueIterMap;
// Key and value edit boxes. These remain available even for multiple entity
// selections.
wxTextCtrl* _keyEntry;
wxTextCtrl* _valEntry;
wxBitmapButton* _setButton;
wxTextCtrl* _helpText;
// The pane dividing the treeview and the property editors
wxSplitterWindow* _paned;
// An object tracking the divider position of the paned view
wxutil::PanedPosition _panedPosition;
// Context menu
wxutil::PopupMenuPtr _contextMenu;
// Currently displayed PropertyEditor
IPropertyEditor::Ptr _currentPropertyEditor;
// The clipboard for spawnargs
typedef std::pair<std::string, std::string> KeyValuePair;
typedef std::vector<KeyValuePair> ClipBoard;
ClipBoard _clipboard;
// Data structure to store the type (vector3, text etc) and the options
// string for a single property.
struct PropertyParms
{
std::string type;
std::string options;
};
// Map of property names to PropertyParms, mapped like this: regex => parms
typedef std::map<std::string, PropertyParms> PropertyParmMap;
PropertyParmMap _propertyTypes;
sigc::connection _undoHandler;
sigc::connection _redoHandler;
sigc::connection _defsReloadedHandler;
sigc::connection _mapEditModeChangedHandler;
sigc::connection _keyValueAddedHandler;
sigc::connection _keyValueRemovedHandler;
sigc::connection _keyValueSetChangedHandler;
// Maps the key names to a possible merge action that should be displayed
std::map<std::string, scene::merge::IEntityKeyValueMergeAction::Ptr> _mergeActions;
std::map<std::string, scene::merge::IConflictResolutionAction::Ptr> _conflictActions;
bool _selectionNeedsUpdate;
private:
bool canUpdateEntity();
// Utility functions to construct the Gtk components
void construct();
wxWindow* createPropertyEditorPane(wxWindow* parent); // bottom widget pane
wxWindow* createTreeViewPane(wxWindow* parent); // tree view for selecting attributes
void createContextMenu();
// Utility function to retrieve the string selection from the given column in the
// list store
// getSelectedKey() returns an empty string if nothing is selected
std::string getSelectedKey();
std::string getListSelection(const wxutil::TreeModel::Column& col);
bool getListSelectionBool(const wxutil::TreeModel::Column& col);
// wxutil::PopupMenu callbacks
void _onAddKey();
void _onDeleteKey();
void _onCopyKey();
void _onCutKey();
void _onPasteKey();
void _onAcceptMergeAction();
void _onRejectMergeAction();
bool _testAddKey();
bool _testDeleteKey();
bool _testCopyKey();
bool _testCutKey();
bool _testPasteKey();
bool _testAcceptMergeAction();
bool _testRejectMergeAction();
// Shared by cut and delete keys
bool _testNonEmptyAndDeletableSelection();
bool isItemDeletable(const wxutil::TreeModel::Row& row);
bool isItemAffecedByMergeConflict(const wxutil::TreeModel::Row& row);
bool isItemAffecedByMergeOperation(const wxutil::TreeModel::Row& row);
// callbacks
void _onEntryActivate(wxCommandEvent& ev);
void _onSetProperty(wxCommandEvent& ev);
void _onTreeViewSelectionChanged(wxDataViewEvent& ev);
void _onContextMenu(wxDataViewEvent& ev);
void _onDataViewItemChanged(wxDataViewEvent& ev);
void onKeyAdded(const std::string& key, const std::string& value);
void onKeyRemoved(const std::string& key);
void onKeyValueSetChanged(const std::string& key, const std::string& uniqueValue);
void handleShowInheritedChanged();
void handleShowHelpTextChanged();
void updateHelpText(const wxutil::TreeModel::Row& row);
static std::string cleanInputString( const std::string& );
// Add and remove inherited properties from the entity class
void addClassAttribute(const EntityClassAttribute& a);
void addClassProperties();
void removeClassProperties();
// Update our selected entity pointer from the selection system
void getEntityFromSelectionSystem();
// Change the selected entity pointer, setting up the observer
void changeSelectedEntity(const scene::INodePtr& newEntity, const scene::INodePtr& selectedNode);
void handleMergeActions(const scene::INodePtr& selectedNode);
void handleKeyValueMergeAction(const scene::merge::IEntityKeyValueMergeAction::Ptr& mergeAction);
// Set the keyval on all selected entities from the key and value textboxes
void setPropertyFromEntries();
// Applies the given key/value pair to the selection (works with multiple
// selected entities)
void applyKeyValueToSelection(const std::string& key,
const std::string& value);
// Initialise the property lookup tables
void loadPropertyMap();
// Returns property type and option for the given entity key
PropertyParms getPropertyParmsForKey(const std::string& key);
// Update tree view contents and property editor
void updateGUIElements();
void updateTreeView();
// Release the current entity and rescan the selection
void refresh();
// Gets called after an undo operation
void onUndoRedoOperation();
void onMapEditModeChanged(IMap::EditMode mode);
void onDefsReloaded();
protected:
// Called when the app is idle
void onIdle();
public:
// Constructor
EntityInspector();
// Get the main widget for packing
wxPanel* getWidget();
/** greebo: Gets called by the RadiantSelectionSystem upon selection change.
*/
void selectionChanged(const scene::INodePtr& node, bool isComponent);
void registerPropertyEditor(const std::string& key, const IPropertyEditor::CreationFunc& creator) override;
void unregisterPropertyEditor(const std::string& key) override;
void registerPropertyEditorDialog(const std::string& key, const IPropertyEditorDialog::CreationFunc& create) override;
IPropertyEditorDialog::Ptr createDialog(const std::string& key) override;
void unregisterPropertyEditorDialog(const std::string& key) override;
void onMainFrameConstructed();
void onMainFrameShuttingDown();
void onKeyInsert(const std::string& key, EntityKeyValue& value);
void onKeyChange(const std::string& key, const std::string& value, bool isMultiValue = false);
void onKeyErase(const std::string& key, EntityKeyValue& value);
// greebo: Tells the inspector to reload the window settings from the registry.
void restoreSettings();
/**
* greebo: Static command target for toggling the Entity Inspector in the GroupDialog.
*/
static void toggle(const cmd::ArgumentList& args);
// RegisterableModule implementation
const std::string& getName() const override;
const StringSet& getDependencies() const override;
void initialiseModule(const IApplicationContext& ctx) override;
void shutdownModule() override;
};
} // namespace ui