103 lines
4.1 KiB
C#
103 lines
4.1 KiB
C#
using System;
|
|
using System.Collections.Generic;
|
|
using System.Linq;
|
|
using System.Text.RegularExpressions;
|
|
using Sirenix.OdinInspector;
|
|
using UnityEngine;
|
|
using Object = UnityEngine.Object;
|
|
|
|
namespace VOID.Generic.DynamicValue
|
|
{
|
|
[Serializable]
|
|
public class DynamicText
|
|
{
|
|
// STATIC - Cached markers
|
|
private static List<IMarker> _markers =
|
|
AppDomain.CurrentDomain.GetAssemblies()
|
|
.SelectMany(assembly => assembly.GetTypes())
|
|
.Where(type => typeof(IMarker).IsAssignableFrom(type) && type.IsClass)
|
|
.Select(Activator.CreateInstance)
|
|
.Cast<IMarker>()
|
|
.ToList();
|
|
|
|
private static List<IMarkerGroup> _groupMarkers =
|
|
AppDomain.CurrentDomain.GetAssemblies()
|
|
.SelectMany(assembly => assembly.GetTypes())
|
|
.Where(type => typeof(IMarkerGroup).IsAssignableFrom(type) && type.IsClass)
|
|
.Select(Activator.CreateInstance)
|
|
.Cast<IMarkerGroup>()
|
|
.ToList();
|
|
|
|
#if UNITY_EDITOR
|
|
[ShowInInspector, Searchable, ListDrawerSettings(IsReadOnly = true)]
|
|
private static List<MarkerDummyString> _allMarkers = new List<string>()
|
|
.Union(_markers.Select(m => m.Marker()))
|
|
.Union(_groupMarkers.SelectMany(mg => mg.Markers().Select(m => $"{mg.Group()}.{m}")))
|
|
.Select(str => new MarkerDummyString(str))
|
|
.ToList();
|
|
#endif
|
|
|
|
// User defined formula or text with markers
|
|
[SerializeField, TextArea(1,20)] private string _dynamicValue;
|
|
public string dynamicValue => _dynamicValue;
|
|
|
|
// TODO: Sources are needed to work, but so far will be given only via script
|
|
private List<Object> _sources = new();
|
|
|
|
// Parsed
|
|
private bool _isParsed;
|
|
private string _stringFormat;
|
|
private List<Func<string>> _valueGetters;
|
|
|
|
public void AddSource(Object obj) => _sources.Add(obj);
|
|
|
|
private void Parse()
|
|
{
|
|
_isParsed = true;
|
|
_valueGetters = Regex.Matches(_dynamicValue, "{(.*?)}")
|
|
.Select(match => match.Value)
|
|
.Select(stringMarker =>
|
|
{
|
|
stringMarker = stringMarker.Trim('{', '}');
|
|
var dotIndex = stringMarker.LastIndexOf('.');
|
|
var groupName = string.Join(string.Empty, stringMarker.Take(dotIndex));
|
|
var markerName = string.Join(string.Empty, stringMarker.Skip(dotIndex+1));
|
|
|
|
return TryParseMarker(markerName) ?? TryParseMarkerGroup(groupName, markerName) ?? (() => $"{{{stringMarker}}}");
|
|
})
|
|
.ToList();
|
|
|
|
var matchIndex = 0;
|
|
_stringFormat = Regex.Replace(_dynamicValue, "{(.*?)}", _ => $"{{{matchIndex++}}}");
|
|
}
|
|
|
|
private Func<string> TryParseMarker(string markerName)
|
|
{
|
|
var marker = _markers.FirstOrDefault(m => m.Marker().Equals(markerName));
|
|
if (marker == null) return null;
|
|
var source = _sources.FirstOrDefault(source => marker.SourceType().IsInstanceOfType(source));
|
|
if (source == null) return null;
|
|
return marker.Getter(source);
|
|
}
|
|
|
|
private Func<string> TryParseMarkerGroup(string groupName, string markerName)
|
|
{
|
|
var markerGroup = _groupMarkers.FirstOrDefault(mg => mg.Group().Equals(groupName) && mg.Markers().Contains(markerName));
|
|
if (markerGroup == null) return null;
|
|
var source = _sources.FirstOrDefault(source => markerGroup.SourceType().IsInstanceOfType(source));
|
|
if (source == null) return null;
|
|
return markerGroup.Getter(source, markerName);
|
|
}
|
|
|
|
public string Get()
|
|
{
|
|
#if UNITY_EDITOR
|
|
_isParsed = false;
|
|
#endif
|
|
if (!_isParsed) Parse();
|
|
return string.Format(_stringFormat, _valueGetters.Select(getter => getter.Invoke()).ToArray<object>());
|
|
}
|
|
|
|
public static implicit operator string(DynamicText dynamicText) => dynamicText.Get();
|
|
}
|
|
} |