diff --git a/src/microbe_stage/editor/ToleranceRangeDisplay.cs b/src/microbe_stage/editor/ToleranceRangeDisplay.cs index d7ba3bbe2bf..b03e23b71cf 100644 --- a/src/microbe_stage/editor/ToleranceRangeDisplay.cs +++ b/src/microbe_stage/editor/ToleranceRangeDisplay.cs @@ -18,6 +18,12 @@ public partial class ToleranceRangeDisplay : HSlider [Export] private bool showMiddleMarker; + [Export] + private bool logarithmicScale; + + [Export] + private float logarithmicScaleOffset = 1; + [Export] private RangeMarker beginConnectorFromMarker; @@ -71,8 +77,7 @@ public override void _Draw() var lowerBoundCenter = new Vector2(lowerBoundPos + LINE_WIDTH * 0.5f, Size.Y * 0.5f); var upperBoundCenter = new Vector2(upperBoundPos + LINE_WIDTH * 0.5f, Size.Y * 0.5f); - var middleBoundCenter = - new Vector2((float)(Size.X * (Value - MinValue) / (MaxValue - MinValue)), Size.Y * 0.5f); + var middleBoundCenter = new Vector2(Size.X * GetValueFraction((float)Value), Size.Y * 0.5f); var boundOffset = new Vector2(0, Constants.TOLERANCE_DISPLAY_BOUND_HEIGHT * 0.5f); @@ -134,8 +139,7 @@ public override void _Draw() /// Has to be between this slider's max and min. public void UpdateMarker(float value) { - optimalValueMarker.OptimalValue = (value - (float)MinValue) - / (float)(MaxValue - MinValue); + optimalValueMarker.OptimalValue = GetValueFraction(value); } /// @@ -186,11 +190,11 @@ public void SetColorsAndRedraw() private void SetBoundPositions() { - var upperBoundFraction = Math.Clamp((upperValue - MinValue) / (MaxValue - MinValue), 0, 1); - var lowerBoundFraction = Math.Clamp((lowerValue - MinValue) / (MaxValue - MinValue), 0, 1); + var upperBoundFraction = GetValueFraction(upperValue); + var lowerBoundFraction = GetValueFraction(lowerValue); - lowerBoundPos = Size.X * (float)lowerBoundFraction - 1; - upperBoundPos = Size.X * (float)upperBoundFraction - 1; + lowerBoundPos = Size.X * lowerBoundFraction - 1; + upperBoundPos = Size.X * upperBoundFraction - 1; QueueRedraw(); } @@ -211,6 +215,24 @@ private void UpdateSliderGrabberXPos() QueueRedraw(); } + private float GetValueFraction(float value) + { + if (MaxValue <= MinValue) + return 0; + + value = Math.Clamp(value, (float)MinValue, (float)MaxValue); + + if (!logarithmicScale) + return (float)((value - MinValue) / (MaxValue - MinValue)); + + var offset = Math.Max(logarithmicScaleOffset, MathUtils.EPSILON); + var shiftedValue = value - (float)MinValue; + var shiftedMaximum = (float)(MaxValue - MinValue); + + return Math.Clamp((float)(Math.Log((shiftedValue + offset) / offset) / + Math.Log((shiftedMaximum + offset) / offset)), 0, 1); + } + private void SetBoundPositionsInternal() { if (hasTwoBounds) diff --git a/src/microbe_stage/editor/TolerancesEditorSubComponent.cs b/src/microbe_stage/editor/TolerancesEditorSubComponent.cs index 25acdd0ccc4..528163896b8 100644 --- a/src/microbe_stage/editor/TolerancesEditorSubComponent.cs +++ b/src/microbe_stage/editor/TolerancesEditorSubComponent.cs @@ -16,6 +16,9 @@ public partial class TolerancesEditorSubComponent : EditorComponentBase tempToleranceModifiers = new(); private CompoundDefinition temperature = null!; @@ -300,7 +303,9 @@ public void UpdateMPCostInToolTips() if (pressureToolTip != null) { - var pressureCost = pressureSlider.Step * Constants.TOLERANCE_CHANGE_MP_PER_PRESSURE_MINIMUM * + var pressureCost = EstimatePressureChangeFromSliderStep(pressureSlider, 0, + Constants.TOLERANCE_PRESSURE_MAX, PressureSliderLogOffset) * + Constants.TOLERANCE_CHANGE_MP_PER_PRESSURE_MINIMUM * MPDisplayCostMultiplier; pressureToolTip.MPCost = (float)pressureCost; @@ -456,6 +461,37 @@ protected override void RegisterTooltips() } } + private static float ActualPressureToSliderValue(float pressure, float maximum, float offset, float minimum = 0) + { + pressure = Math.Clamp(pressure, minimum, maximum); + + return Math.Clamp((float)(Math.Log((pressure - minimum + offset) / offset) / + Math.Log((maximum - minimum + offset) / offset)), 0, 1); + } + + private static float SliderValueToActualPressure(float sliderValue, float maximum, float offset, float minimum = 0) + { + sliderValue = Math.Clamp(sliderValue, 0, 1); + + return (float)(minimum + offset * (Math.Pow((maximum - minimum + offset) / offset, sliderValue) - 1)); + } + + private static float RoundPressureForEditing(float pressure) + { + return MathF.Round(pressure / PressureEditorRounding) * PressureEditorRounding; + } + + private static double EstimatePressureChangeFromSliderStep(Slider slider, float minimum, float maximum, + float offset) + { + var previous = SliderValueToActualPressure((float)Math.Max(slider.Value - slider.Step, slider.MinValue), + maximum, offset, minimum); + var next = SliderValueToActualPressure((float)Math.Min(slider.Value + slider.Step, slider.MaxValue), + maximum, offset, minimum); + + return Math.Max(Math.Abs(next - previous) * 0.5f, PressureEditorRounding); + } + private void CalculateStatsAndShow(EnvironmentalTolerances calculationTolerances, EnvironmentalToleranceToolTip toolTip) { @@ -514,7 +550,8 @@ private void ApplyCurrentValuesToGUI() temperatureSlider.Value = CurrentTolerances.PreferredTemperature; temperatureToleranceRangeSlider.Value = CurrentTolerances.TemperatureTolerance; - pressureSlider.Value = CurrentTolerances.PressureMinimum; + pressureSlider.Value = ActualPressureToSliderValue(CurrentTolerances.PressureMinimum, + Constants.TOLERANCE_PRESSURE_MAX, PressureSliderLogOffset); pressureToleranceRangeSlider.Value = CurrentTolerances.PressureTolerance; oxygenResistanceSlider.Value = CurrentTolerances.OxygenResistance; @@ -594,13 +631,15 @@ private void OnPressureSliderChanged(float value) reusableTolerances ??= new EnvironmentalTolerances(); reusableTolerances.CopyFrom(CurrentTolerances); - reusableTolerances.PressureMinimum = value; + reusableTolerances.PressureMinimum = RoundPressureForEditing( + SliderValueToActualPressure(value, Constants.TOLERANCE_PRESSURE_MAX, PressureSliderLogOffset)); automaticallyChanging = true; if (!TriggerChangeIfPossible()) { - pressureSlider.Value = CurrentTolerances.PressureMinimum; + pressureSlider.Value = ActualPressureToSliderValue(CurrentTolerances.PressureMinimum, + Constants.TOLERANCE_PRESSURE_MAX, PressureSliderLogOffset); } automaticallyChanging = false; diff --git a/src/microbe_stage/editor/TolerancesEditorSubComponent.tscn b/src/microbe_stage/editor/TolerancesEditorSubComponent.tscn index 98b40b4ab46..63f1c751e2a 100644 --- a/src/microbe_stage/editor/TolerancesEditorSubComponent.tscn +++ b/src/microbe_stage/editor/TolerancesEditorSubComponent.tscn @@ -316,6 +316,8 @@ size_flags_horizontal = 3 max_value = 80000000.0 value = 0.0 hasTwoBounds = true +logarithmicScale = true +logarithmicScaleOffset = 100000.0 relatedSlider = NodePath("../PressureSlider") [node name="PressureSlider" type="HSlider" parent="Pressure/RangeDisplayContainer/VBoxContainer" unique_id=691339473] @@ -327,9 +329,9 @@ focus_next = NodePath("../../../HBoxContainer4/PressureRange") focus_previous = NodePath("../../../../Temperature/HBoxContainer3/TemperatureRange") theme_override_constants/center_grabber = 1 theme_override_styles/slider = SubResource("StyleBoxEmpty_n6u17") -max_value = 80000000.0 -step = 200000.0 -value = 40000000.0 +max_value = 1.0 +step = 0.005 +value = 0.5 [node name="Spacer2" type="Control" parent="Pressure/RangeDisplayContainer" unique_id=1570659681] custom_minimum_size = Vector2(8, 0)