/// <summary> /// Compiles an enumeration of DomNode properties (as objects) that matched the conditions of the search predicates</summary> /// <param name="predicate">Specifies the test conditions for a query</param> /// <returns>The enumeration of DomNode properties (e.g., DomNodeQueryMatch) satisfying the query</returns> public IEnumerable <object> Query(IQueryPredicate predicate) { m_results.Clear(); // Iterate over all dom nodes under this adapter foreach (DomNode domNode in DomNode.Subtree) { // The results of one DomNode query associate each predicate with matching dom node properties Dictionary <IQueryPredicate, IList <IQueryMatch> > predicateMatchResults = new Dictionary <IQueryPredicate, IList <IQueryMatch> >(); // For each queryable item (ie a DomNode) there may be 0 to many "query matches" // (ie a DomNode property). On success, predicate.Test() will supply one // IQueryMatch per DomNode property that matched. IList <IQueryMatch> matchingPropertiesList; if (predicate.Test(domNode, out matchingPropertiesList)) { if (matchingPropertiesList != null) { predicateMatchResults[predicate] = matchingPropertiesList; } // For this queryable, a match is the DomNode that passed the predicate test, // paired with all its properties that allowed it to satisfy the test m_results.Add(new DomNodeQueryMatch(domNode, predicateMatchResults)); } } // Announce that the search results have changed ResultsChanged.Raise(this, EventArgs.Empty); return(m_results); }
/// <inheritdoc /> public override void CastPoints() { if (!isActiveAndEnabled) { return; } Ray ray = new Ray(transform.position, transform.forward); RaycastHit hitData; bool hasCollided = PhysicsCast.Raycast(physicsCast, ray, out hitData, maximumLength, Physics.IgnoreRaycastLayer); TargetHit = (hasCollided ? hitData : (RaycastHit?)null); points[0] = transform.position; points[1] = (hasCollided ? hitData.point : transform.position + transform.forward * maximumLength); ResultsChanged?.Invoke(eventData.Set(TargetHit, Points)); }
/// <summary> /// Checks for collisions along the parabolic line segments and generates the final points. /// </summary> /// <param name="forward">The forward direction to use for the checks.</param> /// <param name="down">The downwards direction to use for the checks.</param> protected virtual void GeneratePointsIncludingSegments(Vector3 forward, Vector3 down) { GeneratePoints(forward, down); collisionCheckFrequency = Mathf.Clamp(collisionCheckFrequency, 0, segmentCount); int step = segmentCount / (collisionCheckFrequency > 0 ? collisionCheckFrequency : 1); for (int index = 0; index < segmentCount - step; index += step) { Vector3 currentPoint = points[index]; Vector3 nextPoint = index + step < points.Count ? points[index + step] : points[points.Count - 1]; Vector3 nextPointDirection = (nextPoint - currentPoint).normalized; float nextPointDistance = Vector3.Distance(currentPoint, nextPoint); Ray pointsRay = new Ray(currentPoint, nextPointDirection); RaycastHit pointsHitData; if (!PhysicsCast.Raycast(physicsCast, pointsRay, out pointsHitData, nextPointDistance, Physics.IgnoreRaycastLayer)) { continue; } Vector3 collisionPoint = pointsRay.GetPoint(pointsHitData.distance); Ray downwardRay = new Ray(collisionPoint + Vector3.up * 0.01f, Vector3.down); RaycastHit downwardHitData; if (!PhysicsCast.Raycast(physicsCast, downwardRay, out downwardHitData, float.PositiveInfinity, Physics.IgnoreRaycastLayer)) { continue; } TargetHit = downwardHitData; Vector3 newDownPosition = downwardRay.GetPoint(downwardHitData.distance); Vector3 newJointPosition = newDownPosition.y < forward.y ? new Vector3(newDownPosition.x, forward.y, newDownPosition.z) : forward; GeneratePoints(newJointPosition, newDownPosition); break; } ResultsChanged?.Invoke(eventData.Set(TargetHit, Points)); }
/// <inheritdoc /> protected override void DoCastPoints() { GeneratePoints(); ResultsChanged?.Invoke(eventData.Set(TargetHit, Points)); }
/// <summary> /// Applies a replacement on the results of the last Query</summary> /// <param name="replaceInfo">Replacement information</param> /// <returns>The list of objects on which we just performed a replacement</returns> public IEnumerable <object> Replace(object replaceInfo) { ITransactionContext currentTransaction = null; try { foreach (DomNodeQueryMatch match in m_results) { DomNode domNode = match.DomNode; // Set up undo/redo for the replacement operation ITransactionContext newTransaction = domNode != null?domNode.GetRoot().As <ITransactionContext>() : null; if (newTransaction != currentTransaction) { { if (currentTransaction != null) { currentTransaction.End(); } currentTransaction = newTransaction; if (currentTransaction != null) { currentTransaction.Begin("Replace".Localize()); } } } // Apply replacement to all matching items that were found on last search foreach (IQueryPredicate predicateInfo in match.PredicateMatchResults.Keys) { predicateInfo.Replace(match.PredicateMatchResults[predicateInfo], replaceInfo); } } } catch (InvalidTransactionException ex) { // cancel the replacement transaction in the undo/redo queue if (currentTransaction != null && currentTransaction.InTransaction) { currentTransaction.Cancel(); } if (ex.ReportError) { Outputs.WriteLine(OutputMessageType.Error, ex.Message); } } finally { // finish the replacement transaction for the undo/redo queue if (currentTransaction != null && currentTransaction.InTransaction) { currentTransaction.End(); } } ResultsChanged.Raise(this, EventArgs.Empty); return(m_results); }