Пример #1
0
        /// <summary>
        /// Draws in the title area of the window
        /// </summary>
        public override void DrawTitle()
        {
            if (Editor.Canvas.SelectedNode != null && Editor.Canvas.SelectedNode.Content != null)
            {
                string lTitle = "";

                SpellAction lAction = Editor.Canvas.SelectedNode.Content as SpellAction;
                if (lAction != null)
                {
                    lTitle = lAction.Name;
                }

                if (lTitle.Length == 0)
                {
                    lTitle = BaseNameAttribute.GetName(Editor.Canvas.SelectedNode.Content.GetType());
                }
                GUI.Label(new Rect(12f, 8f, Position.width - 12f, 20f), lTitle, PanelTitleStyle);

                if (GUI.Button(new Rect(Position.width - 31f, 10f, 16f, 16f), new GUIContent(" ", "Remove Spell Action"), NodeEditorStyle.ButtonX))
                {
                    Editor.Canvas.SelectedNode.DestroyContent();
                }
            }
            else
            {
                GUI.Label(new Rect(12f, 8f, Position.width - 12f, 20f), Title, PanelTitleStyle);
            }
        }
Пример #2
0
        /// <summary>
        /// Simple test to determine if the link can be traversed
        /// </summary>
        /// <param name="rUserData">Optional data to help with the test</param>
        /// <returns>Determines if the link can be traversed</returns>
        public override bool TestActivate(object rUserData = null)
        {
            if (_Link == null || _Link.StartNode == null || _Link.StartNode._Content == null)
            {
                return(false);
            }

            SpellAction lSpellAction = _Link.StartNode._Content as SpellAction;

            if (lSpellAction == null)
            {
                return(false);
            }
            if (lSpellAction._Spell == null)
            {
                return(false);
            }

            if (lSpellAction._Spell.State == State)
            {
                return(true);
            }

            return(false);
        }
Пример #3
0
        /// <summary>
        /// Deactivate the node contents and remove the node from the active list
        /// </summary>
        /// <param name="rNode">Node to activate</param>
        public void DeactivateNode(Node rNode)
        {
            if (ShowDebug)
            {
                Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].DeactivateNode() - Node: {1}", Name, rNode.Content.GetType().Name));
            }

            // If we're dealing with a spell action, activate
            SpellAction lAction = rNode.Content as SpellAction;

            if (lAction != null)
            {
                if (lAction.State == EnumSpellActionState.ACTIVE)
                {
                    lAction.Deactivate();
                }
            }

            // Remove the node from the active list
            mActiveNodes.Remove(rNode);

            // Add the action to the shuttind down list. This way it can
            // run and we can remove it when needed
            if (lAction.IsShuttingDown)
            {
                if (ShowDebug)
                {
                    Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].DeactivateNode() - Added to expiring nodes: {1}", Name, rNode.Content.GetType().Name));
                }

                mExpiringActions.Add(lAction);
            }
            // Since we are instantiating the nodes, we now destroy them
            else // if (!rNode.IsImmediate)
            {
                if (ShowDebug)
                {
                    Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].DeactivateNode() - Destroyed: {1}", Name, rNode.Content.GetType().Name));
                }

                ScriptableObject.Destroy(rNode.Content);
                ScriptableObject.Destroy(rNode);
            }
        }
