Browse Source

merged InvokeMethod.cs

master
Timothy Ng 9 years ago
parent
commit
a2d4ae5b25
  1. 832
      Assets/Fungus/Flowchart/Editor/InvokeMethodEditor.cs
  2. 41
      Assets/Fungus/Flowchart/Scripts/Block.cs
  3. 4
      Assets/Fungus/Flowchart/Scripts/Commands/Call.cs
  4. 232
      Assets/Fungus/Flowchart/Scripts/Commands/InvokeMethod.cs
  5. 131
      Assets/Fungus/Flowchart/Scripts/Flowchart.cs
  6. 2
      Assets/Fungus/Narrative/Scripts/Commands/Say.cs
  7. 10
      Assets/Fungus/Narrative/Scripts/MenuDialog.cs
  8. 10
      Assets/Fungus/Narrative/Scripts/SayDialog.cs
  9. 414
      Assets/Fungus/Thirdparty/CSVParser/CsvParser.cs
  10. 6
      Assets/Fungus/UI/Scripts/Commands/Write.cs
  11. 8
      Assets/Fungus/UI/Scripts/Writer.cs
  12. 72
      Assets/Tests/Scripting/Scripting.unity

832
Assets/Fungus/Flowchart/Editor/InvokeMethodEditor.cs

