/// <summary>
        /// Set the position in spongy space. Rotation not needed since it is computed based on relative positions.
        /// </summary>
        /// <param name="spongyPosition">Position in spongyt space.</param>
        public void SetSpongyPosition(Vector3 spongyPosition)
        {
            WorldLockingManager wltMgr         = WorldLockingManager.GetInstance();
            Vector3             lockedPosition = wltMgr.LockedFromSpongy.Multiply(spongyPosition);

            SetLockedPose(new Pose(lockedPosition, LockedRotation));
        }
예제 #2
0
        /// <summary>
        /// Prompt the AlignmentManager to compute a new alignment pose, then apply it to the target subtree.
        /// </summary>
        private void Update()
        {
            Debug.Assert(alignmentManager != null);

            CheckAutoLoad();

            var wltMgr = WorldLockingManager.GetInstance();

            Debug.Assert(alignmentManager != wltMgr.AlignmentManager);

            Pose lockedHeadPose = wltMgr.LockedFromPlayspace.Multiply(wltMgr.PlayspaceFromSpongy.Multiply(wltMgr.SpongyFromCamera));

            alignmentManager.ComputePinnedPose(lockedHeadPose);
            var pinnedFromLocked = alignmentManager.PinnedFromLocked;
            var lockedFromPinned = pinnedFromLocked.Inverse();

            if (wltMgr.ApplyAdjustment)
            {
                subTree.SetGlobalPose(lockedFromPinned);
            }
            else
            {
                var spongyFromLocked = wltMgr.SpongyFromLocked;
                var pinnedFromFrozen = wltMgr.PinnedFromFrozen;

                var spongyFromFrozen = spongyFromLocked.Multiply(lockedFromPinned).Multiply(pinnedFromFrozen);
                subTree.SetGlobalPose(spongyFromFrozen);
            }

            CheckAutoSave();
        }
        /// <summary>
        /// Adjust to refit operations.
        /// </summary>
        /// <param name="mainId">The new combined fragment.</param>
        /// <param name="absorbedIds">Id's of other fragments being merged into mainId.</param>
        /// <remarks>
        /// This callback occurs *after* the refit operation. As part of the refit,
        /// positions of the managed SpacePinOrientables may have changed, and therefore
        /// their implied orientations must be re-calculated.
        /// Note that there is an apparent race condition, as there is no order guarantee on
        /// the order of refit notifications, and the AlignmentManager also relies on the
        /// refit notification to adjust after refit operations.
        /// However, both the Orienter and the AlignmentManager rely only on the positions
        /// having been set, which was accomplished during the refit and before the refit
        /// notification. So it really doesn't matter whether the Orienter.OnRefit or the
        /// AlignmentManager.OnRefit is called first.
        /// </remarks>
        private void OnRefit(FragmentId mainId, FragmentId[] absorbedIds)
        {
            IAlignmentManager alignMgr = WorldLockingManager.GetInstance().AlignmentManager;

            Reorient(mainId, alignMgr);
            alignMgr.SendAlignmentAnchors();
        }
        /// <summary>
        /// Set the position in frozen space. Rotation not needed since it is computed based on relative positions.
        /// </summary>
        /// <param name="frozenPosition">Position in frozen space.</param>
        public void SetFrozenPosition(Vector3 frozenPosition)
        {
            WorldLockingManager wltMgr         = WorldLockingManager.GetInstance();
            Vector3             lockedPosition = wltMgr.LockedFromFrozen.Multiply(frozenPosition);

            SetLockedPose(new Pose(lockedPosition, LockedRotation));
        }
