#if ENABLE_UIELEMENTS_MODULE && UNITY_ENABLE_CHECKS #define ENABLE_RENDERING_DEBUGGER_UI #endif using System; #if ENABLE_RENDERING_DEBUGGER_UI using UnityEngine.UIElements; namespace UnityEngine.Rendering { public partial class DebugUI { // Helper for configuring Field that is implemented using a UIElements.BaseField internal static class BaseFieldHelper { internal static void ConfigureBaseField(Field widget, UIElements.BaseField field) { field.label = widget.displayName; field.style.flexGrow = 0f; field.AddToClassList($"debug-window-basefield_{typeof(T).Name.ToLower()}"); field.labelElement.AddToClassList("debug-window-search-filter-target"); field.RegisterCallback>(evt => widget.SetValue(evt.newValue)); widget.ScheduleTracked(field, () => field.schedule.Execute(() => { field.SetValueWithoutNotify((T)Convert.ChangeType(widget.GetValue(), typeof(T))); }).Every(100)); field.AddToClassList(UIElements.BaseField.alignedFieldUssClassName); } } // Helper for adding numeric fields increment/decrement buttons for Runtime UI internal static class DebugUIStepperHelper { public static void AddStepper( UIElements.TextInputBaseField field, Action onValueChanged, Func getValue, Action onDecrement = null, Action onIncrement = null) where T : struct { // Create stepper buttons var btnDecLarge = new UIElements.Button { text = "<<", focusable = false }; var btnDecSmall = new UIElements.Button { text = "<", focusable = false }; var btnIncSmall = new UIElements.Button { text = ">", focusable = false }; // Need to remove marginRight of latest button to perfectly align with the other fields var btnIncLarge = new UIElements.Button { text = ">>", focusable = false, style = { marginRight = 0 } }; // Add button event handlers btnDecLarge.clicked += () => { if (onDecrement == null) return; T validatedValue; onDecrement(true); validatedValue = getValue(); field.SetValueWithoutNotify(validatedValue); }; btnDecSmall.clicked += () => { if (onDecrement == null) return; T validatedValue; onDecrement(false); validatedValue = getValue(); field.SetValueWithoutNotify(validatedValue); }; btnIncSmall.clicked += () => { if (onIncrement == null) return; T validatedValue; onIncrement(false); validatedValue = getValue(); field.SetValueWithoutNotify(validatedValue); }; btnIncLarge.clicked += () => { if (onIncrement == null) return; T validatedValue; onIncrement(true); validatedValue = getValue(); field.SetValueWithoutNotify(validatedValue); }; // Make field read-only for stepper control, disable select text field.isReadOnly = true; // Disable test selection to better readability field.selectAllOnFocus = false; field.doubleClickSelectsWord = false; field.tripleClickSelectsLine = false; // Insert buttons into field field.Insert(0, btnDecLarge); field.Insert(1, btnDecSmall); field.Add(btnIncSmall); field.Add(btnIncLarge); field.AddToClassList("debug-window-stepper-field"); // Style the buttons foreach (var btn in new[] { btnDecLarge, btnDecSmall, btnIncSmall, btnIncLarge }) { btn.AddToClassList("debug-window-stepper-button"); } } static int CountDecimalPlaces(float value) { value = Mathf.Abs(value); if (value == 0f || float.IsNaN(value) || float.IsInfinity(value)) return 0; int decimals = 0; const int kMaxDecimalPlaces = 7; const float kEpsilon = 1e-4f; // Multiply the original value by 10 until we reach an integer value float multipliedValue = value; while (decimals < kMaxDecimalPlaces) { float nearestInteger = Mathf.Round(multipliedValue); if (Mathf.Abs(multipliedValue - nearestInteger) <= kEpsilon) break; multipliedValue *= 10f; decimals++; } return decimals; } // Rounds 'value' to the maximum decimal precision found in 'referenceValues' internal static float RoundToPrecision(float value, params float[] referenceValues) { int decimalPlaces = 0; foreach (float refValue in referenceValues) { decimalPlaces = Math.Max(decimalPlaces, CountDecimalPlaces(refValue)); } double rounded = Math.Round(value, decimalPlaces, MidpointRounding.AwayFromZero); return (float)rounded; } } } } #endif