/// <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> /// Invoke a refreeze operation on the plugin, and make all necessary adjustments /// in bookeeping after. /// </summary> /// <returns>True for successful refreeze.</returns> public bool Refreeze() { FragmentId targetFragmentId; FragmentId[] absorbedIds; if (!plugin.Refreeze(out targetFragmentId, out absorbedIds)) { return(false); } Debug.Assert(targetFragmentId.IsKnown(), "Received invalid merged fragment id from successful refreeze"); Fragment targetFragment = EnsureFragment(targetFragmentId); Debug.Assert(targetFragment != null, "Valid fragmentId but no fragment found"); for (int i = 0; i < absorbedIds.Length; ++i) { FragmentId sourceId = absorbedIds[i]; if (sourceId != targetFragmentId) { Fragment sourceFragment; if (fragments.TryGetValue(sourceId, out sourceFragment)) { targetFragment.AbsorbOtherFragment(sourceFragment); fragments.Remove(sourceId); } else { Debug.LogError($"Try to merge in a non-existent fragment {sourceId.FormatStr()}"); } } } CurrentFragmentId = targetFragmentId; // now apply individual adjustments to each attachment point. targetFragment.AdjustAll(plugin); // now that all adjustments have been made, notify the plugin to finish up the operation. plugin.RefreezeFinish(); refitNotifications?.Invoke(targetFragment.FragmentId, absorbedIds); return(true); }
/// <summary> /// Call on the plugin to compute the merge, then apply by /// setting transforms and adjusting scene graph. /// </summary> /// <returns>True for successful merge.</returns> public bool Merge() { FragmentId targetFragmentId; FragmentPose[] mergeAdjustments; if (!plugin.Merge(out targetFragmentId, out mergeAdjustments)) { return(false); } Debug.Assert(targetFragmentId.IsKnown(), "Received invalid merged fragment id from successful merge"); Fragment targetFragment = EnsureFragment(targetFragmentId); Debug.Assert(targetFragment != null, "Valid fragmentId but null target fragment from Merge"); int numAbsorbed = mergeAdjustments.Length; for (int i = 0; i < numAbsorbed; ++i) { FragmentId sourceId = mergeAdjustments[i].fragmentId; Pose adjustment = mergeAdjustments[i].pose; Fragment sourceFragment; if (fragments.TryGetValue(sourceId, out sourceFragment)) { targetFragment.AbsorbOtherFragment(sourceFragment, adjustment); fragments.Remove(sourceId); } else { Debug.LogError($"Try to merge in a non-existent fragment {sourceId.FormatStr()}"); } } CurrentFragmentId = targetFragmentId; ApplyActiveCurrentFragment(); refitNotifications?.Invoke(targetFragment.FragmentId, ExtractFragmentIds(mergeAdjustments)); return(true); }
/// <summary> /// If still waiting for a valid current fragment since last load, /// and there is a current valid fragment, set it to reference poses. /// </summary> private void CheckFragment() { bool changed = ActiveFragmentId != CurrentFragmentId; if (needFragment && CurrentFragmentId.IsKnown()) { FragmentId fragmentId = CurrentFragmentId; for (int i = 0; i < referencePoses.Count; ++i) { if (!referencePoses[i].fragmentId.IsKnown()) { DebugLogSaveLoad($"Transfer {referencePoses[i].anchorId.FormatStr()} from frag={referencePoses[i].fragmentId.FormatStr()} to {fragmentId.FormatStr()}"); referencePoses[i].fragmentId = fragmentId; changed = true; } } needFragment = false; } if (changed) { ActivateCurrentFragment(); } }