/// <summary>
        /// Sets the specified outfit material target, or adds a new material target if the
        /// type does not exist.
        /// </summary>
        /// <remarks>
        /// <para>
        /// This method is meant for use during configuration of the outfit.  It is not normal to change material
        /// targets while the outfit is in use.
        /// </para>
        /// </remarks>
        /// <param name="outfit">The outfit. (Required)</param>
        /// <param name="typ">The material type.</param>
        /// <param name="target">The new target for the material type.</param>
        public static void AddMaterialTarget(
            StandardOutfit outfit, OutfitMaterialType typ, RendererMaterialPtr target)
        {
            // Design note: This is a class member because its use is expected to be limited
            // to outfit initialization.  Don't want to unnecessarily clutter the instance API.

            outfit.m_OutfitMaterials.AddTarget(typ, target);
        }
        /// <summary>
        /// Refreshes the body parts by performing a child search.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Behavior is undefined if this method if used after outfit initialization.
        /// </para>
        /// <para>
        /// If <paramref name="replace"/> is false, the order of currently defined body parts will be preserved.  New
        /// body parts will be added to the end of the body part list.
        /// </para>
        /// </remarks>
        /// <param name="outfit">The outfit. (Required)</param>
        /// <param name="replace">
        /// If true, all current body parts will be cleared and replaced with the result of the refresh.  Otherwise
        /// only newly detected body parts will be added.
        /// </param>
        /// <returns>The number of body parts added, or all  if <paramref name="replace"/> is true.</returns>
        public static int UnsafeRefreshBodyParts(StandardOutfit outfit, bool replace = false)
        {
            var items = outfit.GetComponentsInChildren <BodyPart>();

            if (replace)
            {
                UnsafeSet(outfit, true, items);
                return(items.Length);
            }

            var before = outfit.m_Parts.ItemCount;

            outfit.m_Parts.CompressAndAdd(items);

            return(outfit.m_Parts.ItemCount - before);
        }
        /// <summary>
        /// Attempts to auto-detect settings using standard component searches.
        /// </summary>
        /// <remarks>
        /// <para>
        /// Using this method after outfit initialization can result in undefined behavior.
        /// </para>
        /// <para>
        /// The MotionRoot is guarenteed to be assigned after this process completes.
        /// </para>
        /// <para>
        /// Will attempt to locate and assign the MotionRoot, primary collider, body parts, and mount points,
        /// and observers.  Lists will be updated such that the order of existing items will not change.
        /// </para>
        /// <para>
        /// Warning: Will not attempt to check the validity in existing settings.
        /// </para>
        /// </remarks>
        /// <param name="outfit">The outfit. (Required.)</param>
        public static void UnsafeRefreshAllSettings(StandardOutfit outfit)
        {
            var outfitAnimator = outfit.GetAnimator();

            if (!outfit.MotionRoot)
            {
                var motionRoot = outfitAnimator
                    ? outfitAnimator.transform
                    : outfit.transform;

                UnsafeSetMotionRoot(outfit, motionRoot);
            }

            if (!outfit.PrimaryCollider)
            {
                var collider = outfit.MotionRoot.GetComponent <Collider>();  // Not a child search.

                if (collider && collider.GetAssociatedRigidBody())
                {
                    outfit.PrimaryCollider = collider;
                }
            }

            if (!outfit.BlendShapeRenderer)
            {
                foreach (var item in outfit.GetComponentsInChildren <SkinnedMeshRenderer>())
                {
                    if (item.sharedMesh && item.sharedMesh.blendShapeCount > 0)
                    {
                        outfit.BlendShapeRenderer = item;
                        break;
                    }
                }
            }

            UnsafeRefreshBodyParts(outfit, false);
            UnsafeRefreshMountPoints(outfit, false);
            outfit.RefreshObservers();
        }
 /// <summary>
 /// Clear all body parts.
 /// </summary>
 /// <para>
 /// Behavior is undefined if this method if used after outfit initialization.
 /// </para>
 /// <param name="outfit">The outfit. (Required.)</param>
 public static void UnsafeClearBodyParts(StandardOutfit outfit)
 {
     outfit.m_Parts.Clear(0);
 }
 /// <summary>
 /// Replaces the current body parts with the provided body parts.
 /// </summary>
 /// <remarks>
 /// <para>
 /// Behavior is undefined if this method if used after outfit initialization.
 /// </para>
 /// <para>
 /// If <paramref name="asReference"/> is true, then all external references to the body part array must be
 /// discared or behavior will be undefined.
 /// </para>
 /// </remarks>
 /// <param name="outfit">The outfit. (Required)</param>
 /// <param name="asReference">
 /// If true the outfit will use the reference to the body part rray.  Otherwise the array will be copied.
 /// </param>
 /// <param name="mountPoints">The body parts, or null to clear all body parts.</param>
 public static void UnsafeSet(
     StandardOutfit outfit, bool asReference, params BodyPart[] bodyParts)
 {
     BodyPartGroup.UnsafeReplaceItems(outfit.m_Parts, asReference, bodyParts);
 }