Add NonTile in Advanced Settings

This commit is contained in:
copecone committed 2026-08-04 21:33:13 +09:00
1 parent c07b57b273
commit 5711ad109f
8 files changed
+225 -66

No files matched your search

Binary file not shown.
BIN
View File
Binary file not shown.
Binary file not shown.
+3 -3
View File
@@ -379,7 +379,7 @@ namespace ADOFAIRenderer.Core
GCS.nextSpeedRun = 1;
GCS.customLevelIndex = 0;
if (Configuration.RandomSeed.HasValue) Random.InitState(Configuration.RandomSeed.Value);
if (Configuration.AdvancedConfig.RandomSeed.HasValue) Random.InitState(Configuration.AdvancedConfig.RandomSeed.Value);
ADOBase.loader.LoadSceneWithTransition(WipeDirection.StartsFromRight, "scnGame");
skipPressToStart = true;
_renderSetup = true;
@@ -387,7 +387,7 @@ namespace ADOFAIRenderer.Core
private IEnumerator SetupPlay()
{
if (Configuration.AudioConfig.RenderAudio && GetOutputExtension(Configuration.VideoConfig!.Codec) != ".mp4")
if (Configuration.AudioConfig.RenderAudio && GetOutputExtension(Configuration.VideoConfig.Codec) != ".mp4")
{
Configuration.AudioConfig.AudioSampleRate = 48000;
}
@@ -430,7 +430,7 @@ namespace ADOFAIRenderer.Core
scrController.instance.levelWasSkipped = true;
if (!scrConductor.instance || !scrConductor.instance.song) yield break;
if (Configuration.ProcessAudio)
if (Configuration.AdvancedConfig.ProcessAudio)
{
AudioSpectrumGenerator.Initialize(scrConductor.instance.song.clip);
}
+24
View File
@@ -120,6 +120,30 @@ namespace ADOFAIRenderer.Data
{
configObj.Remove("AudioConfig");
}
// 4. legacy top-level Advanced properties -> AdvancedConfig
string[] legacyAdvancedProps = { "RandomSeed", "ProcessAudio", "NonTile" };
foreach (var prop in legacyAdvancedProps)
{
var legacyToken = configObj[prop];
if (legacyToken != null && legacyToken.Type != JTokenType.Null)
{
if (configObj["AdvancedConfig"] == null || configObj["AdvancedConfig"]!.Type == JTokenType.Null)
{
configObj["AdvancedConfig"] = new JObject();
}
var advancedConfigObj = (JObject)configObj["AdvancedConfig"]!;
advancedConfigObj[prop] ??= legacyToken;
}
configObj.Remove(prop);
}
if (configObj["AdvancedConfig"] != null && configObj["AdvancedConfig"]!.Type == JTokenType.Null)
{
configObj.Remove("AdvancedConfig");
}
}
var preset = jObject.ToObject<RenderPreset>();
+8 -3
View File
@@ -10,14 +10,19 @@ namespace ADOFAIRenderer.Data
public int RenderWidth { get; set; }
public int RenderHeight { get; set; }
public VideoEncodingConfig VideoConfig { get; set; } = new VideoEncodingConfig();
public AudioEncodingConfig AudioConfig { get; set; } = new AudioEncodingConfig();
public VideoEncodingConfig VideoConfig { get; set; } = new();
public AudioEncodingConfig AudioConfig { get; set; } = new();
public AdvancedConfig AdvancedConfig { get; set; } = new();
public double DelayAfterLevelEnd { get; set; }
public bool ShowJudgementText { get; set; }
}
public class AdvancedConfig
{
public int? RandomSeed { get; set; } = null;
public bool ProcessAudio { get; set; }
public bool ProcessAudio { get; set; } = true;
public bool NonTile { get; set; } = false;
}
public class VideoEncodingConfig
+2 -2
View File
@@ -148,7 +148,7 @@ namespace ADOFAIRenderer.Patch.Engine
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static bool Prefix(AudioSource __instance, float[] samples, int channel, FFTWindow window)
{
if (!RenderManager.IsCapturingActive || !RenderPatch || !RenderManager.Instance.Configuration.ProcessAudio) return true;
if (!RenderManager.IsCapturingActive || !RenderPatch || !RenderManager.Instance.Configuration.AdvancedConfig.ProcessAudio) return true;
AudioSpectrumGenerator.GetSpectrumData(samples, channel, window);
return false;
}
@@ -160,7 +160,7 @@ namespace ADOFAIRenderer.Patch.Engine
[SuppressMessage("ReSharper", "InconsistentNaming")]
public static void Prefix(ref bool stream)
{
if (RenderManager.Instance && RenderManager.Instance.OverrideLoading && RenderManager.Instance.Configuration.ProcessAudio)
if (RenderManager.Instance && RenderManager.Instance.OverrideLoading && RenderManager.Instance.Configuration.AdvancedConfig.ProcessAudio)
stream = false;
}
}
+188 -58
View File
@@ -24,6 +24,9 @@ namespace ADOFAIRenderer.UI
private Button _audioEncodingConfigButton = null!;
private VisualElement _audioEncodingConfigContainer = null!;
private Button _advancedSettingsButton = null!;
private VisualElement? _advancedConfigContainer;
private void Awake()
{
_root = uiDocument.rootVisualElement;
@@ -84,6 +87,161 @@ namespace ADOFAIRenderer.UI
{
Melon<RenderMod>.Logger.Error("Button 'PresetSettingsButton'을(를) 찾을 수 없습니다.");
}
_advancedSettingsButton = _root.Q<Button>("AdvancedSettingsButton");
if (_advancedSettingsButton == null)
{
var bottomRow = CreateRow();
bottomRow.pickingMode = PickingMode.Ignore;
bottomRow.style.position = Position.Absolute;
bottomRow.style.right = 0f;
bottomRow.style.bottom = 0f;
bottomRow.style.justifyContent = Justify.FlexEnd;
_advancedSettingsButton = new Button { name = "AdvancedSettingsButton", text = "고급 설정..." };
bottomRow.Add(_advancedSettingsButton);
var targetContainer = _root.childCount > 0 ? _root[0] : _root;
targetContainer.Add(bottomRow);
Melon<RenderMod>.Logger.Msg("[UI] AdvancedSettingsButton 동적 생성 완료.");
}
else
{
_advancedSettingsButton.text = "고급 설정...";
Melon<RenderMod>.Logger.Msg($"[UI] AdvancedSettingsButton 발견: pickingMode={_advancedSettingsButton.pickingMode}, enabledSelf={_advancedSettingsButton.enabledSelf}");
}
_advancedSettingsButton.RegisterCallback<ClickEvent>(_ => OpenAdvancedConfig());
}
private void OpenAdvancedConfig()
{
var config = RenderManager.Instance.Configuration;
config.AdvancedConfig ??= GenerateAdvancedConfig();
var tempConfig = new AdvancedConfig
{
ProcessAudio = config.AdvancedConfig.ProcessAudio,
RandomSeed = config.AdvancedConfig.RandomSeed,
NonTile = config.AdvancedConfig.NonTile
};
if (_advancedConfigContainer != null && _root.Contains(_advancedConfigContainer))
{
_root.Remove(_advancedConfigContainer);
}
_advancedConfigContainer = new VisualElement
{
name = "AdvancedSettingsContainer",
style =
{
position = Position.Absolute,
width = Length.Percent(100),
height = Length.Percent(100),
left = 0,
top = 0,
backgroundColor = new StyleColor(new Color(0.15f, 0.15f, 0.15f, 1.0f)),
justifyContent = Justify.Center,
alignItems = Align.Center
}
};
// 1. 타이틀 로우
var titleRow = CreateRow();
var titleLabel = new Label("고급 설정")
{
style =
{
fontSize = 24,
color = new StyleColor(Color.white)
}
};
titleRow.Add(titleLabel);
_advancedConfigContainer.Add(titleRow);
// 2. 오디오 처리 로우
var processAudioRow = CreateRow();
var processAudioLabel = CreateFormLabel("오디오 처리");
var processAudioToggle = new Toggle { name = "AdvancedProcessAudioToggle", label = "", value = tempConfig.ProcessAudio };
processAudioRow.Add(processAudioLabel);
processAudioRow.Add(processAudioToggle);
_advancedConfigContainer.Add(processAudioRow);
// 3. 논타일 모드 로우
var nonTileRow = CreateRow();
var nonTileLabel = CreateFormLabel("논타일 모드");
var nonTileToggle = new Toggle { name = "AdvancedNonTileToggle", label = "", value = tempConfig.NonTile };
nonTileRow.Add(nonTileLabel);
nonTileRow.Add(nonTileToggle);
_advancedConfigContainer.Add(nonTileRow);
// 4. 랜덤 시드 로우
var randomSeedRow = CreateRow();
var randomSeedLabel = CreateFormLabel("랜덤 시드 (입력 선택)");
var randomSeedField = new IntegerField { name = "AdvancedRandomSeed", label = "", value = tempConfig.RandomSeed ?? 0 };
if (!tempConfig.RandomSeed.HasValue)
{
var textProperty = typeof(IntegerField).GetProperty("text", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy);
if (textProperty == null)
{
textProperty = typeof(TextInputBaseField<int>).GetProperty("text", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy);
}
textProperty?.SetValue(randomSeedField, string.Empty);
}
randomSeedRow.Add(randomSeedLabel);
randomSeedRow.Add(randomSeedField);
_advancedConfigContainer.Add(randomSeedRow);
// 5. 제어 버튼 로우 (취소 / 저장)
var buttonRow = CreateRow();
var cancelBtn = new Button { text = "취소" };
var saveBtn = new Button { text = "저장" };
buttonRow.Add(cancelBtn);
buttonRow.Add(saveBtn);
_advancedConfigContainer.Add(buttonRow);
cancelBtn.RegisterCallback<ClickEvent>(_ =>
{
ToggleAdvancedScreens(false);
_root.Remove(_advancedConfigContainer);
_advancedConfigContainer = null!;
});
saveBtn.RegisterCallback<ClickEvent>(_ =>
{
tempConfig.ProcessAudio = processAudioToggle.value;
tempConfig.NonTile = nonTileToggle.value;
if (!string.IsNullOrEmpty(randomSeedField.text))
{
tempConfig.RandomSeed = randomSeedField.value;
}
else
{
tempConfig.RandomSeed = null;
}
config.AdvancedConfig = tempConfig;
ToggleAdvancedScreens(false);
_root.Remove(_advancedConfigContainer);
_advancedConfigContainer = null!;
});
_root.Add(_advancedConfigContainer);
ToggleAdvancedScreens(true);
void ToggleAdvancedScreens(bool showAdvanced)
{
if (_root.childCount > 0)
{
_root[0].style.display = showAdvanced ? DisplayStyle.None : DisplayStyle.Flex;
}
_advancedConfigContainer.style.display = showAdvanced ? DisplayStyle.Flex : DisplayStyle.None;
}
}
private void Update()
@@ -149,7 +307,7 @@ namespace ADOFAIRenderer.UI
var codecRow = CreateRow();
var codecLabel = CreateFormLabel("코덱");
var codecChoices = new List<string>(System.Enum.GetNames(typeof(Codec)));
var codecDropdown = new DropdownField(codecChoices, tempConfig.Codec.ToString());
var codecDropdown = new DropdownField(codecChoices, tempConfig.Codec.ToString()) { name = "VideoCodec" };
codecRow.Add(codecLabel);
codecRow.Add(codecDropdown);
_videoEncodingConfigContainer.Add(codecRow);
@@ -158,7 +316,7 @@ namespace ADOFAIRenderer.UI
var modeRow = CreateRow();
var modeLabel = CreateFormLabel("모드");
var modeChoices = new List<string>(System.Enum.GetNames(typeof(RateControlMode)));
var modeDropdown = new DropdownField(modeChoices, tempConfig.RateControlMode.ToString());
var modeDropdown = new DropdownField(modeChoices, tempConfig.RateControlMode.ToString()) { name = "VideoRateControlMode" };
modeRow.Add(modeLabel);
modeRow.Add(modeDropdown);
_videoEncodingConfigContainer.Add(modeRow);
@@ -166,7 +324,7 @@ namespace ADOFAIRenderer.UI
// 5. 비트레이트 로우
var bitrateRow = CreateRow();
var bitrateLabel = CreateFormLabel("비트레이트(kbps)");
var bitrateField = new IntegerField { name = "EncodingBitrate", label = "", value = tempConfig.Bitrate };
var bitrateField = new IntegerField { name = "VideoBitrate", label = "", value = tempConfig.Bitrate };
bitrateRow.Add(bitrateLabel);
bitrateRow.Add(bitrateField);
_videoEncodingConfigContainer.Add(bitrateRow);
@@ -174,7 +332,7 @@ namespace ADOFAIRenderer.UI
// 5.5. 최대 비트레이트 로우 (VBR 전용)
var maxBitrateRow = CreateRow();
var maxBitrateLabel = CreateFormLabel("최대 비트레이트(kbps)");
var maxBitrateField = new IntegerField { name = "EncodingMaxBitrate", label = "", value = tempConfig.MaxBitrate };
var maxBitrateField = new IntegerField { name = "VideoMaxBitrate", label = "", value = tempConfig.MaxBitrate };
maxBitrateRow.Add(maxBitrateLabel);
maxBitrateRow.Add(maxBitrateField);
_videoEncodingConfigContainer.Add(maxBitrateRow);
@@ -182,7 +340,7 @@ namespace ADOFAIRenderer.UI
// 6. QP 로우
var qpRow = CreateRow();
var qpLabel = CreateFormLabel("품질 (QP)");
var qpField = new IntegerField { name = "EncodingQP", label = "", value = tempConfig.QP };
var qpField = new IntegerField { name = "VideoQP", label = "", value = tempConfig.QP };
qpRow.Add(qpLabel);
qpRow.Add(qpField);
_videoEncodingConfigContainer.Add(qpRow);
@@ -190,7 +348,7 @@ namespace ADOFAIRenderer.UI
// 6.5. 키프레임 간격 로우 (초 단위)
var keyframeRow = CreateRow();
var keyframeLabel = CreateFormLabel("키프레임 간격(초)");
var keyframeField = new DoubleField { name = "EncodingKeyframeInterval", label = "", value = tempConfig.KeyframeInterval };
var keyframeField = new DoubleField { name = "VideoKeyframeInterval", label = "", value = tempConfig.KeyframeInterval };
keyframeRow.Add(keyframeLabel);
keyframeRow.Add(keyframeField);
_videoEncodingConfigContainer.Add(keyframeRow);
@@ -198,7 +356,7 @@ namespace ADOFAIRenderer.UI
// 6.75. 강제 소프트웨어 인코더 로우 (라벨 + 토글)
var forceSoftwareRow = CreateRow();
var forceSoftwareLabel = CreateFormLabel("소프트웨어 인코더");
var forceSoftwareToggle = new Toggle { name = "ForceSoftwareEncoder", label = "", value = tempConfig.ForceSoftwareEncoder };
var forceSoftwareToggle = new Toggle { name = "VideoForceSoftwareEncoderToggle", label = "", value = tempConfig.ForceSoftwareEncoder };
forceSoftwareRow.Add(forceSoftwareLabel);
forceSoftwareRow.Add(forceSoftwareToggle);
_videoEncodingConfigContainer.Add(forceSoftwareRow);
@@ -224,13 +382,13 @@ namespace ADOFAIRenderer.UI
var encodingValidator = new IntegerInputValidator(_videoEncodingConfigContainer);
encodingValidator
.AddLimits("EncodingBitrate", new PositiveOnlyIntegerLimit(), new RangeIntegerLimit(1, 1000000))
.AddLimits("EncodingMaxBitrate", new PositiveOnlyIntegerLimit(), new RangeIntegerLimit(1, 1000000))
.AddLimits("EncodingQP", new RangeIntegerLimit(0, 51));
.AddLimits("VideoBitrate", new PositiveOnlyIntegerLimit(), new RangeIntegerLimit(1, 1000000))
.AddLimits("VideoMaxBitrate", new PositiveOnlyIntegerLimit(), new RangeIntegerLimit(1, 1000000))
.AddLimits("VideoQP", new RangeIntegerLimit(0, 51));
encodingValidator.SetupValidation();
var doubleValidator = new DoubleInputValidator(_videoEncodingConfigContainer);
doubleValidator.AddLimits("EncodingKeyframeInterval", new PositiveOnlyDoubleLimit(), new RangeDoubleLimit(0.1, 60.0));
doubleValidator.AddLimits("VideoKeyframeInterval", new PositiveOnlyDoubleLimit(), new RangeDoubleLimit(0.1, 60.0));
doubleValidator.SetupValidation();
modeDropdown.RegisterValueChangedCallback(evt => UpdateVisibility(evt.newValue));
@@ -364,7 +522,7 @@ namespace ADOFAIRenderer.UI
// 2. 오디오 렌더링 활성화 로우 (라벨 + 토글)
var renderAudioRow = CreateRow();
var renderAudioLabel = CreateFormLabel("오디오 렌더링 활성화");
var renderAudioToggle = new Toggle { name = "RenderAudioToggle", label = "", value = tempAudioConfig.RenderAudio };
var renderAudioToggle = new Toggle { name = "AudioRenderAudioToggle", label = "", value = tempAudioConfig.RenderAudio };
renderAudioRow.Add(renderAudioLabel);
renderAudioRow.Add(renderAudioToggle);
_audioEncodingConfigContainer.Add(renderAudioRow);
@@ -380,7 +538,7 @@ namespace ADOFAIRenderer.UI
var sampleRateDropdown = new DropdownField(
new List<string> { "44100", "48000" },
sampleRateStr
);
) { name = "AudioSampleRate" };
sampleRateRow.Add(sampleRateLabel);
sampleRateRow.Add(sampleRateDropdown);
_audioEncodingConfigContainer.Add(sampleRateRow);
@@ -391,7 +549,7 @@ namespace ADOFAIRenderer.UI
var channelsDropdown = new DropdownField(
new List<string> { "1 (Mono)", "2 (Stereo)" },
tempAudioConfig.AudioChannels == 1 ? "1 (Mono)" : "2 (Stereo)"
);
) { name = "AudioChannels" };
channelsRow.Add(channelsLabel);
channelsRow.Add(channelsDropdown);
_audioEncodingConfigContainer.Add(channelsRow);
@@ -478,13 +636,10 @@ namespace ADOFAIRenderer.UI
var widthField = _root.Q<IntegerField>("RenderWidth");
var heightField = _root.Q<IntegerField>("RenderHeight");
var randomSeedField = _root.Q<IntegerField>("RandomSeed");
var renderFpsField = _root.Q<DoubleField>("RenderFPS");
var videoFpsField = _root.Q<DoubleField>("VideoFPS");
var delayField = _root.Q<DoubleField>("DelayAfterLevelEnd");
var showJudgementText = _root.Q<Toggle>("ShowJudgementText");
var processAudio = _root.Q<Toggle>("ProcessAudioToggle");
// Copy validated values to Configuration manually
var config = RenderManager.Instance.Configuration;
@@ -494,16 +649,12 @@ namespace ADOFAIRenderer.UI
config.VideoFPS = videoFpsField.value;
config.DelayAfterLevelEnd = delayField.value;
config.ShowJudgementText = showJudgementText.value;
config.ProcessAudio = processAudio.value;
if (!string.IsNullOrEmpty(randomSeedField.text))
config.RandomSeed = randomSeedField.value;
else
config.RandomSeed = null;
if (showJudgementText != null)
config.ShowJudgementText = showJudgementText.value;
RenderManager.Instance.Configuration.VideoConfig ??= GenerateEncodingConfig();
RenderManager.Instance.Configuration.AudioConfig ??= GenerateAudioEncodingConfig();
RenderManager.Instance.Configuration.AdvancedConfig ??= GenerateAdvancedConfig();
RenderManager.Instance.SetupCaptureDirectory();
RenderManager.Instance.SetupGameScene();
@@ -542,12 +693,10 @@ namespace ADOFAIRenderer.UI
{
var widthField = _root.Q<IntegerField>("RenderWidth");
var heightField = _root.Q<IntegerField>("RenderHeight");
var randomSeedField = _root.Q<IntegerField>("RandomSeed");
var renderFpsField = _root.Q<DoubleField>("RenderFPS");
var videoFpsField = _root.Q<DoubleField>("VideoFPS");
var delayField = _root.Q<DoubleField>("DelayAfterLevelEnd");
var showJudgementText = _root.Q<Toggle>("ShowJudgementText");
var processAudio = _root.Q<Toggle>("ProcessAudioToggle");
if (widthField != null) widthField.value = config.RenderWidth;
if (heightField != null) heightField.value = config.RenderHeight;
@@ -555,28 +704,10 @@ namespace ADOFAIRenderer.UI
if (videoFpsField != null) videoFpsField.value = config.VideoFPS;
if (delayField != null) delayField.value = config.DelayAfterLevelEnd;
if (showJudgementText != null) showJudgementText.value = config.ShowJudgementText;
if (processAudio != null) processAudio.value = config.ProcessAudio;
if (randomSeedField != null)
{
if (config.RandomSeed.HasValue)
{
randomSeedField.value = config.RandomSeed.Value;
}
else
{
randomSeedField.value = 0;
var textProperty = typeof(IntegerField).GetProperty("text", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy);
if (textProperty == null)
{
textProperty = typeof(TextInputBaseField<int>).GetProperty("text", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.FlattenHierarchy);
}
textProperty?.SetValue(randomSeedField, string.Empty);
}
}
config.VideoConfig ??= GenerateEncodingConfig();
config.AudioConfig ??= GenerateAudioEncodingConfig();
config.AdvancedConfig ??= GenerateAdvancedConfig();
RenderManager.Instance.Configuration = config;
}
@@ -906,8 +1037,6 @@ namespace ADOFAIRenderer.UI
var videoFpsField = _root.Q<DoubleField>("VideoFPS");
var delayField = _root.Q<DoubleField>("DelayAfterLevelEnd");
var showJudgementText = _root.Q<Toggle>("ShowJudgementText");
var processAudio = _root.Q<Toggle>("ProcessAudioToggle");
var randomSeedField = _root.Q<IntegerField>("RandomSeed");
var currentConfig = new RenderConfig
{
@@ -916,21 +1045,12 @@ namespace ADOFAIRenderer.UI
RenderFPS = renderFpsField.value,
VideoFPS = videoFpsField.value,
DelayAfterLevelEnd = delayField.value,
ShowJudgementText = showJudgementText.value,
ProcessAudio = processAudio.value
ShowJudgementText = showJudgementText?.value ?? true
};
if (!string.IsNullOrEmpty(randomSeedField.text))
{
currentConfig.RandomSeed = randomSeedField.value;
}
else
{
currentConfig.RandomSeed = null;
}
currentConfig.VideoConfig = RenderManager.Instance.Configuration.VideoConfig ?? GenerateEncodingConfig();
currentConfig.AudioConfig = RenderManager.Instance.Configuration.AudioConfig ?? GenerateAudioEncodingConfig();
currentConfig.AdvancedConfig = RenderManager.Instance.Configuration.AdvancedConfig ?? GenerateAdvancedConfig();
PresetManager.SavePreset(presetName, currentConfig);
nameField.value = string.Empty;
@@ -1032,5 +1152,15 @@ namespace ADOFAIRenderer.UI
AudioBitrate = 256000
};
}
private AdvancedConfig GenerateAdvancedConfig()
{
return new AdvancedConfig
{
ProcessAudio = true,
RandomSeed = null,
NonTile = false
};
}
}
}