playMaker

Author Topic: Inter FSM event list and FSM -> Message with method call please?  (Read 16334 times)

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Inter FSM event list and FSM -> Message with method call please?
« on: November 23, 2012, 05:14:05 AM »
We are starting to use a lot of FSMs and it sometimes takes quite a while to find which FSM triggered an event in another FSM. In the events window you can see how many times an event is used. It would be great to expand that and see which FSM/State/Action uses it so we can quickly zoom into what has been set up.

It would also be great to do something similar for method calls (i.e. where a state has an action that uses Send Message to call a method) because I sometimes want to drill down to who is calling a given method.

I am guessing that both of these should be fairly straight forward, can we have them please please please? Or perhaps I'm missing something that's already there (I'm using 1.4.3f5) ?

If you really want to go to town with it you could show all the FSMs with state->events radiating out to the other FSM/states with event lines or something cool & visual. But a small tweak to see where the events are going from the existing event window would be great too.

Alex Chouls

  • Administrator
  • Hero Member
  • *****
  • Posts: 3987
  • Official Playmaker Support
    • LinkedIn
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #1 on: November 23, 2012, 05:59:23 PM »
There are some things you can do right now:

You can right click on the event to jump to states that use it.

You can use the FSM Log to follow events by clicking on the Sent By and Target log entries.

Have you tried playing with these features?

But I agree you can never have enough tools for this kind of detective work! I'd love to make a fully visual scene explorer like you describe!

This is definitely an area I want to expand on...


KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #2 on: November 26, 2012, 04:18:02 AM »
I'd not noticed that you could right click and to see where an event is coming in from an FSM/state so that is a great help, thank you for pointing it out to me.  :)

I found that this only picks up on things sent by an FSM (I think), which is understandable. I frequently have lots of events sent to FSMs from scripts and, as the object type I'm calling SendEvent on ends up being from an FSM object (of course), I should think it's viable to pick up on that. I appreciate this this would be perhaps quite involved as I normally pass the string event name to a function that checks the FSM exists etc. before trying to send it (so sifting through all the layers would perhaps be involved)... but it sure would be handy. This also goes back to another posting I made wanting to refer to event names via a Playmaker mechanism for maintainability rather than a string in the inspector (as this would also assist you in displaying that the event is used more widely than just from FSMs in the event window).

Also! How about method calls? It would perhaps be fairly easy to list all the SendMessage calls so you could, (say, in coding utopia), click on the method call & go to the script (but just listing all the method calls sorted (say) A-Z by method name showing host FSM/state would help).

I hope you can put something in along these lines sometime, it would be a great help as projects grow & we find more ways that we can use Playmaker.

Alex Chouls

  • Administrator
  • Hero Member
  • *****
  • Posts: 3987
  • Official Playmaker Support
    • LinkedIn
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #3 on: November 26, 2012, 10:27:53 AM »
Actually a lot of the Playmaker Editor GUI methods are public.

So for example you should be able to do this:

Code: [Select]
fsmEvent = FsmEditorGUILayout.EventPopup(label, FsmEvent.EventList, fsmEvent);
Where fsmEvent is of type FsmEvent.

FsmEvent.EventList contains all the events in the project.

But there are utility methods for getting other lists. E.g.:

Code: [Select]
FsmEditorUtility.GetEventList(targetFsm)
Rememember this:

Code: [Select]
using HutongGames.PlayMakerEditor;
Then you can poke around with code completion...

NOTE: I haven't tried using these outside of Playmaker! Use at your own risk - the editor API is not officially supported!

Actually, it would be cool to use the new PropertyDrawers in Unity 4 to make custom PropertyDrawers for FsmEvent and other FSM variables. So you'd get the same UI you get in Playmaker to edit these in your own scripts! Hmmm....
« Last Edit: November 26, 2012, 10:31:00 AM by Alex Chouls »

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #4 on: December 04, 2012, 12:03:06 PM »
OK, Here's a free mini tool to help with this. I have it generating a very basic list of what I wanted to see. It would be easy for someone to do something far more pretty if they have some time.

I hope that you folks at Playmaker can take this under your wing and I bet you can really make the tool sing with some tweaks (I just don't have the time). Or do something much better than this.

There are just 2 files, follow the instructions for where to put them etc. in the code comments.

PlayMakerCommsToolEditor.cs
Code: [Select]
using UnityEngine;
using System.Collections;

using UnityEditor;

// Show SendEvent and SendMessage actions in FSMs so you can track down what's going on in multi-FSM designs more easily.
// Put the PlayMakerCommsTool.cs script in with your normal code (NOT in the Assets/Editor directory).
// Put the PlayMakerCommsToolEditor in the Assets/Editor directory.
//
// To use:
// Once the code is in the right place you will find a new menu item "Comm Tool" under
// the Playmaker menu. Click this, you only need to do it once in a scene. Then when
// you want to see the details for SendEvent and SendMessage select the
// "PlayMakerCommsTool" from the Hierarchy and then in the inspector click the
// "Re-output Playmaker Comms (to Console)" button. Now you should see a new entry
// added to the Console, click it to get more detail. If you change stuff and want
// to see the detail just click the button again. You can delete the PlayMakerCommsTool
// object from your Hierarchy when finished.

[CustomEditor (typeof (PlayMakerCommsTool))]
public class PlayMakerCommsToolEditor : Editor {
[MenuItem ("PlayMaker/Comm Tool")]
static void Create(){
GameObject gameObject = new GameObject("PlayMakerCommsTool");
PlayMakerCommsTool s = gameObject.AddComponent<PlayMakerCommsTool>();
s.Rebuild();
}

public override void OnInspectorGUI ()
{
PlayMakerCommsTool obj;

obj = target as PlayMakerCommsTool;

if (obj == null)
{
return;
}

base.DrawDefaultInspector();
EditorGUILayout.BeginHorizontal ();

// Rebuild the comms lines when user click the Rebuild button
if (GUILayout.Button("Re-output Playmaker Comms (to Console)")){
obj.Rebuild();
}
EditorGUILayout.EndHorizontal ();
}
}

PlayMakerCommsTool.cs
Code: [Select]
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using HutongGames.PlayMaker;

// Show SendEvent and SendMessage actions in FSMs so you can track down what's going on in multi-FSM designs more easily.
// Put the PlayMakerCommsTool.cs script in with your normal code (NOT in the Assets/Editor directory).
// Put the PlayMakerCommsToolEditor in the Assets/Editor directory.
//
// To use:
// Once the code is in the right place you will find a new menu item "Comm Tool" under
// the Playmaker menu. Click this, you only need to do it once in a scene. Then when
// you want to see the details for SendEvent and SendMessage select the
// "PlayMakerCommsTool" from the Hierarchy and then in the inspector click the
// "Re-output Playmaker Comms (to Console)" button. Now you should see a new entry
// added to the Console, click it to get more detail. If you change stuff and want
// to see the detail just click the button again. You can delete the PlayMakerCommsTool
// object from your Hierarchy when finished.


public class PlayMakerCommsTool : MonoBehaviour {

public bool ShowSendMessage = true;
public string FilterMethodName = "";
public bool ShowSendEvent = true;
public bool ShowEventAndMessagesTogether = false;
public string FilterStateName = "";
public string FilterFsmName = "";

public void Rebuild(){
// An array of all FSMs
PlayMakerFSM [] fsms = FindObjectsOfType(typeof(PlayMakerFSM)) as PlayMakerFSM[];

if (fsms != null)
{
string results;
results = "PlayMakerCommsTool: " + fsms.Length + " FSMs found. CLICK THIS in top panal to expand in bottom panal.\n";

foreach(PlayMakerFSM fsm in fsms)
{
if ((FilterFsmName.Length > 0) && (fsm.name != FilterFsmName)) continue;

for (int s = 0; s<fsm.FsmStates.Length; ++s)
{
if ((FilterStateName.Length > 0) && (fsm.FsmStates[s].Name != FilterStateName)) continue;

if (ShowEventAndMessagesTogether == true)
{
foreach(FsmStateAction action in fsm.FsmStates[s].Actions)
{
if ((ShowSendEvent == true) && (action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendEvent)))
{
results += "SendEvent " + fsm.ToString() + " State " + fsm.FsmStates[s].Name + "\n";
}

if ((ShowSendMessage == true) && (action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendMessage)))
{
HutongGames.PlayMaker.Actions.SendMessage sm = (HutongGames.PlayMaker.Actions.SendMessage)(action);
string funcName = sm.functionCall.FunctionName;

if ((FilterMethodName.Length > 0) && (FilterMethodName != funcName)) continue;

results += "SendMessage " + fsm.ToString() + " State " + fsm.FsmStates[s].Name + " call method " + funcName + "\n";
}
}
}
else
{
if (ShowSendEvent == true)
{
foreach(FsmStateAction action in fsm.FsmStates[s].Actions)
{
if (action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendEvent))
{
results += "SendEvent " + fsm.ToString() + " State " + fsm.FsmStates[s].Name + "\n";
}
}
}

if (ShowSendMessage == true)
{
foreach(FsmStateAction action in fsm.FsmStates[s].Actions)
{
if (action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendMessage))
{
HutongGames.PlayMaker.Actions.SendMessage sm = (HutongGames.PlayMaker.Actions.SendMessage)(action);
string funcName = sm.functionCall.FunctionName;

if ((FilterMethodName.Length > 0) && (FilterMethodName != funcName)) continue;

results += "SendMessage " + fsm.ToString() + " State " + fsm.FsmStates[s].Name + " call method " + funcName + "\n";
}
}
}
}
}
}
if (FilterMethodName.Length > 0) results += "Filter Method Name = " + FilterMethodName + "\n";
if (FilterStateName.Length > 0) results += "Filter State Name = " + FilterStateName + "\n";
if (FilterFsmName.Length > 0) results += "Filter FSM Name = " + FilterFsmName + "\n";
Debug.Log(results);
}
else
{
Debug.Log("PlayMakerCommsTool: No FSMs found");
}
}
}

