Files
better-genshin-impact/BetterGenshinImpact/GameTask/Model/Area/Region.cs
辉鸭蛋 4cb5442161 add switch party task
在 `BetterGenshinImpact.csproj` 文件中,添加了两个新文件夹路径 `GameTask\OneDragon\` 和 `User\AutoPathing\`。

在 `BvStatus.cs` 文件中:
- 将 `WaitForMainUi` 方法的默认重试次数从 25 次减少到 10 次。
- 添加了 `IsInPartyViewUi` 和 `WaitForPartyViewUi` 方法。

在 `ElementAssets.cs` 文件中:
- 添加并初始化了 `PartyBtnChooseView` 和 `PartyBtnDelete` 两个新的识别对象。

在 `NewRetry.cs` 文件中:
- 添加了 `using System.Threading.Tasks;` 引用。
- 添加了 `WaitForAction` 方法。

在 `Region.cs` 文件中,添加了一个新的 `ClickTo` 方法,该方法接受 `double` 类型的参数。

在 `ReturnMainUiTask.cs` 文件中:
- 删除了旧的 `ReturnMainUiTask` 类。
- 添加了新的 `ReturnMainUiTask` 类,内容与旧的类似,但文件路径和命名空间有所变化。

在 `RunnerContext.cs` 文件中,移除了 `using BetterGenshinImpact.GameTask.OneDragon;` 引用,添加了 `using BetterGenshinImpact.GameTask.Common.Job;` 引用。

在 `HotKeyPageViewModel.cs` 文件中:
- 添加了多个 `using` 引用,包括 `using System.Threading.Tasks;` 和 `using BetterGenshinImpact.GameTask.Common.Job;`。
- 修改了多个方法的代码格式,使其更加简洁。
- 添加了多个新的快捷键设置。

添加了两个新的 PNG 图片文件 `party_btn_choose_view.png` 和 `party_btn_delete.png`。

在 `SwitchPartyTask.cs` 文件中,添加了新的 `SwitchPartyTask` 类,用于切换队伍。
2024-10-29 01:41:43 +08:00

360 lines
11 KiB
C#

using BetterGenshinImpact.GameTask.Model.Area.Converter;
using BetterGenshinImpact.View.Drawable;
using OpenCvSharp;
using System;
using System.Diagnostics;
using System.Drawing;
using System.Threading;
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)
{
X = x;
Y = y;
Width = width;
Height = height;
Prev = owner;
PrevConverter = converter;
}
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; }
// 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 void Click()
{
// 相对自己是 0, 0 坐标
ClickTo(0, 0, Width, Height);
}
/// <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);
VisionContext.Instance().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);
VisionContext.Instance().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);
VisionContext.Instance().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));
}
public Region Derive(Rect rect)
{
return Derive(rect.X, rect.Y, rect.Width, rect.Height);
}
}