Kursach_StealthAction/Assets/Tremble/FieldConverters/TrembleFieldConverter.cs
2026-10-11 19:16:11 +03:00

114 lines
3.3 KiB
C#

//
// 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);
}
}