fernandojsg / aframe-teleport-controls

A-Frame teleport controls component
https://fernandojsg.github.io/aframe-teleport-controls
MIT License
174 stars 72 forks source link

How to set orientation based on axis position after teleport? #44

Open fernandojsg opened 6 years ago

fernandojsg commented 6 years ago

from @machenmusik https://github.com/fernandojsg/aframe-input-mapping-component/issues

A common teleport mechanic now (robo recall, blade runner 2049, windows mixed reality) is for orientation after teleport to be set via axis position, and shown live while targeting. How should that best be done with teleport-controls?

netpro2k commented 6 years ago

This does serve to point out a common usecase that input-mappings currently does not map well onto, bindings that combine multiple types of inputs/events.

In order to do this behavior you would need a mapping to start teleport, a mapping for axismove, and a mapping to end teleporting. The teleport-controls component would need to store state about the axismove events and then use them in the teleport end event (similar to what is being done here for dpad controls https://github.com/mozilla/mr-social-client/blob/master/src/components/axis-dpad.js)

Not sure about the right way to solve this, but a non-evented way to access mappings would solve the intermediate state for these cases. Not sure what the mapping side would look like but I could imagine an api like AFRAME.input.getAxis("some_named_axis") returning a float between -1 and 1, and AFRAME.input.getButtonDown("some_named_button") returning a boolean. Then in teleport-controlstick` you could just query the current axis values to render the teleport target with facing information.

machenmusik commented 6 years ago

It can be a separate component that is looking for the right events, as long as teleport-controls provides the right ones. Not hard to have a component remember last trackpadmoved or thumbstickmoved and react to a teleport?

machenmusik commented 6 years ago

Or, you can just read the current values off the controller reference, right?

fernandojsg commented 6 years ago

Based on https://github.com/fernandojsg/aframe-input-mapping-component/issues/12 what do you think about something like:

{
  "trackpaddown": "startTeleport",
  "axisMove[@state=startTeleport]": "rotateForwardVector",
  "trackpadup": "endTeleport"
}

So on trackpaddown the ray will appear, then you could decide depending on your controller if define the rotatingForward that will be called just if the startTeleport state is set and it will be called on axisMove so in the listener we could get the Z angle to modify the forward direction. Once we release the trackpad it will jump to that position.

fernandojsg commented 6 years ago

Other option is to create another inputMapping while you're on aiming/startTeleport, maybe more verbose, but:

teleport: {
  "trackpaddown": "startTeleport",
},
aiming: {
  axisMove: 'rotatingForward',
  "trackpadup": "endTeleport"
}
fernandojsg commented 6 years ago

This is highly related to the latest comments by @johnshaughnessy on https://github.com/fernandojsg/aframe-input-mapping-component/issues/2

dmarcos commented 6 years ago

I don’t think creating a DSL where we have to parse strings and handle errors is a maintainable path. If a robo recall teleport system is something we need or someone is trying to implement right we can look into it, better with some working code. I would not anticipate too much, keep the input mapping simple and evolve it as we need.

fernandojsg commented 6 years ago

Yep, the more I check the syntax with custom attributes and so on, the less I like it. It's a complex problem, I'm not sure how they solve it on the steam controller API. I believe @johnshaughnessy mentioned the modifiers or layers that could be used for that.

If we're painting and click the teleport it maybe makes sense to change the mapping to teleporting-state as you won't be able to do any other action while waiting for teleport.

So when the startTeleport event is triggered, we set the state to teleportAiming and on the teleport event, we change it back to painting.

{
  painting: {
    vive: {
      "triggerdown": "paint"
      "trackpaddown": "startTeleport"
    }
  },
  teleportAiming: {
    vive: {
      "trackpadup": "teleport"
      "axismoveZ": "changeTeleportOrientation"
    }
  }
}

For this specific issue I believe this is enough to solve it but modifiers are something that we'll need. I'll open a specific issue on the input mapping for that.

dmarcos commented 6 years ago

Yes, I think teleportAiming involves a sate change. I propose two ideas to explore in the future but I do not love either of them yet 😄

  1. tasks \ states to be able to reuse other tasks \ states. So you have to only define the differences in the mapping.
    {
    painting: {
    vive: {
      "gripdown" : "undo",
      "menudown" :  "togglepalette",
      "triggerdown": "paint",
      "trackpaddown": "startTeleport"
    }
    },
    teleportAiming: {
    use: 'painting'
    vive: {
      "trackpadup": "teleport"
      "axismoveZ": "changeTeleportOrientation"
    }
    }
    }

    Another option is to allow for nested mappings:

    painting: {
    vive: {
       "gripdown" : "undo",
      "menudown" :  "togglepalette",
      "triggerdown": "paint",
      "trackpaddown": "startTeleport"
    }, 
    mappings:  {
       teleportAiming: {
       vive: {
         "trackpadup": "teleport"
         "axismoveZ": "changeTeleportOrientation"
       }
    }
    }