OpenXR: Add support for binding modifiers

This commit is contained in:
Bastiaan Olij 2024-09-18 10:14:21 +10:00
parent c2e4ae782a
commit 0a61ebdcea
56 changed files with 3127 additions and 763 deletions

View file

@ -37,7 +37,8 @@
#include "editor/gui/editor_file_dialog.h"
#include "editor/themes/editor_scale.h"
// TODO implement redo/undo system
HashMap<String, String> OpenXRActionMapEditor::interaction_profile_editors;
HashMap<String, String> OpenXRActionMapEditor::binding_modifier_editors;
void OpenXRActionMapEditor::_bind_methods() {
ClassDB::bind_method("_add_action_set_editor", &OpenXRActionMapEditor::_add_action_set_editor);
@ -50,6 +51,9 @@ void OpenXRActionMapEditor::_bind_methods() {
ClassDB::bind_method(D_METHOD("_do_remove_action_set_editor", "action_set_editor"), &OpenXRActionMapEditor::_do_remove_action_set_editor);
ClassDB::bind_method(D_METHOD("_do_add_interaction_profile_editor", "interaction_profile_editor"), &OpenXRActionMapEditor::_do_add_interaction_profile_editor);
ClassDB::bind_method(D_METHOD("_do_remove_interaction_profile_editor", "interaction_profile_editor"), &OpenXRActionMapEditor::_do_remove_interaction_profile_editor);
ClassDB::bind_static_method("OpenXRActionMapEditor", D_METHOD("register_interaction_profile_editor", "interaction_profile_path", "editor_class"), &OpenXRActionMapEditor::register_interaction_profile_editor);
ClassDB::bind_static_method("OpenXRActionMapEditor", D_METHOD("register_binding_modifier_editor", "binding_modifier_class", "editor_class"), &OpenXRActionMapEditor::register_binding_modifier_editor);
}
void OpenXRActionMapEditor::_notification(int p_what) {
@ -100,19 +104,32 @@ OpenXRInteractionProfileEditorBase *OpenXRActionMapEditor::_add_interaction_prof
// need to instance the correct editor for our profile
OpenXRInteractionProfileEditorBase *new_profile_editor = nullptr;
if (profile_path == "placeholder_text") {
// instance specific editor for this type
} else {
if (interaction_profile_editors.has(profile_path)) {
Object *new_editor = ClassDB::instantiate(interaction_profile_editors[profile_path]);
if (new_editor) {
new_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(new_editor);
if (!new_profile_editor) {
WARN_PRINT("Interaction profile editor type mismatch for " + profile_path);
memfree(new_editor);
}
}
}
if (!new_profile_editor) {
// instance generic editor
new_profile_editor = memnew(OpenXRInteractionProfileEditor(action_map, p_interaction_profile));
new_profile_editor = memnew(OpenXRInteractionProfileEditor);
}
// now add it in..
ERR_FAIL_NULL_V(new_profile_editor, nullptr);
new_profile_editor->setup(action_map, p_interaction_profile);
tabs->add_child(new_profile_editor);
new_profile_editor->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
tabs->set_tab_button_icon(tabs->get_tab_count() - 1, get_theme_icon(SNAME("close"), SNAME("TabBar")));
if (!new_profile_editor->tooltip.is_empty()) {
tabs->set_tab_tooltip(tabs->get_tab_count() - 1, new_profile_editor->tooltip);
}
return new_profile_editor;
}
@ -195,8 +212,19 @@ void OpenXRActionMapEditor::_on_remove_action_set(Object *p_action_set_editor) {
Ref<OpenXRActionSet> action_set = action_set_editor->get_action_set();
ERR_FAIL_COND(action_set.is_null());
// Remove all actions first.
action_set_editor->remove_all_actions();
// Make sure we update our interaction profiles.
for (int i = 0; i < tabs->get_tab_count(); i++) {
// First tab won't be an interaction profile editor, but being thorough..
OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(i));
if (interaction_profile_editor) {
interaction_profile_editor->remove_all_for_action_set(action_set);
}
}
// And now we can remove our action set.
undo_redo->create_action(TTR("Remove action set"));
undo_redo->add_do_method(this, "_do_remove_action_set_editor", action_set_editor);
undo_redo->add_undo_method(this, "_do_add_action_set_editor", action_set_editor);
@ -210,7 +238,7 @@ void OpenXRActionMapEditor::_on_action_removed(Ref<OpenXRAction> p_action) {
// First tab won't be an interaction profile editor, but being thorough..
OpenXRInteractionProfileEditorBase *interaction_profile_editor = Object::cast_to<OpenXRInteractionProfileEditorBase>(tabs->get_tab_control(i));
if (interaction_profile_editor) {
interaction_profile_editor->remove_all_bindings_for_action(p_action);
interaction_profile_editor->remove_all_for_action(p_action);
}
}
}
@ -387,6 +415,22 @@ void OpenXRActionMapEditor::_clear_action_map() {
}
}
void OpenXRActionMapEditor::register_interaction_profile_editor(const String &p_for_path, const String &p_editor_class) {
interaction_profile_editors[p_for_path] = p_editor_class;
}
void OpenXRActionMapEditor::register_binding_modifier_editor(const String &p_binding_modifier_class, const String &p_editor_class) {
binding_modifier_editors[p_binding_modifier_class] = p_editor_class;
}
String OpenXRActionMapEditor::get_binding_modifier_editor_class(const String &p_binding_modifier_class) {
if (binding_modifier_editors.has(p_binding_modifier_class)) {
return binding_modifier_editors[p_binding_modifier_class];
}
return OpenXRBindingModifierEditor::get_class_static();
}
OpenXRActionMapEditor::OpenXRActionMapEditor() {
undo_redo = EditorUndoRedoManager::get_singleton();
set_custom_minimum_size(Size2(0.0, 300.0));