SHA256
Implement O5Kit
This commit is contained in:
8 files changed
+98
-174
No files matched your search
@@ -42,3 +42,4 @@ GEMINI.md
|
|||||||
# Developer Description Files
|
# Developer Description Files
|
||||||
/AsyncInputAutoplayFix.md
|
/AsyncInputAutoplayFix.md
|
||||||
/AudioMixerExplanation.md
|
/AudioMixerExplanation.md
|
||||||
|
/O5Theme.md
|
||||||
@@ -16,6 +16,9 @@
|
|||||||
<Reference Include="0Harmony">
|
<Reference Include="0Harmony">
|
||||||
<HintPath>$(ADOFAI_PATH)\MelonLoader\net35\0Harmony.dll</HintPath>
|
<HintPath>$(ADOFAI_PATH)\MelonLoader\net35\0Harmony.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
<Reference Include="O5Kit">
|
||||||
|
<HintPath>$(ADOFAI_PATH)\UserLibs\O5Kit.dll</HintPath>
|
||||||
|
</Reference>
|
||||||
<Reference Include="Assembly-CSharp">
|
<Reference Include="Assembly-CSharp">
|
||||||
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\Assembly-CSharp.dll</HintPath>
|
<HintPath>$(ADOFAI_PATH)\A Dance of Fire and Ice_Data\Managed\Assembly-CSharp.dll</HintPath>
|
||||||
</Reference>
|
</Reference>
|
||||||
|
|||||||
@@ -1,85 +1,3 @@
|
|||||||
{
|
{
|
||||||
"ui.button.presets": "Presets",
|
"ui.render_config.window_title": "Render Config"
|
||||||
"ui.placeholder.render_fps": "Render FPS",
|
|
||||||
"ui.placeholder.video_fps": "Video FPS",
|
|
||||||
"ui.placeholder.render_width": "Render Width (px)",
|
|
||||||
"ui.placeholder.render_height": "Render Height (px)",
|
|
||||||
"ui.button.video_config": "Video Encoding Config",
|
|
||||||
"ui.button.audio_config": "Audio Encoding Config",
|
|
||||||
"ui.placeholder.delay_after_end": "Delay After Level End",
|
|
||||||
"ui.toggle.show_judgement": "Show Judgement",
|
|
||||||
"ui.button.go_render": "Go Render",
|
|
||||||
"ui.button.advanced_settings": "Advanced Settings...",
|
|
||||||
"ui.version.expired": " (Expired)",
|
|
||||||
"ui.validation.required_fields": "Required input fields are empty or invalid. Please fill in all settings.",
|
|
||||||
|
|
||||||
"ui.advanced.title": "Advanced Settings",
|
|
||||||
"ui.advanced.file_extension": "File Extension",
|
|
||||||
"ui.advanced.process_audio": "Process Audio",
|
|
||||||
"ui.advanced.non_tile_mode": "Non-Tile Mode",
|
|
||||||
"ui.advanced.random_seed": "Random Seed (Optional)",
|
|
||||||
"ui.button.cancel": "Cancel",
|
|
||||||
"ui.button.save": "Save",
|
|
||||||
|
|
||||||
"ui.video.title": "Video Encoding Settings",
|
|
||||||
"ui.video.codec": "Codec",
|
|
||||||
"ui.video.rate_control": "Bitrate Control Mode",
|
|
||||||
"ui.video.bitrate": "Bitrate (kbps)",
|
|
||||||
"ui.video.max_bitrate": "Max Bitrate (kbps)",
|
|
||||||
"ui.video.qp": "Quality (QP)",
|
|
||||||
"ui.video.keyframe_interval": "Keyframe Interval (s)",
|
|
||||||
"ui.video.force_software": "Force Software Encoder",
|
|
||||||
"ui.video.qp_zero_warning": "Warning: Setting QP to 0 applies lossless encoding and may result in very large file sizes.",
|
|
||||||
|
|
||||||
"ui.audio.title": "Audio Encoding Settings",
|
|
||||||
"ui.audio.rendering": "Audio Rendering",
|
|
||||||
"ui.audio.sample_rate": "Sample Rate (Hz)",
|
|
||||||
"ui.audio.channels": "Audio Channels",
|
|
||||||
"ui.audio.channels_mono": "1 (Mono)",
|
|
||||||
"ui.audio.channels_stereo": "2 (Stereo)",
|
|
||||||
"ui.audio.bitrate": "Audio Bitrate (kbps)",
|
|
||||||
|
|
||||||
"ui.preset.title": "Preset Settings",
|
|
||||||
"ui.preset.new_name": "New Preset Name",
|
|
||||||
"ui.preset.no_presets": "No saved presets.",
|
|
||||||
"ui.button.load": "Load",
|
|
||||||
"ui.button.delete": "Delete",
|
|
||||||
"ui.button.close": "Close",
|
|
||||||
"ui.preset.save_failed": "Save Failed",
|
|
||||||
"ui.preset.enter_name": "Please enter a preset name.",
|
|
||||||
"ui.preset.invalid_inputs": "Cannot save preset because required input values are empty or invalid.",
|
|
||||||
"ui.preset.save_error": "An error occurred while saving the preset: {0}",
|
|
||||||
"ui.preset.delete_title": "Delete Preset",
|
|
||||||
"ui.preset.delete_confirm": "Are you sure you want to delete the preset '{0}'?",
|
|
||||||
"ui.button.yes": "Yes",
|
|
||||||
"ui.button.no": "No",
|
|
||||||
"ui.button.ok": "OK",
|
|
||||||
|
|
||||||
"ui.ffmpeg.title": "FFmpeg Library Installation Required",
|
|
||||||
"ui.ffmpeg.desc_main": "FFmpeg shared libraries are required to render video.",
|
|
||||||
"ui.ffmpeg.desc_osx": "For macOS, reliable public builds are unavailable, so FFmpeg 8.1 must be built manually.\nClick the button below to open the official FFmpeg website.",
|
|
||||||
"ui.ffmpeg.desc_auto": "Click the button below to automatically download and install from the internet.\n<color=#aaaaaa><size=13>(Download size: ~70MB, extracted to UserLibs folder)</size></color>",
|
|
||||||
"ui.ffmpeg.button_download": "Download & Install",
|
|
||||||
"ui.ffmpeg.button_open_web": "Open Download Page",
|
|
||||||
"ui.ffmpeg.button_cancel": "Cancel",
|
|
||||||
"ui.ffmpeg.button_opening": "Opening...",
|
|
||||||
"ui.ffmpeg.status_downloading": "Downloading... ({0:F1}%)",
|
|
||||||
"ui.ffmpeg.status_extracting": "Extracting FFmpeg files...",
|
|
||||||
"ui.ffmpeg.status_done": "Done! Restarting audio/video engine...",
|
|
||||||
"ui.ffmpeg.status_failed": "Failed to download FFmpeg: {0}",
|
|
||||||
|
|
||||||
"ui.escape.cancelling": "<color=#FF5252>Cancelling in {0:F1}s..</color>\n<size=40><color=#DDDDDD>Hold Esc to cancel render</color></size>",
|
|
||||||
|
|
||||||
"ui.monitor.title": "ADOFAI Renderer Realtime Monitor",
|
|
||||||
"ui.monitor.queue": "• Queue: <b>{0}</b> / {1} frames",
|
|
||||||
"ui.monitor.rendered_frames": "• Rendered Frames: <b>{0}</b>",
|
|
||||||
"ui.monitor.frames_sent": "• Frames Sent: <b>{0}</b>",
|
|
||||||
"ui.monitor.throttling": "• Throttling Controls: {0} times",
|
|
||||||
"ui.monitor.readback_failures": "• Readback Hard Failures: <color=#ff3333>{0}</color> times",
|
|
||||||
"ui.monitor.skip_retry": "• Render Skip-Retry: {0} / {1}",
|
|
||||||
"ui.monitor.memory": "• Mono Heap Memory: {0:F2} MB",
|
|
||||||
|
|
||||||
"ui.notification.complete_title": "Rendering Complete!",
|
|
||||||
"ui.notification.complete_msg": "{0} saved successfully.",
|
|
||||||
"ui.notification.video_fallback": "Video"
|
|
||||||
}
|
}
|
||||||
@@ -1,85 +1,3 @@
|
|||||||
{
|
{
|
||||||
"ui.button.presets": "프리셋",
|
"ui.render_config.window_title": "렌더 설정"
|
||||||
"ui.placeholder.render_fps": "렌더링 FPS",
|
|
||||||
"ui.placeholder.video_fps": "영상 FPS",
|
|
||||||
"ui.placeholder.render_width": "렌더링 너비 (px)",
|
|
||||||
"ui.placeholder.render_height": "렌더링 높이 (px)",
|
|
||||||
"ui.button.video_config": "비디오 인코딩 설정",
|
|
||||||
"ui.button.audio_config": "오디오 인코딩 설정",
|
|
||||||
"ui.placeholder.delay_after_end": "레벨 종료 후 대기 시간 (초)",
|
|
||||||
"ui.toggle.show_judgement": "판정 텍스트 표시",
|
|
||||||
"ui.button.go_render": "렌더링 시작",
|
|
||||||
"ui.button.advanced_settings": "고급 설정...",
|
|
||||||
"ui.version.expired": " (만료됨)",
|
|
||||||
"ui.validation.required_fields": "필수 입력란이 비어 있거나 올바르지 않습니다. 모든 설정을 확인해 주세요.",
|
|
||||||
|
|
||||||
"ui.advanced.title": "고급 설정",
|
|
||||||
"ui.advanced.file_extension": "파일 확장자",
|
|
||||||
"ui.advanced.process_audio": "오디오 처리",
|
|
||||||
"ui.advanced.non_tile_mode": "논타일 모드",
|
|
||||||
"ui.advanced.random_seed": "랜덤 시드 (선택 사항)",
|
|
||||||
"ui.button.cancel": "취소",
|
|
||||||
"ui.button.save": "저장",
|
|
||||||
|
|
||||||
"ui.video.title": "비디오 인코딩 설정",
|
|
||||||
"ui.video.codec": "코덱",
|
|
||||||
"ui.video.rate_control": "비트레이트 제어 모드",
|
|
||||||
"ui.video.bitrate": "비트레이트 (kbps)",
|
|
||||||
"ui.video.max_bitrate": "최대 비트레이트 (kbps)",
|
|
||||||
"ui.video.qp": "품질 (QP)",
|
|
||||||
"ui.video.keyframe_interval": "키프레임 간격 (초)",
|
|
||||||
"ui.video.force_software": "강제 소프트웨어 인코더",
|
|
||||||
"ui.video.qp_zero_warning": "경고: QP를 0으로 설정하면 무손실 인코딩이 적용되어 파일 크기가 매우 커질 수 있습니다.",
|
|
||||||
|
|
||||||
"ui.audio.title": "오디오 인코딩 설정",
|
|
||||||
"ui.audio.rendering": "오디오 렌더링",
|
|
||||||
"ui.audio.sample_rate": "샘플레이트 (Hz)",
|
|
||||||
"ui.audio.channels": "오디오 채널",
|
|
||||||
"ui.audio.channels_mono": "1 (모노)",
|
|
||||||
"ui.audio.channels_stereo": "2 (스테레오)",
|
|
||||||
"ui.audio.bitrate": "오디오 비트레이트 (kbps)",
|
|
||||||
|
|
||||||
"ui.preset.title": "프리셋 설정",
|
|
||||||
"ui.preset.new_name": "새 프리셋 이름",
|
|
||||||
"ui.preset.no_presets": "저장된 프리셋이 없습니다.",
|
|
||||||
"ui.button.load": "불러오기",
|
|
||||||
"ui.button.delete": "삭제",
|
|
||||||
"ui.button.close": "닫기",
|
|
||||||
"ui.preset.save_failed": "저장 실패",
|
|
||||||
"ui.preset.enter_name": "프리셋 이름을 입력해 주세요.",
|
|
||||||
"ui.preset.invalid_inputs": "필수 입력값이 비어 있거나 올바르지 않아 프리셋을 저장할 수 없습니다.",
|
|
||||||
"ui.preset.save_error": "프리셋 저장 중 오류가 발생했습니다: {0}",
|
|
||||||
"ui.preset.delete_title": "프리셋 삭제",
|
|
||||||
"ui.preset.delete_confirm": "정말 '{0}' 프리셋을 삭제하시겠습니까?",
|
|
||||||
"ui.button.yes": "예",
|
|
||||||
"ui.button.no": "아니오",
|
|
||||||
"ui.button.ok": "확인",
|
|
||||||
|
|
||||||
"ui.ffmpeg.title": "FFmpeg 라이브러리 설치 필요",
|
|
||||||
"ui.ffmpeg.desc_main": "영상을 렌더링하려면 FFmpeg 공유 라이브러리가 필요합니다.",
|
|
||||||
"ui.ffmpeg.desc_osx": "macOS의 경우 신뢰할 수 있는 빌드가 제공되지 않아 FFmpeg 8.1을 직접 빌드해야 합니다.\n아래 버튼을 눌러 공식 FFmpeg 웹사이트를 방문하세요.",
|
|
||||||
"ui.ffmpeg.desc_auto": "아래 버튼을 눌러 인터넷에서 자동으로 다운로드하여 설치합니다.\n<color=#aaaaaa><size=13>(다운로드 크기: 약 70MB, UserLibs 폴더에 압축 해제됨)</size></color>",
|
|
||||||
"ui.ffmpeg.button_download": "다운로드 및 설치",
|
|
||||||
"ui.ffmpeg.button_open_web": "다운로드 페이지 열기",
|
|
||||||
"ui.ffmpeg.button_cancel": "취소",
|
|
||||||
"ui.ffmpeg.button_opening": "열리는 중...",
|
|
||||||
"ui.ffmpeg.status_downloading": "다운로드 중... ({0:F1}%)",
|
|
||||||
"ui.ffmpeg.status_extracting": "FFmpeg 파일 압축 해제 중...",
|
|
||||||
"ui.ffmpeg.status_done": "완료! 오디오/비디오 엔진을 재시작합니다...",
|
|
||||||
"ui.ffmpeg.status_failed": "FFmpeg 다운로드 실패: {0}",
|
|
||||||
|
|
||||||
"ui.escape.cancelling": "<color=#FF5252>{0:F1}초 후 취소됩니다..</color>\n<size=40><color=#DDDDDD>렌더링을 취소하려면 Esc를 길게 누르세요</color></size>",
|
|
||||||
|
|
||||||
"ui.monitor.title": "ADOFAI Renderer 실시간 모니터",
|
|
||||||
"ui.monitor.queue": "• 대기열: <b>{0}</b> / {1} 프레임",
|
|
||||||
"ui.monitor.rendered_frames": "• 렌더링된 프레임: <b>{0}</b>",
|
|
||||||
"ui.monitor.frames_sent": "• 전송된 프레임: <b>{0}</b>",
|
|
||||||
"ui.monitor.throttling": "• 쓰로틀링 제어: {0}회",
|
|
||||||
"ui.monitor.readback_failures": "• 리드백 실패: <color=#ff3333>{0}</color>회",
|
|
||||||
"ui.monitor.skip_retry": "• 렌더 건너뜀-재시도: {0} / {1}",
|
|
||||||
"ui.monitor.memory": "• 모노 힙 메모리: {0:F2} MB",
|
|
||||||
|
|
||||||
"ui.notification.complete_title": "렌더링 완료!",
|
|
||||||
"ui.notification.complete_msg": "{0}이(가) 성공적으로 저장되었습니다.",
|
|
||||||
"ui.notification.video_fallback": "동영상"
|
|
||||||
}
|
}
|
||||||
@@ -165,7 +165,7 @@ internal static class LocalizationManager
|
|||||||
public static string Get(string key, params object[] args)
|
public static string Get(string key, params object[] args)
|
||||||
{
|
{
|
||||||
var template = Get(key);
|
var template = Get(key);
|
||||||
if (args == null || args.Length == 0) return template;
|
if (args.Length == 0) return template;
|
||||||
|
|
||||||
try
|
try
|
||||||
{
|
{
|
||||||
@@ -185,7 +185,6 @@ internal static class LocalizationManager
|
|||||||
return language switch
|
return language switch
|
||||||
{
|
{
|
||||||
SystemLanguage.Korean => "ko",
|
SystemLanguage.Korean => "ko",
|
||||||
SystemLanguage.English => "en",
|
|
||||||
_ => "en"
|
_ => "en"
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
@@ -218,6 +217,7 @@ internal static class LocalizationManager
|
|||||||
/// <summary>
|
/// <summary>
|
||||||
/// Convenient shorthand alias for <see cref="LocalizationManager"/>.
|
/// Convenient shorthand alias for <see cref="LocalizationManager"/>.
|
||||||
/// </summary>
|
/// </summary>
|
||||||
|
// ReSharper disable once InconsistentNaming
|
||||||
internal static class I18n
|
internal static class I18n
|
||||||
{
|
{
|
||||||
/// <inheritdoc cref="LocalizationManager.Get(string)"/>
|
/// <inheritdoc cref="LocalizationManager.Get(string)"/>
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
namespace ADOFAIRenderer.UI;
|
|
||||||
|
|
||||||
public class RendererUI
|
|
||||||
{
|
|
||||||
|
|
||||||
}
|
|
||||||
@@ -0,0 +1,39 @@
|
|||||||
|
using O5Kit.Core;
|
||||||
|
|
||||||
|
namespace ADOFAIRenderer.UI;
|
||||||
|
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
public class RendererUIManager : MonoBehaviour
|
||||||
|
{
|
||||||
|
public static RendererUIManager Instance { get; private set; } = null!;
|
||||||
|
|
||||||
|
public static O5Context Context = null!;
|
||||||
|
public O5WindowManager WindowManager = null!;
|
||||||
|
|
||||||
|
private void Awake() {
|
||||||
|
Instance = this;
|
||||||
|
|
||||||
|
Context = new O5Context(
|
||||||
|
config: new O5Config {
|
||||||
|
UIScale = 1.0f,
|
||||||
|
MiddleClickToDefault = true,
|
||||||
|
SliderSensitivity = 1.0f
|
||||||
|
},
|
||||||
|
theme: O5Theme.Dark
|
||||||
|
);
|
||||||
|
|
||||||
|
WindowManager = O5WindowManager.Create(Context, transform, "RendererMod_Canvas");
|
||||||
|
}
|
||||||
|
|
||||||
|
private void Update() {
|
||||||
|
O5Object.TickAll();
|
||||||
|
Context.Tooltip.Tick();
|
||||||
|
O5Kit.Input.O5ShortcutManager.HandleUpdate();
|
||||||
|
}
|
||||||
|
|
||||||
|
private void OnDestroy() {
|
||||||
|
WindowManager.Dispose();
|
||||||
|
Context.Dispose();
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,51 @@
|
|||||||
|
using ADOFAIRenderer.Localization;
|
||||||
|
using O5Kit.Core;
|
||||||
|
using O5Kit.Factory;
|
||||||
|
using UnityEngine;
|
||||||
|
|
||||||
|
namespace ADOFAIRenderer.UI.Window;
|
||||||
|
|
||||||
|
internal static class RenderConfigWindow
|
||||||
|
{
|
||||||
|
private static O5Window? _configWindow;
|
||||||
|
|
||||||
|
// 윈도우 만드는 메서드...
|
||||||
|
public static void CreateWindow()
|
||||||
|
{
|
||||||
|
if (_configWindow == null)
|
||||||
|
{
|
||||||
|
_configWindow = RendererUIManager.Instance.WindowManager.Create(new O5WindowOptions
|
||||||
|
{
|
||||||
|
Id = "RendererMod_RenderConfig",
|
||||||
|
Title = LocalizationManager.Get("ui.render_config.window_title"),
|
||||||
|
Size = new Vector2(580f, 420f),
|
||||||
|
Draggable = true,
|
||||||
|
Resizable = true,
|
||||||
|
ShowCloseButton = true
|
||||||
|
});
|
||||||
|
|
||||||
|
_configWindow.CloseRequested += win =>
|
||||||
|
{
|
||||||
|
win.Rect.gameObject.SetActive(false);
|
||||||
|
};
|
||||||
|
|
||||||
|
BuildUI(_configWindow.Content);
|
||||||
|
}
|
||||||
|
|
||||||
|
SetWindowActive(true);
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void BuildUI(RectTransform content)
|
||||||
|
{
|
||||||
|
var (viewport, scrollContent, scroller) =
|
||||||
|
O5Factory.ScrollView(RendererUIManager.Context, content, spacing: 10f);
|
||||||
|
|
||||||
|
// TODO: RenderFPS double 입력칸, VideoFPS double 입력칸, RenderWidth int (>0) 입력칸, RenderHeight int (>0) 입력칸, Video Encoding Config, Audio Encoding Config, Delay After Level End double (>=0) 입력칸, Show Judgement Toggle, Global Settings, Advanced Settings, Go Render 버튼
|
||||||
|
// NOTE: 한 가로줄에 두개씩
|
||||||
|
}
|
||||||
|
|
||||||
|
private static void SetWindowActive(bool enabled)
|
||||||
|
{
|
||||||
|
_configWindow?.Rect.gameObject.SetActive(enabled);
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in new issue
Block a user