/// <summary> /// Sets the outfit's motion root. /// </summary> /// <remarks> /// <para> /// Behavior is undefined if this method is used after outfit initialization. /// </para> /// </remarks> /// <param name="outfit">The outfit. (Required.)</param> /// <param name="motionRoot">The motion root. (Required.)</param> public static void UnsafeSetMotionRoot(OutfitCore outfit, Transform motionRoot) { // Hack: Naming convention: An overload failure requires this to be unique method name. // This method used to be UnsafeSet(Outfit, Transform). But for some reason calls were redirecting to // UnsafeSet(StandardOutfit, bool, BodyPart[]) in StandardBody, so had to abandon the overload // naming convention for this method. Note: This problem only started to happen when the body // part features were moved from OutfitCore to StandardOutfit. if (motionRoot) { var check = motionRoot.GetComponentInParent <OutfitCore>(); if (check != outfit) { // This is not a completely accurate test. But it is ok since having // multiple outfits in the parent hierachy is not appropriate. Debug.LogError("The motion root is not a child of the outfit.", outfit); return; } outfit.m_MotionRoot = motionRoot; } else { Debug.LogError("Invalid motion root. Motion root can't be null.", outfit); } }
/// <summary> /// Set the value of <see cref="UseDefaultStorage"/>. /// </summary> /// <remarks> /// <para> /// Behavior is undefined if the value of <see cref="UseDefaultStorage"/> is changed after outfit /// initialization. /// </para> /// </remarks> public static void UnsafeSetUseDefaultStorage(OutfitCore outfit, bool useDefaultStorage) { /* * Design note: The reason this is unsafe is because of unpredicable beahvior if the value is changed * during use of the outfit. E.g. What should the outfit do if default storage is turned off when it is * already in storage? What will the user expect? */ outfit.m_UseDefaultStorage = useDefaultStorage; }
/// <summary> /// Replaces the current mount points with the provided mounts points. /// </summary> /// <remarks> /// <para> /// Behavior is undefined if this method if used after outfit initialization or after /// accessories are attached. /// </para> /// <para> /// If <paramref name="asReference"/> is true, then all external references to the /// <paramref name="mountPoints"/> array must be discared or behavior will be undefined. /// </para> /// </remarks> /// <param name="outfit">The outfit. (Required)</param> /// <param name="asReference"> /// If true, the <paramref name="mountPoints"/> refrence will be used internally, otherwise the array will /// be copied. /// </param> /// <param name="mountPoints">The mount points, or null to clear all mount points.</param> public static void UnsafeSet(OutfitCore outfit, bool asReference, params MountPoint[] mountPoints) { // Design note: While an odd use case, it is not required that a mount point be a child of the outfit, so // don't put any restrictions in place for that. if (mountPoints == null) { outfit.m_MountPoints.Clear(); } else { MountPointGroup.UnsafeReplaceItems(outfit.m_MountPoints, asReference, mountPoints); } }
/// <summary> /// Refreshes the mount points using a child search. /// </summary> /// <remarks> /// <para> /// Behavior is undefined if this method is used after outfit initialization or after accessories are attached. /// </para> /// <para> /// If <paramref name="replace"/> is false, the order of currently defined mount points will be preserved with /// new mount points added to the end of the list. /// </para> /// </remarks> /// <param name="outfit">The outfit. (Required)</param> /// <param name="replace"> /// If true, all current mount points will be cleared and replaced with the result of he refresh. Otherwise /// only newly detected mount points will be added. /// </param> /// <returns> /// The number of new mount points added, or the total count if <paramref name="replace"/> is true. /// </returns> public static int UnsafeRefreshMountPoints(OutfitCore outfit, bool replace = false) { var fitems = outfit.GetComponentsInChildren <MountPoint>(); if (replace) { UnsafeSet(outfit, true, fitems); return(fitems.Length); } var before = outfit.m_MountPoints.AssignedCount; outfit.m_MountPoints.CompressAndAdd(fitems); return(outfit.m_MountPoints.AssignedCount - before); }
/// <summary> /// Refreshes an outfit's observers, purging all missing items and adding any new observers local to the /// outfit's GameObject. /// </summary> /// <param name="outfit">The outfit. (Required.)</param> public static void RefreshObservers(OutfitCore outfit) { outfit.Observers.PurgeDestroyed(); var refreshItems = outfit.GetComponents <IOutfitObserver>(); if (refreshItems.Length > 0) { // Add new items to end. foreach (var refreshItem in refreshItems) { if (!outfit.Observers.Contains(refreshItem)) { outfit.Observers.Add(refreshItem); } } } }
/// <summary> /// Clear all mount points. /// </summary> /// <para> /// Behavior is undefined if this method if used after outfit initialization or after accessories are attached. /// </para> /// <param name="outfit">The outfit. (Required.)</param> public static void UnsafeClearMountPoints(OutfitCore outfit) { outfit.m_MountPoints.Clear(); }
/// <summary> /// True if the motion root is assigned. Otherwise the motion root is defaulting to the outfit transform. /// </summary> /// <remarks> /// <para>This is helpful for editor checks since <see cref="MotionRoot"/> must always return a value.</para> /// </remarks> /// <param name="outfit">The outfit to check.</param> /// <returns> /// True if the motion root is assigned. Otherwise the motion root is defaulting to the outfit transform. /// </returns> public static bool IsMotionRootAssigned(OutfitCore outfit) { return(outfit.m_MotionRoot); }