playMaker

Author Topic: Possible to create / set Transition events for specific State by script[SOLVED]  (Read 1690 times)

azevedco

  • Playmaker Newbie
  • *
  • Posts: 2
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, 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
« Last Edit: April 20, 2017, 01:51:11 PM by azevedco »

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Hi,

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

 Bye,

 Jean

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
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

azevedco

  • Playmaker Newbie
  • *
  • Posts: 2
That's perfect, thank you very much Jean!

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
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