Пример #1
0
        /// <summary>
        /// Teleport (as opposed to Move) means that the object is meant to have disappeared at its old position
        /// and instantaneously reappeared at its new position in frozen space without traversing the space in between.
        /// </summary>
        /// <remarks>
        /// This is equivalent to releasing the existing attachment point and creating a new one,
        /// except in that the attachment point reference remains valid.
        /// See <see cref="WorldLockingManager.TeleportAttachmentPoint"/>.
        /// </remarks>
        /// <param name="attachPointIface">The attachment point to teleport</param>
        /// <param name="newFrozenPosition">The position to teleport to.</param>
        /// <param name="context">The optional context.</param>
        public void TeleportAttachmentPoint(IAttachmentPoint attachPointIface, Vector3 newFrozenPosition, IAttachmentPoint context)
        {
            AttachmentPoint attachPoint = attachPointIface as AttachmentPoint;

            if (attachPoint != null)
            {
                attachPoint.ObjectPosition = newFrozenPosition;

                // Save the fragment it's currently in, in case it changes here.
                FragmentId oldFragmentId = attachPoint.FragmentId;

                // If it's not in a valid fragment, it is still pending and will get processed when the system is ready.
                if (oldFragmentId.IsKnown())
                {
                    FragmentId newFragmentId = GetTargetFragmentId(context);
                    // If there is a valid current fragment,
                    if (newFragmentId.IsKnown())
                    {
                        // Fill it in with a new one.
                        SetupAttachmentPoint(plugin, attachPoint, context);

                        if (attachPoint.FragmentId != oldFragmentId)
                        {
                            ChangeAttachmentPointFragment(oldFragmentId, attachPoint);
                        }
                    }
                    else
                    {
                        AddPendingAttachmentPoint(attachPoint, context);
                    }
                }
            }
        }
Пример #2
0
        /// <summary>
        /// If conditions have changed to allow finalizing creation of any pending attachment points,
        /// do it now.
        /// </summary>
        private void ProcessPendingAttachmentPoints()
        {
            if (CurrentFragmentId.IsKnown() && pendingAttachments.Count > 0)
            {
                // We have a valid destination fragment. Note that since this queue is in order of submission,
                // if an attachment point depends on a second attachment point for context,
                // that second will be either earlier in the list (because there was no valid current fragment when it was
                // created) or it will have a valid fragment. So by the time we get to the one with a dependency (pending.context != null),
                // its dependency will have a valid fragment id.
                int pendingCount = pendingAttachments.Count;
                for (int i = 0; i < pendingCount; ++i)
                {
                    AttachmentPoint  target         = pendingAttachments[i].target;
                    Vector3          frozenPosition = pendingAttachments[i].target.ObjectPosition;
                    IAttachmentPoint context        = pendingAttachments[i].context;

                    SetupAttachmentPoint(plugin, target, context);

                    FragmentId fragmentId = CurrentFragmentId;
                    if (context != null)
                    {
                        fragmentId = context.FragmentId;
                    }
                    Debug.Assert(fragmentId.IsKnown(), $"FragmentId {fragmentId.FormatStr()} invalid from {(context != null ? "context" : "head")} in processing pending");
                    Fragment fragment = EnsureFragment(fragmentId);
                    Debug.Assert(fragment != null, "Valid fragmentId but no fragment found");
                    fragment.AddAttachmentPoint(target);
                }
                // All pending must now be in a good home fragment, clear the to-do list.
                pendingAttachments.Clear();
            }
        }
 /// <summary>
 /// Release any resources bound to this reference point.
 /// </summary>
 public void Release()
 {
     if (attachmentPoint != null)
     {
         manager.AttachmentPointManager.ReleaseAttachmentPoint(attachmentPoint);
         attachmentPoint = null;
     }
 }
