Second commit

This commit is contained in:
ThomasCharester committed 2026-09-20 15:26:03 +03:00
commit 36840f3ad4
999 files changed
+61364

No files matched your search

@@ -0,0 +1,3 @@
fileFormatVersion: 2
guid: 5d85820039b34dbdad142e9e57d62b6e
timeCreated: 1710147886
@@ -0,0 +1,120 @@
//
// 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 System.Reflection;
using UnityEngine;
using Object = UnityEngine.Object;
namespace TinyGoose.Tremble
{
public static class UnityObjectFieldConverterStatics
{
public static readonly Dictionary<Type, string[]> s_CachedAssetLists = new();
}
public abstract class UnityAssetFieldConverter<TObjectType> : TrembleFieldConverter<Object>
where TObjectType : Object
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Object value)
{
if (!entity.TryGetString(key, out string objectName))
{
value = null;
return false;
}
return TryLoadObjectWithName(objectName, target.GetFieldOrPropertyTypeOrElementType(), key, entity, target, out value);
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Object[] values)
{
if (!entity.TryGetString(key, out string objectNameString))
{
values = default;
return false;
}
string[] objectNames = objectNameString.Split(',').ToArray();
values = new Object[objectNames.Length];
for (int objIdx = 0; objIdx < objectNames.Length; objIdx++)
{
if (!TryLoadObjectWithName(objectNames[objIdx], target.GetFieldOrPropertyTypeOrElementType(), key, entity, target, out Object foundObject))
continue;
values[objIdx] = foundObject;
}
return true;
}
private bool TryLoadObjectWithName(string name, Type objectType, string key, BspEntity entity, MemberInfo target, out Object obj)
{
string[] assetPaths = GetCachedAssetsPaths(objectType)
.Where(p => Path.GetFileNameWithoutExtension(p).EqualsInvariant(name))
.ToArray();
if (assetPaths.Length > 1)
{
Debug.LogWarning($"Warning - importing {objectType.Name} value '{name}' for field '{key}', but multiple {objectType.Name}s match that name. Ensure your {target.GetFieldOrPropertyType().Name}s are named uniquely. Selecting the first available one!");
foreach (string assetPath in assetPaths)
{
Debug.LogWarning($"Could be: {assetPath}?", TrembleAssetLoader.LoadAssetByPath<Object>(assetPath));
}
}
if (assetPaths.Length == 0 || assetPaths[0].IsNullOrEmpty())
{
string entityName = entity.GetID().IsNullOrEmpty() ? entity.GetClassname() : $"'{entity.GetID()}' ({entity.GetClassname()})";
Debug.LogWarning($"Couldn't find a {objectType.Name} asset named '{name}' in the project! Using default for entity {entityName}.");
obj = null;
return false;
}
obj = TrembleAssetLoader.LoadAssetByPath<Object>(assetPaths[0]);
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, Object defaultValue, MemberInfo target)
{
target.GetCustomAttributes(out TooltipAttribute tooltip);
string[] choices = GetCachedAssetsPaths(target.GetFieldOrPropertyTypeOrElementType())
.Select(Path.GetFileNameWithoutExtension)
.ToArray();
string defaultString = Path.GetFileNameWithoutExtension(TrembleAssetLoader.GetPath(defaultValue));
entityClass.AddField(new FgdChoicesStringField
{
Name = fieldName,
Choices = choices,
Description = tooltip?.tooltip ?? $"{target.GetFieldOrPropertyType()} {target.Name}",
DefaultValue = defaultString
});
}
private string[] GetCachedAssetsPaths(Type actualType)
{
if (!UnityObjectFieldConverterStatics.s_CachedAssetLists.TryGetValue(actualType, out string[] assetPaths))
{
List<string> assetPathList = TrembleAssetLoader.FindAssetPaths(actualType).ToList();
assetPathList.Insert(0, "");
assetPaths = assetPathList.ToArray();
UnityObjectFieldConverterStatics.s_CachedAssetLists[actualType] = assetPaths;
}
return assetPaths;
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 7d223aafbe7449fa87a27768d5809659
timeCreated: 1710147897
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/FieldConverters/BaseClasses/UnityAssetFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,99 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(bool))]
public class BoolFieldConverter : TrembleFieldConverter<bool>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out bool value)
{
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
target.GetCustomAttributes(
out SpawnFlagsAttribute sfa,
out NoSpawnFlagsAttribute noSfa
);
bool useSpawnFlag = sfa != null || syncSettings.AlwaysPackBoolsIntoSpawnFlags;
if (noSfa != null)
{
useSpawnFlag = false;
}
// No spawn flag - easy!
if (!useSpawnFlag)
return entity.TryGetBoolean(key, out value);
// Spawn flag
int bit = sfa.GetBitForSpawnFlagsField(syncSettings, target);
return entity.TryGetSpawnFlag(bit, out value);
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out bool[] values)
{
if (!entity.TryGetString(key, out string stringValues))
{
values = default;
return false;
}
values = stringValues
.Split(',')
.Select(s => int.TryParse(s, out int result) ? result == 1 : default)
.ToArray();
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, bool defaultValue, MemberInfo target)
{
TrembleSyncSettings syncSettings = TrembleSyncSettings.Get();
target.GetCustomAttributes(
out SpawnFlagsAttribute sfa,
out NoSpawnFlagsAttribute noSfa,
out TooltipAttribute tooltip
);
bool useSpawnFlag = sfa != null || syncSettings.AlwaysPackBoolsIntoSpawnFlags;
if (noSfa != null)
{
useSpawnFlag = false;
}
if (useSpawnFlag)
{
string spawnFlagName = target.Name.GetFieldNameInMap(syncSettings.SpawnFlagNamingConvention);
if (syncSettings.SpawnFlagNamingConvention == NamingConvention.HumanFriendly)
{
spawnFlagName += "?";
}
int bit = sfa.GetBitForSpawnFlagsField(syncSettings, target);
entityClass.AddField(new FgdSpawnFlagField
{
Description = spawnFlagName,
Bit = bit,
DefaultValue = defaultValue
});
}
else
{
string friendlyName = target.Name.GetFieldNameInMap(NamingConvention.HumanFriendly) + "?";
entityClass.AddField(new FgdBooleanField
{
Name = fieldName,
Description = tooltip?.tooltip ?? friendlyName,
DefaultValue = defaultValue
});
}
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: b803c9e49f18b441a9c42c5bbbc96d24
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/FieldConverters/BoolFieldConverter.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.Linq;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(Color))]
public class ColourFieldConverter : TrembleFieldConverter<Color>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Color value)
{
return entity.TryGetColour(key, out value);
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Color[] values)
{
if (!entity.TryGetString(key, out string stringValues))
{
values = default;
return false;
}
values = stringValues
.Split(',')
.Select(s => s.TryParseQ3Colour(out Color result) ? result : Color.white)
.ToArray();
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, Color defaultValue, MemberInfo target)
{
string tooltip = target.GetCustomAttribute<TooltipAttribute>()?.tooltip;
entityClass.AddField(new FgdColourField
{
Name = fieldName,
Description = tooltip ?? $"{target.GetFieldOrPropertyType().Name} {target.Name}",
DefaultColour = defaultValue
});
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 5ddf531949ddd48c9b45c5bc4b79515a
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/FieldConverters/ColourFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,74 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System.Collections.Generic;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(Component))]
public class ComponentReferenceFieldConverter : TrembleFieldConverter<Component>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Component value)
{
if (entity.TryGetString(key, out string id))
{
if (TrembleMapImportSettings.Current.TryGetGameObjectsForID(id, out List<GameObject> objs) && objs.Count > 0)
{
value = objs[0].GetComponent(target.GetFieldOrPropertyTypeOrElementType());
if (!value)
{
Debug.LogWarning($"Entity '{objs[0].name}' reference '{id}' is of unexpected type. (expected: {target.GetFieldOrPropertyTypeOrElementType().Name}). Check the targeted entity in the map is of the correct type.");
}
return value;
}
}
value = default;
return false;
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Component[] values)
{
if (entity.TryGetString(key, out string id) && TrembleMapImportSettings.Current.TryGetGameObjectsForID(id, out List<GameObject> objs))
{
values = new Component[objs.Count];
for (int objIdx = 0; objIdx < objs.Count; objIdx++)
{
Component component = objs[objIdx].GetComponent(target.GetFieldOrPropertyTypeOrElementType());
if (!component)
{
Debug.LogWarning($"Entity '{objs[objIdx].name}' reference '{id}' is of unexpected type. (expected: {target.GetFieldOrPropertyTypeOrElementType().Name}). Check the targeted entity in the map is of the correct type.");
continue;
}
values[objIdx] = component;
}
return true;
}
values = default;
return false;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, Component defaultValue, MemberInfo target)
{
target.GetCustomAttributes(
out TooltipAttribute tooltip
);
entityClass.AddField(new FgdTargetDestinationField
{
Name = fieldName,
Description = tooltip?.tooltip ?? $"{target.GetFieldOrPropertyType().Name} {target.Name}",
DefaultValue = default
});
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: e3f0373df73804108ada11dc71de54ad
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/FieldConverters/ComponentReferenceFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,98 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
public class EnumFieldConverter : TrembleFieldConverter
{
public override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out object value)
{
// Enum special case - parse as int or string
if (entity.TryGetInt(key, out int enumIntValue))
{
value = enumIntValue;
return true;
}
if (entity.TryGetString(key, out string enumStringValue))
{
if (Enum.TryParse(target.GetFieldOrPropertyTypeOrElementType(), enumStringValue, true, out object enumObjValue))
{
value = (int)enumObjValue;
return true;
}
string entityName = entity.GetID().IsNullOrEmpty() ? entity.GetClassname() : $"'{entity.GetID()}' ({entity.GetClassname()})";
Debug.LogWarning($"Failed to parse value '{enumStringValue}' for enum {target.GetFieldOrPropertyTypeOrElementType()} in entity {entityName}. Using default.");
}
value = null;
return false;
}
public override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out object[] values)
{
if (!entity.TryGetString(key, out string commaDelimitedValue))
{
values = Array.Empty<object>();
return false;
}
string[] parts = commaDelimitedValue.Split(',');
values = new object[parts.Length];
for (int i = 0; i < parts.Length; i++)
{
// Enum special case - parse as int or string
if (int.TryParse(parts[i], out int enumIntValue))
{
values[i] = Enum.GetValues(target.GetFieldOrPropertyTypeOrElementType()).GetValue(enumIntValue);
}
else if (Enum.TryParse(target.GetFieldOrPropertyTypeOrElementType(), parts[i], true, out object enumObjValue))
{
values[i] = enumObjValue;
}
else
{
string entityName = entity.GetID().IsNullOrEmpty() ? entity.GetClassname() : $"'{entity.GetID()}' ({entity.GetClassname()})";
Debug.LogWarning($"Failed to parse value '{parts[i]}' for enum {target.GetFieldOrPropertyTypeOrElementType()} in entity {entityName}. Using default.");
}
}
return true;
}
public override void AddFieldToFgd(FgdClass entityClass, string fieldName, object defaultValue, MemberInfo target)
{
string tooltip = target.GetCustomAttribute<TooltipAttribute>()?.tooltip;
bool isFlags = target.GetFieldOrPropertyTypeOrElementType().GetCustomAttribute<FlagsAttribute>() != null;
if (isFlags)
{
entityClass.AddField(new FgdFlagsField
{
EnumClassName = target.GetFieldOrPropertyTypeOrElementType().FullName,
Name = fieldName,
Description = tooltip ?? $"{target.GetFieldOrPropertyTypeOrElementType()} {target.Name}",
});
}
else
{
entityClass.AddField(new FgdEnumField
{
EnumClassName = target.GetFieldOrPropertyTypeOrElementType().FullName,
Name = fieldName,
Description = tooltip ?? $"{target.GetFieldOrPropertyTypeOrElementType()} {target.Name}",
DefaultValue = defaultValue == null ? 0 : (int)defaultValue
});
}
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d027622fcb2143c28cb9bd4ed8b74bd2
timeCreated: 1710930324
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/FieldConverters/EnumFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,58 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System.Globalization;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(float))]
public class FloatFieldConverter : TrembleFieldConverter<float>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out float value)
{
return entity.TryGetFloat(key, out value);
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out float[] values)
{
if (!entity.TryGetString(key, out string stringValues))
{
values = default;
return false;
}
values = stringValues
.Split(',')
.Select(s => s.TryParseFloat(out float result) ? result : default)
.ToArray();
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, float defaultValue, MemberInfo target)
{
target.GetCustomAttributes(
out TooltipAttribute tooltip,
out RangeAttribute range
);
// Read range hint, if available
string rangeHint = "";
if (range != null)
{
rangeHint = $" (valid range: {range.min} - {range.max})";
}
entityClass.AddField(new FgdFloatField
{
Name = fieldName,
Description = (tooltip?.tooltip ?? $"{target.GetFieldOrPropertyType().Name} {target.Name}") + rangeHint,
DefaultValue = defaultValue
});
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 8bd2fdf6f450b4c9abf17350308678c6
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/FieldConverters/FloatFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,57 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(int))]
public class IntFieldConverter : TrembleFieldConverter<int>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out int value)
{
return entity.TryGetInt(key, out value);
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out int[] values)
{
if (!entity.TryGetString(key, out string stringValues))
{
values = default;
return false;
}
values = stringValues
.Split(',')
.Select(s => int.TryParse(s, out int result) ? result : default)
.ToArray();
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, int defaultValue, MemberInfo target)
{
target.GetCustomAttributes(
out TooltipAttribute tooltip,
out RangeAttribute range
);
// Read range hint, if available
string rangeHint = "";
if (range != null)
{
rangeHint = $" (valid range: {range.min} - {range.max})";
}
entityClass.AddField(new FgdIntegerField
{
Name = fieldName,
Description = (tooltip?.tooltip ?? $"{target.GetFieldOrPropertyType().Name} {target.Name}") + rangeHint,
DefaultValue = defaultValue
});
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 4f73e981a84ca44b4bfe0fe68379f559
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/FieldConverters/IntFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,14 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(Material))]
public class MaterialFieldConverter : UnityAssetFieldConverter<Material>
{
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: ce5b862461044f8f85be37945f4d2ba2
timeCreated: 1710146712
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/FieldConverters/MaterialFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,14 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(GameObject))]
public class PrefabFieldConverter : UnityAssetFieldConverter<GameObject>
{
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: d590871b719743c88547b6587254c7a0
timeCreated: 1710148685
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/FieldConverters/PrefabFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,14 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(ScriptableObject))]
public class ScriptableObjectFieldConverter : UnityAssetFieldConverter<ScriptableObject>
{
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 267ae928b4a54d1e8a4e47c20016b646
timeCreated: 1710148829
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/FieldConverters/ScriptableObjectFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,47 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(string))]
public class StringFieldConverter : TrembleFieldConverter<string>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out string value)
{
return entity.TryGetString(key, out value);
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out string[] values)
{
if (!entity.TryGetString(key, out string stringValues))
{
values = default;
return false;
}
values = stringValues.Split(',').ToArray();
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, string defaultValue, MemberInfo target)
{
target.GetCustomAttributes(
out TooltipAttribute tooltip
);
entityClass.AddField(new FgdStringField
{
Name = fieldName,
Description = tooltip?.tooltip ?? $"{target.GetFieldOrPropertyType().Name} {target.Name}",
DefaultValue = defaultValue
});
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: a40a28dd235b940dda3957abcdb86de6
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/FieldConverters/StringFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,114 @@
//
// 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.Linq;
using System.Reflection;
using UnityEngine;
using UnityEngine.Scripting;
namespace TinyGoose.Tremble
{
[AttributeUsage(AttributeTargets.Class)]
public class TrembleFieldConverterAttribute : PreserveAttribute
{
public TrembleFieldConverterAttribute(Type t)
{
m_Type = t;
}
private readonly Type m_Type;
public Type Type => m_Type;
}
[Preserve]
public abstract class TrembleFieldConverter
{
public abstract bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out object value);
public abstract bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out object[] value);
public abstract void AddFieldToFgd(FgdClass entityClass, string fieldName, object defaultValue, MemberInfo target);
}
public abstract class TrembleFieldConverter<T> : TrembleFieldConverter
{
public sealed override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out object value)
{
Type targetType = target.GetFieldOrPropertyType();
if (targetType.IsArray)
{
value = entity
.GetAllNumberedKeys(key)
.Select(k => TryGetValueFromMap(entity, k, gameObject, target, out T typedValue) ? typedValue : default)
.ToArray();
return true;
}
else
{
bool success = TryGetValueFromMap(entity, key, gameObject, target, out T typedValue);
value = success ? typedValue : default;
return success;
}
}
public sealed override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out object[] values)
{
string[] numberedKeys = entity.GetAllNumberedKeys(key).ToArray();
if (numberedKeys is { Length: 0 })
{
values = default;
return false;
}
List<object> outValues = new(numberedKeys.Length);
foreach (string numberedKey in numberedKeys)
{
// First get multiple and add if possible
if (TryGetValuesFromMap(entity, numberedKey, gameObject, target, out T[] tValues))
{
outValues.AddRange(tValues.Cast<object>());
}
else if (TryGetValueFromMap(entity, numberedKey, gameObject, target, out T value))
{
outValues.Add(value);
}
}
values = outValues.ToArray();
return true;
}
public sealed override void AddFieldToFgd(FgdClass entityClass, string fieldName, object defaultValue, MemberInfo target)
{
if (defaultValue is Array { Length: > 0 } defaultArray)
{
defaultValue = defaultArray.GetValue(0);
}
AddFieldToFgd(entityClass, fieldName, (T)defaultValue, target);
}
protected abstract bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out T value);
protected virtual bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out T[] values)
{
if (!TryGetValueFromMap(entity, key, gameObject, target, out T value))
{
values = default;
return false;
}
values = new T[1];
values[0] = value;
return true;
}
protected abstract void AddFieldToFgd(FgdClass entityClass, string fieldName, T defaultValue, MemberInfo target);
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: d6a1b8d48d2694bfb8d7dc8cbdc6c7ab
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/FieldConverters/TrembleFieldConverter.cs
uploadId: 939664
@@ -0,0 +1,81 @@
//
// 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.Linq;
using System.Reflection;
namespace TinyGoose.Tremble
{
public class TrembleFieldConverterCollection
{
private readonly List<TrembleFieldConverter> m_Converters = new();
private static readonly Dictionary<Type, TrembleFieldConverter> s_LookupCache = new();
private static readonly Dictionary<TrembleFieldConverter, TrembleFieldConverterAttribute> s_ConverterSetupCache = new();
public TrembleFieldConverterCollection()
{
m_Converters.AddRange(TypeDatabase
.GetTypesWithAttribute<TrembleFieldConverterAttribute>()
.Select(t => (TrembleFieldConverter)Activator.CreateInstance(t)));
}
public TrembleFieldConverter GetConverterForType(Type t)
{
// Array special case - expose as element type of array
if (t.IsArray)
{
t = t.GetElementType();
}
// Enum special case!
if (t.IsEnum)
{
return new EnumFieldConverter();
}
// First see if we've seen this type before
if (s_LookupCache.TryGetValue(t, out TrembleFieldConverter existingConverter))
{
return existingConverter;
}
// Exact match first
foreach (TrembleFieldConverter converter in m_Converters)
{
if (!s_ConverterSetupCache.TryGetValue(converter, out TrembleFieldConverterAttribute tfca))
{
tfca = converter.GetType().GetCustomAttribute<TrembleFieldConverterAttribute>();
s_ConverterSetupCache.Add(converter, tfca);
}
if (tfca.Type != t)
continue;
s_LookupCache[t] = converter;
return converter;
}
// Nothing exactly matches - look for subclasses too (for Components)
foreach (TrembleFieldConverter converter in m_Converters)
{
if (!s_ConverterSetupCache.TryGetValue(converter, out TrembleFieldConverterAttribute tfca))
{
tfca = converter.GetType().GetCustomAttribute<TrembleFieldConverterAttribute>();
s_ConverterSetupCache.Add(converter, tfca);
}
if (!t.IsSubclassOf(tfca.Type))
continue;
s_LookupCache[t] = converter;
return converter;
}
return null;
}
}
}
@@ -0,0 +1,10 @@
fileFormatVersion: 2
guid: 9c34bb2b1df149a9bc168bb41f596387
timeCreated: 1710858661
AssetOrigin:
serializedVersion: 1
productId: 277805
packageName: Tremble - Map Importer
packageVersion: 1.11.1
assetPath: Assets/Tremble/FieldConverters/TrembleFieldConverterCollection.cs
uploadId: 939664
@@ -0,0 +1,82 @@
//
// 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.Linq;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(Vector3))]
public class Vector3Converter : TrembleFieldConverter<Vector3>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Vector3 value)
{
target.GetCustomAttributes(out TrembleAttribute tremble);
bool? isRotation = tremble?.IsRotation;
// Keep raw value if requested, or it's a "rotation"
isRotation ??= key.ContainsInvariant("rotation") || key.ContainsInvariant("rotate");
return isRotation.Value
? entity.TryGetUntransformedVector(key, out value)
: entity.TryGetVector(key, out value);
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Vector3[] values)
{
if (!entity.TryGetString(key, out string stringValues))
{
values = default;
return false;
}
target.GetCustomAttributes(out TrembleAttribute tremble);
bool? isRotation = tremble?.IsRotation;
// Keep raw value if requested, or it's a "rotation"
isRotation ??= key.ContainsInvariant("rotation") || key.ContainsInvariant("rotate");
values = stringValues
.Split(',')
.Select(s =>
{
s.TryParseQ3Vector(out Vector3 result);
if (!isRotation.GetValueOrDefault(false))
{
result.Q3ToUnityVector(entity.ImportScale);
}
return result;
})
.ToArray();
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, Vector3 defaultValue, MemberInfo target)
{
target.GetCustomAttributes(
out TrembleAttribute tremble,
out TooltipAttribute tooltip
);
// Keep raw value if requested, or it's a "rotation"
bool? isRotation = tremble?.IsRotation;
isRotation ??= fieldName.ContainsInvariant("rotation") || fieldName.ContainsInvariant("rotate");
entityClass.AddField(new FgdVectorField
{
Name = fieldName,
Description = tooltip?.tooltip ?? $"{target.GetFieldOrPropertyType().Name} {target.Name}",
DefaultValue = defaultValue,
ImportScale = isRotation.Value ? 1f : TrembleSyncSettings.Get().ImportScale,
ConvertToQ3 = true
});
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 6e3e987223b8a49f19b5873fcb84b8b4
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/FieldConverters/Vector3Converter.cs
uploadId: 939664
@@ -0,0 +1,71 @@
//
// This file is part of the Tremble package by Tiny Goose.
// Copyright (c) 2024-2026 TinyGoose Ltd., All Rights Reserved.
//
using System;
using System.Linq;
using System.Reflection;
using UnityEngine;
namespace TinyGoose.Tremble
{
[TrembleFieldConverter(typeof(Vector3Int))]
public class Vector3IntConverter : TrembleFieldConverter<Vector3Int>
{
protected override bool TryGetValueFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Vector3Int value)
{
if (entity.TryGetUntransformedVector(key, out Vector3 v3Value))
{
value = new((int)v3Value.x, (int)v3Value.z, (int)v3Value.y);
return true;
}
value = default;
return false;
}
protected override bool TryGetValuesFromMap(BspEntity entity, string key, GameObject gameObject, MemberInfo target, out Vector3Int[] values)
{
if (!entity.TryGetString(key, out string stringValues))
{
values = default;
return false;
}
target.GetCustomAttributes(out TrembleAttribute tremble);
bool? isRotation = tremble?.IsRotation;
// Keep raw value if requested, or it's a "rotation"
isRotation ??= key.ContainsInvariant("rotation") || key.ContainsInvariant("rotate");
values = stringValues
.Split(',')
.Select(s =>
{
s.TryParseQ3Vector(out Vector3 result);
if (!isRotation.GetValueOrDefault(false))
{
result.Q3ToUnityVector(entity.ImportScale);
}
return new Vector3Int((int)result.x, (int)result.z, (int)result.y);
})
.ToArray();
return true;
}
protected override void AddFieldToFgd(FgdClass entityClass, string fieldName, Vector3Int defaultValue, MemberInfo target)
{
string tooltip = target.GetCustomAttribute<TooltipAttribute>()?.tooltip;
entityClass.AddField(new FgdVectorField
{
Name = fieldName,
Description = tooltip ?? $"{target.GetFieldOrPropertyType().Name} {target.Name}",
DefaultValue = defaultValue
});
}
}
}
@@ -0,0 +1,18 @@
fileFormatVersion: 2
guid: 77ccd99169ea24f61a74fcabd01696e1
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/FieldConverters/Vector3IntConverter.cs
uploadId: 939664