예제 #5
0
 /// <summary>
 /// Check that all internal wiring is complete.
 /// </summary>
 private void Start()
 {
     CheckInternalWiring();
     needAutoLoad = WorldLockingManager.GetInstance().AutoLoad;
     autoSave     = WorldLockingManager.GetInstance().AutoSave;
     DebugLogSaveLoad($"Subtree {name} Start");
 }
 /// <summary>
 /// Push contained settings if the input scene matches this's scene.
 /// </summary>
 /// <param name="scene"></param>
 private void CheckPushSettings(Scene scene)
 {
     if (scene == this.gameObject.scene)
     {
         WorldLockingManager manager = WorldLockingManager.GetInstance();
         manager.SetContext(this);
     }
 }
 /// <summary>
 /// Get the WorldLockingManager instance. This may be called at any time in program execution,
 /// but if called during load its settings may not have been loaded from a new scene yet.
 /// </summary>
 /// <returns>The WorldLockingManager</returns>
 public static WorldLockingManager GetInstance()
 {
     if (managerInstance == null)
     {
         managerInstance = new WorldLockingManager();
     }
     return(managerInstance);
 }
 /// <summary>
 /// Check that all internal wiring is complete.
 /// </summary>
 private void Start()
 {
     CheckInternalWiring();
     if (AutoSave && !WorldLockingManager.GetInstance().AutoSave)
     {
         Debug.LogError("AutoSaving alignment requires WorldLockingManager.AutoSave to work as expected.");
     }
 }
            /// <summary>
            /// Pass the update on to the manager.
            /// </summary>
            private void Update()
            {
                var manager = WorldLockingManager.GetInstance();

                if (manager != null)
                {
                    manager.Update();
                }
            }
예제 #10
0
        private void CheckDependencies()
        {
            /// Cache the WorldLockingManager as a dependency.
            manager = WorldLockingManager.GetInstance();

            if (AlignmentManager == null)
            {
                AlignmentManager = manager.AlignmentManager;
            }
        }
예제 #11
0
        /// <summary>
        /// Record the locked pose and push data to the manager.
        /// </summary>
        /// <param name="lockedPose"></param>
        public virtual void SetLockedPose(Pose lockedPose)
        {
            this.lockedPose = lockedPose;

            DebugLogSaveLoad($"SetLockedPose {name}: mgr={(AlignmentManager == WorldLockingManager.GetInstance().AlignmentManager ? "global" : "local")}");

            PushAlignmentData(AlignmentManager);

            SendAlignmentData(AlignmentManager);
        }
예제 #12
0
        private void CheckDependencies()
        {
            /// Cache the WorldLockingManager as a dependency.
            manager = WorldLockingManager.GetInstance();

            if (AlignmentManager == null)
            {
                DebugLogSaveLoad($"Setting {name} pin's alignment manager to global because unset.");
                AlignmentManager = manager.AlignmentManager;
            }
        }
예제 #13
0
        /// <summary>
        /// Adjust to refit operations.
        /// </summary>
        /// <param name="mainId">The new combined fragment.</param>
        /// <param name="absorbedIds">Id's of other fragments being merged into mainId.</param>
        /// <remarks>
        /// This callback occurs *after* the refit operation. As part of the refit,
        /// positions of the managed SpacePinOrientables may have changed, and therefore
        /// their implied orientations must be re-calculated.
        /// Note that there is an apparent race condition, as there is no order guarantee on
        /// the order of refit notifications, and the AlignmentManager also relies on the
        /// refit notification to adjust after refit operations.
        /// However, both the Orienter and the AlignmentManager rely only on the positions
        /// having been set, which was accomplished during the refit and before the refit
        /// notification. So it really doesn't matter whether the Orienter.OnRefit or the
        /// AlignmentManager.OnRefit is called first.
        /// </remarks>
        private void OnRefit(FragmentId mainId, FragmentId[] absorbedIds)
        {
            /// Use the last alignment manager used. If none, use the wlt manager's current alignment manager.
            IAlignmentManager alignMgr = cachedAlignmentManager;

            if (alignMgr == null)
            {
                alignMgr = WorldLockingManager.GetInstance().AlignmentManager;
            }
            Reorient(mainId, alignMgr);
            alignMgr.SendAlignmentAnchors();
        }
 /// <summary>
 /// Create the alignmentManager if needed.
 /// </summary>
 /// <remarks>
 /// The AlignmentManager, though mostly independent, does have a dependency on the WorldLockingManager.
 /// The WorldLockingManager can't be created until Start/OnEnable (whichever comes first). So even
 /// though the AlignmentManager isn't a Unity derived type, it is still limited on how early it can
 /// be created.
 /// </remarks>
 private void CheckInternalWiring()
 {
     if (alignmentManager == null)
     {
         alignmentManager = new AlignmentManager(WorldLockingManager.GetInstance());
         alignmentManager.SaveFileName = SaveFileName;
     }
     if (subTree == null)
     {
         subTree = transform;
     }
 }
        // Start is called before the first frame update
        protected virtual void Start()
        {
            /// Cache the WorldLockingManager as a dependency.
            manager = WorldLockingManager.GetInstance();

            /// Cache the initial pose.
            ResetModelingPose();

            /// Register for post-loaded messages from the Alignment Manager.
            /// When these come in check for the loading of the reference point
            /// associated with this pin. Reference is by unique name.
            manager.AlignmentManager.RegisterForLoad(RestoreOnLoad);
        }
        /// <summary>
        /// Prompt the AlignmentManager to compute a new alignment pose, then apply it to the target subtree.
        /// </summary>
        private void Update()
        {
            Debug.Assert(alignmentManager != null);

            CheckLoad();

            var wltMgr = WorldLockingManager.GetInstance();

            Debug.Assert(alignmentManager != wltMgr.AlignmentManager);

            Pose lockedHeadPose = wltMgr.LockedFromPlayspace.Multiply(wltMgr.PlayspaceFromSpongy.Multiply(wltMgr.SpongyFromCamera));

            alignmentManager.ComputePinnedPose(lockedHeadPose);
            var pinnedFromLocked = alignmentManager.PinnedFromLocked;
            var lockedFromPinned = pinnedFromLocked.Inverse();

            subTree.SetGlobalPose(lockedFromPinned);
        }