Пример #4
0
        /// <summary>
        /// Draws in the content area of the window
        /// </summary>
        public override void DrawContent()
        {
            if (Editor.Canvas.SelectedNode == null)
            {
                return;
            }

            bool lIsDirty = false;

            if (Editor.Canvas.SelectedNode.Content != null)
            {
                string lDescription = BaseDescriptionAttribute.GetDescription(Editor.Canvas.SelectedNode.Content.GetType());
                if (lDescription != null && lDescription.Length > 0)
                {
                    NodeEditorStyle.DrawInspectorDescription(lDescription, MessageType.None);
                }
            }

            GUILayout.BeginHorizontal();

            if (EditorHelper.BoolField("Is Start Node", "Determines if the node is used as a starting node.", Editor.Canvas.SelectedNode.IsStartNode, Editor.RootAsset))
            {
                lIsDirty = true;
                Editor.Canvas.SelectedNode.IsStartNode = EditorHelper.FieldBoolValue;

                Spell lSpell = ((SpellEditor)Editor).Spell;
                if (lSpell != null)
                {
                    if (lSpell.StartNodes == null)
                    {
                        lSpell.StartNodes = new System.Collections.Generic.List <Node>();
                    }
                    if (lSpell.StartNodes.Contains(Editor.Canvas.SelectedNode))
                    {
                        if (!Editor.Canvas.SelectedNode.IsStartNode)
                        {
                            lSpell.StartNodes.Remove(Editor.Canvas.SelectedNode);
                            UnityEditor.EditorUtility.SetDirty(lSpell);
                        }
                    }
                    else if (Editor.Canvas.SelectedNode.IsStartNode)
                    {
                        lSpell.StartNodes.Add(Editor.Canvas.SelectedNode);
                        UnityEditor.EditorUtility.SetDirty(lSpell);
                    }
                }
            }

            EditorHelper.LabelField("End Node", "Determines if the node is used as an ending node.", 60f);
            if (EditorHelper.BoolField(Editor.Canvas.SelectedNode.IsEndNode, "End Node", Editor.RootAsset, 16f))
            {
                lIsDirty = true;
                Editor.Canvas.SelectedNode.IsEndNode = EditorHelper.FieldBoolValue;

                Spell lSpell = ((SpellEditor)Editor).Spell;
                if (lSpell != null)
                {
                    if (lSpell.EndNodes == null)
                    {
                        lSpell.EndNodes = new System.Collections.Generic.List <Node>();
                    }
                    if (lSpell.EndNodes.Contains(Editor.Canvas.SelectedNode))
                    {
                        if (!Editor.Canvas.SelectedNode.IsEndNode)
                        {
                            lSpell.EndNodes.Remove(Editor.Canvas.SelectedNode);
                            UnityEditor.EditorUtility.SetDirty(lSpell);
                        }
                    }
                    else if (Editor.Canvas.SelectedNode.IsEndNode)
                    {
                        lSpell.EndNodes.Add(Editor.Canvas.SelectedNode);
                        UnityEditor.EditorUtility.SetDirty(lSpell);
                    }
                }
            }

            GUILayout.EndHorizontal();

            if (Editor.Canvas.SelectedNode.Content == null)
            {
                EditorGUILayout.HelpBox(" Select an action for this node to take. Actions will be used to drive how the spell works.", MessageType.None);

                if (GUILayout.Button(new GUIContent("Select")))
                {
                    TypeSelectWindow lWindow = EditorWindow.GetWindow(typeof(TypeSelectWindow), false, "Select", true) as TypeSelectWindow;
                    lWindow.BaseType      = typeof(SpellAction);
                    lWindow.SelectedEvent = OnTypeSelected;
                }
            }
            else
            {
                SpellAction lAction = Editor.Canvas.SelectedNode.Content as SpellAction;
                if (lAction != null)
                {
                    bool lIsActionDirty = lAction.OnInspectorGUI(Editor.RootAsset);
                    if (lIsActionDirty)
                    {
                        lIsDirty = true;
                    }
                }
            }

            // If the node is dirty, we need to report it
            if (lIsDirty)
            {
                UnityEditor.EditorUtility.SetDirty(Editor.Canvas.SelectedNode);

                if (Editor.Canvas.SelectedNode._Content != null)
                {
                    UnityEditor.EditorUtility.SetDirty(Editor.Canvas.SelectedNode._Content);
                }

                Editor.SetDirty();
            }
        }
Пример #5
0
        /// <summary>
        /// Activate the node contents and flag the node as working
        /// </summary>
        /// <param name="rNode">Node to activate</param>
        public void ActivateNode(Node rNode, object rData = null)
        {
            Node lNode = rNode;

            // If the node isn't immediate, we'll create an instance of it so we can
            // loop over and over as needed. This instance is a shallow copy. So, we're not
            // creating new instances of children.
            //if (!lNode.IsImmediate)
            {
                // Create an instance of the node.
                lNode    = ScriptableObject.Instantiate <Node>(rNode);
                lNode.ID = rNode.ID;

                // Tell all the node links that this is the start node. We shallow copy them
                // as well so the StartNode can be different each instance
                for (int i = 0; i < lNode.Links.Count; i++)
                {
                    NodeLink lLink = ScriptableObject.Instantiate <NodeLink>(lNode.Links[i]);
                    lLink.StartNode = lNode;

                    // Creates instances for each of the actions
                    if (lLink.Actions != null && lLink.Actions.Count > 0)
                    {
                        for (int j = 0; j < lLink.Actions.Count; j++)
                        {
                            NodeLinkAction lLinkAction = ScriptableObject.Instantiate <NodeLinkAction>(lLink.Actions[j]);
                            lLinkAction._Link = lLink;

                            lLink.Actions[j] = lLinkAction;
                        }
                    }

                    lNode.Links[i] = lLink;
                }

                // We do want a deep copy of the content.
                lNode.Content = ScriptableObjectPool.DeepCopy(lNode.Content, true);

                if (ShowDebug)
                {
                    Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].ActivateNode() - Instance created for", Name, lNode.Content.GetType().Name));
                }
            }

            // If we're dealing with a spell action, activate
            SpellAction lAction = lNode.Content as SpellAction;

            if (lAction != null)
            {
                lNode.State = EnumNodeState.WORKING;

                lAction.Spell = this;
                lAction.Node  = lNode;
                lAction.Activate(0, rData);

                if (ShowDebug)
                {
                    Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].ActivateNode() - Activated: {1}", Name, lAction.GetType().Name));
                }

                // If the action takes time, add it to your queue
                if (lNode.State == EnumNodeState.WORKING)
                {
                    if (!mActiveNodes.Contains(lNode))
                    {
                        mActiveNodes.Add(lNode);

                        if (ShowDebug)
                        {
                            Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].ActivateNode() - Added to active nodes: {1}", Name, lAction.GetType().Name));
                        }
                    }
                }
                // if it's an instant action, we want to move to the next node
                else
                {
                    if (ShowDebug)
                    {
                        Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].ActivateNode() - Testing links: {1}", Name, lAction.GetType().Name));
                    }

                    // Process the node links to see if they should be activated
                    for (int i = 0; i < lNode.Links.Count; i++)
                    {
                        bool lActivate = lNode.Links[i].TestActivate();
                        if (lActivate)
                        {
                            ActivateLink(lNode.Links[i], lNode.Data);
                        }
                    }
                }
            }
            // We may still have links that need to process
            else
            {
                lNode.State = EnumNodeState.SUCCEEDED;

                if (ShowDebug)
                {
                    Utilities.Debug.Log.FileWrite(string.Format("Spell[{0}].ActivateNode() - No action, testing links: {1}", Name, lAction.GetType().Name));
                }

                // Process the node links to see if they should be activated
                for (int i = 0; i < lNode.Links.Count; i++)
                {
                    bool lActivate = lNode.Links[i].TestActivate();
                    if (lActivate)
                    {
                        ActivateLink(lNode.Links[i], lNode.Data);
                    }
                }
            }
        }