Пример #4
0
 /// <summary>
 /// Dispose of any previously created attachment point.
 /// </summary>
 protected void ReleaseAttachment()
 {
     if (attachmentPoint != null)
     {
         manager.AttachmentPointManager.ReleaseAttachmentPoint(attachmentPoint);
         attachmentPoint = null;
     }
 }
 /// <summary>
 /// Ask the manager for an attachment point, passing delegates for update
 /// </summary>
 private void Start()
 {
     AttachmentPoint = Manager.CreateAttachmentPoint(gameObject.transform.position, null,
                                                     HandleAdjustLocation, // Handle adjustments to position
                                                     HandleAdjustState     // Handle connectedness of fragment
                                                     );
     AttachmentPoint.Name = string.Format($"{gameObject.name}=>{AttachmentPoint.Name}");
 }
Пример #6
0
        /// <summary>
        /// Establish which fragment a new attachment point should join.
        /// </summary>
        /// <param name="context">Optional spawning attachment point. May be null to "spawn from head".</param>
        /// <returns>Id of fragment to join. May be FragmentId.Invalid if not currently tracking.</returns>
        private FragmentId GetTargetFragmentId(IAttachmentPoint context)
        {
            FragmentId fragmentId = CurrentFragmentId;

            if (context != null)
            {
                fragmentId = context.FragmentId;
            }
            return(fragmentId);
        }
Пример #7
0
 /// <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>
            /// When the reference point position is initially set, create an attachment point if there isn't one,
            /// or if there is, updated its position.
            /// </summary>
            private void CheckAttachmentPoint()
            {
                IAttachmentPointManager mgr = manager.AttachmentPointManager;

                if (attachmentPoint == null)
                {
                    attachmentPoint = mgr.CreateAttachmentPoint(LockedPose.position, null, OnLocationUpdate, null);
                }
                else
                {
                    mgr.TeleportAttachmentPoint(attachmentPoint, LockedPose.position, null);
                }
            }
Пример #9
0
        /// <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");
            }
        }
Пример #10
0
        /// <summary>
        /// Create and register a new attachment point.
        /// </summary>
        /// <remarks>
        /// The attachment point itself is a fairly opaque handle. Its effects are propagated to the client via the
        /// two handlers associated with it.
        /// The optional context attachment point provides an optional contextual hint to where in the anchor
        /// graph to bind the new attachment point.
        /// See <see cref="IAttachmentPointManager.CreateAttachmentPoint"/>.
        /// </remarks>
        /// <param name="frozenPosition">The position in the frozen space at which to start the attachment point</param>
        /// <param name="context">The optional context into which to create the attachment point (may be null)</param>
        /// <param name="locationHandler">Delegate to handle WorldLocking system adjustments to position</param>
        /// <param name="stateHandler">Delegate to handle WorldLocking connectivity changes</param>
        /// <returns>The new attachment point interface.</returns>
        public IAttachmentPoint CreateAttachmentPoint(Vector3 frozenPosition, IAttachmentPoint context,
                                                      AdjustLocationDelegate locationHandler, AdjustStateDelegate stateHandler)
        {
            FragmentId      fragmentId  = GetTargetFragmentId(context);
            AttachmentPoint attachPoint = new AttachmentPoint(locationHandler, stateHandler);

            attachPoint.ObjectPosition = frozenPosition;
            if (fragmentId.IsKnown())
            {
                SetupAttachmentPoint(plugin, attachPoint, context);

                Fragment fragment = EnsureFragment(fragmentId);
                Debug.Assert(fragment != null, "Valid fragmentId but no fragment found");
                fragment.AddAttachmentPoint(attachPoint);
            }
            else
            {
                AddPendingAttachmentPoint(attachPoint, context);
            }
            return(attachPoint);
        }
Пример #11
0
        /// <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;
                        }
                    }
                }
            }
        }
Пример #12
0
    public bool AttachTo(GameObject otherObject, IAttachmentPoint attachmentPoint)
    {
        // check for null pointers
        if (!otherObject)
        {
            return(false);
        }
        BlockController otherBlock = otherObject.GetComponent <BlockController>();

        if (!otherBlock)
        {
            return(false);
        }
        AttachmentPlug plug = attachmentPoint.GetGameObject().GetComponent <AttachmentPlug>();

        if (!plug)
        {
            return(false);
        }

        attachedTo = plug;
        DestroyRigidbody();
        EnableCollision();
        BlockController newRoot = null;

        if (otherBlock.rootBlock)
        {
            newRoot = otherBlock.rootBlock;
        }
        else
        {
            newRoot = otherBlock;
        }

        Reroot(newRoot);
        attached = true;
        return(true);
    }
