/// <summary> /// Synchronize the mount point state of all common mount points using the observer's settings. /// </summary> /// <param name="to">The outfit being synchonized to. (Required)</param> /// <param name="from">The outfit being syncronzied from. (Required)</param> public virtual void Synchronize(Outfit to, Outfit from) { Outfit.SynchronizeMountPointState(to, from, m_BlockedStatus, m_Context); }
/// <summary> /// Called at the end of an outfit change operation. /// </summary> /// <remarks> /// <para> /// There are three situations when a forced release is performed: /// </para> /// <para> /// <ul> /// <li><see cref="SetOutfit"/> was used to initiate the forced release.</li> /// <li>A bake event was received from the outfit.</li> /// <li> /// The body detected that the outfit was improperly destroyed using Object.Destroy() directly, instead of /// <see cref="Outfit.Destroy"/>. /// </li> /// </ul> /// </para> /// </remarks> /// <param name="previous">The previous outfit, or null if there is none.</param> /// <param name="wasForced">True if a forced release was performed.</param> protected virtual void OnOutfitChange(Outfit previous, bool wasForced) { // Do nothing. }
protected sealed override void OnOutfitChange(Body sender, Outfit previous, bool wasForced) { Synchronize(sender.Outfit, previous); }
void IOutfitObserver.OnReleaseAccessory(Outfit sender, Accessory accessory) { // Do nothing. }
private void SendOutfitChange(Outfit previous, bool wasForced) { OnOutfitChange(previous, wasForced); Observers.SendOutfitChange(this, previous, wasForced); }
public sealed override Outfit SetOutfit(Outfit outfit, bool forceRelease) { // Warning: This method can be called by CheckOutfitLost(), so make sure no code paths trigger that // method. if (outfit) { if (outfit == m_Outfit) { Debug.LogWarning("Outfit is already set. No action taken.", this); return(null); } if (outfit && outfit.IsManaged && (outfit.Owner && outfit.Owner != gameObject)) { Debug.LogErrorFormat(this, "Outfit is managed by another object. Can't set outfit. Outfit: {0}, Owner: {1}", outfit.name, outfit.Owner.name); return(outfit); } } if (forceRelease && !m_HasOutfit) { Debug.LogWarning("Force release ignored. Body has no outfit to release.", this); forceRelease = false; } forceRelease = forceRelease || (m_HasOutfit && !m_Outfit); var origOutfit = m_Outfit ? m_Outfit : null; // Get rid of potential destoryed reference early. if (m_Outfit) { m_Outfit.RemoveObserver(this); // Keep this early. // Note: The state of the outfit it set at the end of the method, just before final release. if (m_Outfit.transform.parent == transform) { m_Outfit.transform.parent = null; } // Preserve the outfit's position. DefaultMotionRoot.position = m_Outfit.MotionRoot.position; DefaultMotionRoot.rotation = m_Outfit.MotionRoot.rotation; // Assumption: The body should never be the context of outfit compoenents for an outfit it isn't // managing. for (int i = 0; i < m_Outfit.BodyPartCount; i++) { var item = m_Outfit.GetBodyPart(i); if (item && item.Context == gameObject) { item.Context = null; } } for (int i = 0; i < m_Outfit.MountPointCount; i++) { var item = m_Outfit.GetMountPoint(i); if (item && item.Context == gameObject) { item.Context = null; } } } m_Outfit = outfit; m_HasOutfit = m_Outfit; if (m_Outfit) { m_Outfit.SetState(OutfitStatus.InUse, gameObject); m_Outfit.transform.parent = transform; // Persist the previous outfit's position. m_Outfit.MotionRoot.position = DefaultMotionRoot.position; m_Outfit.MotionRoot.rotation = DefaultMotionRoot.rotation; m_Outfit.AddObserver(this); // Keep this late. } AccessoriesLocal.SetOutfit(outfit, forceRelease); SendOutfitChange(origOutfit, forceRelease); // Keep this last. There may be outfit observers that take action when the outfit transitions state. // Don't want to trigger them until the outfit is truley free. if (origOutfit && origOutfit.Owner == gameObject) { origOutfit.SetState(OutfitStatus.Unmanaged, null); } return(origOutfit); }
void IOutfitObserver.OnMountAccessory(Outfit sender, Accessory accessory) { // Do nothing. }
void IBodyObserver.OnOutfitChange(Body sender, Outfit previous, bool wasForced) { OnOutfitChange(sender, previous, wasForced); }
protected abstract void OnOutfitChange(Body sender, Outfit previous, bool wasForced);
void IOutfitObserver.OnReleaseAccessory(Outfit sender, Accessory accessory) { // Handled by accesory manager. }
protected virtual void LocalOutfitChange(Outfit previous) { // Do nothing. }
private void SendOutfitChange(Outfit previous) { LocalOutfitChange(previous); Observers.SendOutfitChange(this, previous); }
/// <summary> /// Get the outfit's animator, or null if there is none. /// </summary> /// <remarks> /// <para> /// The default behavior is to use <see cref="Outfit.GetAnimator()"/>. /// </para> /// </remarks> /// <param name="outfit">The outfit. (May be null.)</param> /// <returns>The outfit's animator, or null if none found.</returns> protected virtual Animator GetAnimator(Outfit outfit) { return(outfit ? outfit.GetAnimator() : null); }
////////////////////////////////////////////////////////////////////////////////////////////// /// <summary> /// Destroy the outfit. /// </summary> /// <remarks> /// <para> /// Important: Only the owner of the oufit should call this method. /// </para> /// <para> /// This is the best way of destroying an outfit since the outfit will send events to its observers and /// other associated components so they can properly respond. /// </para> /// <para> /// The component is responsible for destroying itself as appropriate. So he client only needs to call this /// method then dispose of its references to the component. /// </para> /// <para><strong>Baking</strong> /// </para> /// Baking is the process of converting the outfit into a non-outfit state. What exactly happens during /// the bake is implemenation specific. It may result in the baking of skinned meshes into static meshes. /// It may result in conversion to a ragdoll configuration. Etc. /// <para> /// </remarks> /// <param name="typ">The type of destruction.</param> /// <param name="referenceOutfit"> /// The outfit that the the current outfit is derived from. (E.g. Was instanced from.) Or null if the outfit /// has no known source. (Only applies to the 'bake' type.) /// </param> public abstract void Destroy(DestroyType typ, Outfit referenceOutfit);