All Downloads are FREE. Search and download functionalities are using the official Maven repository.

com.onemillionworlds.tamarin.actions.actionprofile.Action Maven / Gradle / Ivy

There is a newer version: 2.6.1
Show newest version
package com.onemillionworlds.tamarin.actions.actionprofile;

import com.onemillionworlds.tamarin.actions.ActionType;
import com.onemillionworlds.tamarin.actions.HandSide;
import com.onemillionworlds.tamarin.actions.controllerprofile.GoogleDaydreamController;
import com.onemillionworlds.tamarin.actions.controllerprofile.HtcProVive;
import com.onemillionworlds.tamarin.actions.controllerprofile.HtcViveController;
import com.onemillionworlds.tamarin.actions.controllerprofile.KhronosSimpleController;
import com.onemillionworlds.tamarin.actions.controllerprofile.MixedRealityMotionController;
import com.onemillionworlds.tamarin.actions.controllerprofile.OculusGoController;
import com.onemillionworlds.tamarin.actions.controllerprofile.OculusTouchController;
import com.onemillionworlds.tamarin.actions.controllerprofile.ValveIndexController;
import java.util.ArrayList;
import java.util.List;

public class Action {
    /**
     * By default, all actions support the left and right hand sides.
     */
    public static List DEFAULT_SUB_ACTIONS = new ArrayList<>();

    static {
        DEFAULT_SUB_ACTIONS.add(HandSide.LEFT.restrictToInputString);
        DEFAULT_SUB_ACTIONS.add(HandSide.RIGHT.restrictToInputString);
    }

    private final ActionHandle actionHandle;
    /**
     * This is presented to the user as a description of the action. This string should be presented in the system’s current active locale.
     */
    private final String translatedName;
    private final ActionType actionType;
    /**
     * These are physical bindings to specific devices for this action.
     */
    private final List suggestedBindings;
    private final List supportedSubActionPaths;

    public Action(ActionHandle actionHandle, String translatedName, ActionType actionType, List suggestedBindings) {
        this.actionHandle = actionHandle;
        this.translatedName = translatedName;
        this.actionType = actionType;
        this.suggestedBindings = suggestedBindings;
        this.supportedSubActionPaths = DEFAULT_SUB_ACTIONS;
    }

    public Action(ActionHandle actionName, String translatedName, ActionType actionType, List suggestedBindings, List supportedSubActionPaths) {
        this.actionHandle = actionName;
        this.translatedName = translatedName;
        this.actionType = actionType;
        this.suggestedBindings = suggestedBindings;
        this.supportedSubActionPaths = supportedSubActionPaths;
    }

    public String getActionName() {
        return actionHandle.actionName();
    }

    public String getActionSetName() {
        return actionHandle.actionSetName();
    }

    @SuppressWarnings("unused")
    public static ActionBuilder builder() {
        return new ActionBuilder();
    }


    @SuppressWarnings("unused")
    public static class ActionBuilder {
        private ActionHandle actionHandle;
        private String translatedName;
        private ActionType actionType;
        /**
         * These are physical bindings to specific devices for this action.
         */
        private final List suggestedBindings = new ArrayList<>();
        private List supportedSubActionPaths = DEFAULT_SUB_ACTIONS;

