diff --git a/Core/FirstUpdateHook.cs b/Core/FirstUpdateHook.cs
index 33cb51b..dba8266 100644
--- a/Core/FirstUpdateHook.cs
+++ b/Core/FirstUpdateHook.cs
@@ -7,13 +7,28 @@ namespace ADOFAIRenderer.Core
public class FirstUpdateHook : MonoBehaviour
{
private bool _checkedFFmpeg;
+ private bool _checkedNvidiaDriver;
private void Update()
{
if (!_checkedFFmpeg)
{
+ if (FFmpegDownloadUI.Instance) return;
+
+ if (!FFmpegDownloadUI.CheckFFmpegExists())
+ {
+ FFmpegDownloadUI.ShowDownloadUI();
+ return;
+ }
_checkedFFmpeg = true;
- FFmpegDownloadUI.ShowDownloadUI();
+ }
+
+ if (!_checkedNvidiaDriver)
+ {
+ if (CommonWarningDialogUI.Instance) return;
+
+ _checkedNvidiaDriver = true;
+ CheckNvidiaDriverWarning();
}
if (RenderManager.Instance)
@@ -21,5 +36,31 @@ namespace ADOFAIRenderer.Core
RenderManager.Instance.OnPreRenderUpdate();
}
}
+
+ private void CheckNvidiaDriverWarning()
+ {
+ var driverVer = Util.GPUUtil.GetNvidiaDriverVersion();
+ if (driverVer is null or >= 610.00f) return;
+
+ var currentVersion = driverVer.Value.ToString("F2");
+
+ CommonWarningDialogUI.ShowDialog(
+ "NVIDIA 그래픽 드라이버 업데이트 권장",
+ $"현재 감지된 NVIDIA 그래픽 드라이버 버전: {currentVersion}\n\n하드웨어 가속(NVENC)을 사용하여 영상을 렌더링하려면 드라이버 버전 610.00 이상이 필요합니다.\n\n드라이버 버전이 낮으면 인코딩이 실패하거나 소프트웨어(CPU) 인코딩으로 대체되어 렌더링이 매우 느려집니다. 드라이버 업데이트를 진행해 주시기 바랍니다.",
+ new DialogButton("드라이버 업데이트", () =>
+ {
+ Application.OpenURL("https://www.nvidia.com/Download/index.aspx");
+ Application.Quit();
+ }, new Color(0.0f, 0.8f, 1.0f, 1.0f)),
+ new DialogButton("기능 비활성화", () =>
+ {
+ RenderMod.IsFeatureDisabled = true;
+ }),
+ new DialogButton("이번만 그냥 진행", () =>
+ {
+ // 아무 동작 안 함
+ })
+ );
+ }
}
}
\ No newline at end of file
diff --git a/Patch/Game/scnEditorPatch.cs b/Patch/Game/scnEditorPatch.cs
index bbc0e77..d73286e 100644
--- a/Patch/Game/scnEditorPatch.cs
+++ b/Patch/Game/scnEditorPatch.cs
@@ -14,6 +14,8 @@ namespace ADOFAIRenderer.Patch.Game
// ReSharper disable once InconsistentNaming
public static void AddButtonRender(scnEditor __instance)
{
+ if (RenderMod.IsFeatureDisabled) return;
+
var cloneTarget = __instance.buttonExit!.gameObject;
var buttonContainer = cloneTarget.transform.parent!;
@@ -33,12 +35,11 @@ namespace ADOFAIRenderer.Patch.Game
// ReSharper disable once Unity.UnknownResource
// images[0] is the background on the root, images[1] is the icon on the child
var sprite = Resources.Load("LevelEditor/LevelEvents/MoveCamera");
- if (sprite != null)
- {
- var iconImage = images[1];
- iconImage.sprite = sprite;
- iconImage.rectTransform.sizeDelta = new Vector2(24, 24);
- }
+ if (sprite == null) return;
+
+ var iconImage = images[1];
+ iconImage.sprite = sprite;
+ iconImage.rectTransform.sizeDelta = new Vector2(24, 24);
}
}
}
\ No newline at end of file
diff --git a/RenderMod.cs b/RenderMod.cs
index 4b7e5df..5b3db62 100644
--- a/RenderMod.cs
+++ b/RenderMod.cs
@@ -17,8 +17,10 @@ namespace ADOFAIRenderer
public static AssetBundle FontBundle = null!;
// ReSharper disable once MemberCanBePrivate.Global
public static AssetBundle SceneBundle = null!;
+ // ReSharper disable once MemberCanBePrivate.Global
public static AssetBundle ShaderBundle = null!;
public static ComputeShader ColorConversionShader = null!;
+ public static bool IsFeatureDisabled = false;
public override void OnInitializeMelon()
{
diff --git a/UI/CommonWarningDialogUI.cs b/UI/CommonWarningDialogUI.cs
new file mode 100644
index 0000000..db63372
--- /dev/null
+++ b/UI/CommonWarningDialogUI.cs
@@ -0,0 +1,292 @@
+using System;
+using TMPro;
+using UnityEngine;
+using UnityEngine.UI;
+
+namespace ADOFAIRenderer.UI
+{
+ public class DialogButton
+ {
+ public string Text;
+ public Action OnClick;
+ public Color? BackgroundColor;
+
+ public DialogButton(string text, Action onClick, Color? backgroundColor = null)
+ {
+ Text = text;
+ OnClick = onClick;
+ BackgroundColor = backgroundColor;
+ }
+ }
+
+ public class CommonWarningDialogUI : MonoBehaviour
+ {
+ public static CommonWarningDialogUI? Instance { get; private set; }
+
+ private void Awake()
+ {
+ Instance = this;
+ }
+
+ private void OnDestroy()
+ {
+ if (Instance == this)
+ {
+ Instance = null;
+ }
+ }
+
+ private static TMP_FontAsset GetNanumSquareNeoBdFontAsset()
+ {
+ TMP_FontAsset? font = null;
+ if (RenderMod.FontBundle)
+ {
+ try
+ {
+ font = RenderMod.FontBundle.LoadAsset("NanumSquareNeoOTF-Bd SDF");
+ }
+ catch
+ {
+ // 로딩 실패
+ }
+ }
+
+ // 폴백 처리
+ if (!font)
+ {
+ try
+ {
+ font = RDString.fontData.fontTMP;
+ }
+ catch
+ {
+ // ignored
+ }
+ }
+ if (!font)
+ {
+ // ReSharper disable once Unity.UnknownResource
+ font = Resources.Load("Fonts & Materials/LiberationSans SDF");
+ }
+
+ if (font) return font;
+ var fonts = Resources.FindObjectsOfTypeAll();
+ if (fonts.Length > 0) font = fonts[0];
+
+ return font!;
+ }
+
+ public static void ShowDialog(string title, string description, params DialogButton[] buttons)
+ {
+ if (buttons.Length == 0) return;
+
+ var obj = new GameObject("CommonWarningDialogUI");
+ DontDestroyOnLoad(obj);
+ var dialog = obj.AddComponent();
+ dialog.Initialize(title, description, buttons);
+ }
+
+ private void Initialize(string title, string description, DialogButton[] buttons)
+ {
+ // UI 레이어(5) 설정
+ gameObject.layer = 5;
+
+ // Canvas 설정
+ var canvas = gameObject.AddComponent