Files
better-genshin-impact/BetterGenshinImpact/Core/Recorder/GlobalKeyMouseRecord.cs
2025-01-05 02:38:41 +08:00

289 lines
8.2 KiB
C#
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
using BetterGenshinImpact.Core.Monitor;
using BetterGenshinImpact.GameTask;
using BetterGenshinImpact.GameTask.Common;
using BetterGenshinImpact.GameTask.Common.Element.Assets;
using BetterGenshinImpact.Model;
using Gma.System.MouseKeyHook;
using Microsoft.Extensions.Logging;
using SharpDX.DirectInput;
using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Threading.Tasks;
using System.Windows.Forms;
using BetterGenshinImpact.Core.Config;
using BetterGenshinImpact.Core.Video;
using BetterGenshinImpact.Core.Video.obs;
using NAudio.Wave;
using SharpAvi;
using Vanara.PInvoke;
using Wpf.Ui.Violeta.Controls;
namespace BetterGenshinImpact.Core.Recorder;
public class GlobalKeyMouseRecord : Singleton<GlobalKeyMouseRecord>
{
private readonly ILogger<GlobalKeyMouseRecord> _logger = App.GetLogger<GlobalKeyMouseRecord>();
private KeyMouseRecorderJsonLine? _recorder;
// private SharpAviRecorder _sharpAviRecorder;
private IVideoRecorder? _videoRecorder;
private readonly Dictionary<Keys, bool> _keyDownState = [];
private DirectInputMonitor? _directInputMonitor;
private readonly System.Timers.Timer _timer = new();
private bool _isInMainUi = false; // 是否在主界面
private bool _paimonSwitchEnabled = false; // 是否启用派蒙切换
// private string _keyMouseMacroRecordHotkey = "";
public KeyMouseRecorderStatus Status { get; set; } = KeyMouseRecorderStatus.Stop;
public GlobalKeyMouseRecord()
{
_timer.Elapsed += Tick;
_timer.Interval = 50; // ms
}
public async Task StartRecord(string fileName)
{
if (!TaskContext.Instance().IsInitialized)
{
Toast.Warning("请先在启动页,启动截图器再使用本功能");
return;
}
if (Status != KeyMouseRecorderStatus.Stop)
{
Toast.Warning("已经在录制状态,请不要重复启动录制功能");
return;
}
// _keyMouseMacroRecordHotkey = TaskContext.Instance().Config.HotKeyConfig.KeyMouseMacroRecordHotkey;
_paimonSwitchEnabled = TaskContext.Instance().Config.RecordConfig.PaimonSwitchEnabled;
Status = KeyMouseRecorderStatus.Start;
SystemControl.ActivateWindow();
// _logger.LogInformation("录制:{Text}", "实时任务已暂停");
// _logger.LogInformation("注意:录制时遇到主界面(鼠标永远在界面中心)和其他界面(鼠标可自由移动,比如地图等)的切换,请把手离开鼠标等待录制模式切换日志");
// 先实例化
// _sharpAviRecorder = new SharpAviRecorder( Path.Combine(videoPath, $"{DateTime.Now:yyyyMMddHH_mmssffff.avi}"),
// CodecIds.MotionJpeg, 90, 0, SupportedWaveFormat.WAVE_FORMAT_44M16, false, 0);
_videoRecorder = VideoRecorderFactory.Create(TaskContext.Instance().Config.CommonConfig.Recorder, fileName);
_directInputMonitor = new DirectInputMonitor();
var recorderTmp = new KeyMouseRecorderJsonLine(fileName);
// TaskTriggerDispatcher.Instance().StopTimer();
// for (var i = 3; i >= 1; i--)
// {
// _logger.LogInformation("{Sec}秒后启动录制...", i);
// await Task.Delay(1000);
// }
if (_paimonSwitchEnabled)
{
_timer.Start();
}
var tmpTime = DateTime.Now;
var sw = new Stopwatch();
sw.Start();
long current;
_directInputMonitor.Start();
_logger.LogInformation("从开始到directInput启动累计耗时ms{Text}", sw.ElapsedMilliseconds);
var videoEnabled = _videoRecorder.Start();
_logger.LogInformation("从开始到视频录制启动累计耗时OBS是WS通知完成耗时并非实际录制时间ms{Text}", sw.ElapsedMilliseconds);
_recorder = recorderTmp.Start();
_recorder.AppendStartInfo();
_logger.LogInformation("从开始到键鼠录制启动累计耗时ms{Text}", sw.ElapsedMilliseconds);
sw.Stop();
ObsLogFileProcessor.FindStartTime(fileName, tmpTime);
Status = KeyMouseRecorderStatus.Recording;
_logger.LogInformation("录制:{Text}", "已启动");
}
public void StopRecord()
{
if (Status != KeyMouseRecorderStatus.Recording)
{
throw new InvalidOperationException("未处于录制中状态,无法停止");
}
var sw = new Stopwatch();
sw.Start();
// var macro = _recorder?.ToJsonMacro() ?? string.Empty;
_recorder = null;
_directInputMonitor?.Stop();
_directInputMonitor?.Dispose();
_directInputMonitor = null;
_logger.LogInformation("从结束触发到键鼠录制关闭累计耗时ms{Text}", sw.ElapsedMilliseconds);
_videoRecorder?.Stop();
_logger.LogInformation("从结束触发到视频录制关闭累计耗时ms{Text}", sw.ElapsedMilliseconds);
if (_timer.Enabled)
{
_timer.Stop();
}
_logger.LogInformation("录制:{Text}", "结束录制");
// TaskTriggerDispatcher.Instance().StartTimer();
Status = KeyMouseRecorderStatus.Stop;
// return macro;
}
public void Tick(object? sender, EventArgs e)
{
var ra = TaskControl.CaptureToRectArea(true);
var iconRa = ra.Find(ElementAssets.Instance.FriendChat);
var exist = iconRa.IsExist();
if (exist != _isInMainUi)
{
_logger.LogInformation("录制:{Text}", exist ? "进入主界面,捕获鼠标相对移动" : "离开主界面,捕获鼠标绝对移动");
}
_isInMainUi = exist;
iconRa.Dispose();
ra.Dispose();
}
public void GlobalHookKeyDown(KeyEventArgsExt e)
{
// 排除热键
// if (e.KeyCode.ToString() == _keyMouseMacroRecordHotkey)
// {
// return;
// }
if (_keyDownState.TryGetValue(e.KeyCode, out var v))
{
if (v)
{
return; // 处于按下状态的不再记录
}
else
{
_keyDownState[e.KeyCode] = true;
}
}
else
{
_keyDownState.Add(e.KeyCode, true);
}
// Debug.WriteLine($"KeyDown: {e.KeyCode}");
_recorder?.KeyDown(e);
}
public void GlobalHookKeyUp(KeyEventArgsExt e)
{
if (_keyDownState.TryGetValue(e.KeyCode, out bool state) && state)
{
// Debug.WriteLine($"KeyUp: {e.KeyCode}");
_keyDownState[e.KeyCode] = false;
_recorder?.KeyUp(e);
}
}
public void GlobalHookMouseDown(MouseEventExtArgs e)
{
// Debug.WriteLine($"MouseDown: {e.Button}");
_recorder?.MouseDown(e);
}
public void GlobalHookMouseUp(MouseEventExtArgs e)
{
// Debug.WriteLine($"MouseUp: {e.Button}");
_recorder?.MouseUp(e);
}
public void GlobalHookMouseMoveTo(MouseEventExtArgs e)
{
// Debug.WriteLine($"MouseMove: {e.X}, {e.Y}");
if (_paimonSwitchEnabled)
{
if (_isInMainUi)
{
_recorder?.MouseMoveTo(e, false);
}
else
{
_recorder?.MouseMoveTo(e, true);
}
}
else
{
_recorder?.MouseMoveTo(e, false);
}
}
public void GlobalHookMouseWheel(MouseEventExtArgs e)
{
// Debug.WriteLine($"MouseWheel: {e.Delta}");
_recorder?.MouseWheel(e);
}
public void GlobalHookMouseMoveBy(MouseState state)
{
// Debug.WriteLine($"MouseMoveBy: {state.X}, {state.Y}");
if (state is { X: 0, Y: 0 })
{
return;
}
var tick = Kernel32.GetTickCount();
if (_paimonSwitchEnabled)
{
if (!_isInMainUi)
{
_recorder?.MouseMoveBy(state, tick, false);
}
else
{
_recorder?.MouseMoveBy(state, tick, true);
}
}
else
{
_recorder?.MouseMoveBy(state, tick, true);
}
}
}
public enum KeyMouseRecorderStatus
{
Start,
Recording,
Stop
}