Пример #6
0
        /// <summary>
        /// Run as needed to process the "instance" data. This spell itself should only
        /// contain template level data.
        /// </summary>
        /// <param name="rDeltaTime">Time since the last frame update</param>
        /// <param name="rData">Instance level data for the spell.</param>
        public virtual void Update()
        {
            int lActiveNodes = mActiveNodes.Count;

            // Allow any expiring actions to finish shutting down. Then,
            // remove them when they are done.
            for (int i = mExpiringActions.Count - 1; i >= 0; i--)
            {
                SpellAction lAction = mExpiringActions[i];

                lAction.Update();
                if (!lAction.IsShuttingDown)
                {
                    mExpiringActions.RemoveAt(i);

                    // Since the node was probably listening for the action
                    // to finish, now we can stop
                    //if (!lAction.Node.IsImmediate)
                    {
                        Node lNode = lAction.Node;
                        ScriptableObject.Destroy(lNode.Content);
                        ScriptableObject.Destroy(lNode);
                    }
                }
            }

            // Go through all the active nodes and update. Since we
            // may append new nodes, we don't want to go past the original
            // active node count
            for (int i = 0; i < lActiveNodes; i++)
            {
                Node lNode = mActiveNodes[i];

                // Process the node content
                SpellAction lAction = lNode.Content as SpellAction;
                if (lAction != null)
                {
                    lAction.Update();
                }

                // If we're not shutting down, process the node links to see if they should be activated
                if (!mIsCancelling)
                {
                    for (int j = 0; j < lNode.Links.Count; j++)
                    {
                        bool lActivate = lNode.Links[j].TestActivate();
                        if (lActivate)
                        {
                            ActivateLink(lNode.Links[j], lNode.Data);
                        }
                    }
                }
            }

            // If we've cancelled, clear any active nodes
            if (mIsCancelling && !mEndNodesLoaded)
            {
                mActiveNodes.Clear();
            }
            // Deactivate any active nodes that have completed. This
            // may simply move them to the expiring queue
            else
            {
                for (int i = mActiveNodes.Count - 1; i >= 0; i--)
                {
                    Node lNode = mActiveNodes[i];

                    if (lNode.State == EnumNodeState.SUCCEEDED || lNode.State == EnumNodeState.FAILED)
                    {
                        DeactivateNode(lNode);
                    }
                }
            }

            // Flag the spell as completed if no actions are active
            if (State != EnumSpellState.READY && mExpiringActions.Count == 0 && mActiveNodes.Count == 0)
            {
                // Since no end nodes required, end
                if (mEndNodesLoaded || EndNodes.Count == 0)
                {
                    State = EnumSpellState.COMPLETED;
                }
                // Start all the end nodes
                else
                {
                    for (int i = 0; i < EndNodes.Count; i++)
                    {
                        ActivateNode(EndNodes[i]);
                    }

                    mIsCancelling   = false;
                    mEndNodesLoaded = true;
                }
            }
        }