Tested in Unity 3.5.6f4 with Playmaker 1.4.3f5

Enjoy  :)

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #5 on: December 05, 2012, 10:21:29 AM »
OK, I've been trying to improve things a bit (with a windowed version) which I thought I'd done and then I tried it in project with lots of FSMs and where I found that I then have a problem where stuff is not initialised. Due to that, I put this line of code in place:

Code: [Select]
if (fsm.FsmStates[s].IsInitialized == true)
before doing this:

Code: [Select]
int numActions = fsm.FsmStates[s].Actions.Length;
The top line of code stopped the problems in that second line of code but then when I went back I found that I got no results because the top line is always returning false.

I'd put that top line in because where as I wasn't getting problems in the initial project I did with the larger project. In the small project it does not seem to matter that things are not initialized. How should I be getting the actions for a given state please (i.e. in a way that they will be initialized etc.)?

Thank you.

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #6 on: December 05, 2012, 11:40:25 AM »
OK, things seem to be fine now.

The tool now pops a window up with quick refresh filters etc. and you can also get the output in the console still by pressing the inspector button (when you have the PlayMakerCommsTool object selected).

If you get errors when you start the tool, close the window it pops up, start the Playmaker editor (from the Playmaker menu) and then try again.

I have moved the tool so it's now under the Playmaker->Tools menu as "Windowed Comm Tool".

