diff --git a/Editor/Editors/YarnProjectImporterEditor.cs b/Editor/Editors/YarnProjectImporterEditor.cs index 7db89bdf..ec25e82d 100644 --- a/Editor/Editors/YarnProjectImporterEditor.cs +++ b/Editor/Editors/YarnProjectImporterEditor.cs @@ -249,29 +249,25 @@ protected override void Apply() var name = decl.FindPropertyRelative("name").stringValue; - SerializedProperty typeProperty = decl.FindPropertyRelative("type"); + SerializedProperty typeProperty = decl.FindPropertyRelative("typeName"); - Type type = (Yarn.Type)typeProperty.enumValueIndex; + Yarn.IType type = YarnProjectImporter.SerializedDeclaration.BuiltInTypesList.FirstOrDefault(t => t.Name == typeProperty.stringValue); var description = decl.FindPropertyRelative("description").stringValue; - object defaultValue; - switch (type) - { - case Yarn.Type.Number: - defaultValue = decl.FindPropertyRelative("defaultValueNumber").floatValue; - break; - case Yarn.Type.String: - defaultValue = decl.FindPropertyRelative("defaultValueString").stringValue; - break; - case Yarn.Type.Bool: - defaultValue = decl.FindPropertyRelative("defaultValueBool").boolValue; - break; - default: - throw new System.ArgumentOutOfRangeException($"Invalid declaration type {type}"); - } + System.IConvertible defaultValue; - var declaration = Declaration.CreateVariable(name, defaultValue, description); + if (type == Yarn.BuiltinTypes.Number) { + defaultValue = decl.FindPropertyRelative("defaultValueNumber").floatValue; + } else if (type == Yarn.BuiltinTypes.String) { + defaultValue = decl.FindPropertyRelative("defaultValueString").stringValue; + } else if (type == Yarn.BuiltinTypes.Boolean) { + defaultValue = decl.FindPropertyRelative("defaultValueBool").boolValue; + } else { + throw new System.ArgumentOutOfRangeException($"Invalid declaration type {type.Name}"); + } + + var declaration = Declaration.CreateVariable(name, type, defaultValue, description); thisProgramDeclarations.Add(declaration); } diff --git a/Editor/Importers/YarnProjectImporter.cs b/Editor/Importers/YarnProjectImporter.cs index ecb5ec4d..62d87371 100644 --- a/Editor/Importers/YarnProjectImporter.cs +++ b/Editor/Importers/YarnProjectImporter.cs @@ -21,8 +21,17 @@ public class YarnProjectImporter : ScriptedImporter [System.Serializable] public class SerializedDeclaration { + internal static List BuiltInTypesList = new List { + Yarn.BuiltinTypes.String, + Yarn.BuiltinTypes.Boolean, + Yarn.BuiltinTypes.Number, + }; + public string name = "$variable"; - public Yarn.Type type = Yarn.Type.String; + + [UnityEngine.Serialization.FormerlySerializedAs("type")] + public string typeName = Yarn.BuiltinTypes.String.Name; + public bool defaultValueBool; public float defaultValueNumber; public string defaultValueString; @@ -36,25 +45,20 @@ public class SerializedDeclaration public SerializedDeclaration(Declaration decl) { this.name = decl.Name; - this.type = decl.ReturnType; + this.typeName = decl.Type.Name; this.description = decl.Description; this.isImplicit = decl.IsImplicit; sourceYarnAsset = AssetDatabase.LoadAssetAtPath(decl.SourceFileName); - switch (this.type) - { - case Type.Number: - this.defaultValueNumber = System.Convert.ToSingle(decl.DefaultValue); - break; - case Type.String: - this.defaultValueString = System.Convert.ToString(decl.DefaultValue); - break; - case Type.Bool: - this.defaultValueBool = System.Convert.ToBoolean(decl.DefaultValue); - break; - default: - throw new System.InvalidOperationException($"Invalid declaration type {decl.ReturnType}"); + if (this.typeName == BuiltinTypes.String.Name) { + this.defaultValueString = System.Convert.ToString(decl.DefaultValue); + } else if (this.typeName == BuiltinTypes.Boolean.Name) { + this.defaultValueBool = System.Convert.ToBoolean(decl.DefaultValue); + } else if (this.typeName == BuiltinTypes.Number.Name) { + this.defaultValueNumber = System.Convert.ToSingle(decl.DefaultValue); + } else { + throw new System.InvalidOperationException($"Invalid declaration type {decl.Type.Name}"); } } } @@ -160,7 +164,7 @@ public override void OnImportAsset(AssetImportContext ctx) // We'll replace this with a more complete list later if // compilation succeeds. serializedDeclarations = localDeclarations - .Where(decl => decl.DeclarationType == Declaration.Type.Variable) + .Where(decl => !(decl.Type is FunctionType)) .Select(decl => new SerializedDeclaration(decl)).ToList(); // We're done processing this file - we've parsed it, and @@ -233,7 +237,7 @@ public override void OnImportAsset(AssetImportContext ctx) // .yarnproject file, and the ones inside the .yarn files serializedDeclarations = localDeclarations .Concat(compilationResult.Declarations) - .Where(decl => decl.DeclarationType == Declaration.Type.Variable) + .Where(decl => !(decl.Type is FunctionType)) .Select(decl => new SerializedDeclaration(decl)).ToList(); // Clear error messages from all scripts - they've all passed @@ -575,13 +579,13 @@ private void OnAdd(ReorderableList list) // Clear necessary properties to something useful var nameProp = entry.FindPropertyRelative("name"); - var typeProp = entry.FindPropertyRelative("type"); + var typeProp = entry.FindPropertyRelative("typeName"); var defaultValueStringProp = entry.FindPropertyRelative("defaultValueString"); var sourceYarnAssetProp = entry.FindPropertyRelative("sourceYarnAsset"); var descriptionProp = entry.FindPropertyRelative("description"); nameProp.stringValue = "$variable"; - typeProp.enumValueIndex = (int)Yarn.Type.String; + typeProp.enumValueIndex = YarnProjectImporter.SerializedDeclaration.BuiltInTypesList.IndexOf(Yarn.BuiltinTypes.String); defaultValueStringProp.stringValue = string.Empty; sourceYarnAssetProp.objectReferenceValue = null; descriptionProp.stringValue = string.Empty; @@ -877,32 +881,41 @@ Rect RectForFieldIndex(int index, int lineCount = 1) DrawPropertyField(namePosition, nameProperty, propertyIsReadOnly); - SerializedProperty typeProperty = property.FindPropertyRelative("type"); + SerializedProperty typeProperty = property.FindPropertyRelative("typeName"); + + if (propertyIsReadOnly) { + DrawPropertyField(typePosition, typeProperty, true); + } else { + var popupElements = YarnProjectImporter.SerializedDeclaration.BuiltInTypesList; + var popupElementNames = popupElements.Select(t => t.Name).ToList(); + var selectedIndex = popupElementNames.IndexOf(typeProperty.stringValue); - DrawPropertyField(typePosition, typeProperty, propertyIsReadOnly); + var prefixPosition = EditorGUI.PrefixLabel(typePosition, new GUIContent("Type")); + + selectedIndex = EditorGUI.Popup(prefixPosition, selectedIndex, popupElementNames.ToArray()); + if (selectedIndex >= 0 && selectedIndex <= popupElementNames.Count) { + typeProperty.stringValue = popupElementNames[selectedIndex]; + } + } SerializedProperty defaultValueProperty; - switch ((Yarn.Type)typeProperty.enumValueIndex) - { - case Yarn.Type.Number: - defaultValueProperty = property.FindPropertyRelative("defaultValueNumber"); - break; - case Yarn.Type.String: - defaultValueProperty = property.FindPropertyRelative("defaultValueString"); - break; - case Yarn.Type.Bool: - defaultValueProperty = property.FindPropertyRelative("defaultValueBool"); - break; - default: - defaultValueProperty = null; - break; + var type = YarnProjectImporter.SerializedDeclaration.BuiltInTypesList.FirstOrDefault(t => t.Name == typeProperty.stringValue); + + if (type == BuiltinTypes.Number) { + defaultValueProperty = property.FindPropertyRelative("defaultValueNumber"); + } else if (type == BuiltinTypes.String) { + defaultValueProperty = property.FindPropertyRelative("defaultValueString"); + } else if (type == BuiltinTypes.Boolean) { + defaultValueProperty = property.FindPropertyRelative("defaultValueBool"); + } else { + defaultValueProperty = null; } if (defaultValueProperty == null) { - EditorGUI.LabelField(defaultValuePosition, "Default Value", $"Variable type {(Yarn.Type)typeProperty.enumValueIndex} is not allowed"); + EditorGUI.LabelField(defaultValuePosition, "Default Value", $"Variable type {typeProperty.stringValue} is not allowed"); } else { diff --git a/Editor/Utility/YarnProjectUtility.cs b/Editor/Utility/YarnProjectUtility.cs index fb9c7f31..de66fa1c 100644 --- a/Editor/Utility/YarnProjectUtility.cs +++ b/Editor/Utility/YarnProjectUtility.cs @@ -544,7 +544,7 @@ internal static void ConvertImplicitVariableDeclarationsToExplicit(YarnProjectIm return; } - var implicitDeclarations = implicitResult.Declarations.Where(d => d.DeclarationType == Compiler.Declaration.Type.Variable && d.IsImplicit); + var implicitDeclarations = implicitResult.Declarations.Where(d => !(d.Type is Yarn.FunctionType) && d.IsImplicit); var output = Yarn.Compiler.Utility.GenerateYarnFileWithDeclarations(explicitResult.Declarations.Concat(implicitDeclarations), "Program"); diff --git a/Runtime/DLLs/YarnSpinner.Compiler.dll b/Runtime/DLLs/YarnSpinner.Compiler.dll index 3797cecf..e350edb2 100644 Binary files a/Runtime/DLLs/YarnSpinner.Compiler.dll and b/Runtime/DLLs/YarnSpinner.Compiler.dll differ diff --git a/Runtime/DLLs/YarnSpinner.dll b/Runtime/DLLs/YarnSpinner.dll index 1aea8ac1..90f242b3 100644 Binary files a/Runtime/DLLs/YarnSpinner.dll and b/Runtime/DLLs/YarnSpinner.dll differ diff --git a/Runtime/InMemoryVariableStorage.cs b/Runtime/InMemoryVariableStorage.cs index 1358bb09..67e71a27 100644 --- a/Runtime/InMemoryVariableStorage.cs +++ b/Runtime/InMemoryVariableStorage.cs @@ -94,37 +94,39 @@ public string GetDebugList() /// Used internally by serialization functions to wrap around the /// SetValue() methods. /// - void SetVariable(string name, Yarn.Type type, string value) + void SetVariable(string name, Yarn.IType type, string value) { - switch (type) + if (type == Yarn.BuiltinTypes.Boolean) { - case Type.Bool: - bool newBool; - if (bool.TryParse(value, out newBool)) - { - SetValue(name, newBool); - } - else - { - throw new System.InvalidCastException($"Couldn't initialize default variable {name} with value {value} as Bool"); - } - break; - case Type.Number: - float newNumber; - if (float.TryParse(value, out newNumber)) - { // TODO: this won't work for different cultures (e.g. French write "0.53" as "0,53") - SetValue(name, newNumber); - } - else - { - throw new System.InvalidCastException($"Couldn't initialize default variable {name} with value {value} as Number (Float)"); - } - break; - case Type.String: - case Type.Undefined: - default: - SetValue(name, value); // no special type conversion required - break; + bool newBool; + if (bool.TryParse(value, out newBool)) + { + SetValue(name, newBool); + } + else + { + throw new System.InvalidCastException($"Couldn't initialize default variable {name} with value {value} as Bool"); + } + } + else if (type == Yarn.BuiltinTypes.Number) + { + float newNumber; + if (float.TryParse(value, out newNumber)) + { // TODO: this won't work for different cultures (e.g. French write "0.53" as "0,53") + SetValue(name, newNumber); + } + else + { + throw new System.InvalidCastException($"Couldn't initialize default variable {name} with value {value} as Number (Float)"); + } + } + else if (type == Yarn.BuiltinTypes.String) + { + SetValue(name, value); // no special type conversion required + } + else + { + throw new System.ArgumentOutOfRangeException($"Unsupported type {type.Name}"); } } @@ -332,21 +334,21 @@ public void LoadFromFile(string filepath) Debug.Log($"Variables loaded from file {filepath}"); } - public static readonly Dictionary TypeMappings = new Dictionary + public static readonly Dictionary TypeMappings = new Dictionary { - { typeof(string), Yarn.Type.String }, - { typeof(bool), Yarn.Type.Bool }, - { typeof(int), Yarn.Type.Number }, - { typeof(float), Yarn.Type.Number }, - { typeof(double), Yarn.Type.Number }, - { typeof(sbyte), Yarn.Type.Number }, - { typeof(byte), Yarn.Type.Number }, - { typeof(short), Yarn.Type.Number }, - { typeof(ushort), Yarn.Type.Number }, - { typeof(uint), Yarn.Type.Number }, - { typeof(long), Yarn.Type.Number }, - { typeof(ulong), Yarn.Type.Number }, - { typeof(decimal), Yarn.Type.Number }, + { typeof(string), Yarn.BuiltinTypes.String }, + { typeof(bool), Yarn.BuiltinTypes.Boolean }, + { typeof(int), Yarn.BuiltinTypes.Number }, + { typeof(float), Yarn.BuiltinTypes.Number }, + { typeof(double), Yarn.BuiltinTypes.Number }, + { typeof(sbyte), Yarn.BuiltinTypes.Number }, + { typeof(byte), Yarn.BuiltinTypes.Number }, + { typeof(short), Yarn.BuiltinTypes.Number }, + { typeof(ushort), Yarn.BuiltinTypes.Number }, + { typeof(uint), Yarn.BuiltinTypes.Number }, + { typeof(long), Yarn.BuiltinTypes.Number }, + { typeof(ulong), Yarn.BuiltinTypes.Number }, + { typeof(decimal), Yarn.BuiltinTypes.Number }, }; #endregion diff --git a/Samples~/Space/Dialogue/Space.yarnproject.meta b/Samples~/Space/Dialogue/Space.yarnproject.meta index cba8d772..54b07f3c 100644 --- a/Samples~/Space/Dialogue/Space.yarnproject.meta +++ b/Samples~/Space/Dialogue/Space.yarnproject.meta @@ -17,7 +17,7 @@ ScriptedImporter: compileError: serializedDeclarations: - name: $should_see_ship - type: 3 + typeName: Bool defaultValueBool: 0 defaultValueNumber: 0 defaultValueString: @@ -25,7 +25,7 @@ ScriptedImporter: isImplicit: 0 sourceYarnAsset: {instanceID: 0} - name: $sally_warning - type: 3 + typeName: Bool defaultValueBool: 0 defaultValueNumber: 0 defaultValueString: diff --git a/Tests/Runtime/Tests.yarnproject.meta b/Tests/Runtime/Tests.yarnproject.meta index c1a524bb..2971f473 100644 --- a/Tests/Runtime/Tests.yarnproject.meta +++ b/Tests/Runtime/Tests.yarnproject.meta @@ -19,7 +19,7 @@ ScriptedImporter: compileError: serializedDeclarations: - name: $laps - type: 1 + typeName: Bool defaultValueBool: 0 defaultValueNumber: 0 defaultValueString: