/// <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)); }
/// <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)); }
/// <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(); } }
private void CheckDependencies() { /// Cache the WorldLockingManager as a dependency. manager = WorldLockingManager.GetInstance(); if (AlignmentManager == null) { AlignmentManager = manager.AlignmentManager; } }
/// <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); }
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; } }
/// <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); }
/// <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); }
/// <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); }