There are now 3 files, 2 go in the Assets/Editor folder and the other not in there but some place you like to stick scripts under Assets.

Put this somewhere under Assets (but NOT the Editor folder).
You have to call it "PlayMakerCommsTool.cs"
Code: [Select]
using UnityEngine;
using System.Collections;
using System.Collections.Generic;
using HutongGames.PlayMaker;

// Show SendEvent and SendMessage actions in FSMs so you can track down what's going on in multi-FSM designs more easily.
// Put the PlayMakerCommsTool.cs script in with your normal code (NOT in the Assets/Editor directory).
// Put the PlayMakerCommsToolEditor and PlayMakerCommsToolWindow in the Assets/Editor directory.
//
// To use:
// Once the code is in the right place you will find a new menu item "Comm Tool Window" under
// the Playmaker Tools menu. Click this, you only need to do it once in a scene. Then when
// you want to see the details for SendEvent and SendMessage select the
// "PlayMakerCommsTool" from the Hierarchy and then in the inspector click the
// "Re-output Playmaker Comms (to Console)" button. Now you should see a new entry
// added to the Console, click it to get more detail. If you change stuff and want
// to see the detail just click the button again. You can delete the PlayMakerCommsTool
// object from your Hierarchy when finished.


public class PlayMakerCommsTool : MonoBehaviour {

public bool ShowSendMessage = true;
public string FilterMethodName = "";
public bool ShowSendEvent = true;
public bool EventMessageTogether = false;
public string FilterStateName = "";
public string FilterFsmName = "";

// Results in a crude string form
private string results;

// Results in a list - if you want to stick them in a nice tree control or something.
public List<PlaymakerCommsEntry> commsList = null;

[HideInInspector]
public int numFsms = 0;

public void Rebuild(bool showInConsole){
// An array of all FSMs
PlayMakerFSM [] fsms = FindObjectsOfType(typeof(PlayMakerFSM)) as PlayMakerFSM[];
commsList = null;
numFsms = 0;

if (fsms != null)
{
results = "PlayMakerCommsTool: " + fsms.Length + " FSMs found. CLICK THIS in top panel to expand in bottom panel.\n";

commsList = new List<PlaymakerCommsEntry>();

numFsms = fsms.Length;
int ourFsmIndex = 0;
foreach(PlayMakerFSM fsm in fsms)
{
if ((FilterFsmName.Length > 0) && (fsm.name.Contains(FilterFsmName) == false)) continue;

if (fsm.FsmStates != null) fsm.FsmStates.Initialize();

for (int s = 0; s<fsm.FsmStates.Length; ++s)
{
if ((FilterStateName.Length > 0) && (fsm.FsmStates[s].Name.Contains(FilterStateName) == false)) continue;

if (EventMessageTogether == true)
{
// Show SendEvent and SendMessage as we find them
foreach(FsmStateAction action in fsm.FsmStates[s].Actions)
{
if (ShowSendEvent == true) HandleSendEvent(ourFsmIndex, fsm, fsm.FsmStates[s], action);
if (ShowSendMessage == true) HandleSendMessage(ourFsmIndex, fsm, fsm.FsmStates[s], action);
}
}
else
{
// Show the SendEvent and then the SendMessage text
if (ShowSendEvent == true)
{
int numActions = fsm.FsmStates[s].Actions.Length;
for (int actionNum=0; actionNum < numActions; ++actionNum)
{
//foreach(FsmStateAction action in fsm.FsmStates[s].Actions) HandleSendEvent(ourFsmIndex, fsm, fsm.FsmStates[s], action);
HandleSendEvent(ourFsmIndex, fsm, fsm.FsmStates[s], fsm.FsmStates[s].Actions[actionNum]);
}
}

if (ShowSendMessage == true)
{
foreach(FsmStateAction action in fsm.FsmStates[s].Actions) HandleSendMessage(ourFsmIndex, fsm, fsm.FsmStates[s], action);
}
}
}
++ourFsmIndex;
}

// Show what filters affected the output
if (FilterMethodName.Length > 0) results += "Filter Method Name = " + FilterMethodName + "\n";
if (FilterStateName.Length > 0) results += "Filter State Name = " + FilterStateName + "\n";
if (FilterFsmName.Length > 0) results += "Filter FSM Name = " + FilterFsmName + "\n";
if ((ShowSendMessage == false) && (ShowSendEvent == false)) results += "Unable to show anything useful with both ShowSendMessage false and ShowSendEvent false!\n";
if (showInConsole == true)
{
Debug.Log(results);
}
}
else
{
if (showInConsole == true)
{
Debug.Log("PlayMakerCommsTool: No FSMs found");
}
}
}

private void HandleSendMessage(int ourFsmIndex, PlayMakerFSM fsm, FsmState state, FsmStateAction action)
{
if (action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendMessage))
{
HutongGames.PlayMaker.Actions.SendMessage sm = (HutongGames.PlayMaker.Actions.SendMessage)(action);
string funcName = sm.functionCall.FunctionName;
GameObject targetGO = sm.Fsm.GetOwnerDefaultTarget(sm.gameObject);
string gameObjectName = ((targetGO != null) ? targetGO.name : "UNKNOWN");

if ((FilterMethodName.Length > 0) && (funcName.Contains(FilterMethodName) == false)) return;

results += "SendMessage " + fsm.ToString() + " State " + state.Name + " calls method " + funcName + " on GameObject " + gameObjectName +"\n";

commsList.Add(new PlaymakerCommsEntry(ourFsmIndex, fsm, state, action));
}
}

