From ed61cef4bb714e045cead4130ba34459e2d429c8c959bea9c7d8df7eb31669a3 Mon Sep 17 00:00:00 2001 From: copecone Date: Thu, 8 Oct 2026 15:44:40 +0900 Subject: [PATCH] Improve Video Encoding Options in `RenderConfigWindow` --- UI/Window/RenderConfigWindow.cs | 100 ++++++++++++++++++++++++++++---- 1 file changed, 88 insertions(+), 12 deletions(-) diff --git a/UI/Window/RenderConfigWindow.cs b/UI/Window/RenderConfigWindow.cs index bbe6b7e..d56d8dc 100644 --- a/UI/Window/RenderConfigWindow.cs +++ b/UI/Window/RenderConfigWindow.cs @@ -34,8 +34,17 @@ internal static class RenderConfigWindow private static O5Dropdown? _codecDropdown; private static O5Dropdown? _rateControlDropdown; private static O5InputField? _bitrateInput; + private static TMPro.TextMeshProUGUI? _bitrateLabel; + private static ITweenHandle? _bitrateLabelTween; + private static O5InputField? _maxBitrateInput; + private static TMPro.TextMeshProUGUI? _maxBitrateLabel; + private static ITweenHandle? _maxBitrateLabelTween; + private static O5InputField? _qpInput; + private static TMPro.TextMeshProUGUI? _qpLabel; + private static ITweenHandle? _qpLabelTween; + private static O5Slider? _keyframeIntervalSlider; private static O5Toggle? _forceSoftwareToggle; @@ -205,14 +214,14 @@ internal static class RenderConfigWindow c => { config.VideoConfig.Codec = c; - UpdateVideoCodec(c); + UpdateVideoCodecUI(c, config); }); _bitrateInput = CreateInputField( ctx, CreateFieldSlot(videoLeft), LocalizationManager.Get("ui.render_config.bitrate"), "30000", config.VideoConfig.Bitrate.ToString(), - "input_bitrate", + "input_bitrate", out _bitrateLabel, TMPro.TMP_InputField.CharacterValidation.Integer, val => { if (int.TryParse(val, out var b) && b > 0) config.VideoConfig.Bitrate = b; } ); @@ -221,7 +230,7 @@ internal static class RenderConfigWindow ctx, CreateFieldSlot(videoLeft), LocalizationManager.Get("ui.render_config.qp"), "18", config.VideoConfig.QP.ToString(), - "input_qp", + "input_qp", out _qpLabel, TMPro.TMP_InputField.CharacterValidation.Integer, val => { if (int.TryParse(val, out var qp) && qp >= 0) config.VideoConfig.QP = qp; } ); @@ -233,14 +242,18 @@ internal static class RenderConfigWindow RateControlMode.CBR, config.VideoConfig.RateControlMode, rateModes, m => m.ToString(), "dd_rate_control", - m => config.VideoConfig.RateControlMode = m + m => + { + config.VideoConfig.RateControlMode = m; + UpdateRateControlUI(m); + } ); _maxBitrateInput = CreateInputField( ctx, CreateFieldSlot(videoRight), LocalizationManager.Get("ui.render_config.max_bitrate"), "50000", config.VideoConfig.MaxBitrate.ToString(), - "input_max_bitrate", + "input_max_bitrate", out _maxBitrateLabel, TMPro.TMP_InputField.CharacterValidation.Integer, val => { if (int.TryParse(val, out var mb) && mb > 0) config.VideoConfig.MaxBitrate = mb; } ); @@ -250,7 +263,7 @@ internal static class RenderConfigWindow false, config.VideoConfig.ForceSoftwareEncoder, LocalizationManager.Get("ui.render_config.force_software"), "toggle_force_software", - val => config.AudioConfig.RenderAudio = val, + val => config.VideoConfig.ForceSoftwareEncoder = val, generateLabel: true ); @@ -465,11 +478,6 @@ internal static class RenderConfigWindow double Snap(double[] array, double value) => array.OrderBy(n => Math.Abs(n - value)).First(); - - void UpdateVideoCodec(Codec codec) - { - _sampleRateDropdown?.SetValues(CodecUtil.AvailableSampleRate[CodecUtil.AudioCodecMatch[codec]]); - } } private static void EnsureDefaultConfig(RenderConfig config) @@ -511,6 +519,9 @@ internal static class RenderConfigWindow _randomSeedInput?.Set(config.AdvancedConfig.RandomSeed?.ToString() ?? "", false); _processAudioToggle?.Set(config.AdvancedConfig.ProcessAudio, false); _nonTileToggle?.Set(config.AdvancedConfig.NonTile, false); + + UpdateVideoCodecUI(config.VideoConfig.Codec, config); + UpdateRateControlUI(config.VideoConfig.RateControlMode, noAnimate: true); } private static void TryGoRender() @@ -678,7 +689,21 @@ internal static class RenderConfigWindow TMPro.TMP_InputField.CharacterValidation characterValidation = TMPro.TMP_InputField.CharacterValidation.None, Action? onChanged = null) { - var label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true); + return CreateInputField(ctx, colParent, labelText, defaultValue, value, id, out _, characterValidation, onChanged); + } + + private static O5InputField CreateInputField( + O5Context ctx, + Transform colParent, + string labelText, + string? defaultValue, + string value, + string id, + out TMPro.TextMeshProUGUI label, + TMPro.TMP_InputField.CharacterValidation characterValidation = TMPro.TMP_InputField.CharacterValidation.None, + Action? onChanged = null) + { + label = O5Factory.ControlText(ctx, colParent, 13f, noPad: true); label.text = labelText; label.color = ctx.Theme.TextDim; @@ -702,6 +727,57 @@ internal static class RenderConfigWindow return inputField; } + private static void SetFieldBlocked( + O5InputField? input, + TMPro.TextMeshProUGUI? label, + ref ITweenHandle? tweenHandle, + bool blocked, + bool noAnimate = false) + { + input?.SetBlocked(blocked, noAnimate); + + if (label == null) return; + + tweenHandle?.Kill(); + var ctx = RendererUIManager.Context; + var baseColor = ctx.Theme.TextDim; + var targetColor = blocked + ? new Color(baseColor.r, baseColor.g, baseColor.b, baseColor.a * 0.4f) + : baseColor; + + if (noAnimate) + { + label.color = targetColor; + } + else + { + tweenHandle = ctx.Tween.TweenColor(label, targetColor, 0.2f); + } + } + + private static void UpdateRateControlUI(RateControlMode mode, bool noAnimate = false) + { + bool blockBitrate = mode is RateControlMode.CQP; + bool blockMaxBitrate = mode is RateControlMode.CBR or RateControlMode.CQP; + bool blockQp = mode is RateControlMode.CBR or RateControlMode.VBR; + + SetFieldBlocked(_bitrateInput, _bitrateLabel, ref _bitrateLabelTween, blockBitrate, noAnimate); + SetFieldBlocked(_maxBitrateInput, _maxBitrateLabel, ref _maxBitrateLabelTween, blockMaxBitrate, noAnimate); + SetFieldBlocked(_qpInput, _qpLabel, ref _qpLabelTween, blockQp, noAnimate); + } + + private static void UpdateVideoCodecUI(Codec codec, RenderConfig? config = null) + { + if (_sampleRateDropdown == null) return; + + _sampleRateDropdown.SetValues(CodecUtil.AvailableSampleRate[CodecUtil.AudioCodecMatch[codec]]); + + if (config != null && _sampleRateDropdown.Value is var currentRate) + { + config.AudioConfig.AudioSampleRate = currentRate; + } + } + private static O5InputField CreateFullWidthInputField( O5Context ctx, Transform parent,