예제 #17
0
        /// <summary>
        /// Create the alignmentManager if needed.
        /// </summary>
        /// <remarks>
        /// The AlignmentManager, though mostly independent, does have a dependency on the WorldLockingManager.
        /// The WorldLockingManager can't be created until Start/OnEnable (whichever comes first). So even
        /// though the AlignmentManager isn't a Unity derived type, it is still limited on how early it can
        /// be created.
        /// </remarks>
        private void CheckInternalWiring()
        {
            if (alignmentManager == null)
            {
                alignmentManager = new AlignmentManager(WorldLockingManager.GetInstance());
                alignmentManager.SaveFileName = SaveFileName;

                OnAlignManagerCreated?.Invoke(this, alignmentManager);
            }
            if (subTree == null)
            {
                subTree = transform;
            }
            if (orienter == null)
            {
                orienter = GetComponentInChildren <Orienter>();
                Debug.LogWarning($"No Orienter found on {name}, implicit Orienter found in subtree is {(orienter == null ? "null" : orienter.name)}");
            }
            if (Orienter != null)
            {
                Orienter.AlignmentManager = alignmentManager;
            }
        }
 /// <summary>
 /// Check that all internal wiring is complete.
 /// </summary>
 private void Start()
 {
     CheckInternalWiring();
     needLoad = WorldLockingManager.GetInstance().AutoLoad;
 }
 private void OnDestroy()
 {
     WorldLockingManager.GetInstance().FragmentManager.UnregisterForRefitNotifications(OnRefit);
 }
 private void Start()
 {
     WorldLockingManager.GetInstance().FragmentManager.RegisterForRefitNotifications(OnRefit);
 }
 /// <summary>
 /// Constructor, binds to a specific WorldLockingManager. Also registers for scene loading events.
 /// </summary>
 /// <param name="manager">WorldLocking manager which owns this sub-manager.</param>
 public AlignmentManager(WorldLockingManager manager)
 {
     this.manager = manager;
     SceneManager.sceneUnloaded += OnSceneUnloaded;
     manager.FragmentManager.RegisterForRefitNotifications(OnRefit);
 }
예제 #22
0
 /// <summary>
 /// Communicate the data from this point to the alignment manager.
 /// </summary>
 /// <param name="mgr"></param>
 protected void PushAlignmentData(IAlignmentManager mgr)
 {
     DebugLogExtra($"F{Time.frameCount} Push: {name}: MPG={ModelingPoseGlobal.ToString("F3")} GfP={GlobalFromParent.ToString("F3")} R={restorePoseLocal.ToString("F3")} MPP={WorldLockingManager.GetInstance().PinnedFromFrozen.Multiply(ModelingPoseGlobal)}");
     if (PinActive)
     {
         mgr.RemoveAlignmentAnchor(AnchorId);
     }
     AnchorId = mgr.AddAlignmentAnchor(AnchorName, ModelingPoseGlobal, lockedPose);
 }