FuncInputProperty.cs 6.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195
  1. using PixiEditor.ChangeableDocument.Changeables.Graph.Context;
  2. using PixiEditor.ChangeableDocument.Changeables.Graph.Interfaces;
  3. using PixiEditor.ChangeableDocument.Changeables.Graph.Nodes;
  4. using PixiEditor.ChangeableDocument.Changes.NodeGraph;
  5. using Drawie.Backend.Core.Shaders;
  6. using Drawie.Backend.Core.Shaders.Generation;
  7. using Drawie.Backend.Core.Shaders.Generation.Expressions;
  8. namespace PixiEditor.ChangeableDocument.Changeables.Graph;
  9. public class FuncInputProperty<T, TContext> : InputProperty<Func<TContext, T>>, IFuncInputProperty where TContext : FuncContext
  10. {
  11. private T? constantNonOverrideValue;
  12. private int lastConstantHashCode;
  13. internal FuncInputProperty(Node node, string internalName, string displayName, T defaultValue) : base(node,
  14. internalName, displayName, null)
  15. {
  16. constantNonOverrideValue = defaultValue;
  17. NonOverridenValue = _ => constantNonOverrideValue;
  18. }
  19. protected override void NonOverridenValueSet(Func<TContext, T> value)
  20. {
  21. constantNonOverrideValue = value(null);
  22. }
  23. protected internal override object FuncFactory(object toReturn)
  24. {
  25. Func<TContext, T> func = _ =>
  26. {
  27. if (typeof(T).IsAssignableTo(typeof(ShaderExpressionVariable)))
  28. {
  29. var shaderExpressionVariable = (ShaderExpressionVariable)Activator.CreateInstance(typeof(T), "");
  30. shaderExpressionVariable.SetConstantValue(toReturn, ConversionTable.Convert);
  31. return (T)(object)shaderExpressionVariable;
  32. }
  33. return (T)toReturn;
  34. };
  35. return func;
  36. }
  37. protected override object FuncFactoryDelegate(Delegate delegateToCast)
  38. {
  39. Func<TContext, T> func = f =>
  40. {
  41. Type targetType = typeof(T);
  42. bool isShaderExpression = false;
  43. if (typeof(T).IsAssignableTo(typeof(ShaderExpressionVariable)))
  44. {
  45. targetType = targetType.BaseType.GenericTypeArguments[0];
  46. isShaderExpression = true;
  47. }
  48. var sourceObj = delegateToCast.DynamicInvoke(f);
  49. ConversionTable.TryConvert(sourceObj, targetType, out var result);
  50. if (isShaderExpression)
  51. {
  52. var toReturn = Activator.CreateInstance(typeof(T), "");
  53. if (result != null)
  54. {
  55. ((ShaderExpressionVariable)toReturn).SetConstantValue(result, ConversionTable.Convert);
  56. }
  57. else if (sourceObj is Expression expression)
  58. {
  59. ShaderExpressionVariable shaderExpressionVariable = (ShaderExpressionVariable)toReturn;
  60. var adjusted = Adjust(expression, toReturn, out var adjustNested);
  61. if (adjustNested)
  62. {
  63. AdjustNested(((IMultiValueVariable)toReturn), expression);
  64. shaderExpressionVariable.OverrideExpression = ((IMultiValueVariable)toReturn).GetWholeNestedExpression();
  65. }
  66. else
  67. {
  68. shaderExpressionVariable.OverrideExpression = adjusted;
  69. }
  70. }
  71. return (T)toReturn;
  72. }
  73. return result == null ? default : (T)result;
  74. };
  75. return func;
  76. }
  77. private Expression Adjust(Expression expression, object toReturn, out bool adjustNestedVariables)
  78. {
  79. adjustNestedVariables = false;
  80. if (expression is IMultiValueVariable multiVal && toReturn is not IMultiValueVariable)
  81. {
  82. return multiVal.GetValueAt(0);
  83. }
  84. if (toReturn is IMultiValueVariable)
  85. {
  86. adjustNestedVariables = true;
  87. }
  88. return expression;
  89. }
  90. private void AdjustNested(IMultiValueVariable toReturn, Expression expression)
  91. {
  92. if (toReturn is not ShaderExpressionVariable shaderExpressionVariable)
  93. {
  94. return;
  95. }
  96. if (expression is not IMultiValueVariable multiVal)
  97. {
  98. int count = toReturn.GetValuesCount();
  99. for (int i = 0; i < count; i++)
  100. {
  101. toReturn.OverrideExpressionAt(i, expression);
  102. }
  103. }
  104. else
  105. {
  106. int sourceCount = multiVal.GetValuesCount();
  107. int targetCount = toReturn.GetValuesCount();
  108. int count = Math.Min(sourceCount, targetCount);
  109. for (int i = 0; i < count; i++)
  110. {
  111. toReturn.OverrideExpressionAt(i, multiVal.GetValueAt(i));
  112. }
  113. }
  114. }
  115. object? IFuncInputProperty.GetFuncConstantValue() => constantNonOverrideValue;
  116. void IFuncInputProperty.SetFuncConstantValue(object? value)
  117. {
  118. if (value is T)
  119. {
  120. constantNonOverrideValue = (T)value;
  121. return;
  122. }
  123. if (constantNonOverrideValue is ShaderExpressionVariable shaderExpressionVariable)
  124. {
  125. shaderExpressionVariable.SetConstantValue(value, ConversionTable.Convert);
  126. NonOverridenValue = _ => constantNonOverrideValue;
  127. return;
  128. }
  129. if (ConversionTable.TryConvert(value, typeof(T), out var result))
  130. {
  131. constantNonOverrideValue = (T)result;
  132. return;
  133. }
  134. constantNonOverrideValue = default;
  135. }
  136. internal override bool CacheChanged
  137. {
  138. get
  139. {
  140. if (constantNonOverrideValue == null)
  141. {
  142. return base.CacheChanged;
  143. }
  144. if (Connection == null && lastConnectionHash != -1)
  145. {
  146. return true;
  147. }
  148. if (Connection != null && lastConnectionHash != Connection.GetHashCode())
  149. {
  150. lastConnectionHash = Connection.GetHashCode();
  151. return true;
  152. }
  153. if (constantNonOverrideValue is ShaderExpressionVariable expressionVariable)
  154. {
  155. return expressionVariable.ConstantValueString.GetHashCode() != lastConstantHashCode;
  156. }
  157. return base.CacheChanged;
  158. }
  159. }
  160. internal override void UpdateCache()
  161. {
  162. base.UpdateCache();
  163. if (constantNonOverrideValue is ShaderExpressionVariable expressionVariable)
  164. {
  165. lastConstantHashCode = expressionVariable.ConstantValueString.GetHashCode();
  166. }
  167. }
  168. }