        /**
         * This is used to identify the action when you want to programatically interact with it e.g. getting an actions value. It is anticipated that
         * these may be held in a static enum, or a static final field, or something similar where they can be easily accessed
         * application wide.
         * 

* The action name should be things like "teleport", not things like "X Click". The idea is that they are * abstract concept your application would like to support and they are bound to specific buttons based on the suggested * bindings (which may be changed by the user, or guessed at by the binding). */ public ActionBuilder actionHandle(ActionHandle actionHandle) { this.actionHandle = actionHandle; return this; } /** * This is presented to the user as a description of the action. This string should be presented in the system’s current active locale. */ public ActionBuilder translatedName(String translatedName) { this.translatedName = translatedName; return this; } public ActionBuilder actionType(ActionType actionType) { this.actionType = actionType; return this; } /** * Suggested bindings are physical bindings to specific devices for this action. * This method can be called multiple times to add more bindings (to the same action). *

* At least one binding should be added for each profile (aka controller) you explicitly want to support. *

* Intended usage is : * * withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().leftHand().haptic()) * *

* Tamarin provided profiles are: *

    *
  • {@link GoogleDaydreamController#PROFILE}
  • *
  • {@link HtcProVive#PROFILE} - note this is the headset itself
  • *
  • {@link HtcViveController#PROFILE}
  • *
  • {@link KhronosSimpleController#PROFILE}
  • *
  • {@link MixedRealityMotionController#PROFILE}
  • *
  • {@link OculusGoController#PROFILE}
  • *
  • {@link OculusTouchController#PROFILE}
  • *
  • {@link ValveIndexController#PROFILE}
  • *
* @param profile the name of the controller (e.g. {@link OculusTouchController#PROFILE}) * @param binding the physics binding (e.g. `OculusTouchController.pathBuilder().leftHand().haptic()`) */ @SuppressWarnings("UnusedReturnValue") public ActionBuilder withSuggestedBinding(String profile, String binding) { this.suggestedBindings.add(new SuggestedBinding(profile, binding)); return this; } /** * Suggested bindings are physical bindings to specific devices for this action. * This method can be called multiple times to add more bindings. */ public ActionBuilder withSuggestedBinding(SuggestedBinding suggestedBinding) { this.suggestedBindings.add(suggestedBinding); return this; } /** * Binds all the devices this library knows about (and that have haptics) to this action for both hands. *

* Note that the occulus go does not have haptics so no binding is added for it */ public ActionBuilder withSuggestAllKnownHapticBindings() { withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().leftHand().haptic()); withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().rightHand().haptic()); withSuggestedBinding(HtcViveController.PROFILE, HtcViveController.pathBuilder().leftHand().haptic()); withSuggestedBinding(HtcViveController.PROFILE, HtcViveController.pathBuilder().rightHand().haptic()); withSuggestedBinding(KhronosSimpleController.PROFILE, KhronosSimpleController.pathBuilder().leftHand().haptic()); withSuggestedBinding(KhronosSimpleController.PROFILE, KhronosSimpleController.pathBuilder().rightHand().haptic()); withSuggestedBinding(MixedRealityMotionController.PROFILE, MixedRealityMotionController.pathBuilder().leftHand().haptic()); withSuggestedBinding(MixedRealityMotionController.PROFILE, MixedRealityMotionController.pathBuilder().rightHand().haptic()); withSuggestedBinding(ValveIndexController.PROFILE, ValveIndexController.pathBuilder().leftHand().haptic()); withSuggestedBinding(ValveIndexController.PROFILE, ValveIndexController.pathBuilder().rightHand().haptic()); return this; } /** * Binds all the devices this library knows about (and that have aim poses) to this action for both hands. *

* Represents the position and orientation of the user's hand grip. *

* This pose is typically derived from a hand-held controller's physical design and is generally aligned with the device's handle. * In many cases, this pose aligns with the location of the user's hand when they are holding the device naturally. *

* The orientation of this pose is typically as follows: * - The X-axis points to the right of the handle. * - The Y-axis points up along the handle. * - The Z-axis points in the direction opposite to the front of the handle. *

* This pose is commonly used for: * - Placing virtual objects in the user's hand. * - Representing the user's hand position in the virtual world. *

* Note: The exact position and orientation can vary between devices. Always test with the specific device to ensure it behaves as expected. */ public ActionBuilder withSuggestAllKnownGripPoseBindings() { withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().leftHand().gripPose()); withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().rightHand().gripPose()); withSuggestedBinding(HtcViveController.PROFILE, HtcViveController.pathBuilder().leftHand().gripPose()); withSuggestedBinding(HtcViveController.PROFILE, HtcViveController.pathBuilder().rightHand().gripPose()); withSuggestedBinding(KhronosSimpleController.PROFILE, KhronosSimpleController.pathBuilder().leftHand().gripPose()); withSuggestedBinding(KhronosSimpleController.PROFILE, KhronosSimpleController.pathBuilder().rightHand().gripPose()); withSuggestedBinding(MixedRealityMotionController.PROFILE, MixedRealityMotionController.pathBuilder().leftHand().gripPose()); withSuggestedBinding(MixedRealityMotionController.PROFILE, MixedRealityMotionController.pathBuilder().rightHand().gripPose()); withSuggestedBinding(ValveIndexController.PROFILE, ValveIndexController.pathBuilder().leftHand().gripPose()); withSuggestedBinding(ValveIndexController.PROFILE, ValveIndexController.pathBuilder().rightHand().gripPose()); withSuggestedBinding(OculusGoController.PROFILE, OculusGoController.pathBuilder().leftHand().gripPose()); withSuggestedBinding(OculusGoController.PROFILE, OculusGoController.pathBuilder().rightHand().gripPose()); withSuggestedBinding(GoogleDaydreamController.PROFILE, GoogleDaydreamController.pathBuilder().rightHand().gripPose()); withSuggestedBinding(GoogleDaydreamController.PROFILE, GoogleDaydreamController.pathBuilder().leftHand().gripPose()); return this; } /** * Binds all the devices this library knows about (and that have aim poses) to this action for both hands. *

* Represents the position and orientation of the user's aiming direction. *

* This pose is typically derived from a hand-held controller's physical design and is generally aligned with the device's primary pointing direction. * In many cases, this pose aligns with the direction the user is pointing the device, like a laser pointer. *

* The orientation of this pose is typically as follows: * - The X-axis points to the right of the controller (as viewed from the back of the controller). * - The Y-axis points up from the top of the controller. * - The Z-axis points in the direction the user is pointing the controller (i.e., from the back of the controller towards the front). *

* This pose is commonly used for: * - Directing the user's gaze or aim in the virtual world. * - Placing the origin of a raycast for selecting or interacting with virtual objects. *

* Note: The exact position and orientation can vary between devices. Always test with the specific device to ensure it behaves as expected. */ public ActionBuilder withSuggestAllKnownAimPoseBindings() { withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().leftHand().aimPose()); withSuggestedBinding(OculusTouchController.PROFILE, OculusTouchController.pathBuilder().rightHand().aimPose()); withSuggestedBinding(HtcViveController.PROFILE, HtcViveController.pathBuilder().leftHand().aimPose()); withSuggestedBinding(HtcViveController.PROFILE, HtcViveController.pathBuilder().rightHand().aimPose()); withSuggestedBinding(KhronosSimpleController.PROFILE, KhronosSimpleController.pathBuilder().leftHand().aimPose()); withSuggestedBinding(KhronosSimpleController.PROFILE, KhronosSimpleController.pathBuilder().rightHand().aimPose()); withSuggestedBinding(MixedRealityMotionController.PROFILE, MixedRealityMotionController.pathBuilder().leftHand().aimPose()); withSuggestedBinding(MixedRealityMotionController.PROFILE, MixedRealityMotionController.pathBuilder().rightHand().aimPose()); withSuggestedBinding(ValveIndexController.PROFILE, ValveIndexController.pathBuilder().leftHand().aimPose()); withSuggestedBinding(ValveIndexController.PROFILE, ValveIndexController.pathBuilder().rightHand().aimPose()); withSuggestedBinding(OculusGoController.PROFILE, OculusGoController.pathBuilder().leftHand().aimPose()); withSuggestedBinding(OculusGoController.PROFILE, OculusGoController.pathBuilder().rightHand().aimPose()); withSuggestedBinding(GoogleDaydreamController.PROFILE, GoogleDaydreamController.pathBuilder().leftHand().aimPose()); withSuggestedBinding(GoogleDaydreamController.PROFILE, GoogleDaydreamController.pathBuilder().rightHand().aimPose()); return this; } /** * Sub action paths are things like "/user/hand/left", for use when restricting actions to a specific input source. * This is defaulted to ["/user/hand/left", "/user/hand/right"] and there is usually no reason to change it. */ public void overrideSupportedSubActionPaths(List supportedSubActionPaths) { this.supportedSubActionPaths = supportedSubActionPaths; } public Action build() { if (actionHandle == null) { throw new IllegalArgumentException("actionHandle cannot be null"); } if (translatedName == null) { translatedName = actionHandle.actionName(); } if (actionType == null) { throw new IllegalArgumentException("actionType cannot be null"); } if (suggestedBindings.isEmpty()) { throw new IllegalArgumentException("suggestedBindings cannot be empty"); } return new Action(actionHandle, translatedName, actionType, suggestedBindings, supportedSubActionPaths); } } /** * This is presented to the user as a description of the action. This string should be presented in the system’s current active locale. */ public String getTranslatedName() { return this.translatedName; } public ActionType getActionType() { return this.actionType; } /** * These are physical bindings to specific devices for this action. */ public List getSuggestedBindings() { return this.suggestedBindings; } public List getSupportedSubActionPaths() { return this.supportedSubActionPaths; } }





© 2015 - 2025 Weber Informatics LLC | Privacy Policy