private void HandleSendEvent(int ourFsmIndex, PlayMakerFSM fsm, FsmState state, FsmStateAction action)
{
if (action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendEvent))
{
HutongGames.PlayMaker.Actions.SendEvent se = (HutongGames.PlayMaker.Actions.SendEvent)(action);
results += "SendEvent " + fsm.ToString() + " State " + state.Name + " sends " + se.sendEvent.Name +
" to (FSM called) " + se.eventTarget.fsmName +
" on GameObject " + se.eventTarget.gameObject.GameObject.ToString() +
"\n";
commsList.Add(new PlaymakerCommsEntry(ourFsmIndex, fsm, state, action));
}
}
}

public class PlaymakerCommsEntry
{
public bool showMyFsm = true;
public bool showMyState = true;
public bool showMe = true;
public int ourFsmIndex = 0;
public PlayMakerFSM fsm;
public FsmState state;
public FsmStateAction action;

public PlaymakerCommsEntry(int anFsmIndex, PlayMakerFSM an_fsm, FsmState a_state, FsmStateAction an_action)
{
showMe = showMyState = showMyFsm = true;
ourFsmIndex = anFsmIndex;
fsm = an_fsm;
state = a_state;
action = an_action;
}
}

Put this in the Assets/Editor folder.
You have to call the file "PlayMakerCommsToolEditor.cs"
Code: [Select]
using UnityEngine;
using System.Collections;

