Book a Demo!
CoCalc Logo Icon
StoreFeaturesDocsShareSupportNewsAboutPoliciesSign UpSign In
godotengine
GitHub Repository: godotengine/godot
Path: blob/master/modules/objectdb_profiler/editor/data_viewers/object_view.cpp
20900 views
1
/**************************************************************************/
2
/* object_view.cpp */
3
/**************************************************************************/
4
/* This file is part of: */
5
/* GODOT ENGINE */
6
/* https://godotengine.org */
7
/**************************************************************************/
8
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
9
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
10
/* */
11
/* Permission is hereby granted, free of charge, to any person obtaining */
12
/* a copy of this software and associated documentation files (the */
13
/* "Software"), to deal in the Software without restriction, including */
14
/* without limitation the rights to use, copy, modify, merge, publish, */
15
/* distribute, sublicense, and/or sell copies of the Software, and to */
16
/* permit persons to whom the Software is furnished to do so, subject to */
17
/* the following conditions: */
18
/* */
19
/* The above copyright notice and this permission notice shall be */
20
/* included in all copies or substantial portions of the Software. */
21
/* */
22
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
23
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
24
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
25
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
26
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
27
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
28
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
29
/**************************************************************************/
30
31
#include "object_view.h"
32
33
#include "editor/editor_node.h"
34
#include "editor/themes/editor_scale.h"
35
#include "scene/gui/rich_text_label.h"
36
#include "scene/gui/split_container.h"
37
38
SnapshotObjectView::SnapshotObjectView() {
39
set_name(TTRC("Objects"));
40
}
41
42
void SnapshotObjectView::show_snapshot(GameStateSnapshot *p_data, GameStateSnapshot *p_diff_data) {
43
SnapshotView::show_snapshot(p_data, p_diff_data);
44
45
item_data_map.clear();
46
data_item_map.clear();
47
48
set_v_size_flags(SizeFlags::SIZE_EXPAND_FILL);
49
set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
50
51
objects_view = memnew(HSplitContainer);
52
add_child(objects_view);
53
objects_view->set_anchors_preset(LayoutPreset::PRESET_FULL_RECT);
54
55
VBoxContainer *object_column = memnew(VBoxContainer);
56
object_column->set_anchors_preset(LayoutPreset::PRESET_FULL_RECT);
57
objects_view->add_child(object_column);
58
object_column->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
59
object_column->set_v_size_flags(SizeFlags::SIZE_EXPAND_FILL);
60
61
object_list = memnew(Tree);
62
63
filter_bar = memnew(TreeSortAndFilterBar(object_list, TTRC("Filter Objects")));
64
object_column->add_child(filter_bar);
65
int sort_idx = 0;
66
if (diff_data) {
67
filter_bar->add_sort_option(TTRC("Snapshot"), TreeSortAndFilterBar::SortType::ALPHA_SORT, sort_idx++);
68
}
69
filter_bar->add_sort_option(TTRC("Class"), TreeSortAndFilterBar::SortType::ALPHA_SORT, sort_idx++);
70
filter_bar->add_sort_option(TTRC("Name"), TreeSortAndFilterBar::SortType::ALPHA_SORT, sort_idx++);
71
filter_bar->add_sort_option(TTRC("Inbound References"), TreeSortAndFilterBar::SortType::NUMERIC_SORT, sort_idx++);
72
TreeSortAndFilterBar::SortOptionIndexes default_sort = filter_bar->add_sort_option(
73
TTRC("Outbound References"), TreeSortAndFilterBar::SortType::NUMERIC_SORT, sort_idx++);
74
75
// Tree of objects.
76
object_list->set_select_mode(Tree::SelectMode::SELECT_ROW);
77
object_list->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
78
object_list->set_hide_folding(false);
79
object_column->add_child(object_list);
80
object_list->set_hide_root(true);
81
object_list->set_columns(diff_data ? 5 : 4);
82
object_list->set_column_titles_visible(true);
83
object_list->set_theme_type_variation("TreeSecondary");
84
85
int offset = 0;
86
if (diff_data) {
87
object_list->set_column_title(0, TTRC("Snapshot"));
88
object_list->set_column_expand(0, false);
89
object_list->set_column_title_tooltip_text(0, "A: " + snapshot_data->name + ", B: " + diff_data->name);
90
offset++;
91
}
92
93
object_list->set_column_title(offset + 0, TTRC("Class"));
94
object_list->set_column_expand(offset + 0, true);
95
object_list->set_column_title_tooltip_text(offset + 0, TTRC("Object's class"));
96
object_list->set_column_title(offset + 1, TTRC("Object"));
97
object_list->set_column_expand(offset + 1, true);
98
object_list->set_column_expand_ratio(offset + 1, 2);
99
object_list->set_column_title_tooltip_text(offset + 1, TTRC("Object's name"));
100
object_list->set_column_title(offset + 2, TTRC("In"));
101
object_list->set_column_expand(offset + 2, false);
102
object_list->set_column_clip_content(offset + 2, false);
103
object_list->set_column_title_tooltip_text(offset + 2, TTRC("Number of inbound references"));
104
object_list->set_column_custom_minimum_width(offset + 2, 30 * EDSCALE);
105
object_list->set_column_title(offset + 3, TTRC("Out"));
106
object_list->set_column_expand(offset + 3, false);
107
object_list->set_column_clip_content(offset + 3, false);
108
object_list->set_column_title_tooltip_text(offset + 3, TTRC("Number of outbound references"));
109
object_list->set_column_custom_minimum_width(offset + 2, 30 * EDSCALE);
110
object_list->connect(SceneStringName(item_selected), callable_mp(this, &SnapshotObjectView::_object_selected));
111
object_list->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
112
object_list->set_v_size_flags(SizeFlags::SIZE_EXPAND_FILL);
113
114
object_details = memnew(VBoxContainer);
115
object_details->set_custom_minimum_size(Size2(200, 0) * EDSCALE);
116
objects_view->add_child(object_details);
117
object_details->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
118
object_details->set_v_size_flags(SizeFlags::SIZE_EXPAND_FILL);
119
120
object_list->create_item();
121
_insert_data(snapshot_data, TTRC("A"));
122
if (diff_data) {
123
_insert_data(diff_data, TTRC("B"));
124
}
125
126
filter_bar->select_sort(default_sort.descending);
127
filter_bar->apply();
128
object_list->set_selected(object_list->get_root()->get_first_child());
129
// Expand the left panel as wide as we can. Passing `INT_MAX` or any very large int will have the opposite effect
130
// and shrink the left panel as small as it can go. So, pass an int we know is larger than the current panel, but not
131
// 'very' large (whatever that exact number is).
132
objects_view->set_split_offset(get_viewport_rect().size.x);
133
}
134
135
void SnapshotObjectView::_insert_data(GameStateSnapshot *p_snapshot, const String &p_name) {
136
for (const KeyValue<ObjectID, SnapshotDataObject *> &pair : p_snapshot->objects) {
137
TreeItem *item = object_list->create_item(object_list->get_root());
138
int offset = 0;
139
if (diff_data) {
140
item->set_text(0, p_name);
141
item->set_tooltip_text(0, p_snapshot->name);
142
item->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_DISABLED);
143
offset = 1;
144
}
145
item->set_auto_translate_mode(offset + 0, AUTO_TRANSLATE_MODE_DISABLED);
146
item->set_auto_translate_mode(offset + 1, AUTO_TRANSLATE_MODE_DISABLED);
147
item->set_text(offset + 0, pair.value->type_name);
148
item->set_text(offset + 1, pair.value->get_name());
149
item->set_text(offset + 2, String::num_uint64(pair.value->inbound_references.size()));
150
item->set_text(offset + 3, String::num_uint64(pair.value->outbound_references.size()));
151
item_data_map[item] = pair.value;
152
data_item_map[pair.value] = item;
153
}
154
}
155
156
void SnapshotObjectView::_object_selected() {
157
reference_item_map.clear();
158
159
for (int i = 0; i < object_details->get_child_count(); i++) {
160
object_details->get_child(i)->queue_free();
161
}
162
163
SnapshotDataObject *d = item_data_map[object_list->get_selected()];
164
EditorNode::get_singleton()->push_item(static_cast<Object *>(d));
165
166
DarkPanelContainer *object_panel = memnew(DarkPanelContainer);
167
VBoxContainer *object_panel_content = memnew(VBoxContainer);
168
object_panel_content->set_v_size_flags(SizeFlags::SIZE_EXPAND_FILL);
169
object_panel_content->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
170
object_details->add_child(object_panel);
171
object_panel->add_child(object_panel_content);
172
object_panel_content->add_child(memnew(SpanningHeader(d->get_name())));
173
174
ScrollContainer *properties_scroll = memnew(ScrollContainer);
175
properties_scroll->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
176
properties_scroll->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_AUTO);
177
properties_scroll->set_v_size_flags(SizeFlags::SIZE_EXPAND_FILL);
178
properties_scroll->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
179
object_panel_content->add_child(properties_scroll);
180
181
VBoxContainer *properties_container = memnew(VBoxContainer);
182
properties_container->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
183
properties_scroll->add_child(properties_container);
184
properties_container->add_theme_constant_override("separation", 8);
185
186
inbound_tree = _make_references_list(properties_container, TTRC("Inbound References"), TTRC("Source"), TTRC("Other object referencing this object"), TTRC("Property"), TTRC("Property of other object referencing this object"));
187
inbound_tree->connect(SceneStringName(item_selected), callable_mp(this, &SnapshotObjectView::_reference_selected).bind(inbound_tree));
188
TreeItem *ib_root = inbound_tree->create_item();
189
for (const KeyValue<String, ObjectID> &ob : d->inbound_references) {
190
TreeItem *i = inbound_tree->create_item(ib_root);
191
i->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_DISABLED);
192
i->set_auto_translate_mode(1, AUTO_TRANSLATE_MODE_DISABLED);
193
194
SnapshotDataObject *target = d->snapshot->objects[ob.value];
195
i->set_text(0, target->get_name());
196
i->set_text(1, ob.key);
197
reference_item_map[i] = data_item_map[target];
198
}
199
200
outbound_tree = _make_references_list(properties_container, TTRC("Outbound References"), TTRC("Property"), TTRC("Property of this object referencing other object"), TTRC("Target"), TTRC("Other object being referenced"));
201
outbound_tree->connect(SceneStringName(item_selected), callable_mp(this, &SnapshotObjectView::_reference_selected).bind(outbound_tree));
202
TreeItem *ob_root = outbound_tree->create_item();
203
for (const KeyValue<String, ObjectID> &ob : d->outbound_references) {
204
TreeItem *i = outbound_tree->create_item(ob_root);
205
i->set_auto_translate_mode(0, AUTO_TRANSLATE_MODE_DISABLED);
206
i->set_auto_translate_mode(1, AUTO_TRANSLATE_MODE_DISABLED);
207
208
SnapshotDataObject *target = d->snapshot->objects[ob.value];
209
i->set_text(0, ob.key);
210
i->set_text(1, target->get_name());
211
reference_item_map[i] = data_item_map[target];
212
}
213
}
214
215
void SnapshotObjectView::_reference_selected(Tree *p_source_tree) {
216
TreeItem *ref_item = p_source_tree->get_selected();
217
Tree *other_tree = p_source_tree == inbound_tree ? outbound_tree : inbound_tree;
218
other_tree->deselect_all();
219
TreeItem *other = reference_item_map[ref_item];
220
if (other) {
221
if (!other->is_visible()) {
222
// Clear the filter if we can't see the node we just chose.
223
filter_bar->clear_filter();
224
}
225
other->get_tree()->deselect_all();
226
other->get_tree()->set_selected(other);
227
other->get_tree()->ensure_cursor_is_visible();
228
}
229
}
230
231
Tree *SnapshotObjectView::_make_references_list(Control *p_container, const String &p_name, const String &p_col_1, const String &p_col_1_tooltip, const String &p_col_2, const String &p_col_2_tooltip) {
232
VBoxContainer *vbox = memnew(VBoxContainer);
233
vbox->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
234
vbox->set_v_size_flags(SizeFlags::SIZE_EXPAND_FILL);
235
vbox->add_theme_constant_override("separation", 4);
236
p_container->add_child(vbox);
237
238
vbox->set_custom_minimum_size(Vector2(300, 0) * EDSCALE);
239
240
RichTextLabel *lbl = memnew(RichTextLabel("[center]" + p_name + "[center]"));
241
lbl->set_fit_content(true);
242
lbl->set_use_bbcode(true);
243
vbox->add_child(lbl);
244
Tree *tree = memnew(Tree);
245
tree->set_hide_folding(true);
246
vbox->add_child(tree);
247
tree->set_select_mode(Tree::SelectMode::SELECT_ROW);
248
tree->set_hide_root(true);
249
tree->set_columns(2);
250
tree->set_column_titles_visible(true);
251
tree->set_column_title(0, p_col_1);
252
tree->set_column_expand(0, true);
253
tree->set_column_title_tooltip_text(0, p_col_1_tooltip);
254
tree->set_column_clip_content(0, false);
255
tree->set_column_title(1, p_col_2);
256
tree->set_column_expand(1, true);
257
tree->set_column_clip_content(1, false);
258
tree->set_column_title_tooltip_text(1, p_col_2_tooltip);
259
tree->set_v_scroll_enabled(false);
260
tree->set_h_size_flags(SizeFlags::SIZE_EXPAND_FILL);
261
262
return tree;
263
}
264
265