Playmaker Forum

PlayMaker Help & Tips => PlayMaker Help => Topic started by: azevedco on April 19, 2017, 10:44:20 AM

Title: Possible to create / set Transition events for specific State by script[SOLVED]
Post by: azevedco on April 19, 2017, 10:44:20 AM
Hi guys,

Attempting to set the transition events for a specific state based on an array of strings.  I've reached a point where the events are set, under the hood, the state is aware of the events being hooked up, however, in the FSM, the events are not selectable.  If I manually add a new transition to the state, all the states that were previously not selectable become selectable.
[Question] 
Is there a way to call some form of update or redraw on the State and/or FSM that is also called when manually creating/removing/setting transition events on to states?

[Update]
I've been messing around with what I have here and an example found here https://gist.github.com/ApprenticeGC/5693533 (https://gist.github.com/ApprenticeGC/5693533), discovered that if I create a new State and add transition events to it, they're selectable.  If I add transition events to a pre-existing State, the events are not selectable...Plot thickens?


For the sake of quick testing, i've created an Action along with an editor for the action to provide a button that once clicked will hook up the events.

Action code:
Code: [Select]
    [ActionCategory("TestBed Stuff")]
    [HutongGames.PlayMaker.Tooltip("Automatically set events based on string array.")]
    public class AutoSetEvents : FsmStateAction
    {

        public FsmString[] events;

        public override void OnEnter()
        {
            base.OnEnter();
        }

    }

Editor code:
Code: [Select]
[CustomActionEditor(typeof(AutoSetEvents))]
    public class AutoSetEventsEditor : CustomActionEditor
    {

        AutoSetEvents action;

        public override void OnEnable()
        {
            base.OnEnable();
        }

        public override bool OnGUI()
        {
            action = target as AutoSetEvents;

            // You can draw the full default inspector.

            GUILayout.Label("Default Inspector:", EditorStyles.boldLabel);

            var isDirty = DrawDefaultInspector();

            // Do stuff here
            if (GUILayout.Button("Set Events"))
            {
                GenerateEvents();
                isDirty = true; // e.g., if you change action data
            }
            //***

            // OnGUI should return true if you change action data!

            return isDirty || GUI.changed;
        }

        // Create and add events to FSM
        // Create and add Transition to current state
        public void GenerateEvents()
        {

            PlayMakerFSM myFsm = action.Fsm.FsmComponent;
            bool transitionExists = false;

            if (myFsm != null)
            {

                FsmEditor.SelectFsm(myFsm.Fsm);

                for (int i = 0; i < action.events.Length; i++) {
                    FsmEvent fsmEvent = new FsmEvent(action.events[i].Value);
                    FsmEditor.Builder.AddEvent(myFsm.Fsm, fsmEvent);

                    for (int j = 0; j < action.State.Transitions.Length; j++)
                    {
                        if(action.State.Transitions[j].FsmEvent.Name.Equals(fsmEvent.Name))
                        {
                            transitionExists = true;
                            break;
                        }
                    }

                    if(!transitionExists)
                    {
                        FsmTransition fsmTransition = FsmEditor.Builder.AddTransition(action.State, "", fsmEvent);
                    }

                    transitionExists = false;
                }
                // Attemping to update FSM here, currently not working...
                action.Fsm.UpdateStateChanges();
                action.Fsm.setDirty = true;
                FsmEditor.Window.Repaint();
               
                FsmEditor.RepaintAll();

            }

        }
    }

It's my first time posting, and i've included attachment photos of examples showing what I mean by events being hooked up that aren't selectable but them becoming selectable after I manually add a transition event.

Hope the amount of information that's provided here should suffice.

Cheers,

Cole
Title: Re: Possible to create and set Transition events for specific State by script?
Post by: jeanfabre on April 20, 2017, 01:53:40 AM
Hi,

 yes, I am currently investigating this :) I'll get back to you when I found the way to do it.

 Bye,

 Jean
Title: Re: Possible to create and set Transition events for specific State by script?
Post by: jeanfabre on April 20, 2017, 04:07:13 AM
Hi,

 ok, you need to call EditorCommands.UpdateGraphView();

and you remove all other attemps to update or set dirty, this seems to be the only thing needed. I tested and it works full code below:

Code: [Select]
using HutongGames.PlayMaker.Actions;
using HutongGames.PlayMaker;
using HutongGames.PlayMakerEditor;
using UnityEditor;
using UnityEngine;

[CustomActionEditor(typeof(AutoSetEvents))]
public class AutoSetEventsEditor : CustomActionEditor
{

AutoSetEvents action;

public override void OnEnable()
{
base.OnEnable();
}

public override bool OnGUI()
{
action = target as AutoSetEvents;

// You can draw the full default inspector.

GUILayout.Label("Default Inspector:", EditorStyles.boldLabel);

var isDirty = DrawDefaultInspector();

// Do stuff here
if (GUILayout.Button("Set Events"))
{
GenerateEvents();
isDirty = true; // e.g., if you change action data
}
//***

// OnGUI should return true if you change action data!

return isDirty || GUI.changed;
}

// Create and add events to FSM
// Create and add Transition to current state
public void GenerateEvents()
{

PlayMakerFSM myFsm = action.Fsm.FsmComponent;
bool transitionExists = false;

if (myFsm != null)
{

FsmEditor.SelectFsm(myFsm.Fsm);

for (int i = 0; i < action.events.Length; i++) {
FsmEvent fsmEvent = new FsmEvent(action.events[i].Value);
FsmEditor.Builder.AddEvent(myFsm.Fsm, fsmEvent);

for (int j = 0; j < action.State.Transitions.Length; j++)
{
if(action.State.Transitions[j].FsmEvent.Name.Equals(fsmEvent.Name))
{
transitionExists = true;
break;
}
}

if(!transitionExists)
{
FsmTransition fsmTransition = FsmEditor.Builder.AddTransition(action.State, "", fsmEvent);

}

transitionExists = false;
}


EditorCommands.UpdateGraphView();

}

}
}


 Bye,

 Jean
Title: Re: Possible to create and set Transition events for specific State by script[SOLVE]
Post by: azevedco on April 20, 2017, 01:49:41 PM
That's perfect, thank you very much Jean!
Title: Re: Possible to create / set Transition events for specific State by script[SOLVED]
Post by: jeanfabre on April 21, 2017, 01:47:06 AM
Hi,

 You are welcome, can't wait to see what you are going to do with this :) I may also start doing some auto setup for complex actions with many events like iteration, xml etc, where you always need the same kind of transitions. Could really speed up workflow.

 Bye,

 Jean