mirror of
https://github.com/babalae/better-genshin-impact.git
synced 2026-04-04 11:15:18 +08:00
378 lines
11 KiB
C#
378 lines
11 KiB
C#
using BetterGenshinImpact.GameTask.Model.Area.Converter;
|
|
using BetterGenshinImpact.View.Drawable;
|
|
using Fischless.WindowsInput;
|
|
using OpenCvSharp;
|
|
using System;
|
|
using System.Diagnostics;
|
|
using System.Drawing;
|
|
using System.Threading;
|
|
using BetterGenshinImpact.GameTask.Common;
|
|
using Vanara.PInvoke;
|
|
|
|
namespace BetterGenshinImpact.GameTask.Model.Area;
|
|
|
|
/// <summary>
|
|
/// 区域基类
|
|
/// 用于描述一个区域,可以是一个矩形,也可以是一个点
|
|
/// </summary>
|
|
public class Region : IDisposable
|
|
{
|
|
public int X { get; set; }
|
|
public int Y { get; set; }
|
|
public int Width { get; set; }
|
|
public int Height { get; set; }
|
|
|
|
public int Top
|
|
{
|
|
get => Y;
|
|
set => Y = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the y-coordinate that is the sum of the Y and Height property values of this Rect structure.
|
|
/// </summary>
|
|
public int Bottom => Y + Height;
|
|
|
|
/// <summary>
|
|
/// Gets the x-coordinate of the left edge of this Rect structure.
|
|
/// </summary>
|
|
public int Left
|
|
{
|
|
get => X;
|
|
set => X = value;
|
|
}
|
|
|
|
/// <summary>
|
|
/// Gets the x-coordinate that is the sum of X and Width property values of this Rect structure.
|
|
/// </summary>
|
|
public int Right => X + Width;
|
|
|
|
/// <summary>
|
|
/// 存放OCR识别的结果文本
|
|
/// </summary>
|
|
public string Text { get; set; } = string.Empty;
|
|
|
|
public Region()
|
|
{
|
|
}
|
|
|
|
public Region(int x, int y, int width, int height, Region? owner = null, INodeConverter? converter = null, DrawContent? drawContent = null)
|
|
{
|
|
X = x;
|
|
Y = y;
|
|
Width = width;
|
|
Height = height;
|
|
Prev = owner;
|
|
PrevConverter = converter;
|
|
this.drawContent = drawContent ?? VisionContext.Instance().DrawContent;
|
|
}
|
|
|
|
public Region(Rect rect, Region? owner = null, INodeConverter? converter = null) : this(rect.X, rect.Y, rect.Width, rect.Height, owner, converter)
|
|
{
|
|
}
|
|
|
|
public Region? Prev { get; }
|
|
|
|
/// <summary>
|
|
/// 本区域节点向上一个区域节点坐标的转换器
|
|
/// </summary>
|
|
public INodeConverter? PrevConverter { get; }
|
|
|
|
/// <summary>
|
|
/// 绘图上下文
|
|
/// </summary>
|
|
protected readonly DrawContent drawContent;
|
|
|
|
// public List<Region>? NextChildren { get; protected set; }
|
|
|
|
/// <summary>
|
|
/// 后台点击【自己】的中心
|
|
/// </summary>
|
|
public void BackgroundClick()
|
|
{
|
|
User32.GetCursorPos(out var p);
|
|
this.Move(); // 必须移动实际鼠标
|
|
TaskContext.Instance().PostMessageSimulator.LeftButtonClickBackground();
|
|
Thread.Sleep(10);
|
|
DesktopRegion.DesktopRegionMove(p.X, p.Y); // 鼠标移动回原来位置
|
|
}
|
|
|
|
/// <summary>
|
|
/// 点击【自己】的中心
|
|
/// region.Derive(x,y).Click() 等效于 region.ClickTo(x,y)
|
|
/// </summary>
|
|
public Region Click()
|
|
{
|
|
// 相对自己是 0, 0 坐标
|
|
ClickTo(0, 0, Width, Height);
|
|
return this;
|
|
}
|
|
|
|
public Region DoubleClick()
|
|
{
|
|
// 相对自己是 0, 0 坐标
|
|
ClickTo(0, 0, Width, Height);
|
|
TaskControl.Sleep(60);
|
|
ClickTo(0, 0, Width, Height);
|
|
return this;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 点击区域内【指定位置】
|
|
/// region.Derive(x,y).Click() 等效于 region.ClickTo(x,y)
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
public void ClickTo(int x, int y)
|
|
{
|
|
ClickTo(x, y, 0, 0);
|
|
}
|
|
|
|
public void ClickTo(double dx, double dy)
|
|
{
|
|
var x = (int)Math.Round(dx);
|
|
var y = (int)Math.Round(dy);
|
|
ClickTo(x, y, 0, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 点击区域内【指定矩形区域】的中心
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <param name="w"></param>
|
|
/// <param name="h"></param>
|
|
/// <exception cref="Exception"></exception>
|
|
public void ClickTo(int x, int y, int w, int h)
|
|
{
|
|
var res = ConvertRes<DesktopRegion>.ConvertPositionToTargetRegion(x, y, w, h, this);
|
|
res.TargetRegion.DesktopRegionClick(res.X, res.Y, res.Width, res.Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移动到【自己】的中心
|
|
/// region.Derive(x,y).Move() 等效于 region.MoveTo(x,y)
|
|
/// </summary>
|
|
public void Move()
|
|
{
|
|
// 相对自己是 0, 0 坐标
|
|
MoveTo(0, 0, Width, Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移动到区域内【指定位置】
|
|
/// region.Derive(x,y).Move() 等效于 region.MoveTo(x,y)
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
public void MoveTo(int x, int y)
|
|
{
|
|
MoveTo(x, y, 0, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 移动到区域内【指定矩形区域】的中心
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <param name="w"></param>
|
|
/// <param name="h"></param>
|
|
/// <exception cref="Exception"></exception>
|
|
public void MoveTo(int x, int y, int w, int h)
|
|
{
|
|
var res = ConvertRes<DesktopRegion>.ConvertPositionToTargetRegion(x, y, w, h, this);
|
|
res.TargetRegion.DesktopRegionMove(res.X, res.Y, res.Width, res.Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 直接在遮罩窗口绘制【自己】
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <param name="pen"></param>
|
|
public void DrawSelf(string name, Pen? pen = null)
|
|
{
|
|
// 相对自己是 0, 0 坐标
|
|
DrawRect(0, 0, Width, Height, name, pen);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 直接在遮罩窗口绘制当前区域下的【指定区域】
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <param name="w"></param>
|
|
/// <param name="h"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="pen"></param>
|
|
public void DrawRect(int x, int y, int w, int h, string name, Pen? pen = null)
|
|
{
|
|
var drawable = ToRectDrawable(x, y, w, h, name, pen);
|
|
drawContent.PutRect(name, drawable);
|
|
}
|
|
|
|
public void DrawRect(Rect rect, string name, Pen? pen = null)
|
|
{
|
|
var drawable = ToRectDrawable(rect.X, rect.Y, rect.Width, rect.Height, name, pen);
|
|
drawContent.PutRect(name, drawable);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 转换【自己】到遮罩窗口绘制矩形
|
|
/// </summary>
|
|
/// <param name="name"></param>
|
|
/// <param name="pen"></param>
|
|
/// <returns></returns>
|
|
public RectDrawable SelfToRectDrawable(string name, Pen? pen = null)
|
|
{
|
|
// 相对自己是 0, 0 坐标
|
|
return ToRectDrawable(0, 0, Width, Height, name, pen);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 转换【指定区域】到遮罩窗口绘制矩形
|
|
/// </summary>
|
|
/// <param name="rect"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="pen"></param>
|
|
/// <returns></returns>
|
|
public RectDrawable ToRectDrawable(Rect rect, string name, Pen? pen = null)
|
|
{
|
|
return ToRectDrawable(rect.X, rect.Y, rect.Width, rect.Height, name, pen);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 转换【指定区域】到遮罩窗口绘制矩形
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <param name="w"></param>
|
|
/// <param name="h"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="pen"></param>
|
|
/// <returns></returns>
|
|
/// <exception cref="Exception"></exception>
|
|
public RectDrawable ToRectDrawable(int x, int y, int w, int h, string name, Pen? pen = null)
|
|
{
|
|
var res = ConvertRes<GameCaptureRegion>.ConvertPositionToTargetRegion(x, y, w, h, this);
|
|
return res.TargetRegion.ConvertToRectDrawable(res.X, res.Y, res.Width, res.Height, pen, name);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 转换【指定直线】到遮罩窗口绘制直线
|
|
/// </summary>
|
|
/// <param name="x1"></param>
|
|
/// <param name="y1"></param>
|
|
/// <param name="x2"></param>
|
|
/// <param name="y2"></param>
|
|
/// <param name="name"></param>
|
|
/// <param name="pen"></param>
|
|
/// <returns></returns>
|
|
public LineDrawable ToLineDrawable(int x1, int y1, int x2, int y2, string name, Pen? pen = null)
|
|
{
|
|
var res1 = ConvertRes<GameCaptureRegion>.ConvertPositionToTargetRegion(x1, y1, 0, 0, this);
|
|
var res2 = ConvertRes<GameCaptureRegion>.ConvertPositionToTargetRegion(x2, y2, 0, 0, this);
|
|
return res1.TargetRegion.ConvertToLineDrawable(res1.X, res1.Y, res2.X, res2.Y, pen, name);
|
|
}
|
|
|
|
public void DrawLine(int x1, int y1, int x2, int y2, string name, Pen? pen = null)
|
|
{
|
|
var drawable = ToLineDrawable(x1, y1, x2, y2, name, pen);
|
|
drawContent.PutLine(name, drawable);
|
|
}
|
|
|
|
public Rect ConvertSelfPositionToGameCaptureRegion()
|
|
{
|
|
return ConvertPositionToGameCaptureRegion(X, Y, Width, Height);
|
|
}
|
|
|
|
public Rect ConvertPositionToGameCaptureRegion(int x, int y, int w, int h)
|
|
{
|
|
var res = ConvertRes<GameCaptureRegion>.ConvertPositionToTargetRegion(x, y, w, h, this);
|
|
return res.ToRect();
|
|
}
|
|
|
|
public (int, int) ConvertPositionToGameCaptureRegion(int x, int y)
|
|
{
|
|
var res = ConvertRes<GameCaptureRegion>.ConvertPositionToTargetRegion(x, y, 0, 0, this);
|
|
return (res.X, res.Y);
|
|
}
|
|
|
|
public (int, int) ConvertPositionToDesktopRegion(int x, int y)
|
|
{
|
|
var res = ConvertRes<DesktopRegion>.ConvertPositionToTargetRegion(x, y, 0, 0, this);
|
|
return (res.X, res.Y);
|
|
}
|
|
|
|
public Rect ToRect()
|
|
{
|
|
return new Rect(X, Y, Width, Height);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 生成一个新的区域
|
|
/// 请使用 using var newRegion
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public ImageRegion ToImageRegion()
|
|
{
|
|
if (this is ImageRegion imageRegion)
|
|
{
|
|
Debug.WriteLine("ToImageRegion 但已经是 ImageRegion");
|
|
return imageRegion;
|
|
}
|
|
|
|
var res = ConvertRes<ImageRegion>.ConvertPositionToTargetRegion(0, 0, Width, Height, this);
|
|
var newRegion = new ImageRegion(new Mat(res.TargetRegion.SrcMat, res.ToRect()), X, Y, Prev, PrevConverter);
|
|
return newRegion;
|
|
}
|
|
|
|
public bool IsEmpty()
|
|
{
|
|
return Width == 0 && Height == 0 && X == 0 && Y == 0;
|
|
}
|
|
|
|
/// <summary>
|
|
/// 语义化包装
|
|
/// </summary>
|
|
/// <returns></returns>
|
|
public bool IsExist()
|
|
{
|
|
return !IsEmpty();
|
|
}
|
|
|
|
public void Dispose()
|
|
{
|
|
// 子节点全部释放
|
|
// NextChildren?.ForEach(x => x.Dispose());
|
|
}
|
|
|
|
/// <summary>
|
|
/// 派生一个点类型的区域
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <returns></returns>
|
|
public Region Derive(int x, int y)
|
|
{
|
|
return Derive(x, y, 0, 0);
|
|
}
|
|
|
|
/// <summary>
|
|
/// 派生一个矩形类型的区域
|
|
/// </summary>
|
|
/// <param name="x"></param>
|
|
/// <param name="y"></param>
|
|
/// <param name="w"></param>
|
|
/// <param name="h"></param>
|
|
/// <returns></returns>
|
|
public Region Derive(int x, int y, int w, int h)
|
|
{
|
|
return new Region(x, y, w, h, this, new TranslationConverter(x, y), this.drawContent);
|
|
}
|
|
|
|
public Region Derive(Rect rect)
|
|
{
|
|
return Derive(rect.X, rect.Y, rect.Width, rect.Height);
|
|
}
|
|
}
|