5 using System.Collections.Generic;
6 using System.Reflection;
8 namespace SiliconStudio.
Paradox.Effects
11 internal class ParameterPath
13 public ParameterPath(params ParameterKey[] keys)
15 Keys = keys.ToArray();
18 public object GetValue(ParameterCollection parameterCollection)
20 for (
int i = 0; i < Keys.Length; ++i)
22 if (!parameterCollection.ContainsKey(
Keys[i]))
25 var value = parameterCollection.GetObject(
Keys[i]);
28 if (i ==
Keys.Length - 1)
32 if (!(value is ParameterCollection))
35 parameterCollection = (ParameterCollection)value;
41 internal ParameterKey[]
Keys {
get; set; }
45 internal class ParameterListener
47 private List<KeyValuePair<ParameterKey, ParameterCollection>> containers =
new List<KeyValuePair<ParameterKey, ParameterCollection>>();
48 private List<ParameterCollection.ValueChangedDelegate> delegates =
new List<ParameterCollection.ValueChangedDelegate>();
50 private ParameterPath path;
52 private object currentValue;
54 public delegate
void ParameterUpdatedDelegate(ParameterCollection container, ParameterPath path,
object newValue);
56 public event ParameterUpdatedDelegate ParameterUpdated;
58 public ParameterListener(ParameterCollection parameterCollection, ParameterPath path)
62 foreach (var currentContainer
in ContainersInPath(parameterCollection, path.Keys))
64 AppendCurrentPath(currentContainer);
67 currentValue = path.GetValue(containers[0].Value);
70 private void AppendCurrentPath(ParameterCollection parameterCollection)
72 ParameterCollection.ValueChangedDelegate currentDelegate;
75 var key = path.Keys[containers.Count];
76 var keyAndContainer =
new KeyValuePair<ParameterKey, ParameterCollection>(key, parameterCollection);
77 var containerIndex = containers.IndexOf(keyAndContainer);
79 if (containerIndex == -1)
81 var pathIndex = containers.Count;
82 currentDelegate = (internalValueKey, internalValue, oldValue) =>
83 propertyContainer_PropertyUpdated(parameterCollection, internalValue.Object, oldValue, pathIndex);
84 parameterCollection.AddEvent(key, currentDelegate);
88 currentDelegate = delegates[containerIndex];
91 containers.Add(keyAndContainer);
92 delegates.Add(currentDelegate);
97 yield
return parameterCollection;
98 foreach (var key
in keys)
100 if (!parameterCollection.ContainsKey(key))
102 var nextContainer = parameterCollection.GetObject(key) as ParameterCollection;
103 if (nextContainer == null)
105 yield
return nextContainer;
106 parameterCollection = nextContainer;
110 private void propertyContainer_PropertyUpdated(ParameterCollection parameterCollection,
object newValue,
object oldValue,
int pathIndex)
112 if (containers[pathIndex].Value != parameterCollection)
113 throw new InvalidOperationException(
"Unexpected PropertyContainer in PathListener.");
116 if (pathIndex < path.Keys.Length - 1)
119 for (
int i = pathIndex + 1; i < containers.Count; ++i)
122 if (containers.IndexOf(containers[i], 0, i) == -1)
123 containers[i].
Value.RemoveEvent(path.Keys[i], delegates[i]);
127 containers.RemoveRange(pathIndex + 1, containers.Count - pathIndex - 1);
128 delegates.RemoveRange(pathIndex + 1, delegates.Count - pathIndex - 1);
131 foreach (var currentContainer
in ContainersInPath(parameterCollection, path.Keys.Skip(pathIndex)).Skip(1))
134 AppendCurrentPath(currentContainer);
138 var newValue2 = path.GetValue(containers[0].Value);
139 if (ParameterUpdated != null && !ArePropertyValuesEqual(path.Keys.Last(), this.currentValue, newValue2))
140 ParameterUpdated(containers[0].Value, path, newValue2);
141 this.currentValue = newValue2;
144 private static bool ArePropertyValuesEqual(ParameterKey propertyKey,
object propertyValue1,
object propertyValue2)
146 var propertyType = propertyKey.PropertyType;
148 if (!propertyType.GetTypeInfo().IsValueType && propertyType != typeof(
string))
150 return object.ReferenceEquals(propertyValue1, propertyValue2);
153 return object.Equals(propertyValue1, propertyValue2);
SiliconStudio.Paradox.Input.Keys Keys