/// <summary> /// Add a new attachment point to the pending list to be processed when the system is ready. /// </summary> /// <param name="attachPoint">Attachment point to process later.</param> /// <param name="context">Optional spawning attachment point, may be null.</param> private void AddPendingAttachmentPoint(AttachmentPoint attachPoint, IAttachmentPoint context) { // Flag as being in an invalid state attachPoint.HandleStateChange(AttachmentPointStateType.Pending); pendingAttachments.Add( new PendingAttachmentPoint { target = attachPoint, context = context } ); }
/// <summary> /// Add an existing attachment point to this fragment. /// </summary> /// <remarks> /// The attachment point might currently belong to another fragment, if /// it is being moved from the other to this. /// Since this is only used internally, it operates directly on an AttachmentPoint /// rather than an interface to avoid an unnecessary downcast. /// </remarks> /// <param name="attachPoint"></param> public void AddAttachmentPoint(AttachmentPoint attachPoint) { if (attachPoint != null) { if (attachPoint.StateHandler != null) { updateStateAllAttachments += attachPoint.StateHandler; } attachPoint.HandleStateChange(State); attachmentList.Add(attachPoint); } }
/// <summary> /// Absorb the contents of another fragment, emptying it. /// </summary> /// <param name="other">The fragment to lose all its contents to this.</param> public void AbsorbOtherFragment(Fragment other) { Debug.Assert(other != this, $"Trying to merge to and from the same fragment {FragmentId}"); int otherCount = other.attachmentList.Count; for (int i = 0; i < otherCount; ++i) { AttachmentPoint att = other.attachmentList[i]; att.Set(FragmentId, att.CachedPosition, att.AnchorId, att.LocationFromAnchor); if (att.StateHandler != null) { updateStateAllAttachments += att.StateHandler; } att.HandleStateChange(State); attachmentList.Add(att); } other.ReleaseAll(); }
/// <summary> /// Notify system attachment point is no longer needed. See <see cref="IAttachmentPointManager.ReleaseAttachmentPoint"/> /// </summary> /// <param name="attachmentPoint"></param> public void ReleaseAttachmentPoint(IAttachmentPoint attachmentPoint) { AttachmentPoint attachPoint = attachmentPoint as AttachmentPoint; if (attachPoint != null) { if (attachPoint.StateHandler != null) { updateStateAllAttachments -= attachPoint.StateHandler; } attachPoint.HandleStateChange(AttachmentPointStateType.Released); attachmentList.Remove(attachPoint); } else { Debug.LogError("On release, IAttachmentPoint isn't AttachmentPoint"); } }
/// <summary> /// Release an attachment point for disposal. The attachment point is no longer valid after this call. /// </summary> /// <remarks> /// In the unlikely circumstance that another attachment point has been spawned from this one /// but has not yet been processed (is still in the pending queue), /// that relationship is broken on release of this one, and when the other attachment point is /// finally processed, it will be as if it was created with a null context. /// </remarks> /// <param name="attachPointIface">The attachment point to release.</param> public void ReleaseAttachmentPoint(IAttachmentPoint attachPointIface) { AttachmentPoint attachPoint = attachPointIface as AttachmentPoint; if (attachPoint != null) { Fragment fragment = EnsureFragment(attachPoint.FragmentId); if (fragment != null) { // Fragment handles notification. fragment.ReleaseAttachmentPoint(attachPoint); } else { // Notify of the state change to released. attachPoint.HandleStateChange(AttachmentPointStateType.Released); // The list of pending attachments is expected to be small, and release of an attachment // point while there are pending attachments is expected to be rare. So brute force it here. // If the attachment point being released is a target in the pending list, remove it. // If it is the context of another pending target, set that context to null. // Proceed through the list in reverse order, because context fixes will only be found // later in the list than the original, and once the original is found we are done. int pendingCount = pendingAttachments.Count; for (int i = pendingCount - 1; i >= 0; --i) { if (pendingAttachments[i].context == attachPoint) { var p = pendingAttachments[i]; p.context = null; pendingAttachments[i] = p; } else if (pendingAttachments[i].target == attachPoint) { pendingAttachments.RemoveAt(i); break; } } } } }