using UnityEditor;

// Show SendEvent and SendMessage actions in FSMs so you can track down what's going on in multi-FSM designs more easily.
// Put the PlayMakerCommsTool.cs script in with your normal code (NOT in the Assets/Editor directory).
// Put the PlayMakerCommsToolEditor and PlayMakerCommsToolWindow in the Assets/Editor directory.
//
// To use:
// Once the code is in the right place you will find a new menu item "Comm Tool Window" under
// the Playmaker Tools menu. Click this, you only need to do it once in a scene. Then when
// you want to see the details for SendEvent and SendMessage select the
// "PlayMakerCommsTool" from the Hierarchy and then in the inspector click the
// "Re-output Playmaker Comms (to Console)" button. Now you should see a new entry
// added to the Console, click it to get more detail. If you change stuff and want
// to see the detail just click the button again. You can delete the PlayMakerCommsTool
// object from your Hierarchy when finished.

[CustomEditor (typeof (PlayMakerCommsTool))]
public class PlayMakerCommsToolEditor : Editor {
static void Create(){
GameObject gameObject = new GameObject("PlayMakerCommsTool");
PlayMakerCommsTool s = gameObject.AddComponent<PlayMakerCommsTool>();
s.Rebuild(true);
}

public override void OnInspectorGUI ()
{
PlayMakerCommsTool obj;

obj = target as PlayMakerCommsTool;

if (obj == null)
{
return;
}

base.DrawDefaultInspector();
EditorGUILayout.BeginHorizontal ();

// Rebuild the comms lines when user click the Rebuild button
if (GUILayout.Button("Re-output Playmaker Comms (to Console)")){
obj.Rebuild(true);
}
EditorGUILayout.EndHorizontal ();
}

}

Put this in the Assets/Editor folder too.
You have to call this file "PlayMakerCommsToolWindow".
Code: [Select]
using UnityEngine;
using UnityEditor;

// Show SendEvent and SendMessage actions in FSMs so you can track down what's going on in multi-FSM designs more easily.
// Put the PlayMakerCommsTool.cs script in with your normal code (NOT in the Assets/Editor directory).
// Put the PlayMakerCommsToolEditor and PlayMakerCommsToolWindow in the Assets/Editor directory.
//
// To use:
// Once the code is in the right place you will find a new menu item "Comm Tool Window" under
// the Playmaker Tools menu. Click this, you only need to do it once in a scene. Then when
// you want to see the details for SendEvent and SendMessage select the
// "PlayMakerCommsTool" from the Hierarchy and then in the inspector click the
// "Re-output Playmaker Comms (to Console)" button. Now you should see a new entry
// added to the Console, click it to get more detail. If you change stuff and want
// to see the detail just click the button again. You can delete the PlayMakerCommsTool
// object from your Hierarchy when finished.

