integrated recording and playback

This commit is contained in:
辉鸭蛋
2024-06-27 00:00:49 +08:00
parent 84465d866f
commit 083fdd435f
6 changed files with 98 additions and 30 deletions

View File

@@ -7,7 +7,7 @@ using System.Threading.Tasks;
namespace BetterGenshinImpact.Core.Monitor;
public class DirectInputMonitor
public class DirectInputMonitor : IDisposable
{
private bool _isRunning = true;
@@ -36,7 +36,7 @@ public class DirectInputMonitor
MouseState state = _mouse.GetCurrentState();
// Debug.WriteLine($"{state.X} {state.Y} {state.Buttons[0]} {state.Buttons[1]}");
GlobalKeyMouseRecord.Instance.GlobalHookMouseMoveBy(state);
Thread.Sleep(10); // 10ms, equivalent to CLOCKS_PER_SEC/100
Thread.Sleep(5); // 10ms, equivalent to CLOCKS_PER_SEC/100
}
});
}
@@ -45,4 +45,9 @@ public class DirectInputMonitor
{
_isRunning = false;
}
public void Dispose()
{
_mouse.Dispose();
}
}

View File

@@ -21,6 +21,7 @@ namespace BetterGenshinImpact.Core.Recorder;
/// <summary>
/// DirectInput、鼠标移动距离、视角度数之间的校准
/// </summary>
[Obsolete]
public class DirectInputCalibration
{
// 视角偏移移动单位

View File

@@ -1,30 +1,49 @@
using System.Collections.Generic;
using System.Diagnostics;
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 System.Windows.Forms;
using BetterGenshinImpact.GameTask;
using BetterGenshinImpact.GameTask.Model.Area;
using OpenCvSharp;
using Microsoft.Extensions.Logging;
using SharpDX.DirectInput;
using System;
using System.Collections.Generic;
using System.Windows.Forms;
namespace BetterGenshinImpact.Core.Recorder;
public class GlobalKeyMouseRecord : Singleton<GlobalKeyMouseRecord>
{
private readonly ILogger<GlobalKeyMouseRecord> _logger = App.GetLogger<GlobalKeyMouseRecord>();
private KeyMouseRecorder? _recorder;
private readonly Dictionary<Keys, bool> _keyDownState = new();
// private Rect _captureAreaCenterRect;
private DirectInputMonitor? _directInputMonitor;
private readonly System.Timers.Timer _timer = new();
private bool _isInMainUi = false; // 是否在主界面
public GlobalKeyMouseRecord()
{
_timer.Elapsed += Tick;
_timer.Interval = 50; // ms
}
public KeyMouseRecorder StartRecord()
{
_recorder = new KeyMouseRecorder();
TaskTriggerDispatcher.Instance().StopTimer();
_timer.Start();
_recorder = new KeyMouseRecorder();
_directInputMonitor = new DirectInputMonitor();
_directInputMonitor.Start();
_logger.LogInformation("录制:{Text}", "实时任务已暂停,录制已启动");
_logger.LogInformation("注意:录制时遇到主界面(鼠标永远在界面中心)和其他界面(鼠标可自由移动,比如地图等)的切换,请把手离开鼠标等待录制模式切换日志");
// var rect = TaskContext.Instance().SystemInfo.CaptureAreaRect;
// var centerPoint = new Point(rect.X + rect.Width / 2, rect.Y + rect.Height / 2);
// _captureAreaCenterRect = new Rect(centerPoint.X - 10, centerPoint.Y - 15, 20, 20);
return _recorder;
}
@@ -32,11 +51,39 @@ public class GlobalKeyMouseRecord : Singleton<GlobalKeyMouseRecord>
{
var macro = _recorder?.ToJsonMacro() ?? string.Empty;
_recorder = null;
_directInputMonitor?.Stop();
_directInputMonitor?.Dispose();
_directInputMonitor = null;
_timer.Stop();
_logger.LogInformation("录制:{Text}", "结束录制");
TaskTriggerDispatcher.Instance().StartTimer();
return macro;
}
public void Tick(object? sender, EventArgs e)
{
var ra = TaskControl.CaptureToRectArea();
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(KeyEventArgs e)
{
if (e.KeyCode.ToString() == TaskContext.Instance().Config.HotKeyConfig.Test1Hotkey)
{
return;
}
if (_keyDownState.TryGetValue(e.KeyCode, out var v))
{
if (v)
@@ -52,15 +99,20 @@ public class GlobalKeyMouseRecord : Singleton<GlobalKeyMouseRecord>
{
_keyDownState.Add(e.KeyCode, true);
}
Debug.WriteLine($"KeyDown: {e.KeyCode}");
// Debug.WriteLine($"KeyDown: {e.KeyCode}");
_recorder?.KeyDown(e);
}
public void GlobalHookKeyUp(KeyEventArgs e)
{
if (e.KeyCode.ToString() == TaskContext.Instance().Config.HotKeyConfig.Test1Hotkey)
{
return;
}
if (_keyDownState.ContainsKey(e.KeyCode) && _keyDownState[e.KeyCode])
{
Debug.WriteLine($"KeyUp: {e.KeyCode}");
// Debug.WriteLine($"KeyUp: {e.KeyCode}");
_keyDownState[e.KeyCode] = false;
_recorder?.KeyUp(e);
}
@@ -80,21 +132,21 @@ public class GlobalKeyMouseRecord : Singleton<GlobalKeyMouseRecord>
public void GlobalHookMouseMoveTo(MouseEventExtArgs e)
{
// if (_captureAreaCenterRect.Contains(e.X, e.Y))
// {
// return;
// }
if (_isInMainUi)
{
return;
}
// Debug.WriteLine($"MouseMove: {e.X}, {e.Y}");
// _recorder?.MouseMoveTo(e);
_recorder?.MouseMoveTo(e);
}
public void GlobalHookMouseMoveBy(MouseState state)
{
// Debug.WriteLine($"MouseMoveBy: {state.X}, {state.Y}");
if (state is { X: 0, Y: 0 })
if (state is { X: 0, Y: 0 } || !_isInMainUi)
{
return;
}
// Debug.WriteLine($"MouseMoveBy: {state.X}, {state.Y}");
_recorder?.MouseMoveBy(state);
}
}

Binary file not shown.

After

Width:  |  Height:  |  Size: 805 B

View File

@@ -21,6 +21,8 @@ public class ElementAssets : BaseAssets<ElementAssets>
public RecognitionObject SpaceKey;
public RecognitionObject XKey;
public RecognitionObject FriendChat;
private ElementAssets()
{
// 按钮
@@ -116,5 +118,15 @@ public class ElementAssets : BaseAssets<ElementAssets>
RegionOfInterest = new Rect(CaptureRect.Width - (int)(210 * AssetScale), CaptureRect.Height - (int)(70 * AssetScale), (int)(60 * AssetScale), (int)(70 * AssetScale)),
DrawOnWindow = false
}.InitTemplate();
// 左下角的好友聊天icon
FriendChat = new RecognitionObject
{
Name = "FriendChat",
RecognitionType = RecognitionTypes.TemplateMatch,
TemplateImageMat = GameTaskManager.LoadAssetImage(@"Common\Element", "friend_chat.png"),
RegionOfInterest = new Rect(0, CaptureRect.Height - (int)(70 * AssetScale), (int)(83 * AssetScale), (int)(70 * AssetScale)),
DrawOnWindow = false
}.InitTemplate();
}
}

View File

@@ -419,26 +419,23 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel
//
// if (GetGUIThreadInfo(threadid, ref lpgui))
// {
// if (lpgui.hwndCaret != 0)
// {
// _logger.LogInformation("输入状态");
// return;
// }
// if (lpgui.hwndCaret != 0)
// {
// _logger.LogInformation("输入状态");
// return;
// }
// }
// _logger.LogInformation("非输入状态");
if (!flag)
{
GlobalKeyMouseRecord.Instance.StartRecord();
new DirectInputMonitor().Start();
_logger.LogInformation("开始录制脚本");
flag = true;
}
else
{
m = GlobalKeyMouseRecord.Instance.StopRecord();
Debug.WriteLine("录制脚本结束:" + m);
_logger.LogInformation("录制脚本结束");
flag = false;
}
}
@@ -451,6 +448,7 @@ public partial class HotKeyPageViewModel : ObservableObject, IViewModel
Config.HotKeyConfig.Test2HotkeyType,
(_, _) =>
{
_logger.LogInformation("开始重放脚本");
Task.Run(async () =>
{
await KeyMouseMacroPlayer.PlayMacro(m);