private static void Possess(MotionControllerWithCustomPossessPoint motionControl, FreeControllerV3 controller) { if (!motionControl.controlPosition && !motionControl.controlRotation) { return; } var sc = SuperController.singleton; controller.possessed = true; var mac = controller.GetComponent <MotionAnimationControl>(); if (mac != null) { if (motionControl.controlPosition) { mac.suspendPositionPlayback = true; } if (motionControl.controlRotation) { mac.suspendRotationPlayback = true; } } if (!motionControl.keepCurrentPhysicsHoldStrength) { if (motionControl.controlPosition) { controller.RBHoldPositionSpring = sc.possessPositionSpring; } if (motionControl.controlRotation) { controller.RBHoldRotationSpring = sc.possessRotationSpring; } } var motionControllerRB = motionControl.controllerPointRB; FreeControllerV3.SelectLinkState linkState; if (!motionControl.controlRotation) { linkState = FreeControllerV3.SelectLinkState.Position; } else if (!motionControl.controlPosition) { linkState = FreeControllerV3.SelectLinkState.Rotation; } else { linkState = FreeControllerV3.SelectLinkState.PositionAndRotation; } controller.SelectLinkToRigidbody( motionControllerRB, linkState ); controller.canGrabPosition = false; controller.canGrabRotation = false; }
public void AttachToClosestNode(MotionControllerWithCustomPossessPoint motionControl) { var controllers = _context.containingAtom.freeControllers .Where(fc => fc.name.EndsWith("Control")) .Where(fc => fc.control != null); AttachToClosestNode(motionControl, controllers); }
private MotionControllerWithCustomPossessPoint AddMotionControl(string motionControlName, Func <Transform> getMotionControl, string mappedControllerName = null, Action <MotionControllerWithCustomPossessPoint> configure = null) { var motionControl = MotionControllerWithCustomPossessPoint.Create(motionControlName, getMotionControl, configure); motionControl.mappedControllerName = mappedControllerName; motionControls.Add(motionControl); motionControl.SyncMotionControl(); return(motionControl); }
public MeasureArmsAtRestStep(EmbodyContext context, ControllerAnchorPoint anchor) : base(context) { _anchor = anchor; _leftHandControl = context.containingAtom.freeControllers.First(fc => fc.name == "lHandControl"); _rightHandControl = context.containingAtom.freeControllers.First(fc => fc.name == "rHandControl"); _leftHandMotion = context.trackers.motionControls.First(mc => mc.name == MotionControlNames.LeftHand); _rightHandMotion = context.trackers.motionControls.First(mc => mc.name == MotionControlNames.RightHand); }
public override void Hide() { base.Hide(); _section = null; if (_currentMotionControl != null) { _currentMotionControl.highlighted = false; } _currentMotionControl = null; }
public static void ConfigureHand(MotionControllerWithCustomPossessPoint motionControl, bool isRight) { ConfigureHandPerDevice(motionControl, isRight); // Hands are mapped to something else than the hand control; cancel hand rotation if (motionControl.mappedControllerName != (isRight ? VamConstants.RightHandControlName : VamConstants.LeftHandControlName)) { motionControl.rotateControllerCustom = new Vector3(-90, -90, 90); } }
private void AddMotionControl(string motionControlName, Func <Transform> getMotionControl, string mappedControllerName = null, Vector3 baseOffset = new Vector3(), Vector3 baseOffsetRotation = new Vector3()) { var motionControl = MotionControllerWithCustomPossessPoint.Create(motionControlName, getMotionControl); motionControl.mappedControllerName = mappedControllerName; motionControl.baseOffset = baseOffset; motionControl.baseOffsetRotation = baseOffsetRotation; motionControls.Add(motionControl); motionControl.SyncMotionControl(); }
private bool Bind(MotionControllerWithCustomPossessPoint motionControl) { var controllerWithSnapshot = FindController(motionControl); if (controllerWithSnapshot == null) { return(false); } if (controllerWithSnapshot.active) { return(false); } var controller = controllerWithSnapshot.controller; controller.startedPossess = true; if (motionControl.name == MotionControlNames.Head) { if (motionControl.mappedControllerName == VamConstants.HeadControlName) { // Reduce the stretch between the head and the eye by matching the controller and the head bone controller.control.position = context.bones.First(b => b.name == VamConstants.HeadBoneName).transform.position; AdjustHeadToEyesOffset(); } if (motionControl.currentMotionControl == SuperController.singleton.centerCameraTarget.transform) { UserPreferences.singleton.headCollider.gameObject.SetActive(false); SuperController.singleton.AlignRigAndController(controller, motionControl); } else { SuperController.singleton.AlignTransformAndController(controller, motionControl); } } else { if (motionControl.controlRotation) { controller.control.rotation = motionControl.controllerPointTransform.rotation; } if (motionControl.controlPosition) { controller.control.position = motionControl.controllerPointTransform.position; } } controllerWithSnapshot.active = true; controllerWithSnapshot.snapshot = FreeControllerV3Snapshot.Snap(controller); Possess(motionControl, controller); return(true); }
public static void ConfigureHand(MotionControllerWithCustomPossessPoint motionControl, bool isRight) { var t = motionControl.currentMotionControl; if (t == SuperController.singleton.touchObjectLeft) { motionControl.offsetControllerBase = OVRLeftOffset; motionControl.rotateControllerBase = OVRLeftRotate; } else if (t == SuperController.singleton.touchObjectRight) { motionControl.offsetControllerBase = OVRRightOffset; motionControl.rotateControllerBase = OVRRightRotate; } else if (t == SuperController.singleton.viveObjectLeft) { motionControl.offsetControllerBase = _viveLeftOffset; motionControl.rotateControllerBase = _viveLeftRotate; } else if (t == SuperController.singleton.viveObjectRight) { motionControl.offsetControllerBase = _viveRightOffset; motionControl.rotateControllerBase = _viveRightRotate; } else if (t == SuperController.singleton.leapHandLeft) { motionControl.offsetControllerBase = _leapLeftOffset; motionControl.rotateControllerBase = _leapLeftRotate; } else if (t == SuperController.singleton.leapHandRight) { motionControl.offsetControllerBase = _leapRightOffset; motionControl.rotateControllerBase = _leapRightRotate; } else if (!isRight) { // TODO: Copied from Oculus controller motionControl.offsetControllerBase = OVRLeftOffset; motionControl.rotateControllerBase = OVRLeftRotate; } else { // TODO: Copied from Oculus controller motionControl.offsetControllerBase = OVRRightOffset; motionControl.rotateControllerBase = OVRRightRotate; } }
private FreeControllerV3WithSnapshot FindController(MotionControllerWithCustomPossessPoint motionControl) { if (!motionControl.enabled) { return(null); } if (motionControl.mappedControllerName == null) { return(null); } if (context.passenger.selectedJSON.val && motionControl.name == MotionControlNames.Head) { return(null); } if (context.snug.selectedJSON.val && (motionControl.name == MotionControlNames.LeftHand || motionControl.name == MotionControlNames.RightHand)) { if (motionControl.name == MotionControlNames.LeftHand && motionControl.mappedControllerName != VamConstants.LeftHandControlName) { SuperController.LogError($"Embody: Left hand control is mapped to {motionControl.mappedControllerName} but since Snug is activated, your setting will be ignored"); } if (motionControl.name == MotionControlNames.RightHand && motionControl.mappedControllerName != VamConstants.RightHandControlName) { SuperController.LogError($"Embody: Left hand control is mapped to {motionControl.mappedControllerName} but since Snug is activated, your setting will be ignored"); } return(null); } var controllerWithSnapshot = controllers.FirstOrDefault(cs => cs.controller.name == motionControl.mappedControllerName); if (controllerWithSnapshot == null) { return(null); } var controller = controllerWithSnapshot.controller; if (controller.possessed) { return(null); } if (!motionControl.SyncMotionControl()) { return(null); } return(controllerWithSnapshot); }
private static void Possess(MotionControllerWithCustomPossessPoint motionControl, FreeControllerV3 controller) { var sc = SuperController.singleton; controller.possessed = true; var motionControllerHeadRigidbody = motionControl.customRigidbody; var motionAnimationControl = controller.GetComponent <MotionAnimationControl>(); controller.canGrabPosition = true; motionAnimationControl.suspendPositionPlayback = true; controller.RBHoldPositionSpring = sc.possessPositionSpring; controller.canGrabRotation = true; motionAnimationControl.suspendRotationPlayback = true; controller.RBHoldRotationSpring = sc.possessRotationSpring; controller.SelectLinkToRigidbody(motionControllerHeadRigidbody, FreeControllerV3.SelectLinkState.PositionAndRotation); }
private static void AlignRigAndController(FreeControllerV3 controller, MotionControllerWithCustomPossessPoint motionControl) { var sc = SuperController.singleton; var navigationRig = sc.navigationRig; var forwardPossessAxis = controller.GetForwardPossessAxis(); var upPossessAxis = controller.GetUpPossessAxis(); var navigationRigUp = navigationRig.up; var fromDirection = Vector3.ProjectOnPlane(motionControl.possessPointTransform.forward, navigationRigUp); var vector = Vector3.ProjectOnPlane(forwardPossessAxis, navigationRigUp); if (Vector3.Dot(upPossessAxis, navigationRigUp) < 0f && Vector3.Dot(motionControl.possessPointTransform.up, navigationRigUp) > 0f) { vector = -vector; } var rotation = Quaternion.FromToRotation(fromDirection, vector); navigationRig.rotation = rotation * navigationRig.rotation; controller.AlignTo(motionControl.possessPointTransform, true); var possessPointDelta = controller.control.position - motionControl.currentMotionControl.position - controller.control.rotation * motionControl.combinedOffset; var navigationRigPosition = navigationRig.position; var navigationRigPositionDelta = navigationRigPosition + possessPointDelta; var navigationRigUpDelta = Vector3.Dot(navigationRigPositionDelta - navigationRigPosition, navigationRigUp); navigationRigPositionDelta += navigationRigUp * (0f - navigationRigUpDelta); navigationRig.position = navigationRigPositionDelta; sc.playerHeightAdjust += navigationRigUpDelta; if (sc.MonitorCenterCamera != null) { var monitorCenterCameraTransform = sc.MonitorCenterCamera.transform; monitorCenterCameraTransform.LookAt(controller.transform.position + forwardPossessAxis); var localEulerAngles = monitorCenterCameraTransform.localEulerAngles; localEulerAngles.y = 0f; localEulerAngles.z = 0f; monitorCenterCameraTransform.localEulerAngles = localEulerAngles; } }
private FreeControllerV3WithSnapshot FindController(MotionControllerWithCustomPossessPoint motionControl) { if (!motionControl.enabled) { return(null); } if (motionControl.mappedControllerName == null) { return(null); } if (passenger.selectedJSON.val && motionControl.name == MotionControlNames.Head) { return(null); } if (snug.selectedJSON.val && (motionControl.name == MotionControlNames.LeftHand || motionControl.name == MotionControlNames.RightHand)) { return(null); } var controllerWithSnapshot = controllers.FirstOrDefault(cs => cs.controller.name == motionControl.mappedControllerName); if (controllerWithSnapshot == null) { return(null); } var controller = controllerWithSnapshot.controller; if (controller.possessed) { return(null); } if (!controller.possessable) { return(null); } if (!motionControl.SyncMotionControl()) { return(null); } return(controllerWithSnapshot); }
private void AttachToClosestNode(MotionControllerWithCustomPossessPoint motionControl) { if (!motionControl.SyncMotionControl()) { SuperController.LogError($"Embody: {motionControl.name} does not seem to be attached to a VR motion control."); return; } var position = motionControl.currentMotionControl.position; var closestDistance = float.PositiveInfinity; Rigidbody closest = null; foreach (var controller in context.containingAtom.freeControllers.Where(fc => fc.name.EndsWith("Control")).Select(fc => fc.GetComponent <Rigidbody>())) { if (_skipAutoBindControllers.Contains(controller.name)) { continue; } var distance = Vector3.Distance(position, controller.position); if (distance < closestDistance) { closestDistance = distance; closest = controller; } } if (closest == null) { throw new NullReferenceException("There was no controller available to attach."); } motionControl.mappedControllerName = closest.name; motionControl.customOffset = motionControl.possessPointTransform.InverseTransformDirection(closest.position - position); motionControl.customOffsetRotation = (Quaternion.Inverse(motionControl.possessPointTransform.rotation) * closest.rotation).eulerAngles; ShowMotionControl(motionControl); context.Refresh(); }
public void AttachToClosestNode(MotionControllerWithCustomPossessPoint motionControl, IEnumerable <FreeControllerV3> controllers) { if (!motionControl.SyncMotionControl()) { SuperController.LogError($"Embody: {motionControl.name} does not seem to be attached to a VR motion control."); return; } var position = motionControl.currentMotionControl.position; var closestDistance = float.PositiveInfinity; FreeControllerV3 closest = null; foreach (var controller in controllers) { var rigidbody = controller.GetComponent <Rigidbody>(); if (!_autoBindControllers.Contains(controller.name)) { continue; } var distance = Vector3.Distance(position, rigidbody.position); if (!(distance < closestDistance)) { continue; } closestDistance = distance; closest = controller; } if (closest == null) { throw new NullReferenceException("There was no controller available to attach."); } motionControl.mappedControllerName = closest.name; AlignToNode(motionControl, closest); }
public void AlignToNode(MotionControllerWithCustomPossessPoint motionControl, FreeControllerV3 controller) { if (!motionControl.SyncMotionControl()) { SuperController.LogError($"Embody: {motionControl.name} does not seem to be attached to a VR motion control."); return; } motionControl.offsetControllerCustom = motionControl.currentMotionControl.InverseTransformPoint(controller.control.position); var customOffsetRotation = (Quaternion.Inverse(motionControl.currentMotionControl.rotation) * controller.control.rotation).eulerAngles; motionControl.rotateControllerCustom = new Vector3( customOffsetRotation.x > 180 ? customOffsetRotation.x - 360 : customOffsetRotation.x, customOffsetRotation.y > 180 ? customOffsetRotation.y - 360 : customOffsetRotation.y, customOffsetRotation.z > 180 ? customOffsetRotation.z - 360 : customOffsetRotation.z ); motionControl.rotateAroundTrackerCustom = Vector3.zero; motionControl.controlRotation = !_disableRotationControllers.Contains(controller.name); if (_centeredControllers.Contains(controller.name)) { motionControl.offsetControllerCustom.Scale(new Vector3(1f, 0f, 1f)); motionControl.rotateControllerCustom.Scale(new Vector3(1f, 0f, 0f)); } }
private static void ConfigureHandPerDevice(MotionControllerWithCustomPossessPoint motionControl, bool isRight) { var t = motionControl.currentMotionControl; // Vive Controller if (t == SuperController.singleton.touchObjectLeft) { motionControl.offsetControllerBase = OVRLeftOffset; motionControl.rotateControllerBase = OVRLeftRotate; return; } if (t == SuperController.singleton.touchObjectRight) { motionControl.offsetControllerBase = OVRRightOffset; motionControl.rotateControllerBase = OVRRightRotate; return; } // Vive Tracker if (t == SuperController.singleton.viveObjectLeft) { motionControl.offsetControllerBase = _viveLeftOffset; motionControl.rotateControllerBase = _viveLeftRotate; return; } if (t == SuperController.singleton.viveObjectRight) { motionControl.offsetControllerBase = _viveRightOffset; motionControl.rotateControllerBase = _viveRightRotate; return; } // Leap Motion if (t == SuperController.singleton.leapHandLeft) { motionControl.offsetControllerBase = _leapLeftOffset; motionControl.rotateControllerBase = _leapLeftRotate; return; } if (t == SuperController.singleton.leapHandRight) { motionControl.offsetControllerBase = _leapRightOffset; motionControl.rotateControllerBase = _leapRightRotate; return; } // Oculus Rift if (isRight) { motionControl.offsetControllerBase = OVRRightOffset; motionControl.rotateControllerBase = OVRRightRotate; return; } else { motionControl.offsetControllerBase = OVRLeftOffset; motionControl.rotateControllerBase = OVRLeftRotate; return; } }
private static Vector3 ComputePosition(Transform transform, FreeControllerV3 controller, MotionControllerWithCustomPossessPoint motionControl) { var possessPointDelta = controller.control.position - motionControl.controllerPointTransform.position; var currentPosition = transform.position; return(currentPosition + possessPointDelta); }
public static void AlignRigAndController(this SuperController sc, FreeControllerV3 controller, MotionControllerWithCustomPossessPoint motionControl, bool alignControl = true) { var up = sc.navigationRig.up; sc.navigationRig.rotation = ComputeRotation(sc.navigationRig, controller, up); if (alignControl) { controller.AlignTo(motionControl.controllerPointTransform, true); } var position = ComputePosition(sc.navigationRig, controller, motionControl); var upDelta = Vector3.Dot(position - sc.navigationRig.position, up); position += up * (0f - upDelta); sc.navigationRig.position = position; sc.playerHeightAdjust += upDelta; if (sc.MonitorCenterCamera != null) { var monitorCenterCameraTransform = sc.MonitorCenterCamera.transform; monitorCenterCameraTransform.LookAt(controller.transform.position + controller.GetForwardPossessAxis()); var localEulerAngles = monitorCenterCameraTransform.localEulerAngles; localEulerAngles.y = 0f; localEulerAngles.z = 0f; monitorCenterCameraTransform.localEulerAngles = localEulerAngles; } }
// ReSharper disable once UnusedParameter.Global public static void AlignTransformAndController(this SuperController _, FreeControllerV3 controller, MotionControllerWithCustomPossessPoint motionControl, bool alignControl = true) { var transform = motionControl.currentMotionControl; var up = transform.up; transform.rotation = ComputeRotation(transform, controller, up); if (alignControl) { controller.AlignTo(motionControl.controllerPointTransform, true); } var position = ComputePosition(transform, controller, motionControl); transform.position = position; }
private void ShowMotionControl(MotionControllerWithCustomPossessPoint motionControl) { if (_section == null) { _section = CreateSection(); } _section.RemoveAll(); if (_currentMotionControl != null) { _currentMotionControl.highlighted = false; } if (motionControl == null) { return; } _currentMotionControl = motionControl; _currentMotionControl.highlighted = true; if (MotionControlNames.IsViveTracker(motionControl.name)) { _section.CreateButton("Map to Closest Control", true).button.onClick.AddListener(() => { _trackerAutoSetup.AttachToClosestNode(motionControl); ShowMotionControl(motionControl); context.Refresh(); }); _section.CreateButton("Align to Mapped Control", true).button.onClick.AddListener(() => { var controller = context.containingAtom.freeControllers.FirstOrDefault(fc => fc.name == motionControl.mappedControllerName); if (controller != null) { _trackerAutoSetup.AlignToNode(motionControl, controller); ShowMotionControl(motionControl); context.Refresh(); } }); } _section.CreateToggle(new JSONStorableBool( $"{motionControl.name} Enabled", motionControl.enabled, val => { motionControl.enabled = val; if (MotionControlNames.IsHands(motionControl.name)) { _handsToggleJSON.valNoCallback = _trackers.leftHandMotionControl.enabled || _trackers.rightHandMotionControl.enabled; } context.Refresh(); } )); if (!MotionControlNames.IsHeadOrHands(motionControl.name)) { _section.CreateFilterablePopup(new JSONStorableStringChooser( "", new[] { _none }.Concat(_trackers.controllers.Select(mc => mc.controller.name)).ToList(), motionControl.mappedControllerName, "Map to control*", val => { motionControl.mappedControllerName = val == _none ? null : val; context.Refresh(); }), false); _section.CreateToggle(new JSONStorableBool( $"{motionControl.name} Controls Position*", motionControl.controlPosition, val => motionControl.controlPosition = val ), false); _section.CreateToggle(new JSONStorableBool( $"{motionControl.name} Controls Rotation*", motionControl.controlRotation, val => motionControl.controlRotation = val ), false); } if (MotionControlNames.IsHands(motionControl.name)) { _section.CreateToggle(new JSONStorableBool( $"Fingers Tracking*", motionControl.fingersTracking, val => motionControl.fingersTracking = val ), false); _section.CreateToggle(new JSONStorableBool( $"Position Tracking*", motionControl.controlPosition, val => motionControl.controlPosition = motionControl.controlRotation = val ), false); _section.CreateToggle(new JSONStorableBool( $"Use Leap Motion Position*", motionControl.useLeapPositioning, val => motionControl.useLeapPositioning = val ), false); } _section.CreateSlider(new JSONStorableFloat( $"Offset X*", motionControl.offsetControllerCustom.x, val => motionControl.offsetControllerCustom = new Vector3(val, motionControl.offsetControllerCustom.y, motionControl.offsetControllerCustom.z), -0.5f, 0.5f, false), false); _section.CreateSlider(new JSONStorableFloat( $"Offset Y*", motionControl.offsetControllerCustom.y, val => motionControl.offsetControllerCustom = new Vector3(motionControl.offsetControllerCustom.x, val, motionControl.offsetControllerCustom.z), -0.5f, 0.5f, false), false); _section.CreateSlider(new JSONStorableFloat( $"Offset Z*", motionControl.offsetControllerCustom.z, val => motionControl.offsetControllerCustom = new Vector3(motionControl.offsetControllerCustom.x, motionControl.offsetControllerCustom.y, val), -0.5f, 0.5f, false), false); _section.CreateSlider(new JSONStorableFloat( $"Rotate Controller X*", motionControl.rotateControllerCustom.x, val => motionControl.rotateControllerCustom = new Vector3(val, motionControl.rotateControllerCustom.y, motionControl.rotateControllerCustom.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"Rotate Controller Y*", motionControl.rotateControllerCustom.y, val => motionControl.rotateControllerCustom = new Vector3(motionControl.rotateControllerCustom.x, val, motionControl.rotateControllerCustom.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"Rotate Controller Z*", motionControl.rotateControllerCustom.z, val => motionControl.rotateControllerCustom = new Vector3(motionControl.rotateControllerCustom.x, motionControl.rotateControllerCustom.y, val), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"Rotate Around Tracker X*", motionControl.rotateAroundTrackerCustom.x, val => motionControl.rotateAroundTrackerCustom = new Vector3(val, motionControl.rotateAroundTrackerCustom.y, motionControl.rotateAroundTrackerCustom.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"Rotate Around Tracker Y*", motionControl.rotateAroundTrackerCustom.y, val => motionControl.rotateAroundTrackerCustom = new Vector3(motionControl.rotateAroundTrackerCustom.x, val, motionControl.rotateAroundTrackerCustom.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"Rotate Around Tracker Z*", motionControl.rotateAroundTrackerCustom.z, val => motionControl.rotateAroundTrackerCustom = new Vector3(motionControl.rotateAroundTrackerCustom.x, motionControl.rotateAroundTrackerCustom.y, val), -180, 180, false), false); _section.CreateToggle(new JSONStorableBool( "Keep current physics hold strength*", motionControl.keepCurrentPhysicsHoldStrength, val => motionControl.keepCurrentPhysicsHoldStrength = val), false); if (MotionControlNames.IsHands(motionControl.name)) { _section.CreateButton("Sync to other hand").button.onClick.AddListener(() => { var otherHand = motionControl.name == MotionControlNames.LeftHand ? _trackers.rightHandMotionControl : _trackers.leftHandMotionControl; otherHand.offsetControllerCustom = new Vector3(-motionControl.offsetControllerCustom.x, motionControl.offsetControllerCustom.y, motionControl.offsetControllerCustom.z); otherHand.rotateControllerCustom = new Vector3(motionControl.rotateControllerCustom.x, -motionControl.rotateControllerCustom.y, -motionControl.rotateControllerCustom.z); otherHand.rotateAroundTrackerCustom = new Vector3(motionControl.rotateAroundTrackerCustom.x, -motionControl.rotateAroundTrackerCustom.y, -motionControl.rotateAroundTrackerCustom.z); }); } }
private void ShowMotionControl(MotionControllerWithCustomPossessPoint motionControl) { if (_section == null) { _section = CreateSection(); } _section.RemoveAll(); if (motionControl == null) { return; } _section.CreateToggle(new JSONStorableBool( $"{motionControl.name} Enabled", motionControl.enabled, val => { motionControl.enabled = val; context.Refresh(); } )); _section.CreateFilterablePopup(new JSONStorableStringChooser( "", new[] { _none }.Concat(_trackers.controllers.Select(mc => mc.controller.name)).ToList(), motionControl.mappedControllerName, "Map to control", val => { motionControl.mappedControllerName = val == _none ? null : val; context.Refresh(); }), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Offset X", motionControl.customOffset.x, val => motionControl.customOffset = new Vector3(val, motionControl.customOffset.y, motionControl.customOffset.z), -0.5f, 0.5f, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Offset Y", motionControl.customOffset.y, val => motionControl.customOffset = new Vector3(motionControl.customOffset.x, val, motionControl.customOffset.z), -0.5f, 0.5f, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Offset Z", motionControl.customOffset.z, val => motionControl.customOffset = new Vector3(motionControl.customOffset.x, motionControl.customOffset.y, val), -0.5f, 0.5f, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Offset rotate X", motionControl.customOffsetRotation.x, val => motionControl.customOffsetRotation = new Vector3(val, motionControl.customOffsetRotation.y, motionControl.customOffsetRotation.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Offset rotate Y", motionControl.customOffsetRotation.y, val => motionControl.customOffsetRotation = new Vector3(motionControl.customOffsetRotation.x, val, motionControl.customOffsetRotation.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Offset rotate Z", motionControl.customOffsetRotation.z, val => motionControl.customOffsetRotation = new Vector3(motionControl.customOffsetRotation.x, motionControl.customOffsetRotation.y, val), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Point rotate X", motionControl.possessPointRotation.x, val => motionControl.possessPointRotation = new Vector3(val, motionControl.possessPointRotation.y, motionControl.possessPointRotation.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Point rotate Y", motionControl.possessPointRotation.y, val => motionControl.possessPointRotation = new Vector3(motionControl.possessPointRotation.x, val, motionControl.possessPointRotation.z), -180, 180, false), false); _section.CreateSlider(new JSONStorableFloat( $"{motionControl.name} Point rotate Z", motionControl.possessPointRotation.z, val => motionControl.possessPointRotation = new Vector3(motionControl.possessPointRotation.x, motionControl.possessPointRotation.y, val), -180, 180, false), false); _section.CreateButton("Attach and align to closest node", true).button.onClick.AddListener(() => { AttachToClosestNode(motionControl); }); }