@ -13,430 +13,430 @@ namespace Fungus
[CustomEditor(typeof(InvokeMethod))] [CustomEditor(typeof(InvokeMethod))]
public class InvokeMethodEditor : CommandEditor public class InvokeMethodEditor : CommandEditor
{ {
InvokeMethod targetMethod; InvokeMethod targetMethod;
public override void DrawCommandGUI() public override void DrawCommandGUI()
{ {
base.DrawCommandGUI(); base.DrawCommandGUI();
targetMethod = target as InvokeMethod; targetMethod = target as InvokeMethod;
if (targetMethod == null || targetMethod.targetObject == null) if (targetMethod == null || targetMethod.targetObject == null)
return; return;
SerializedObject objSerializedTarget = new SerializedObject(targetMethod); SerializedObject objSerializedTarget = new SerializedObject(targetMethod);
string component = ShowComponents(objSerializedTarget, targetMethod.targetObject); string component = ShowComponents(objSerializedTarget, targetMethod.targetObject);
// show component methods if selected // show component methods if selected
if (!string.IsNullOrEmpty(component)) if (!string.IsNullOrEmpty(component))
{ {
var method = ShowMethods(objSerializedTarget, targetMethod.targetObject, component); var method = ShowMethods(objSerializedTarget, targetMethod.targetObject, component);
// show method parameters if selected // show method parameters if selected
if (method != null) if (method != null)
{ {
objSerializedTarget.ApplyModifiedProperties(); objSerializedTarget.ApplyModifiedProperties();
ShowParameters(objSerializedTarget, targetMethod.targetObject, method); ShowParameters(objSerializedTarget, targetMethod.targetObject, method);
ShowReturnValue(objSerializedTarget, method); ShowReturnValue(objSerializedTarget, method);
} }
} }
} }
private string ShowComponents(SerializedObject objTarget, GameObject gameObject) private string ShowComponents(SerializedObject objTarget, GameObject gameObject)
{ {
var targetComponentAssemblyName = objTarget.FindProperty("targetComponentAssemblyName"); var targetComponentAssemblyName = objTarget.FindProperty("targetComponentAssemblyName");
var targetComponentFullname = objTarget.FindProperty("targetComponentFullname"); var targetComponentFullname = objTarget.FindProperty("targetComponentFullname");
var targetComponentText = objTarget.FindProperty("targetComponentText"); var targetComponentText = objTarget.FindProperty("targetComponentText");
var objComponents = gameObject.GetComponents<Component>(); var objComponents = gameObject.GetComponents<Component>();
var objTypesAssemblynames = (from objComp in objComponents select objComp.GetType().AssemblyQualifiedName).ToList(); var objTypesAssemblynames = (from objComp in objComponents select objComp.GetType().AssemblyQualifiedName).ToList();
var objTypesName = (from objComp in objComponents select objComp.GetType().Name).ToList(); var objTypesName = (from objComp in objComponents select objComp.GetType().Name).ToList();
int index = objTypesAssemblynames.IndexOf(targetComponentAssemblyName.stringValue); int index = objTypesAssemblynames.IndexOf(targetComponentAssemblyName.stringValue);
index = EditorGUILayout.Popup("Target Component", index, objTypesName.ToArray()); index = EditorGUILayout.Popup("Target Component", index, objTypesName.ToArray());
if (index != -1) if (index != -1)
{ {
targetComponentAssemblyName.stringValue = objTypesAssemblynames[index]; targetComponentAssemblyName.stringValue = objTypesAssemblynames[index];
targetComponentFullname.stringValue = objComponents.GetType().FullName; targetComponentFullname.stringValue = objComponents.GetType().FullName;
targetComponentText.stringValue = objTypesName[index]; targetComponentText.stringValue = objTypesName[index];
} }
else else
{ {
targetComponentAssemblyName.stringValue = null; targetComponentAssemblyName.stringValue = null;
} }
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
return targetComponentAssemblyName.stringValue; return targetComponentAssemblyName.stringValue;
} }
private MethodInfo ShowMethods(SerializedObject objTarget, GameObject gameObject, string component) private MethodInfo ShowMethods(SerializedObject objTarget, GameObject gameObject, string component)
{ {
MethodInfo result = null; MethodInfo result = null;
var targetMethodProp = objTarget.FindProperty("targetMethod"); var targetMethodProp = objTarget.FindProperty("targetMethod");
var targetMethodTextProp = objTarget.FindProperty("targetMethodText"); var targetMethodTextProp = objTarget.FindProperty("targetMethodText");
var methodParametersProp = objTarget.FindProperty("methodParameters"); var methodParametersProp = objTarget.FindProperty("methodParameters");
var showInheritedProp = objTarget.FindProperty("showInherited"); var showInheritedProp = objTarget.FindProperty("showInherited");
var saveReturnValueProp = objTarget.FindProperty("saveReturnValue"); var saveReturnValueProp = objTarget.FindProperty("saveReturnValue");
var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey"); var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey");
var objComponent = gameObject.GetComponent(ReflectionHelper.GetType(component)); var objComponent = gameObject.GetComponent(ReflectionHelper.GetType(component));
var bindingFlags = BindingFlags.Default | BindingFlags.Public | BindingFlags.Instance; var bindingFlags = BindingFlags.Default | BindingFlags.Public | BindingFlags.Instance;
if (!showInheritedProp.boolValue) if (!showInheritedProp.boolValue)
{ {
bindingFlags |= BindingFlags.DeclaredOnly; bindingFlags |= BindingFlags.DeclaredOnly;
} }
if (objComponent != null) if (objComponent != null)
{ {
var objMethods = objComponent.GetType().GetMethods(bindingFlags); var objMethods = objComponent.GetType().GetMethods(bindingFlags);
var methods = (from objMethod in objMethods where !objMethod.IsSpecialName select objMethod).ToList(); // filter out the getter/setter methods var methods = (from objMethod in objMethods where !objMethod.IsSpecialName select objMethod).ToList(); // filter out the getter/setter methods
var methodText = (from objMethod in methods select objMethod.Name + FormatParameters(objMethod.GetParameters()) + ": " + objMethod.ReturnType.Name).ToList(); var methodText = (from objMethod in methods select objMethod.Name + FormatParameters(objMethod.GetParameters()) + ": " + objMethod.ReturnType.Name).ToList();
int index = methodText.IndexOf(targetMethodTextProp.stringValue); int index = methodText.IndexOf(targetMethodTextProp.stringValue);
index = EditorGUILayout.Popup("Target Method", index, methodText.ToArray()); index = EditorGUILayout.Popup("Target Method", index, methodText.ToArray());
EditorGUILayout.PropertyField(showInheritedProp); EditorGUILayout.PropertyField(showInheritedProp);
if (index != -1) if (index != -1)
{ {
if (targetMethodTextProp.stringValue != methodText[index]) if (targetMethodTextProp.stringValue != methodText[index])
{ {
// reset // reset
methodParametersProp.ClearArray(); methodParametersProp.ClearArray();
methodParametersProp.arraySize = methods[index].GetParameters().Length; methodParametersProp.arraySize = methods[index].GetParameters().Length;
saveReturnValueProp.boolValue = false; saveReturnValueProp.boolValue = false;
returnValueKeyProp.stringValue = null; returnValueKeyProp.stringValue = null;
} }
targetMethodTextProp.stringValue = methodText[index]; targetMethodTextProp.stringValue = methodText[index];
targetMethodProp.stringValue = methods[index].Name; targetMethodProp.stringValue = methods[index].Name;
result = methods[index]; result = methods[index];
} }
else else
{ {
targetMethodTextProp.stringValue = null; targetMethodTextProp.stringValue = null;
targetMethodProp.stringValue = null; targetMethodProp.stringValue = null;
} }
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
} }
return result; return result;
} }
private void ShowParameters(SerializedObject objTarget, GameObject gameObject, MethodInfo method) private void ShowParameters(SerializedObject objTarget, GameObject gameObject, MethodInfo method)
{ {
var methodParametersProp = objTarget.FindProperty("methodParameters"); var methodParametersProp = objTarget.FindProperty("methodParameters");
var objParams = method.GetParameters(); var objParams = method.GetParameters();
if (objParams.Length > 0) if (objParams.Length > 0)
{ {
GUILayout.Space(20); GUILayout.Space(20);
EditorGUILayout.LabelField("Parameters", EditorStyles.boldLabel); EditorGUILayout.LabelField("Parameters", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.BeginVertical(EditorStyles.helpBox);
for (int i = 0; i < objParams.Length; i++) for (int i = 0; i < objParams.Length; i++)
{ {
var objParam = objParams[i]; var objParam = objParams[i];
GUILayout.BeginHorizontal(); GUILayout.BeginHorizontal();
string labelFormat = string.Format("{0}: {1}", objParam.ParameterType.Name, objParam.Name); string labelFormat = string.Format("{0}: {1}", objParam.ParameterType.Name, objParam.Name);
var objItemProp = methodParametersProp.GetArrayElementAtIndex(i); var objItemProp = methodParametersProp.GetArrayElementAtIndex(i);
var serObjValueProp = objItemProp.FindPropertyRelative("objValue"); var serObjValueProp = objItemProp.FindPropertyRelative("objValue");
var serVariableKeyProp = objItemProp.FindPropertyRelative("variableKey"); var serVariableKeyProp = objItemProp.FindPropertyRelative("variableKey");
var serValueTypeAssemblynameProp = serObjValueProp.FindPropertyRelative("typeAssemblyname"); var serValueTypeAssemblynameProp = serObjValueProp.FindPropertyRelative("typeAssemblyname");
var serValueTypeFullnameProp = serObjValueProp.FindPropertyRelative("typeFullname"); var serValueTypeFullnameProp = serObjValueProp.FindPropertyRelative("typeFullname");
serValueTypeAssemblynameProp.stringValue = objParam.ParameterType.AssemblyQualifiedName; serValueTypeAssemblynameProp.stringValue = objParam.ParameterType.AssemblyQualifiedName;
serValueTypeFullnameProp.stringValue = objParam.ParameterType.FullName; serValueTypeFullnameProp.stringValue = objParam.ParameterType.FullName;
bool isDrawn = true; bool isDrawn = true;
if (string.IsNullOrEmpty(serVariableKeyProp.stringValue)) if (string.IsNullOrEmpty(serVariableKeyProp.stringValue))
{ {
isDrawn = DrawTypedPropertyInput(labelFormat, serObjValueProp, objParam.ParameterType); isDrawn = DrawTypedPropertyInput(labelFormat, serObjValueProp, objParam.ParameterType);
} }
if (isDrawn) if (isDrawn)
{ {
var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, objParam.ParameterType); var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, objParam.ParameterType);
var values = new string[] { "<Value>" }; var values = new string[] { "<Value>" };
var displayValue = values.Concat(vars).ToList(); var displayValue = values.Concat(vars).ToList();
int index = displayValue.IndexOf(serVariableKeyProp.stringValue); int index = displayValue.IndexOf(serVariableKeyProp.stringValue);
if (index == -1) if (index == -1)
{ {
index = 0; index = 0;
} }
if (string.IsNullOrEmpty(serVariableKeyProp.stringValue)) if (string.IsNullOrEmpty(serVariableKeyProp.stringValue))
{ {
index = EditorGUILayout.Popup(index, displayValue.ToArray(), GUILayout.MaxWidth(80)); index = EditorGUILayout.Popup(index, displayValue.ToArray(), GUILayout.MaxWidth(80));
} }
else else
{ {
index = EditorGUILayout.Popup(labelFormat, index, displayValue.ToArray()); index = EditorGUILayout.Popup(labelFormat, index, displayValue.ToArray());
} }
if (index > 0) if (index > 0)
{ {
serVariableKeyProp.stringValue = displayValue[index]; serVariableKeyProp.stringValue = displayValue[index];
} }
else else
{ {
serVariableKeyProp.stringValue = null; serVariableKeyProp.stringValue = null;
} }
} }
else else
{ {
var style = EditorStyles.label; var style = EditorStyles.label;
var prevColor = style.normal.textColor; var prevColor = style.normal.textColor;
style.normal.textColor = Color.red; style.normal.textColor = Color.red;
EditorGUILayout.LabelField(new GUIContent(objParam.ParameterType.Name + " cannot be drawn, don´t use this method in the flowchart."), style); EditorGUILayout.LabelField(new GUIContent(objParam.ParameterType.Name + " cannot be drawn, don´t use this method in the flowchart."), style);
style.normal.textColor = prevColor; style.normal.textColor = prevColor;
} }
GUILayout.EndHorizontal(); GUILayout.EndHorizontal();
} }
EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical();
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
} }
} }
private void ShowReturnValue(SerializedObject objTarget, MethodInfo method) private void ShowReturnValue(SerializedObject objTarget, MethodInfo method)
{ {
var saveReturnValueProp = objTarget.FindProperty("saveReturnValue"); var saveReturnValueProp = objTarget.FindProperty("saveReturnValue");
var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey"); var returnValueKeyProp = objTarget.FindProperty("returnValueVariableKey");
var returnValueTypeProp = objTarget.FindProperty("returnValueType"); var returnValueTypeProp = objTarget.FindProperty("returnValueType");
var callModeProp = objTarget.FindProperty("callMode"); var callModeProp = objTarget.FindProperty("callMode");
returnValueTypeProp.stringValue = method.ReturnType.FullName; returnValueTypeProp.stringValue = method.ReturnType.FullName;
if (method.ReturnType == typeof(IEnumerator)) if (method.ReturnType == typeof(IEnumerator))
{ {
GUILayout.Space(20); GUILayout.Space(20);
EditorGUILayout.PropertyField(callModeProp); EditorGUILayout.PropertyField(callModeProp);
} }
else if (method.ReturnType != typeof(void)) else if (method.ReturnType != typeof(void))
{ {
GUILayout.Space(20); GUILayout.Space(20);
EditorGUILayout.LabelField("Return Value", EditorStyles.boldLabel); EditorGUILayout.LabelField("Return Value", EditorStyles.boldLabel);
EditorGUILayout.BeginVertical(EditorStyles.helpBox); EditorGUILayout.BeginVertical(EditorStyles.helpBox);
saveReturnValueProp.boolValue = EditorGUILayout.Toggle("Save return value", saveReturnValueProp.boolValue); saveReturnValueProp.boolValue = EditorGUILayout.Toggle("Save return value", saveReturnValueProp.boolValue);
if (saveReturnValueProp.boolValue) if (saveReturnValueProp.boolValue)
{ {
var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, method.ReturnType).ToList(); var vars = GetFungusVariablesByType(targetMethod.GetFlowchart().variables, method.ReturnType).ToList();
int index = vars.IndexOf(returnValueKeyProp.stringValue); int index = vars.IndexOf(returnValueKeyProp.stringValue);
index = EditorGUILayout.Popup(method.ReturnType.Name, index, vars.ToArray()); index = EditorGUILayout.Popup(method.ReturnType.Name, index, vars.ToArray());
if (index != -1) if (index != -1)
{ {
returnValueKeyProp.stringValue = vars[index]; returnValueKeyProp.stringValue = vars[index];
} }
} }
EditorGUILayout.EndVertical(); EditorGUILayout.EndVertical();
} }
else else
{ {
saveReturnValueProp.boolValue = false; saveReturnValueProp.boolValue = false;
} }
objTarget.ApplyModifiedProperties(); objTarget.ApplyModifiedProperties();
} }
private bool DrawTypedPropertyInput(string label, SerializedProperty objProperty, Type type) private bool DrawTypedPropertyInput(string label, SerializedProperty objProperty, Type type)
{ {
SerializedProperty objectValue = null; SerializedProperty objectValue = null;
if (type == typeof(int)) if (type == typeof(int))
{ {
objectValue = objProperty.FindPropertyRelative("intValue"); objectValue = objProperty.FindPropertyRelative("intValue");
objectValue.intValue = EditorGUILayout.IntField(new GUIContent(label), objectValue.intValue); objectValue.intValue = EditorGUILayout.IntField(new GUIContent(label), objectValue.intValue);
return true; return true;
} }
else if (type == typeof(bool)) else if (type == typeof(bool))
{ {
objectValue = objProperty.FindPropertyRelative("boolValue"); objectValue = objProperty.FindPropertyRelative("boolValue");
objectValue.boolValue = EditorGUILayout.Toggle(new GUIContent(label), objectValue.boolValue); objectValue.boolValue = EditorGUILayout.Toggle(new GUIContent(label), objectValue.boolValue);
return true; return true;
} }
else if (type == typeof(float)) else if (type == typeof(float))
{ {
objectValue = objProperty.FindPropertyRelative("floatValue"); objectValue = objProperty.FindPropertyRelative("floatValue");
objectValue.floatValue = EditorGUILayout.FloatField(new GUIContent(label), objectValue.floatValue); objectValue.floatValue = EditorGUILayout.FloatField(new GUIContent(label), objectValue.floatValue);
return true; return true;
} }
else if (type == typeof(string)) else if (type == typeof(string))
{ {
objectValue = objProperty.FindPropertyRelative("stringValue"); objectValue = objProperty.FindPropertyRelative("stringValue");
objectValue.stringValue = EditorGUILayout.TextField(new GUIContent(label), objectValue.stringValue); objectValue.stringValue = EditorGUILayout.TextField(new GUIContent(label), objectValue.stringValue);
return true; return true;
} }
else if (type == typeof(Color)) else if (type == typeof(Color))
{ {
objectValue = objProperty.FindPropertyRelative("colorValue"); objectValue = objProperty.FindPropertyRelative("colorValue");
objectValue.colorValue = EditorGUILayout.ColorField(new GUIContent(label), objectValue.colorValue); objectValue.colorValue = EditorGUILayout.ColorField(new GUIContent(label), objectValue.colorValue);
return true; return true;
} }
else if (type == typeof(UnityEngine.GameObject)) else if (type == typeof(UnityEngine.GameObject))
{ {
objectValue = objProperty.FindPropertyRelative("gameObjectValue"); objectValue = objProperty.FindPropertyRelative("gameObjectValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.GameObject), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.GameObject), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Material)) else if (type == typeof(UnityEngine.Material))
{ {
objectValue = objProperty.FindPropertyRelative("materialValue"); objectValue = objProperty.FindPropertyRelative("materialValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Material), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Material), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Sprite)) else if (type == typeof(UnityEngine.Sprite))
{ {
objectValue = objProperty.FindPropertyRelative("spriteValue"); objectValue = objProperty.FindPropertyRelative("spriteValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Sprite), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Sprite), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Texture)) else if (type == typeof(UnityEngine.Texture))
{ {
objectValue = objProperty.FindPropertyRelative("textureValue"); objectValue = objProperty.FindPropertyRelative("textureValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Texture), true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, typeof(UnityEngine.Texture), true);
return true; return true;
} }
else if (type == typeof(UnityEngine.Vector2)) else if (type == typeof(UnityEngine.Vector2))
{ {
objectValue = objProperty.FindPropertyRelative("vector2Value"); objectValue = objProperty.FindPropertyRelative("vector2Value");
objectValue.vector2Value = EditorGUILayout.Vector2Field(new GUIContent(label), objectValue.vector2Value); objectValue.vector2Value = EditorGUILayout.Vector2Field(new GUIContent(label), objectValue.vector2Value);
return true; return true;
} }
else if (type == typeof(UnityEngine.Vector3)) else if (type == typeof(UnityEngine.Vector3))
{ {
objectValue = objProperty.FindPropertyRelative("vector3Value"); objectValue = objProperty.FindPropertyRelative("vector3Value");
objectValue.vector3Value = EditorGUILayout.Vector3Field(new GUIContent(label), objectValue.vector3Value); objectValue.vector3Value = EditorGUILayout.Vector3Field(new GUIContent(label), objectValue.vector3Value);
return true; return true;
} }
else if (type.IsSubclassOf(typeof(UnityEngine.Object))) else if (type.IsSubclassOf(typeof(UnityEngine.Object)))
{ {
objectValue = objProperty.FindPropertyRelative("objectValue"); objectValue = objProperty.FindPropertyRelative("objectValue");
objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, type, true); objectValue.objectReferenceValue = EditorGUILayout.ObjectField(new GUIContent(label), objectValue.objectReferenceValue, type, true);
return true; return true;
} }
else if (type.IsEnum) else if (type.IsEnum)
{ {
var enumNames = Enum.GetNames(type); var enumNames = Enum.GetNames(type);
objectValue = objProperty.FindPropertyRelative("intValue"); objectValue = objProperty.FindPropertyRelative("intValue");
objectValue.intValue = EditorGUILayout.Popup(label, objectValue.intValue, enumNames); objectValue.intValue = EditorGUILayout.Popup(label, objectValue.intValue, enumNames);
return true; return true;
} }
return false; return false;
} }
private string[] GetFungusVariablesByType(List<Variable> variables, Type type) private string[] GetFungusVariablesByType(List<Variable> variables, Type type)
{ {
string[] result = new string[0]; string[] result = new string[0];
if (type == typeof(int)) if (type == typeof(int))
{ {
result = (from v in variables where v.GetType() == typeof(IntegerVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(IntegerVariable) select v.key).ToArray();
} }
else if (type == typeof(bool)) else if (type == typeof(bool))
{ {
result = (from v in variables where v.GetType() == typeof(BooleanVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(BooleanVariable) select v.key).ToArray();
} }
else if (type == typeof(float)) else if (type == typeof(float))
{ {
result = (from v in variables where v.GetType() == typeof(FloatVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(FloatVariable) select v.key).ToArray();
} }
else if (type == typeof(string)) else if (type == typeof(string))
{ {
result = (from v in variables where v.GetType() == typeof(StringVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(StringVariable) select v.key).ToArray();
} }
else if (type == typeof(Color)) else if (type == typeof(Color))
{ {
result = (from v in variables where v.GetType() == typeof(ColorVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(ColorVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.GameObject)) else if (type == typeof(UnityEngine.GameObject))
{ {
result = (from v in variables where v.GetType() == typeof(GameObjectVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(GameObjectVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Material)) else if (type == typeof(UnityEngine.Material))
{ {
result = (from v in variables where v.GetType() == typeof(MaterialVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(MaterialVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Sprite)) else if (type == typeof(UnityEngine.Sprite))
{ {
result = (from v in variables where v.GetType() == typeof(SpriteVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(SpriteVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Texture)) else if (type == typeof(UnityEngine.Texture))
{ {
result = (from v in variables where v.GetType() == typeof(TextureVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(TextureVariable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Vector2)) else if (type == typeof(UnityEngine.Vector2))
{ {
result = (from v in variables where v.GetType() == typeof(Vector2Variable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(Vector2Variable) select v.key).ToArray();
} }
else if (type == typeof(UnityEngine.Vector3)) else if (type == typeof(UnityEngine.Vector3))
{ {
result = (from v in variables where v.GetType() == typeof(Vector3Variable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(Vector3Variable) select v.key).ToArray();
} }
else if (type.IsSubclassOf(typeof(UnityEngine.Object))) else if (type.IsSubclassOf(typeof(UnityEngine.Object)))
{ {
result = (from v in variables where v.GetType() == typeof(ObjectVariable) select v.key).ToArray(); result = (from v in variables where v.GetType() == typeof(ObjectVariable) select v.key).ToArray();
} }
return result; return result;
} }
private string FormatParameters(ParameterInfo[] paramInfo) private string FormatParameters(ParameterInfo[] paramInfo)
{ {
string result = " ("; string result = " (";
for (int i = 0; i < paramInfo.Length; i++) for (int i = 0; i < paramInfo.Length; i++)
{ {
var pi = paramInfo[i]; var pi = paramInfo[i];
result += pi.ParameterType.Name; // " arg" + (i + 1); result += pi.ParameterType.Name; // " arg" + (i + 1);
if (i < paramInfo.Length - 1) if (i < paramInfo.Length - 1)
{ {
result += ", "; result += ", ";
} }
} }
return result + ")"; return result + ")";
} }
private object GetDefaultValue(Type t) private object GetDefaultValue(Type t)
{ {
if (t.IsValueType) if (t.IsValueType)
return Activator.CreateInstance(t); return Activator.CreateInstance(t);
return null; return null;
} }
} }
} }

41
Assets/Fungus/Flowchart/Scripts/Block.cs

@ -142,26 +142,25 @@ namespace Fungus
return executionCount; return executionCount;
} }
public virtual bool Execute(Action onComplete = null) /// <summary>
/// Execute the Block in a coroutine. Only one running instance of each Block is permitted.
/// </summary>
/// <param name="commandIndex">Index of command to start execution at</param>
/// <param name="onComplete">Delegate function to call when execution completes</param>
public virtual IEnumerator Execute(int commandIndex = 0, Action onComplete = null)
{ {
if (executionState != ExecutionState.Idle) if (executionState != ExecutionState.Idle)
{ {
return false; yield break;
} }
if (!executionInfoSet)
{
SetExecutionInfo();
}
executionCount++; if (!executionInfoSet)
StartCoroutine(ExecuteBlock(onComplete)); {
SetExecutionInfo();
}
return true; executionCount++;
}
protected virtual IEnumerator ExecuteBlock(Action onComplete = null)
{
Flowchart flowchart = GetFlowchart(); Flowchart flowchart = GetFlowchart();
executionState = ExecutionState.Executing; executionState = ExecutionState.Executing;
@ -175,6 +174,8 @@ namespace Fungus
} }
#endif #endif
jumpToCommandIndex = commandIndex;
int i = 0; int i = 0;
while (true) while (true)
{ {
@ -248,10 +249,10 @@ namespace Fungus
executionState = ExecutionState.Idle; executionState = ExecutionState.Idle;
activeCommand = null; activeCommand = null;
if (onComplete != null) if (onComplete != null)
{ {
onComplete(); onComplete();
} }
} }
public virtual void Stop() public virtual void Stop()

4
Assets/Fungus/Flowchart/Scripts/Commands/Call.cs

@ -64,12 +64,12 @@ namespace Fungus
flowchart.selectedBlock = targetBlock; flowchart.selectedBlock = targetBlock;
} }
targetBlock.Execute(onComplete); StartCoroutine(targetBlock.Execute(0, onComplete));
} }
else else
{ {
// Execute block in another Flowchart // Execute block in another Flowchart
targetFlowchart.ExecuteBlock(targetBlock, onComplete); targetFlowchart.ExecuteBlock(targetBlock, 0, onComplete);
} }
} }

232
Assets/Fungus/Flowchart/Scripts/Commands/InvokeMethod.cs

@ -11,64 +11,64 @@ namespace Fungus
{ {
[CommandInfo("Scripting", [CommandInfo("Scripting",
"Invoke Method", "Invoke Method",
"Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.")] "Invokes a method of a component via reflection. Supports passing multiple parameters and storing returned values in a Fungus variable.")]
public class InvokeMethod : Command public class InvokeMethod : Command
{ {
[Tooltip("GameObject containing the component method to be invoked")] [Tooltip("GameObject containing the component method to be invoked")]
public GameObject targetObject; public GameObject targetObject;
[HideInInspector] [HideInInspector]
[Tooltip("Name of assembly containing the target component")] [Tooltip("Name of assembly containing the target component")]
public string targetComponentAssemblyName; public string targetComponentAssemblyName;
[HideInInspector] [HideInInspector]
[Tooltip("Full name of the target component")] [Tooltip("Full name of the target component")]
public string targetComponentFullname; public string targetComponentFullname;
[HideInInspector] [HideInInspector]
[Tooltip("Display name of the target component")] [Tooltip("Display name of the target component")]
public string targetComponentText; public string targetComponentText;
[HideInInspector] [HideInInspector]
[Tooltip("Name of target method to invoke on the target component")] [Tooltip("Name of target method to invoke on the target component")]
public string targetMethod; public string targetMethod;
[HideInInspector] [HideInInspector]
[Tooltip("Display name of target method to invoke on the target component")] [Tooltip("Display name of target method to invoke on the target component")]
public string targetMethodText; public string targetMethodText;
[HideInInspector] [HideInInspector]
[Tooltip("List of parameters to pass to the invoked method")] [Tooltip("List of parameters to pass to the invoked method")]
public InvokeMethodParameter[] methodParameters; public InvokeMethodParameter[] methodParameters;
[HideInInspector] [HideInInspector]
[Tooltip("If true, store the return value in a flowchart variable of the same type.")] [Tooltip("If true, store the return value in a flowchart variable of the same type.")]
public bool saveReturnValue; public bool saveReturnValue;
[HideInInspector] [HideInInspector]
[Tooltip("Name of Fungus variable to store the return value in")] [Tooltip("Name of Fungus variable to store the return value in")]
public string returnValueVariableKey; public string returnValueVariableKey;
[HideInInspector] [HideInInspector]
[Tooltip("The type of the return value")] [Tooltip("The type of the return value")]
public string returnValueType; public string returnValueType;
[HideInInspector] [HideInInspector]
[Tooltip("If true, list all inherited methods for the component")] [Tooltip("If true, list all inherited methods for the component")]
public bool showInherited; public bool showInherited;
[HideInInspector] [HideInInspector]
[Tooltip("The coroutine call behavior for methods that return IEnumerator")] [Tooltip("The coroutine call behavior for methods that return IEnumerator")]
public Fungus.Call.CallMode callMode; public Fungus.Call.CallMode callMode;
protected Type componentType; protected Type componentType;
protected Component objComponent; protected Component objComponent;
protected Type[] parameterTypes = null; protected Type[] parameterTypes = null;
protected MethodInfo objMethod; protected MethodInfo objMethod;
protected virtual void Awake() protected virtual void Awake()
{ {
if (componentType == null) if (componentType == null)
{ {
componentType = ReflectionHelper.GetType(targetComponentAssemblyName); componentType = ReflectionHelper.GetType(targetComponentAssemblyName);
@ -88,10 +88,10 @@ namespace Fungus
{ {
objMethod = UnityEvent.GetValidMethodInfo(objComponent, targetMethod, parameterTypes); objMethod = UnityEvent.GetValidMethodInfo(objComponent, targetMethod, parameterTypes);
} }
} }
public override void OnEnter() public override void OnEnter()
{ {
try try
{ {
if (targetObject == null || string.IsNullOrEmpty(targetComponentAssemblyName) || string.IsNullOrEmpty(targetMethod)) if (targetObject == null || string.IsNullOrEmpty(targetComponentAssemblyName) || string.IsNullOrEmpty(targetMethod))
@ -121,7 +121,7 @@ namespace Fungus
} }
else if(callMode == Call.CallMode.Stop) else if(callMode == Call.CallMode.Stop)
{ {
StopParentBlock(); StopParentBlock();
} }
} }
} }
@ -131,45 +131,45 @@ namespace Fungus
} }
} }
protected virtual IEnumerator ExecuteCoroutine() protected virtual IEnumerator ExecuteCoroutine()
{ {
yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues())); yield return StartCoroutine((IEnumerator)objMethod.Invoke(objComponent, GetParameterValues()));
if (callMode == Call.CallMode.WaitUntilFinished) if (callMode == Call.CallMode.WaitUntilFinished)
{ {
Continue(); Continue();
} }
} }
public override Color GetButtonColor() public override Color GetButtonColor()
{ {
return new Color32(235, 191, 217, 255); return new Color32(235, 191, 217, 255);
} }
public override string GetSummary() public override string GetSummary()
{ {
if (targetObject == null) if (targetObject == null)
{ {
return "Error: targetObject is not assigned"; return "Error: targetObject is not assigned";
} }
return targetObject.name + "." + targetComponentText + "." + targetMethodText; return targetObject.name + "." + targetComponentText + "." + targetMethodText;
} }
protected System.Type[] GetParameterTypes() protected System.Type[] GetParameterTypes()
{ {
System.Type[] types = new System.Type[methodParameters.Length]; System.Type[] types = new System.Type[methodParameters.Length];
for (int i = 0; i < methodParameters.Length; i++) for (int i = 0; i < methodParameters.Length; i++)
{ {
var item = methodParameters[i]; var item = methodParameters[i];
var objType = ReflectionHelper.GetType(item.objValue.typeAssemblyname); var objType = ReflectionHelper.GetType(item.objValue.typeAssemblyname);
types[i] = objType; types[i] = objType;
} }
return types; return types;
} }
protected object[] GetParameterValues() protected object[] GetParameterValues()
{ {
@ -308,90 +308,90 @@ namespace Fungus
[System.Serializable] [System.Serializable]
public class InvokeMethodParameter public class InvokeMethodParameter
{ {
[SerializeField] [SerializeField]
public ObjectValue objValue; public ObjectValue objValue;
[SerializeField] [SerializeField]
public string variableKey; public string variableKey;
} }
[System.Serializable] [System.Serializable]
public class ObjectValue public class ObjectValue
{ {
public string typeAssemblyname; public string typeAssemblyname;
public string typeFullname; public string typeFullname;
public int intValue; public int intValue;
public bool boolValue; public bool boolValue;
public float floatValue; public float floatValue;
public string stringValue; public string stringValue;
public Color colorValue; public Color colorValue;
public GameObject gameObjectValue; public GameObject gameObjectValue;
public Material materialValue; public Material materialValue;
public UnityEngine.Object objectValue; public UnityEngine.Object objectValue;
public Sprite spriteValue; public Sprite spriteValue;
public Texture textureValue; public Texture textureValue;
public Vector2 vector2Value; public Vector2 vector2Value;
public Vector3 vector3Value; public Vector3 vector3Value;
public object GetValue() public object GetValue()
{ {
switch (typeFullname) switch (typeFullname)
{ {
case "System.Int32": case "System.Int32":
return intValue; return intValue;
case "System.Boolean": case "System.Boolean":
return boolValue; return boolValue;
case "System.Single": case "System.Single":
return floatValue; return floatValue;
case "System.String": case "System.String":
return stringValue; return stringValue;
case "UnityEngine.Color": case "UnityEngine.Color":
return colorValue; return colorValue;
case "UnityEngine.GameObject": case "UnityEngine.GameObject":
return gameObjectValue; return gameObjectValue;
case "UnityEngine.Material": case "UnityEngine.Material":
return materialValue; return materialValue;
case "UnityEngine.Sprite": case "UnityEngine.Sprite":
return spriteValue; return spriteValue;
case "UnityEngine.Texture": case "UnityEngine.Texture":
return textureValue; return textureValue;
case "UnityEngine.Vector2": case "UnityEngine.Vector2":
return vector2Value; return vector2Value;
case "UnityEngine.Vector3": case "UnityEngine.Vector3":
return vector3Value; return vector3Value;
default: default:
var objType = ReflectionHelper.GetType(typeAssemblyname); var objType = ReflectionHelper.GetType(typeAssemblyname);
if (objType.IsSubclassOf(typeof(UnityEngine.Object))) if (objType.IsSubclassOf(typeof(UnityEngine.Object)))
{ {
return objectValue; return objectValue;
} }
else if (objType.IsEnum()) else if (objType.IsEnum())
return System.Enum.ToObject(objType, intValue); return System.Enum.ToObject(objType, intValue);
break; break;
} }
return null; return null;
} }
} }
public static class ReflectionHelper public static class ReflectionHelper
{ {
static Dictionary<string, System.Type> types = new Dictionary<string, System.Type>(); static Dictionary<string, System.Type> types = new Dictionary<string, System.Type>();
public static System.Type GetType(string typeName) public static System.Type GetType(string typeName)
{ {
if (types.ContainsKey(typeName)) if (types.ContainsKey(typeName))
return types[typeName]; return types[typeName];
types[typeName] = System.Type.GetType(typeName); types[typeName] = System.Type.GetType(typeName);
return types[typeName]; return types[typeName];
} }
} }
} }

131
Assets/Fungus/Flowchart/Scripts/Flowchart.cs

@ -371,61 +371,50 @@ namespace Fungus
} }
/** /**
* Start running another Flowchart by executing a specific child block. * Execute a child block in the Flowchart.
* The block must be in an idle state to be executed.
* You can use this method in a UI event. e.g. to handle a button click. * You can use this method in a UI event. e.g. to handle a button click.
* Returns true if the Block started execution.
*/ */
public virtual void ExecuteBlock(string blockName) public virtual bool ExecuteBlock(string blockName)
{
Block [] blocks = GetComponentsInChildren<Block>();
foreach (Block block in blocks)
{
if (block.blockName == blockName)
{
ExecuteBlock(block);
}
}
}
/**
* Sends a message to this Flowchart only.
* Any block with a matching MessageReceived event handler will start executing.
*/
public virtual void SendFungusMessage(string messageName)
{
MessageReceived[] eventHandlers = GetComponentsInChildren<MessageReceived>();
foreach (MessageReceived eventHandler in eventHandlers)
{
eventHandler.OnSendFungusMessage(messageName);
}
}
/**
* Sends a message to all Flowchart objects in the current scene.
* Any block with a matching MessageReceived event handler will start executing.
*/
public static void BroadcastFungusMessage(string messageName)
{ {
MessageReceived[] eventHandlers = GameObject.FindObjectsOfType<MessageReceived>(); Block block = null;
foreach (MessageReceived eventHandler in eventHandlers) foreach (Block b in GetComponentsInChildren<Block>())
{ {
eventHandler.OnSendFungusMessage(messageName); if (b.blockName == blockName)
} {
block = b;
break;
}
}
if (block == null)
{
Debug.LogError("Block " + blockName + "does not exist");
return false;
}
return ExecuteBlock(block);
} }
/** /**
* Start executing a specific child block in the flowchart. * Execute a child block in the flowchart.
* The block must be in an idle state to be executed. * The block must be in an idle state to be executed.
* This version provides extra options to control how the block is executed.
* Returns true if the Block started execution. * Returns true if the Block started execution.
*/ */
public virtual bool ExecuteBlock(Block block, Action onComplete = null) public virtual bool ExecuteBlock(Block block, int commandIndex = 0, Action onComplete = null)
{ {
// Block must be a component of the Flowchart game object if (block == null)
if (block == null || {
block.gameObject != gameObject) Debug.LogError("Block must not be null");
{ return false;
return false; }
}
if (block.gameObject != gameObject)
{
Debug.LogError("Block must belong to the same gameobject as this Flowchart");
return false;
}
// Can't restart a running block, have to wait until it's idle again // Can't restart a running block, have to wait until it's idle again
if (block.IsExecuting()) if (block.IsExecuting())
@ -433,10 +422,10 @@ namespace Fungus
return false; return false;
} }
// Execute the first command in the command list // Start executing the Block as a new coroutine
block.Execute(onComplete); StartCoroutine(block.Execute(commandIndex, onComplete));
return true; return true;
} }
/** /**
@ -454,6 +443,32 @@ namespace Fungus
} }
} }
/**
* Sends a message to this Flowchart only.
* Any block with a matching MessageReceived event handler will start executing.
*/
public virtual void SendFungusMessage(string messageName)
{
MessageReceived[] eventHandlers = GetComponentsInChildren<MessageReceived>();
foreach (MessageReceived eventHandler in eventHandlers)
{
eventHandler.OnSendFungusMessage(messageName);
}
}
/**
* Sends a message to all Flowchart objects in the current scene.
* Any block with a matching MessageReceived event handler will start executing.
*/
public static void BroadcastFungusMessage(string messageName)
{
MessageReceived[] eventHandlers = GameObject.FindObjectsOfType<MessageReceived>();
foreach (MessageReceived eventHandler in eventHandlers)
{
eventHandler.OnSendFungusMessage(messageName);
}
}
/** /**
* Returns a new variable key that is guaranteed not to clash with any existing variable in the list. * Returns a new variable key that is guaranteed not to clash with any existing variable in the list.
*/ */
@ -590,6 +605,26 @@ namespace Fungus
} }
} }
/**
* Returns the variable with the specified key, or null if the key is not found.
* You will need to cast the returned variable to the correct sub-type.
* You can then access the variable's value using the Value property. e.g.
* BooleanVariable boolVar = flowchart.GetVariable("MyBool") as BooleanVariable;
* boolVar.Value = false;
*/
public Variable GetVariable(string key)
{
foreach (Variable variable in variables)
{
if (variable != null && variable.key == key)
{
return variable;
}
}
return null;
}
/** /**
* Returns the variable with the specified key, or null if the key is not found. * Returns the variable with the specified key, or null if the key is not found.
* You can then access the variable's value using the Value property. e.g. * You can then access the variable's value using the Value property. e.g.

2
Assets/Fungus/Narrative/Scripts/Commands/Say.cs

@ -99,7 +99,7 @@ namespace Fungus
string subbedText = flowchart.SubstituteVariables(displayText); string subbedText = flowchart.SubstituteVariables(displayText);
sayDialog.Say(subbedText, !extendPrevious, waitForClick, fadeWhenDone, voiceOverClip, stopVoiceover, delegate { sayDialog.Say(subbedText, !extendPrevious, waitForClick, fadeWhenDone, stopVoiceover, voiceOverClip, delegate {
Continue(); Continue();
}); });
} }

10
Assets/Fungus/Narrative/Scripts/MenuDialog.cs

@ -13,8 +13,11 @@ namespace Fungus
// Currently active Menu Dialog used to display Menu options // Currently active Menu Dialog used to display Menu options
public static MenuDialog activeMenuDialog; public static MenuDialog activeMenuDialog;
protected Button[] cachedButtons; [NonSerialized]
protected Slider cachedSlider; public Button[] cachedButtons;
[NonSerialized]
public Slider cachedSlider;
public static MenuDialog GetMenuDialog() public static MenuDialog GetMenuDialog()
{ {
@ -139,7 +142,7 @@ namespace Fungus
return addedOption; return addedOption;
} }
protected virtual void HideSayDialog() public virtual void HideSayDialog()
{ {
SayDialog sayDialog = SayDialog.GetSayDialog(); SayDialog sayDialog = SayDialog.GetSayDialog();
if (sayDialog != null) if (sayDialog != null)
@ -150,7 +153,6 @@ namespace Fungus
public virtual void ShowTimer(float duration, Block targetBlock) public virtual void ShowTimer(float duration, Block targetBlock)
{ {
if (cachedSlider != null) if (cachedSlider != null)
{ {
cachedSlider.gameObject.SetActive(true); cachedSlider.gameObject.SetActive(true);

10
Assets/Fungus/Narrative/Scripts/SayDialog.cs

@ -126,12 +126,12 @@ namespace Fungus
} }
} }
public virtual void Say(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, AudioClip voiceOverClip, bool stopVoiceover, Action onComplete) public virtual void Say(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, bool stopVoiceover, AudioClip voiceOverClip, Action onComplete)
{ {
StartCoroutine(SayInternal(text, clearPrevious, waitForInput, fadeWhenDone, voiceOverClip, stopVoiceover, onComplete)); StartCoroutine(SayInternal(text, clearPrevious, waitForInput, fadeWhenDone, stopVoiceover, voiceOverClip, onComplete));
} }
protected virtual IEnumerator SayInternal(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, AudioClip voiceOverClip, bool stopVoiceover, Action onComplete) public virtual IEnumerator SayInternal(string text, bool clearPrevious, bool waitForInput, bool fadeWhenDone, bool stopVoiceover, AudioClip voiceOverClip, Action onComplete)
{ {
Writer writer = GetWriter(); Writer writer = GetWriter();
@ -144,6 +144,8 @@ namespace Fungus
} }
} }
gameObject.SetActive(true);
this.fadeWhenDone = fadeWhenDone; this.fadeWhenDone = fadeWhenDone;
// Voice over clip takes precedence over a character sound effect if provided // Voice over clip takes precedence over a character sound effect if provided
@ -158,8 +160,8 @@ namespace Fungus
{ {
soundEffectClip = speakingCharacter.soundEffect; soundEffectClip = speakingCharacter.soundEffect;
} }
writer.Write(text, clearPrevious, waitForInput, stopVoiceover, soundEffectClip, onComplete);
yield return writer.Write(text, clearPrevious, waitForInput, stopVoiceover, soundEffectClip, onComplete);
} }
protected virtual void LateUpdate() protected virtual void LateUpdate()

414
Assets/Fungus/Thirdparty/CSVParser/CsvParser.cs vendored

@ -5,215 +5,215 @@ using System.Text;
namespace Ideafixxxer.CsvParser namespace Ideafixxxer.CsvParser
{ {
public class CsvParser public class CsvParser
{ {
private const char CommaCharacter = ','; private const char CommaCharacter = ',';
private const char QuoteCharacter = '"'; private const char QuoteCharacter = '"';
#region Nested types #region Nested types
private abstract class ParserState private abstract class ParserState
{ {
public static readonly LineStartState LineStartState = new LineStartState(); public static readonly LineStartState LineStartState = new LineStartState();
public static readonly ValueStartState ValueStartState = new ValueStartState(); public static readonly ValueStartState ValueStartState = new ValueStartState();
public static readonly ValueState ValueState = new ValueState(); public static readonly ValueState ValueState = new ValueState();
public static readonly QuotedValueState QuotedValueState = new QuotedValueState(); public static readonly QuotedValueState QuotedValueState = new QuotedValueState();
public static readonly QuoteState QuoteState = new QuoteState(); public static readonly QuoteState QuoteState = new QuoteState();
public abstract ParserState AnyChar(char ch, ParserContext context); public abstract ParserState AnyChar(char ch, ParserContext context);
public abstract ParserState Comma(ParserContext context); public abstract ParserState Comma(ParserContext context);
public abstract ParserState Quote(ParserContext context); public abstract ParserState Quote(ParserContext context);
public abstract ParserState EndOfLine(ParserContext context); public abstract ParserState EndOfLine(ParserContext context);
} }
private class LineStartState : ParserState private class LineStartState : ParserState
{ {
public override ParserState AnyChar(char ch, ParserContext context) public override ParserState AnyChar(char ch, ParserContext context)
{ {
context.AddChar(ch); context.AddChar(ch);
return ValueState; return ValueState;
} }
public override ParserState Comma(ParserContext context) public override ParserState Comma(ParserContext context)
{ {
context.AddValue(); context.AddValue();
return ValueStartState; return ValueStartState;
} }
public override ParserState Quote(ParserContext context) public override ParserState Quote(ParserContext context)
{ {
return QuotedValueState; return QuotedValueState;
} }
public override ParserState EndOfLine(ParserContext context) public override ParserState EndOfLine(ParserContext context)
{ {
context.AddLine(); context.AddLine();
return LineStartState; return LineStartState;
} }
} }
private class ValueStartState : LineStartState private class ValueStartState : LineStartState
{ {
public override ParserState EndOfLine(ParserContext context) public override ParserState EndOfLine(ParserContext context)
{ {
context.AddValue(); context.AddValue();
context.AddLine(); context.AddLine();
return LineStartState; return LineStartState;
} }
} }
private class ValueState : ParserState private class ValueState : ParserState
{ {
public override ParserState AnyChar(char ch, ParserContext context) public override ParserState AnyChar(char ch, ParserContext context)
{ {
context.AddChar(ch); context.AddChar(ch);
return ValueState; return ValueState;
} }
public override ParserState Comma(ParserContext context) public override ParserState Comma(ParserContext context)
{ {
context.AddValue(); context.AddValue();
return ValueStartState; return ValueStartState;
} }
public override ParserState Quote(ParserContext context) public override ParserState Quote(ParserContext context)
{ {
context.AddChar(QuoteCharacter); context.AddChar(QuoteCharacter);
return ValueState; return ValueState;
} }
public override ParserState EndOfLine(ParserContext context) public override ParserState EndOfLine(ParserContext context)
{ {
context.AddValue(); context.AddValue();
context.AddLine(); context.AddLine();
return LineStartState; return LineStartState;
} }
} }
private class QuotedValueState : ParserState private class QuotedValueState : ParserState
{ {
public override ParserState AnyChar(char ch, ParserContext context) public override ParserState AnyChar(char ch, ParserContext context)
{ {
context.AddChar(ch); context.AddChar(ch);
return QuotedValueState; return QuotedValueState;
} }
public override ParserState Comma(ParserContext context) public override ParserState Comma(ParserContext context)
{ {
context.AddChar(CommaCharacter); context.AddChar(CommaCharacter);
return QuotedValueState; return QuotedValueState;
} }
public override ParserState Quote(ParserContext context) public override ParserState Quote(ParserContext context)
{ {
return QuoteState; return QuoteState;
} }
public override ParserState EndOfLine(ParserContext context) public override ParserState EndOfLine(ParserContext context)
{ {
context.AddChar('\r'); context.AddChar('\r');
context.AddChar('\n'); context.AddChar('\n');
return QuotedValueState; return QuotedValueState;
} }
} }
private class QuoteState : ParserState private class QuoteState : ParserState
{ {
public override ParserState AnyChar(char ch, ParserContext context) public override ParserState AnyChar(char ch, ParserContext context)
{ {
//undefined, ignore " //undefined, ignore "
context.AddChar(ch); context.AddChar(ch);
return QuotedValueState; return QuotedValueState;
} }
public override ParserState Comma(ParserContext context) public override ParserState Comma(ParserContext context)
{ {
context.AddValue(); context.AddValue();
return ValueStartState; return ValueStartState;
} }
public override ParserState Quote(ParserContext context) public override ParserState Quote(ParserContext context)
{ {
context.AddChar(QuoteCharacter); context.AddChar(QuoteCharacter);
return QuotedValueState; return QuotedValueState;
} }
public override ParserState EndOfLine(ParserContext context) public override ParserState EndOfLine(ParserContext context)
{ {
context.AddValue(); context.AddValue();
context.AddLine(); context.AddLine();
return LineStartState; return LineStartState;
} }
} }
private class ParserContext private class ParserContext
{ {
private readonly StringBuilder _currentValue = new StringBuilder(); private readonly StringBuilder _currentValue = new StringBuilder();
private readonly List<string[]> _lines = new List<string[]>(); private readonly List<string[]> _lines = new List<string[]>();
private readonly List<string> _currentLine = new List<string>(); private readonly List<string> _currentLine = new List<string>();
public void AddChar(char ch) public void AddChar(char ch)
{ {
_currentValue.Append(ch); _currentValue.Append(ch);
} }
public void AddValue() public void AddValue()
{ {
_currentLine.Add(_currentValue.ToString()); _currentLine.Add(_currentValue.ToString());
_currentValue.Remove(0, _currentValue.Length); _currentValue.Remove(0, _currentValue.Length);
} }
public void AddLine() public void AddLine()
{ {
_lines.Add(_currentLine.ToArray()); _lines.Add(_currentLine.ToArray());
_currentLine.Clear(); _currentLine.Clear();
} }
public List<string[]> GetAllLines() public List<string[]> GetAllLines()
{ {
if (_currentValue.Length > 0) if (_currentValue.Length > 0)
{ {
AddValue(); AddValue();
} }
if (_currentLine.Count > 0) if (_currentLine.Count > 0)
{ {
AddLine(); AddLine();
} }
return _lines; return _lines;
} }
} }
#endregion #endregion
public string[][] Parse(string csvData) public string[][] Parse(string csvData)
{ {
var context = new ParserContext(); var context = new ParserContext();
// Handle both Windows and Mac line endings // Handle both Windows and Mac line endings
string[] lines = csvData.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries); string[] lines = csvData.Split(new string[] { "\r\n", "\n" }, StringSplitOptions.RemoveEmptyEntries);
ParserState currentState = ParserState.LineStartState; ParserState currentState = ParserState.LineStartState;
foreach (string next in lines) foreach (string next in lines)
{ {
foreach (char ch in next) foreach (char ch in next)
{ {
switch (ch) switch (ch)
{ {
case CommaCharacter: case CommaCharacter:
currentState = currentState.Comma(context); currentState = currentState.Comma(context);
break; break;
case QuoteCharacter: case QuoteCharacter:
currentState = currentState.Quote(context); currentState = currentState.Quote(context);
break; break;
default: default:
currentState = currentState.AnyChar(ch, context); currentState = currentState.AnyChar(ch, context);
break; break;
} }
} }
currentState = currentState.EndOfLine(context); currentState = currentState.EndOfLine(context);
} }
List<string[]> allLines = context.GetAllLines(); List<string[]> allLines = context.GetAllLines();
return allLines.ToArray(); return allLines.ToArray();
} }
} }
} }

6
Assets/Fungus/UI/Scripts/Commands/Write.cs

@ -86,14 +86,14 @@ namespace Fungus
if (!waitUntilFinished) if (!waitUntilFinished)
{ {
writer.Write(newText, clearText, false, true, null, null); StartCoroutine(writer.Write(newText, clearText, false, true, null, null));
Continue(); Continue();
} }
else else
{ {
writer.Write(newText, clearText, false, true, null, StartCoroutine(writer.Write(newText, clearText, false, true, null,
() => { Continue (); } () => { Continue (); }
); ));
} }
} }

8
Assets/Fungus/UI/Scripts/Writer.cs

@ -317,7 +317,7 @@ namespace Fungus
} }
} }
public virtual void Write(string content, bool clear, bool waitForInput, bool stopAudio, AudioClip audioClip, Action onComplete) public virtual IEnumerator Write(string content, bool clear, bool waitForInput, bool stopAudio, AudioClip audioClip, Action onComplete)
{ {
if (clear) if (clear)
{ {
@ -326,7 +326,7 @@ namespace Fungus
if (!HasTextObject()) if (!HasTextObject())
{ {
return; yield break;
} }
// If this clip is null then WriterAudio will play the default sound effect (if any) // If this clip is null then WriterAudio will play the default sound effect (if any)
@ -341,7 +341,9 @@ namespace Fungus
TextTagParser tagParser = new TextTagParser(); TextTagParser tagParser = new TextTagParser();
List<TextTagParser.Token> tokens = tagParser.Tokenize(tokenText); List<TextTagParser.Token> tokens = tagParser.Tokenize(tokenText);
StartCoroutine(ProcessTokens(tokens, stopAudio, onComplete)); gameObject.SetActive(true);
yield return StartCoroutine(ProcessTokens(tokens, stopAudio, onComplete));
} }
virtual protected bool CheckParamCount(List<string> paramList, int count) virtual protected bool CheckParamCount(List<string> paramList, int count)

72
Assets/Tests/Scripting/Scripting.unity

@ -196,7 +196,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -209,8 +209,7 @@ MonoBehaviour:
width: 1114 width: 1114
height: 859 height: 859
selectedBlock: {fileID: 115525222} selectedBlock: {fileID: 115525222}
selectedCommands: selectedCommands: []
- {fileID: 115525219}
variables: [] variables: []
description: description:
stepPause: 0 stepPause: 0
@ -279,7 +278,10 @@ MonoBehaviour:
itemId: 1 itemId: 1
errorMessage: errorMessage:
indentLevel: 0 indentLevel: 0
duration: 3 _duration:
floatRef: {fileID: 0}
floatVal: 3
durationOLD: 0
--- !u!114 &169310213 --- !u!114 &169310213
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 2 m_ObjectHideFlags: 2
@ -330,7 +332,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -433,7 +435,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -967,7 +969,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -1073,7 +1075,10 @@ MonoBehaviour:
itemId: 3 itemId: 3
errorMessage: errorMessage:
indentLevel: 0 indentLevel: 0
duration: 1 _duration:
floatRef: {fileID: 0}
floatVal: 1
durationOLD: 0
--- !u!114 &575910003 --- !u!114 &575910003
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 2 m_ObjectHideFlags: 2
@ -1134,6 +1139,7 @@ MonoBehaviour:
extendPrevious: 0 extendPrevious: 0
fadeWhenDone: 1 fadeWhenDone: 1
waitForClick: 1 waitForClick: 1
stopVoiceover: 1
setSayDialog: {fileID: 0} setSayDialog: {fileID: 0}
--- !u!114 &575910006 --- !u!114 &575910006
MonoBehaviour: MonoBehaviour:
@ -1185,7 +1191,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -1310,7 +1316,10 @@ MonoBehaviour:
itemId: 3 itemId: 3
errorMessage: errorMessage:
indentLevel: 0 indentLevel: 0
duration: 1 _duration:
floatRef: {fileID: 0}
floatVal: 1
durationOLD: 0
--- !u!114 &590474777 --- !u!114 &590474777
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 2 m_ObjectHideFlags: 2
@ -1398,7 +1407,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -1530,7 +1539,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -1595,7 +1604,10 @@ MonoBehaviour:
itemId: 3 itemId: 3
errorMessage: errorMessage:
indentLevel: 0 indentLevel: 0
duration: 1 _duration:
floatRef: {fileID: 0}
floatVal: 1
durationOLD: 0
--- !u!114 &636123612 --- !u!114 &636123612
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 2 m_ObjectHideFlags: 2
@ -1708,7 +1720,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 61dddfdc5e0e44ca298d8f46f7f5a915, type: 3} m_Script: {fileID: 11500000, guid: 61dddfdc5e0e44ca298d8f46f7f5a915, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
selectedFlowchart: {fileID: 115525223} selectedFlowchart: {fileID: 1618689129}
--- !u!4 &646902075 --- !u!4 &646902075
Transform: Transform:
m_ObjectHideFlags: 1 m_ObjectHideFlags: 1
@ -1736,7 +1748,7 @@ GameObject:
m_Icon: {fileID: 0} m_Icon: {fileID: 0}
m_NavMeshLayer: 0 m_NavMeshLayer: 0
m_StaticEditorFlags: 0 m_StaticEditorFlags: 0
m_IsActive: 1 m_IsActive: 0
--- !u!114 &676156675 --- !u!114 &676156675
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 0
@ -2320,7 +2332,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1
@ -2334,7 +2346,7 @@ MonoBehaviour:
height: 873 height: 873
selectedBlock: {fileID: 1618689131} selectedBlock: {fileID: 1618689131}
selectedCommands: selectedCommands:
- {fileID: 1618689152} - {fileID: 1618689150}
variables: variables:
- {fileID: 1618689138} - {fileID: 1618689138}
- {fileID: 1618689141} - {fileID: 1618689141}
@ -2719,7 +2731,7 @@ MonoBehaviour:
callMode: 0 callMode: 0
--- !u!114 &1618689140 --- !u!114 &1618689140
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1618689128} m_GameObject: {fileID: 1618689128}
@ -2858,7 +2870,7 @@ MonoBehaviour:
callMode: 0 callMode: 0
--- !u!114 &1618689147 --- !u!114 &1618689147
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1618689128} m_GameObject: {fileID: 1618689128}
@ -2884,7 +2896,7 @@ MonoBehaviour:
- {fileID: 1618689148} - {fileID: 1618689148}
--- !u!114 &1618689148 --- !u!114 &1618689148
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1618689128} m_GameObject: {fileID: 1618689128}
@ -2948,7 +2960,7 @@ MonoBehaviour:
Culture=neutral, PublicKeyToken=null Culture=neutral, PublicKeyToken=null
--- !u!114 &1618689149 --- !u!114 &1618689149
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1618689128} m_GameObject: {fileID: 1618689128}
@ -2975,7 +2987,7 @@ MonoBehaviour:
callMode: 0 callMode: 0
--- !u!114 &1618689150 --- !u!114 &1618689150
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1618689128} m_GameObject: {fileID: 1618689128}
@ -2993,7 +3005,7 @@ MonoBehaviour:
targetComponentFullname: UnityEngine.Component[] targetComponentFullname: UnityEngine.Component[]
targetComponentText: Flowchart targetComponentText: Flowchart
targetMethod: ExecuteBlock targetMethod: ExecuteBlock
targetMethodText: 'ExecuteBlock (String): Void' targetMethodText: 'ExecuteBlock (String): Boolean'
methodParameters: methodParameters:
- objValue: - objValue:
typeAssemblyname: System.String, mscorlib, Version=2.0.0.0, Culture=neutral, typeAssemblyname: System.String, mscorlib, Version=2.0.0.0, Culture=neutral,
@ -3014,12 +3026,12 @@ MonoBehaviour:
variableKey: variableKey:
saveReturnValue: 0 saveReturnValue: 0
returnValueVariableKey: returnValueVariableKey:
returnValueType: System.Void returnValueType: System.Boolean
showInherited: 0 showInherited: 0
callMode: 0 callMode: 0
--- !u!114 &1618689151 --- !u!114 &1618689151
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1618689128} m_GameObject: {fileID: 1618689128}
@ -3031,10 +3043,13 @@ MonoBehaviour:
itemId: 16 itemId: 16
errorMessage: errorMessage:
indentLevel: 0 indentLevel: 0
duration: 1 _duration:
floatRef: {fileID: 0}
floatVal: 1
durationOLD: 0
--- !u!114 &1618689152 --- !u!114 &1618689152
MonoBehaviour: MonoBehaviour:
m_ObjectHideFlags: 0 m_ObjectHideFlags: 2
m_PrefabParentObject: {fileID: 0} m_PrefabParentObject: {fileID: 0}
m_PrefabInternal: {fileID: 0} m_PrefabInternal: {fileID: 0}
m_GameObject: {fileID: 1618689128} m_GameObject: {fileID: 1618689128}
@ -3314,6 +3329,7 @@ Canvas:
m_ReceivesEvents: 1 m_ReceivesEvents: 1
m_OverrideSorting: 0 m_OverrideSorting: 0
m_OverridePixelPerfect: 0 m_OverridePixelPerfect: 0
m_SortingBucketNormalizedSize: 0
m_SortingLayerID: 0 m_SortingLayerID: 0
m_SortingOrder: 0 m_SortingOrder: 0
m_TargetDisplay: 0 m_TargetDisplay: 0
@ -3438,7 +3454,7 @@ MonoBehaviour:
m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3} m_Script: {fileID: 11500000, guid: 7a334fe2ffb574b3583ff3b18b4792d3, type: 3}
m_Name: m_Name:
m_EditorClassIdentifier: m_EditorClassIdentifier:
version: 1.0 version: 1
scrollPos: {x: 0, y: 0} scrollPos: {x: 0, y: 0}
variablesScrollPos: {x: 0, y: 0} variablesScrollPos: {x: 0, y: 0}
variablesExpanded: 1 variablesExpanded: 1

Loading…
Cancel
Save