100 lines
3.4 KiB
C#
100 lines
3.4 KiB
C#
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<string, SerializableType> _serializedTypes = new();
|
|
[SerializeField] internal SerializableDictionary<string, Object> _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<string, Type> 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<object>();
|
|
return string.Format(_formulaFormat, values);
|
|
}
|
|
|
|
public int GetValue(DynamicValueSourceContext sourceContext = null)
|
|
{
|
|
Parse();
|
|
ExpressionEvaluator.Evaluate(GetString(sourceContext), out int value);
|
|
return value;
|
|
}
|
|
}
|
|
} |