using System; using System.Collections.Generic; using System.Linq; using System.Text.RegularExpressions; using RPGCoreCommon.Helpers; using RPGCoreCommon.Helpers.CustomTypes; using UnityEngine; using Object = UnityEngine.Object; namespace RPGCoreCommon.DynamicValues { [Serializable] public class DynamicValue { // User defined formula or text with markers [SerializeField] internal string _serializedFormula; [SerializeField] internal SerializableDictionary _serializedTypes = new(); [SerializeField] internal SerializableDictionary _serializedSources = new(); private bool _isParsed; private string _formulaFormat; private MarkerParser[] _markers; private void Parse() { if (Application.isPlaying && _isParsed) return; _isParsed = true; var matches = new Regex("{[a-zA-z0-9-\\.]*}").Matches(_serializedFormula); _markers = new MarkerParser[matches.Count]; _formulaFormat = _serializedFormula; for (var i = matches.Count-1; i >= 0; i--) { _markers[i] = new MarkerParser(matches[i].Value); _markers[i].sourceType = GetSourceType(_markers[i].sourceMarker); _formulaFormat = _formulaFormat.Remove(matches[i].Index, matches[i].Length).Insert(matches[i].Index, $"{{{i}}}"); } } private Type GetSourceType(string sourceMarker) { if (_serializedTypes.TryGetValue(sourceMarker, out var type)) return type; if (_serializedSources.TryGetValue(sourceMarker, out var obj)) return obj.GetType(); return null; } private object GetSource(string sourceMarker, DynamicValueSourceContext sourceContext = null) { if (_serializedSources.TryGetValue(sourceMarker, out var s1)) return s1; if (sourceContext != null && sourceContext.TryGetSource(sourceMarker, out var s2)) return s2; return null; } public void RemoveDynamicTypes() { _serializedTypes.Clear(); } public void SetDynamicTypes(Dictionary types) { RemoveDynamicTypes(); types.DictForEach(SetDynamicType); } public void SetDynamicType(string name, Type type) { if (Application.isPlaying) { Debug.LogError($"method '{nameof(SetDynamicType)}' is only available in editor. Dynamic types should not be changed runtime!"); return; } _serializedTypes[name] = new SerializableType(type); } public MarkerParser[] GetMarkers() { Parse(); return _markers.ToArray(); } public string GetString(DynamicValueSourceContext sourceContext = null) { Parse(); var values = _markers .Select(marker => marker.GetValue(GetSource(marker.sourceMarker, sourceContext))) .ToArray(); return string.Format(_formulaFormat, values); } public int GetValue(DynamicValueSourceContext sourceContext = null) { Parse(); ExpressionEvaluator.Evaluate(GetString(sourceContext), out int value); return value; } } }