Beispiel #1
0
        public static bool SetOutfit(Body body, Outfit outfit, float repoOffset = 0,
                                     RemoveActionType removeType = RemoveActionType.Undefined, bool singleUndo = true,
                                     string undoLabel            = "Set Outfit")
        {
            // Design note:  It would be much simpler to just remove and add in separate transactions.  But that
            // sends the wrong type of event to observers, so have to go the messy route in order to properly
            // mimic runtime behavior.

            // Validations

            if (!CheckValidAction(body))
            {
                return(false);
            }

            if (outfit == body.Outfit)
            {
                Debug.LogWarning("No action taken. Outfit is the same as the body's current outfit: "
                                 + (outfit ? outfit.name : "null"), body);
                return(true);  // This is the correct behavior.
            }

            if (outfit && outfit.IsManaged)
            {
                Debug.LogError("Can't set outfit.  The outfit is already managed by: " + outfit.Owner.name, body);
                return(false);
            }

            // Keep last since it may involve a dialog box.
            Transform origParent = null;

            if (body.Outfit)
            {
                removeType = GetRemoveType(body, removeType);
                if (removeType == RemoveActionType.Cancel)
                {
                    return(false);
                }

                origParent = body.Outfit.transform.parent;
            }

            // Prepare for transaction.

            if (singleUndo)
            {
                Undo.IncrementCurrentGroup();
            }

            bool      isNew        = false;
            Transform outfitParent = null;

            if (outfit)
            {
                isNew = AssetDatabase.Contains(outfit);
                if (isNew)
                {
                    var name = outfit.name;
                    outfit      = outfit.Instantiate();
                    outfit.name = name;
                    // Will register the undo after success has been determined.
                }
                else
                {
                    Undo.RecordObjects(Outfit.UnsafeGetUndoObjects(outfit).ToArray(), undoLabel);
                }

                outfitParent = outfit.transform.parent;
            }

            Undo.RecordObjects(Body.UnsafeGetUndoObjects(body).ToArray(), undoLabel);

            // Set the outfit.

            var orig    = body.SetOutfit(outfit);
            var success = (orig != outfit);

            if (success)
            {
                if (orig)
                {
                    // Finalize the original outfit.

                    orig.transform.parent = origParent;
                    Undo.SetTransformParent(orig.transform, null, undoLabel);

                    if (removeType == RemoveActionType.RemoveAndDestroy)
                    {
                        orig.Destroy(DestroyType.GameObject, true);
                        Undo.DestroyObjectImmediate(orig.gameObject);
                    }
                    else if (repoOffset > 0)
                    {
                        // This extra call is needed, otherwise only **part** of the translation is recorded.  The
                        // problem might be due to the change in the parent.  Anyway, more fun with undo...
                        Undo.RecordObject(orig.transform, undoLabel);
                        orig.transform.position += body.transform.right * repoOffset;
                    }
                }

                if (outfit)
                {
                    // Finalize the outfit that was set.

                    if (isNew)
                    {
                        Undo.RegisterCreatedObjectUndo(outfit.gameObject, undoLabel);
                    }

                    var parent = outfit.transform.parent;
                    outfit.transform.parent = outfitParent;
                    Undo.SetTransformParent(outfit.transform, parent, undoLabel);

                    if (body is StandardBody)
                    {
                        // HACK: Addition of body as outfit observer is not being recorded for serialization.
                        // This fixes it until the cause and proper fix can be determined.
                        StandardOutfitEditor.AddObserverWithUndo(outfit, (StandardBody)body);
                    }
                }

                success = true;
            }
            else
            {
                if (isNew)
                {
                    outfit.gameObject.SafeDestroy();
                }

                success = false;
            }

            if (singleUndo)
            {
                Undo.CollapseUndoOperations(Undo.GetCurrentGroup());
            }

            return(success);
        }