mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-04-02 10:45:22 +08:00
integrated recording and playback
This commit is contained in:
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -21,6 +21,7 @@ namespace BetterGenshinImpact.Core.Recorder;
|
||||
/// <summary>
|
||||
/// DirectInput、鼠标移动距离、视角度数之间的校准
|
||||
/// </summary>
|
||||
[Obsolete]
|
||||
public class DirectInputCalibration
|
||||
{
|
||||
// 视角偏移移动单位
|
||||
|
||||
@@ -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 |
@@ -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();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
Reference in New Issue
Block a user