public class PlayMakerCommsToolWindow : EditorWindow
{

static PlayMakerCommsTool pmCommsTool = null;

// So we can compare to PlayMakerCommsTool
public bool ShowSendMessage = true;
public string FilterMethodName = "";
public bool ShowSendEvent = true;
public bool EventMessageTogether = false;
public string FilterStateName = "";
public string FilterFsmName = "";

// Add menu named "My Window" to the Window menu
[MenuItem ("PlayMaker/Tools/Windowed Comm Tool")]
static void Init ()
{
// Get existing open window or if none, make a new one:
PlayMakerCommsToolWindow window = (PlayMakerCommsToolWindow)EditorWindow.GetWindow (typeof (PlayMakerCommsToolWindow));

if (pmCommsTool == null)
{
pmCommsTool = FindObjectOfType(typeof(PlayMakerCommsTool)) as PlayMakerCommsTool;
if (pmCommsTool == null)
{
GameObject gameObject = new GameObject("PlayMakerCommsTool");
pmCommsTool = gameObject.AddComponent<PlayMakerCommsTool>();
}
}
pmCommsTool.Rebuild(true);
}

// Scroll position
Vector2 scrollPos = Vector2.zero;
void OnGUI ()
{
if (pmCommsTool == null) return;

if ((pmCommsTool.commsList == null) || (pmCommsTool.commsList.Count == 0))
{
GUILayout.Label ("Nothing to show? MAKESURE YOU START Playmaker, from the menu: PlayMaker->Playmaker Editor", EditorStyles.boldLabel);
GUILayout.Label ("Remember; Filters are case sensitive.", EditorStyles.boldLabel);
}

GUILayout.Label ("Playmaker Comms", EditorStyles.boldLabel);

// Remember what was set
ShowSendMessage = pmCommsTool.ShowSendMessage;
FilterMethodName = pmCommsTool.FilterMethodName;
ShowSendEvent = pmCommsTool.ShowSendEvent;
EventMessageTogether = pmCommsTool.EventMessageTogether;
FilterStateName = pmCommsTool.FilterStateName;
FilterFsmName = pmCommsTool.FilterFsmName;


pmCommsTool.FilterFsmName =  EditorGUILayout.TextField ("Filter FSM Name (optional)", pmCommsTool.FilterFsmName);
pmCommsTool.FilterStateName =  EditorGUILayout.TextField ("Filter State Name (optional)", pmCommsTool.FilterStateName);

pmCommsTool.ShowSendMessage = EditorGUILayout.Toggle ("Show Send Message", pmCommsTool.ShowSendMessage);
if (pmCommsTool.ShowSendMessage == true)
{
pmCommsTool.FilterMethodName =  EditorGUILayout.TextField ("Filter Method Name (optional)", pmCommsTool.FilterMethodName);
}
pmCommsTool.ShowSendEvent = EditorGUILayout.Toggle ("Show Send Event", pmCommsTool.ShowSendEvent);
pmCommsTool.EventMessageTogether = EditorGUILayout.Toggle ("Event & Messages together", pmCommsTool.EventMessageTogether);

// Did something change?
bool changed = (
(ShowSendMessage != pmCommsTool.ShowSendMessage) ||
(FilterMethodName != pmCommsTool.FilterMethodName) ||
(ShowSendEvent != pmCommsTool.ShowSendEvent) ||
(EventMessageTogether != pmCommsTool.EventMessageTogether) ||
(FilterStateName != pmCommsTool.FilterStateName) ||
(FilterFsmName != pmCommsTool.FilterFsmName)
);

if (changed)
{
pmCommsTool.Rebuild(false);
}
else
{
if ((pmCommsTool.ShowSendEvent == false) && (pmCommsTool.ShowSendMessage == false))
{
GUILayout.Label ("Nothing useful to show if you set both SendMessage & SendEvent false!", EditorStyles.boldLabel);
}
else
if (GUILayout.Button("Re-generate Playmaker communication data (inc to Console)")){
pmCommsTool.Rebuild(true);
}
}

// The position of the window
Rect windowRect = new Rect(0,0, Screen.width, Screen.height);
// Set up a scroll view
scrollPos = GUI.BeginScrollView (
new Rect(0, 160, position.width, position.height), // NOTE; Magic number for Rect.top in use to position the data, TODO: get the actual position of where there is space below the GUI items all ready put in.
scrollPos,
new Rect (0, 0, 1000, 100000), // TODO: set vertical scroll bar based on size of window it controls!
true,
true
);
// Same code as before - make a window. Only now, it's INSIDE the scrollview
BeginWindows ();
windowRect = GUILayout.Window (1, windowRect, DoWindow, pmCommsTool.numFsms + " FSMs enabled in scene");
EndWindows ();
// Close the scroll view
GUI.EndScrollView ();
}
void DoWindow(int n)
{
if ((FilterMethodName.Length > 0) || (FilterStateName.Length > 0) || (FilterFsmName.Length > 0))
{
GUILayout.Label ("Note: CASE SENSITIVE filter(s) are in use.", EditorStyles.boldLabel);
EditorGUILayout.Space();
}

if ((pmCommsTool.ShowSendEvent == true) && (pmCommsTool.ShowSendMessage == true))
GUILayout.Label ("Only FSMs with a SendMessage or SendEvent here:", EditorStyles.boldLabel);
else
{
if (pmCommsTool.ShowSendEvent == true)
GUILayout.Label ("Only FSMs with a SendEvent action are here:", EditorStyles.boldLabel);
else
if (pmCommsTool.ShowSendMessage == true)
GUILayout.Label ("Only FSMs with a SendMessage action are here:", EditorStyles.boldLabel);
}


int currentFsmIndex = -1;
for (int i=0; i<pmCommsTool.commsList.Count; ++i)
{
if (pmCommsTool.commsList[i].ourFsmIndex > currentFsmIndex)
{
currentFsmIndex = pmCommsTool.commsList[i].ourFsmIndex;

EditorGUILayout.Space();
GUILayout.Label ("(FSM name)= " + pmCommsTool.commsList[i].fsm.name, EditorStyles.boldLabel);

pmCommsTool.commsList[i].showMyFsm = EditorGUILayout.Toggle (
"Show this FSM?",
pmCommsTool.commsList[i].showMyFsm);

if (pmCommsTool.commsList[i].showMyFsm == true)
{
GUILayout.Label ("States with entry:-", EditorStyles.label);
string state = "";
bool showState = true;
for (int ii=i; ii<pmCommsTool.commsList.Count; ++ii)
{
if (pmCommsTool.commsList[ii].ourFsmIndex == currentFsmIndex)
{
if (state != pmCommsTool.commsList[ii].state.Name)
{
state = pmCommsTool.commsList[ii].state.Name;

showState = pmCommsTool.commsList[ii].showMyState = EditorGUILayout.Toggle (
(pmCommsTool.commsList[ii].state.Name + ":"),
pmCommsTool.commsList[ii].showMyState);
}

if (showState == true)
{
if (pmCommsTool.commsList[ii].action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendEvent))
{
HutongGames.PlayMaker.Actions.SendEvent se = (HutongGames.PlayMaker.Actions.SendEvent)(pmCommsTool.commsList[ii].action);

GUILayout.Label (
"SentEvent:" + se.sendEvent.Name +
" to (FSM called) " + se.eventTarget.fsmName +
" on GameObject " + se.eventTarget.gameObject.GameObject.ToString()
, EditorStyles.label);
}
else
if (pmCommsTool.commsList[ii].action.GetType() == typeof(HutongGames.PlayMaker.Actions.SendMessage))
{
HutongGames.PlayMaker.Actions.SendMessage sm = (HutongGames.PlayMaker.Actions.SendMessage)(pmCommsTool.commsList[ii].action);
string funcName = sm.functionCall.FunctionName;
GameObject targetGO = sm.Fsm.GetOwnerDefaultTarget(sm.gameObject);
string gameObjectName = ((targetGO == null) ? "UNKNOWN NAME" : targetGO.name);

GUILayout.Label (
"SendMessage to GameObject " + gameObjectName +
" method=" + funcName
, EditorStyles.label);
}
}
}
else
{
i = ii-1;
break;
}
}
}
}
}
}
}

