99 lines
3.2 KiB
C#
99 lines
3.2 KiB
C#
using Cryville.Common.ComponentModel;
|
|
using System;
|
|
using System.ComponentModel;
|
|
using System.Linq;
|
|
using System.Reflection;
|
|
|
|
namespace Cryville.Crtr.Config {
|
|
public interface IPropertyAdapter {
|
|
string Category { get; }
|
|
string Name { get; }
|
|
PropertyType Type { get; }
|
|
object[] Range { get; }
|
|
object GetValue();
|
|
void SetValue(object value);
|
|
object MapValue(object value);
|
|
bool SetMapped { get; }
|
|
object MapValueInverse(object value);
|
|
}
|
|
|
|
public enum PropertyType {
|
|
Unknown,
|
|
Number,
|
|
NumberStepped,
|
|
Boolean,
|
|
String,
|
|
}
|
|
|
|
public class DefaultPropertyAdapter : IPropertyAdapter {
|
|
readonly object _target;
|
|
readonly PropertyInfo _prop;
|
|
public string Category { get; private set; }
|
|
public string Name { get; private set; }
|
|
public PropertyType Type { get; private set; }
|
|
public object[] Range { get; private set; }
|
|
public object GetValue() { return _prop.GetValue(_target, null); }
|
|
public void SetValue(object value) { _prop.SetValue(_target, value, null); }
|
|
|
|
readonly double _precision;
|
|
readonly double _step;
|
|
readonly bool _logarithmic;
|
|
public object MapValue(object value) {
|
|
if (Type == PropertyType.Number || Type == PropertyType.NumberStepped) {
|
|
var result = (double)value;
|
|
if (_step != 0) result *= _step;
|
|
if (_logarithmic) result = Math.Pow(Math.E, result);
|
|
if (_precision != 0) result = Math.Round(result / _precision) * _precision;
|
|
return Convert.ChangeType(result, _prop.PropertyType);
|
|
}
|
|
return value;
|
|
}
|
|
public bool SetMapped { get { return true; } }
|
|
public object MapValueInverse(object value) {
|
|
if (Type == PropertyType.Number || Type == PropertyType.NumberStepped) {
|
|
var result = Convert.ToDouble(value);
|
|
if (_logarithmic) result = Math.Log(result);
|
|
if (_step != 0) result /= _step;
|
|
return result;
|
|
}
|
|
return value;
|
|
}
|
|
|
|
public DefaultPropertyAdapter(object target, PropertyInfo prop) {
|
|
_target = target;
|
|
_prop = prop;
|
|
var attrs = prop.GetCustomAttributes(typeof(CategoryAttribute), true);
|
|
if (attrs.Length > 0) Category = ((CategoryAttribute)attrs.Single()).Category;
|
|
Name = prop.Name;
|
|
if (prop.PropertyType == typeof(bool)) Type = PropertyType.Boolean;
|
|
else if (prop.PropertyType == typeof(char)) throw new NotSupportedException();
|
|
else if (prop.PropertyType.IsPrimitive) {
|
|
Type = prop.GetCustomAttributes(typeof(StepAttribute), true).Length > 0
|
|
? PropertyType.NumberStepped
|
|
: PropertyType.Number;
|
|
var attr = prop.GetCustomAttributes(typeof(RangeAttribute), true);
|
|
if (attr.Length > 0) {
|
|
var u = (RangeAttribute)attr.Single();
|
|
Range = new object[] { u.Min, u.Max };
|
|
}
|
|
attr = prop.GetCustomAttributes(typeof(PrecisionAttribute), true);
|
|
if (attr.Length > 0) {
|
|
var u = (PrecisionAttribute)attr.Single();
|
|
_precision = u.Precision;
|
|
}
|
|
attr = prop.GetCustomAttributes(typeof(StepAttribute), true);
|
|
if (attr.Length > 0) {
|
|
var u = (StepAttribute)attr.Single();
|
|
_step = u.Step;
|
|
}
|
|
attr = prop.GetCustomAttributes(typeof(LogarithmicScaleAttribute), true);
|
|
if (attr.Length > 0) {
|
|
_logarithmic = true;
|
|
}
|
|
}
|
|
else if (prop.PropertyType == typeof(string)) Type = PropertyType.String;
|
|
else return;
|
|
}
|
|
}
|
|
}
|