SHA256
Merge branch 'main' into video_bg_sync
This commit is contained in:
5 files changed
+98
-24
No files matched your search
@@ -27,6 +27,9 @@ namespace ADOFAIRenderer.Core
|
||||
public const int MaxQueuedFrames = 64;
|
||||
public const int MaxRenderRetry = 64;
|
||||
|
||||
// Statistics
|
||||
public long framesSent;
|
||||
|
||||
// Core Render Configuration and Path
|
||||
public int countdown;
|
||||
public long frameCount;
|
||||
@@ -332,7 +335,7 @@ namespace ADOFAIRenderer.Core
|
||||
var targetMethod = typeof(scnEditor).GetMethod("TryApplicationQuit",
|
||||
System.Reflection.BindingFlags.NonPublic | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.Public);
|
||||
|
||||
if (targetMethod == null || scnEditor.instance == null) return;
|
||||
if (targetMethod == null || !scnEditor.instance) return;
|
||||
if (ADOBase.levelPath.IsNullOrEmpty())
|
||||
{
|
||||
scnEditor.instance.TryQuitToMenu();
|
||||
@@ -382,6 +385,7 @@ namespace ADOFAIRenderer.Core
|
||||
}
|
||||
|
||||
frameCount = 0;
|
||||
framesSent = 0;
|
||||
timeBase = Time.timeAsDouble;
|
||||
unscaledTimeBase = Time.unscaledTimeAsDouble;
|
||||
dspTimeBase = AudioSettings.dspTime;
|
||||
@@ -507,12 +511,15 @@ namespace ADOFAIRenderer.Core
|
||||
if (frame.ManagedBuffer.Length > 0)
|
||||
{
|
||||
videoFFmpeg.SendDataFromBuffer(frame.ManagedBuffer, frame.Length);
|
||||
Interlocked.Increment(ref framesSent);
|
||||
|
||||
ArrayPool<byte>.Shared.Return(frame.ManagedBuffer);
|
||||
}
|
||||
}
|
||||
else if (frame.NativePointer != IntPtr.Zero && frame.Length > 0)
|
||||
{
|
||||
videoFFmpeg.SendDataFromNativeBuffer(frame.NativePointer, frame.Length);
|
||||
Interlocked.Increment(ref framesSent);
|
||||
|
||||
if (frame.ReadbackState != null)
|
||||
{
|
||||
|
||||
+1
-1
@@ -7,7 +7,7 @@ using MelonLoader.Utils;
|
||||
using UnityEngine;
|
||||
using UnityEngine.EventSystems;
|
||||
|
||||
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.2.1-BETA", "ADOFAI Editor Forum")]
|
||||
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.2.2-BETA", "ADOFAI Editor Forum")]
|
||||
[assembly: MelonGame("7th Beat Games", "A Dance of Fire and Ice")]
|
||||
|
||||
namespace ADOFAIRenderer
|
||||
|
||||
@@ -1,5 +1,6 @@
|
||||
using System;
|
||||
using System.Text;
|
||||
using System.Threading;
|
||||
using ADOFAIRenderer.Core;
|
||||
using TMPro;
|
||||
using UnityEngine;
|
||||
@@ -94,7 +95,7 @@ namespace ADOFAIRenderer.UI
|
||||
panelRect.anchorMax = new Vector2(1, 1);
|
||||
panelRect.pivot = new Vector2(1, 1);
|
||||
panelRect.anchoredPosition = new Vector2(-30, -30);
|
||||
panelRect.sizeDelta = new Vector2(340, 250);
|
||||
panelRect.sizeDelta = new Vector2(360, 220);
|
||||
|
||||
// 텍스트 생성
|
||||
var textObj = new GameObject("MonitorText");
|
||||
@@ -187,7 +188,6 @@ namespace ADOFAIRenderer.UI
|
||||
var sb = new StringBuilder();
|
||||
sb.AppendLine("<b><color=#00ccff>ADOFAI Renderer Realtime Monitor</color></b>");
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"• Rendered Progress: <b>{(RenderManager.Instance ? RenderManager.Instance.frameCount : 0)}</b> frames");
|
||||
|
||||
var queueCount = 0;
|
||||
if (RenderManager.Instance)
|
||||
@@ -197,7 +197,10 @@ namespace ADOFAIRenderer.UI
|
||||
queueCount = RenderManager.Instance.ImageQueue.Count;
|
||||
}
|
||||
}
|
||||
sb.AppendLine($"• Queued Buffers: <b>{queueCount}</b> / {RenderManager.MaxQueuedFrames} frames");
|
||||
|
||||
sb.AppendLine($"• Queue: <b>{queueCount}</b> / {RenderManager.MaxQueuedFrames} frames");
|
||||
sb.AppendLine($"• Rendered Frames: <b>{(RenderManager.Instance ? RenderManager.Instance.frameCount : 0)}</b>");
|
||||
sb.AppendLine($"• Frames Sent: <b>{(RenderManager.Instance ? Interlocked.Read(ref RenderManager.Instance.framesSent) : 0)}</b>");
|
||||
|
||||
sb.AppendLine();
|
||||
sb.AppendLine($"• Throttling Controls: {(RenderManager.Instance ? RenderManager.Instance.throttleCount : 0)} times");
|
||||
|
||||
+82
-7
@@ -22,7 +22,12 @@ namespace ADOFAIRenderer.UI
|
||||
private TextMeshProUGUI _statusText = null!;
|
||||
|
||||
private bool _isDownloading;
|
||||
private readonly string _downloadUrl = "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl-shared.zip";
|
||||
private string DownloadUrl => Application.platform switch
|
||||
{
|
||||
RuntimePlatform.WindowsPlayer => "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-win64-gpl-shared.zip",
|
||||
RuntimePlatform.OSXPlayer => "https://github.com/ColorsWind/FFmpeg-macOS/releases/download/n5.0.1-patch3/FFmpeg-shared-n5.0.1-OSX-universal.zip",
|
||||
_ => "https://github.com/BtbN/FFmpeg-Builds/releases/download/latest/ffmpeg-master-latest-linux64-gpl-shared.tar.xz"
|
||||
};
|
||||
|
||||
private System.Threading.CancellationTokenSource? _cts;
|
||||
private readonly System.Collections.Concurrent.ConcurrentQueue<Action> _mainThreadQueue = new();
|
||||
@@ -32,8 +37,14 @@ namespace ADOFAIRenderer.UI
|
||||
var userLibs = MelonEnvironment.UserLibsDirectory;
|
||||
if (!Directory.Exists(userLibs)) return false;
|
||||
|
||||
// Check for avcodec-*.dll
|
||||
var files = Directory.GetFiles(userLibs, "avcodec-*.dll");
|
||||
string searchPattern = Application.platform switch
|
||||
{
|
||||
RuntimePlatform.WindowsPlayer => "avcodec-*.dll",
|
||||
RuntimePlatform.OSXPlayer => "libavcodec.*.dylib",
|
||||
_ => "libavcodec.so*"
|
||||
};
|
||||
|
||||
var files = Directory.GetFiles(userLibs, searchPattern);
|
||||
return files.Length > 0;
|
||||
}
|
||||
|
||||
@@ -402,7 +413,13 @@ namespace ADOFAIRenderer.UI
|
||||
Directory.CreateDirectory(userLibsDir);
|
||||
}
|
||||
|
||||
tempZipPath = Path.Combine(userLibsDir, "ffmpeg_temp.zip");
|
||||
string extension = Application.platform switch
|
||||
{
|
||||
RuntimePlatform.WindowsPlayer => ".zip",
|
||||
RuntimePlatform.OSXPlayer => ".zip",
|
||||
_ => ".tar.xz"
|
||||
};
|
||||
tempZipPath = Path.Combine(userLibsDir, "ffmpeg_temp" + extension);
|
||||
|
||||
var progressReporter = new Progress<float>(percent =>
|
||||
{
|
||||
@@ -410,7 +427,7 @@ namespace ADOFAIRenderer.UI
|
||||
UpdateStatus($"다운로드 중... ({(percent * 100f):F1}%)", new Color(0f, 0.8f, 1f));
|
||||
});
|
||||
|
||||
await DownloadFileAsync(_downloadUrl, tempZipPath, progressReporter, _cts.Token);
|
||||
await DownloadFileAsync(DownloadUrl, tempZipPath, progressReporter, _cts.Token);
|
||||
|
||||
// 다운로드 완료 후 압축 해제
|
||||
UpdateStatus("압축 해제 및 DLL 파일 복사 중...", new Color(0.9f, 0.9f, 0.2f));
|
||||
@@ -531,14 +548,16 @@ namespace ADOFAIRenderer.UI
|
||||
private async Task ExtractDllsAsync(string zipPath, string outputDirectory)
|
||||
{
|
||||
try
|
||||
{
|
||||
if (Application.platform == RuntimePlatform.OSXPlayer || Application.platform == RuntimePlatform.WindowsPlayer)
|
||||
{
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var targetExtension = Application.platform == RuntimePlatform.OSXPlayer ? ".dylib" : ".dll";
|
||||
using var archive = ZipFile.OpenRead(zipPath);
|
||||
foreach (var entry in archive.Entries)
|
||||
{
|
||||
// dll 파일만 userlibs 디렉토리 경로에 바로 복사
|
||||
if (entry.FullName.EndsWith(".dll", StringComparison.OrdinalIgnoreCase))
|
||||
if (entry.FullName.EndsWith(targetExtension, StringComparison.OrdinalIgnoreCase))
|
||||
{
|
||||
var targetPath = Path.Combine(outputDirectory, entry.Name);
|
||||
|
||||
@@ -553,6 +572,62 @@ namespace ADOFAIRenderer.UI
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
// 리눅스 (또는 기타 플랫폼) - tar.xz 해제
|
||||
await Task.Run(() =>
|
||||
{
|
||||
var tempExtractDir = Path.Combine(outputDirectory, "ffmpeg_temp_extracted");
|
||||
if (Directory.Exists(tempExtractDir))
|
||||
{
|
||||
Directory.Delete(tempExtractDir, true);
|
||||
}
|
||||
Directory.CreateDirectory(tempExtractDir);
|
||||
|
||||
var archiveUnixPath = zipPath.Replace('\\', '/');
|
||||
var tempExtractUnixDir = tempExtractDir.Replace('\\', '/');
|
||||
|
||||
var startInfo = new System.Diagnostics.ProcessStartInfo
|
||||
{
|
||||
FileName = "tar",
|
||||
Arguments = $"-xf \"{archiveUnixPath}\" -C \"{tempExtractUnixDir}\"",
|
||||
RedirectStandardOutput = true,
|
||||
RedirectStandardError = true,
|
||||
UseShellExecute = false,
|
||||
CreateNoWindow = true
|
||||
};
|
||||
|
||||
using (var process = System.Diagnostics.Process.Start(startInfo))
|
||||
{
|
||||
process!.WaitForExit();
|
||||
if (process.ExitCode != 0)
|
||||
{
|
||||
var error = process.StandardError.ReadToEnd();
|
||||
throw new Exception($"tar 압축 해제 실패 (ExitCode: {process.ExitCode}): {error}");
|
||||
}
|
||||
}
|
||||
|
||||
// 압축이 풀린 파일 중에서 .so 파일들을 찾아서 outputDirectory로 이동
|
||||
var soFiles = Directory.GetFiles(tempExtractDir, "*.so*", SearchOption.AllDirectories);
|
||||
foreach (var soFile in soFiles)
|
||||
{
|
||||
var fileName = Path.GetFileName(soFile);
|
||||
var targetPath = Path.Combine(outputDirectory, fileName);
|
||||
File.Copy(soFile, targetPath, true);
|
||||
}
|
||||
|
||||
// 임시 디렉토리 정리
|
||||
try
|
||||
{
|
||||
Directory.Delete(tempExtractDir, true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
finally
|
||||
{
|
||||
if (File.Exists(zipPath))
|
||||
|
||||
+1
-12
@@ -207,6 +207,7 @@ namespace ADOFAIRenderer.Util
|
||||
var data = request.GetData<byte>();
|
||||
// 비동기 요청 버퍼 데이터를 지속성(NativeBuffer) 메모리로 복사
|
||||
NativeArray<byte>.Copy(data, state.NativeBuffer, data.Length);
|
||||
}
|
||||
|
||||
var ptr = (IntPtr)state.NativeBuffer.GetUnsafeReadOnlyPtr();
|
||||
var capFrame = new RenderManager.CapturedFrame
|
||||
@@ -217,18 +218,6 @@ namespace ADOFAIRenderer.Util
|
||||
};
|
||||
PushToQueue(frame, capFrame);
|
||||
}
|
||||
else
|
||||
{
|
||||
var ptr = (IntPtr)state.NativeBuffer.GetUnsafeReadOnlyPtr();
|
||||
var capFrame = new RenderManager.CapturedFrame
|
||||
{
|
||||
NativePointer = ptr,
|
||||
Length = state.NativeBuffer.Length,
|
||||
ReadbackState = state
|
||||
};
|
||||
PushToQueue(frame, capFrame);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in new issue
Block a user