public override void OverrideRayEndPoint(Ray ray, ref Vector3 rayEndPoint) { bool triggerJustClicked = false; bool triggerJustReleased = false; VRInput.GetInstantButtonEvent(VRInput.primaryController, CommonUsages.triggerButton, ref triggerJustClicked, ref triggerJustReleased); // Project ray on the widget plane. Plane widgetPlane = new Plane(-transform.forward, transform.position); float enter; widgetPlane.Raycast(ray, out enter); Vector3 worldCollisionOnWidgetPlane = ray.GetPoint(enter); Vector3 localWidgetPosition = transform.InverseTransformPoint(worldCollisionOnWidgetPlane); Vector3 localProjectedWidgetPosition = new Vector3(localWidgetPosition.x, localWidgetPosition.y, 0.0f); if (IgnoreRayInteraction()) { // return endPoint at the surface of the widget. rayEndPoint = transform.TransformPoint(localProjectedWidgetPosition); return; } float startX = 0; float endX = width; float startY = 0; float endY = -height; Vector2 currentKnobPosition = new Vector2(cursorPosition.x * width, (-1.0f + cursorPosition.y) * height); // DRAG if (!triggerJustClicked) // if trigger just clicked, use the actual projection, no interpolation. { localProjectedWidgetPosition.x = Mathf.Lerp(currentKnobPosition.x, localProjectedWidgetPosition.x, GlobalState.Settings.RaySliderDrag); localProjectedWidgetPosition.y = Mathf.Lerp(currentKnobPosition.y, localProjectedWidgetPosition.y, GlobalState.Settings.RaySliderDrag); } // CLAMP if (localProjectedWidgetPosition.x < startX) { localProjectedWidgetPosition.x = startX; } if (localProjectedWidgetPosition.x > endX) { localProjectedWidgetPosition.x = endX; } if (localProjectedWidgetPosition.y > startY) { localProjectedWidgetPosition.y = startY; } if (localProjectedWidgetPosition.y < endY) { localProjectedWidgetPosition.y = endY; } // SET float x = localProjectedWidgetPosition.x / width; float y = 1.0f - (-localProjectedWidgetPosition.y / height); x = Mathf.Clamp(x, 0, 1); y = Mathf.Clamp(y, 0, 1); SetSaturation(new Vector2(x, y)); colorPicker.OnColorChanged(); // Haptic intensity as we go deeper into the widget. //float intensity = Mathf.Clamp01(0.001f + 0.999f * localWidgetPosition.z / UIElement.collider_min_depth_deep); //intensity *= intensity; // ease-in //VRInput.SendHaptic(VRInput.rightController, 0.005f, intensity); Vector3 worldProjectedWidgetPosition = transform.TransformPoint(localProjectedWidgetPosition); //cursorShapeTransform.position = worldProjectedWidgetPosition; rayEndPoint = worldProjectedWidgetPosition; }
public override void OverrideRayEndPoint(Ray ray, ref Vector3 rayEndPoint) { bool triggerJustClicked = false; bool triggerJustReleased = false; VRInput.GetInstantButtonEvent(VRInput.primaryController, CommonUsages.triggerButton, ref triggerJustClicked, ref triggerJustReleased); // Project ray on the widget plane. Plane widgetPlane = new Plane(-transform.forward, transform.position); float enter; widgetPlane.Raycast(ray, out enter); Vector3 worldCollisionOnWidgetPlane = ray.GetPoint(enter); Vector3 localWidgetPosition = transform.InverseTransformPoint(worldCollisionOnWidgetPlane); Vector3 localProjectedWidgetPosition = new Vector3(localWidgetPosition.x, localWidgetPosition.y, 0.0f); if (IgnoreRayInteraction()) { // return endPoint at the surface of the widget. rayEndPoint = transform.TransformPoint(localProjectedWidgetPosition); return; } float startX = 0; float endX = width; float currentKnobPositionX = cursorPosition * width; // DRAG if (!triggerJustClicked) // if trigger just clicked, use the actual projection, no interpolation. { localProjectedWidgetPosition.x = Mathf.Lerp(currentKnobPositionX, localProjectedWidgetPosition.x, GlobalState.Settings.RaySliderDrag); } // CLAMP if (localProjectedWidgetPosition.x < startX) { localProjectedWidgetPosition.x = startX; } if (localProjectedWidgetPosition.x > endX) { localProjectedWidgetPosition.x = endX; } localProjectedWidgetPosition.y = -height / 2.0f; // SET float pct = localProjectedWidgetPosition.x / width; SetAlpha(Mathf.Clamp(pct, 0, 1)); colorPicker.OnColorChanged(); Vector3 worldProjectedWidgetPosition = transform.TransformPoint(localProjectedWidgetPosition); //cursorShapeTransform.position = worldProjectedWidgetPosition; rayEndPoint = worldProjectedWidgetPosition; }
public override void OverrideRayEndPoint(Ray ray, ref Vector3 rayEndPoint) { bool triggerJustClicked = false; bool triggerJustReleased = false; VRInput.GetInstantButtonEvent(VRInput.primaryController, CommonUsages.triggerButton, ref triggerJustClicked, ref triggerJustReleased); // Project ray on the widget plane. Plane widgetPlane = new Plane(-transform.forward, transform.position); float enter; widgetPlane.Raycast(ray, out enter); Vector3 worldCollisionOnWidgetPlane = ray.GetPoint(enter); Vector3 localWidgetPosition = transform.InverseTransformPoint(worldCollisionOnWidgetPlane); Vector3 localProjectedWidgetPosition = new Vector3(localWidgetPosition.x, localWidgetPosition.y, -thickness); if (IgnoreRayInteraction()) { // return endPoint at the surface of the widget. rayEndPoint = transform.TransformPoint(localProjectedWidgetPosition); return; } float w2 = width / 2.0f; float h2 = height / 2.0f; float ir = innerCirclePct * w2; // circle inner radius float or = outerCirclePct * w2; // circle outer radius float mr = (ir + or) / 2.0f; // circle middle radius float cw = (or - ir); // circle width float tr = trianglePct * w2; Vector2 circleCenter_L = new Vector2(w2, -h2); Vector2 cursor_L = new Vector2(localProjectedWidgetPosition.x, localProjectedWidgetPosition.y); // Just clicked, find out which subpart to lock on if (triggerJustClicked) { float cursorDistanceFromCenter = Vector2.Distance(cursor_L, circleCenter_L); if (cursorDistanceFromCenter >= ir && cursorDistanceFromCenter <= or) { lockedOnCircle = true; } else { // TODO: really check for triangle bounds, not only bounding circle. if (cursorDistanceFromCenter <= tr) { lockedOnTriangle = true; } } } if (lockedOnCircle) { Vector2 cursor_C = cursor_L - circleCenter_L; float angle = Mathf.Rad2Deg * (Mathf.PI - Mathf.Atan2(cursor_C.y, cursor_C.x)); float newHue = angle / 360.0f; // DRAG if (!triggerJustClicked) { float oldHue = hsv.x; if (newHue - oldHue < -0.5f) // ex: 0.9 -> 0.1 ==> 0.9 -> 1.1 { newHue = Mathf.Lerp(oldHue, newHue + 1.0f, GlobalState.Settings.RayHueDrag); if (newHue >= 1.0f) { newHue -= 1.0f; } } else if (newHue - oldHue > 0.5f) // ex: 0.1 -> 0.9 ==> 1.1 -> 0.9 { newHue = Mathf.Lerp(oldHue + 1.0f, newHue, GlobalState.Settings.RayHueDrag); if (newHue >= 1.0f) { newHue -= 1.0f; } } else // ex: 0.1 -> 0.2 { newHue = Mathf.Lerp(oldHue, newHue, GlobalState.Settings.RayHueDrag); } } HSV = new Vector3(newHue, hsv.y, hsv.z); // NOTE: also re-position the cursors. colorPicker.OnColorChanged(); localProjectedWidgetPosition = new Vector3( w2 + mr * -Mathf.Cos(hsv.x * 2.0f * Mathf.PI), -h2 + mr * Mathf.Sin(hsv.x * 2.0f * Mathf.PI), -thickness); } else if (lockedOnTriangle) { Vector3 closest; Vector3 baryOfClosest; ClosestPointToTriangle2D(localProjectedWidgetPosition, pt_A_HUE, pt_B_WHITE, pt_C_BLACK, out closest, out baryOfClosest); localProjectedWidgetPosition = new Vector3(closest.x, closest.y, -thickness); barycentric = baryOfClosest; // DRAG //if (!triggerJustClicked) //{ // localProjectedWidgetPosition = Vector3.Lerp(lastProjected, localProjectedWidgetPosition, GlobalState.Settings.RaySliderDrag); // barycentric = GetBarycentricCoordinates2D(localProjectedWidgetPosition, pt_A_HUE, pt_B_WHITE, pt_C_BLACK); //} //lastProjected = localProjectedWidgetPosition; //float H, S, V; //Color.RGBToHSV(BarycentricToRGB(), out H, out S, out V); //// TODO: make a function PointInTriangleToRGB(closest, a, b, c), using the resterizer algo to find color instead of barycentric. //hsv = new Vector3(hsv.x, S, V); Vector3 _sv = PointInTriangleToHSV(closest); hsv = new Vector3(hsv.x, _sv.y, _sv.z); UpdateCursorPositions(); colorPicker.OnColorChanged(); } Vector3 worldProjectedWidgetPosition = transform.TransformPoint(localProjectedWidgetPosition); rayEndPoint = worldProjectedWidgetPosition; }