diff options
Diffstat (limited to 'viewport_vr_preview/action_map.py')
-rw-r--r-- | viewport_vr_preview/action_map.py | 172 |
1 files changed, 172 insertions, 0 deletions
diff --git a/viewport_vr_preview/action_map.py b/viewport_vr_preview/action_map.py new file mode 100644 index 00000000..49c3f7dd --- /dev/null +++ b/viewport_vr_preview/action_map.py @@ -0,0 +1,172 @@ +# ##### BEGIN GPL LICENSE BLOCK ##### +# +# This program is free software; you can redistribute it and/or +# modify it under the terms of the GNU General Public License +# as published by the Free Software Foundation; either version 2 +# of the License, or (at your option) any later version. +# +# This program is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +# GNU General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program; if not, write to the Free Software Foundation, +# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. +# +# ##### END GPL LICENSE BLOCK ##### + +# <pep8 compliant> + +if "bpy" in locals(): + import importlib + importlib.reload(defaults) +else: + from . import action_map_io, defaults + +import bpy +from bpy.app.handlers import persistent +from bpy_extras.io_utils import ExportHelper, ImportHelper +import importlib.util +import os.path + + +def vr_actionset_active_update(context): + session_state = context.window_manager.xr_session_state + if not session_state or len(session_state.actionmaps) < 1: + return + + scene = context.scene + + if scene.vr_actions_use_gamepad and session_state.actionmaps.find(session_state, defaults.VRDefaultActionmaps.GAMEPAD.value): + session_state.active_action_set_set(context, defaults.VRDefaultActionmaps.GAMEPAD.value) + else: + # Use first action map. + session_state.active_action_set_set(context, session_state.actionmaps[0].name) + + +def vr_actions_use_gamepad_update(self, context): + vr_actionset_active_update(context) + + +@persistent +def vr_create_actions(context: bpy.context): + context = bpy.context + session_state = context.window_manager.xr_session_state + if not session_state: + return + + # Check if actions are enabled. + scene = context.scene + if not scene.vr_actions_enable: + return + + # Ensure default action maps. + if not defaults.vr_ensure_default_actionmaps(session_state): + return + + for am in session_state.actionmaps: + if len(am.actionmap_items) < 1: + continue + + ok = session_state.action_set_create(context, am) + if not ok: + return + + controller_grip_name = "" + controller_aim_name = "" + + for ami in am.actionmap_items: + if len(ami.bindings) < 1: + continue + + ok = session_state.action_create(context, am, ami) + if not ok: + return + + if ami.type == 'POSE': + if ami.pose_is_controller_grip: + controller_grip_name = ami.name + if ami.pose_is_controller_aim: + controller_aim_name = ami.name + + for amb in ami.bindings: + # Check for bindings that require OpenXR extensions. + if amb.name == defaults.VRDefaultActionbindings.REVERB_G2.value: + if not scene.vr_actions_enable_reverb_g2: + continue + elif amb.name == defaults.VRDefaultActionbindings.COSMOS.value: + if not scene.vr_actions_enable_cosmos: + continue + elif amb.name == defaults.VRDefaultActionbindings.HUAWEI.value: + if not scene.vr_actions_enable_huawei: + continue + + ok = session_state.action_binding_create(context, am, ami, amb) + if not ok: + return + + # Set controller pose actions. + if controller_grip_name and controller_aim_name: + session_state.controller_pose_actions_set(context, am.name, controller_grip_name, controller_aim_name) + + # Set active action set. + vr_actionset_active_update(context) + + +def vr_load_actionmaps(session_state, filepath): + if not os.path.exists(filepath): + return False + + spec = importlib.util.spec_from_file_location(os.path.basename(filepath), filepath) + file = importlib.util.module_from_spec(spec) + spec.loader.exec_module(file) + + action_map_io.actionconfig_init_from_data(session_state, file.actionconfig_data, file.actionconfig_version) + + return True + + +def vr_save_actionmaps(session_state, filepath, sort=False): + action_map_io.actionconfig_export_as_data(session_state, filepath, sort=sort) + + print("Saved XR actionmaps: " + filepath) + + return True + + +def register(): + bpy.types.Scene.vr_actions_enable = bpy.props.BoolProperty( + name="Use Controller Actions", + description="Enable default VR controller actions, including controller poses and haptics", + default=True, + ) + bpy.types.Scene.vr_actions_use_gamepad = bpy.props.BoolProperty( + description="Use input from gamepad (Microsoft Xbox Controller) instead of motion controllers", + default=False, + update=vr_actions_use_gamepad_update, + ) + bpy.types.Scene.vr_actions_enable_cosmos = bpy.props.BoolProperty( + description="Enable bindings for the HTC Vive Cosmos controllers. Note that this may not be supported by all OpenXR runtimes", + default=False, + ) + bpy.types.Scene.vr_actions_enable_huawei = bpy.props.BoolProperty( + description="Enable bindings for the Huawei controllers. Note that this may not be supported by all OpenXR runtimes", + default=False, + ) + bpy.types.Scene.vr_actions_enable_reverb_g2 = bpy.props.BoolProperty( + description="Enable bindings for the HP Reverb G2 controllers. Note that this may not be supported by all OpenXR runtimes", + default=False, + ) + + bpy.app.handlers.xr_session_start_pre.append(vr_create_actions) + + +def unregister(): + del bpy.types.Scene.vr_actions_enable + del bpy.types.Scene.vr_actions_use_gamepad + del bpy.types.Scene.vr_actions_enable_cosmos + del bpy.types.Scene.vr_actions_enable_huawei + del bpy.types.Scene.vr_actions_enable_reverb_g2 + + bpy.app.handlers.xr_session_start_pre.remove(vr_create_actions) |