Пример #13
0
        /// <summary>
        /// Move (as opposed to Teleport) means that the object is meant to have traversed
        /// flozen space from its old position to the given new position on some continuous path.
        /// </summary>
        /// <remarks>
        /// Not to be used for automatic (i.e. FrozenWorld Engine instigated) moves.
        /// See <see cref="WorldLockingManager.MoveAttachmentPoint"/>
        /// </remarks>
        /// <param name="attachPoint">Attachment point to move</param>
        /// <param name="newFrozenPosition">The new position in frozen space</param>
        public void MoveAttachmentPoint(IAttachmentPoint attachPointIface, Vector3 newFrozenPosition)
        {
            AttachmentPoint attachPoint = attachPointIface as AttachmentPoint;

            if (attachPoint != null)
            {
                attachPoint.ObjectPosition = newFrozenPosition;

                // If it's not in a valid fragment, it is still pending and will get processed when the system is ready.
                if (attachPoint.FragmentId.IsKnown())
                {
                    float minDistToUpdateSq = 0.5f * 0.5f;

                    float moveDistanceSq = (newFrozenPosition - attachPoint.CachedPosition).sqrMagnitude;
                    if (moveDistanceSq > minDistToUpdateSq)
                    {
                        attachPoint.LocationFromAnchor = plugin.MoveAttachmentPoint(newFrozenPosition, attachPoint.AnchorId, attachPoint.LocationFromAnchor);
                        attachPoint.CachedPosition     = newFrozenPosition;
                    }
                    // Else we haven't moved enough to bother doing anything.
                }
            }
        }
Пример #14
0
 /// <summary>
 /// Helper function for setting up the internals of an AttachmentPoint
 /// </summary>
 /// <param name="plugin">The global plugin</param>
 /// <param name="target">The attachment point to setup</param>
 /// <param name="context">The optional context <see cref="CreateAttachmentPoint"/></param>
 public static void SetupAttachmentPoint(IPlugin plugin, AttachmentPoint target, IAttachmentPoint context)
 {
     if (context != null)
     {
         AnchorId anchorId;
         Vector3  locationFromAnchor;
         plugin.CreateAttachmentPointFromSpawner(context.AnchorId, context.LocationFromAnchor, target.ObjectPosition,
                                                 out anchorId, out locationFromAnchor);
         FragmentId fragmentId = context.FragmentId;
         target.Set(fragmentId, target.ObjectPosition, anchorId, locationFromAnchor);
     }
     else
     {
         FragmentId currentFragmentId = plugin.GetMostSignificantFragmentId();
         AnchorId   anchorId;
         Vector3    locationFromAnchor;
         plugin.CreateAttachmentPointFromHead(target.ObjectPosition,
                                              out anchorId, out locationFromAnchor);
         FragmentId fragmentId = currentFragmentId;
         target.Set(fragmentId, target.ObjectPosition, anchorId, locationFromAnchor);
     }
 }
Пример #15
0
 /// <inheritdoc />
 public void TeleportTo(IAttachmentPointManager manager, Vector3 newFrozenPosition, IAttachmentPoint parent)
 {
     manager.TeleportAttachmentPoint(this, newFrozenPosition, parent);
 }
 private void OnDestroy()
 {
     // Let the manager know the attachment point is freed.
     Manager.ReleaseAttachmentPoint(AttachmentPoint);
     AttachmentPoint = null;
 }
 /// <summary>
 /// Let the manager know the attachment point is freed.
 /// </summary>
 private void OnDestroy()
 {
     Manager.ReleaseAttachmentPoint(AttachmentPoint);
     AttachmentPoint = null;
 }
 private string DebugAttachmentPoint(string label, IAttachmentPoint att)
 {
     return($"aaa {label} A:{att.AnchorId} F:{att.FragmentId} {att.State} {att.LocationFromAnchor.ToString("F3")}\n");
 }