void debug(Vector2 input, UnityEngine.Experimental.Input.InputDevice context) { bool isKeyborad = context.device is Keyboard; if (isKeyborad) { Debug.Log(input); } }
private void OnJoin(UnityEngine.Experimental.Input.InputDevice device) { // Spawn player. var player = SpawnPlayer(); // Give the player the device that the join was initiated from and then // let the player component do the initialization work from there. player.AssignInputDevice(device); player.StartMultiPlayerGame(); }
private DemoPlayerController FindPlayerControllerForDevice(InputDevice device) { var user = InputUser.FindUserPairedToDevice(device); if (user == null) { return(null); } return(FindPlayerControllerForUser(user.Value)); }
void updateCameraPos(Vector2 mouse, UnityEngine.Experimental.Input.InputDevice context) { if (context.device is Gamepad) { mouse.x = mouse.x * gamepadSens; mouse.y = mouse.y * gamepadSens; } else { mouse.x = mouse.x * mouseSensitivity * Time.deltaTime; mouse.y = mouse.y * mouseSensitivity * Time.deltaTime; } xRotation -= mouse.y; xRotation = Mathf.Clamp(xRotation, -90f, 90f); transform.localRotation = Quaternion.Euler(xRotation, 0f, 0f); playerBody.Rotate(Vector3.up * mouse.x); }
/// <summary> /// Called when there's a change in the input user setup in the system. /// </summary> /// <param name="user"></param> /// <param name="change"></param> /// <param name="device"></param> private void OnUserChange(InputUser user, InputUserChange change, InputDevice device) { var player = FindPlayerControllerForUser(user); switch (change) { // A player has switched accounts. This will only happen on platforms that have user account // management (PS4, Xbox, Switch). On PS4, for example, this can happen at any time by the // player pressing the PS4 button and switching accounts. We simply update the information // we display for the player's active user account. case InputUserChange.AccountChanged: { if (player != null) { player.OnUserAccountChanged(); } break; } // If the user has cancelled account selection, we remove the user if there's no devices // already paired to it. This usually happens when a player initiates a join on a device on // Xbox or Switch, has the account picker come up, but then cancels instead of making an // account selection. In this case, we want to cancel the join. // NOTE: We are only adding DemoPlayerControllers once device pairing is complete case InputUserChange.AccountSelectionCancelled: { if (user.pairedDevices.Count == 0) { Debug.Assert(FindPlayerControllerForUser(user) == null); user.UnpairDevicesAndRemoveUser(); } break; } // An InputUser gained a new device. If we're in the lobby and don't yet have a player // for the user, it means a new player has joined. We don't join players until they have // a device paired to them which is why we ignore InputUserChange.Added and only react // to InputUserChange.DevicePaired instead. case InputUserChange.DevicePaired: { if (state == State.InLobby && player == null) { OnPlayerJoins(user); } else if (player != null) { player.OnDevicesOrBindingsHaveChanged(); } break; } // Some player ran out of battery or unplugged a wired device. case InputUserChange.DeviceLost: { Debug.Assert(player != null); player.OnDeviceLost(); ////REVIEW: should we unjoin a user when losing devices in the lobby? ////TODO: we need a way for other players to be able to resolve the situation // If we're currently in-game, we pause the game until the player has re-gained control. if (isInGame) { PauseGame(); } break; } // Some player has customized controls or had previously customized controls loaded. case InputUserChange.BindingsChanged: { player.OnDevicesOrBindingsHaveChanged(); break; } } }
/// <summary> /// Checks an Input Event for any significant changes that would be considered user activity. /// </summary> /// <param name="inputEvent">The input event being checked for changes</param> /// <param name="device">The input device being checked against </param> /// <param name="offset">The offset into the device that the event is placed</param> /// <param name="sizeInBytes">The size of the event in bytes</param> /// <returns>True if any changes exist in the event once the device has been filtered through for noise and non-significant changes. False otherwise.</returns> public unsafe bool EventHasValidData(InputDevice device, InputEventPtr inputEvent, uint offset, uint sizeInBytes) { if (!inputEvent.valid) { throw new ArgumentException("Invalid or unset event being checked.", "inputEvent"); } if (device == null) { throw new ArgumentNullException("device"); } if (IsEmpty()) { return(true); } if ((offset + sizeInBytes) * 8 > device.stateBlock.sizeInBits) { return(false); } var noiseFilterPtr = InputStateBuffers.s_NoiseBitmaskBuffer; if (noiseFilterPtr == IntPtr.Zero) { throw new Exception("Noise Filter Buffer is uninitialized while trying to check state events for data."); } var ptrToEventState = IntPtr.Zero; if (inputEvent.IsA <StateEvent>()) { var stateEvent = StateEvent.From(inputEvent); ptrToEventState = stateEvent->state; } else if (inputEvent.IsA <DeltaStateEvent>()) { var stateEvent = DeltaStateEvent.From(inputEvent); ptrToEventState = stateEvent->deltaState; } else { throw new ArgumentException(string.Format( "Invalid event type '{0}', we can only check for valid data on StateEvents and DeltaStateEvents.", inputEvent.type), "inputEvent"); } if (MemoryHelpers.HasAnyNonZeroBitsAfterMaskingWithBuffer(ptrToEventState, noiseFilterPtr, offset, sizeInBytes * 8)) { return(true); } for (var i = 0; i < elements.Length; i++) { if (elements[i].EventHasValidData(inputEvent, device)) { return(true); } } return(false); }
public void SetDeviceCommandCallback(InputDevice device, DeviceCommandCallback callback) { SetDeviceCommandCallback(device.id, callback); }
private static TControl MatchByUsageAtDeviceRootRecursive <TControl>(InputDevice device, string path, int indexInPath, ref InputControlList <TControl> matches, bool matchMultiple) where TControl : InputControl { var usages = device.m_UsagesForEachControl; if (usages == null) { return(null); } var usageCount = usages.Length; var startIndex = indexInPath + 1; var pathCanMatchMultiple = PathComponentCanYieldMultipleMatches(path, indexInPath); var pathLength = path.Length; Debug.Assert(path[indexInPath] == '{'); ++indexInPath; if (indexInPath == pathLength) { throw new Exception(string.Format("Invalid path spec '{0}'; trailing '{{'", path)); } TControl lastMatch = null; for (var i = 0; i < usageCount; ++i) { var usage = usages[i]; // Match usage agaist path. var usageIsMatch = MatchPathComponent(usage, path, ref indexInPath, PathComponentType.Usage); // If it isn't a match, go to next usage. if (!usageIsMatch) { indexInPath = startIndex; continue; } var controlMatchedByUsage = device.m_UsageToControl[i]; // If there's more to go in the path, dive into the children of the control. if (indexInPath < pathLength && path[indexInPath] == '/') { lastMatch = MatchChildrenRecursive(controlMatchedByUsage, path, indexInPath + 1, ref matches, matchMultiple); // We can stop going through usages if we matched something and the // path component covering usage does not contain wildcards. if (lastMatch != null && !pathCanMatchMultiple) { break; } // We can stop going through usages if we have a match and are only // looking for a single one. if (lastMatch != null && !matchMultiple) { break; } } else { lastMatch = controlMatchedByUsage as TControl; if (lastMatch != null) { if (matchMultiple) { matches.Add(lastMatch); } else { // Only looking for single match and we have one. break; } } } } return(lastMatch); }
public InputDeviceBuilder(string layout, InputDevice existingDevice = null, string variants = null) { m_LayoutCache.layouts = InputControlLayout.s_Layouts; Setup(new InternedString(layout), existingDevice, new InternedString(variants)); }
private InputControl InstantiateLayout(InputControlLayout layout, InternedString variants, InternedString name, InputControl parent, InputControl existingControl) { InputControl control; // If we have an existing control, see whether it's usable. if (existingControl != null && existingControl.layout == layout.name && existingControl.GetType() == layout.type) { control = existingControl; ////FIXME: the re-use path probably has some data that could stick around when it shouldn't control.m_UsagesReadOnly = new ReadOnlyArray <InternedString>(); control.ClearProcessors(); } else { Debug.Assert(layout.type != null); // No, so create a new control. var controlObject = Activator.CreateInstance(layout.type); control = controlObject as InputControl; if (control == null) { throw new Exception(string.Format("Type '{0}' referenced by layout '{1}' is not an InputControl", layout.type.Name, layout.name)); } } // If it's a device, perform some extra work specific to the control // hierarchy root. var controlAsDevice = control as InputDevice; if (controlAsDevice != null) { if (parent != null) { throw new Exception(string.Format( "Cannot instantiate device layout '{0}' as child of '{1}'; devices must be added at root", layout.name, parent.path)); } m_Device = controlAsDevice; m_Device.m_StateBlock.byteOffset = 0; m_Device.m_StateBlock.format = layout.stateFormat; // If we have an existing device, we'll start the various control arrays // from scratch. Note that all the controls still refer to the existing // arrays and so we can iterate children, for example, just fine while // we are rebuilding the control hierarchy. m_Device.m_AliasesForEachControl = null; m_Device.m_ChildrenForEachControl = null; m_Device.m_UsagesForEachControl = null; m_Device.m_UsageToControl = null; // But we preserve IDs and descriptions of existing devices. if (existingControl != null) { var existingDevice = (InputDevice)existingControl; m_Device.m_Id = existingDevice.m_Id; m_Device.m_Description = existingDevice.m_Description; } if (layout.m_UpdateBeforeRender == true) { m_Device.m_Flags |= InputDevice.Flags.UpdateBeforeRender; } } else if (parent == null) { // Someone did "new InputDeviceBuilder(...)" with a control layout. // We don't support creating control hierarchies without a device at the root. throw new InvalidOperationException( string.Format( "Toplevel layout used with InputDeviceBuilder must be a device layout; '{0}' is a control layout", layout.name)); } // Name defaults to name of layout. if (name.IsEmpty()) { name = layout.name; // If there's a namespace in the layout name, snip it out. var indexOfLastColon = name.ToString().LastIndexOf(':'); if (indexOfLastColon != -1) { name = new InternedString(name.ToString().Substring(indexOfLastColon + 1)); } } // Variant defaults to variants of layout. if (variants.IsEmpty()) { variants = layout.variants; if (variants.IsEmpty()) { variants = InputControlLayout.DefaultVariant; } } control.m_Name = name; control.m_DisplayNameFromLayout = layout.m_DisplayName; control.m_Layout = layout.name; control.m_Variants = variants; control.m_Parent = parent; control.m_Device = m_Device; // Create children and configure their settings from our // layout values. var haveChildrenUsingStateFromOtherControl = false; try { // Pass list of existing control on to function as we may have decided to not // actually reuse the existing control (and thus control.m_ChildrenReadOnly will // now be blank) but still want crawling down the hierarchy to preserve existing // controls where possible. AddChildControls(layout, variants, control, existingControl != null ? existingControl.m_ChildrenReadOnly : (ReadOnlyArray <InputControl>?)null, ref haveChildrenUsingStateFromOtherControl); } catch { ////TODO: remove control from collection and rethrow throw; } // Come up with a layout for our state. ComputeStateLayout(control); // Finally, if we have child controls that take their state blocks from other // controls, assign them their blocks now. if (haveChildrenUsingStateFromOtherControl) { foreach (var controlLayout in layout.controls) { if (string.IsNullOrEmpty(controlLayout.useStateFrom)) { continue; } var child = TryGetControl(control, controlLayout.name); Debug.Assert(child != null); // Find the referenced control. var referencedControl = TryGetControl(control, controlLayout.useStateFrom); if (referencedControl == null) { throw new Exception( string.Format( "Cannot find control '{0}' referenced in 'useStateFrom' of control '{1}' in layout '{2}'", controlLayout.useStateFrom, controlLayout.name, layout.name)); } // Copy its state settings. child.m_StateBlock = referencedControl.m_StateBlock; // At this point, all byteOffsets are relative to parents so we need to // walk up the referenced control's parent chain and add offsets until // we are at the same level that we are at. for (var parentInChain = referencedControl.parent; parentInChain != control; parentInChain = parentInChain.parent) { child.m_StateBlock.byteOffset += parentInChain.m_StateBlock.byteOffset; } } } return(control); }
// Reset the setup in a way where it can be reused for another setup. // Should retain allocations that can be reused. private void Reset() { m_Device = null; m_ChildControlOverrides = null; // Leave the cache in place so we can reuse them in another setup path. }
/// <summary> /// Given an existing <paramref name="device">input device</paramref>, try to find a control scheme in /// <paramref name="asset"/> that matches the device with one of its required or optional devices. /// </summary> /// <param name="asset"></param> /// <param name="device"></param> /// <returns></returns> public static InputControlScheme?FindFirstControlSchemeMatchingDevice(this InputActionAsset asset, InputDevice device) { throw new NotImplementedException(); }