Skip to content
Snippets Groups Projects
action_map.py 6 KiB
Newer Older
  • Learn to ignore specific revisions
  • # ##### 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)