Second commit
This commit is contained in:
commit
36840f3ad4
999 files changed
+61364
No files matched your search
@@ -0,0 +1,166 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public enum FgdClassType
|
||||
{
|
||||
Base,
|
||||
|
||||
Point,
|
||||
Brush,
|
||||
}
|
||||
|
||||
public class FgdClass
|
||||
{
|
||||
public FgdClass(FgdClassType type, string name, string description)
|
||||
{
|
||||
Type = type;
|
||||
Name = name;
|
||||
Description = description;
|
||||
}
|
||||
|
||||
public FgdClassType Type { get; }
|
||||
public string Name { get; }
|
||||
public string Description { get; set; }
|
||||
public bool HasModel { get; init; }
|
||||
public Color? Colour { get; init; }
|
||||
public string Sprite { get; init; }
|
||||
public Bounds? Box { get; init; }
|
||||
|
||||
private readonly List<string> m_BaseClasses = new();
|
||||
private readonly List<FgdFieldBase> m_Fields = new();
|
||||
private readonly List<FgdSpawnFlagField> m_SpawnFlags = new();
|
||||
|
||||
public void AddBaseClass(string baseClass) => m_BaseClasses.Add(baseClass);
|
||||
|
||||
public void AddBaseClassInterfaces(Type entityType)
|
||||
{
|
||||
foreach (Type iface in entityType.GetInterfaces())
|
||||
{
|
||||
if (!iface.GetInterfaces().Contains(typeof(ITrembleBaseClass)))
|
||||
continue;
|
||||
|
||||
AddBaseClass(iface.Name.Substring(1)); // Remove 'I'
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public void AddField(FgdFieldBase fgdField)
|
||||
{
|
||||
if (fgdField is FgdSpawnFlagField flag)
|
||||
{
|
||||
m_SpawnFlags.Add(flag);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_Fields.Add(fgdField);
|
||||
}
|
||||
}
|
||||
|
||||
public List<FgdFieldBase> AllFields => m_Fields;
|
||||
public List<FgdSpawnFlagField> AllSpawnFlags => m_SpawnFlags;
|
||||
public List<string> BaseClassNames => m_BaseClasses;
|
||||
|
||||
public bool HasField(string name) => m_Fields.Any(m => m.FieldName.EqualsInvariant(name, caseSensitive: true));
|
||||
|
||||
public bool HasSpawnFlag(int bit) => m_SpawnFlags.Any(sf => sf.Bit == bit);
|
||||
|
||||
public void AddComment(string comment)
|
||||
{
|
||||
m_Fields.Add(new FgdComment { Comment = comment });
|
||||
}
|
||||
|
||||
public void WriteFgd(StreamWriter stream, float importScale)
|
||||
{
|
||||
string typeString = Type switch
|
||||
{
|
||||
FgdClassType.Base => "@BaseClass",
|
||||
FgdClassType.Point => "@PointClass",
|
||||
FgdClassType.Brush => "@SolidClass",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
stream.WriteLine(typeString);
|
||||
|
||||
if (m_BaseClasses.Count > 0)
|
||||
{
|
||||
string baseList = String.Join(", ", m_BaseClasses);
|
||||
stream.WriteLine($"\tbase({baseList})");
|
||||
}
|
||||
|
||||
if (HasModel)
|
||||
{
|
||||
stream.WriteLine($"\tmodel({{ path: \"models/{Name}.md3\", scale: scale }})");
|
||||
}
|
||||
|
||||
if (Colour.HasValue)
|
||||
{
|
||||
stream.WriteLine($"\tcolor({Colour.Value.ToStringInvariant()})");
|
||||
}
|
||||
|
||||
if (!Sprite.IsNullOrEmpty())
|
||||
{
|
||||
stream.WriteLine($"\tsprite(\"models/{Sprite}.png\")");
|
||||
}
|
||||
|
||||
if (Box.HasValue)
|
||||
{
|
||||
Vector3 q3Min = Box.Value.min.UnityToQ3Vector(scale: importScale);
|
||||
Vector3 q3Max = Box.Value.max.UnityToQ3Vector(scale: importScale);
|
||||
|
||||
// From xage on TB Discord: bboxes need to be symmetrical
|
||||
Vector3 extents = new()
|
||||
{
|
||||
x = (Mathf.Abs(q3Min.x) + Mathf.Abs(q3Max.x)),
|
||||
y = (Mathf.Abs(q3Min.y) + Mathf.Abs(q3Max.y)),
|
||||
z = (Mathf.Abs(q3Min.z) + Mathf.Abs(q3Max.z))
|
||||
};
|
||||
|
||||
stream.WriteLine($"\tsize({Mathf.RoundToInt(extents.x)} {Mathf.RoundToInt(extents.y)} {Mathf.RoundToInt(extents.z)})");
|
||||
}
|
||||
|
||||
stream.Write($" = {Name} : \"{Description}\"");
|
||||
|
||||
// Write fields, and then spawnflags fields
|
||||
if (m_Fields.Count == 0 && m_SpawnFlags.Count == 0)
|
||||
{
|
||||
stream.WriteLine(" []");
|
||||
}
|
||||
else
|
||||
{
|
||||
stream.WriteLine();
|
||||
stream.WriteLine("[");
|
||||
|
||||
foreach (FgdFieldBase variable in m_Fields)
|
||||
{
|
||||
stream.Write("\t");
|
||||
variable.Write(stream);
|
||||
}
|
||||
|
||||
if (m_SpawnFlags.Count > 0)
|
||||
{
|
||||
stream.WriteLine("\tspawnflags(Flags) = ");
|
||||
stream.WriteLine("\t[");
|
||||
foreach (FgdSpawnFlagField flag in m_SpawnFlags.OrderBy(sf => sf.Bit))
|
||||
{
|
||||
stream.Write("\t\t");
|
||||
flag.Write(stream);
|
||||
}
|
||||
|
||||
stream.WriteLine("\t]");
|
||||
}
|
||||
|
||||
stream.WriteLine("]");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: e3de2d23101644c9a58c281bfcca7eae
|
||||
timeCreated: 1709808579
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FgdClass.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,89 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public abstract class FgdFieldBase
|
||||
{
|
||||
public abstract void Write(StreamWriter sw);
|
||||
public abstract void WriteCSharpClass(StreamWriter sw, int indent);
|
||||
public abstract void WriteCSharpInterface(StreamWriter sw, int indent);
|
||||
|
||||
public virtual string FieldName => null;
|
||||
|
||||
public string FriendlyTypeName
|
||||
{
|
||||
get
|
||||
{
|
||||
string friendlyTypeName = GetType().Name;
|
||||
if (friendlyTypeName.StartsWithInvariant("Fgd", caseSensitive: true))
|
||||
{
|
||||
friendlyTypeName = friendlyTypeName.Remove(0, 3);
|
||||
}
|
||||
|
||||
if (friendlyTypeName.EndsWithInvariant("Field", caseSensitive: true))
|
||||
{
|
||||
friendlyTypeName = friendlyTypeName.Remove(friendlyTypeName.Length - 5, 5);
|
||||
}
|
||||
return friendlyTypeName;
|
||||
}
|
||||
}
|
||||
|
||||
protected void WriteClassField(StreamWriter sw, int indent, string unityType, string name, string description, string defaultValue = null, string extraAttributes = null)
|
||||
{
|
||||
sw.WriteIndent(indent);
|
||||
|
||||
sw.Write("[");
|
||||
{
|
||||
if (!TrembleSyncSettings.Get().SyncSerializedFields)
|
||||
{
|
||||
sw.Write("Tremble, ");
|
||||
}
|
||||
|
||||
sw.Write($"SerializeField");
|
||||
if (!description.IsNullOrEmpty())
|
||||
{
|
||||
sw.Write($", Tooltip(\"{description}\")");
|
||||
}
|
||||
}
|
||||
|
||||
if (!extraAttributes.IsNullOrEmpty())
|
||||
{
|
||||
sw.Write(", ");
|
||||
sw.Write(extraAttributes);
|
||||
}
|
||||
|
||||
sw.Write("] ");
|
||||
|
||||
sw.Write($"private {unityType} m_{name.ToNamingConvention(NamingConvention.UpperCamelCase)}");
|
||||
|
||||
if (defaultValue == null)
|
||||
{
|
||||
sw.WriteLine(";");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($" = {defaultValue};");
|
||||
}
|
||||
}
|
||||
protected void WriteInterfaceProperty(StreamWriter sw, int indent, string unityType, string name, string description, string attributes = null)
|
||||
{
|
||||
sw.WriteIndent(indent);
|
||||
|
||||
if (!attributes.IsNullOrEmpty())
|
||||
{
|
||||
sw.Write("[");
|
||||
sw.Write(attributes);
|
||||
sw.Write("] ");
|
||||
}
|
||||
|
||||
sw.Write($"public {unityType} {name.ToNamingConvention(NamingConvention.UpperCamelCase)} => default;");
|
||||
sw.WriteLine(description.IsNullOrEmpty() ? "" : $" // \"{description}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f13869dde160409ca3a827a856d24d48
|
||||
timeCreated: 1698227234
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FgdFieldBase.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,86 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System.Globalization;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public static class FgdFieldFactory
|
||||
{
|
||||
public static FgdFieldBase CreateField(string typename, string name, string description, string defaultValue)
|
||||
{
|
||||
switch (typename.ToLowerInvariant())
|
||||
{
|
||||
case "float":
|
||||
return new FgdFloatField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultValue = defaultValue != null ? float.Parse(defaultValue, NumberStyles.Any, CultureInfo.InvariantCulture) : 0f
|
||||
};
|
||||
case "integer":
|
||||
return new FgdIntegerField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultValue = defaultValue != null ? int.Parse(defaultValue, NumberStyles.Any, CultureInfo.InvariantCulture) : 0
|
||||
};
|
||||
case "vector":
|
||||
if (defaultValue == null || !defaultValue.TryParseQ3Vector(out Vector3 vector))
|
||||
{
|
||||
vector = Vector3.zero;
|
||||
}
|
||||
|
||||
return new FgdVectorField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultValue = vector
|
||||
};
|
||||
case "color":
|
||||
if (!defaultValue.TryParseQ3Colour(out Color colour))
|
||||
{
|
||||
colour = Color.white;
|
||||
}
|
||||
|
||||
return new FgdColourField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultColour = colour
|
||||
};
|
||||
case "string":
|
||||
return new FgdStringField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultValue = defaultValue
|
||||
};
|
||||
case "target_source":
|
||||
return new FgdTargetSourceField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultValue = defaultValue
|
||||
};
|
||||
case "target_destination":
|
||||
return new FgdTargetDestinationField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultValue = defaultValue
|
||||
};
|
||||
}
|
||||
|
||||
return new FgdStringField
|
||||
{
|
||||
Name = name,
|
||||
Description = description,
|
||||
DefaultValue = defaultValue
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b3806920a91d5469f8c9ef060771e83b
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FgdFieldFactory.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,130 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public static class FgdInferredFieldExtensions
|
||||
{
|
||||
public static void TryAddInferredField(this FgdClass fgdClass, string key, string value)
|
||||
{
|
||||
// ID property (or "targetname")
|
||||
string identityProperty = TrembleSyncSettings.Get().IdentityPropertyName;
|
||||
if (key.EqualsInvariant("targetname") || key.EqualsInvariant(identityProperty, caseSensitive: true))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// "Target"
|
||||
if (key.ContainsInvariant(FgdConsts.PROPERTY_TARGET))
|
||||
{
|
||||
fgdClass.AddField(new FgdTargetDestinationField
|
||||
{
|
||||
Name = key,
|
||||
Description = $"{key.ToNamingConvention(NamingConvention.UpperCamelCase)} of this Entity"
|
||||
});
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// "Origin" - skip
|
||||
if (key.EqualsInvariant(FgdConsts.PROPERTY_ORIGIN))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// "Scale" - skip
|
||||
if (key.EqualsInvariant(FgdConsts.PROPERTY_SCALE))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// "Parent" - skip
|
||||
if (key.EqualsInvariant(FgdConsts.PROPERTY_PARENT))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Angles - skip
|
||||
if (key.EqualsInvariant(FgdConsts.PROPERTY_ANGLES))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// _tb_textures, group, etc - skip
|
||||
if (key.StartsWithInvariant(TBConsts.TB_PREFIX))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
// Spawnflags
|
||||
if (key.EqualsInvariant(FgdConsts.PROPERTY_SPAWNFLAGS))
|
||||
{
|
||||
if (!int.TryParse(value, out int flags))
|
||||
return;
|
||||
|
||||
int bit = 0;
|
||||
while (flags > 0)
|
||||
{
|
||||
if (!fgdClass.HasSpawnFlag(bit))
|
||||
{
|
||||
fgdClass.AddField(new FgdSpawnFlagField
|
||||
{
|
||||
Bit = bit,
|
||||
Description = $"Unknown spawnflag bit #{bit}"
|
||||
});
|
||||
}
|
||||
|
||||
bit++;
|
||||
flags >>= 1;
|
||||
}
|
||||
|
||||
return;
|
||||
}
|
||||
|
||||
// Anything else? Try to infer type.
|
||||
if (IsValueVector(value))
|
||||
{
|
||||
fgdClass.AddField(new FgdVectorField
|
||||
{
|
||||
Name = key,
|
||||
Description = $"Vector {key}",
|
||||
});
|
||||
}
|
||||
else if (IsValueFloat(value))
|
||||
{
|
||||
fgdClass.AddField(new FgdFloatField
|
||||
{
|
||||
Name = key,
|
||||
Description = $"Float {key}",
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
fgdClass.AddField(new FgdStringField
|
||||
{
|
||||
Name = key,
|
||||
Description = $"String {key}",
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private static bool IsValueFloat(string value) => value.TryParseFloat(out float _);
|
||||
|
||||
private static bool IsValueVector(string value)
|
||||
{
|
||||
if (value.IsNullOrEmpty())
|
||||
return false;
|
||||
|
||||
string[] parts = value.Split(' ');
|
||||
if (parts.Length != 3)
|
||||
return false;
|
||||
|
||||
return IsValueFloat(parts[0]) && IsValueFloat(parts[1]) && IsValueFloat(parts[2]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a207e07b3115419e90f7b5092c0ea67f
|
||||
timeCreated: 1712223098
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FgdInferredFieldExtensions.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,283 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
#if UNITY_EDITOR
|
||||
using UnityEditor;
|
||||
#endif
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public record EnumDefinition(string Name, string[] Values);
|
||||
|
||||
public static class FgdParser
|
||||
{
|
||||
public static void Import(string fgdFilePath)
|
||||
{
|
||||
string fgdName = Path.GetFileNameWithoutExtension(fgdFilePath).ToNamingConvention(NamingConvention.UpperCamelCase);
|
||||
|
||||
TokenParser tokenParser = new(File.ReadAllText(fgdFilePath));
|
||||
|
||||
List<FgdClass> baseClasses = new(16);
|
||||
List<FgdClass> concreteClasses = new(64);
|
||||
|
||||
List<EnumDefinition> enums = new(64);
|
||||
|
||||
// Work out type of class and parse
|
||||
while (!tokenParser.IsAtEnd)
|
||||
{
|
||||
string classType = tokenParser.ReadToken(eatAllBracketContent: true).ToString();
|
||||
|
||||
switch (classType.ToLowerInvariant())
|
||||
{
|
||||
case "@baseclass":
|
||||
baseClasses.Add(ParseClass(FgdClassType.Base, tokenParser, fgdName, enums));
|
||||
break;
|
||||
case "@pointclass":
|
||||
concreteClasses.Add(ParseClass(FgdClassType.Point, tokenParser, fgdName, enums));
|
||||
break;
|
||||
case "@solidclass":
|
||||
concreteClasses.Add(ParseClass(FgdClassType.Brush, tokenParser, fgdName, enums));
|
||||
break;
|
||||
default:
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
string basePath = Path.GetDirectoryName(fgdFilePath);
|
||||
string baseEnumPath = Path.Combine(basePath, fgdName, "Enums");
|
||||
string baseEntitiesPath = Path.Combine(basePath, fgdName, "Entities");
|
||||
|
||||
DirectoryUtil.CreateAllDirectories(baseEnumPath);
|
||||
DirectoryUtil.CreateAllDirectories(baseEntitiesPath);
|
||||
|
||||
// Write Enums first
|
||||
foreach (EnumDefinition enumDef in enums)
|
||||
{
|
||||
string enumFile = Path.Combine(baseEnumPath, enumDef.Name + ".cs");
|
||||
enumDef.WriteCSharp(enumFile, fgdName);
|
||||
}
|
||||
|
||||
// ... then base classes ...
|
||||
foreach (FgdClass baseClass in baseClasses)
|
||||
{
|
||||
string namespaceName = fgdName;
|
||||
string folderPath = baseEntitiesPath;
|
||||
|
||||
baseClass.Name.Split('_', out string folderName, out string bareClassName);
|
||||
if (!folderName.IsNullOrEmpty())
|
||||
{
|
||||
namespaceName = $"{fgdName.ToNamingConvention(NamingConvention.UpperCamelCase)}.{folderName.ToNamingConvention(NamingConvention.UpperCamelCase)}";
|
||||
folderPath = Path.Combine(folderPath, folderName);
|
||||
}
|
||||
|
||||
DirectoryUtil.CreateAllDirectories(folderPath);
|
||||
|
||||
string classFile = Path.Combine(folderPath, "I" + bareClassName.ToNamingConvention(NamingConvention.UpperCamelCase) + ".cs");
|
||||
baseClass.WriteCSharp(classFile, baseClasses, namespaceName);
|
||||
}
|
||||
|
||||
// ... finally concrete classes
|
||||
foreach (FgdClass concreteClass in concreteClasses)
|
||||
{
|
||||
string namespaceName = fgdName;
|
||||
string folderPath = baseEntitiesPath;
|
||||
|
||||
concreteClass.Name.Split('_', out string folderName, out string bareClassName);
|
||||
if (!folderName.IsNullOrEmpty())
|
||||
{
|
||||
namespaceName = $"{fgdName.ToNamingConvention(NamingConvention.UpperCamelCase)}.{folderName.ToNamingConvention(NamingConvention.UpperCamelCase)}";
|
||||
folderPath = Path.Combine(folderPath, folderName);
|
||||
}
|
||||
|
||||
DirectoryUtil.CreateAllDirectories(folderPath);
|
||||
|
||||
string classFile = Path.Combine(folderPath, bareClassName.ToNamingConvention(NamingConvention.UpperCamelCase) + ".cs");
|
||||
concreteClass.WriteCSharp(classFile, baseClasses, namespaceName);
|
||||
}
|
||||
|
||||
// Refresh code, in editor
|
||||
#if UNITY_EDITOR
|
||||
AssetDatabase.Refresh(ImportAssetOptions.ForceUpdate | ImportAssetOptions.ForceSynchronousImport);
|
||||
#endif
|
||||
}
|
||||
|
||||
private static FgdClass ParseClass(FgdClassType type, TokenParser tokenParser, string fgdNamespace, List<EnumDefinition> outEnumDefinitions)
|
||||
{
|
||||
Dictionary<string, string> metadata = new();
|
||||
while (!tokenParser.PeekToken("=", eatAllBracketContent: true))
|
||||
{
|
||||
string metadataString = tokenParser.ReadToken(eatAllBracketContent: true).ToString(); // e.g. base(asfasf, asdgs) or model({f: "fasf"})
|
||||
metadataString.Split('(', out string key, out string value);
|
||||
|
||||
metadata[key.ToLowerInvariant()] = value[..^1];
|
||||
}
|
||||
|
||||
tokenParser.MatchToken("=", eatAllBracketContent: true);
|
||||
|
||||
ReadOnlySpan<char> classname = tokenParser.ReadToken();
|
||||
string classDescription = null;
|
||||
|
||||
classname.Split('_', out string _, out string unityClassname);
|
||||
unityClassname = unityClassname.ToNamingConvention(NamingConvention.UpperCamelCase);
|
||||
|
||||
if (tokenParser.PeekToken(":"))
|
||||
{
|
||||
tokenParser.ReadToken();
|
||||
classDescription = tokenParser.ReadToken().ToString();
|
||||
}
|
||||
|
||||
FgdClass newClass = new(type, classname.ToString(), classDescription ?? $"{unityClassname} Class");
|
||||
|
||||
// Add base classes
|
||||
if (metadata.TryGetValue("base", out string bases))
|
||||
{
|
||||
foreach (string baseClass in bases.Split(","))
|
||||
{
|
||||
newClass.AddBaseClass(baseClass.Trim());
|
||||
}
|
||||
}
|
||||
|
||||
//TODO(jwf): what about model, colour, size, etc?
|
||||
|
||||
if (!tokenParser.PeekToken("[]"))
|
||||
{
|
||||
tokenParser.MatchToken("["); // Eat '['
|
||||
|
||||
while (!tokenParser.IsAtEnd && !tokenParser.PeekToken("]"))
|
||||
{
|
||||
// Get name and type
|
||||
ReadOnlySpan<char> typeString = tokenParser.ReadToken(eatAllBracketContent: true); // e.g. thing(Integer)
|
||||
typeString.Split('(', out string varName, out string typename);
|
||||
typename = typename[..^1];
|
||||
|
||||
string description = null;
|
||||
string defaultValue = null;
|
||||
|
||||
// Has description?
|
||||
if (tokenParser.PeekToken(":"))
|
||||
{
|
||||
tokenParser.MatchToken(":");
|
||||
description = tokenParser.ReadToken().ToString();
|
||||
}
|
||||
|
||||
// Has default value?
|
||||
if (tokenParser.PeekToken(":"))
|
||||
{
|
||||
tokenParser.MatchToken(":");
|
||||
defaultValue = tokenParser.ReadToken().ToString();
|
||||
}
|
||||
|
||||
// Has multiple selections?
|
||||
if (tokenParser.PeekToken("="))
|
||||
{
|
||||
tokenParser.MatchToken("=");
|
||||
tokenParser.MatchToken("[");
|
||||
|
||||
if (typename.EqualsInvariant("choices"))
|
||||
{
|
||||
// Collect values (not necessarily in order, not necessarily sequential)
|
||||
Dictionary<int, string> values = new(64);
|
||||
int counter = 0;
|
||||
|
||||
while (!tokenParser.PeekToken("]"))
|
||||
{
|
||||
if (!int.TryParse(tokenParser.ReadToken(supportCommentsAndQuotes: false), NumberStyles.Any, CultureInfo.InvariantCulture, out int enumValue))
|
||||
{
|
||||
enumValue = counter++;
|
||||
}
|
||||
tokenParser.MatchToken(":");
|
||||
string enumValueName = NamingConventionUtil.FromHuman(tokenParser.ReadToken());
|
||||
values[enumValue] = enumValueName;
|
||||
}
|
||||
|
||||
tokenParser.MatchToken("]");
|
||||
|
||||
int maxEnumValue = values.Keys.Max();
|
||||
string[] valueStrings = new string[maxEnumValue+1];
|
||||
for (int i = 0; i <= maxEnumValue; i++)
|
||||
{
|
||||
valueStrings[i] = values.TryGetValue(i, out string valueName) ? valueName : $"Value_{i}";
|
||||
}
|
||||
|
||||
string enumName = $"{unityClassname.ToNamingConvention(NamingConvention.UpperCamelCase)}{varName.ToNamingConvention(NamingConvention.UpperCamelCase)}";
|
||||
outEnumDefinitions.Add(new
|
||||
(
|
||||
Name: enumName,
|
||||
Values: valueStrings
|
||||
));
|
||||
|
||||
newClass.AddField(new FgdEnumField
|
||||
{
|
||||
Name = varName,
|
||||
Description = description,
|
||||
EnumClassName = $"{fgdNamespace}.{enumName}",
|
||||
DefaultValue = 0,
|
||||
Values = valueStrings,
|
||||
});
|
||||
}
|
||||
else if (typename.EqualsInvariant("flags"))
|
||||
{
|
||||
//TODO(jwf): this assumes all "flags" are "spawnflags" - we should support other flags
|
||||
while (!tokenParser.PeekToken("]"))
|
||||
{
|
||||
int flagBit = (int)Math.Log(int.Parse(tokenParser.ReadToken(), NumberStyles.Any, CultureInfo.InvariantCulture), 2);
|
||||
tokenParser.MatchToken(":");
|
||||
ReadOnlySpan<char> flagName = tokenParser.ReadToken();
|
||||
int flagDefaultValue = 0;
|
||||
|
||||
if (tokenParser.PeekToken(":"))
|
||||
{
|
||||
tokenParser.MatchToken(":");
|
||||
flagDefaultValue = int.Parse(tokenParser.ReadToken(), NumberStyles.Any, CultureInfo.InvariantCulture);
|
||||
}
|
||||
|
||||
newClass.AddField(new FgdSpawnFlagField
|
||||
{
|
||||
Bit = flagBit,
|
||||
Description = flagName.ToString(),
|
||||
DefaultValue = flagDefaultValue == 1
|
||||
});
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
Debug.LogWarning("Unexpected options list... skipping...");
|
||||
|
||||
while (!tokenParser.PeekToken("]"))
|
||||
{
|
||||
tokenParser.ReadToken();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
FgdFieldBase field = FgdFieldFactory.CreateField(typename, varName, description, defaultValue);
|
||||
if (field == null)
|
||||
{
|
||||
Debug.LogWarning($"Could not parse field '{varName}' of type '{typename}'");
|
||||
continue;
|
||||
}
|
||||
|
||||
newClass.AddField(field);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Eat "[]"
|
||||
tokenParser.MatchToken("[]");
|
||||
}
|
||||
|
||||
return newClass;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: af5ff8df18459483090b8292fe668523
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FgdParser.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,239 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public class FgdWriter
|
||||
{
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// State
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
private FgdClass m_WorldSpawn;
|
||||
private readonly List<FgdClass> m_OtherClasses = new();
|
||||
private readonly List<FgdClass> m_BaseClasses = new();
|
||||
private readonly string m_VersionString;
|
||||
private readonly float m_ImportScale;
|
||||
|
||||
public FgdWriter(string versionString, TrembleSyncSettings settings)
|
||||
{
|
||||
m_VersionString = versionString;
|
||||
m_ImportScale = settings.ImportScale;
|
||||
|
||||
// Add base entities
|
||||
AddMapBaseEntity();
|
||||
AddMapPointBaseEntity();
|
||||
AddMapPrefabBaseEntity();
|
||||
}
|
||||
|
||||
public FgdClass WorldspawnClass
|
||||
{
|
||||
get => m_WorldSpawn;
|
||||
set => m_WorldSpawn = value;
|
||||
}
|
||||
|
||||
public IReadOnlyList<FgdClass> BaseClasses => m_BaseClasses;
|
||||
public IReadOnlyList<FgdClass> Classes => m_OtherClasses;
|
||||
|
||||
public void AddClass(FgdClass entityClass)
|
||||
{
|
||||
if (entityClass.Name.Length > 31)
|
||||
{
|
||||
Debug.LogError($"Class '{entityClass.Name}' is too long - it cannot be longer than 31 characters." +
|
||||
" Add a custom [PrefabEntity], [BrushEntity], or [PointEntity] attribute to this MonoBehaviour and set a shorter name!");
|
||||
}
|
||||
|
||||
if (entityClass.Type == FgdClassType.Base)
|
||||
{
|
||||
int insertionIdx = m_BaseClasses.BinarySearch(entityClass, Comparer<FgdClass>.Create((c1, c2) => String.Compare(c1.Name, c2.Name, StringComparison.Ordinal)));
|
||||
if (insertionIdx < 0)
|
||||
{
|
||||
m_BaseClasses.Add(entityClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_BaseClasses.Insert(insertionIdx, entityClass);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
int insertionIdx = m_OtherClasses.BinarySearch(entityClass, Comparer<FgdClass>.Create((c1, c2) => String.Compare(c1.Name, c2.Name, StringComparison.Ordinal)));
|
||||
if (insertionIdx < 0)
|
||||
{
|
||||
m_OtherClasses.Add(entityClass);
|
||||
}
|
||||
else
|
||||
{
|
||||
m_OtherClasses.Insert(insertionIdx, entityClass);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void WriteFgd(StreamWriter stream, bool humanReadable = true)
|
||||
{
|
||||
if (humanReadable)
|
||||
{
|
||||
stream.WriteLine("// TrenchBroom game definition file (.fgd)");
|
||||
stream.WriteLine($"// Generated by Tremble for Unity v{m_VersionString}");
|
||||
stream.WriteLine($"// For: {Application.productName}. (c) {DateTime.UtcNow.Year} {Application.companyName}");
|
||||
stream.WriteLine();
|
||||
stream.WriteLine();
|
||||
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
stream.WriteLine("//");
|
||||
stream.WriteLine("// Base Classes");
|
||||
stream.WriteLine("//");
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
// Base entities
|
||||
foreach (FgdClass entity in m_BaseClasses)
|
||||
{
|
||||
if (humanReadable)
|
||||
{
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
stream.WriteLine($"// Tremble Base Class '{entity.Name}'");
|
||||
stream.WriteLine($"// {entity.Description}");
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
entity.WriteFgd(stream, m_ImportScale);
|
||||
|
||||
if (humanReadable)
|
||||
{
|
||||
stream.WriteLine();
|
||||
stream.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
if (m_WorldSpawn != null)
|
||||
{
|
||||
if (humanReadable)
|
||||
{
|
||||
stream.WriteLine();
|
||||
stream.WriteLine();
|
||||
stream.WriteLine();
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
stream.WriteLine("//");
|
||||
stream.WriteLine("// worldspawn - World Root Properties");
|
||||
stream.WriteLine("//");
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
m_WorldSpawn.WriteFgd(stream, m_ImportScale);
|
||||
|
||||
if (humanReadable)
|
||||
{
|
||||
stream.WriteLine();
|
||||
stream.WriteLine();
|
||||
}
|
||||
}
|
||||
|
||||
if (humanReadable)
|
||||
{
|
||||
stream.WriteLine();
|
||||
stream.WriteLine();
|
||||
stream.WriteLine();
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
stream.WriteLine("//");
|
||||
stream.WriteLine("// Game Entities");
|
||||
stream.WriteLine("//");
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
stream.WriteLine();
|
||||
}
|
||||
|
||||
foreach (FgdClass entity in m_OtherClasses)
|
||||
{
|
||||
if (humanReadable)
|
||||
{
|
||||
string type = entity.Type switch
|
||||
{
|
||||
FgdClassType.Base => nameof(ITrembleBaseClass),
|
||||
FgdClassType.Point => "Point Entity",
|
||||
FgdClassType.Brush => "Brush Entity",
|
||||
_ => throw new ArgumentOutOfRangeException()
|
||||
};
|
||||
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
stream.WriteLine($"// {type}");
|
||||
stream.WriteLine($"// {entity.Description}");
|
||||
stream.WriteLine("// ----------------------------------------------------------------------------------------------------");
|
||||
}
|
||||
|
||||
entity.WriteFgd(stream, m_ImportScale);
|
||||
}
|
||||
}
|
||||
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
// Helpers
|
||||
// -----------------------------------------------------------------------------------------------------------------------------
|
||||
private void AddMapBaseEntity()
|
||||
{
|
||||
FgdClass mapBase = new(FgdClassType.Base, FgdConsts.CLASS_MAP_BASE, "The base class for all map entities");
|
||||
mapBase.Description = "Base class for common map properties";
|
||||
|
||||
mapBase.AddField(new FgdTargetSourceField
|
||||
{
|
||||
Name = TrembleSyncSettings.Get().IdentityPropertyName,
|
||||
Description = "The ID/Name of this entity",
|
||||
DefaultValue = ""
|
||||
});
|
||||
|
||||
mapBase.AddField(new FgdAnglesField
|
||||
{
|
||||
Name = FgdConsts.PROPERTY_ANGLES,
|
||||
Description = "Rotation Angles",
|
||||
DefaultValue = Vector3.zero
|
||||
});
|
||||
|
||||
mapBase.AddField(new FgdVectorField
|
||||
{
|
||||
Name = FgdConsts.PROPERTY_ORIGIN,
|
||||
Description = "Spawn position of this entity",
|
||||
DefaultValue = Vector3.zero,
|
||||
ConvertToQ3 = true,
|
||||
ImportScale = m_ImportScale
|
||||
});
|
||||
|
||||
AddClass(mapBase);
|
||||
}
|
||||
private void AddMapPointBaseEntity()
|
||||
{
|
||||
FgdClass mapBase = new(FgdClassType.Base, FgdConsts.CLASS_MAP_POINT_BASE, "The base class for all Point entities");
|
||||
mapBase.Description = "Base class for common Point properties";
|
||||
|
||||
mapBase.AddField(new FgdTargetDestinationField
|
||||
{
|
||||
Name = FgdConsts.PROPERTY_PARENT,
|
||||
Description = "Parent Transform",
|
||||
DefaultValue = null
|
||||
});
|
||||
|
||||
AddClass(mapBase);
|
||||
}
|
||||
|
||||
private void AddMapPrefabBaseEntity()
|
||||
{
|
||||
FgdClass mapBase = new(FgdClassType.Base, FgdConsts.CLASS_MAP_PREFAB_BASE, "The base class for all Prefab entities");
|
||||
mapBase.Description = "Base class for common Prefab properties";
|
||||
|
||||
mapBase.AddBaseClass(FgdConsts.CLASS_MAP_POINT_BASE);
|
||||
|
||||
mapBase.AddField(new FgdVectorField
|
||||
{
|
||||
Name = FgdConsts.PROPERTY_SCALE,
|
||||
Description = "Prefab Scale",
|
||||
DefaultValue = Vector3.one
|
||||
});
|
||||
|
||||
AddClass(mapBase);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8ae2428dfb70468ab002a264f8bc17de
|
||||
timeCreated: 1698227021
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FgdWriter.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 80fdd27eed8a4e8cbca74e05b26cfc12
|
||||
timeCreated: 1712223157
|
||||
@@ -0,0 +1,44 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdAnglesField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public Vector3 DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
if (Mathf.Approximately(DefaultValue.x, DefaultValue.y) && Mathf.Approximately(DefaultValue.y, DefaultValue.z))
|
||||
{
|
||||
sw.WriteLine($"{Name}(float) : \"{Description.Replace("\"", "'")}\" : \"{DefaultValue.x.ToStringInvariant()}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(float) : \"{Description.Replace("\"", "'")}\" : \"{DefaultValue.ToStringInvariant()}\"");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
{
|
||||
string defaultValueString = DefaultValue == Vector3.zero
|
||||
? "Vector3.zero"
|
||||
: $"new Vector3({DefaultValue.x.ToStringInvariant()}, {DefaultValue.y.ToStringInvariant()}, {DefaultValue.z.ToStringInvariant()})";
|
||||
WriteClassField(sw, indent, nameof(Vector3), Name, Description, defaultValueString);
|
||||
}
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, nameof(Vector3), Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 67ec51e0586d4dedaad0c34cef140416
|
||||
timeCreated: 1712223260
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdAnglesField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdBooleanField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public bool DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
string description = Description != null ? Description.Replace("\"", "'") : Name;
|
||||
|
||||
sw.WriteLine($"{Name}(choices) : \"{description}\" : {(DefaultValue ? "1" : "0")} = ");
|
||||
sw.WriteLine("\t[");
|
||||
{
|
||||
sw.WriteLine("\t\t0 : \"False\"");
|
||||
sw.WriteLine("\t\t1 : \"True\"");
|
||||
}
|
||||
sw.WriteLine("\t]");
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "bool", Name, Description, DefaultValue ? "true" : null);
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "bool", Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 31b88cf082164f41b2a7d78f67919483
|
||||
timeCreated: 1712223319
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdBooleanField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdChoicesIntField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string[] Choices { get; init; }
|
||||
public int DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
if (DefaultValue == 0)
|
||||
{
|
||||
sw.WriteLine($"{Name}(choices) : \"{Description.Replace("\"", "'")}\" = ");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(choices) : \"{Description.Replace("\"", "'")}\" : {DefaultValue} = ");
|
||||
}
|
||||
|
||||
sw.WriteLine("\t[");
|
||||
{
|
||||
for (int i = 0; i < Choices.Length; i++)
|
||||
{
|
||||
sw.WriteLine($"\t\t{i} : \"{Choices[i]}\"");
|
||||
}
|
||||
}
|
||||
sw.WriteLine("\t]");
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "int", Name, Description, DefaultValue == 0 ? null : DefaultValue.ToString());
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "int", Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 8b1808df0f9246d981380501211318d8
|
||||
timeCreated: 1712223378
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdChoicesIntField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,48 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdChoicesStringField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string[] Choices { get; init; }
|
||||
public string DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
sw.WriteLine($"{Name}(choices) : \"{Description.Replace("\"", "'")}\" : \"{DefaultValue ?? Choices[0]}\" = ");
|
||||
sw.WriteLine("\t[");
|
||||
{
|
||||
foreach (string choice in Choices)
|
||||
{
|
||||
if (choice.IsNullOrEmpty())
|
||||
{
|
||||
sw.WriteLine("\t\t\"\" : \"(none)\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"\t\t\"{choice}\" : \"{choice.ToNamingConvention(NamingConvention.HumanFriendly)}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
sw.WriteLine("\t]");
|
||||
}
|
||||
|
||||
//TODO(jwf): support default values?
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "string", Name, Description);
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "string", Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 6c59811822b3441d835a848021e6ef17
|
||||
timeCreated: 1712223387
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdChoicesStringField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,39 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdColourField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public Color DefaultColour { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
sw.WriteLine($"{Name}(color) : \"{Description.Replace("\"", "'")}\" : \"{DefaultColour.ToStringInvariant()}\"");
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
{
|
||||
string defaultValueString = DefaultColour == Color.white
|
||||
? "Color.white"
|
||||
: $"new Color({DefaultColour.r.ToStringInvariant()}, {DefaultColour.g.ToStringInvariant()}, {DefaultColour.b.ToStringInvariant()})";
|
||||
|
||||
WriteClassField(sw, indent, nameof(Color), Name, Description, DefaultColour == Color.white ? null : defaultValueString);
|
||||
}
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, nameof(Color), Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d14b410b2bd14d4e8a9a0b9e4cc5d984
|
||||
timeCreated: 1712223272
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdColourField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdComment : FgdFieldBase
|
||||
{
|
||||
public string Comment { get; init; }
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
sw.WriteLine($"// {Comment}");
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
{
|
||||
sw.WriteIndent(indent);
|
||||
sw.WriteLine($"// {Comment}");
|
||||
}
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
{
|
||||
sw.WriteIndent(indent);
|
||||
sw.WriteLine($"// {Comment}");
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a46440a8a9254de1aad67d79e4cb1509
|
||||
timeCreated: 1712223182
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdComment.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,124 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdEnumField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string EnumClassName { get; init; }
|
||||
public int DefaultValue { get; init; }
|
||||
public string[] Values { get; set; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
private string[] EnumValuesOrCached
|
||||
{
|
||||
get
|
||||
{
|
||||
if (Values == null || Values.Length == 0)
|
||||
{
|
||||
if (EnumClassName.ContainsInvariant("+"))
|
||||
{
|
||||
EnumClassName.Split('+', out string className, out string enumName);
|
||||
|
||||
Debug.LogError($"Couldn't use {enumName} enum. Enums embedded in classes are "
|
||||
+ $"not supported by Tremble :(. Move your '{enumName}' enum "
|
||||
+ $"outside of {className} to use it!");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
Type enumType = TypeDatabase.GetType(EnumClassName);
|
||||
string[] names = Enum.GetNames(enumType);
|
||||
|
||||
int[] values = Enum.GetValues(enumType).Cast<int>().ToArray();
|
||||
int maxValue = values.Max();
|
||||
|
||||
Values = new string[maxValue + 1];
|
||||
for (int i = 0; i <= maxValue; i++)
|
||||
{
|
||||
int nameIdx = Array.FindIndex(values, v => v == i);
|
||||
if (nameIdx == -1)
|
||||
{
|
||||
Values[i] = "_";
|
||||
}
|
||||
else
|
||||
{
|
||||
Values[i] = names[nameIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return Values;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
|
||||
|
||||
if (syncSettings.SyncEnumsAsStringValue)
|
||||
{
|
||||
string[] values = EnumValuesOrCached;
|
||||
string defaultString = values.Length > DefaultValue && !values[DefaultValue].EqualsInvariant("_") ? values[DefaultValue] : "(none)";
|
||||
sw.WriteLine($"{Name}(choices) : \"{Description.Replace("\"", "'")}\" : \"{defaultString}\" = ");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (DefaultValue == 0)
|
||||
{
|
||||
sw.WriteLine($"{Name}(choices) : \"{Description.Replace("\"", "'")}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(choices) : \"{Description.Replace("\"", "'")}\" : {DefaultValue} = ");
|
||||
}
|
||||
}
|
||||
|
||||
sw.WriteLine("\t[");
|
||||
{
|
||||
for (int i = 0; i < EnumValuesOrCached.Length; i++)
|
||||
{
|
||||
string value = EnumValuesOrCached[i];
|
||||
if (value.EqualsInvariant("_"))
|
||||
continue;
|
||||
|
||||
if (syncSettings.SyncEnumsAsStringValue)
|
||||
{
|
||||
sw.WriteLine($"\t\t\"{value}\" : \"{value}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"\t\t{i} : \"{value}\"");
|
||||
}
|
||||
}
|
||||
}
|
||||
sw.WriteLine("\t]");
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
{
|
||||
string enumTypeName = EnumClassName;
|
||||
int lastDot = enumTypeName.LastIndexOf('.');
|
||||
if (lastDot != -1)
|
||||
{
|
||||
enumTypeName = enumTypeName.Substring(lastDot + 1);
|
||||
}
|
||||
|
||||
string defaultValueString = $"{EnumClassName}.{EnumValuesOrCached[DefaultValue]}";
|
||||
WriteClassField(sw, indent, enumTypeName, Name, Description, defaultValueString);
|
||||
}
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, EnumClassName, Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 7cb83d47f4a14179baba19b9197b90ea
|
||||
timeCreated: 1712223369
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdEnumField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,97 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdFlagsField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string EnumClassName { get; init; }
|
||||
public string[] EnumNames { get; set; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
private string[] EnumNamesOrCached
|
||||
{
|
||||
get
|
||||
{
|
||||
if (EnumNames == null || EnumNames.Length == 0)
|
||||
{
|
||||
if (EnumClassName.ContainsInvariant("+"))
|
||||
{
|
||||
EnumClassName.Split('+', out string className, out string enumName);
|
||||
|
||||
Debug.LogError($"Couldn't use {enumName} enum. Enums embedded in classes are "
|
||||
+ $"not supported by Tremble :(. Move your '{enumName}' enum "
|
||||
+ $"outside of {className} to use it!");
|
||||
return Array.Empty<string>();
|
||||
}
|
||||
|
||||
Type enumType = TypeDatabase.GetType(EnumClassName);
|
||||
string[] names = Enum.GetNames(enumType);
|
||||
int[] values = Enum.GetValues(enumType).Cast<int>().ToArray();
|
||||
|
||||
int maxValue = values.Max();
|
||||
EnumNames = new string[maxValue + 1];
|
||||
|
||||
for (int i = 0; i <= maxValue; i++)
|
||||
{
|
||||
int nameIdx = Array.FindIndex(values, v => v == i);
|
||||
if (nameIdx == -1)
|
||||
{
|
||||
EnumNames[i] = "_";
|
||||
}
|
||||
else
|
||||
{
|
||||
EnumNames[i] = names[nameIdx];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return EnumNames;
|
||||
}
|
||||
}
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
sw.WriteLine($"{Name}(flags) = ");
|
||||
sw.WriteLine("\t[");
|
||||
{
|
||||
for (int i = 0; i < EnumNamesOrCached.Length; i++)
|
||||
{
|
||||
string name = EnumNamesOrCached[i];
|
||||
if (name.EqualsInvariant("_"))
|
||||
continue;
|
||||
|
||||
sw.WriteLine($"\t\t{i} : \"{name}\" : 0");
|
||||
}
|
||||
}
|
||||
sw.WriteLine("\t]");
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
{
|
||||
string enumTypeName = EnumClassName;
|
||||
int lastDot = enumTypeName.LastIndexOf('.');
|
||||
if (lastDot != -1)
|
||||
{
|
||||
enumTypeName = enumTypeName.Substring(lastDot + 1);
|
||||
}
|
||||
|
||||
WriteClassField(sw, indent, enumTypeName, Name, Description, "default");
|
||||
}
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, EnumClassName, Name, Description, "Flags");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 86f42cfbe8b54eeeaf7d8102766a3fba
|
||||
timeCreated: 1774358034
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdFlagsField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdFloatField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public float DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
if (DefaultValue == 0f)
|
||||
{
|
||||
sw.WriteLine($"{Name}(float) : \"{Description.Replace("\"", "'")}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(float) : \"{Description.Replace("\"", "'")}\" : \"{DefaultValue.ToStringInvariant()}\"");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "float", Name, Description, DefaultValue == 0f ? null : DefaultValue.ToStringInvariant() + "f");
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "float", Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 56cba705d7a240a8b2b05ae6edb8ddeb
|
||||
timeCreated: 1712223287
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdFloatField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdIntegerField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public int DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
if (DefaultValue == 0)
|
||||
{
|
||||
sw.WriteLine($"{Name}(integer) : \"{Description.Replace("\"", "'")}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(integer) : \"{Description.Replace("\"", "'")}\" : {DefaultValue}");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "int", Name, Description, DefaultValue == 0 ? null : DefaultValue.ToString());
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "int", Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 96bcc84614cf430590935b78d98f0ca0
|
||||
timeCreated: 1712223311
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdIntegerField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,33 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdSpawnFlagField : FgdFieldBase
|
||||
{
|
||||
public int Bit { get; init; }
|
||||
public string Description { get; init; }
|
||||
public bool DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => NamingConventionUtil.FromHuman(Description);
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
int bitDefaultValue = 1 << Bit;
|
||||
|
||||
sw.WriteLine($"{bitDefaultValue} : \"{Description.Replace("\"", "'")}\" : {(DefaultValue ? "1" : "0")}");
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "bool", FieldName, Description, DefaultValue ? "true" : null, extraAttributes: $"SpawnFlags({Bit})");
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "bool", FieldName, Description, attributes: $"SpawnFlags({Bit})");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: d5d3344597c842eb8c287ffb9e4e6854
|
||||
timeCreated: 1712223402
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdSpawnFlagField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdStringField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
if (DefaultValue.IsNullOrEmpty())
|
||||
{
|
||||
sw.WriteLine($"{Name}(string) : \"{Description.Replace("\"", "'")}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(string) : \"{Description.Replace("\"", "'")}\" : \"{DefaultValue}\"");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "string", Name, Description, DefaultValue.IsNullOrEmpty() ? null : $"\"{DefaultValue}\"");
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "string", Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: b475d7d5cead4105af48ebd7252e50db
|
||||
timeCreated: 1712223334
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdStringField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,40 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdTargetDestinationField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
if (DefaultValue.IsNullOrEmpty())
|
||||
{
|
||||
sw.WriteLine($"{Name}(target_destination) : \"{Description.Replace("\"", "'")}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(target_destination) : \"{Description.Replace("\"", "'")}\" : \"{DefaultValue}\"");
|
||||
}
|
||||
}
|
||||
|
||||
//TODO(jwf): support default values?
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, nameof(Transform), Name, Description);
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, nameof(Transform), Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ce6a69e950e34780a3a25026a94798b1
|
||||
timeCreated: 1712223349
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdTargetDestinationField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,38 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdTargetSourceField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public string DefaultValue { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
if (DefaultValue.IsNullOrEmpty())
|
||||
{
|
||||
sw.WriteLine($"{Name}(target_source) : \"{Description.Replace("\"", "'")}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(target_source) : \"{Description.Replace("\"", "'")}\" : \"{DefaultValue}\"");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
=> WriteClassField(sw, indent, "string", Name, Description, DefaultValue.IsNullOrEmpty() ? null : $"\"{DefaultValue}\"");
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, "string", Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ef716bdc4952478b80d299a922219b1a
|
||||
timeCreated: 1712223341
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdTargetSourceField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,53 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.IO;
|
||||
using UnityEngine;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
[Serializable]
|
||||
public class FgdVectorField : FgdFieldBase
|
||||
{
|
||||
public string Name { get; init; }
|
||||
public string Description { get; init; }
|
||||
public Vector3 DefaultValue { get; init; }
|
||||
public bool ConvertToQ3 { get; init; }
|
||||
public float ImportScale { get; init; }
|
||||
|
||||
public override string FieldName => Name;
|
||||
|
||||
public override void Write(StreamWriter sw)
|
||||
{
|
||||
Vector3 value = DefaultValue;
|
||||
|
||||
if (ConvertToQ3)
|
||||
{
|
||||
value = new Vector3(-value.x, -value.z, value.y) / ImportScale;
|
||||
}
|
||||
|
||||
if (Mathf.Approximately(value.x, value.y) && Mathf.Approximately(value.y, value.z))
|
||||
{
|
||||
sw.WriteLine($"{Name}(float) : \"{Description.Replace("\"", "'")}\" : \"{value.x.ToStringInvariant()}\"");
|
||||
}
|
||||
else
|
||||
{
|
||||
sw.WriteLine($"{Name}(float) : \"{Description.Replace("\"", "'")}\" : \"{value.ToStringInvariant()}\"");
|
||||
}
|
||||
}
|
||||
|
||||
public override void WriteCSharpClass(StreamWriter sw, int indent)
|
||||
{
|
||||
string defaultValueString = DefaultValue == Vector3.zero
|
||||
? "Vector3.zero"
|
||||
: $"new Vector3({DefaultValue.x.ToStringInvariant()}, {DefaultValue.y.ToStringInvariant()}, {DefaultValue.z.ToStringInvariant()})";
|
||||
WriteClassField(sw, indent, nameof(Vector3), Name, Description, defaultValueString);
|
||||
}
|
||||
|
||||
public override void WriteCSharpInterface(StreamWriter sw, int indent)
|
||||
=> WriteInterfaceProperty(sw, indent, nameof(Vector3), Name, Description);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: 078725a3929747ceb3f93ad3e68e36d5
|
||||
timeCreated: 1712223216
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/FieldTypes/FgdVectorField.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,3 @@
|
||||
fileFormatVersion: 2
|
||||
guid: f8e7b72eacf0406e90949f0230906787
|
||||
timeCreated: 1712323557
|
||||
@@ -0,0 +1,330 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public static class EntityClassWriter
|
||||
{
|
||||
public static void WriteCSharp(this FgdClass fgdClass, string file, List<FgdClass> allBaseClasses = null, string namespaceName = null)
|
||||
{
|
||||
if (fgdClass.Type == FgdClassType.Base)
|
||||
{
|
||||
WriteCSharpInterface(fgdClass, file, namespaceName);
|
||||
}
|
||||
else
|
||||
{
|
||||
WriteCSharpClass(fgdClass, file, allBaseClasses, namespaceName);
|
||||
}
|
||||
}
|
||||
|
||||
private static void WriteCSharpClass(this FgdClass fgdClass, string file, List<FgdClass> allBaseClasses = null, string namespaceName = null)
|
||||
{
|
||||
using FileStream classFile = new(file, FileMode.Create, FileAccess.Write);
|
||||
using StreamWriter writer = new(classFile);
|
||||
|
||||
writer.WriteLine($"// Class '{fgdClass.Name}'");
|
||||
writer.WriteLine($"// Generated by Tremble v{TrembleConsts.VERSION_STRING}");
|
||||
writer.WriteLine();
|
||||
|
||||
writer.WriteLine("using UnityEngine;");
|
||||
writer.WriteLine("using TinyGoose.Tremble;");
|
||||
writer.WriteLine();
|
||||
|
||||
writer.WriteLine("// Disable 'Field is assigned but its value is never used' warning");
|
||||
writer.WriteLine("#pragma warning disable CS0414");
|
||||
writer.WriteLine();
|
||||
|
||||
bool hasNamespace = !namespaceName.IsNullOrEmpty();
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.WriteLine($"namespace {namespaceName}");
|
||||
writer.WriteLine("{");
|
||||
}
|
||||
|
||||
if (!fgdClass.Description.IsNullOrEmpty())
|
||||
{
|
||||
writer.WriteLine($"\t// \"{fgdClass.Description}\"");
|
||||
}
|
||||
|
||||
{
|
||||
fgdClass.Name.Split('_', out string category, out string classname);
|
||||
|
||||
if (fgdClass.Type == FgdClassType.Brush)
|
||||
{
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.Write("[BrushEntity(");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.Write("[PointEntity(");
|
||||
}
|
||||
|
||||
writer.Write($"\"{classname}\"");
|
||||
|
||||
if (category.IsNullOrEmpty())
|
||||
{
|
||||
writer.Write($", category: \"\" /* empty category - gross, but necessary */");
|
||||
}
|
||||
else
|
||||
{
|
||||
writer.Write($", category: \"{category}\"");
|
||||
}
|
||||
|
||||
if (fgdClass.Type == FgdClassType.Brush && fgdClass.Name.ContainsInvariant("trigger"))
|
||||
{
|
||||
writer.Write($", type: BrushType.Trigger");
|
||||
}
|
||||
|
||||
writer.WriteLine(")]");
|
||||
|
||||
string csharpClassname = classname.ToNamingConvention(NamingConvention.UpperCamelCase);
|
||||
if (!category.IsNullOrEmpty()
|
||||
&& !category.EqualsInvariant("misc")
|
||||
&& !category.EqualsInvariant("func"))
|
||||
{
|
||||
csharpClassname += category.ToNamingConvention(NamingConvention.UpperCamelCase);
|
||||
}
|
||||
|
||||
if (csharpClassname.EqualsInvariant("light"))
|
||||
{
|
||||
// Hack: you can't call a MonoBehaviour "Light" in Unity, but Quake for example
|
||||
// has an entity called "light" - let's call it LightEntity
|
||||
csharpClassname = "LightEntity";
|
||||
}
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.Write($"public class {csharpClassname} : MonoBehaviour");
|
||||
|
||||
foreach (string baseClass in fgdClass.BaseClassNames)
|
||||
{
|
||||
// Not the Tremble ones!
|
||||
if (baseClass.EqualsInvariant(FgdConsts.CLASS_MAP_BASE, caseSensitive: true)
|
||||
|| baseClass.EqualsInvariant(FgdConsts.CLASS_MAP_POINT_BASE, caseSensitive: true))
|
||||
continue;
|
||||
|
||||
writer.Write($", I{baseClass}");
|
||||
}
|
||||
writer.WriteLine();
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("{");
|
||||
|
||||
if (fgdClass.AllFields.Count > 0)
|
||||
{
|
||||
writer.WriteIndent(hasNamespace ? 2 : 1);
|
||||
writer.WriteLine("// Fields:");
|
||||
|
||||
foreach (FgdFieldBase field in fgdClass.AllFields)
|
||||
{
|
||||
field.WriteCSharpClass(writer, hasNamespace ? 2 : 1);
|
||||
}
|
||||
|
||||
writer.WriteLine();
|
||||
}
|
||||
|
||||
if (fgdClass.AllSpawnFlags.Count > 0)
|
||||
{
|
||||
writer.WriteIndent(hasNamespace ? 2 : 1);
|
||||
writer.WriteLine("// Spawnflags: ");
|
||||
foreach (FgdSpawnFlagField spawnFlagField in fgdClass.AllSpawnFlags)
|
||||
{
|
||||
spawnFlagField.WriteCSharpClass(writer, hasNamespace ? 2 : 1);
|
||||
}
|
||||
|
||||
writer.WriteLine();
|
||||
}
|
||||
|
||||
// Write base class fields
|
||||
if (allBaseClasses != null)
|
||||
{
|
||||
List<string> writtenBaseClasses = new(64);
|
||||
List<string> writtenFields = new(64);
|
||||
|
||||
foreach (string baseClassName in fgdClass.BaseClassNames)
|
||||
{
|
||||
AddBaseClassFields(fgdClass, writer, hasNamespace, baseClassName, writtenBaseClasses, writtenFields, allBaseClasses);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
|
||||
writer.WriteLine();
|
||||
writer.WriteLine("#pragma warning restore CS0414");
|
||||
}
|
||||
|
||||
private static void AddBaseClassFields(FgdClass thisClass, StreamWriter writer, bool hasNamespace, string baseClassName, List<string> writtenBaseClasses, List<string> writtenFields, List<FgdClass> allBaseClasses)
|
||||
{
|
||||
// Find the base class and add!
|
||||
FgdClass baseClass = allBaseClasses.FirstOrDefault(bc => bc.Name.EqualsInvariant(baseClassName, caseSensitive: true));
|
||||
if (baseClass == null)
|
||||
return;
|
||||
|
||||
if (baseClass.AllFields.Count + baseClass.AllSpawnFlags.Count == 0)
|
||||
return;
|
||||
|
||||
if (writtenBaseClasses.Contains(baseClassName))
|
||||
return;
|
||||
|
||||
writtenBaseClasses.Add(baseClassName);
|
||||
|
||||
foreach (string baseBaseClassName in baseClass.BaseClassNames)
|
||||
{
|
||||
AddBaseClassFields(thisClass, writer, hasNamespace, baseBaseClassName, writtenBaseClasses, writtenFields, allBaseClasses);
|
||||
}
|
||||
|
||||
writer.WriteLine();
|
||||
writer.WriteIndent(hasNamespace ? 2 : 1);
|
||||
writer.WriteLine($"// From Base Class '{baseClassName}':");
|
||||
|
||||
foreach (FgdFieldBase field in baseClass.AllFields)
|
||||
{
|
||||
if (writtenFields.Contains(field.FieldName))
|
||||
{
|
||||
writer.WriteIndent(hasNamespace ? 2 : 1);
|
||||
writer.WriteLine($"// Skipped '{field.FieldName}' - already defined by a base class!");
|
||||
continue;
|
||||
}
|
||||
|
||||
writtenFields.Add(field.FieldName);
|
||||
|
||||
bool overridden = thisClass.AllFields.Any(m => m.FieldName.EqualsInvariant(field.FieldName, caseSensitive: true));
|
||||
if (overridden)
|
||||
{
|
||||
writer.WriteLine("/* (overriden by subclass)");
|
||||
}
|
||||
|
||||
field.WriteCSharpClass(writer, hasNamespace ? 2 : 1);
|
||||
|
||||
if (overridden)
|
||||
{
|
||||
writer.WriteLine("(overriden by subclass) */");
|
||||
}
|
||||
}
|
||||
|
||||
foreach (FgdSpawnFlagField spawnFlag in baseClass.AllSpawnFlags)
|
||||
{
|
||||
bool overridden = thisClass.AllSpawnFlags.Any(m => m.FieldName.EqualsInvariant(spawnFlag.FieldName, caseSensitive: true));
|
||||
if (overridden)
|
||||
{
|
||||
writer.WriteLine("/* (overriden by subclass)");
|
||||
}
|
||||
|
||||
spawnFlag.WriteCSharpClass(writer, hasNamespace ? 2 : 1);
|
||||
|
||||
if (overridden)
|
||||
{
|
||||
writer.WriteLine("(overriden by subclass) */");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
private static void WriteCSharpInterface(this FgdClass fgdClass, string file, string namespaceOrNull)
|
||||
{
|
||||
using FileStream classFile = new(file, FileMode.Create, FileAccess.Write);
|
||||
using StreamWriter writer = new(classFile);
|
||||
|
||||
writer.WriteLine($"// Interface 'I{fgdClass.Name}'");
|
||||
writer.WriteLine($"// Generated by Tremble v{TrembleConsts.VERSION_STRING}");
|
||||
writer.WriteLine();
|
||||
|
||||
writer.WriteLine("using UnityEngine;");
|
||||
writer.WriteLine("using TinyGoose.Tremble;");
|
||||
writer.WriteLine();
|
||||
|
||||
bool hasNamespace = !namespaceOrNull.IsNullOrEmpty();
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.WriteLine($"namespace {namespaceOrNull}");
|
||||
writer.WriteLine("{");
|
||||
}
|
||||
|
||||
{
|
||||
fgdClass.Name.Split('_', out string _, out string classname);
|
||||
string csharpClassname = classname.ToNamingConvention(NamingConvention.UpperCamelCase);
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine($"public interface I{csharpClassname} : ITrembleBaseClass");
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("{");
|
||||
|
||||
if (fgdClass.AllFields.Count > 0)
|
||||
{
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("\t// Fields:");
|
||||
|
||||
foreach (FgdFieldBase field in fgdClass.AllFields)
|
||||
{
|
||||
field.WriteCSharpInterface(writer, hasNamespace ? 2 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (fgdClass.AllSpawnFlags.Count > 0)
|
||||
{
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("\t// Spawnflags: ");
|
||||
foreach (FgdSpawnFlagField spawnFlagField in fgdClass.AllSpawnFlags)
|
||||
{
|
||||
spawnFlagField.WriteCSharpInterface(writer, hasNamespace ? 2 : 1);
|
||||
}
|
||||
}
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,10 @@
|
||||
fileFormatVersion: 2
|
||||
guid: ae5ecd0fb11d4baf988975b57deb3f53
|
||||
timeCreated: 1712132457
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/Writers/EntityClassWriter.cs
|
||||
uploadId: 939664
|
||||
@@ -0,0 +1,69 @@
|
||||
//
|
||||
// This file is part of the Tremble package by Tiny Goose.
|
||||
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
|
||||
//
|
||||
|
||||
using System.IO;
|
||||
|
||||
namespace TinyGoose.Tremble
|
||||
{
|
||||
public static class EntityEnumWriter
|
||||
{
|
||||
public static void WriteCSharp(this EnumDefinition enumDefinition, string file, string namespaceOrNull)
|
||||
{
|
||||
using FileStream classFile = new(file, FileMode.Create, FileAccess.Write);
|
||||
using StreamWriter writer = new(classFile);
|
||||
|
||||
writer.WriteLine($"// Enum '{enumDefinition.Name}'");
|
||||
writer.WriteLine($"// Generated by Tremble v{TrembleConsts.VERSION_STRING}");
|
||||
writer.WriteLine();
|
||||
|
||||
writer.WriteLine("using UnityEngine;");
|
||||
writer.WriteLine("using TinyGoose.Tremble;");
|
||||
writer.WriteLine();
|
||||
|
||||
bool hasNamespace = !namespaceOrNull.IsNullOrEmpty();
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.WriteLine($"namespace {namespaceOrNull}");
|
||||
writer.WriteLine("{");
|
||||
}
|
||||
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine($"public enum {enumDefinition.Name}");
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("{");
|
||||
|
||||
for (int i = 0; i < enumDefinition.Values.Length; i++)
|
||||
{
|
||||
string value = enumDefinition.Values[i];
|
||||
|
||||
writer.Write("\t");
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine($"{value} = {i},");
|
||||
}
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.Write("\t");
|
||||
}
|
||||
writer.WriteLine("}");
|
||||
|
||||
if (hasNamespace)
|
||||
{
|
||||
writer.WriteLine("}");
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
fileFormatVersion: 2
|
||||
guid: a0ba86bd49f1a4af5b7b8522b5e470de
|
||||
MonoImporter:
|
||||
externalObjects: {}
|
||||
serializedVersion: 2
|
||||
defaultReferences: []
|
||||
executionOrder: 0
|
||||
icon: {instanceID: 0}
|
||||
userData:
|
||||
assetBundleName:
|
||||
assetBundleVariant:
|
||||
AssetOrigin:
|
||||
serializedVersion: 1
|
||||
productId: 277805
|
||||
packageName: Tremble - Map Importer
|
||||
packageVersion: 1.11.1
|
||||
assetPath: Assets/Tremble/IO/FGD/Writers/EntityEnumWriter.cs
|
||||
uploadId: 939664
|
||||
Reference in new issue
Block a user