playMaker

Author Topic: CustomActionEditor Set FsmVar[] variable Issue [SOLVED]  (Read 5204 times)

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
CustomActionEditor Set FsmVar[] variable Issue [SOLVED]
« on: March 29, 2018, 08:33:46 AM »
Hi

I have a CustomActionEditor script and have a FsmVar[] variable which i want to populate from a script which just takes selected variable names and populates the FsmVar[] with these. I can update all other variables types but i cant seem to update FsmVar. What am i doing wrong? do i need to somehow refresh the editor when i update the FsmVar?

Here is my script where "xxxxx" is the FsmVar[].

Code: [Select]
[CustomActionEditor(typeof(PMDTAddRow))]
public class PMDTAddRowCustomEditor : CustomActionEditor
{

    public override void OnEnable()
    {

var action = target as PMDTAddRow;

                DrawDefaultInspector();

                List<string> fsmvars = new List<string>();

PlayMakerFSM[] fsms = Resources.FindObjectsOfTypeAll(typeof(PlayMakerFSM)) as PlayMakerFSM[]; //get all fsms in scene

if (fsms != null)
{
foreach (PlayMakerFSM _fsm in fsms) //fsm
{
if (_fsm.Fsm.Variables.ArrayVariables.Length > 0)
{
for (var i = 0; i < _fsm.Fsm.Variables.ArrayVariables.Length; i++)
{
if(_fsm.Fsm.Variables.ArrayVariables[i].Name.StartsWith("example"))
{
fsmvars.Add(_fsm.Fsm.Variables.ArrayVariables[i].Name);
//Debug.Log(_fsm.Fsm.Variables.ArrayVariables[i].Name);
}
}
}
}
}

if (action.xxxxx.Length != fsmvars.Count)
{
action.xxxxx = new FsmVar[fsmvars.Count];
}

for (var v = 0; v < fsmvars.Count; v++)
{

var fsmArray = action.fsmComponent.FsmVariables.GetFsmArray(fsmvars[v]);

if (fsmArray != null ) {
action.xxxxx[v].UpdateValue();
action.xxxxx[v].variableName = fsmArray.Name;
}
}
}
}
« Last Edit: May 11, 2018, 02:08:55 PM by coxy17 »

Deek

  • Full Member
  • ***
  • Posts: 133
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #1 on: March 29, 2018, 04:45:31 PM »
The first thing I noticed (and probably also the main reason for your problem), is that you don't run the main logic in OnGUI(), but in OnEnable().
I've created a template a while ago that demonstrates how to authorize a basic custom inspector, which you can find here.
In there you can also see that OnEnable() is only for resource heavy initialization, since it doesn't update as often as OnGUI().

If that doesn't help, you could try to update the individual FsmVar's with "PlayMakerUtils.ApplyValueToFsmVar()".


P.S.: FsmVar's and FsmArray's behave differently from each other FsmVariable by design: FsmVar's have to be updated before you use them (but you already seem to do that) and with FsmArray's you need to define the variable type before setting/changing variables and in a repeating action it needs to be cleared at the start, but that just as a side-note.

Also remember that any Editor-Script cannot be executed in your build, that's why you have to reference variables from the base script, because Unity only saves the values of those during runtime.

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #2 on: April 02, 2018, 06:58:28 AM »
Hi

I have tried running it in OnGUI() and have the same issue. I have tried to include PlayMakerUtils.ApplyValueToFsmVar() but i get the following error

error CS0103: The name `PlayMakerUtils' does not exist in the current context

even when i include dependencies ...
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using HutongGames.PlayMakerEditor;

all of my scripts are in a Editor folder so there is no execution issues when deployed.

But whats interesting is that if i remove my iteration and just update the FsmVar count it updates fine, even after refreshing the scene.

Code: [Select]
action.xxxxx = new FsmVar[fsmvars.Count];
it seems that the following code is the issue? ...

Code: [Select]
for (var v = 0; v < fsmvars.Count; v++)
{
var fsmArray = action.fsmComponent.FsmVariables.GetFsmArray(fsmvars[v]);

if (fsmArray != null ) {
action.xxxxx[v].UpdateValue();
action.xxxxx[v].variableName = fsmArray.Name;
}
}

« Last Edit: April 02, 2018, 07:04:03 AM by coxy17 »

Deek

  • Full Member
  • ***
  • Posts: 133
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #3 on: April 02, 2018, 03:32:11 PM »
Oh sorry, I thought PlayMakerUtils where a native thing in PlayMaker, but it rather seems to be an extension to it. You can get it from here (click on 'Clone or Download', 'Download ZIP', extract and put it in your "Assets" folder).
In there are also the helper methods "RefreshValueFromFsmVar" and "GetValueFromFsmVar" which might also help you out, but I think I the problem might be with how you set the variable in each single FsmVar:
try
Code: [Select]
action.xxxxx[v].SetValue(fsmArray.Name);or
Code: [Select]
action.xxxxx[v].stringValue = fsmArray.Name;instead of
Code: [Select]
action.xxxxx[v].variableName = fsmArray.Name;because ".variableName" seems to be the name of the FsmVar variable, not the value that you want to set.

Further thoughts:
When you tried the code in OnGUI() did you also return true at the end, so that it updates whenever something changes in that action? You could also try to put the "DrawDefaultInspector();" at the end of OnGUI() before returning true, so that it only draws the fields after you've modified their values.
Also IIRC, PlayMaker already provides a list of all FSMs in the current scene, just like "Fsm" gives you the current fsm as a variable or "Owner" returns the GameObject of the current FSM, but I don't remember how to access that list. Maybe you find something of that sort so that you don't have to search them through the resources.

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #4 on: April 04, 2018, 09:36:49 AM »
Hi

I will check out PlayMakerUtils later but in theory i shouldnt require this as i can successfully update all other variable types using this approach.

I have tried using all of the suggestions but they dont work
Code: [Select]
action.xxxxx[v].stringValue = fsmArray.Name;
Code: [Select]
action.xxxxx[v].SetValue(fsmArray.Name);
I have also tried placing "DrawDefaultInspector();" before and after the update.

After further testing I can see that the issue is just with the updating of the variablename. To prove this I populated the FsmVar with a count of 5 using the FsmEditor before running the script.



then it populates just fine...


So it seems there is an update issue with the FsmVar. Somehow i need to force a refresh of the FsmEditor before populating? any ideas?

Here is the full code I'm using (ignore certain parts as this is just a sample)...

Code: [Select]
using UnityEngine;
using System;
using System.Collections;
using System.Collections.Generic;
using HutongGames.PlayMaker;
using HutongGames.PlayMaker.Actions;
using HutongGames.PlayMakerEditor;


[CustomActionEditor(typeof(PmTest))]
public class PmTestCustomEditor : CustomActionEditor
{

public List<object> fsmObjects = new List<object>(); //fsm ref
public List<string> fsmValues = new List<string>(); //fsm values
public int databaseIDSelected;

//store references to the target script
private static PmTest action;
private PlayMakerFSM thisFSM;
private bool isDirty = false;


    public override void OnEnable()
    {
        // Do any expensive initialization stuff here.
Debug.Log("enabled");
    }

    public override bool OnGUI()
    {
        //reset isDirty
isDirty = false;

// If you need to reference the action directly:
        action = target as PmTest;

        //draw default inspector (action-content) if you only want to add to it
isDirty = DrawDefaultInspector();

//blocks everything that follows if in Action Browser (so that no errors happen when getting scene-references)
if(action.Fsm == null || action.Fsm.FsmComponent == null) return false;

//if you need reference to the FSM-Component:
//thisFSM = action.Fsm.FsmComponent;

//switch database
EditorGUI.BeginChangeCheck();
var dboptions = fsmValues.ToArray();
var switchdb = EditorGUILayout.Popup("", databaseIDSelected, dboptions);
if (EditorGUI.EndChangeCheck())
{
if (EditorUtility.DisplayDialog("Switch DB?",
"Make sure you have saved your data, unsaved data will be lost, do you wish to proceed?", "Yes", "No"))
{
databaseIDSelected = switchdb;
}
}

        // Or add your own controls using any GUILayout method
        GUILayout.Label("Your Controls:", EditorStyles.boldLabel);

        if (GUILayout.Button("Press Me"))
        {
            EditorUtility.DisplayDialog("My Dialog", "Hello", "OK");
BuildFsmVariableList();
        }

        //needs to be at the end and tells OnGUI if something has changed
return isDirty || GUI.changed;

    }


    public void BuildFsmVariableList()
    {

List<string> fsmvars = new List<string>();

PlayMakerFSM[] fsms = Resources.FindObjectsOfTypeAll(typeof(PlayMakerFSM)) as PlayMakerFSM[]; //get all fsms in scene

if (fsms != null)
{
foreach (PlayMakerFSM _fsm in fsms) //fsm
{
if (_fsm.Fsm.Variables.ArrayVariables.Length > 0)
{
for (var i = 0; i < _fsm.Fsm.Variables.ArrayVariables.Length; i++)
{
if(_fsm.Fsm.Variables.ArrayVariables[i].Name.StartsWith("pmdt~"))
{
fsmvars.Add(_fsm.Fsm.Variables.ArrayVariables[i].Name);
}
}
}
}
}

if (action.xxxxx.Length != fsmvars.Count)
{
action.xxxxx = new FsmVar[fsmvars.Count];
}

for (var v = 0; v < fsmvars.Count; v++)
{
var fsmArray = action.fsmComponent.FsmVariables.GetFsmArray(fsmvars[v]);

if ( fsmArray != null ) {
action.xxxxx[v].UpdateValue();
//action.xxxxx[v].Type = VariableType.Array;
//action.xxxxx[v].stringValue = fsmArray.Name;
//action.xxxxx[v].SetValue(fsmArray.Name);
action.xxxxx[v].variableName = fsmArray.Name;
}
}
    }
}
« Last Edit: April 04, 2018, 09:38:54 AM by coxy17 »

Deek

  • Full Member
  • ***
  • Posts: 133
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #5 on: April 04, 2018, 04:32:00 PM »
I replicated your setup because this remote maintenance proves quite difficult :).

It turns out that there is a problem with resizing the FsmVar[] xxxxx by creating a new object ("new FsmVar[fsmvars.Count]") and trying to use it immediately afterwards.

You can test it yourself by throwing a Debug.Log() at the end of BuildFsmVariableList(): whenever you try to do something with xxxxx, wheter updating, setting or getting a value to/from it, it seems to break the function without throwing any error, and anything afterwards won't get executed (as if that action variable gets corrupted or isn't accessible).

When you comment that resizing process out (
Code: [Select]
//action.xxxxx = new FsmVar[fsmvars.Count];), you'll see that it reaches the end of that function.

It might be that something needs to be done to the FsmVar[] after resetting/resizing it, but I think your best bet would be to go for a different collection variable if possible, like FsmArray which natively has a .Resize() function and can also hold any object type.
If you do, you should know that with FsmArrays you need to do the following when resizing/manipulating them (kind-of pseudo-code):
Code: [Select]
FsmArray array;
...
array.SetType.(...);
array.Resize(...);
for(...) {
array.Set(i, ...);
}
array.SaveChanges();


While setting up your scenario I also noticed that you were missing the UnityEditor using directive ( "using UnityEditor;" ), to get things like EditorGUI to work and you'd need to set the types to string before filling it with string values:
Code: [Select]
action.xxxxx[v].Type = VariableType.String;

I guess I can't help you any further than that. Maybe Jean or someone else sees this and might know what is going with FsmVar[]'s in such a scenario, but It could be that using an FsmVar[] is not be the desired approach and the reason that something like FsmArray exists.

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #6 on: April 05, 2018, 02:31:48 AM »
Hi,

 Can you send me the action and custom editor to go with it, and I'll see what I can do. I am trying to glance through the thread, but It will be quicker if I get the latest and check it out.

 Bye,

 Jean

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #7 on: April 05, 2018, 04:07:33 AM »
Hi Jean,

Thanks! I've attached a new script which just includes the issue i'm referring to.

1. Add the NickTest script and create a few ArrayVariables with a variablename starting with 'test', the script looks for this.
2. Add a FSM in the Action.
3. Run the script using the button located in the action editor called "Populate FsmVar[]"

Then you will see that updating the variable count and population doesn't work. From the onset it seems to work but when you refresh the FSM the changes dont apply.

Like i was discussing in this thread, if you manually increase the count of the FsmVar then run the NickTest script it does work, so there must be an issue with  line 89 in NickTestActionEditor.cs

Code: [Select]
action.xxxxx = new FsmVar[fsmvars.Count];
Nick

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #8 on: April 06, 2018, 04:38:48 AM »
Hi,

working action and editor attach. All is well, there is no bug with playmaker, only lots of confusion, action editor is tricky indeed.

Few things :)

- I think you are getting mixed up with the public fsmComponent and the action fsm.fsmcomponent. I fixed it by just using the FsmOwnerDefault, check out the code on how to deal with it, no need for a second dedicated public variable for this.

- then, to cast properly from various fsm variables to an FsmVar, you need to create a new fsmVar based on a namedVariable, that you get from the api, check out the code again.

 I also refactored few things, just to my liking, but feel free to do the rest anyway you want.

Bye,

 Jean

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #9 on: April 06, 2018, 09:54:08 AM »
Hi Jean

Ah I see, well thanks for the pointers and the solution! works great, the script was thrown together to just test a idea out, so I forgot about the action fsm.fsmcomponent.

Nick

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #10 on: April 16, 2018, 09:48:57 AM »
Hi Jean,

The demo script works just fine when targeting the actions owner Fsm to save references to variables, however, i was testing targeting another FSM instead of the owner FSM and found that the FsmEditor populates the variables just fine but when i go to refresh the FsmEditor the values disappear? even after saving the scene.

Nick

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #11 on: April 17, 2018, 02:19:13 AM »
Hi,

 it's likely because you are trying to refer to a scene object from a prefab no?

 Can you show more of your setup, via screenshot or a package and then I'll have a look.

 Bye,

 Jean

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #12 on: April 17, 2018, 04:47:00 AM »
Hi Jean,

No im not but you may be right about the scene object, I checked the original script you sent and thought i would test this too and i have the same issue. Original scripts attached and a video of the issue.

You can see that I....
1. Add the reference to any FSM not on the same object
2. Populate any FSM var with the prefix of 'test;
3. You can see it populates it, but then when you save/refresh the values disappear.

https://drive.google.com/open?id=1INjax9W-WpI1ZdDf1T20cH6LPxuEDL04

Nick

jeanfabre

  • Administrator
  • Hero Member
  • *****
  • Posts: 15500
  • Official Playmaker Support
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #13 on: April 26, 2018, 03:08:58 AM »
Hi,

 yes, I see the problem. It looks like you need to save the variable names and not a FsmVar, else the action tries to find that fsmVar inside its own fsm and because it doesn't find it, set it to none.

 to verify this, create a variable of the same name on your fsm owner and you;ll see that this one will not be set back to none.

 so, the quickest way to indeed to save just the names of the variables in an FsmString[] and get them at runtime when you need to use them.

 I'll check with Alex on this, maybe there is something we can do to improve this.

 Bye,

 Jean

coxy17

  • Beta Group
  • Sr. Member
  • *
  • Posts: 355
Re: CustomActionEditor Set FsmVar[] variable Issue
« Reply #14 on: April 26, 2018, 10:51:15 AM »
Hi Jean,

Ok well thats what I was afraid of, I need to really just reference it without having to assign it during runtime. Plus having the additional FsmString[] is not really ideal. Its a shame we cant just link this up somehow.

Let me know what you can do? otherwise I may have to re-think my actions as I dont want to have to do this ideally.

Nick