1/**************************************************************************/
2/* openxr_action_set_editor.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 "openxr_action_set_editor.h"
32
33#include "editor/editor_string_names.h"
34#include "openxr_action_editor.h"
35
36void OpenXRActionSetEditor::_bind_methods() {
37 ClassDB::bind_method(D_METHOD("_do_set_name", "name"), &OpenXRActionSetEditor::_do_set_name);
38 ClassDB::bind_method(D_METHOD("_do_set_localized_name", "name"), &OpenXRActionSetEditor::_do_set_localized_name);
39 ClassDB::bind_method(D_METHOD("_do_set_priority", "value"), &OpenXRActionSetEditor::_do_set_priority);
40 ClassDB::bind_method(D_METHOD("_do_add_action_editor", "action_editor"), &OpenXRActionSetEditor::_do_add_action_editor);
41 ClassDB::bind_method(D_METHOD("_do_remove_action_editor", "action_editor"), &OpenXRActionSetEditor::_do_remove_action_editor);
42
43 ADD_SIGNAL(MethodInfo("remove", PropertyInfo(Variant::OBJECT, "action_set_editor")));
44 ADD_SIGNAL(MethodInfo("action_removed", PropertyInfo(Variant::OBJECT, "action")));
45}
46
47void OpenXRActionSetEditor::_set_fold_icon() {
48 if (is_expanded) {
49 fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons)));
50 } else {
51 fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons)));
52 }
53}
54
55void OpenXRActionSetEditor::_theme_changed() {
56 _set_fold_icon();
57 add_action->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
58 rem_action_set->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
59}
60
61void OpenXRActionSetEditor::_notification(int p_what) {
62 switch (p_what) {
63 case NOTIFICATION_ENTER_TREE:
64 case NOTIFICATION_THEME_CHANGED: {
65 _theme_changed();
66 panel->add_theme_style_override("panel", get_theme_stylebox(SNAME("panel"), SNAME("TabContainer")));
67 } break;
68 }
69}
70
71OpenXRActionEditor *OpenXRActionSetEditor::_add_action_editor(Ref<OpenXRAction> p_action) {
72 OpenXRActionEditor *action_editor = memnew(OpenXRActionEditor(p_action));
73 action_editor->connect("remove", callable_mp(this, &OpenXRActionSetEditor::_on_remove_action));
74 actions_vb->add_child(action_editor);
75
76 return action_editor;
77}
78
79void OpenXRActionSetEditor::_on_toggle_expand() {
80 is_expanded = !is_expanded;
81 actions_vb->set_visible(is_expanded);
82 _set_fold_icon();
83}
84
85void OpenXRActionSetEditor::_on_action_set_name_changed(const String p_new_text) {
86 if (action_set->get_name() != p_new_text) {
87 undo_redo->create_action(TTR("Rename Action Set"));
88 undo_redo->add_do_method(this, "_do_set_name", p_new_text);
89 undo_redo->add_undo_method(this, "_do_set_name", action_set->get_name());
90 undo_redo->commit_action(false);
91
92 // If our localized name matches our action set name, set this too
93 if (action_set->get_name() == action_set->get_localized_name()) {
94 undo_redo->create_action(TTR("Rename Action Sets Localized name"));
95 undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text);
96 undo_redo->add_undo_method(this, "_do_set_localized_name", action_set->get_localized_name());
97 undo_redo->commit_action(false);
98
99 action_set->set_localized_name(p_new_text);
100 action_set_localized_name->set_text(p_new_text);
101 }
102 action_set->set_name(p_new_text);
103 action_set->set_edited(true);
104 }
105}
106
107void OpenXRActionSetEditor::_do_set_name(const String p_new_text) {
108 action_set->set_name(p_new_text);
109 action_set_name->set_text(p_new_text);
110}
111
112void OpenXRActionSetEditor::_on_action_set_localized_name_changed(const String p_new_text) {
113 if (action_set->get_localized_name() != p_new_text) {
114 undo_redo->create_action(TTR("Rename Action Sets Localized name"));
115 undo_redo->add_do_method(this, "_do_set_localized_name", p_new_text);
116 undo_redo->add_undo_method(this, "_do_set_localized_name", action_set->get_localized_name());
117 undo_redo->commit_action(false);
118
119 action_set->set_localized_name(p_new_text);
120 action_set->set_edited(true);
121 }
122}
123
124void OpenXRActionSetEditor::_do_set_localized_name(const String p_new_text) {
125 action_set->set_localized_name(p_new_text);
126 action_set_localized_name->set_text(p_new_text);
127}
128
129void OpenXRActionSetEditor::_on_action_set_priority_changed(const String p_new_text) {
130 int64_t value = p_new_text.to_int();
131
132 if (action_set->get_priority() != value) {
133 undo_redo->create_action(TTR("Change Action Sets priority"));
134 undo_redo->add_do_method(this, "_do_set_priority", value);
135 undo_redo->add_undo_method(this, "_do_set_priority", action_set->get_priority());
136 undo_redo->commit_action(false);
137
138 action_set->set_priority(value);
139 action_set->set_edited(true);
140 }
141}
142
143void OpenXRActionSetEditor::_do_set_priority(int64_t p_value) {
144 action_set->set_priority(p_value);
145 action_set_priority->set_text(itos(p_value));
146}
147
148void OpenXRActionSetEditor::_on_add_action() {
149 Ref<OpenXRAction> new_action;
150
151 new_action.instantiate();
152 new_action->set_name("New");
153 new_action->set_localized_name("New");
154 action_set->add_action(new_action);
155 action_set->set_edited(true);
156
157 OpenXRActionEditor *action_editor = _add_action_editor(new_action);
158
159 undo_redo->create_action(TTR("Add action"));
160 undo_redo->add_do_method(this, "_do_add_action_editor", action_editor);
161 undo_redo->add_undo_method(this, "_do_remove_action_editor", action_editor);
162 undo_redo->commit_action(false);
163
164 // TODO handle focus
165}
166
167void OpenXRActionSetEditor::_on_remove_action_set() {
168 emit_signal("remove", this);
169}
170
171void OpenXRActionSetEditor::_on_remove_action(Object *p_action_editor) {
172 OpenXRActionEditor *action_editor = Object::cast_to<OpenXRActionEditor>(p_action_editor);
173 ERR_FAIL_NULL(action_editor);
174 ERR_FAIL_COND(action_editor->get_parent() != actions_vb);
175 Ref<OpenXRAction> action = action_editor->get_action();
176 ERR_FAIL_COND(action.is_null());
177
178 emit_signal("action_removed", action);
179
180 undo_redo->create_action(TTR("Delete action"));
181 undo_redo->add_do_method(this, "_do_remove_action_editor", action_editor);
182 undo_redo->add_undo_method(this, "_do_add_action_editor", action_editor);
183 undo_redo->commit_action(true);
184
185 action_set->set_edited(true);
186}
187
188void OpenXRActionSetEditor::_do_add_action_editor(OpenXRActionEditor *p_action_editor) {
189 Ref<OpenXRAction> action = p_action_editor->get_action();
190 ERR_FAIL_COND(action.is_null());
191
192 action_set->add_action(action);
193 actions_vb->add_child(p_action_editor);
194}
195
196void OpenXRActionSetEditor::_do_remove_action_editor(OpenXRActionEditor *p_action_editor) {
197 Ref<OpenXRAction> action = p_action_editor->get_action();
198 ERR_FAIL_COND(action.is_null());
199
200 actions_vb->remove_child(p_action_editor);
201 action_set->remove_action(action);
202}
203
204void OpenXRActionSetEditor::remove_all_actions() {
205 for (int i = actions_vb->get_child_count(); i > 0; --i) {
206 _on_remove_action(actions_vb->get_child(i));
207 }
208}
209
210void OpenXRActionSetEditor::set_focus_on_entry() {
211 ERR_FAIL_NULL(action_set_name);
212 action_set_name->grab_focus();
213}
214
215OpenXRActionSetEditor::OpenXRActionSetEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRActionSet> p_action_set) {
216 undo_redo = EditorUndoRedoManager::get_singleton();
217 action_map = p_action_map;
218 action_set = p_action_set;
219
220 set_h_size_flags(Control::SIZE_EXPAND_FILL);
221
222 panel = memnew(PanelContainer);
223 panel->set_h_size_flags(Control::SIZE_EXPAND_FILL);
224 add_child(panel);
225
226 HBoxContainer *panel_hb = memnew(HBoxContainer);
227 panel_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
228 panel->add_child(panel_hb);
229
230 fold_btn = memnew(Button);
231 fold_btn->set_v_size_flags(Control::SIZE_SHRINK_BEGIN);
232 fold_btn->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_toggle_expand));
233 fold_btn->set_flat(true);
234 panel_hb->add_child(fold_btn);
235
236 main_vb = memnew(VBoxContainer);
237 main_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
238 panel_hb->add_child(main_vb);
239
240 action_set_hb = memnew(HBoxContainer);
241 action_set_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
242 main_vb->add_child(action_set_hb);
243
244 action_set_name = memnew(LineEdit);
245 action_set_name->set_text(action_set->get_name());
246 action_set_name->set_custom_minimum_size(Size2(150.0, 0.0));
247 action_set_name->connect("text_changed", callable_mp(this, &OpenXRActionSetEditor::_on_action_set_name_changed));
248 action_set_hb->add_child(action_set_name);
249
250 action_set_localized_name = memnew(LineEdit);
251 action_set_localized_name->set_text(action_set->get_localized_name());
252 action_set_localized_name->set_custom_minimum_size(Size2(150.0, 0.0));
253 action_set_localized_name->set_h_size_flags(Control::SIZE_EXPAND_FILL);
254 action_set_localized_name->connect("text_changed", callable_mp(this, &OpenXRActionSetEditor::_on_action_set_localized_name_changed));
255 action_set_hb->add_child(action_set_localized_name);
256
257 action_set_priority = memnew(TextEdit);
258 action_set_priority->set_text(itos(action_set->get_priority()));
259 action_set_priority->set_custom_minimum_size(Size2(50.0, 0.0));
260 action_set_priority->connect("text_changed", callable_mp(this, &OpenXRActionSetEditor::_on_action_set_priority_changed));
261 action_set_hb->add_child(action_set_priority);
262
263 add_action = memnew(Button);
264 add_action->set_tooltip_text("Add Action.");
265 add_action->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_add_action));
266 add_action->set_flat(true);
267 action_set_hb->add_child(add_action);
268
269 rem_action_set = memnew(Button);
270 rem_action_set->set_tooltip_text("Remove Action Set.");
271 rem_action_set->connect("pressed", callable_mp(this, &OpenXRActionSetEditor::_on_remove_action_set));
272 rem_action_set->set_flat(true);
273 action_set_hb->add_child(rem_action_set);
274
275 actions_vb = memnew(VBoxContainer);
276 actions_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
277 main_vb->add_child(actions_vb);
278
279 // Add our existing actions
280 Array actions = action_set->get_actions();
281 for (int i = 0; i < actions.size(); i++) {
282 Ref<OpenXRAction> action = actions[i];
283 _add_action_editor(action);
284 }
285}
286