/// <summary> /// Called when the <see cref="Children"/> collection was changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="eventArgs"> /// The <see cref="CollectionChangedEventArgs{IGeometricObject}"/> instance containing the event /// data. /// </param> private void OnChildrenChanged(object sender, CollectionChangedEventArgs <IGeometricObject> eventArgs) { if (eventArgs.Action == CollectionChangedAction.Move) { return; } // Handle removed items. var oldItems = eventArgs.OldItems; int numberOfOldItems = oldItems.Count; for (int i = 0; i < numberOfOldItems; i++) { var geometricObject = oldItems[i]; geometricObject.PoseChanged -= OnChildShapeChanged; geometricObject.ShapeChanged -= OnChildShapeChanged; } // Handle new items. var newItems = eventArgs.NewItems; int numberOfNewItems = newItems.Count; for (int i = 0; i < numberOfNewItems; i++) { var geometricObject = newItems[i]; geometricObject.PoseChanged += OnChildShapeChanged; geometricObject.ShapeChanged += OnChildShapeChanged; } // Rebuild spatial partition. if (_partition != null) { _partition.Clear(); int numberOfChildren = Children.Count; for (int i = 0; i < numberOfChildren; i++) { _partition.Add(i); } } if (numberOfOldItems == 1 && numberOfNewItems == 1 && eventArgs.OldItemsIndex == eventArgs.NewItemsIndex) { // Exactly one item was replaced. // --> Set the feature index of the item in the event args. var shapeChangedEventArgs = ShapeChangedEventArgs.Create(eventArgs.OldItemsIndex); OnChanged(shapeChangedEventArgs); shapeChangedEventArgs.Recycle(); } else { // Multiple items added or removed. The indices of multiple items have changed. // --> Do not set a feature index. Use the default. OnChanged(ShapeChangedEventArgs.Empty); } }
/// <inheritdoc/> protected override void OnChanged(ShapeChangedEventArgs eventArgs) { // Set cached AABB to "invalid". _aabbLocal = new Aabb(new Vector3(float.NaN), new Vector3(float.NaN)); _innerPoint = new Vector3(float.NaN); base.OnChanged(eventArgs); }
/// <summary> /// Raises the <see cref="Shape.Changed"/> event. /// </summary> /// <param name="eventArgs"> /// <see cref="ShapeChangedEventArgs"/> object that provides the arguments for the event. /// </param> /// <remarks> /// <strong>Notes to Inheritors:</strong> When overriding <see cref="OnChanged"/> in a derived /// class, be sure to call the base class's <see cref="OnChanged"/> method so that registered /// delegates receive the event. /// </remarks> protected virtual void OnChanged(ShapeChangedEventArgs eventArgs) { var handler = _changed; if (handler != null) { handler(this, eventArgs); } }
private void OnChildShapeChanged(object sender, ShapeChangedEventArgs eventArgs) { IGeometricObject geometricObject = (IGeometricObject)sender; if (geometricObject.Shape is ConvexShape == false) { throw new GeometryException("The child objects in a ConvexHullOfShapes must have ConvexShapes."); } OnChanged(ShapeChangedEventArgs.Empty); }
/// <summary> /// Invalidates the whole triangle mesh or a single triangle. /// </summary> /// <param name="triangleIndex"> /// Index of the triangle. Can be -1 to invalidate the whole mesh. /// </param> /// <param name="invalidateTopology"> /// If set to <see langword="true"/> the mesh topology is invalidated. /// </param> /// <remarks> /// <para> /// This method must be called if the position of a triangle stored in <see cref="Mesh"/> is /// changed. This method updates the <see cref="Partition"/> and raises the /// <see cref="Shape.Changed"/> event by calling <see cref="Shape.OnChanged"/>. /// </para> /// <para> /// If the mesh topology has changed, <paramref name="invalidateTopology"/> must be set to /// <see langword="true"/>. The topology has changed if triangle neighbor relationships have /// changed. If each triangle has the same neighbor triangles as before and only the vertices /// were moved, <paramref name="invalidateTopology"/> can be <see langword="false"/>. /// </para> /// </remarks> /// <exception cref="ArgumentOutOfRangeException"> /// <paramref name="triangleIndex"/> is out of range. /// </exception> public void Invalidate(int triangleIndex, bool invalidateTopology) { int numberOfTriangles = Mesh.NumberOfTriangles; if (triangleIndex >= numberOfTriangles) { throw new ArgumentOutOfRangeException("triangleIndex"); } // Set cached AABB to "invalid". _aabbLocal = new Aabb(new Vector3(float.NaN), new Vector3(float.NaN)); // Fill new spatial partition. if (_partition != null) { if (numberOfTriangles != _partition.Count) { // Triangle count has changed. Re-initialize partition content. _partition.Clear(); for (int i = 0; i < numberOfTriangles; i++) { _partition.Add(i); } } else { // Same number of triangles - invalidate the triangle. if (triangleIndex >= 0) { _partition.Invalidate(triangleIndex); } else { _partition.Invalidate(); } } } if (invalidateTopology) { ComputeTriangleNeighbors(); } if (triangleIndex < 0) { OnChanged(ShapeChangedEventArgs.Empty); } else { var eventArgs = ShapeChangedEventArgs.Create(triangleIndex); OnChanged(eventArgs); eventArgs.Recycle(); } }
/// <inheritdoc/> protected override void OnChanged(ShapeChangedEventArgs eventArgs) { // Set cached AABB to "invalid". _minHeight = float.NaN; _maxHeight = float.NaN; // Cached normals are also invalid. //NormalArray = null; base.OnChanged(eventArgs); }
/// <summary> /// Called when a child object was changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="eventArgs"> /// The <see cref="EventArgs"/> instance containing the event data. /// </param> private void OnChildShapeChanged(object sender, EventArgs eventArgs) { // Invalidate partition. var index = Children.IndexOf(sender as IGeometricObject); if (Partition != null) { if (index >= 0) { Partition.Invalidate(index); } else { Partition.Invalidate(); } } var shapeChangedEventArgs = ShapeChangedEventArgs.Create(index); OnChanged(shapeChangedEventArgs); shapeChangedEventArgs.Recycle(); }
/// <summary> /// Called when child shape was changed. /// </summary> /// <param name="sender">The sender.</param> /// <param name="eventArgs"> /// The <see cref="ShapeChangedEventArgs"/> instance containing the event data. /// </param> private void OnChildShapeChanged(object sender, ShapeChangedEventArgs eventArgs) { CheckShapes(); OnChanged(eventArgs); }