1 /*************************************************************************/
2 /*  editor_inspector.h                                                   */
3 /*************************************************************************/
4 /*                       This file is part of:                           */
5 /*                           GODOT ENGINE                                */
6 /*                      https://godotengine.org                          */
7 /*************************************************************************/
8 /* Copyright (c) 2007-2020 Juan Linietsky, Ariel Manzur.                 */
9 /* Copyright (c) 2014-2020 Godot Engine contributors (cf. AUTHORS.md).   */
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 #ifndef EDITOR_INSPECTOR_H
32 #define EDITOR_INSPECTOR_H
33 
34 #include "scene/gui/box_container.h"
35 #include "scene/gui/line_edit.h"
36 #include "scene/gui/scroll_container.h"
37 
38 class UndoRedo;
39 
40 class EditorPropertyRevert {
41 public:
42 	static bool may_node_be_in_instance(Node *p_node);
43 	static bool get_instanced_node_original_property(Node *p_node, const StringName &p_prop, Variant &value);
44 	static bool is_node_property_different(Node *p_node, const Variant &p_current, const Variant &p_orig);
45 
46 	static bool can_property_revert(Object *p_object, const StringName &p_property);
47 };
48 
49 class EditorProperty : public Container {
50 
51 	GDCLASS(EditorProperty, Container);
52 
53 private:
54 	String label;
55 	int text_size;
56 	friend class EditorInspector;
57 	Object *object;
58 	StringName property;
59 
60 	int property_usage;
61 
62 	bool read_only;
63 	bool checkable;
64 	bool checked;
65 	bool draw_red;
66 	bool keying;
67 
68 	Rect2 right_child_rect;
69 	Rect2 bottom_child_rect;
70 
71 	Rect2 keying_rect;
72 	bool keying_hover;
73 	Rect2 revert_rect;
74 	bool revert_hover;
75 	Rect2 check_rect;
76 	bool check_hover;
77 
78 	bool can_revert;
79 
80 	bool use_folding;
81 	bool draw_top_bg;
82 
83 	bool _is_property_different(const Variant &p_current, const Variant &p_orig);
84 	bool _get_instanced_node_original_property(const StringName &p_prop, Variant &value);
85 	void _focusable_focused(int p_index);
86 
87 	bool selectable;
88 	bool selected;
89 	int selected_focusable;
90 
91 	float split_ratio;
92 
93 	Vector<Control *> focusables;
94 	Control *label_reference;
95 	Control *bottom_editor;
96 
97 	mutable String tooltip_text;
98 
99 protected:
100 	void _notification(int p_what);
101 	static void _bind_methods();
102 
103 	void _gui_input(const Ref<InputEvent> &p_event);
104 
105 public:
106 	void emit_changed(const StringName &p_property, const Variant &p_value, const StringName &p_field = StringName(), bool p_changing = false);
107 
108 	virtual Size2 get_minimum_size() const;
109 
110 	void set_label(const String &p_label);
111 	String get_label() const;
112 
113 	void set_read_only(bool p_read_only);
114 	bool is_read_only() const;
115 
116 	Object *get_edited_object();
117 	StringName get_edited_property();
118 
119 	virtual void update_property();
120 	void update_reload_status();
121 
122 	virtual bool use_keying_next() const;
123 
124 	void set_checkable(bool p_checkable);
125 	bool is_checkable() const;
126 
127 	void set_checked(bool p_checked);
128 	bool is_checked() const;
129 
130 	void set_draw_red(bool p_draw_red);
131 	bool is_draw_red() const;
132 
133 	void set_keying(bool p_keying);
134 	bool is_keying() const;
135 
136 	void add_focusable(Control *p_control);
137 	void select(int p_focusable = -1);
138 	void deselect();
139 	bool is_selected() const;
140 
141 	void set_label_reference(Control *p_control);
142 	void set_bottom_editor(Control *p_control);
143 
144 	void set_use_folding(bool p_use_folding);
145 	bool is_using_folding() const;
146 
147 	virtual void expand_all_folding();
148 	virtual void collapse_all_folding();
149 
150 	virtual Variant get_drag_data(const Point2 &p_point);
151 
152 	void set_selectable(bool p_selectable);
153 	bool is_selectable() const;
154 
155 	void set_name_split_ratio(float p_ratio);
156 	float get_name_split_ratio() const;
157 
158 	void set_object_and_property(Object *p_object, const StringName &p_property);
159 	virtual Control *make_custom_tooltip(const String &p_text) const;
160 
161 	String get_tooltip_text() const;
162 
set_draw_top_bg(bool p_draw)163 	void set_draw_top_bg(bool p_draw) { draw_top_bg = p_draw; }
164 
can_revert_to_default()165 	bool can_revert_to_default() const { return can_revert; }
166 
167 	EditorProperty();
168 };
169 
170 class EditorInspectorPlugin : public Reference {
171 	GDCLASS(EditorInspectorPlugin, Reference);
172 
173 	friend class EditorInspector;
174 	struct AddedEditor {
175 		Control *property_editor;
176 		Vector<String> properties;
177 		String label;
178 	};
179 
180 	List<AddedEditor> added_editors;
181 
182 protected:
183 	static void _bind_methods();
184 
185 public:
186 	void add_custom_control(Control *control);
187 	void add_property_editor(const String &p_for_property, Control *p_prop);
188 	void add_property_editor_for_multiple_properties(const String &p_label, const Vector<String> &p_properties, Control *p_prop);
189 
190 	virtual bool can_handle(Object *p_object);
191 	virtual void parse_begin(Object *p_object);
192 	virtual void parse_category(Object *p_object, const String &p_parse_category);
193 	virtual bool parse_property(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
194 	virtual void parse_end();
195 };
196 
197 class EditorInspectorCategory : public Control {
198 	GDCLASS(EditorInspectorCategory, Control);
199 
200 	friend class EditorInspector;
201 	Ref<Texture> icon;
202 	String label;
203 	Color bg_color;
204 	mutable String tooltip_text;
205 
206 protected:
207 	void _notification(int p_what);
208 	static void _bind_methods();
209 
210 public:
211 	virtual Size2 get_minimum_size() const;
212 	virtual Control *make_custom_tooltip(const String &p_text) const;
213 
214 	String get_tooltip_text() const;
215 
216 	EditorInspectorCategory();
217 };
218 
219 class EditorInspectorSection : public Container {
220 	GDCLASS(EditorInspectorSection, Container);
221 
222 	String label;
223 	String section;
224 	Object *object;
225 	VBoxContainer *vbox;
226 	bool vbox_added; //optimization
227 	Color bg_color;
228 	bool foldable;
229 
230 	void _test_unfold();
231 
232 protected:
233 	void _notification(int p_what);
234 	static void _bind_methods();
235 	void _gui_input(const Ref<InputEvent> &p_event);
236 
237 public:
238 	virtual Size2 get_minimum_size() const;
239 
240 	void setup(const String &p_section, const String &p_label, Object *p_object, const Color &p_bg_color, bool p_foldable);
241 	VBoxContainer *get_vbox();
242 	void unfold();
243 	void fold();
244 
245 	Object *get_edited_object();
246 
247 	EditorInspectorSection();
248 	~EditorInspectorSection();
249 };
250 
251 class EditorInspector : public ScrollContainer {
252 	GDCLASS(EditorInspector, ScrollContainer);
253 
254 	UndoRedo *undo_redo;
255 	enum {
256 		MAX_PLUGINS = 1024
257 	};
258 	static Ref<EditorInspectorPlugin> inspector_plugins[MAX_PLUGINS];
259 	static int inspector_plugin_count;
260 
261 	VBoxContainer *main_vbox;
262 
263 	//map use to cache the instanced editors
264 	Map<StringName, List<EditorProperty *> > editor_property_map;
265 	List<EditorInspectorSection *> sections;
266 	Set<StringName> pending;
267 
268 	void _clear();
269 	Object *object;
270 
271 	//
272 
273 	LineEdit *search_box;
274 	bool show_categories;
275 	bool hide_script;
276 	bool use_doc_hints;
277 	bool capitalize_paths;
278 	bool use_filter;
279 	bool autoclear;
280 	bool use_folding;
281 	int changing;
282 	bool update_all_pending;
283 	bool read_only;
284 	bool keying;
285 	bool sub_inspector;
286 
287 	float refresh_countdown;
288 	bool update_tree_pending;
289 	StringName _prop_edited;
290 	StringName property_selected;
291 	int property_focusable;
292 	int update_scroll_request;
293 
294 	Map<StringName, Map<StringName, String> > descr_cache;
295 	Map<StringName, String> class_descr_cache;
296 	Set<StringName> restart_request_props;
297 
298 	Map<ObjectID, int> scroll_cache;
299 
300 	String property_prefix; //used for sectioned inspector
301 	String object_class;
302 
303 	void _edit_set(const String &p_name, const Variant &p_value, bool p_refresh_all, const String &p_changed_field);
304 
305 	void _property_changed(const String &p_path, const Variant &p_value, const String &p_name = "", bool changing = false);
306 	void _property_changed_update_all(const String &p_path, const Variant &p_value, const String &p_name = "", bool p_changing = false);
307 	void _multiple_properties_changed(Vector<String> p_paths, Array p_values);
308 	void _property_keyed(const String &p_path, bool p_advance);
309 	void _property_keyed_with_value(const String &p_path, const Variant &p_value, bool p_advance);
310 
311 	void _property_checked(const String &p_path, bool p_checked);
312 
313 	void _resource_selected(const String &p_path, RES p_resource);
314 	void _property_selected(const String &p_path, int p_focusable);
315 	void _object_id_selected(const String &p_path, ObjectID p_id);
316 
317 	void _node_removed(Node *p_node);
318 
319 	void _changed_callback(Object *p_changed, const char *p_prop);
320 	void _edit_request_change(Object *p_object, const String &p_prop);
321 
322 	void _filter_changed(const String &p_text);
323 	void _parse_added_editors(VBoxContainer *current_vbox, Ref<EditorInspectorPlugin> ped);
324 
325 	void _vscroll_changed(double);
326 
327 	void _feature_profile_changed();
328 
329 	bool _is_property_disabled_by_feature_profile(const StringName &p_property);
330 
331 protected:
332 	static void _bind_methods();
333 	void _notification(int p_what);
334 
335 public:
336 	static void add_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
337 	static void remove_inspector_plugin(const Ref<EditorInspectorPlugin> &p_plugin);
338 	static void cleanup_plugins();
339 
340 	static EditorProperty *instantiate_property_editor(Object *p_object, Variant::Type p_type, const String &p_path, PropertyHint p_hint, const String &p_hint_text, int p_usage);
341 
342 	void set_undo_redo(UndoRedo *p_undo_redo);
343 
344 	String get_selected_path() const;
345 
346 	void update_tree();
347 	void update_property(const String &p_prop);
348 
349 	void refresh();
350 
351 	void edit(Object *p_object);
352 	Object *get_edited_object();
353 
354 	void set_keying(bool p_active);
355 	void set_read_only(bool p_read_only);
356 
357 	bool is_capitalize_paths_enabled() const;
358 	void set_enable_capitalize_paths(bool p_capitalize);
359 	void set_autoclear(bool p_enable);
360 
361 	void set_show_categories(bool p_show);
362 	void set_use_doc_hints(bool p_enable);
363 	void set_hide_script(bool p_hide);
364 
365 	void set_use_filter(bool p_use);
366 	void register_text_enter(Node *p_line_edit);
367 
368 	void set_use_folding(bool p_enable);
369 	bool is_using_folding();
370 
371 	void collapse_all_folding();
372 	void expand_all_folding();
373 
374 	void set_scroll_offset(int p_offset);
375 	int get_scroll_offset() const;
376 
377 	void set_property_prefix(const String &p_prefix);
378 	String get_property_prefix() const;
379 
380 	void set_object_class(const String &p_class);
381 	String get_object_class() const;
382 
383 	void set_sub_inspector(bool p_enable);
384 
385 	EditorInspector();
386 };
387 
388 #endif // INSPECTOR_H
389