I hope you like it and if you don't, feel free to fix / improve stuff.

 :)

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #7 on: December 05, 2012, 11:53:43 AM »
The one thing I forgot was to update the "To use" bit in the comments. Now there's a window you don't need to fiddle about so much and it will be clearer what to do (I hope).

I guess that the "To use" section should be something like:
Code: [Select]
// To use:
// Once the code is in the right place you will find a new menu item "Comm Tool Window" under
// the Playmaker -> Tools menu. Click this, you only need to do it once in a scene.
// You can delete the PlayMakerCommsTool object from your Hierarchy when finished.

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #8 on: December 06, 2012, 04:35:26 AM »
I have now modified the tool so that you can also filter on target FSM and target Event (i.e. from SendEvent use).

If anyone is wanting updates let me know and I will put them here (or say where to get them) but perhaps no one else has found a use for this tool yet. If you start using lots of FSMs that talk to eachother or to scripts then you might find this is just the ticket when you're scratching your head wondering how something happened & you know you set something up somewhere (or someone else on your team did) but now it's lost & your alternative is going through every FSM, State and Action hoping that you don't miss it.

I was kind of hoping I could pass this on to you guys at Hutong Games because other wise there's always the potential maintenance issue when you do an update & I'm obviously wanting to use Playmaker to save me time & don't want to add to my workload... so if you want to take it, it's yours, (let me know & I will provide the latest - it would be easy for you to make far nicer), if not, perhaps you can point to any issues you perceive in how I'm digging the information out.

