feat: updated engine version to 4.4-rc1
This commit is contained in:
parent
ee00efde1f
commit
21ba8e33af
5459 changed files with 1128836 additions and 198305 deletions
|
|
@ -1,5 +1,11 @@
|
|||
#!/usr/bin/env python
|
||||
from misc.utility.scons_hints import *
|
||||
|
||||
Import("env")
|
||||
Import("env_openxr")
|
||||
|
||||
env.add_source_files(env.modules_sources, "*.cpp")
|
||||
module_obj = []
|
||||
|
||||
env_openxr.add_source_files(module_obj, "*.cpp")
|
||||
|
||||
env.modules_sources += module_obj
|
||||
|
|
|
|||
|
|
@ -41,7 +41,7 @@ void OpenXRActionEditor::_bind_methods() {
|
|||
}
|
||||
|
||||
void OpenXRActionEditor::_theme_changed() {
|
||||
rem_action->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
|
||||
rem_action->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
|
||||
}
|
||||
|
||||
void OpenXRActionEditor::_notification(int p_what) {
|
||||
|
|
|
|||
|
|
@ -68,7 +68,7 @@ protected:
|
|||
void _do_set_action_type(OpenXRAction::ActionType p_action_type);
|
||||
|
||||
public:
|
||||
Ref<OpenXRAction> get_action() { return action; };
|
||||
Ref<OpenXRAction> get_action() { return action; }
|
||||
OpenXRActionEditor(Ref<OpenXRAction> p_action);
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -32,12 +32,11 @@
|
|||
|
||||
#include "core/config/project_settings.h"
|
||||
#include "editor/editor_node.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/gui/editor_bottom_panel.h"
|
||||
#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 +49,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 +102,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 +210,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 +236,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 +413,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));
|
||||
|
|
|
|||
|
|
@ -36,6 +36,7 @@
|
|||
#include "openxr_interaction_profile_editor.h"
|
||||
#include "openxr_select_interaction_profile_dialog.h"
|
||||
|
||||
#include "core/templates/hash_map.h"
|
||||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
|
|
@ -48,6 +49,9 @@ class OpenXRActionMapEditor : public VBoxContainer {
|
|||
GDCLASS(OpenXRActionMapEditor, VBoxContainer);
|
||||
|
||||
private:
|
||||
static HashMap<String, String> interaction_profile_editors; // interaction profile path, interaction profile editor
|
||||
static HashMap<String, String> binding_modifier_editors; // binding modifier class, binding modifiers editor
|
||||
|
||||
EditorUndoRedoManager *undo_redo;
|
||||
String edited_path;
|
||||
Ref<OpenXRActionMap> action_map;
|
||||
|
|
@ -100,6 +104,10 @@ protected:
|
|||
void _do_remove_interaction_profile_editor(OpenXRInteractionProfileEditorBase *p_interaction_profile_editor);
|
||||
|
||||
public:
|
||||
static void register_interaction_profile_editor(const String &p_for_path, const String &p_editor_class);
|
||||
static void register_binding_modifier_editor(const String &p_binding_modifier_class, const String &p_editor_class);
|
||||
static String get_binding_modifier_editor_class(const String &p_binding_modifier_class);
|
||||
|
||||
void open_action_map(String p_path);
|
||||
|
||||
OpenXRActionMapEditor();
|
||||
|
|
|
|||
|
|
@ -46,16 +46,16 @@ void OpenXRActionSetEditor::_bind_methods() {
|
|||
|
||||
void OpenXRActionSetEditor::_set_fold_icon() {
|
||||
if (is_expanded) {
|
||||
fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons)));
|
||||
fold_btn->set_button_icon(get_theme_icon(SNAME("GuiTreeArrowDown"), EditorStringName(EditorIcons)));
|
||||
} else {
|
||||
fold_btn->set_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons)));
|
||||
fold_btn->set_button_icon(get_theme_icon(SNAME("GuiTreeArrowRight"), EditorStringName(EditorIcons)));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRActionSetEditor::_theme_changed() {
|
||||
_set_fold_icon();
|
||||
add_action->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
|
||||
rem_action_set->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
|
||||
add_action->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
|
||||
rem_action_set->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
|
||||
}
|
||||
|
||||
void OpenXRActionSetEditor::_notification(int p_what) {
|
||||
|
|
|
|||
|
|
@ -87,7 +87,7 @@ protected:
|
|||
void _do_remove_action_editor(OpenXRActionEditor *p_action_editor);
|
||||
|
||||
public:
|
||||
Ref<OpenXRActionSet> get_action_set() { return action_set; };
|
||||
Ref<OpenXRActionSet> get_action_set() { return action_set; }
|
||||
void set_focus_on_entry();
|
||||
|
||||
void remove_all_actions();
|
||||
|
|
|
|||
289
engine/modules/openxr/editor/openxr_binding_modifier_editor.cpp
Normal file
289
engine/modules/openxr/editor/openxr_binding_modifier_editor.cpp
Normal file
|
|
@ -0,0 +1,289 @@
|
|||
/**************************************************************************/
|
||||
/* openxr_binding_modifier_editor.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "openxr_binding_modifier_editor.h"
|
||||
|
||||
#include "editor/editor_string_names.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EditorPropertyActionSet
|
||||
|
||||
void EditorPropertyActionSet::_set_read_only(bool p_read_only) {
|
||||
options->set_disabled(p_read_only);
|
||||
}
|
||||
|
||||
void EditorPropertyActionSet::_option_selected(int p_which) {
|
||||
Ref<OpenXRActionSet> val = options->get_item_metadata(p_which);
|
||||
emit_changed(get_edited_property(), val);
|
||||
}
|
||||
|
||||
void EditorPropertyActionSet::update_property() {
|
||||
Variant current = get_edited_property_value();
|
||||
if (current.get_type() == Variant::NIL) {
|
||||
options->select(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
Ref<OpenXRActionSet> which = current;
|
||||
for (int i = 0; i < options->get_item_count(); i++) {
|
||||
if (which == (Ref<OpenXRActionSet>)options->get_item_metadata(i)) {
|
||||
options->select(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find it? deselect..
|
||||
options->select(-1);
|
||||
}
|
||||
|
||||
void EditorPropertyActionSet::setup(const Ref<OpenXRActionMap> &p_action_map) {
|
||||
options->clear();
|
||||
|
||||
Array action_sets = p_action_map->get_action_sets();
|
||||
for (Ref<OpenXRActionSet> action_set : action_sets) {
|
||||
options->add_item(action_set->get_localized_name());
|
||||
options->set_item_metadata(-1, action_set);
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPropertyActionSet::set_option_button_clip(bool p_enable) {
|
||||
options->set_clip_text(p_enable);
|
||||
}
|
||||
|
||||
EditorPropertyActionSet::EditorPropertyActionSet() {
|
||||
options = memnew(OptionButton);
|
||||
options->set_clip_text(true);
|
||||
options->set_flat(true);
|
||||
options->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
|
||||
add_child(options);
|
||||
add_focusable(options);
|
||||
options->connect(SceneStringName(item_selected), callable_mp(this, &EditorPropertyActionSet::_option_selected));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// EditorPropertyBindingPath
|
||||
|
||||
void EditorPropertyBindingPath::_set_read_only(bool p_read_only) {
|
||||
options->set_disabled(p_read_only);
|
||||
}
|
||||
|
||||
void EditorPropertyBindingPath::_option_selected(int p_which) {
|
||||
String val = options->get_item_metadata(p_which);
|
||||
emit_changed(get_edited_property(), val);
|
||||
}
|
||||
|
||||
void EditorPropertyBindingPath::update_property() {
|
||||
Variant current = get_edited_property_value();
|
||||
if (current.get_type() == Variant::NIL) {
|
||||
options->select(-1);
|
||||
return;
|
||||
}
|
||||
|
||||
String which = current;
|
||||
for (int i = 0; i < options->get_item_count(); i++) {
|
||||
if (which == (String)options->get_item_metadata(i)) {
|
||||
options->select(i);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
// Couldn't find it? deselect..
|
||||
options->select(-1);
|
||||
}
|
||||
|
||||
void EditorPropertyBindingPath::setup(const String &p_interaction_profile_path, Vector<OpenXRAction::ActionType> p_include_action_types) {
|
||||
options->clear();
|
||||
|
||||
const OpenXRInteractionProfileMetadata::InteractionProfile *profile_def = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(p_interaction_profile_path);
|
||||
|
||||
// Determine toplevel paths
|
||||
Vector<String> top_level_paths;
|
||||
for (const OpenXRInteractionProfileMetadata::IOPath &io_path : profile_def->io_paths) {
|
||||
if (!top_level_paths.has(io_path.top_level_path)) {
|
||||
top_level_paths.push_back(io_path.top_level_path);
|
||||
}
|
||||
}
|
||||
|
||||
for (const String &top_level_path : top_level_paths) {
|
||||
String top_level_name = OpenXRInteractionProfileMetadata::get_singleton()->get_top_level_name(top_level_path);
|
||||
|
||||
for (const OpenXRInteractionProfileMetadata::IOPath &io_path : profile_def->io_paths) {
|
||||
if (io_path.top_level_path == top_level_path && p_include_action_types.has(io_path.action_type)) {
|
||||
options->add_item(top_level_name + "/" + io_path.display_name);
|
||||
options->set_item_metadata(-1, io_path.openxr_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
void EditorPropertyBindingPath::set_option_button_clip(bool p_enable) {
|
||||
options->set_clip_text(p_enable);
|
||||
}
|
||||
|
||||
EditorPropertyBindingPath::EditorPropertyBindingPath() {
|
||||
options = memnew(OptionButton);
|
||||
options->set_clip_text(true);
|
||||
options->set_flat(true);
|
||||
options->set_auto_translate_mode(AUTO_TRANSLATE_MODE_DISABLED);
|
||||
add_child(options);
|
||||
add_focusable(options);
|
||||
options->connect(SceneStringName(item_selected), callable_mp(this, &EditorPropertyBindingPath::_option_selected));
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// OpenXRBindingModifierEditor
|
||||
|
||||
bool EditorInspectorPluginBindingModifier::can_handle(Object *p_object) {
|
||||
Ref<OpenXRBindingModifier> binding_modifier(Object::cast_to<OpenXRBindingModifier>(p_object));
|
||||
return binding_modifier.is_valid();
|
||||
}
|
||||
|
||||
bool EditorInspectorPluginBindingModifier::parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) {
|
||||
Ref<OpenXRActionBindingModifier> action_binding_modifier(Object::cast_to<OpenXRActionBindingModifier>(p_object));
|
||||
if (action_binding_modifier.is_valid()) {
|
||||
if (p_type == Variant::OBJECT && p_hint == PROPERTY_HINT_RESOURCE_TYPE && p_hint_text == OpenXRActionSet::get_class_static()) {
|
||||
OpenXRIPBinding *ip_binding = action_binding_modifier->get_ip_binding();
|
||||
ERR_FAIL_NULL_V(ip_binding, false);
|
||||
|
||||
OpenXRActionMap *action_map = ip_binding->get_action_map();
|
||||
ERR_FAIL_NULL_V(action_map, false);
|
||||
|
||||
EditorPropertyActionSet *action_set_property = memnew(EditorPropertyActionSet);
|
||||
action_set_property->setup(action_map);
|
||||
add_property_editor(p_path, action_set_property);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
Ref<OpenXRIPBindingModifier> ip_binding_modifier(Object::cast_to<OpenXRIPBindingModifier>(p_object));
|
||||
if (ip_binding_modifier.is_valid()) {
|
||||
if (p_type == Variant::OBJECT && p_hint == PROPERTY_HINT_RESOURCE_TYPE && p_hint_text == OpenXRActionSet::get_class_static()) {
|
||||
OpenXRInteractionProfile *interaction_profile = ip_binding_modifier->get_interaction_profile();
|
||||
ERR_FAIL_NULL_V(interaction_profile, false);
|
||||
|
||||
OpenXRActionMap *action_map = interaction_profile->get_action_map();
|
||||
ERR_FAIL_NULL_V(action_map, false);
|
||||
|
||||
EditorPropertyActionSet *action_set_property = memnew(EditorPropertyActionSet);
|
||||
action_set_property->setup(action_map);
|
||||
add_property_editor(p_path, action_set_property);
|
||||
return true;
|
||||
}
|
||||
|
||||
if (p_type == Variant::STRING && p_hint == PROPERTY_HINT_TYPE_STRING && p_hint_text == "binding_path") {
|
||||
EditorPropertyBindingPath *binding_path_property = memnew(EditorPropertyBindingPath);
|
||||
|
||||
OpenXRInteractionProfile *interaction_profile = ip_binding_modifier->get_interaction_profile();
|
||||
ERR_FAIL_NULL_V(interaction_profile, false);
|
||||
|
||||
Vector<OpenXRAction::ActionType> action_types;
|
||||
action_types.push_back(OpenXRAction::OPENXR_ACTION_VECTOR2);
|
||||
binding_path_property->setup(interaction_profile->get_interaction_profile_path(), action_types);
|
||||
|
||||
add_property_editor(p_path, binding_path_property);
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////////////////////////////
|
||||
// OpenXRBindingModifierEditor
|
||||
|
||||
void OpenXRBindingModifierEditor::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("get_binding_modifier"), &OpenXRBindingModifierEditor::get_binding_modifier);
|
||||
ClassDB::bind_method(D_METHOD("setup", "action_map", "binding_modifier"), &OpenXRBindingModifierEditor::setup);
|
||||
|
||||
ADD_SIGNAL(MethodInfo("binding_modifier_removed", PropertyInfo(Variant::OBJECT, "binding_modifier_editor")));
|
||||
}
|
||||
|
||||
void OpenXRBindingModifierEditor::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_ENTER_TREE:
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
rem_binding_modifier_btn->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRBindingModifierEditor::_on_remove_binding_modifier() {
|
||||
// Tell parent to remove us
|
||||
emit_signal("binding_modifier_removed", this);
|
||||
}
|
||||
|
||||
OpenXRBindingModifierEditor::OpenXRBindingModifierEditor() {
|
||||
undo_redo = EditorUndoRedoManager::get_singleton();
|
||||
|
||||
set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
|
||||
main_vb = memnew(VBoxContainer);
|
||||
main_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
add_child(main_vb);
|
||||
|
||||
header_hb = memnew(HBoxContainer);
|
||||
header_hb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
main_vb->add_child(header_hb);
|
||||
|
||||
binding_modifier_title = memnew(Label);
|
||||
binding_modifier_title->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
header_hb->add_child(binding_modifier_title);
|
||||
|
||||
rem_binding_modifier_btn = memnew(Button);
|
||||
rem_binding_modifier_btn->set_tooltip_text(TTR("Remove binding modifier."));
|
||||
rem_binding_modifier_btn->connect(SceneStringName(pressed), callable_mp(this, &OpenXRBindingModifierEditor::_on_remove_binding_modifier));
|
||||
rem_binding_modifier_btn->set_flat(true);
|
||||
header_hb->add_child(rem_binding_modifier_btn);
|
||||
|
||||
editor_inspector = memnew(EditorInspector);
|
||||
editor_inspector->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
|
||||
editor_inspector->set_vertical_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
|
||||
editor_inspector->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
main_vb->add_child(editor_inspector);
|
||||
}
|
||||
|
||||
void OpenXRBindingModifierEditor::setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRBindingModifier> p_binding_modifier) {
|
||||
ERR_FAIL_NULL(binding_modifier_title);
|
||||
ERR_FAIL_NULL(editor_inspector);
|
||||
|
||||
action_map = p_action_map;
|
||||
binding_modifier = p_binding_modifier;
|
||||
|
||||
if (p_binding_modifier.is_valid()) {
|
||||
binding_modifier_title->set_text(p_binding_modifier->get_description());
|
||||
|
||||
editor_inspector->set_object_class(p_binding_modifier->get_class());
|
||||
editor_inspector->edit(p_binding_modifier.ptr());
|
||||
}
|
||||
}
|
||||
113
engine/modules/openxr/editor/openxr_binding_modifier_editor.h
Normal file
113
engine/modules/openxr/editor/openxr_binding_modifier_editor.h
Normal file
|
|
@ -0,0 +1,113 @@
|
|||
/**************************************************************************/
|
||||
/* openxr_binding_modifier_editor.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef OPENXR_BINDING_MODIFIER_EDITOR_H
|
||||
#define OPENXR_BINDING_MODIFIER_EDITOR_H
|
||||
|
||||
#include "../action_map/openxr_action_map.h"
|
||||
#include "../action_map/openxr_action_set.h"
|
||||
#include "../action_map/openxr_binding_modifier.h"
|
||||
#include "editor/editor_inspector.h"
|
||||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/panel_container.h"
|
||||
|
||||
class EditorPropertyActionSet : public EditorProperty {
|
||||
GDCLASS(EditorPropertyActionSet, EditorProperty);
|
||||
OptionButton *options = nullptr;
|
||||
|
||||
void _option_selected(int p_which);
|
||||
|
||||
protected:
|
||||
virtual void _set_read_only(bool p_read_only) override;
|
||||
|
||||
public:
|
||||
void setup(const Ref<OpenXRActionMap> &p_action_map);
|
||||
virtual void update_property() override;
|
||||
void set_option_button_clip(bool p_enable);
|
||||
EditorPropertyActionSet();
|
||||
};
|
||||
|
||||
class EditorPropertyBindingPath : public EditorProperty {
|
||||
GDCLASS(EditorPropertyBindingPath, EditorProperty);
|
||||
OptionButton *options = nullptr;
|
||||
|
||||
void _option_selected(int p_which);
|
||||
|
||||
protected:
|
||||
virtual void _set_read_only(bool p_read_only) override;
|
||||
|
||||
public:
|
||||
void setup(const String &p_interaction_profile_path, Vector<OpenXRAction::ActionType> p_include_action_types);
|
||||
virtual void update_property() override;
|
||||
void set_option_button_clip(bool p_enable);
|
||||
EditorPropertyBindingPath();
|
||||
};
|
||||
|
||||
class EditorInspectorPluginBindingModifier : public EditorInspectorPlugin {
|
||||
GDCLASS(EditorInspectorPluginBindingModifier, EditorInspectorPlugin);
|
||||
|
||||
public:
|
||||
virtual bool can_handle(Object *p_object) override;
|
||||
virtual bool parse_property(Object *p_object, const Variant::Type p_type, const String &p_path, const PropertyHint p_hint, const String &p_hint_text, const BitField<PropertyUsageFlags> p_usage, const bool p_wide) override;
|
||||
};
|
||||
|
||||
class OpenXRBindingModifierEditor : public PanelContainer {
|
||||
GDCLASS(OpenXRBindingModifierEditor, PanelContainer);
|
||||
|
||||
private:
|
||||
HBoxContainer *header_hb = nullptr;
|
||||
Label *binding_modifier_title = nullptr;
|
||||
Button *rem_binding_modifier_btn = nullptr;
|
||||
EditorInspector *editor_inspector = nullptr;
|
||||
|
||||
protected:
|
||||
VBoxContainer *main_vb = nullptr;
|
||||
|
||||
EditorUndoRedoManager *undo_redo;
|
||||
Ref<OpenXRBindingModifier> binding_modifier;
|
||||
Ref<OpenXRActionMap> action_map;
|
||||
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
void _on_remove_binding_modifier();
|
||||
|
||||
public:
|
||||
Ref<OpenXRBindingModifier> get_binding_modifier() const { return binding_modifier; }
|
||||
|
||||
virtual void setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRBindingModifier> p_binding_modifier);
|
||||
|
||||
OpenXRBindingModifierEditor();
|
||||
};
|
||||
|
||||
#endif // OPENXR_BINDING_MODIFIER_EDITOR_H
|
||||
257
engine/modules/openxr/editor/openxr_binding_modifiers_dialog.cpp
Normal file
257
engine/modules/openxr/editor/openxr_binding_modifiers_dialog.cpp
Normal file
|
|
@ -0,0 +1,257 @@
|
|||
/**************************************************************************/
|
||||
/* openxr_binding_modifiers_dialog.cpp */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#include "openxr_binding_modifiers_dialog.h"
|
||||
#include "../action_map/openxr_interaction_profile_metadata.h"
|
||||
#include "openxr_action_map_editor.h"
|
||||
|
||||
void OpenXRBindingModifiersDialog::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("_do_add_binding_modifier_editor", "binding_modifier_editor"), &OpenXRBindingModifiersDialog::_do_add_binding_modifier_editor);
|
||||
ClassDB::bind_method(D_METHOD("_do_remove_binding_modifier_editor", "binding_modifier_editor"), &OpenXRBindingModifiersDialog::_do_remove_binding_modifier_editor);
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::_notification(int p_what) {
|
||||
switch (p_what) {
|
||||
case NOTIFICATION_READY: {
|
||||
_create_binding_modifiers();
|
||||
} break;
|
||||
|
||||
case NOTIFICATION_THEME_CHANGED: {
|
||||
if (binding_modifier_sc) {
|
||||
binding_modifier_sc->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
|
||||
}
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
OpenXRBindingModifierEditor *OpenXRBindingModifiersDialog::_add_binding_modifier_editor(Ref<OpenXRBindingModifier> p_binding_modifier) {
|
||||
ERR_FAIL_COND_V(p_binding_modifier.is_null(), nullptr);
|
||||
|
||||
String class_name = p_binding_modifier->get_class();
|
||||
ERR_FAIL_COND_V(class_name.is_empty(), nullptr);
|
||||
String editor_class = OpenXRActionMapEditor::get_binding_modifier_editor_class(class_name);
|
||||
ERR_FAIL_COND_V(editor_class.is_empty(), nullptr);
|
||||
|
||||
OpenXRBindingModifierEditor *new_editor = nullptr;
|
||||
|
||||
Object *obj = ClassDB::instantiate(editor_class);
|
||||
if (obj) {
|
||||
new_editor = Object::cast_to<OpenXRBindingModifierEditor>(obj);
|
||||
if (!new_editor) {
|
||||
// Not of correct type?? Free it.
|
||||
memfree(obj);
|
||||
}
|
||||
}
|
||||
ERR_FAIL_NULL_V(new_editor, nullptr);
|
||||
|
||||
new_editor->setup(action_map, p_binding_modifier);
|
||||
new_editor->connect("binding_modifier_removed", callable_mp(this, &OpenXRBindingModifiersDialog::_on_remove_binding_modifier));
|
||||
|
||||
binding_modifiers_vb->add_child(new_editor);
|
||||
new_editor->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
|
||||
|
||||
return new_editor;
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::_create_binding_modifiers() {
|
||||
Array new_binding_modifiers;
|
||||
|
||||
if (ip_binding.is_valid()) {
|
||||
new_binding_modifiers = ip_binding->get_binding_modifiers();
|
||||
} else if (interaction_profile.is_valid()) {
|
||||
new_binding_modifiers = interaction_profile->get_binding_modifiers();
|
||||
} else {
|
||||
ERR_FAIL_MSG("No binding nor interaction profile specified.");
|
||||
}
|
||||
|
||||
for (int i = 0; i < new_binding_modifiers.size(); i++) {
|
||||
Ref<OpenXRBindingModifier> binding_modifier = new_binding_modifiers[i];
|
||||
_add_binding_modifier_editor(binding_modifier);
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::_on_add_binding_modifier() {
|
||||
create_dialog->popup_create(false);
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::_on_remove_binding_modifier(Object *p_binding_modifier_editor) {
|
||||
if (ip_binding.is_valid()) {
|
||||
ip_binding->set_edited(true);
|
||||
} else if (interaction_profile.is_valid()) {
|
||||
interaction_profile->set_edited(true);
|
||||
} else {
|
||||
ERR_FAIL_MSG("No binding nor interaction profile specified.");
|
||||
}
|
||||
|
||||
OpenXRBindingModifierEditor *binding_modifier_editor = Object::cast_to<OpenXRBindingModifierEditor>(p_binding_modifier_editor);
|
||||
ERR_FAIL_NULL(binding_modifier_editor);
|
||||
ERR_FAIL_COND(binding_modifier_editor->get_parent() != binding_modifiers_vb);
|
||||
|
||||
undo_redo->create_action(TTR("Remove binding modifier"));
|
||||
undo_redo->add_do_method(this, "_do_remove_binding_modifier_editor", binding_modifier_editor);
|
||||
undo_redo->add_undo_method(this, "_do_add_binding_modifier_editor", binding_modifier_editor);
|
||||
undo_redo->commit_action(true);
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::_on_dialog_created() {
|
||||
// Instance new binding modifier object
|
||||
Variant obj = create_dialog->instantiate_selected();
|
||||
ERR_FAIL_COND(obj.get_type() != Variant::OBJECT);
|
||||
|
||||
Ref<OpenXRBindingModifier> new_binding_modifier = obj;
|
||||
ERR_FAIL_COND(new_binding_modifier.is_null());
|
||||
|
||||
if (ip_binding.is_valid()) {
|
||||
// Add it to our binding.
|
||||
ip_binding->add_binding_modifier(new_binding_modifier);
|
||||
ip_binding->set_edited(true);
|
||||
} else if (interaction_profile.is_valid()) {
|
||||
// Add it to our interaction profile.
|
||||
interaction_profile->add_binding_modifier(new_binding_modifier);
|
||||
interaction_profile->set_edited(true);
|
||||
} else {
|
||||
ERR_FAIL_MSG("No binding nor interaction profile specified.");
|
||||
}
|
||||
|
||||
// Create our editor for this.
|
||||
OpenXRBindingModifierEditor *binding_modifier_editor = _add_binding_modifier_editor(new_binding_modifier);
|
||||
ERR_FAIL_NULL(binding_modifier_editor);
|
||||
|
||||
// Add undo/redo.
|
||||
undo_redo->create_action(TTR("Add binding modifier"));
|
||||
undo_redo->add_do_method(this, "_do_add_binding_modifier_editor", binding_modifier_editor);
|
||||
undo_redo->add_undo_method(this, "_do_remove_binding_modifier_editor", binding_modifier_editor);
|
||||
undo_redo->commit_action(false);
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::_do_add_binding_modifier_editor(OpenXRBindingModifierEditor *p_binding_modifier_editor) {
|
||||
Ref<OpenXRBindingModifier> binding_modifier = p_binding_modifier_editor->get_binding_modifier();
|
||||
ERR_FAIL_COND(binding_modifier.is_null());
|
||||
|
||||
if (ip_binding.is_valid()) {
|
||||
// Add it to our binding
|
||||
ip_binding->add_binding_modifier(binding_modifier);
|
||||
} else if (interaction_profile.is_valid()) {
|
||||
// Add it to our interaction profile
|
||||
interaction_profile->add_binding_modifier(binding_modifier);
|
||||
} else {
|
||||
ERR_FAIL_MSG("No binding nor interaction profile specified.");
|
||||
}
|
||||
|
||||
binding_modifiers_vb->add_child(p_binding_modifier_editor);
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::_do_remove_binding_modifier_editor(OpenXRBindingModifierEditor *p_binding_modifier_editor) {
|
||||
Ref<OpenXRBindingModifier> binding_modifier = p_binding_modifier_editor->get_binding_modifier();
|
||||
ERR_FAIL_COND(binding_modifier.is_null());
|
||||
|
||||
if (ip_binding.is_valid()) {
|
||||
// Remove it from our binding.
|
||||
ip_binding->remove_binding_modifier(binding_modifier);
|
||||
} else if (interaction_profile.is_valid()) {
|
||||
// Removed it to from interaction profile.
|
||||
interaction_profile->remove_binding_modifier(binding_modifier);
|
||||
} else {
|
||||
ERR_FAIL_MSG("No binding nor interaction profile specified.");
|
||||
}
|
||||
|
||||
binding_modifiers_vb->remove_child(p_binding_modifier_editor);
|
||||
}
|
||||
|
||||
OpenXRBindingModifiersDialog::OpenXRBindingModifiersDialog() {
|
||||
undo_redo = EditorUndoRedoManager::get_singleton();
|
||||
|
||||
set_transient(true);
|
||||
|
||||
binding_modifier_sc = memnew(ScrollContainer);
|
||||
binding_modifier_sc->set_custom_minimum_size(Size2(350.0, 0.0));
|
||||
binding_modifier_sc->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
binding_modifier_sc->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
binding_modifier_sc->set_horizontal_scroll_mode(ScrollContainer::SCROLL_MODE_DISABLED);
|
||||
add_child(binding_modifier_sc);
|
||||
|
||||
binding_modifiers_vb = memnew(VBoxContainer);
|
||||
binding_modifiers_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
binding_modifier_sc->add_child(binding_modifiers_vb);
|
||||
|
||||
binding_warning_label = memnew(Label);
|
||||
binding_warning_label->set_autowrap_mode(TextServer::AUTOWRAP_WORD);
|
||||
binding_warning_label->set_text(TTR("Note: modifiers will only be applied if supported on the host system."));
|
||||
binding_modifiers_vb->add_child(binding_warning_label);
|
||||
|
||||
add_binding_modifier_btn = memnew(Button);
|
||||
add_binding_modifier_btn->set_text(TTR("Add binding modifier"));
|
||||
add_binding_modifier_btn->connect("pressed", callable_mp(this, &OpenXRBindingModifiersDialog::_on_add_binding_modifier));
|
||||
binding_modifiers_vb->add_child(add_binding_modifier_btn);
|
||||
|
||||
// TODO may need to create our own dialog for this that can filter on binding modifiers recorded on interaction profiles or on individual bindings.
|
||||
|
||||
create_dialog = memnew(CreateDialog);
|
||||
create_dialog->set_transient(true);
|
||||
create_dialog->connect("create", callable_mp(this, &OpenXRBindingModifiersDialog::_on_dialog_created));
|
||||
add_child(create_dialog);
|
||||
}
|
||||
|
||||
void OpenXRBindingModifiersDialog::setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile, Ref<OpenXRIPBinding> p_ip_binding) {
|
||||
OpenXRInteractionProfileMetadata *meta_data = OpenXRInteractionProfileMetadata::get_singleton();
|
||||
action_map = p_action_map;
|
||||
interaction_profile = p_interaction_profile;
|
||||
ip_binding = p_ip_binding;
|
||||
|
||||
String profile_path = interaction_profile->get_interaction_profile_path();
|
||||
|
||||
if (ip_binding.is_valid()) {
|
||||
String action_name = "unset";
|
||||
String path_name = "unset";
|
||||
|
||||
Ref<OpenXRAction> action = p_ip_binding->get_action();
|
||||
if (action.is_valid()) {
|
||||
action_name = action->get_name_with_set();
|
||||
}
|
||||
|
||||
const OpenXRInteractionProfileMetadata::IOPath *io_path = meta_data->get_io_path(profile_path, p_ip_binding->get_binding_path());
|
||||
if (io_path != nullptr) {
|
||||
path_name = io_path->display_name;
|
||||
}
|
||||
|
||||
create_dialog->set_base_type("OpenXRActionBindingModifier");
|
||||
set_title(TTR("Binding modifiers for:") + " " + action_name + ": " + path_name);
|
||||
} else if (interaction_profile.is_valid()) {
|
||||
String profile_name = profile_path;
|
||||
|
||||
const OpenXRInteractionProfileMetadata::InteractionProfile *profile_def = meta_data->get_profile(profile_path);
|
||||
if (profile_def != nullptr) {
|
||||
profile_name = profile_def->display_name;
|
||||
}
|
||||
|
||||
create_dialog->set_base_type("OpenXRIPBindingModifier");
|
||||
set_title(TTR("Binding modifiers for:") + " " + profile_name);
|
||||
}
|
||||
}
|
||||
|
|
@ -0,0 +1,81 @@
|
|||
/**************************************************************************/
|
||||
/* openxr_binding_modifiers_dialog.h */
|
||||
/**************************************************************************/
|
||||
/* This file is part of: */
|
||||
/* GODOT ENGINE */
|
||||
/* https://godotengine.org */
|
||||
/**************************************************************************/
|
||||
/* Copyright (c) 2014-present Godot Engine contributors (see AUTHORS.md). */
|
||||
/* Copyright (c) 2007-2014 Juan Linietsky, Ariel Manzur. */
|
||||
/* */
|
||||
/* Permission is hereby granted, free of charge, to any person obtaining */
|
||||
/* a copy of this software and associated documentation files (the */
|
||||
/* "Software"), to deal in the Software without restriction, including */
|
||||
/* without limitation the rights to use, copy, modify, merge, publish, */
|
||||
/* distribute, sublicense, and/or sell copies of the Software, and to */
|
||||
/* permit persons to whom the Software is furnished to do so, subject to */
|
||||
/* the following conditions: */
|
||||
/* */
|
||||
/* The above copyright notice and this permission notice shall be */
|
||||
/* included in all copies or substantial portions of the Software. */
|
||||
/* */
|
||||
/* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, */
|
||||
/* EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF */
|
||||
/* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. */
|
||||
/* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY */
|
||||
/* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, */
|
||||
/* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE */
|
||||
/* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. */
|
||||
/**************************************************************************/
|
||||
|
||||
#ifndef OPENXR_BINDING_MODIFIERS_DIALOG_H
|
||||
#define OPENXR_BINDING_MODIFIERS_DIALOG_H
|
||||
|
||||
#include "../action_map/openxr_action_map.h"
|
||||
#include "../action_map/openxr_interaction_profile.h"
|
||||
#include "../editor/openxr_binding_modifier_editor.h"
|
||||
#include "editor/create_dialog.h"
|
||||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
|
||||
class OpenXRBindingModifiersDialog : public AcceptDialog {
|
||||
GDCLASS(OpenXRBindingModifiersDialog, AcceptDialog);
|
||||
|
||||
private:
|
||||
ScrollContainer *binding_modifier_sc = nullptr;
|
||||
VBoxContainer *binding_modifiers_vb = nullptr;
|
||||
Label *binding_warning_label = nullptr;
|
||||
Button *add_binding_modifier_btn = nullptr;
|
||||
CreateDialog *create_dialog = nullptr;
|
||||
|
||||
OpenXRBindingModifierEditor *_add_binding_modifier_editor(Ref<OpenXRBindingModifier> p_binding_modifier);
|
||||
void _create_binding_modifiers();
|
||||
|
||||
void _on_add_binding_modifier();
|
||||
void _on_remove_binding_modifier(Object *p_binding_modifier_editor);
|
||||
void _on_dialog_created();
|
||||
|
||||
protected:
|
||||
EditorUndoRedoManager *undo_redo;
|
||||
Ref<OpenXRActionMap> action_map;
|
||||
Ref<OpenXRInteractionProfile> interaction_profile;
|
||||
Ref<OpenXRIPBinding> ip_binding;
|
||||
|
||||
static void _bind_methods();
|
||||
void _notification(int p_what);
|
||||
|
||||
// used for undo/redo
|
||||
void _do_add_binding_modifier_editor(OpenXRBindingModifierEditor *p_binding_modifier_editor);
|
||||
void _do_remove_binding_modifier_editor(OpenXRBindingModifierEditor *p_binding_modifier_editor);
|
||||
|
||||
public:
|
||||
OpenXRBindingModifiersDialog();
|
||||
|
||||
void setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile, Ref<OpenXRIPBinding> p_ip_binding = Ref<OpenXRIPBinding>());
|
||||
};
|
||||
|
||||
#endif // OPENXR_BINDING_MODIFIERS_DIALOG_H
|
||||
|
|
@ -54,7 +54,10 @@ void OpenXREditorPlugin::make_visible(bool p_visible) {
|
|||
|
||||
OpenXREditorPlugin::OpenXREditorPlugin() {
|
||||
action_map_editor = memnew(OpenXRActionMapEditor);
|
||||
EditorNode::get_bottom_panel()->add_item(TTR("OpenXR Action Map"), action_map_editor, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_openxr_action_map_bottom_panel", TTR("Toggle OpenXR Action Map Bottom Panel")));
|
||||
EditorNode::get_bottom_panel()->add_item(TTR("OpenXR Action Map"), action_map_editor, ED_SHORTCUT_AND_COMMAND("bottom_panels/toggle_openxr_action_map_bottom_panel", TTRC("Toggle OpenXR Action Map Bottom Panel")));
|
||||
|
||||
binding_modifier_inspector_plugin = Ref<EditorInspectorPluginBindingModifier>(memnew(EditorInspectorPluginBindingModifier));
|
||||
EditorInspector::add_inspector_plugin(binding_modifier_inspector_plugin);
|
||||
|
||||
#ifndef ANDROID_ENABLED
|
||||
select_runtime = memnew(OpenXRSelectRuntime);
|
||||
|
|
|
|||
|
|
@ -32,6 +32,7 @@
|
|||
#define OPENXR_EDITOR_PLUGIN_H
|
||||
|
||||
#include "openxr_action_map_editor.h"
|
||||
#include "openxr_binding_modifier_editor.h"
|
||||
#include "openxr_select_runtime.h"
|
||||
|
||||
#include "editor/plugins/editor_plugin.h"
|
||||
|
|
@ -40,12 +41,13 @@ class OpenXREditorPlugin : public EditorPlugin {
|
|||
GDCLASS(OpenXREditorPlugin, EditorPlugin);
|
||||
|
||||
OpenXRActionMapEditor *action_map_editor = nullptr;
|
||||
Ref<EditorInspectorPluginBindingModifier> binding_modifier_inspector_plugin = nullptr;
|
||||
#ifndef ANDROID_ENABLED
|
||||
OpenXRSelectRuntime *select_runtime = nullptr;
|
||||
#endif
|
||||
|
||||
public:
|
||||
virtual String get_name() const override { return "OpenXRPlugin"; }
|
||||
virtual String get_plugin_name() const override { return "OpenXRPlugin"; }
|
||||
bool has_main_screen() const override { return false; }
|
||||
virtual void edit(Object *p_node) override;
|
||||
virtual bool handles(Object *p_node) const override;
|
||||
|
|
|
|||
|
|
@ -29,20 +29,15 @@
|
|||
/**************************************************************************/
|
||||
|
||||
#include "openxr_interaction_profile_editor.h"
|
||||
|
||||
#include "../openxr_api.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/line_edit.h"
|
||||
#include "scene/gui/panel_container.h"
|
||||
#include "scene/gui/separator.h"
|
||||
#include "scene/gui/text_edit.h"
|
||||
|
||||
///////////////////////////////////////////////////////////////////////////
|
||||
// Interaction profile editor base
|
||||
|
||||
void OpenXRInteractionProfileEditorBase::_bind_methods() {
|
||||
ClassDB::bind_method(D_METHOD("setup", "action_map", "interaction_profile"), &OpenXRInteractionProfileEditorBase::setup);
|
||||
|
||||
ClassDB::bind_method(D_METHOD("_add_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_add_binding);
|
||||
ClassDB::bind_method(D_METHOD("_remove_binding", "action", "path"), &OpenXRInteractionProfileEditorBase::_remove_binding);
|
||||
}
|
||||
|
|
@ -73,17 +68,19 @@ void OpenXRInteractionProfileEditorBase::_add_binding(const String p_action, con
|
|||
Ref<OpenXRAction> action = action_map->get_action(p_action);
|
||||
ERR_FAIL_COND(action.is_null());
|
||||
|
||||
Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
|
||||
Ref<OpenXRIPBinding> binding = interaction_profile->find_binding(action, p_path);
|
||||
if (binding.is_null()) {
|
||||
// create a new binding
|
||||
binding.instantiate();
|
||||
binding->set_action(action);
|
||||
binding->set_binding_path(p_path);
|
||||
|
||||
// add it to our interaction profile
|
||||
interaction_profile->add_binding(binding);
|
||||
interaction_profile->set_edited(true);
|
||||
}
|
||||
|
||||
binding->add_path(p_path);
|
||||
binding->set_edited(true);
|
||||
binding->set_edited(true);
|
||||
}
|
||||
|
||||
// Update our toplevel paths
|
||||
action->set_toplevel_paths(action_map->get_top_level_paths(action));
|
||||
|
|
@ -98,15 +95,10 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action,
|
|||
Ref<OpenXRAction> action = action_map->get_action(p_action);
|
||||
ERR_FAIL_COND(action.is_null());
|
||||
|
||||
Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(action);
|
||||
Ref<OpenXRIPBinding> binding = interaction_profile->find_binding(action, p_path);
|
||||
if (binding.is_valid()) {
|
||||
binding->remove_path(p_path);
|
||||
binding->set_edited(true);
|
||||
|
||||
if (binding->get_path_count() == 0) {
|
||||
interaction_profile->remove_binding(binding);
|
||||
interaction_profile->set_edited(true);
|
||||
}
|
||||
interaction_profile->remove_binding(binding);
|
||||
interaction_profile->set_edited(true);
|
||||
|
||||
// Update our toplevel paths
|
||||
action->set_toplevel_paths(action_map->get_top_level_paths(action));
|
||||
|
|
@ -115,22 +107,47 @@ void OpenXRInteractionProfileEditorBase::_remove_binding(const String p_action,
|
|||
}
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditorBase::remove_all_bindings_for_action(Ref<OpenXRAction> p_action) {
|
||||
Ref<OpenXRIPBinding> binding = interaction_profile->get_binding_for_action(p_action);
|
||||
if (binding.is_valid()) {
|
||||
void OpenXRInteractionProfileEditorBase::_update_interaction_profile() {
|
||||
if (!is_dirty) {
|
||||
// no need to update
|
||||
return;
|
||||
}
|
||||
|
||||
// Nothing to do here for now..
|
||||
|
||||
// and we've updated it...
|
||||
is_dirty = false;
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditorBase::_theme_changed() {
|
||||
if (binding_modifiers_btn) {
|
||||
binding_modifiers_btn->set_button_icon(get_theme_icon(SNAME("Modifiers"), EditorStringName(EditorIcons)));
|
||||
}
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditorBase::remove_all_for_action_set(Ref<OpenXRActionSet> p_action_set) {
|
||||
// Note, don't need to remove bindings themselves as remove_all_for_action will be called for each before this is called.
|
||||
|
||||
// TODO update binding modifiers
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditorBase::remove_all_for_action(Ref<OpenXRAction> p_action) {
|
||||
Vector<Ref<OpenXRIPBinding>> bindings = interaction_profile->get_bindings_for_action(p_action);
|
||||
if (bindings.size() > 0) {
|
||||
String action_name = p_action->get_name_with_set();
|
||||
|
||||
// for our undo/redo we process all paths
|
||||
// For our undo/redo we process all paths
|
||||
undo_redo->create_action(TTR("Remove action from interaction profile"));
|
||||
PackedStringArray paths = binding->get_paths();
|
||||
for (const String &path : paths) {
|
||||
undo_redo->add_do_method(this, "_remove_binding", action_name, path);
|
||||
undo_redo->add_undo_method(this, "_add_binding", action_name, path);
|
||||
for (const Ref<OpenXRIPBinding> &binding : bindings) {
|
||||
undo_redo->add_do_method(this, "_remove_binding", action_name, binding->get_binding_path());
|
||||
undo_redo->add_undo_method(this, "_add_binding", action_name, binding->get_binding_path());
|
||||
}
|
||||
undo_redo->commit_action(false);
|
||||
|
||||
// but we take a shortcut here :)
|
||||
interaction_profile->remove_binding(binding);
|
||||
// But remove them all in one go so we're more efficient in updating our UI.
|
||||
for (const Ref<OpenXRIPBinding> &binding : bindings) {
|
||||
interaction_profile->remove_binding(binding);
|
||||
}
|
||||
interaction_profile->set_edited(true);
|
||||
|
||||
// Update our toplevel paths
|
||||
|
|
@ -139,10 +156,39 @@ void OpenXRInteractionProfileEditorBase::remove_all_bindings_for_action(Ref<Open
|
|||
_do_update_interaction_profile();
|
||||
}
|
||||
}
|
||||
void OpenXRInteractionProfileEditorBase::_on_open_binding_modifiers() {
|
||||
binding_modifiers_dialog->popup_centered(Size2i(500, 400));
|
||||
}
|
||||
|
||||
OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) {
|
||||
OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase() {
|
||||
undo_redo = EditorUndoRedoManager::get_singleton();
|
||||
|
||||
set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
|
||||
interaction_profile_sc = memnew(ScrollContainer);
|
||||
interaction_profile_sc->set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
interaction_profile_sc->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
add_child(interaction_profile_sc);
|
||||
|
||||
binding_modifiers_dialog = memnew(OpenXRBindingModifiersDialog);
|
||||
add_child(binding_modifiers_dialog);
|
||||
|
||||
toolbar_vb = memnew(VBoxContainer);
|
||||
toolbar_vb->set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
add_child(toolbar_vb);
|
||||
|
||||
binding_modifiers_btn = memnew(Button);
|
||||
binding_modifiers_btn->set_tooltip_text(TTR("Edit binding modifiers"));
|
||||
binding_modifiers_btn->connect("pressed", callable_mp(this, &OpenXRInteractionProfileEditorBase::_on_open_binding_modifiers));
|
||||
// TODO show visual difference if there are binding modifiers for this interaction profile
|
||||
toolbar_vb->add_child(binding_modifiers_btn);
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditorBase::setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) {
|
||||
ERR_FAIL_NULL(binding_modifiers_dialog);
|
||||
binding_modifiers_dialog->setup(p_action_map, p_interaction_profile);
|
||||
|
||||
action_map = p_action_map;
|
||||
interaction_profile = p_interaction_profile;
|
||||
String profile_path = interaction_profile->get_interaction_profile_path();
|
||||
|
|
@ -151,11 +197,15 @@ OpenXRInteractionProfileEditorBase::OpenXRInteractionProfileEditorBase(Ref<OpenX
|
|||
profile_def = OpenXRInteractionProfileMetadata::get_singleton()->get_profile(profile_path);
|
||||
if (profile_def != nullptr) {
|
||||
profile_name = profile_def->display_name;
|
||||
|
||||
if (!profile_def->openxr_extension_name.is_empty()) {
|
||||
profile_name += "*";
|
||||
|
||||
tooltip = vformat(TTR("Note: This interaction profile requires extension %s support."), profile_def->openxr_extension_name);
|
||||
}
|
||||
}
|
||||
|
||||
set_name(profile_name);
|
||||
set_h_size_flags(SIZE_EXPAND_FILL);
|
||||
set_v_size_flags(SIZE_EXPAND_FILL);
|
||||
|
||||
// Make sure it is updated when it enters the tree...
|
||||
is_dirty = true;
|
||||
|
|
@ -169,7 +219,7 @@ void OpenXRInteractionProfileEditor::select_action_for(const String p_io_path) {
|
|||
select_action_dialog->open();
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditor::action_selected(const String p_action) {
|
||||
void OpenXRInteractionProfileEditor::_on_action_selected(const String p_action) {
|
||||
undo_redo->create_action(TTR("Add binding"));
|
||||
undo_redo->add_do_method(this, "_add_binding", p_action, selecting_for_io_path);
|
||||
undo_redo->add_undo_method(this, "_remove_binding", p_action, selecting_for_io_path);
|
||||
|
|
@ -191,7 +241,12 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
|
|||
p_container->add_child(path_hb);
|
||||
|
||||
Label *path_label = memnew(Label);
|
||||
path_label->set_text(p_io_path->display_name);
|
||||
if (p_io_path->openxr_extension_name.is_empty()) {
|
||||
path_label->set_text(p_io_path->display_name);
|
||||
} else {
|
||||
path_label->set_text(p_io_path->display_name + "*");
|
||||
p_container->set_tooltip_text(vformat(TTR("Note: This binding path requires extension %s support."), p_io_path->openxr_extension_name));
|
||||
}
|
||||
path_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
path_hb->add_child(path_label);
|
||||
|
||||
|
|
@ -220,7 +275,7 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
|
|||
path_hb->add_child(type_label);
|
||||
|
||||
Button *path_add = memnew(Button);
|
||||
path_add->set_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
|
||||
path_add->set_button_icon(get_theme_icon(SNAME("Add"), EditorStringName(EditorIcons)));
|
||||
path_add->set_flat(true);
|
||||
path_add->connect(SceneStringName(pressed), callable_mp(this, &OpenXRInteractionProfileEditor::select_action_for).bind(String(p_io_path->openxr_path)));
|
||||
path_hb->add_child(path_add);
|
||||
|
|
@ -228,9 +283,8 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
|
|||
if (interaction_profile.is_valid()) {
|
||||
String io_path = String(p_io_path->openxr_path);
|
||||
Array bindings = interaction_profile->get_bindings();
|
||||
for (int i = 0; i < bindings.size(); i++) {
|
||||
Ref<OpenXRIPBinding> binding = bindings[i];
|
||||
if (binding->has_path(io_path)) {
|
||||
for (Ref<OpenXRIPBinding> binding : bindings) {
|
||||
if (binding->get_binding_path() == io_path) {
|
||||
Ref<OpenXRAction> action = binding->get_action();
|
||||
|
||||
HBoxContainer *action_hb = memnew(HBoxContainer);
|
||||
|
|
@ -246,9 +300,20 @@ void OpenXRInteractionProfileEditor::_add_io_path(VBoxContainer *p_container, co
|
|||
action_label->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
action_hb->add_child(action_label);
|
||||
|
||||
OpenXRBindingModifiersDialog *action_binding_modifiers_dialog = memnew(OpenXRBindingModifiersDialog);
|
||||
action_binding_modifiers_dialog->setup(action_map, interaction_profile, binding);
|
||||
action_hb->add_child(action_binding_modifiers_dialog);
|
||||
|
||||
Button *action_binding_modifiers_btn = memnew(Button);
|
||||
action_binding_modifiers_btn->set_flat(true);
|
||||
action_binding_modifiers_btn->set_button_icon(get_theme_icon(SNAME("Modifiers"), EditorStringName(EditorIcons)));
|
||||
action_binding_modifiers_btn->connect(SceneStringName(pressed), callable_mp((Window *)action_binding_modifiers_dialog, &Window::popup_centered).bind(Size2i(500, 400)));
|
||||
// TODO change style of button if there are binding modifiers
|
||||
action_hb->add_child(action_binding_modifiers_btn);
|
||||
|
||||
Button *action_rem = memnew(Button);
|
||||
action_rem->set_flat(true);
|
||||
action_rem->set_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
|
||||
action_rem->set_button_icon(get_theme_icon(SNAME("Remove"), EditorStringName(EditorIcons)));
|
||||
action_rem->connect(SceneStringName(pressed), callable_mp((OpenXRInteractionProfileEditor *)this, &OpenXRInteractionProfileEditor::_on_remove_pressed).bind(action->get_name_with_set(), String(p_io_path->openxr_path)));
|
||||
action_hb->add_child(action_rem);
|
||||
}
|
||||
|
|
@ -264,9 +329,11 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
|
|||
return;
|
||||
}
|
||||
|
||||
PackedStringArray requested_extensions = OpenXRAPI::get_all_requested_extensions();
|
||||
|
||||
// out with the old...
|
||||
while (main_hb->get_child_count() > 0) {
|
||||
memdelete(main_hb->get_child(0));
|
||||
while (interaction_profile_hb->get_child_count() > 0) {
|
||||
memdelete(interaction_profile_hb->get_child(0));
|
||||
}
|
||||
|
||||
// in with the new...
|
||||
|
|
@ -284,7 +351,7 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
|
|||
for (int i = 0; i < top_level_paths.size(); i++) {
|
||||
PanelContainer *panel = memnew(PanelContainer);
|
||||
panel->set_v_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
main_hb->add_child(panel);
|
||||
interaction_profile_hb->add_child(panel);
|
||||
panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("TabContainer")));
|
||||
|
||||
VBoxContainer *container = memnew(VBoxContainer);
|
||||
|
|
@ -296,31 +363,37 @@ void OpenXRInteractionProfileEditor::_update_interaction_profile() {
|
|||
|
||||
for (int j = 0; j < profile_def->io_paths.size(); j++) {
|
||||
const OpenXRInteractionProfileMetadata::IOPath *io_path = &profile_def->io_paths[j];
|
||||
if (io_path->top_level_path == top_level_paths[i]) {
|
||||
if (io_path->top_level_path == top_level_paths[i] && (io_path->openxr_extension_name.is_empty() || requested_extensions.has(io_path->openxr_extension_name))) {
|
||||
_add_io_path(container, io_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// and we've updated it...
|
||||
is_dirty = false;
|
||||
OpenXRInteractionProfileEditorBase::_update_interaction_profile();
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditor::_theme_changed() {
|
||||
for (int i = 0; i < main_hb->get_child_count(); i++) {
|
||||
Control *panel = Object::cast_to<Control>(main_hb->get_child(i));
|
||||
OpenXRInteractionProfileEditorBase::_theme_changed();
|
||||
|
||||
interaction_profile_sc->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("Tree")));
|
||||
|
||||
for (int i = 0; i < interaction_profile_hb->get_child_count(); i++) {
|
||||
Control *panel = Object::cast_to<Control>(interaction_profile_hb->get_child(i));
|
||||
if (panel) {
|
||||
panel->add_theme_style_override(SceneStringName(panel), get_theme_stylebox(SceneStringName(panel), SNAME("TabContainer")));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
OpenXRInteractionProfileEditor::OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) :
|
||||
OpenXRInteractionProfileEditorBase(p_action_map, p_interaction_profile) {
|
||||
main_hb = memnew(HBoxContainer);
|
||||
add_child(main_hb);
|
||||
OpenXRInteractionProfileEditor::OpenXRInteractionProfileEditor() {
|
||||
interaction_profile_hb = memnew(HBoxContainer);
|
||||
interaction_profile_sc->add_child(interaction_profile_hb);
|
||||
}
|
||||
|
||||
void OpenXRInteractionProfileEditor::setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) {
|
||||
OpenXRInteractionProfileEditorBase::setup(p_action_map, p_interaction_profile);
|
||||
|
||||
select_action_dialog = memnew(OpenXRSelectActionDialog(p_action_map));
|
||||
select_action_dialog->connect("action_selected", callable_mp(this, &OpenXRInteractionProfileEditor::action_selected));
|
||||
select_action_dialog->connect("action_selected", callable_mp(this, &OpenXRInteractionProfileEditor::_on_action_selected));
|
||||
add_child(select_action_dialog);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -34,19 +34,29 @@
|
|||
#include "../action_map/openxr_action_map.h"
|
||||
#include "../action_map/openxr_interaction_profile.h"
|
||||
#include "../action_map/openxr_interaction_profile_metadata.h"
|
||||
#include "openxr_select_action_dialog.h"
|
||||
|
||||
#include "../editor/openxr_binding_modifiers_dialog.h"
|
||||
#include "editor/editor_undo_redo_manager.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
#include "openxr_select_action_dialog.h"
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
|
||||
class OpenXRInteractionProfileEditorBase : public ScrollContainer {
|
||||
GDCLASS(OpenXRInteractionProfileEditorBase, ScrollContainer);
|
||||
class OpenXRInteractionProfileEditorBase : public HBoxContainer {
|
||||
GDCLASS(OpenXRInteractionProfileEditorBase, HBoxContainer);
|
||||
|
||||
private:
|
||||
OpenXRBindingModifiersDialog *binding_modifiers_dialog = nullptr;
|
||||
VBoxContainer *toolbar_vb = nullptr;
|
||||
Button *binding_modifiers_btn = nullptr;
|
||||
|
||||
void _on_open_binding_modifiers();
|
||||
|
||||
protected:
|
||||
EditorUndoRedoManager *undo_redo;
|
||||
Ref<OpenXRInteractionProfile> interaction_profile;
|
||||
Ref<OpenXRActionMap> action_map;
|
||||
|
||||
ScrollContainer *interaction_profile_sc = nullptr;
|
||||
|
||||
bool is_dirty = false;
|
||||
|
||||
static void _bind_methods();
|
||||
|
|
@ -55,18 +65,23 @@ protected:
|
|||
const OpenXRInteractionProfileMetadata::InteractionProfile *profile_def = nullptr;
|
||||
|
||||
public:
|
||||
String tooltip; // Tooltip text to show on tab
|
||||
|
||||
Ref<OpenXRInteractionProfile> get_interaction_profile() { return interaction_profile; }
|
||||
|
||||
virtual void _update_interaction_profile() {}
|
||||
virtual void _theme_changed() {}
|
||||
virtual void _update_interaction_profile();
|
||||
virtual void _theme_changed();
|
||||
|
||||
void _do_update_interaction_profile();
|
||||
void _add_binding(const String p_action, const String p_path);
|
||||
void _remove_binding(const String p_action, const String p_path);
|
||||
|
||||
void remove_all_bindings_for_action(Ref<OpenXRAction> p_action);
|
||||
void remove_all_for_action_set(Ref<OpenXRActionSet> p_action_set);
|
||||
void remove_all_for_action(Ref<OpenXRAction> p_action);
|
||||
|
||||
OpenXRInteractionProfileEditorBase(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile);
|
||||
virtual void setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile);
|
||||
|
||||
OpenXRInteractionProfileEditorBase();
|
||||
};
|
||||
|
||||
class OpenXRInteractionProfileEditor : public OpenXRInteractionProfileEditorBase {
|
||||
|
|
@ -74,19 +89,22 @@ class OpenXRInteractionProfileEditor : public OpenXRInteractionProfileEditorBase
|
|||
|
||||
private:
|
||||
String selecting_for_io_path;
|
||||
HBoxContainer *main_hb = nullptr;
|
||||
HBoxContainer *interaction_profile_hb = nullptr;
|
||||
|
||||
OpenXRSelectActionDialog *select_action_dialog = nullptr;
|
||||
|
||||
void _add_io_path(VBoxContainer *p_container, const OpenXRInteractionProfileMetadata::IOPath *p_io_path);
|
||||
|
||||
public:
|
||||
void select_action_for(const String p_io_path);
|
||||
void action_selected(const String p_action);
|
||||
void _on_action_selected(const String p_action);
|
||||
void _on_remove_pressed(const String p_action, const String p_for_io_path);
|
||||
|
||||
virtual void _update_interaction_profile() override;
|
||||
virtual void _theme_changed() override;
|
||||
OpenXRInteractionProfileEditor(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile);
|
||||
virtual void setup(Ref<OpenXRActionMap> p_action_map, Ref<OpenXRInteractionProfile> p_interaction_profile) override;
|
||||
|
||||
OpenXRInteractionProfileEditor();
|
||||
};
|
||||
|
||||
#endif // OPENXR_INTERACTION_PROFILE_EDITOR_H
|
||||
|
|
|
|||
|
|
@ -66,7 +66,7 @@ void OpenXRSelectActionDialog::_on_select_action(const String p_action) {
|
|||
void OpenXRSelectActionDialog::open() {
|
||||
ERR_FAIL_COND(action_map.is_null());
|
||||
|
||||
// out with the old...
|
||||
// Out with the old.
|
||||
while (main_vb->get_child_count() > 0) {
|
||||
memdelete(main_vb->get_child(0));
|
||||
}
|
||||
|
|
@ -74,6 +74,7 @@ void OpenXRSelectActionDialog::open() {
|
|||
selected_action = "";
|
||||
action_buttons.clear();
|
||||
|
||||
// In with the new.
|
||||
Array action_sets = action_map->get_action_sets();
|
||||
for (int i = 0; i < action_sets.size(); i++) {
|
||||
Ref<OpenXRActionSet> action_set = action_sets[i];
|
||||
|
|
|
|||
|
|
@ -30,6 +30,9 @@
|
|||
|
||||
#include "openxr_select_interaction_profile_dialog.h"
|
||||
|
||||
#include "../action_map/openxr_interaction_profile_metadata.h"
|
||||
#include "../openxr_api.h"
|
||||
|
||||
void OpenXRSelectInteractionProfileDialog::_bind_methods() {
|
||||
ADD_SIGNAL(MethodInfo("interaction_profile_selected", PropertyInfo(Variant::STRING, "interaction_profile")));
|
||||
}
|
||||
|
|
@ -66,22 +69,28 @@ void OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile(const
|
|||
void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_include) {
|
||||
int available_count = 0;
|
||||
|
||||
// out with the old...
|
||||
while (main_vb->get_child_count() > 0) {
|
||||
memdelete(main_vb->get_child(0));
|
||||
OpenXRInteractionProfileMetadata *meta_data = OpenXRInteractionProfileMetadata::get_singleton();
|
||||
ERR_FAIL_NULL(meta_data);
|
||||
|
||||
// Out with the old.
|
||||
while (main_vb->get_child_count() > 1) {
|
||||
memdelete(main_vb->get_child(1));
|
||||
}
|
||||
|
||||
PackedStringArray requested_extensions = OpenXRAPI::get_all_requested_extensions();
|
||||
|
||||
selected_interaction_profile = "";
|
||||
ip_buttons.clear();
|
||||
|
||||
// in with the new
|
||||
PackedStringArray interaction_profiles = OpenXRInteractionProfileMetadata::get_singleton()->get_interaction_profile_paths();
|
||||
for (int i = 0; i < interaction_profiles.size(); i++) {
|
||||
const String &path = interaction_profiles[i];
|
||||
if (!p_do_not_include.has(path)) {
|
||||
// In with the new.
|
||||
PackedStringArray interaction_profiles = meta_data->get_interaction_profile_paths();
|
||||
for (const String &path : interaction_profiles) {
|
||||
const String extension = meta_data->get_interaction_profile_extension(path);
|
||||
if (!p_do_not_include.has(path) && (extension.is_empty() || requested_extensions.has(extension))) {
|
||||
Button *ip_button = memnew(Button);
|
||||
ip_button->set_flat(true);
|
||||
ip_button->set_text(OpenXRInteractionProfileMetadata::get_singleton()->get_profile(path)->display_name);
|
||||
ip_button->set_text(meta_data->get_profile(path)->display_name);
|
||||
ip_button->set_text_alignment(HORIZONTAL_ALIGNMENT_LEFT);
|
||||
ip_button->connect(SceneStringName(pressed), callable_mp(this, &OpenXRSelectInteractionProfileDialog::_on_select_interaction_profile).bind(path));
|
||||
main_vb->add_child(ip_button);
|
||||
|
||||
|
|
@ -90,23 +99,16 @@ void OpenXRSelectInteractionProfileDialog::open(PackedStringArray p_do_not_inclu
|
|||
}
|
||||
}
|
||||
|
||||
if (available_count == 0) {
|
||||
// give warning that we have all profiles selected
|
||||
|
||||
} else {
|
||||
// TODO maybe if we only have one, auto select it?
|
||||
|
||||
popup_centered();
|
||||
}
|
||||
all_selected->set_visible(available_count == 0);
|
||||
get_cancel_button()->set_visible(available_count > 0);
|
||||
popup_centered();
|
||||
}
|
||||
|
||||
void OpenXRSelectInteractionProfileDialog::ok_pressed() {
|
||||
if (selected_interaction_profile == "") {
|
||||
return;
|
||||
if (selected_interaction_profile != "") {
|
||||
emit_signal("interaction_profile_selected", selected_interaction_profile);
|
||||
}
|
||||
|
||||
emit_signal("interaction_profile_selected", selected_interaction_profile);
|
||||
|
||||
hide();
|
||||
}
|
||||
|
||||
|
|
@ -118,6 +120,10 @@ OpenXRSelectInteractionProfileDialog::OpenXRSelectInteractionProfileDialog() {
|
|||
add_child(scroll);
|
||||
|
||||
main_vb = memnew(VBoxContainer);
|
||||
// main_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
main_vb->set_h_size_flags(Control::SIZE_EXPAND_FILL);
|
||||
scroll->add_child(main_vb);
|
||||
|
||||
all_selected = memnew(Label);
|
||||
all_selected->set_text(TTR("All interaction profiles have been added to the action map."));
|
||||
main_vb->add_child(all_selected);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -31,16 +31,10 @@
|
|||
#ifndef OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
|
||||
#define OPENXR_SELECT_INTERACTION_PROFILE_DIALOG_H
|
||||
|
||||
#include "../action_map/openxr_interaction_profile_metadata.h"
|
||||
|
||||
#include "scene/gui/box_container.h"
|
||||
#include "scene/gui/button.h"
|
||||
#include "scene/gui/dialogs.h"
|
||||
#include "scene/gui/label.h"
|
||||
#include "scene/gui/line_edit.h"
|
||||
#include "scene/gui/scroll_container.h"
|
||||
#include "scene/gui/separator.h"
|
||||
#include "scene/gui/text_edit.h"
|
||||
|
||||
class OpenXRSelectInteractionProfileDialog : public ConfirmationDialog {
|
||||
GDCLASS(OpenXRSelectInteractionProfileDialog, ConfirmationDialog);
|
||||
|
|
@ -51,6 +45,7 @@ private:
|
|||
|
||||
VBoxContainer *main_vb = nullptr;
|
||||
ScrollContainer *scroll = nullptr;
|
||||
Label *all_selected = nullptr;
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
|
|
|
|||
|
|
@ -33,10 +33,6 @@
|
|||
#include "core/io/dir_access.h"
|
||||
#include "core/os/os.h"
|
||||
#include "editor/editor_settings.h"
|
||||
#include "editor/editor_string_names.h"
|
||||
|
||||
void OpenXRSelectRuntime::_bind_methods() {
|
||||
}
|
||||
|
||||
void OpenXRSelectRuntime::_update_items() {
|
||||
Ref<DirAccess> da = DirAccess::create(DirAccess::ACCESS_FILESYSTEM);
|
||||
|
|
@ -78,7 +74,7 @@ void OpenXRSelectRuntime::_update_items() {
|
|||
select(current_runtime);
|
||||
}
|
||||
|
||||
void OpenXRSelectRuntime::_item_selected(int p_which) {
|
||||
void OpenXRSelectRuntime::_on_item_selected(int p_which) {
|
||||
OS *os = OS::get_singleton();
|
||||
|
||||
if (p_which == 0) {
|
||||
|
|
@ -98,11 +94,11 @@ void OpenXRSelectRuntime::_notification(int p_notification) {
|
|||
_update_items();
|
||||
|
||||
// Connect signal
|
||||
connect(SceneStringName(item_selected), callable_mp(this, &OpenXRSelectRuntime::_item_selected));
|
||||
connect(SceneStringName(item_selected), callable_mp(this, &OpenXRSelectRuntime::_on_item_selected));
|
||||
} break;
|
||||
case NOTIFICATION_EXIT_TREE: {
|
||||
// Disconnect signal
|
||||
disconnect(SceneStringName(item_selected), callable_mp(this, &OpenXRSelectRuntime::_item_selected));
|
||||
disconnect(SceneStringName(item_selected), callable_mp(this, &OpenXRSelectRuntime::_on_item_selected));
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
|
@ -122,6 +118,7 @@ OpenXRSelectRuntime::OpenXRSelectRuntime() {
|
|||
default_runtimes["SteamVR"] = "~/.steam/steam/steamapps/common/SteamVR/steamxr_linux64.json";
|
||||
#endif
|
||||
|
||||
// TODO: Move to editor_settings.cpp
|
||||
EDITOR_DEF_RST("xr/openxr/runtime_paths", default_runtimes);
|
||||
|
||||
set_flat(true);
|
||||
|
|
|
|||
|
|
@ -40,12 +40,11 @@ public:
|
|||
OpenXRSelectRuntime();
|
||||
|
||||
protected:
|
||||
static void _bind_methods();
|
||||
void _notification(int p_notification);
|
||||
|
||||
private:
|
||||
void _update_items();
|
||||
void _item_selected(int p_which);
|
||||
void _on_item_selected(int p_which);
|
||||
};
|
||||
|
||||
#endif // OPENXR_SELECT_RUNTIME_H
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue