playMaker

Author Topic: send FSM.Event() + SetEventData() from script?  (Read 4686 times)

Andy22

  • Junior Playmaker
  • **
  • Posts: 99
send FSM.Event() + SetEventData() from script?
« on: October 15, 2013, 06:48:38 AM »
Hi,

i wonder if i can directly combine the "allowed" SendEvent(name) and SetEventData action logic, to fire a FSM event from script and hand over data?

The fsm.EventData field looks a bit "scary", since its static and has some sendfromxy fields and the SetEventDataSentByInfo() cant be fully emulated from script, since only the fsm is known?

So what would be the correct way to fire a FSM event with custom data?

I also wonder what the correct way is to fire a global FSM event? The problem is that only FsmEventTarget/FsmEvent have the needed "Broadcast ALL" logic to handle this. Is there some kind of script accessible wrapper call or do i have to write my own?

Atm i try to unify/wrap some of our used event systems, since atm we use FSM events, UFPS vp_globalEvent, UFPS vp_Event, Unity Messages.... things start to get out of hand just so the different parts can communicate aka. send events to each other. In principle each system pretty much does the same, define a eventname/name field and a user datatype. The problem is each system used a different delivery/setup.

Thx Andy

« Last Edit: October 15, 2013, 06:51:30 AM by Andy22 »

Alex Chouls

  • Administrator
  • Hero Member
  • *****
  • Posts: 4002
  • Official Playmaker Support
    • LinkedIn
Re: send FSM.Event() + SetEventData() from script?
« Reply #1 on: October 15, 2013, 09:29:35 AM »
There are public BroadcastEvent methods in Fsm:

Code: [Select]
public void BroadcastEvent(string fsmEventName, bool excludeSelf = false)

public void BroadcastEvent(FsmEvent fsmEvent, bool excludeSelf = false)

public void BroadcastEventToGameObject(GameObject go, string fsmEventName, bool sendToChildren, bool excludeSelf = false)

public void BroadcastEventToGameObject(GameObject go, FsmEvent fsmEvent, FsmEventData eventData, bool sendToChildren, bool excludeSelf = false)

If you are going to send an event often, you might consider getting a reference to the FsmEvent instead of using a string event name. In FsmEvent:

Code: [Select]
public static FsmEvent GetFsmEvent(string eventName)
As for setting EventData, right now you have to set the static fsm.EventData field before sending events. See the Set Event Data action for an example. I'd like to improve the API for this at some point...

Hope this helps!


Andy22

  • Junior Playmaker
  • **
  • Posts: 99
Re: send FSM.Event() + SetEventData() from script?
« Reply #2 on: October 15, 2013, 10:22:28 AM »
Yep this helps, at least i did not overlook some SetData() call.

Now i'm trying to make the global FSM events accessible to script, means to the vp_GlobalEvent system. vp/UFPS uses the Register/UnRegister + delegate way and i'm thinking of using some wrapper + string prefix/postfix.

Basically on gamestart register all global Playmaker events as "Eventname"+"_FSM" at the normal vp_GlobalEvent system and use a static callback to handle the PlayMakerFSM.BroadcastEvent() call? The wrapper would also handle the vp_GlobalEvent<T>.Send() cases for data.

Basically i need a easy way to communicate from script to FSM's without extra setup and "emulating" global/local FSM events + data seems a good way to do this, since the FSM itself does not need any special knowledge that the event was send from elsewhere.

any other ideas?

bye Andy
« Last Edit: October 15, 2013, 10:25:24 AM by Andy22 »

Andy22

  • Junior Playmaker
  • **
  • Posts: 99
Re: send FSM.Event() + SetEventData() from script?
« Reply #3 on: October 15, 2013, 12:54:20 PM »
Here is the local SendFSMEvent<T> data version as extension method for Gameobject.
Note: I set the gameobject sender automatically out of convenience, if the data is free.

Code: [Select]
#region GameObjectExtensions

