Add UIComponentWrapper

This commit is contained in:
copecone committed 2026-10-22 11:46:42 +09:00
1 parent 4179ed6696
commit 7eaf4f48e6
3 files changed
+117 -144

No files matched your search

+1 -1
View File
@@ -8,7 +8,7 @@
<EnableSourceControlManagerQueries>false</EnableSourceControlManagerQueries> <EnableSourceControlManagerQueries>false</EnableSourceControlManagerQueries>
<AllowUnsafeBlocks>true</AllowUnsafeBlocks> <AllowUnsafeBlocks>true</AllowUnsafeBlocks>
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies> <CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
<LangVersion>11</LangVersion> <LangVersion>12</LangVersion>
<PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression> <PackageLicenseExpression>GPL-3.0-or-later</PackageLicenseExpression>
</PropertyGroup> </PropertyGroup>
+74 -143
View File
@@ -8,6 +8,7 @@ using ADOFAIRenderer.Core.Data;
using ADOFAIRenderer.Data; using ADOFAIRenderer.Data;
using ADOFAIRenderer.Localization; using ADOFAIRenderer.Localization;
using ADOFAIRenderer.Util.OS; using ADOFAIRenderer.Util.OS;
using ADOFAIRenderer.Util.UI;
using MelonLoader; using MelonLoader;
using Newtonsoft.Json; using Newtonsoft.Json;
using O5Kit.Control; using O5Kit.Control;
@@ -62,7 +63,7 @@ internal static class RenderConfigWindow
// Presets controls // Presets controls
/// <summary>Preset selector: preset names, plus the Custom label at index 0 while the values differ from the preset.</summary> /// <summary>Preset selector: preset names, plus the Custom label at index 0 while the values differ from the preset.</summary>
private static O5Dropdown<string>? _presetDropdown; private static O5DropdownWrapper<string>? _presetDropdown;
/// <summary>Name used by the Save button; set to the selected preset's name when a preset is loaded.</summary> /// <summary>Name used by the Save button; set to the selected preset's name when a preset is loaded.</summary>
private static O5InputField? _presetNameInput; private static O5InputField? _presetNameInput;
/// <summary>Saves the current values under the name in <see cref="_presetNameInput"/>.</summary> /// <summary>Saves the current values under the name in <see cref="_presetNameInput"/>.</summary>
@@ -105,39 +106,22 @@ internal static class RenderConfigWindow
private static O5Slider? _renderWidthSlider; private static O5Slider? _renderWidthSlider;
private static O5Slider? _renderHeightSlider; private static O5Slider? _renderHeightSlider;
private static O5Slider? _delayAfterEndSlider; private static O5Slider? _delayAfterEndSlider;
private static O5Toggle? _showJudgementToggle; private static O5ToggleWrapper? _showJudgementToggle;
private static SegmentedControl<RenderConfig.RenderOutputMode>? _outputModeControl; private static SegmentedControl<RenderConfig.RenderOutputMode>? _outputModeControl;
private static O5Dropdown<Codec>? _codecDropdown; private static O5DropdownWrapper<Codec>? _codecDropdown;
private static TextMeshProUGUI? _codecLabel; private static O5DropdownWrapper<RateControlMode>? _rateControlDropdown;
private static ITweenHandle? _codecLabelTween;
private static O5Dropdown<RateControlMode>? _rateControlDropdown; private static O5InputFieldWrapper? _bitrateInput;
private static TextMeshProUGUI? _rateControlLabel; private static O5InputFieldWrapper? _maxBitrateInput;
private static ITweenHandle? _rateControlLabelTween; private static O5InputFieldWrapper? _qpInput;
// Bitrate / max bitrate / QP inputs keep their label and the running label color tween, so UpdateRateControlUI
// can dim the label together with the blocked input (see SetFieldBlocked).
private static O5InputField? _bitrateInput;
private static TextMeshProUGUI? _bitrateLabel;
private static ITweenHandle? _bitrateLabelTween;
private static O5InputField? _maxBitrateInput;
private static TextMeshProUGUI? _maxBitrateLabel;
private static ITweenHandle? _maxBitrateLabelTween;
private static O5InputField? _qpInput;
private static TextMeshProUGUI? _qpLabel;
private static ITweenHandle? _qpLabelTween;
private static O5Toggle? _forceSoftwareToggle;
private static TextMeshProUGUI? _forceSoftwareLabel;
private static ITweenHandle? _forceSoftwareLabelTween;
private static O5ToggleWrapper? _forceSoftwareToggle;
private static O5Slider? _keyframeIntervalSlider; private static O5Slider? _keyframeIntervalSlider;
private static O5Toggle? _renderAudioToggle; private static O5ToggleWrapper? _renderAudioToggle;
private static O5Dropdown<int>? _sampleRateDropdown; private static O5DropdownWrapper<int>? _sampleRateDropdown;
private static O5Dropdown<int>? _channelsDropdown; private static O5DropdownWrapper<int>? _channelsDropdown;
private static O5Slider? _audioBitrateSlider; private static O5Slider? _audioBitrateSlider;
/// <summary> /// <summary>
@@ -150,22 +134,22 @@ internal static class RenderConfigWindow
/// </summary> /// </summary>
private static O5InputField? _fileNameFormatInput; private static O5InputField? _fileNameFormatInput;
private static O5Dropdown<string>? _fileExtensionDropdown; private static O5DropdownWrapper<string>? _fileExtensionDropdown;
private static O5InputField? _randomSeedInput; private static O5InputFieldWrapper? _randomSeedInput;
private static O5Toggle? _processAudioToggle; private static O5ToggleWrapper? _processAudioToggle;
private static O5Toggle? _nonTileToggle; private static O5ToggleWrapper? _nonTileToggle;
private static O5Toggle? _highResBloomCorrectionToggle; private static O5ToggleWrapper? _highResBloomCorrectionToggle;
private static O5Toggle? _fixCustomFrameRateToggle; private static O5ToggleWrapper? _fixCustomFrameRateToggle;
private static O5Toggle? _disableTileCullingToggle; private static O5ToggleWrapper? _disableTileCullingToggle;
private static O5Toggle? _hideFailedDecorationsToggle; private static O5ToggleWrapper? _hideFailedDecorationsToggle;
// Planet color overrides: the toggle enables the override, the picker holds the color. A disabled toggle stores // Planet color overrides: the toggle enables the override, the picker holds the color. A disabled toggle stores
// null in AdvancedConfig (no override is applied by PersistencePatch) and blocks the picker. // null in AdvancedConfig (no override is applied by PersistencePatch) and blocks the picker.
private static O5Toggle? _firePlanetToggle; private static O5ToggleWrapper? _firePlanetToggle;
private static O5ColorPicker? _firePlanetPicker; private static O5ColorPicker? _firePlanetPicker;
private static O5Toggle? _icePlanetToggle; private static O5ToggleWrapper? _icePlanetToggle;
private static O5ColorPicker? _icePlanetPicker; private static O5ColorPicker? _icePlanetPicker;
private static O5Toggle? _windPlanetToggle; private static O5ToggleWrapper? _windPlanetToggle;
private static O5ColorPicker? _windPlanetPicker; private static O5ColorPicker? _windPlanetPicker;
// Colors shown in a planet picker when its override is off (and its middle-click default value) // Colors shown in a planet picker when its override is off (and its middle-click default value)
@@ -257,30 +241,31 @@ internal static class RenderConfigWindow
// Render FPS: standard video rates, then multiples of 120 and of 288 up to the 3000 maximum. // Render FPS: standard video rates, then multiples of 120 and of 288 up to the 3000 maximum.
// Video FPS: standard video rates, then multiples of 60 and of 72 up to the 600 maximum. // Video FPS: standard video rates, then multiples of 60 and of 72 up to the 600 maximum.
// Audio bitrate: kbps values. Width/height: common resolutions grouped by aspect ratio. // Audio bitrate: kbps values. Width/height: common resolutions grouped by aspect ratio.
double[] renderFpsSnap = { 23.976, 24, 29.97, 30, 59.94, 60, 144, double[] renderFpsSnap = [ 23.976, 24, 29.97, 30, 59.94, 60, 144,
120, 240, 360, 480, 600, 720, // +120 120, 240, 360, 480, 600, 720, // +120
288, 576, 864, 1152, 1440, 1728, // +288 288, 576, 864, 1152, 1440, 1728, // +288
3000 // MAX 3000 // MAX
}; ];
double[] videoFpsSnap = { 23.976, 24, 29.97, 30, 59.94, 60, 72,
double[] videoFpsSnap = [ 23.976, 24, 29.97, 30, 59.94, 60, 72,
120, 180, 240, 300, 360, 420, 480, 540, // +60 120, 180, 240, 300, 360, 420, 480, 540, // +60
144, 216, 288, 432, 504, 576, // +72 144, 216, 288, 432, 504, 576, // +72
600 // MAX 600 // MAX
}; ];
double[] audioBitrateSnap = { 64, 96, 128, 192, 256, 320, 384 }; double[] audioBitrateSnap = [64, 96, 128, 192, 256, 320, 384];
double[] renderWidthSnap = { double[] renderWidthSnap = [
256, 426, 640, 854, 960, 1280, 1366, 1600, 1920, 2048, 2560, 3200, 3840, 4096, 5120, 5760, 6016, 7680, 10240, 15360, // 16:9 256, 426, 640, 854, 960, 1280, 1366, 1600, 1920, 2048, 2560, 3200, 3840, 4096, 5120, 5760, 6016, 7680, 10240, 15360, // 16:9
230, 384, 576, 768, 1152, 1440, 1680, 2880, 3072, // 16:10 230, 384, 576, 768, 1152, 1440, 1680, 2880, 3072, // 16:10
192, 320, 480, 800, 1024, 1400, 2732, 6400, 11520 // 4:3 192, 320, 480, 800, 1024, 1400, 2732, 6400, 11520 // 4:3
}; ];
double[] renderHeightSnap = { double[] renderHeightSnap = [
144, 240, 360, 480, 540, 720, 768, 900, 1080, 1152, 1440, 1800, 2160, 2304, 2880, 3240, 3384, 4320, 5760, 8640, // 16:9 144, 240, 360, 480, 540, 720, 768, 900, 1080, 1152, 1440, 1800, 2160, 2304, 2880, 3240, 3384, 4320, 5760, 8640, // 16:9
400, 600, 800, 1050, 1200, 1600, 1920, 2400, 3200, 4800, 9600, // 16:10 400, 600, 800, 1050, 1200, 1600, 1920, 2400, 3200, 4800, 9600, // 16:10
864, 960, 1536, 2048, 3072 // 4:3 864, 960, 1536, 2048, 3072 // 4:3
}; ];
// --------------------------------------------------------------------------------------------- // ---------------------------------------------------------------------------------------------
// Section 1: Presets card - preset dropdown, then a row with name input, Save and Delete buttons // Section 1: Presets card - preset dropdown, then a row with name input, Save and Delete buttons
@@ -474,7 +459,7 @@ internal static class RenderConfigWindow
ctx: ctx, parent: CreateFieldSlot(topLeft), ctx: ctx, parent: CreateFieldSlot(topLeft),
labelKey: "ui.render_config.delay_after_end", id: "slider_delay_after_end", labelKey: "ui.render_config.delay_after_end", id: "slider_delay_after_end",
defaultValue: 15, min: 0, max: 9999.999, value: 15, defaultValue: 15, min: 0, max: 9999.999, value: 15,
format: "F3", clampMode: ClampMode.All, format: "F3", clampMode: ClampMode.Slider,
onChanged: val => { config.DelayAfterEnd = val; MarkConfigModified(); } onChanged: val => { config.DelayAfterEnd = val; MarkConfigModified(); }
); );
@@ -497,11 +482,11 @@ internal static class RenderConfigWindow
labelKey: "ui.render_config.output_mode", labelKey: "ui.render_config.output_mode",
defaultValue: RenderConfig.RenderOutputMode.Video, defaultValue: RenderConfig.RenderOutputMode.Video,
value: config.OutputMode, value: config.OutputMode,
options: new SegmentOption<RenderConfig.RenderOutputMode>[] options:
{ [
new(RenderConfig.RenderOutputMode.Video, "ui.render_config.output_mode_video"), new SegmentOption<RenderConfig.RenderOutputMode>(RenderConfig.RenderOutputMode.Video, "ui.render_config.output_mode_video"),
new(RenderConfig.RenderOutputMode.PNGSequence, "ui.render_config.output_mode_png_sequence") new SegmentOption<RenderConfig.RenderOutputMode>(RenderConfig.RenderOutputMode.PNGSequence, "ui.render_config.output_mode_png_sequence")
}, ],
id: "seg_output_mode", id: "seg_output_mode",
onChanged: val => onChanged: val =>
{ {
@@ -535,7 +520,7 @@ internal static class RenderConfigWindow
"ui.render_config.codec", "ui.render_config.codec",
Codec.H264, config.VideoConfig.Codec, Codec.H264, config.VideoConfig.Codec,
codecs, c => c.ToString(), codecs, c => c.ToString(),
"dd_video_codec", out _codecLabel, "dd_video_codec",
c => c =>
{ {
config.VideoConfig.Codec = c; config.VideoConfig.Codec = c;
@@ -549,7 +534,7 @@ internal static class RenderConfigWindow
ctx, CreateFieldSlot(videoLeft), ctx, CreateFieldSlot(videoLeft),
"ui.render_config.bitrate", "ui.render_config.bitrate",
"30000", config.VideoConfig.Bitrate.ToString(), "30000", config.VideoConfig.Bitrate.ToString(),
"input_bitrate", out _bitrateLabel, "input_bitrate",
TMP_InputField.CharacterValidation.Integer, TMP_InputField.CharacterValidation.Integer,
val => { if (int.TryParse(val, out var b) && b > 0) config.VideoConfig.Bitrate = b; MarkConfigModified(); } val => { if (int.TryParse(val, out var b) && b > 0) config.VideoConfig.Bitrate = b; MarkConfigModified(); }
); );
@@ -558,7 +543,7 @@ internal static class RenderConfigWindow
ctx, CreateFieldSlot(videoLeft), ctx, CreateFieldSlot(videoLeft),
"ui.render_config.qp", "ui.render_config.qp",
"18", config.VideoConfig.QP.ToString(), "18", config.VideoConfig.QP.ToString(),
"input_qp", out _qpLabel, "input_qp",
TMP_InputField.CharacterValidation.Integer, TMP_InputField.CharacterValidation.Integer,
val => { if (int.TryParse(val, out var qp) && qp >= 0) config.VideoConfig.QP = qp; MarkConfigModified(); } val => { if (int.TryParse(val, out var qp) && qp >= 0) config.VideoConfig.QP = qp; MarkConfigModified(); }
); );
@@ -569,7 +554,7 @@ internal static class RenderConfigWindow
"ui.render_config.rate_control", "ui.render_config.rate_control",
RateControlMode.CBR, config.VideoConfig.RateControlMode, RateControlMode.CBR, config.VideoConfig.RateControlMode,
rateModes, m => m.ToString(), rateModes, m => m.ToString(),
"dd_rate_control", out _rateControlLabel, "dd_rate_control",
m => m =>
{ {
config.VideoConfig.RateControlMode = m; config.VideoConfig.RateControlMode = m;
@@ -582,7 +567,7 @@ internal static class RenderConfigWindow
ctx, CreateFieldSlot(videoRight), ctx, CreateFieldSlot(videoRight),
"ui.render_config.max_bitrate", "ui.render_config.max_bitrate",
"50000", config.VideoConfig.MaxBitrate.ToString(), "50000", config.VideoConfig.MaxBitrate.ToString(),
"input_max_bitrate", out _maxBitrateLabel, "input_max_bitrate",
TMP_InputField.CharacterValidation.Integer, TMP_InputField.CharacterValidation.Integer,
val => { if (int.TryParse(val, out var mb) && mb > 0) config.VideoConfig.MaxBitrate = mb; MarkConfigModified(); } val => { if (int.TryParse(val, out var mb) && mb > 0) config.VideoConfig.MaxBitrate = mb; MarkConfigModified(); }
); );
@@ -593,7 +578,7 @@ internal static class RenderConfigWindow
defaultValue: false, defaultValue: false,
value: config.VideoConfig.ForceSoftwareEncoder, value: config.VideoConfig.ForceSoftwareEncoder,
toggleTextKey: "ui.render_config.force_software", toggleTextKey: "ui.render_config.force_software",
id: "toggle_force_software", out _forceSoftwareLabel, id: "toggle_force_software",
onChanged: val => { config.VideoConfig.ForceSoftwareEncoder = val; MarkConfigModified(); }, onChanged: val => { config.VideoConfig.ForceSoftwareEncoder = val; MarkConfigModified(); },
generateLabel: true generateLabel: true
); );
@@ -1108,7 +1093,7 @@ internal static class RenderConfigWindow
_codecDropdown?.Set(config.VideoConfig.Codec, false); _codecDropdown?.Set(config.VideoConfig.Codec, false);
_rateControlDropdown?.Set(config.VideoConfig.RateControlMode, false); _rateControlDropdown?.Set(config.VideoConfig.RateControlMode, false);
_bitrateInput?.Set(config.VideoConfig.Bitrate.ToString(), false); _bitrateInput?.component.Set(config.VideoConfig.Bitrate.ToString(), false);
_maxBitrateInput?.Set(config.VideoConfig.MaxBitrate.ToString(), false); _maxBitrateInput?.Set(config.VideoConfig.MaxBitrate.ToString(), false);
_qpInput?.Set(config.VideoConfig.QP.ToString(), false); _qpInput?.Set(config.VideoConfig.QP.ToString(), false);
_keyframeIntervalSlider?.Set(config.VideoConfig.KeyframeInterval, false, noFilter: true); _keyframeIntervalSlider?.Set(config.VideoConfig.KeyframeInterval, false, noFilter: true);
@@ -1985,20 +1970,6 @@ internal static class RenderConfigWindow
return button; return button;
} }
/// <summary>Same as the CreateInputField overload with an <c>out</c> label parameter, without returning the label.</summary>
private static O5InputField CreateInputField(
O5Context ctx,
Transform colParent,
string labelKey,
string? defaultValue,
string value,
string id,
TMP_InputField.CharacterValidation characterValidation = TMP_InputField.CharacterValidation.None,
Action<string>? onChanged = null)
{
return CreateInputField(ctx, colParent, labelKey, defaultValue, value, id, out _, characterValidation, onChanged);
}
/// <summary> /// <summary>
/// Creates a labeled text input in <paramref name="colParent"/> (normally a field slot): an 18-unit label row and an /// Creates a labeled text input in <paramref name="colParent"/> (normally a field slot): an 18-unit label row and an
/// O5Kit input below it. The label and the placeholder are both bound to <paramref name="labelKey"/>. /// O5Kit input below it. The label and the placeholder are both bound to <paramref name="labelKey"/>.
@@ -2009,24 +1980,22 @@ internal static class RenderConfigWindow
/// <param name="defaultValue">Value restored by middle click; <c>null</c> for none.</param> /// <param name="defaultValue">Value restored by middle click; <c>null</c> for none.</param>
/// <param name="value">Initial text.</param> /// <param name="value">Initial text.</param>
/// <param name="id">O5Kit control id.</param> /// <param name="id">O5Kit control id.</param>
/// <param name="label">Receives the label text component (used to dim the label of a blocked field).</param>
/// <param name="characterValidation">TextMeshPro character filter for typed text, e.g. Integer.</param> /// <param name="characterValidation">TextMeshPro character filter for typed text, e.g. Integer.</param>
/// <param name="onChanged">Called with the raw text on every change; parsing and validation are up to the caller.</param> /// <param name="onChanged">Called with the raw text on every change; parsing and validation are up to the caller.</param>
/// <returns>The input field.</returns> /// <returns>The input field.</returns>
private static O5InputField CreateInputField( private static O5InputFieldWrapper CreateInputField(
O5Context ctx, O5Context ctx,
Transform colParent, Transform colParent,
string labelKey, string labelKey,
string? defaultValue, string? defaultValue,
string value, string value,
string id, string id,
out TextMeshProUGUI label,
TMP_InputField.CharacterValidation characterValidation = TMP_InputField.CharacterValidation.None, TMP_InputField.CharacterValidation characterValidation = TMP_InputField.CharacterValidation.None,
Action<string>? onChanged = null) Action<string>? onChanged = null)
{ {
// Labeled text input: an 18-unit label row (13 pt, dim) above an O5Kit input. The label key also serves as the // Labeled text input: an 18-unit label row (13 pt, dim) above an O5Kit input. The label key also serves as the
// placeholder. characterValidation restricts typed characters (e.g. Integer). onChanged receives the raw text. // placeholder. characterValidation restricts typed characters (e.g. Integer). onChanged receives the raw text.
label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true); var label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true);
label.text = LocalizationManager.Get(labelKey); label.text = LocalizationManager.Get(labelKey);
label.color = ctx.Theme.TextDim; label.color = ctx.Theme.TextDim;
LocalizedText.Bind(label, labelKey); LocalizedText.Bind(label, labelKey);
@@ -2053,7 +2022,7 @@ internal static class RenderConfigWindow
} }
inputField.InputField.characterValidation = characterValidation; inputField.InputField.characterValidation = characterValidation;
return inputField; return new O5InputFieldWrapper(inputField, label);
} }
// =================================================================================================== // ===================================================================================================
@@ -2061,42 +2030,36 @@ internal static class RenderConfigWindow
// =================================================================================================== // ===================================================================================================
private static void SetFieldBlocked( private static void SetFieldBlocked(
O5InputField? input, O5InputFieldWrapper? input,
TextMeshProUGUI? label,
ref ITweenHandle? tweenHandle,
bool blocked, bool blocked,
bool noAnimate = false) bool noAnimate = false)
{ {
input?.SetBlocked(blocked, noAnimate); input?.component.SetBlocked(blocked, noAnimate);
if (label == null) return; if (input?.label == null) return;
UpdateLabelDim(label, ref tweenHandle, blocked, noAnimate); UpdateLabelDim(input.label, ref input.tween, blocked, noAnimate);
} }
private static void SetToggleBlocked( private static void SetToggleBlocked(
O5Toggle? toggle, O5ToggleWrapper? toggle,
TextMeshProUGUI? label,
ref ITweenHandle? tweenHandle,
bool blocked, bool blocked,
bool noAnimate = false) bool noAnimate = false)
{ {
toggle?.SetBlocked(blocked, noAnimate); toggle?.component.SetBlocked(blocked, noAnimate);
if (label == null) return; if (toggle?.label == null) return;
UpdateLabelDim(label, ref tweenHandle, blocked, noAnimate); UpdateLabelDim(toggle.label, ref toggle.tween, blocked, noAnimate);
} }
private static void SetDropdownBlocked<T>( private static void SetDropdownBlocked<T>(
O5Dropdown<T>? dropdown, O5DropdownWrapper<T>? dropdown,
TextMeshProUGUI? label,
ref ITweenHandle? tweenHandle,
bool blocked, bool blocked,
bool noAnimate = false) bool noAnimate = false)
{ {
dropdown?.SetBlocked(blocked, noAnimate); dropdown?.component.SetBlocked(blocked, noAnimate);
if (label == null) return; if (dropdown?.label == null) return;
UpdateLabelDim(label, ref tweenHandle, blocked, noAnimate); UpdateLabelDim(dropdown.label, ref dropdown.tween, blocked, noAnimate);
} }
private static void UpdateLabelDim(TextMeshProUGUI label, ref ITweenHandle? tweenHandle, bool blocked, bool noAnimate = false) private static void UpdateLabelDim(TextMeshProUGUI label, ref ITweenHandle? tweenHandle, bool blocked, bool noAnimate = false)
@@ -2149,12 +2112,12 @@ internal static class RenderConfigWindow
blockForceSoftwareToggle |= blockVideoEncodingSettings; blockForceSoftwareToggle |= blockVideoEncodingSettings;
blockKeyframeIntervalSlider |= blockVideoEncodingSettings; blockKeyframeIntervalSlider |= blockVideoEncodingSettings;
SetDropdownBlocked(_codecDropdown, _codecLabel, ref _codecLabelTween, blockCodecDropdown, noAnimate); SetDropdownBlocked(_codecDropdown, blockCodecDropdown, noAnimate);
SetDropdownBlocked(_rateControlDropdown, _rateControlLabel, ref _rateControlLabelTween, blockRateControlModeDropdown, noAnimate); SetDropdownBlocked(_rateControlDropdown, blockRateControlModeDropdown, noAnimate);
SetFieldBlocked(_bitrateInput, _bitrateLabel, ref _bitrateLabelTween, blockBitrateInput, noAnimate); SetFieldBlocked(_bitrateInput, blockBitrateInput, noAnimate);
SetFieldBlocked(_maxBitrateInput, _maxBitrateLabel, ref _maxBitrateLabelTween, blockMaxBitrateInput, noAnimate); SetFieldBlocked(_maxBitrateInput, blockMaxBitrateInput, noAnimate);
SetFieldBlocked(_qpInput, _qpLabel, ref _qpLabelTween, blockQPInput, noAnimate); SetFieldBlocked(_qpInput, blockQPInput, noAnimate);
SetToggleBlocked(_forceSoftwareToggle, _forceSoftwareLabel, ref _forceSoftwareLabelTween, blockForceSoftwareToggle, noAnimate); SetToggleBlocked(_forceSoftwareToggle, blockForceSoftwareToggle, noAnimate);
_keyframeIntervalSlider?.SetBlocked(blockKeyframeIntervalSlider, noAnimate); _keyframeIntervalSlider?.SetBlocked(blockKeyframeIntervalSlider, noAnimate);
} }
@@ -2214,28 +2177,13 @@ internal static class RenderConfigWindow
return input; return input;
} }
/// <summary>Same as the CreateToggleField overload with an <c>out</c> label parameter, without returning the label.</summary>
private static O5Toggle CreateToggleField(
O5Context ctx,
Transform colParent,
string labelKey,
bool? defaultValue,
bool value,
string toggleTextKey,
string id,
Action<bool>? onChanged = null,
bool generateLabel = true)
{
return CreateToggleField(ctx, colParent, labelKey, defaultValue, value, toggleTextKey, id, out _, onChanged, generateLabel);
}
/// <summary> /// <summary>
/// Creates an O5Kit toggle whose text is localized with <paramref name="toggleTextKey"/>. With /// Creates an O5Kit toggle whose text is localized with <paramref name="toggleTextKey"/>. With
/// <paramref name="generateLabel"/> an 18-unit label row is added above it (text from <paramref name="labelKey"/>, /// <paramref name="generateLabel"/> an 18-unit label row is added above it (text from <paramref name="labelKey"/>,
/// empty when the key is empty), which keeps the toggle aligned with labeled fields in the neighboring column. /// empty when the key is empty), which keeps the toggle aligned with labeled fields in the neighboring column.
/// </summary> /// </summary>
private static O5Toggle CreateToggleField( private static O5ToggleWrapper CreateToggleField(
O5Context ctx, O5Context ctx,
Transform colParent, Transform colParent,
string labelKey, string labelKey,
@@ -2243,11 +2191,10 @@ internal static class RenderConfigWindow
bool value, bool value,
string toggleTextKey, string toggleTextKey,
string id, string id,
out TextMeshProUGUI? label,
Action<bool>? onChanged = null, Action<bool>? onChanged = null,
bool generateLabel = true) bool generateLabel = true)
{ {
label = null; TextMeshProUGUI? label = null;
if (generateLabel) if (generateLabel)
{ {
label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true); label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true);
@@ -2276,22 +2223,7 @@ internal static class RenderConfigWindow
LocalizedText.Bind(toggle.Label, toggleTextKey); LocalizedText.Bind(toggle.Label, toggleTextKey);
} }
return toggle; return new O5ToggleWrapper(toggle, label);
}
/// <summary>Same as the CreateDropdownField overload with an <c>out</c> label parameter, without returning the label.</summary>
private static O5Dropdown<T> CreateDropdownField<T>(
O5Context ctx,
Transform colParent,
string labelKey,
T defaultValue,
T value,
IReadOnlyList<T> values,
Func<T, string> display,
string id,
Action<T>? onChanged = null)
{
return CreateDropdownField(ctx, colParent, labelKey, defaultValue, value, values, display, id, out _, onChanged);
} }
/// <summary> /// <summary>
@@ -2299,7 +2231,7 @@ internal static class RenderConfigWindow
/// dropdown. <paramref name="display"/> converts values to their shown text. The change callback is not invoked for /// dropdown. <paramref name="display"/> converts values to their shown text. The change callback is not invoked for
/// a null value. /// a null value.
/// </summary> /// </summary>
private static O5Dropdown<T> CreateDropdownField<T>( private static O5DropdownWrapper<T> CreateDropdownField<T>(
O5Context ctx, O5Context ctx,
Transform colParent, Transform colParent,
string labelKey, string labelKey,
@@ -2308,10 +2240,9 @@ internal static class RenderConfigWindow
IReadOnlyList<T> values, IReadOnlyList<T> values,
Func<T, string> display, Func<T, string> display,
string id, string id,
out TextMeshProUGUI label,
Action<T>? onChanged = null) Action<T>? onChanged = null)
{ {
label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true); var label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true);
label.text = LocalizationManager.Get(labelKey); label.text = LocalizationManager.Get(labelKey);
label.color = ctx.Theme.TextDim; label.color = ctx.Theme.TextDim;
LocalizedText.Bind(label, labelKey); LocalizedText.Bind(label, labelKey);
@@ -2329,7 +2260,7 @@ internal static class RenderConfigWindow
ddLE.preferredHeight = 50f; ddLE.preferredHeight = 50f;
ddLE.minHeight = 0f; ddLE.minHeight = 0f;
return O5Factory.DropDown( return new O5DropdownWrapper<T>(O5Factory.DropDown(
ctx: ctx, ctx: ctx,
parent: ddContainer.transform, parent: ddContainer.transform,
defaultValue: defaultValue, defaultValue: defaultValue,
@@ -2338,7 +2269,7 @@ internal static class RenderConfigWindow
display: display, display: display,
onChanged: val => { if (val != null) onChanged?.Invoke(val); }, onChanged: val => { if (val != null) onChanged?.Invoke(val); },
id: id id: id
); ), label);
} }
/// <summary> /// <summary>
+42
View File
@@ -0,0 +1,42 @@
using System.Collections.Generic;
using O5Kit.Control;
using O5Kit.Core;
using TMPro;
using UnityEngine;
namespace ADOFAIRenderer.Util.UI;
internal abstract record UIWrapperBase(TextMeshProUGUI? label)
{
public readonly TextMeshProUGUI? label = label;
#pragma warning disable CS0649
public ITweenHandle? tween;
#pragma warning restore CS0649
}
internal record O5InputFieldWrapper(O5InputField component, TextMeshProUGUI? label) : UIWrapperBase(label)
{
public readonly O5InputField component = component;
public string Value => component.Value;
public void Set(string value, bool invoke = true) => component.Set(value, invoke);
}
internal record O5ToggleWrapper(O5Toggle component, TextMeshProUGUI? label) : UIWrapperBase(label)
{
public readonly O5Toggle component = component;
public bool Value => component.Value;
public void Set(bool value, bool invoke = true) => component.Set(value, invoke);
}
internal record O5DropdownWrapper<T>(O5Dropdown<T> component, TextMeshProUGUI? label) : UIWrapperBase(label)
{
public readonly O5Dropdown<T> component = component;
public T? Value => component.Value;
public IReadOnlyList<T> Values => component.Values;
public void Set(T? value, bool invoke = true) => component.Set(value, invoke);
public void SetValues(IReadOnlyList<T> values) => component.SetValues(values);
}