I've currently tested this on Unity V3.5.6f4 (pro) and V4.0.1 (free) both with Playmaker V1.4.3f5 and I suspect the only issue that you may get is if you have not run the Playmaker editor before you start the tool, (in which case close the Comms Tool window, start the Playmaker editor (from the menu) and then start this tool again). I'd test it on the latest Playmaker but have to wait for work to be ready to try it!

Thanks.

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #9 on: December 06, 2012, 05:46:32 AM »
Oh, now I've added a target game object filter too. Let me know if you want it  :)

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #10 on: December 06, 2012, 10:37:16 AM »
Even more! I've now added ActivateGameObject as that obviously targets stuff beyond the FSM that can have quite an effect.

The Above tests were all on PC. I've now tested on a Mac too and it seems fine although the window is initially a tad too small, just resize it.

Let me know if you would like the scripts because I'm wondering if I'm just talking to myself  ;)

Alex Chouls

  • Administrator
  • Hero Member
  • *****
  • Posts: 3987
  • Official Playmaker Support
    • LinkedIn
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #11 on: December 06, 2012, 11:47:28 AM »
Wow! These seem excellent! I haven't had a chance to play with them yet, but I'd love to host this on the playmaker addons wiki... Are you interested in access to this wiki?

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #12 on: December 06, 2012, 01:58:02 PM »
Hi Alex,

I don't know that I will have any more time at the moment for the Wiki etc. I'm already working a full working week, other stuff at weekends and all evenings! I have placed some comments in the files and the "read me" to explain the basics.

New stuff in since my last post, I now fire up the Playmaker editor if it's not already open. This gets Playmaker initialised but perhaps there's a better way.

Here is the latest version (attached). It would be great if you are able to offer them to folks (so this way I know when I get a new Playmaker version it will be one less thing for me to integrate if you've done it...  ;D )! I think you could easily go way beyond what I've done. I did wonder about a more generic access to the Actions so that all actions could be supported without coding something special for each one... but I doubt I'll find any more time.

Zipped up scripts with a read me attached.

[Warning; begging ahead  ::) ] If you think this is a worthwhile effort, I could always use a full Playmaker licence for home too (let me know & I'll give you a different email etc. if that's what I'd need to do) as I only have it at work so far  :'( and that's fine if you don't want to do that too. If you are able to take on maintenance of this tool that would be nice and everyone's a winner.

Anyway, I hope it helps folks out. We've aleady used it on 3 of our larger projects to check stuff or find things we needed to fix and I think it helps everyone out, including me and our less technical designers who can also have more confidence to do much more complicated stuff & not worry so much about getting lost in it all when something does not behave. Another bonus is that when I pick up a broken project I can get to the bottom of what someone else has been doing in less time.

Like I say, you could go way beyond what I've done. I imagine a nice graphical thing like the Playmaker Editor with filters... I was tempted to recreate something in the scene but... time!

KJIB

  • Playmaker Newbie
  • *
  • Posts: 20
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #13 on: January 04, 2013, 07:39:13 AM »
I notice that (although I thought I'd fixed it) you still need to have used Playmaker to view an FSM before my script can generate anything useful for you. This is a minor inconvinience so you can still use the tool now but I'd like to fix it.

What should I call in Playmaker (from my tool) so that the user does not need to do anything?

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: Inter FSM event list and FSM -> Message with method call please?
« Reply #14 on: January 07, 2013, 02:38:15 AM »
Hi,

 Nice one! It's a very very good start (still a bit rough on the interface, but these things are ver difficult to design properly indeed :) ) , I have made an entry in the wiki, it's not only very useful as is, but it's also good to study your code for getting acquainted with PlayMaker API

https://hutonggames.fogbugz.com/default.asp?W714
https://hutonggames.fogbugz.com/default.asp?W1026

I made it as a package, instead of a zip, which is the preferred way with Unity, a lot easier to get in the project Assets.

 Bye,

 Jean