diff --git a/BetterGenshinImpact/Core/Config/MaskWindowConfig.cs b/BetterGenshinImpact/Core/Config/MaskWindowConfig.cs index 02c1397b..6447b025 100644 --- a/BetterGenshinImpact/Core/Config/MaskWindowConfig.cs +++ b/BetterGenshinImpact/Core/Config/MaskWindowConfig.cs @@ -56,7 +56,7 @@ public partial class MaskWindowConfig : ObservableObject /// 显示状态指示 /// [ObservableProperty] - private bool _showStatus = true; + private bool _showStatus = false; /// /// UID遮盖是否启用 diff --git a/BetterGenshinImpact/Core/Monitor/MouseKeyMonitor.cs b/BetterGenshinImpact/Core/Monitor/MouseKeyMonitor.cs index 40e81464..2ec49595 100644 --- a/BetterGenshinImpact/Core/Monitor/MouseKeyMonitor.cs +++ b/BetterGenshinImpact/Core/Monitor/MouseKeyMonitor.cs @@ -170,7 +170,7 @@ public class MouseKeyMonitor private void GlobalHookMouseWheelExt(object? sender, MouseEventExtArgs e) { - Debug.WriteLine("MouseMove: {0}; \t Location: {1};\t Delta: {2};\t System Timestamp: {3}", e.Button, e.Location, e.Delta, e.Timestamp); + // Debug.WriteLine("MouseMove: {0}; \t Location: {1};\t Delta: {2};\t System Timestamp: {3}", e.Button, e.Location, e.Delta, e.Timestamp); GlobalKeyMouseRecord.Instance.GlobalHookMouseWheel(e); } diff --git a/BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs b/BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs index 4b20a6e8..8e162495 100644 --- a/BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs +++ b/BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs @@ -26,7 +26,9 @@ public class GlobalKeyMouseRecord : Singleton private KeyMouseRecorder? _recorder; - private SharpAviRecorder _sharpAviRecorder; + // private SharpAviRecorder _sharpAviRecorder; + + private FfmpegRecorder? _ffmpegRecorder; private readonly Dictionary _keyDownState = []; @@ -63,7 +65,7 @@ public class GlobalKeyMouseRecord : Singleton SystemControl.ActivateWindow(); _logger.LogInformation("录制:{Text}", "实时任务已暂停"); - _logger.LogInformation("注意:录制时遇到主界面(鼠标永远在界面中心)和其他界面(鼠标可自由移动,比如地图等)的切换,请把手离开鼠标等待录制模式切换日志"); + // _logger.LogInformation("注意:录制时遇到主界面(鼠标永远在界面中心)和其他界面(鼠标可自由移动,比如地图等)的切换,请把手离开鼠标等待录制模式切换日志"); // 先实例化 _recorder = new KeyMouseRecorder(); @@ -73,8 +75,10 @@ public class GlobalKeyMouseRecord : Singleton { Directory.CreateDirectory(videoPath); } - _sharpAviRecorder = new SharpAviRecorder( Path.Combine(videoPath, $"{DateTime.Now:yyyyMMddHH_mmssffff.avi}"), - CodecIds.MotionJpeg, 90, 0, SupportedWaveFormat.WAVE_FORMAT_44M16, false, 0); + // _sharpAviRecorder = new SharpAviRecorder( Path.Combine(videoPath, $"{DateTime.Now:yyyyMMddHH_mmssffff.avi}"), + // CodecIds.MotionJpeg, 90, 0, SupportedWaveFormat.WAVE_FORMAT_44M16, false, 0); + + _ffmpegRecorder = new FfmpegRecorder(); TaskTriggerDispatcher.Instance().StopTimer(); @@ -87,7 +91,7 @@ public class GlobalKeyMouseRecord : Singleton // _timer.Start(); - _sharpAviRecorder.Start(); + _ffmpegRecorder.Start(); _directInputMonitor.Start(); Status = KeyMouseRecorderStatus.Recording; @@ -108,7 +112,7 @@ public class GlobalKeyMouseRecord : Singleton _directInputMonitor?.Dispose(); _directInputMonitor = null; - _sharpAviRecorder.Dispose(); + _ffmpegRecorder?.Stop(); // _timer.Stop(); @@ -191,10 +195,10 @@ public class GlobalKeyMouseRecord : Singleton public void GlobalHookMouseMoveTo(MouseEventExtArgs e) { - if (_isInMainUi) - { - return; - } + // if (_isInMainUi) + // { + // return; + // } // Debug.WriteLine($"MouseMove: {e.X}, {e.Y}"); _recorder?.MouseMoveTo(e); } @@ -208,7 +212,7 @@ public class GlobalKeyMouseRecord : Singleton public void GlobalHookMouseMoveBy(MouseState state) { // Debug.WriteLine($"MouseMoveBy: {state.X}, {state.Y}"); - if (state is { X: 0, Y: 0 } || !_isInMainUi) + if (state is { X: 0, Y: 0 }) { return; } diff --git a/BetterGenshinImpact/Core/Recorder/KeyMouseRecorder.cs b/BetterGenshinImpact/Core/Recorder/KeyMouseRecorder.cs index 19c5977d..ec09e7fd 100644 --- a/BetterGenshinImpact/Core/Recorder/KeyMouseRecorder.cs +++ b/BetterGenshinImpact/Core/Recorder/KeyMouseRecorder.cs @@ -6,6 +6,7 @@ using Gma.System.MouseKeyHook; using SharpDX.DirectInput; using System; using System.Collections.Generic; +using System.Globalization; using System.Text.Json; using System.Text.Json.Serialization; using System.Windows.Forms; @@ -38,69 +39,72 @@ public class KeyMouseRecorder { var rect = TaskContext.Instance().SystemInfo.CaptureAreaRect; // 合并鼠标移动事件 - var mergedMacroEvents = new List(); - MacroEvent? currentMerge = null; - foreach (var macroEvent in MacroEvents) - { - if (currentMerge == null) - { - currentMerge = macroEvent; - continue; - } - if (currentMerge.Type != macroEvent.Type) - { - mergedMacroEvents.Add(currentMerge); - currentMerge = macroEvent; - continue; - } - switch (macroEvent.Type) - { - case MacroEventType.MouseMoveTo: - // 控制合并时间片段长度 - if (macroEvent.Time - currentMerge.Time > MergedEventTimeMax) - { - mergedMacroEvents.Add(currentMerge); - currentMerge = macroEvent; - break; - } - // 合并为最后一个事件的位置,避免丢步 - currentMerge.MouseX = macroEvent.MouseX; - currentMerge.MouseY = macroEvent.MouseY; - break; - - case MacroEventType.MouseMoveBy: - if (macroEvent.Time - currentMerge.Time > MergedEventTimeMax) - { - mergedMacroEvents.Add(currentMerge); - currentMerge = macroEvent; - break; - } - // 相对位移量相加 - currentMerge.MouseX += macroEvent.MouseX; - currentMerge.MouseY += macroEvent.MouseY; - if (macroEvent.CameraOrientation != null) - { - currentMerge.CameraOrientation = macroEvent.CameraOrientation; - } - break; - - default: - mergedMacroEvents.Add(currentMerge); - mergedMacroEvents.Add(macroEvent); - currentMerge = null; - break; - } - } + // var mergedMacroEvents = new List(); + // MacroEvent? currentMerge = null; + // foreach (var macroEvent in MacroEvents) + // { + // if (currentMerge == null) + // { + // currentMerge = macroEvent; + // continue; + // } + // if (currentMerge.Type != macroEvent.Type) + // { + // mergedMacroEvents.Add(currentMerge); + // currentMerge = macroEvent; + // continue; + // } + // switch (macroEvent.Type) + // { + // case MacroEventType.MouseMoveTo: + // // 控制合并时间片段长度 + // if (macroEvent.Time - currentMerge.Time > MergedEventTimeMax) + // { + // mergedMacroEvents.Add(currentMerge); + // currentMerge = macroEvent; + // break; + // } + // // 合并为最后一个事件的位置,避免丢步 + // currentMerge.MouseX = macroEvent.MouseX; + // currentMerge.MouseY = macroEvent.MouseY; + // break; + // + // case MacroEventType.MouseMoveBy: + // if (macroEvent.Time - currentMerge.Time > MergedEventTimeMax) + // { + // mergedMacroEvents.Add(currentMerge); + // currentMerge = macroEvent; + // break; + // } + // // 相对位移量相加 + // currentMerge.MouseX += macroEvent.MouseX; + // currentMerge.MouseY += macroEvent.MouseY; + // if (macroEvent.CameraOrientation != null) + // { + // currentMerge.CameraOrientation = macroEvent.CameraOrientation; + // } + // break; + // + // default: + // mergedMacroEvents.Add(currentMerge); + // mergedMacroEvents.Add(macroEvent); + // currentMerge = null; + // break; + // } + // } KeyMouseScript keyMouseScript = new() { - MacroEvents = mergedMacroEvents, + MacroEvents = MacroEvents, + MouseMoveByMacroEvents = MouseMoveByMacroEvents, Info = new KeyMouseScriptInfo { X = rect.X, Y = rect.Y, Width = rect.Width, Height = rect.Height, - RecordDpi = TaskContext.Instance().DpiScale + RecordDpi = TaskContext.Instance().DpiScale, + StartTime = $"{StartTime:yyyy-MM-dd HH:mm:ss:ffff}", + StartTimeUnixTimestamp = (StartTime - new DateTime(1970, 1, 1)).TotalNanoseconds.ToString("F0") } }; return JsonSerializer.Serialize(keyMouseScript, JsonOptions); @@ -174,22 +178,21 @@ public class KeyMouseRecorder public void MouseMoveBy(MouseState state) { var now = DateTime.UtcNow; - int? cao = null; - if (TaskContext.Instance().Config.RecordConfig.IsRecordCameraOrientation) - { - if ((now - LastOrientationDetection).TotalMilliseconds > 100.0) - { - LastOrientationDetection = now; - cao = (int)Math.Round(CameraOrientation.Compute(TaskControl.CaptureToRectArea().SrcMat)); - } - } - MacroEvents.Add(new MacroEvent + // int? cao = null; + // if (TaskContext.Instance().Config.RecordConfig.IsRecordCameraOrientation) + // { + // if ((now - LastOrientationDetection).TotalMilliseconds > 100.0) + // { + // LastOrientationDetection = now; + // cao = (int)Math.Round(CameraOrientation.Compute(TaskControl.CaptureToRectArea().SrcMat)); + // } + // } + MouseMoveByMacroEvents.Add(new MacroEvent { Type = MacroEventType.MouseMoveBy, MouseX = state.X, MouseY = state.Y, Time = (now - StartTime).TotalMilliseconds, - CameraOrientation = cao, }); } } diff --git a/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScript.cs b/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScript.cs index 762da95d..eff34b25 100644 --- a/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScript.cs +++ b/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScript.cs @@ -9,6 +9,7 @@ namespace BetterGenshinImpact.Core.Recorder.Model; public class KeyMouseScript { public List MacroEvents { get; set; } = []; + public List MouseMoveByMacroEvents { get; set; } = []; public KeyMouseScriptInfo? Info { get; set; } /// diff --git a/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScriptInfo.cs b/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScriptInfo.cs index 76664910..058f08df 100644 --- a/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScriptInfo.cs +++ b/BetterGenshinImpact/Core/Recorder/Model/KeyMouseScriptInfo.cs @@ -24,4 +24,8 @@ public class KeyMouseScriptInfo public int Height { get; set; } public double RecordDpi { get; set; } = 1.0; + + public string StartTime { get; set; } = string.Empty; + + public string StartTimeUnixTimestamp { get; set; } = string.Empty; } diff --git a/BetterGenshinImpact/Core/Video/FfmpegRecorder.cs b/BetterGenshinImpact/Core/Video/FfmpegRecorder.cs new file mode 100644 index 00000000..d4ca56e3 --- /dev/null +++ b/BetterGenshinImpact/Core/Video/FfmpegRecorder.cs @@ -0,0 +1,120 @@ +using System; +using System.Diagnostics; +using System.IO; +using System.Text; +using System.Text.RegularExpressions; +using System.Threading; +using BetterGenshinImpact.Core.Config; +using BetterGenshinImpact.GameTask.Common; +using Microsoft.Extensions.Logging; +using Serilog.Core; + + +namespace BetterGenshinImpact.Core.Video; + +public class FfmpegRecorder +{ + // ffmpeg进程 + private readonly Process _process; + + // ffmpeg.exe实体文件路径 + private static readonly string FfmpegPath = Global.Absolute(@"video\bin\ffmpeg.exe"); + + private readonly string _filePath; + private string _startTime = string.Empty; + + public FfmpegRecorder() + { + if (!File.Exists(FfmpegPath)) + { + throw new Exception("ffmpeg.exe不存在"); + } + + _filePath = Global.Absolute($@"video\{DateTime.Now:yyyyMMddHH_mmssffff}.mp4"); + var processInfo = new ProcessStartInfo + { + FileName = FfmpegPath, + Arguments = $" -f gdigrab -hwaccel cuvid -show_region 1 -framerate 60 -use_wallclock_as_timestamps 1 -i title=原神 -pix_fmt yuv420p -c:v libx264 -preset ultrafast \"{_filePath}\"", + StandardInputEncoding = Encoding.UTF8, + UseShellExecute = false, + CreateNoWindow = true, + RedirectStandardInput = true, + RedirectStandardOutput = true, + RedirectStandardError = true, + // StandardOutputEncoding = Encoding.UTF8, + }; + _process = new Process { StartInfo = processInfo }; + // _process.OutputDataReceived += (sender, args) => { Debug.WriteLine(args.Data); }; + _process.ErrorDataReceived += (sender, args) => + { + Debug.WriteLine(args.Data); + if (string.IsNullOrEmpty(_startTime)) + { + if (args.Data != null && args.Data.Contains("start")) + { + string pattern = @"start:\s*(\d+\.\d+)"; + + Match match = Regex.Match(args.Data, pattern); + if (match.Success) + { + _startTime = match.Groups[1].Value; + TaskControl.Logger.LogInformation("ffmpeg录制: 视频起始时间戳 {Text}", _startTime); + } + } + } + }; + } + + + /// + /// 功能: 开始录制 + /// + public bool Start() + { + _process.Start(); + // _process.BeginOutputReadLine(); + _process.BeginErrorReadLine(); + TaskControl.Logger.LogInformation("ffmpeg录制: {Text}", "已启动"); + return true; + } + + /// + /// 功能: 停止录制 + /// + public void Stop() + { + // Kernel32.AttachConsole((uint)_process.Id); + // Kernel32.SetConsoleCtrlHandler(null, true); + // Kernel32.GenerateConsoleCtrlEvent(0, 0); + // Kernel32.FreeConsole(); + + // AttachConsole(_process.Id); + // SetConsoleCtrlHandler(IntPtr.Zero, true); + // GenerateConsoleCtrlEvent(0, 0); + // FreeConsole(); + TaskControl.Logger.LogInformation("ffmpeg录制: {Text}", "正在停止录制,请稍后..."); + _process.StandardInput.WriteLine("q"); + + if (!_process.WaitForExit(5000)) + { + _process.Kill(); + } + + _process.Close(); + _process.Dispose(); + + + Thread.Sleep(3000); + if (File.Exists(_filePath)) + { + // 重命名文件 + var newFilePath = Global.Absolute($@"video\{_startTime}.mp4"); + File.Move(_filePath, newFilePath); + TaskControl.Logger.LogInformation("ffmpeg录制: {Text}", $"录制完成"); + } + else + { + TaskControl.Logger.LogError("ffmpeg录制: {Text}", "未找到结果文件,录制失败"); + } + } +} \ No newline at end of file diff --git a/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs b/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs index 3abb6413..5396173b 100644 --- a/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs +++ b/BetterGenshinImpact/GameTask/TaskTriggerDispatcher.cs @@ -59,7 +59,7 @@ namespace BetterGenshinImpact.GameTask /// 1. 是否缓存图像 /// 2. 是否执行触发器 /// - private DispatcherCaptureModeEnum _dispatcherCacheCaptureMode = DispatcherCaptureModeEnum.NormalTrigger; + private DispatcherCaptureModeEnum _dispatcherCacheCaptureMode = DispatcherCaptureModeEnum.OnlyCacheCapture; private static readonly object _bitmapLocker = new(); private static readonly object _triggerListLocker = new(); @@ -129,7 +129,7 @@ namespace BetterGenshinImpact.GameTask public void Start(IntPtr hWnd, CaptureModes mode, int interval = 50) { // 初始化截图器 - GameCapture = GameCaptureFactory.Create(mode); + // GameCapture = GameCaptureFactory.Create(mode); // 激活窗口 保证后面能够正常获取窗口信息 SystemControl.ActivateWindow(hWnd); @@ -137,22 +137,22 @@ namespace BetterGenshinImpact.GameTask TaskContext.Instance().Init(hWnd); // 初始化触发器(一定要在任务上下文初始化完毕后使用) - _triggers = GameTaskManager.LoadInitialTriggers(); + _triggers = []; // 启动截图 - GameCapture.Start(hWnd, - new Dictionary() - { - { "useBitmapCache", TaskContext.Instance().Config.WgcUseBitmapCache }, - { "autoFixWin11BitBlt", OsVersionHelper.IsWindows11_OrGreater && TaskContext.Instance().Config.AutoFixWin11BitBlt } - } - ); + // GameCapture.Start(hWnd, + // new Dictionary() + // { + // { "useBitmapCache", TaskContext.Instance().Config.WgcUseBitmapCache }, + // { "autoFixWin11BitBlt", OsVersionHelper.IsWindows11_OrGreater && TaskContext.Instance().Config.AutoFixWin11BitBlt } + // } + // ); // 捕获模式初始化配置 - if (TaskContext.Instance().Config.CommonConfig.ScreenshotEnabled || TaskContext.Instance().Config.MacroConfig.CombatMacroEnabled) - { - _dispatcherCacheCaptureMode = DispatcherCaptureModeEnum.CacheCaptureWithTrigger; - } + // if (TaskContext.Instance().Config.CommonConfig.ScreenshotEnabled || TaskContext.Instance().Config.MacroConfig.CombatMacroEnabled) + // { + // _dispatcherCacheCaptureMode = DispatcherCaptureModeEnum.CacheCaptureWithTrigger; + // } // 启动定时器 _frameIndex = 0; @@ -211,21 +211,21 @@ namespace BetterGenshinImpact.GameTask // 检查截图器是否初始化 var maskWindow = MaskWindow.Instance(); - if (GameCapture == null || !GameCapture.IsCapturing) - { - if (!TaskContext.Instance().SystemInfo.GameProcess.HasExited) - { - _logger.LogError("截图器未初始化!"); - } - else - { - _logger.LogInformation("游戏已退出,BetterGI 自动停止截图器"); - } - - UiTaskStopTickEvent?.Invoke(sender, e); - maskWindow.Invoke(maskWindow.Hide); - return; - } + // if (GameCapture == null || !GameCapture.IsCapturing) + // { + // if (!TaskContext.Instance().SystemInfo.GameProcess.HasExited) + // { + // _logger.LogError("截图器未初始化!"); + // } + // else + // { + // _logger.LogInformation("游戏已退出,BetterGI 自动停止截图器"); + // } + // + // UiTaskStopTickEvent?.Invoke(sender, e); + // maskWindow.Invoke(maskWindow.Hide); + // return; + // } // 检查游戏是否在前台 var hasBackgroundTriggerToRun = false; @@ -303,60 +303,60 @@ namespace BetterGenshinImpact.GameTask } // 帧序号自增 1分钟后归零(MaxFrameIndexSecond) - _frameIndex = (_frameIndex + 1) % (int)(CaptureContent.MaxFrameIndexSecond * 1000d / _timer.Interval); - - if (_dispatcherCacheCaptureMode == DispatcherCaptureModeEnum.NormalTrigger - && (_triggers == null || !_triggers.Exists(t => t.IsEnabled))) - { - // Debug.WriteLine("没有可用的触发器且不处于仅截屏状态, 不再进行截屏"); - return; - } - - var speedTimer = new SpeedTimer(); - // 捕获游戏画面 - var bitmap = GameCapture.Capture(); - speedTimer.Record("截图"); - - if (bitmap == null) - { - _logger.LogWarning("截图失败!"); - return; - } - - if (IsOnlyCacheCapture(bitmap)) - { - return; - } - - // 循环执行所有触发器 有独占状态的触发器的时候只执行独占触发器 - var content = new CaptureContent(bitmap, _frameIndex, _timer.Interval); - - lock (_triggerListLocker) - { - var exclusiveTrigger = _triggers!.FirstOrDefault(t => t is { IsEnabled: true, IsExclusive: true }); - if (exclusiveTrigger != null) - { - exclusiveTrigger.OnCapture(content); - speedTimer.Record(exclusiveTrigger.Name); - } - else - { - var runningTriggers = _triggers!.Where(t => t.IsEnabled); - if (hasBackgroundTriggerToRun) - { - runningTriggers = runningTriggers.Where(t => t.IsBackgroundRunning); - } - - foreach (var trigger in runningTriggers) - { - trigger.OnCapture(content); - speedTimer.Record(trigger.Name); - } - } - } - - speedTimer.DebugPrint(); - content.Dispose(); + // _frameIndex = (_frameIndex + 1) % (int)(CaptureContent.MaxFrameIndexSecond * 1000d / _timer.Interval); + // + // if (_dispatcherCacheCaptureMode == DispatcherCaptureModeEnum.NormalTrigger + // && (_triggers == null || !_triggers.Exists(t => t.IsEnabled))) + // { + // // Debug.WriteLine("没有可用的触发器且不处于仅截屏状态, 不再进行截屏"); + // return; + // } + // + // var speedTimer = new SpeedTimer(); + // // 捕获游戏画面 + // var bitmap = GameCapture.Capture(); + // speedTimer.Record("截图"); + // + // if (bitmap == null) + // { + // _logger.LogWarning("截图失败!"); + // return; + // } + // + // if (IsOnlyCacheCapture(bitmap)) + // { + // return; + // } + // + // // 循环执行所有触发器 有独占状态的触发器的时候只执行独占触发器 + // var content = new CaptureContent(bitmap, _frameIndex, _timer.Interval); + // + // lock (_triggerListLocker) + // { + // var exclusiveTrigger = _triggers!.FirstOrDefault(t => t is { IsEnabled: true, IsExclusive: true }); + // if (exclusiveTrigger != null) + // { + // exclusiveTrigger.OnCapture(content); + // speedTimer.Record(exclusiveTrigger.Name); + // } + // else + // { + // var runningTriggers = _triggers!.Where(t => t.IsEnabled); + // if (hasBackgroundTriggerToRun) + // { + // runningTriggers = runningTriggers.Where(t => t.IsBackgroundRunning); + // } + // + // foreach (var trigger in runningTriggers) + // { + // trigger.OnCapture(content); + // speedTimer.Record(trigger.Name); + // } + // } + // } + // + // speedTimer.DebugPrint(); + // content.Dispose(); } finally { diff --git a/BetterGenshinImpact/View/MainWindow.xaml b/BetterGenshinImpact/View/MainWindow.xaml index 635bd9cb..6a3b2b3e 100644 --- a/BetterGenshinImpact/View/MainWindow.xaml +++ b/BetterGenshinImpact/View/MainWindow.xaml @@ -58,7 +58,16 @@ + + + + + + + + ~1~@1@ - - + ~1~@1@ + ~1~ ConvertRange20 @1@ @@ -99,7 +108,7 @@ - + ~1~ WebAsset24 | DocumentJs16 | Script16 @1@ @@ -107,7 +116,7 @@ - + ~1~ Map24 @1@ @@ -115,7 +124,7 @@ - + ~1~ Script16 @1@ @@ -132,7 +141,7 @@ - + --> - - + Text="通知设置" />--> - @@ -523,7 +523,7 @@ TextWrapping="Wrap" /> - + --> _logger; private readonly IConfigService _configService; - public string Title => $"BetterGI · 更好的原神 · {Global.Version}{(RuntimeHelper.IsDebug ? " · Dev" : string.Empty)}"; + public string Title => $"BetterGI · 更好的原神 · 采集版 · {Global.Version}{(RuntimeHelper.IsDebug ? " · Dev" : string.Empty)}"; [ObservableProperty] public bool _isVisible = true; @@ -69,46 +69,46 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel [SuppressMessage("CommunityToolkit.Mvvm.SourceGenerators.RelayCommandGenerator", "MVVMTK0039:Async void returning method annotated with RelayCommand")] private async void OnLoaded() { - try - { - await Task.Run(() => - { - try - { - var s = OcrFactory.Paddle.Ocr(new Mat(Global.Absolute(@"Assets\Model\PaddleOCR\test_ocr.png"), ImreadModes.Grayscale)); - Debug.WriteLine("PaddleOcr预热结果:" + s); - } - catch (Exception e) - { - Console.WriteLine(e); - _logger.LogError("PaddleOcr预热异常,解决方案:https://bgi.huiyadan.com/faq.html:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); - var innerException = e.InnerException; - if (innerException != null) - { - _logger.LogError("PaddleOcr预热内部异常,解决方案:https://bgi.huiyadan.com/faq.html:" + innerException.Source + "\r\n--" + Environment.NewLine + innerException.StackTrace + "\r\n---" + Environment.NewLine + innerException.Message); - throw innerException; - } - else - { - throw; - } - } - }); - } - catch (Exception e) - { - MessageBox.Warning("PaddleOcr预热失败,解决方案:https://bgi.huiyadan.com/faq.html," + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); - } - - try - { - await Task.Run(GetNewestInfoAsync); - } - catch (Exception e) - { - Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); - _logger.LogWarning("获取 BetterGI 最新版本信息失败"); - } + // try + // { + // await Task.Run(() => + // { + // try + // { + // var s = OcrFactory.Paddle.Ocr(new Mat(Global.Absolute(@"Assets\Model\PaddleOCR\test_ocr.png"), ImreadModes.Grayscale)); + // Debug.WriteLine("PaddleOcr预热结果:" + s); + // } + // catch (Exception e) + // { + // Console.WriteLine(e); + // _logger.LogError("PaddleOcr预热异常,解决方案:https://bgi.huiyadan.com/faq.html:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); + // var innerException = e.InnerException; + // if (innerException != null) + // { + // _logger.LogError("PaddleOcr预热内部异常,解决方案:https://bgi.huiyadan.com/faq.html:" + innerException.Source + "\r\n--" + Environment.NewLine + innerException.StackTrace + "\r\n---" + Environment.NewLine + innerException.Message); + // throw innerException; + // } + // else + // { + // throw; + // } + // } + // }); + // } + // catch (Exception e) + // { + // MessageBox.Warning("PaddleOcr预热失败,解决方案:https://bgi.huiyadan.com/faq.html," + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); + // } + // + // try + // { + // await Task.Run(GetNewestInfoAsync); + // } + // catch (Exception e) + // { + // Debug.WriteLine("获取最新版本信息失败:" + e.Source + "\r\n--" + Environment.NewLine + e.StackTrace + "\r\n---" + Environment.NewLine + e.Message); + // _logger.LogWarning("获取 BetterGI 最新版本信息失败"); + // } // Win11下 BitBlt截图方式不可用,需要关闭窗口优化功能 if (OsVersionHelper.IsWindows11_OrGreater && TaskContext.Instance().Config.AutoFixWin11BitBlt) @@ -117,7 +117,7 @@ public partial class MainWindowViewModel : ObservableObject, IViewModel } // 更新仓库 - ScriptRepoUpdater.Instance.AutoUpdate(); + // ScriptRepoUpdater.Instance.AutoUpdate(); } private async Task GetNewestInfoAsync() diff --git a/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs b/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs index 767c0ac2..af805155 100644 --- a/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs +++ b/BetterGenshinImpact/ViewModel/Pages/HotKeyPageViewModel.cs @@ -28,6 +28,7 @@ using System.Diagnostics; using System.Reflection; using System.Threading; using System.Threading.Tasks; +using BetterGenshinImpact.Core.Video; using BetterGenshinImpact.GameTask.Model.Area; using Vanara.PInvoke; using HotKeySettingModel = BetterGenshinImpact.Model.HotKeySettingModel; @@ -182,20 +183,20 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel ); HotKeySettingModels.Add(systemDirectory); - var timerDirectory = new HotKeySettingModel( - "实时任务" - ); - HotKeySettingModels.Add(timerDirectory); - - var soloTaskDirectory = new HotKeySettingModel( - "独立任务" - ); - HotKeySettingModels.Add(soloTaskDirectory); - - var macroDirectory = new HotKeySettingModel( - "操控辅助" - ); - HotKeySettingModels.Add(macroDirectory); + // var timerDirectory = new HotKeySettingModel( + // "实时任务" + // ); + // HotKeySettingModels.Add(timerDirectory); + // + // var soloTaskDirectory = new HotKeySettingModel( + // "独立任务" + // ); + // HotKeySettingModels.Add(soloTaskDirectory); + // + // var macroDirectory = new HotKeySettingModel( + // "操控辅助" + // ); + // HotKeySettingModels.Add(macroDirectory); var devDirectory = new HotKeySettingModel( "开发者" @@ -233,7 +234,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel } )); - var autoPickEnabledHotKeySettingModel = new HotKeySettingModel( + /*var autoPickEnabledHotKeySettingModel = new HotKeySettingModel( "自动拾取开关", nameof(Config.HotKeyConfig.AutoPickEnabledHotkey), Config.HotKeyConfig.AutoPickEnabledHotkey, @@ -424,7 +425,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel { OnKeyDownAction = (_, _) => { OneKeyFightTask.Instance.KeyDown(); }, OnKeyUpAction = (_, _) => { OneKeyFightTask.Instance.KeyUp(); } - }); + });*/ devDirectory.Children.Add(new HotKeySettingModel( "启动/停止键鼠录制", @@ -451,6 +452,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel } )); + /* devDirectory.Children.Add(new HotKeySettingModel( "(开发)获取当前大地图中心点位置", nameof(Config.HotKeyConfig.RecBigMapPosHotkey), @@ -499,6 +501,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel } } )); + */ // DEBUG if (RuntimeHelper.IsDebug) @@ -508,13 +511,13 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel ); HotKeySettingModels.Add(debugDirectory); - soloTaskDirectory.Children.Add(new HotKeySettingModel( - "启动/停止自动活动音游", - nameof(Config.HotKeyConfig.AutoMusicGameHotkey), - Config.HotKeyConfig.AutoMusicGameHotkey, - Config.HotKeyConfig.AutoMusicGameHotkeyType, - (_, _) => { SwitchSoloTask(_taskSettingsPageViewModel.SwitchAutoMusicGameCommand); } - )); + // soloTaskDirectory.Children.Add(new HotKeySettingModel( + // "启动/停止自动活动音游", + // nameof(Config.HotKeyConfig.AutoMusicGameHotkey), + // Config.HotKeyConfig.AutoMusicGameHotkey, + // Config.HotKeyConfig.AutoMusicGameHotkeyType, + // (_, _) => { SwitchSoloTask(_taskSettingsPageViewModel.SwitchAutoMusicGameCommand); } + // )); // HotKeySettingModels.Add(new HotKeySettingModel( // "(测试)启动/停止自动追踪", // nameof(Config.HotKeyConfig.AutoTrackHotkey), @@ -544,6 +547,8 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel // // _taskSettingsPageViewModel.OnSwitchAutoTrackPath(); // } // )); + + FfmpegRecorder ffmpegRecorder = new FfmpegRecorder(); debugDirectory.Children.Add(new HotKeySettingModel( "(测试)测试", nameof(Config.HotKeyConfig.Test1Hotkey), @@ -574,14 +579,8 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel // 拾取物品 // Task.Run(async () => { await new ScanPickTask().Start(new CancellationToken()); }); - - Simulation.SendInput.Keyboard.KeyDown(false, User32.VK.VK_LMENU); - // TaskContext.Instance().PostMessageSimulator.KeyDown(User32.VK.VK_MENU); - Thread.Sleep(500); - GameCaptureRegion.GameRegion1080PPosMove(200, 100); - Thread.Sleep(500); - // TaskContext.Instance().PostMessageSimulator.KeyUp(User32.VK.VK_MENU); - Simulation.SendInput.Keyboard.KeyUp(false, User32.VK.VK_LMENU); + + ffmpegRecorder.Start(); } )); debugDirectory.Children.Add(new HotKeySettingModel( @@ -591,8 +590,9 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel Config.HotKeyConfig.Test2HotkeyType, (_, _) => { - GoToCraftingBenchTask goToCraftingBenchTask = new GoToCraftingBenchTask(); - Task.Run(async () => { await goToCraftingBenchTask.Start("璃月", new CancellationToken()); }); + // GoToCraftingBenchTask goToCraftingBenchTask = new GoToCraftingBenchTask(); + // Task.Run(async () => { await goToCraftingBenchTask.Start("璃月", new CancellationToken()); }); + ffmpegRecorder.Stop(); } )); diff --git a/Build/setup_build_for_train.cmd b/Build/setup_build_for_train.cmd new file mode 100644 index 00000000..bf035c3d --- /dev/null +++ b/Build/setup_build_for_train.cmd @@ -0,0 +1,64 @@ +cd /d %~dp0 +if exist dist rd /s /q dist +mkdir dist\BetterGI + +@echo [prepare compiler] +for /f "usebackq tokens=*" %%i in (`"%ProgramFiles(x86)%\Microsoft Visual Studio\Installer\vswhere.exe" -latest -property installationPath`) do set "path=%path%;%%i\MSBuild\Current\Bin;%%i\Common7\IDE" + +@echo [prepare version] +cd /d ..\BetterGenshinImpact +set "script=Get-Content 'BetterGenshinImpact.csproj' | Select-String -Pattern 'AssemblyVersion\>(.*)\<\/AssemblyVersion' | ForEach-Object { $_.Matches.Groups[1].Value }" +for /f "usebackq delims=" %%i in (`powershell -NoLogo -NoProfile -Command "%script%"`) do set version=%%i +echo current version is %version% +if "%b%"=="" ( set "b=%version%" ) + +set "tmpfolder=%~dp0dist\BetterGI" +set "archiveFile=BetterGI_T_v%b%.7z" +set "setupFile=BetterGI_T_Setup_v%b%.exe" + +echo [build app using vs2022] +cd /d %~dp0 +rd /s /q ..\BetterGenshinImpact\bin\x64\Release\net8.0-windows10.0.22621.0\publish\win-x64\ +cd ..\ +dotnet publish -c Release -p:PublishProfile=FolderProfile + +echo [pack app using 7z] +cd /d %~dp0 +cd /d ..\BetterGenshinImpact\bin\x64\Release\net8.0-windows10.0.22621.0\publish\win-x64\ +xcopy * "%tmpfolder%" /E /C /I /Y +cd /d %~dp0 +del /f /q %tmpfolder%\*.lib +del /f /q %tmpfolder%\*ffmpeg*.dll + +:: һЩѵ汾Ҫ +del /f /q %tmpfolder%\onnxruntime*.dll +del /f /q %tmpfolder%\paddle*.dll +rd /s /q %tmpfolder%\Assets\Model + + + +:: һЩļʼļʺϷGithub +if exist "E:\HuiTask\BetterGIBuild\BetterGI_train" ( + xcopy "E:\HuiTask\BetterGIBuild\BetterGI_train\*" "%tmpfolder%" /E /C /I /Y +) +:: һЩļ + +MicaSetup.Tools\7-Zip\7z a publish.7z %tmpfolder%\ -t7z -mx=5 -mf=BCJ2 -r -y +copy /y publish.7z .\MicaSetup\Resources\Setups\publish.7z +if exist "%zipFile%" ( del /f /q "%zipfile%" ) +rename publish.7z %archiveFile% + +@echo [build uninst using vs2022] +msbuild MicaSetup\MicaSetup.Uninst.csproj /t:Rebuild /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=FolderProfile /restore + +@echo [build setup using vs2022] +copy /y .\MicaSetup\bin\Release\net472\MicaSetup.exe .\MicaSetup\Resources\Setups\Uninst.exe +msbuild MicaSetup\MicaSetup.csproj /t:Build /p:Configuration=Release /p:DeployOnBuild=true /p:PublishProfile=FolderProfile /restore + +@echo [finish] +del /f /q MicaSetup.exe +copy /y .\MicaSetup\bin\Release\net472\MicaSetup.exe .\ +rename MicaSetup.exe %setupFile% +rd /s /q dist\BetterGI + +@pause