public void StaticFunctionTests() { void InverseWorking(Easing.EaseType easeType, Easing.EaseOption easeOption, double k) { var output = Easing.Calculate(easeType, easeOption, k); var input = Easing.CalculateInverse(easeType, easeOption, output); Assert.AreEqual(k, input, .001); } void RangeTest(Easing.EaseType easeType) { for (double i = 0; i <= 1; i += .05) { InverseWorking(easeType, Easing.EaseOption.In, i); InverseWorking(easeType, Easing.EaseOption.InOut, i); InverseWorking(easeType, Easing.EaseOption.Out, i); } } RangeTest(Easing.EaseType.Linear); RangeTest(Easing.EaseType.Cubic); RangeTest(Easing.EaseType.Quadratic); }
public static GuiWidget GetFieldContentWithSlider(EditableProperty property, PPEContext context, UIField field, UndoBuffer undoBuffer, Func <string, object> valueFromString, ThemeConfig theme) { var sliderAttribute = property.PropertyInfo.GetCustomAttributes(true).OfType <SliderAttribute>().FirstOrDefault(); if (sliderAttribute != null) { var min = sliderAttribute.Min; var max = sliderAttribute.Max; var delta = max - min; // the slider values go from 0 to 1 and are then mapped during translation to the field var slider = new Slider(new Vector2(0, 0), 80 * GuiWidget.DeviceScale, 0, 1) { VAnchor = VAnchor.Center, }; slider.View.TrackColor = theme.TextColor; slider.View.ThumbColor = theme.PrimaryAccentColor; slider.View.TrackHeight = 1 * GuiWidget.DeviceScale; Func <double> getFieldValue = null; double GetSlider0To1FromField() { return(GetSlider0To1FromValue(getFieldValue())); } double GetSlider0To1FromValue(double value) { var mapped0To1 = Math.Max(0, Math.Min(1, (value - min) / delta)); return(Easing.CalculateInverse(sliderAttribute.EasingType, sliderAttribute.EaseOption, mapped0To1)); } double GetFieldFromSlider0To1() { var fieldValue = Easing.Calculate(sliderAttribute.EasingType, sliderAttribute.EaseOption, slider.Value) * delta + min; var snapGridDistance = sliderAttribute.SnapDistance; if (sliderAttribute.UseSnappingGrid) { snapGridDistance = SnapGridDistance(); } if (snapGridDistance > 0) { // snap this position to the grid // snap this position to the grid fieldValue = ((int)((fieldValue / snapGridDistance) + .5)) * snapGridDistance; } return(fieldValue); } double SnapGridDistance() { var view3DWidget = slider.Parents <View3DWidget>().FirstOrDefault(); if (view3DWidget != null) { var object3DControlLayer = view3DWidget.Descendants <Object3DControlsLayer>().FirstOrDefault(); if (object3DControlLayer != null) { return(object3DControlLayer.SnapGridDistance); } } return(0); } var changeDueToSlider = false; var changeDueToField = false; slider.ValueChanged += (s, e) => { if (!changeDueToField) { changeDueToSlider = true; SetValue(property, context, valueFromString, GetFieldFromSlider0To1()); changeDueToSlider = false; } }; double sliderDownValue = 0; slider.SliderGrabed += (s, e) => { sliderDownValue = getFieldValue(); }; slider.SliderReleased += (s, e) => { var currentValue = GetFieldFromSlider0To1(); changeDueToSlider = true; SetValue(property, context, valueFromString, currentValue); changeDueToSlider = false; // save the undo information undoBuffer.Add(new UndoRedoActions(() => { SetValue(property, context, valueFromString, sliderDownValue); }, () => { SetValue(property, context, valueFromString, currentValue); })); }; GuiWidget content = null; var sliderRightMargin = 11; if (field is DoubleField doubleField) { getFieldValue = () => doubleField.DoubleValue; doubleField.ValueChanged += (s, e) => { changeDueToField = true; slider.Value = GetSlider0To1FromField(); changeDueToField = false; }; content = new FlowLayoutWidget(); content.AddChild(slider); content.AddChild(new GuiWidget() { Width = sliderRightMargin * GuiWidget.DeviceScale, Height = 3 }); content.AddChild(field.Content); } else if (field is ExpressionField expressionField) { getFieldValue = () => { if (double.TryParse(expressionField.Value, out double value)) { return(value); } return(0); }; expressionField.ValueChanged += (s, e) => { if (!changeDueToSlider) { changeDueToField = true; slider.Value = GetSlider0To1FromField(); changeDueToField = false; } }; expressionField.Content.Descendants <TextWidget>().First().TextChanged += (s, e) => { if (!changeDueToSlider) { changeDueToField = true; var textWidget = expressionField.Content.Descendants <TextWidget>().First(); double.TryParse(textWidget.Text, out double textWidgetValue); slider.Value = GetSlider0To1FromValue(textWidgetValue); changeDueToField = false; } }; var leftHold = new FlowLayoutWidget() { HAnchor = HAnchor.Stretch, Margin = new BorderDouble(0, 0, 66 / GuiWidget.DeviceScale + sliderRightMargin, 0) }; leftHold.AddChild(new HorizontalSpacer()); leftHold.AddChild(slider); field.Content.AddChild(leftHold, 0); content = field.Content; } // set the initial value of the slider changeDueToField = true; slider.Value = GetSlider0To1FromField(); changeDueToField = false; return(content); } return(field.Content); }