public static class GameObjectExtensions
{
private enum TypeCodeExt
{
Unknown,
Vector2,
Vector3,
Quaternion,
Color,
Rect,
UnityObject,
GameObject,
Material,
Texture
}
private static readonly Dictionary<Type, TypeCodeExt> TypeDict = new Dictionary<Type, TypeCodeExt>
{
{typeof(GameObject), TypeCodeExt.GameObject},
{typeof(Object), TypeCodeExt.UnityObject},
{typeof(Vector2), TypeCodeExt.Vector2},
{typeof(Vector3), TypeCodeExt.Vector3},
{typeof(Rect), TypeCodeExt.Rect},
{typeof(Quaternion), TypeCodeExt.Quaternion},
{typeof(Color), TypeCodeExt.Color},
{typeof(Material), TypeCodeExt.Material},
{typeof(Texture), TypeCodeExt.Texture}
};

/// <summary>
///  simple wrapper to send a data event to a FSM/Childs
/// </summary>
public static void SendFsmEvent<T>(this GameObject inObj, string inEventName, T inData)
{
if (string.IsNullOrEmpty(inEventName) || Equals(inData, default(T))) {
inObj.DebugLogErrorInputs(); // check "invalid" values on T?? (string/reftype/value/nullable)
return;
}

var foundFsm = inObj.GetComponentInChildren<PlayMakerFSM>(); // TODO: searchChild and global version!
if (foundFsm == null) {
inObj.DebugLogError("Cant find a FSM on the gameobject + childs");
return;
}

TypeCode dataType = Type.GetTypeCode(typeof(T));
if (dataType == TypeCode.Object && TypeDict.ContainsKey(typeof(T))) {
TypeCodeExt extType = TypeDict[typeof(T)];

switch (extType) {
// NOTE: we need to down/up-cast all, since c# has no other way without IConvertible
case TypeCodeExt.Vector2:
Fsm.EventData.Vector2Data = (Vector2)(System.Object)inData;
break;
case TypeCodeExt.Vector3:
Fsm.EventData.Vector3Data = (Vector3)(System.Object)inData;
break;
case TypeCodeExt.Quaternion:
Fsm.EventData.QuaternionData = (Quaternion)(System.Object)inData;
break;
case TypeCodeExt.Color:
Fsm.EventData.ColorData = (Color)(System.Object)inData;
break;
case TypeCodeExt.Rect:
Fsm.EventData.RectData = (Rect)(System.Object)inData;
break;
case TypeCodeExt.UnityObject:
Fsm.EventData.ObjectData = (Object)(System.Object)inData;
break;
case TypeCodeExt.GameObject:
Fsm.EventData.GameObjectData = (GameObject)(System.Object)inData;
break;
case TypeCodeExt.Material:
Fsm.EventData.MaterialData = (Material)(System.Object)inData;
break;
case TypeCodeExt.Texture:
Fsm.EventData.TextureData = (Texture)(System.Object)inData;
break;
default:
inObj.DebugLogError("Unsupported EventDataType: " + typeof(T));
break;
}
if (extType != TypeCodeExt.GameObject) {
Fsm.EventData.GameObjectData = inObj; // NOTE: Helper we always set the senderObj here also!
}
}
else {
switch (dataType) {
case TypeCode.Boolean:
Fsm.EventData.BoolData = (bool)(System.Object)inData;
break;
case TypeCode.Int32:
case TypeCode.UInt32:
Fsm.EventData.IntData = (int)(System.Object)inData;
break;
case TypeCode.Single:
case TypeCode.Double:
Fsm.EventData.FloatData = (float)(System.Object)inData;
break;
case TypeCode.String:
Fsm.EventData.StringData = (string)(System.Object)inData;
break;
default:
inObj.DebugLogError("Unsupported EventDataType: " + typeof(T));
break;
}

Fsm.EventData.GameObjectData = inObj; // NOTE: Helper we always set the senderObj here also!
}

foundFsm.SendEvent(inEventName);
}
}

#endregion GameObjectExtensions