// todo: implement mouse-in / mouse-out interaction events instead public override void OnRoutedEvent(IRoutedEvent evnt) { if (!(evnt is IMouseEvent mevent)) { return; } var layer = mevent.Viewport.View.Layers.FirstOrDefault(x => x.VisibleScene == Node.Scene); if (layer == null) { return; } var rayHitInfo = new RayCastInfo(mevent.Viewport, layer, mevent.State.Position); var isMouseOver = Node.SearchComponents <IRayHittableComponent>() .Any(x => x.HitWithClick(rayHitInfo).Successful); if (!wasMouseOver && isMouseOver) { highlightOnMouseService.OnObjectIn(this, GroupName); } else if (wasMouseOver && !isMouseOver) { highlightOnMouseService.OnObjectOut(this, GroupName); } wasMouseOver = isMouseOver; }
public void Init(BoxCollider2D collider2D) { col = collider2D; points = new RayCastPoint( ); info = new RayCastInfo( ); result = new List <HitResult> ( ); CalculateSpace( ); }
public RayHitResult HitWithClick(RayCastInfo clickInfo) { var globalRay = clickInfo.GlobalRay; var sphere = getSphere(master); var segmentLength = (sphere.Center - globalRay.Point).Length() * 3; var segment = new LineSegment3(globalRay.Point, globalRay.Point + globalRay.Direction * segmentLength); sphere.Intersect(segment, out var p1, out var p2); if (!p1.HasValue) { return(RayHitResult.Failure()); } var d1 = (p1.Value - globalRay.Point).Length(); Vector3 globalPoint; float distance; if (p2.HasValue) { var d2 = (p2.Value - globalRay.Point).Length(); var use1 = (d1 <= d2) ^ inverted; if (use1) { globalPoint = p1.Value; distance = d1; } else { globalPoint = p2.Value; distance = d2; } } else { globalPoint = p1.Value; distance = d1; } // todo: consider rotation var localPoint = (globalPoint - sphere.Center) / sphere.Radius; return(new RayHitResult { Successful = true, Node = Node, Distance = distance, GlobalHitPoint = globalPoint, LocalHitPoint = localPoint, IntTag = intTag, StrTag = strTag }); }
public RayHitResult HitWithClick(RayCastInfo clickInfo) { var hitResult = hittable.HitWithClick(clickInfo); var cRect = GetRectComponent(); // todo: make overridable and override in more specific components if (cRect.DragByBorders && (1 - hitResult.LocalHitPoint.X.Abs()) * cRect.Rectangle.HalfWidth * RichTextBox.DefaultPixelScaling > RichTextBox.DraggablePaddingInPixels && (1 - hitResult.LocalHitPoint.Y.Abs()) * cRect.Rectangle.HalfHeight * RichTextBox.DefaultPixelScaling > RichTextBox.DraggablePaddingInPixels) { return(RayHitResult.Failure()); } return(hitResult); }
void DrawRaycast() { int rayCount = meshResolution; float rayAngleSize = lightAngle / (rayCount); List <Vector3> rayPoints = new List <Vector3>(); for (int i = 0; i <= rayCount; i++) { float angle = transform.eulerAngles.z - lightAngle / 2 + rayAngleSize * i; Debug.DrawLine(transform.position, transform.position + DirFromAngle(angle, true) * lightRadius, Color.red); RayCastInfo newRayCastInfo = RayCasting(angle); rayPoints.Add(newRayCastInfo.point); } int vertexCount = rayPoints.Count + 1; Vector3[] vertices = new Vector3[vertexCount + 1]; int[] triangles = new int[(vertexCount - 2) * 3]; print("vertex count " + vertexCount); print("ray point " + rayPoints.Count); print("vertices count" + vertices.Length); vertices[0] = Vector3.zero; for (int i = 0; i < vertexCount - 1; i++) { vertices[i + 1] = transform.InverseTransformPoint(rayPoints[i]); if (i < vertexCount - 2) { triangles[i * 3] = 0; triangles[i * 3 + 1] = i + 1; triangles[i * 3 + 2] = i + 2; } } viewMesh.Clear(); viewMesh.vertices = vertices; viewMesh.triangles = triangles; viewMesh.RecalculateNormals(); }
/* * ============================================================================ * FindEdge() * Iteratively looks for the edge of an obstacle. THe higher the * edgeIterations, the more refined we can make that edge. Takes two * RayCastInfo parameters as the minimum and maximum of the ray cast. * The function works by egetting the two ray casts where one is a hit and * the other is a miss, creating a new ray cast down the middle and then * repeating between a higt and a missd cast until the threshold or * iterations limit is reached. * ============================================================================ */ private EdgeInfo FindEdge(RayCastInfo minRayCast, RayCastInfo maxRayCast) { float minAngle = minRayCast.angle; float maxAngle = maxRayCast.angle; Vector3 minPoint = Vector3.zero; Vector3 maxPoint = Vector3.zero; RayCastInfo newRayCast = new RayCastInfo(); for (int i = 0; i < edgeIterations; i++) { float angle = (minAngle + maxAngle) / 2; newRayCast = RayCast(angle); bool edgeDistThresholExeeded = Mathf.Abs(minRayCast.dist - newRayCast.dist) > edgeDistThreshold; if (newRayCast.hit == minRayCast.hit && !edgeDistThresholExeeded) { // Replace the minimum with the new ray cast we have created minAngle = angle; minPoint = newRayCast.point; } else { // Replace the max as the new ray ast we have created maxAngle = angle; maxPoint = newRayCast.point; } } Debug.DrawLine(transform.position, minPoint, Color.blue); Debug.DrawLine(transform.position, maxPoint, Color.blue); if (newRayCast.hit && Mathf.Round(newRayCast.dist) < MaxRange) { EdgePoints.Add(minPoint); } else if (!newRayCast.hit && Mathf.Round(newRayCast.dist) < MaxRange) { EdgePoints.Add(maxPoint); } return(new EdgeInfo(minPoint, maxPoint)); }
public RayHitResult HitWithClick(RayCastInfo clickInfo) { var globalRay = clickInfo.GlobalRay; var globalTransformInverse = (planeTransform * Node.GlobalTransform).Invert(); var localRay = globalRay * globalTransformInverse; var t = -localRay.Point.Z / localRay.Direction.Z; if (t <= 0f) { return(RayHitResult.Failure()); } var point = localRay.Point + localRay.Direction * t; var rectangle = getLocalRectangle(master); if (!rectangle.ContainsPoint(point.Xy)) { return(RayHitResult.Failure()); } var globalT = t / globalTransformInverse.Scale; var offset = getHitDistanceOffset(master); var globalPoint = globalRay.Point + globalRay.Direction * globalT; var localPoint = new Vector3( (point.X - rectangle.Center.X) / rectangle.HalfWidth, (point.Y - rectangle.Center.Y) / rectangle.HalfHeight, 0); return(new RayHitResult { Successful = true, Node = Node, Distance = globalT + offset, GlobalHitPoint = globalPoint, LocalHitPoint = localPoint, IntTag = intTag, StrTag = strTag }); }
public bool TryHandleInputEvent(IInputEvent eventArgs) { if (!(eventArgs is MouseEvent args)) { return(false); } if (!args.IsLeftClickEvent()) { return(false); } var clickInfo = new RayCastInfo(args.Viewport, args.Viewport.View.Layers.Single(), args.State.Position); var hitResult = rayHitIndex.CastRay(clickInfo).FirstOrNull() ?? RayHitResult.Failure(); if (hitResult.Successful) { int?to = null; var gizmoComponentTo = hitResult.Node.GetComponent <StoryFlowchartNodeGizmoComponent>(); if (gizmoComponentTo != null && gizmoComponentTo.ReferencedNode.Id != from) { to = gizmoComponentTo.ReferencedNode.Id; } if (storyService.GlobalGraph.NodeIds.Contains(hitResult.Node.Id)) { to = hitResult.Node.Id; } if (to.HasValue) { var child = StoryOperations.AddChild(storyService, commonNodeFactory, to.Value, this); storyService.AddEdge(from, child.Id); toolService.CurrentTool = null; return(true); } } toolService.CurrentTool = null; return(false); }
public RayHitResult HitWithClick(RayCastInfo clickInfo) { var globalRay = clickInfo.GlobalRay; var globalTransformInverse = (planeTransform * Node.GlobalTransform).Invert(); var localRay = globalRay * globalTransformInverse; var t = -localRay.Point.Z / localRay.Direction.Z; if (t <= 0f) { return(RayHitResult.Failure()); } var point = localRay.Point + localRay.Direction * t; var cirlce = getLocalCirlce(master); if (!cirlce.Contains(point.Xy)) { return(RayHitResult.Failure()); } var globalT = t / globalTransformInverse.Scale; var offset = getHitDistanceOffset(master); var globalPoint = globalRay.Point + globalRay.Direction * globalT; // todo: consider rotation var localPoint = new Vector3(point.Xy - cirlce.Center, 0) / cirlce.Radius; return(new RayHitResult { Successful = true, Node = Node, Distance = globalT + offset, GlobalHitPoint = globalPoint, LocalHitPoint = localPoint, IntTag = intTag, StrTag = strTag }); }
public RayHitResult HitWithClick(RayCastInfo clickInfo) { // todo: calculate in screen space? var line = getLine(master); var mouseLine = clickInfo.GlobalRay.ToLine(); Line3.GetClosestPoints(line, mouseLine, out var p1, out var p2); var grad = clickInfo.GetAbsPixelGradientAt((p1 + p2) / 2); var diff = (p2 - p1).Abs(); var pixelDiff = Vector3.Dot(diff, grad); return(pixelDiff <= lineWidth ? new RayHitResult { Successful = true, Node = Node, Distance = (clickInfo.GlobalRay.Point - p1).Length(), GlobalHitPoint = p1, LocalHitPoint = p1, IntTag = intTag, StrTag = strTag } : RayHitResult.Failure()); }
// Hittable public RayHitResult HitWithClick(RayCastInfo clickInfo) => hittable.HitWithClick(clickInfo);
public RayHitResult HitWithClick(RayCastInfo clickInfo) => RayHitResult.Failure();
// Hittable public RayHitResult HitWithClick(RayCastInfo clickInfo) => hittable?.HitWithClick(clickInfo) ?? RayHitResult.Failure();
/* * ================================ * DrawRange() * This is the main function for the LIDAR where the LOS circle is drawn * and it calls the other functions to ascertain the raycasts. * ================================ */ void DrawRange() { EdgePoints.Clear(); int stepCount = Mathf.RoundToInt(ScanAngle * (1.0f / ScanResolution)); float stepAngleSize = ScanAngle / stepCount; List <Vector3> scanPoints = new List <Vector3>(); RayCastInfo oldRayCast = new RayCastInfo(); for (int i = 0; i <= stepCount; i++) { float angle = transform.eulerAngles.y - ScanAngle / 2 + stepAngleSize * i; RayCastInfo newRayCast = RayCast(angle); if (i > 0) { bool edgeDistThresholExeeded = Mathf.Abs(oldRayCast.dist - newRayCast.dist) > edgeDistThreshold; if (oldRayCast.hit != newRayCast.hit || (oldRayCast.hit && newRayCast.hit && edgeDistThresholExeeded)) { // Find the edgeb etween the two raycasts EdgeInfo edge = FindEdge(oldRayCast, newRayCast); if (edge.pointA != Vector3.zero) { scanPoints.Add(edge.pointA); if (Mathf.Round(Vector3.Distance(transform.position, edge.pointA)) < MaxRange) { EdgePoints.Add(edge.pointA); } } if (edge.pointB != Vector3.zero) { scanPoints.Add(edge.pointB); if (Mathf.Round(Vector3.Distance(transform.position, edge.pointB)) < MaxRange) { EdgePoints.Add(edge.pointB); } } } } } // End for // Start setting up the mesh int vCount = scanPoints.Count + 1; // How many vertices? Points + origin Vector3[] vertices = new Vector3[vCount]; // Create vertices array from the prev. calc int[] triangles = new int[(vCount - 2) * 3]; // Triangles have 3 points each vertices[0] = Vector3.zero; // Set origin as 0 for (int i = 0; i < vCount - 1; i++) { vertices[i + 1] = transform.InverseTransformPoint(scanPoints[i]) + Vector3.forward; if (i < vCount - 2) { triangles[i * 3] = 0; // Firstr triangle point is origin triangles[i * 3 + 1] = i + 1; // goes clockwise triangles[i * 3 + 2] = i + 2; // ... } } // Draw the mesh ScanMesh.Clear(); ScanMesh.vertices = vertices; ScanMesh.triangles = triangles; ScanMesh.RecalculateNormals(); }
public RayHitResult HitWithClick(RayCastInfo clickInfo) { return(hittable.HitWithClick(clickInfo)); }
private void OnEvent(IInteractionEvent interactionEvent) { if (!(interactionEvent is IInputEvent inputEvent)) { return; } locksToRelease.Clear(); foreach (var inputLock in inputLocks) { var result = inputLock.ProcessEvent(inputEvent); if ((result & InputEventProcessResult.StopPropagating) != 0) { return; } if ((result & InputEventProcessResult.ReleaseLock) != 0) { locksToRelease.Add(inputLock); } } foreach (var inputLock in locksToRelease) { inputLocks.Remove(inputLock); } if (toolService.CurrentTool != null) { var tool = toolService.CurrentTool; if (tool.TryHandleInputEvent(inputEvent)) { return; } } if (dirtyHackServiceLazy.Value.TryHandleInput(inputEvent)) { return; } //if (abstractArgs is IMouseEventArgs mouseArgs) // OnMouseEvent(mouseArgs); //else if (abstractArgs is IKeyEventArgs keyboardArgs) // OnKeyEvent(keyboardArgs); // todo: return if handled if (inputEvent.Viewport?.View.TryHandleInput(inputEvent) ?? false) { return; } if (inputEvent.Viewport != null && inputEvent is IMouseEvent margs) { var hitSomething = false; foreach (var layer in inputEvent.Viewport.View.Layers) { var clickInfo = new RayCastInfo(margs.Viewport, layer, margs.State.Position); var hitResults = rayHitIndex.CastRay(clickInfo); // todo: introduce different levels of stopping propagation and remove '.Take(1)' foreach (var hitResult in hitResults.Take(1)) { hitSomething = true; margs.RayHitResult = hitResult; foreach (var interactionElement in hitResult.Node.SearchComponents <IInteractionComponent>()) { if (interactionElement.TryHandleInteractionEvent(margs)) { return; } } } margs.RayHitResult = null; if (layer.Camera is IControlledCamera controlledCamera && controlledCamera.TryHandleInput(inputEvent)) { return; } } if (margs.IsLeftClickEvent() && margs.KeyModifiers == KeyModifiers.None && !hitSomething) { viewService.SelectedNode = null; } } if (inputEvent is IKeyEvent kargs && viewService.SelectedNode != null) { foreach (var interactionElement in viewService.SelectedNode.Node.SearchComponents <IInteractionComponent>()) { if (interactionElement.TryHandleInteractionEvent(kargs)) { return; } } } navigationService.TryHandleInput(inputEvent); }