diff --git a/SharpHook.Test/SharpHook.Test.csproj b/SharpHook.Test/SharpHook.Test.csproj
index 973df835..1156b45d 100644
--- a/SharpHook.Test/SharpHook.Test.csproj
+++ b/SharpHook.Test/SharpHook.Test.csproj
@@ -8,7 +8,7 @@
-
+
diff --git a/SightKeeper.Application/Profile/Creating/NewProfileDataDTO.cs b/SightKeeper.Application/Profile/Creating/NewProfileDataDTO.cs
index 63f77213..d24b1c45 100644
--- a/SightKeeper.Application/Profile/Creating/NewProfileDataDTO.cs
+++ b/SightKeeper.Application/Profile/Creating/NewProfileDataDTO.cs
@@ -10,15 +10,17 @@ public sealed class NewProfileDataDTO : NewProfileData
public string Description { get; }
public float DetectionThreshold { get; }
public float MouseSensitivity { get; }
+ public TimeSpan PostProcessDelay { get; }
public Weights Weights { get; }
public IReadOnlyList ItemClasses { get; }
- public NewProfileDataDTO(string name, string description, float detectionThreshold, float mouseSensitivity, Weights weights, IEnumerable itemClasses)
+ public NewProfileDataDTO(string name, string description, float detectionThreshold, float mouseSensitivity, TimeSpan postProcessDelay, Weights weights, IEnumerable itemClasses)
{
Name = name;
Description = description;
DetectionThreshold = detectionThreshold;
MouseSensitivity = mouseSensitivity;
+ PostProcessDelay = postProcessDelay;
Weights = weights;
ItemClasses = itemClasses.ToImmutableList();
}
diff --git a/SightKeeper.Application/Profile/Creating/ProfileCreator.cs b/SightKeeper.Application/Profile/Creating/ProfileCreator.cs
index f7fdc3af..7513fd8a 100644
--- a/SightKeeper.Application/Profile/Creating/ProfileCreator.cs
+++ b/SightKeeper.Application/Profile/Creating/ProfileCreator.cs
@@ -15,7 +15,7 @@ public ProfileCreator(IValidator validator, ProfilesDataAccess p
public async Task CreateProfile(NewProfileDataDTO data)
{
await _validator.ValidateAndThrowAsync(data);
- Profile profile = new(data.Name, data.Description, data.DetectionThreshold, data.MouseSensitivity, data.Weights);
+ Profile profile = new(data.Name, data.Description, data.DetectionThreshold, data.MouseSensitivity, data.PostProcessDelay, data.Weights);
foreach (var itemClass in data.ItemClasses)
profile.AddItemClass(itemClass);
await _profilesDataAccess.AddProfile(profile);
diff --git a/SightKeeper.Application/Profile/Editing/EditedProfileDataDTO.cs b/SightKeeper.Application/Profile/Editing/EditedProfileDataDTO.cs
index 638dc2f1..91becebc 100644
--- a/SightKeeper.Application/Profile/Editing/EditedProfileDataDTO.cs
+++ b/SightKeeper.Application/Profile/Editing/EditedProfileDataDTO.cs
@@ -11,16 +11,18 @@ public sealed class EditedProfileDataDTO : EditedProfileData
public string Description { get; }
public float DetectionThreshold { get; }
public float MouseSensitivity { get; }
+ public TimeSpan PostProcessDelay { get; }
public Weights Weights { get; }
public IReadOnlyList ItemClasses { get; }
- public EditedProfileDataDTO(Profile profile, string name, string description, float detectionThreshold, float mouseSensitivity, Weights weights, IEnumerable itemClasses)
+ public EditedProfileDataDTO(Profile profile, string name, string description, float detectionThreshold, float mouseSensitivity, TimeSpan postProcessDelay, Weights weights, IEnumerable itemClasses)
{
Profile = profile;
Name = name;
Description = description;
DetectionThreshold = detectionThreshold;
MouseSensitivity = mouseSensitivity;
+ PostProcessDelay = postProcessDelay;
Weights = weights;
ItemClasses = itemClasses.ToImmutableList();
}
diff --git a/SightKeeper.Application/Profile/Editing/ProfileEditor.cs b/SightKeeper.Application/Profile/Editing/ProfileEditor.cs
index 0c648a47..6050ec17 100644
--- a/SightKeeper.Application/Profile/Editing/ProfileEditor.cs
+++ b/SightKeeper.Application/Profile/Editing/ProfileEditor.cs
@@ -24,6 +24,7 @@ public async Task ApplyChanges(EditedProfileDataDTO data)
profile.Description = data.Description;
profile.DetectionThreshold = data.DetectionThreshold;
profile.MouseSensitivity = data.MouseSensitivity;
+ profile.PostProcessDelay = data.PostProcessDelay;
profile.Weights = data.Weights;
profile.ClearItemClasses();
foreach (var itemClass in data.ItemClasses)
diff --git a/SightKeeper.Application/Profile/ProfileData.cs b/SightKeeper.Application/Profile/ProfileData.cs
index e16020e6..76b9ffc7 100644
--- a/SightKeeper.Application/Profile/ProfileData.cs
+++ b/SightKeeper.Application/Profile/ProfileData.cs
@@ -9,6 +9,7 @@ public interface ProfileData
string Description { get; }
float DetectionThreshold { get; }
float MouseSensitivity { get; }
+ TimeSpan PostProcessDelay { get; }
Weights? Weights { get; }
IReadOnlyList ItemClasses { get; }
}
\ No newline at end of file
diff --git a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/AbstractProfileEditorVIewModel.cs b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/AbstractProfileEditorVIewModel.cs
index 956a8d70..cdaa9f1a 100644
--- a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/AbstractProfileEditorVIewModel.cs
+++ b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/AbstractProfileEditorVIewModel.cs
@@ -55,6 +55,18 @@ public float MouseSensitivity
set => SetProperty(ref _mouseSensitivity, value);
}
+ public TimeSpan PostProcessDelay
+ {
+ get => _postProcessDelay;
+ set => SetProperty(ref _postProcessDelay, value);
+ }
+
+ ushort ProfileEditorViewModel.PostProcessDelay
+ {
+ get => (ushort)_postProcessDelay.TotalMilliseconds;
+ set => SetProperty(PostProcessDelay.TotalMilliseconds, value, newValue => _postProcessDelay = TimeSpan.FromMilliseconds(newValue));
+ }
+
public DataSet? DataSet
{
get => _dataSet;
@@ -112,7 +124,7 @@ protected AbstractProfileEditorVIewModel(IValidator validator, Dat
private IReadOnlyCollection _availableWeights = Array.Empty();
[ObservableProperty, NotifyCanExecuteChangedFor(nameof(AddItemClassCommand))]
private ItemClass? _itemClassToAdd;
-
+ private TimeSpan _postProcessDelay;
ICommand ProfileEditorViewModel.AddItemClassCommand => AddItemClassCommand;
[RelayCommand(CanExecute = nameof(CanAddItemClass))]
diff --git a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ExistingProfileEditorViewModel.cs b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ExistingProfileEditorViewModel.cs
index 95c998e5..7a2b071e 100644
--- a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ExistingProfileEditorViewModel.cs
+++ b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ExistingProfileEditorViewModel.cs
@@ -21,6 +21,7 @@ public void SetData(Profile profile)
Description = profile.Description;
DetectionThreshold = profile.DetectionThreshold;
MouseSensitivity = profile.MouseSensitivity;
+ PostProcessDelay = profile.PostProcessDelay;
DataSet = profile.Weights.Library.DataSet;
Weights = profile.Weights;
_itemClasses.Clear();
diff --git a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/FakeProfileEditorViewModel.cs b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/FakeProfileEditorViewModel.cs
index 0bd82c31..5e3fde4a 100644
--- a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/FakeProfileEditorViewModel.cs
+++ b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/FakeProfileEditorViewModel.cs
@@ -17,6 +17,7 @@ public sealed partial class FakeProfileEditorViewModel : ViewModel, ProfileEdito
public string Description { get; set; } = "Some description.. lorem ipsum and all that stuff";
[ObservableProperty] private float _detectionThreshold = 0.6f;
[ObservableProperty] private float _mouseSensitivity = 1.5f;
+ public ushort PostProcessDelay { get; set; }
public DataSet? DataSet { get; set; }
public Weights? Weights { get; set; }
public IReadOnlyList ItemClasses { get; }
diff --git a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ProfileEditorViewModel.cs b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ProfileEditorViewModel.cs
index 99a4224e..a528c35c 100644
--- a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ProfileEditorViewModel.cs
+++ b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Editor/ProfileEditorViewModel.cs
@@ -15,6 +15,7 @@ public interface ProfileEditorViewModel
string Description { get; set; }
float DetectionThreshold { get; set; }
float MouseSensitivity { get; set; }
+ ushort PostProcessDelay { get; set; }
DataSet? DataSet { get; set; }
Weights? Weights { get; set; }
IReadOnlyList ItemClasses { get; }
diff --git a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/FakeProfilesViewModel.cs b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/FakeProfilesViewModel.cs
index aedb2860..3780d68e 100644
--- a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/FakeProfilesViewModel.cs
+++ b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/FakeProfilesViewModel.cs
@@ -26,8 +26,8 @@ public FakeProfilesViewModel()
dataSet.Game = game;
var weights = dataSet.WeightsLibrary.CreateWeights(Array.Empty(), Array.Empty(), ModelSize.Small,
100, 0.5f, 0.4f, 0.3f, Enumerable.Empty());
- Profile profile1 = new("Profile", string.Empty, 0.5f, 2f, weights);
- Profile profile2 = new("Profile with long name!", string.Empty, 0.3f, 3f, weights);
+ Profile profile1 = new("Profile", string.Empty, 0.5f, 2f, TimeSpan.FromMilliseconds(10), weights);
+ Profile profile2 = new("Profile with long name!", string.Empty, 0.3f, 3f, TimeSpan.FromMilliseconds(15), weights);
Profiles = new ProfileViewModel[]
{
new(profile1),
diff --git a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/ProfilesViewModel.cs b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/ProfilesViewModel.cs
index eaa3bad2..20f467f2 100644
--- a/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/ProfilesViewModel.cs
+++ b/SightKeeper.Avalonia/ViewModels/Tabs/Profiles/Tab/ProfilesViewModel.cs
@@ -74,7 +74,7 @@ private async Task CreateProfile()
if (result == ProfileEditorResult.Apply)
{
Guard.IsNotNull(viewModel.Weights);
- NewProfileDataDTO data = new(viewModel.Name, viewModel.Description, viewModel.DetectionThreshold, viewModel.MouseSensitivity, viewModel.Weights, viewModel.ItemClasses);
+ NewProfileDataDTO data = new(viewModel.Name, viewModel.Description, viewModel.DetectionThreshold, viewModel.MouseSensitivity, viewModel.PostProcessDelay, viewModel.Weights, viewModel.ItemClasses);
await _profileCreator.CreateProfile(data);
}
}
@@ -91,7 +91,7 @@ private async Task EditProfile(ProfileViewModel profileViewModel)
if (result == ProfileEditorResult.Apply)
{
Guard.IsNotNull(viewModel.Weights);
- EditedProfileDataDTO data = new(profileViewModel.Profile, viewModel.Name, viewModel.Description, viewModel.DetectionThreshold, viewModel.MouseSensitivity, viewModel.Weights, viewModel.ItemClasses);
+ EditedProfileDataDTO data = new(profileViewModel.Profile, viewModel.Name, viewModel.Description, viewModel.DetectionThreshold, viewModel.MouseSensitivity, viewModel.PostProcessDelay, viewModel.Weights, viewModel.ItemClasses);
await _profileEditor.ApplyChanges(data);
}
else if (result == ProfileEditorResult.Delete)
diff --git a/SightKeeper.Avalonia/Views/Profiles/ProfileEditor.axaml b/SightKeeper.Avalonia/Views/Profiles/ProfileEditor.axaml
index 036849f7..7d00e40f 100644
--- a/SightKeeper.Avalonia/Views/Profiles/ProfileEditor.axaml
+++ b/SightKeeper.Avalonia/Views/Profiles/ProfileEditor.axaml
@@ -54,6 +54,23 @@
Maximum="5"
Value="{Binding MouseSensitivity}"/>
+
+
+
+
diff --git a/SightKeeper.Data/Configuration/ProfileConfiguration.cs b/SightKeeper.Data/Configuration/ProfileConfiguration.cs
index 755838e0..e079a1f0 100644
--- a/SightKeeper.Data/Configuration/ProfileConfiguration.cs
+++ b/SightKeeper.Data/Configuration/ProfileConfiguration.cs
@@ -13,5 +13,8 @@ public void Configure(EntityTypeBuilder builder)
builder.HasIndex(profile => profile.Name).IsUnique();
builder.Navigation(profile => profile.Weights).AutoInclude();
builder.Navigation(profile => profile.ItemClasses).AutoInclude();
+ builder.Property(profile => profile.PostProcessDelay).HasConversion(
+ timeSpan => (ushort)timeSpan.TotalMilliseconds,
+ number => TimeSpan.FromMilliseconds(number));
}
}
\ No newline at end of file
diff --git a/SightKeeper.Data/Migrations/20230926083614_AddProfilePostProcessDelay.Designer.cs b/SightKeeper.Data/Migrations/20230926083614_AddProfilePostProcessDelay.Designer.cs
new file mode 100644
index 00000000..2151e908
--- /dev/null
+++ b/SightKeeper.Data/Migrations/20230926083614_AddProfilePostProcessDelay.Designer.cs
@@ -0,0 +1,619 @@
+//
+using System;
+using Microsoft.EntityFrameworkCore;
+using Microsoft.EntityFrameworkCore.Infrastructure;
+using Microsoft.EntityFrameworkCore.Migrations;
+using Microsoft.EntityFrameworkCore.Storage.ValueConversion;
+using SightKeeper.Data;
+
+#nullable disable
+
+namespace SightKeeper.Data.Migrations
+{
+ [DbContext(typeof(AppDbContext))]
+ [Migration("20230926083614_AddProfilePostProcessDelay")]
+ partial class AddProfilePostProcessDelay
+ {
+ ///
+ protected override void BuildTargetModel(ModelBuilder modelBuilder)
+ {
+#pragma warning disable 612, 618
+ modelBuilder.HasAnnotation("ProductVersion", "8.0.0-preview.6.23329.4");
+
+ modelBuilder.Entity("AssetWeights", b =>
+ {
+ b.Property("AssetId")
+ .HasColumnType("INTEGER");
+
+ b.Property("WeightsId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("AssetId", "WeightsId");
+
+ b.HasIndex("WeightsId");
+
+ b.ToTable("WeightsAssets", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.Asset", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("INTEGER");
+
+ b.Property("DataSetId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Usage")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DataSetId");
+
+ b.ToTable("Assets", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.Game", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("ProcessName")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Title")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.ToTable("Games");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.Image", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("INTEGER");
+
+ b.Property("Content")
+ .IsRequired()
+ .HasColumnType("BLOB");
+
+ b.HasKey("Id");
+
+ b.ToTable("Images", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.ItemClass", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Color")
+ .HasColumnType("INTEGER");
+
+ b.Property("DataSetId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.HasKey("Id");
+
+ b.HasIndex("DataSetId");
+
+ b.ToTable("ItemClasses", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.DataSet", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("GameId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("Resolution")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("GameId");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.ToTable("DataSets");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Detector.DetectorItem", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("AssetId")
+ .HasColumnType("INTEGER");
+
+ b.Property("ItemClassId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("AssetId");
+
+ b.HasIndex("ItemClassId");
+
+ b.ToTable("DetectorItems", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Profile", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Description")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("DetectionThreshold")
+ .HasColumnType("REAL");
+
+ b.Property("MouseSensitivity")
+ .HasColumnType("REAL");
+
+ b.Property("Name")
+ .IsRequired()
+ .HasColumnType("TEXT");
+
+ b.Property("PostProcessDelay")
+ .HasColumnType("INTEGER");
+
+ b.Property("WeightsId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("Name")
+ .IsUnique();
+
+ b.HasIndex("WeightsId");
+
+ b.ToTable("Profiles");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.ProfileItemClass", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Index")
+ .HasColumnType("INTEGER");
+
+ b.Property("ItemClassId")
+ .HasColumnType("INTEGER");
+
+ b.Property("ProfileId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("ItemClassId");
+
+ b.HasIndex("ProfileId", "Index")
+ .IsUnique();
+
+ b.HasIndex("ProfileId", "ItemClassId")
+ .IsUnique();
+
+ b.ToTable("ProfileItemClasses", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Screenshot", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("CreationDate")
+ .HasColumnType("TEXT");
+
+ b.Property("LibraryId")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LibraryId");
+
+ b.ToTable("Screenshots", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.ScreenshotsLibrary", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("INTEGER");
+
+ b.Property("HasAnyScreenshots")
+ .HasColumnType("INTEGER");
+
+ b.Property("MaxQuantity")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("ScreenshotsLibraries", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Weights", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("BoundingLoss")
+ .HasColumnType("REAL");
+
+ b.Property("ClassificationLoss")
+ .HasColumnType("REAL");
+
+ b.Property("DeformationLoss")
+ .HasColumnType("REAL");
+
+ b.Property("Epoch")
+ .HasColumnType("INTEGER");
+
+ b.Property("LibraryId")
+ .HasColumnType("INTEGER");
+
+ b.Property("Size")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.HasIndex("LibraryId");
+
+ b.ToTable("Weights");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.WeightsData", b =>
+ {
+ b.Property("Id")
+ .ValueGeneratedOnAdd()
+ .HasColumnType("INTEGER");
+
+ b.Property("Content")
+ .IsRequired()
+ .HasColumnType("BLOB");
+
+ b.HasKey("Id");
+
+ b.ToTable("WeightsData");
+
+ b.UseTptMappingStrategy();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.WeightsLibrary", b =>
+ {
+ b.Property("Id")
+ .HasColumnType("INTEGER");
+
+ b.HasKey("Id");
+
+ b.ToTable("WeightsLibraries", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.ONNXData", b =>
+ {
+ b.HasBaseType("SightKeeper.Domain.Model.WeightsData");
+
+ b.Property("WeightsId")
+ .HasColumnType("INTEGER");
+
+ b.HasIndex("WeightsId")
+ .IsUnique();
+
+ b.ToTable("ONNXData", (string)null);
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.PTData", b =>
+ {
+ b.HasBaseType("SightKeeper.Domain.Model.WeightsData");
+
+ b.Property("WeightsId")
+ .HasColumnType("INTEGER");
+
+ b.HasIndex("WeightsId")
+ .IsUnique();
+
+ b.ToTable("PTData", (string)null);
+ });
+
+ modelBuilder.Entity("AssetWeights", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.Common.Asset", null)
+ .WithMany()
+ .HasForeignKey("AssetId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SightKeeper.Domain.Model.Weights", null)
+ .WithMany()
+ .HasForeignKey("WeightsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.Asset", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.DataSet", "DataSet")
+ .WithMany("Assets")
+ .HasForeignKey("DataSetId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SightKeeper.Domain.Model.Screenshot", "Screenshot")
+ .WithOne("Asset")
+ .HasForeignKey("SightKeeper.Domain.Model.Common.Asset", "Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("DataSet");
+
+ b.Navigation("Screenshot");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.Image", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.Screenshot", null)
+ .WithOne("Image")
+ .HasForeignKey("SightKeeper.Domain.Model.Common.Image", "Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.ItemClass", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.DataSet", "DataSet")
+ .WithMany("ItemClasses")
+ .HasForeignKey("DataSetId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("DataSet");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.DataSet", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.Common.Game", "Game")
+ .WithMany()
+ .HasForeignKey("GameId");
+
+ b.Navigation("Game");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Detector.DetectorItem", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.Common.Asset", "Asset")
+ .WithMany("Items")
+ .HasForeignKey("AssetId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SightKeeper.Domain.Model.Common.ItemClass", "ItemClass")
+ .WithMany("Items")
+ .HasForeignKey("ItemClassId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.OwnsOne("SightKeeper.Domain.Model.Detector.Bounding", "Bounding", b1 =>
+ {
+ b1.Property("DetectorItemId")
+ .HasColumnType("INTEGER");
+
+ b1.Property("Bottom")
+ .HasColumnType("REAL")
+ .HasColumnName("BoundingBottom");
+
+ b1.Property("Left")
+ .HasColumnType("REAL")
+ .HasColumnName("BoundingLeft");
+
+ b1.Property("Right")
+ .HasColumnType("REAL")
+ .HasColumnName("BoundingRight");
+
+ b1.Property("Top")
+ .HasColumnType("REAL")
+ .HasColumnName("BoundingTop");
+
+ b1.HasKey("DetectorItemId");
+
+ b1.ToTable("DetectorItems");
+
+ b1.WithOwner()
+ .HasForeignKey("DetectorItemId");
+ });
+
+ b.Navigation("Asset");
+
+ b.Navigation("Bounding")
+ .IsRequired();
+
+ b.Navigation("ItemClass");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Profile", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.Weights", "Weights")
+ .WithMany()
+ .HasForeignKey("WeightsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Weights");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.ProfileItemClass", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.Common.ItemClass", "ItemClass")
+ .WithMany()
+ .HasForeignKey("ItemClassId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SightKeeper.Domain.Model.Profile", null)
+ .WithMany("ItemClasses")
+ .HasForeignKey("ProfileId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("ItemClass");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Screenshot", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.ScreenshotsLibrary", "Library")
+ .WithMany("Screenshots")
+ .HasForeignKey("LibraryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Library");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.ScreenshotsLibrary", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.DataSet", "DataSet")
+ .WithOne("ScreenshotsLibrary")
+ .HasForeignKey("SightKeeper.Domain.Model.ScreenshotsLibrary", "Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("DataSet");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Weights", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.WeightsLibrary", "Library")
+ .WithMany("Weights")
+ .HasForeignKey("LibraryId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("Library");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.WeightsLibrary", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.DataSet", "DataSet")
+ .WithOne("WeightsLibrary")
+ .HasForeignKey("SightKeeper.Domain.Model.WeightsLibrary", "Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.Navigation("DataSet");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.ONNXData", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.WeightsData", null)
+ .WithOne()
+ .HasForeignKey("SightKeeper.Domain.Model.ONNXData", "Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SightKeeper.Domain.Model.Weights", null)
+ .WithOne("ONNXData")
+ .HasForeignKey("SightKeeper.Domain.Model.ONNXData", "WeightsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.PTData", b =>
+ {
+ b.HasOne("SightKeeper.Domain.Model.WeightsData", null)
+ .WithOne()
+ .HasForeignKey("SightKeeper.Domain.Model.PTData", "Id")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+
+ b.HasOne("SightKeeper.Domain.Model.Weights", null)
+ .WithOne("PTData")
+ .HasForeignKey("SightKeeper.Domain.Model.PTData", "WeightsId")
+ .OnDelete(DeleteBehavior.Cascade)
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.Asset", b =>
+ {
+ b.Navigation("Items");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Common.ItemClass", b =>
+ {
+ b.Navigation("Items");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.DataSet", b =>
+ {
+ b.Navigation("Assets");
+
+ b.Navigation("ItemClasses");
+
+ b.Navigation("ScreenshotsLibrary")
+ .IsRequired();
+
+ b.Navigation("WeightsLibrary")
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Profile", b =>
+ {
+ b.Navigation("ItemClasses");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Screenshot", b =>
+ {
+ b.Navigation("Asset");
+
+ b.Navigation("Image")
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.ScreenshotsLibrary", b =>
+ {
+ b.Navigation("Screenshots");
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.Weights", b =>
+ {
+ b.Navigation("ONNXData")
+ .IsRequired();
+
+ b.Navigation("PTData")
+ .IsRequired();
+ });
+
+ modelBuilder.Entity("SightKeeper.Domain.Model.WeightsLibrary", b =>
+ {
+ b.Navigation("Weights");
+ });
+#pragma warning restore 612, 618
+ }
+ }
+}
diff --git a/SightKeeper.Data/Migrations/20230926083614_AddProfilePostProcessDelay.cs b/SightKeeper.Data/Migrations/20230926083614_AddProfilePostProcessDelay.cs
new file mode 100644
index 00000000..3c1dbee5
--- /dev/null
+++ b/SightKeeper.Data/Migrations/20230926083614_AddProfilePostProcessDelay.cs
@@ -0,0 +1,29 @@
+using Microsoft.EntityFrameworkCore.Migrations;
+
+#nullable disable
+
+namespace SightKeeper.Data.Migrations
+{
+ ///
+ public partial class AddProfilePostProcessDelay : Migration
+ {
+ ///
+ protected override void Up(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.AddColumn(
+ name: "PostProcessDelay",
+ table: "Profiles",
+ type: "INTEGER",
+ nullable: false,
+ defaultValue: (ushort)0);
+ }
+
+ ///
+ protected override void Down(MigrationBuilder migrationBuilder)
+ {
+ migrationBuilder.DropColumn(
+ name: "PostProcessDelay",
+ table: "Profiles");
+ }
+ }
+}
diff --git a/SightKeeper.Data/Migrations/AppDbContextModelSnapshot.cs b/SightKeeper.Data/Migrations/AppDbContextModelSnapshot.cs
index 968aff41..2401e115 100644
--- a/SightKeeper.Data/Migrations/AppDbContextModelSnapshot.cs
+++ b/SightKeeper.Data/Migrations/AppDbContextModelSnapshot.cs
@@ -177,6 +177,9 @@ protected override void BuildModel(ModelBuilder modelBuilder)
.IsRequired()
.HasColumnType("TEXT");
+ b.Property("PostProcessDelay")
+ .HasColumnType("INTEGER");
+
b.Property("WeightsId")
.HasColumnType("INTEGER");
diff --git a/SightKeeper.Domain.Model/Profile/Profile.cs b/SightKeeper.Domain.Model/Profile/Profile.cs
index c1084d77..8d0de110 100644
--- a/SightKeeper.Domain.Model/Profile/Profile.cs
+++ b/SightKeeper.Domain.Model/Profile/Profile.cs
@@ -28,6 +28,16 @@ public float MouseSensitivity
}
}
+ public TimeSpan PostProcessDelay
+ {
+ get => _postProcessDelay;
+ set
+ {
+ Guard.IsGreaterThanOrEqualTo(value, TimeSpan.Zero);
+ _postProcessDelay = value;
+ }
+ }
+
public Weights Weights
{
get => _weights;
@@ -43,12 +53,13 @@ public Weights Weights
public IReadOnlyList ItemClasses => _itemClasses;
- public Profile(string name, string description, float detectionThreshold, float mouseSensitivity, Weights weights)
+ public Profile(string name, string description, float detectionThreshold, float mouseSensitivity, TimeSpan postProcessDelay, Weights weights)
{
Name = name;
Description = description;
DetectionThreshold = detectionThreshold;
MouseSensitivity = mouseSensitivity;
+ _postProcessDelay = postProcessDelay;
_weights = weights;
_itemClasses = new List();
}
@@ -95,6 +106,7 @@ public override string ToString() =>
private readonly List _itemClasses;
private float _detectionThreshold;
private float _mouseSensitivity;
+ private TimeSpan _postProcessDelay;
private Profile()
{
diff --git a/SightKeeper.Services/Scoring/HotKeyProfileRunner.cs b/SightKeeper.Services/Scoring/HotKeyProfileRunner.cs
index a5e6a176..5a9083cc 100644
--- a/SightKeeper.Services/Scoring/HotKeyProfileRunner.cs
+++ b/SightKeeper.Services/Scoring/HotKeyProfileRunner.cs
@@ -54,13 +54,17 @@ public byte MaximumFPS
}
}
- private TimeSpan _screenshotingDelay = TimeSpan.FromSeconds(1f / _defaultMaximumFPS);
+ private TimeSpan _screenshotingDelay = TimeSpan.FromSeconds(1f / DefaultMaximumFPS);
private DateTime _lastScreenshotTime = DateTime.UtcNow;
+ private const byte DefaultMaximumFPS = 1;
- private const byte _defaultMaximumFPS = 1;
-
- public HotKeyProfileRunner(StreamDetector streamDetector, MouseMover mouseMover, SharpHookHotKeyManager hotKeyManager, ProfileEditor profileEditor, ScreenshotsDataAccess screenshotsDataAccess)
+ public HotKeyProfileRunner(
+ StreamDetector streamDetector,
+ MouseMover mouseMover,
+ SharpHookHotKeyManager hotKeyManager,
+ ProfileEditor profileEditor,
+ ScreenshotsDataAccess screenshotsDataAccess)
{
_streamDetector = streamDetector;
_mouseMover = mouseMover;
@@ -114,6 +118,19 @@ private void HandleDetection(byte[] imageData, ImmutableList item
MoveTo(mostSuitableItem.Bounding);
}
TryMakeScreenshot(imageData, items);
+ if (_currentProfile.PostProcessDelay != TimeSpan.Zero)
+ {
+ if (_currentProfile.PostProcessDelay.TotalMilliseconds > 20)
+ Thread.Sleep(_currentProfile.PostProcessDelay);
+ else
+ BurnTime(_currentProfile.PostProcessDelay);
+ }
+ }
+
+ private static void BurnTime(TimeSpan time)
+ {
+ var endTime = DateTime.UtcNow + time;
+ while (DateTime.UtcNow < endTime) { }
}
private async void TryMakeScreenshot(byte[] imageData, ImmutableList items)
@@ -188,7 +205,7 @@ public void Stop()
private Dictionary? _itemClassesIndexes;
private float _minimumProbability = 0.2f;
private float _maximumProbability = 0.5f;
- private byte _maximumFPS = _defaultMaximumFPS;
+ private byte _maximumFPS = DefaultMaximumFPS;
private void UpdateDetectionThreshold()
{
diff --git a/SightKeeper.Services/SharpHookExtensions.cs b/SightKeeper.Services/SharpHookExtensions.cs
index c769338b..d30e3dcd 100644
--- a/SightKeeper.Services/SharpHookExtensions.cs
+++ b/SightKeeper.Services/SharpHookExtensions.cs
@@ -7,8 +7,7 @@ public static class SharpHookExtensions
public static string ToStringEx(this KeyCode key)
{
var result = key.ToString();
- if (key != KeyCode.CharUndefined)
- result = result[2..];
+ result = result[2..];
return result;
}
}
\ No newline at end of file
diff --git a/SightKeeper.Services/SightKeeper.Services.csproj b/SightKeeper.Services/SightKeeper.Services.csproj
index b5f40f4a..d2a8b80c 100644
--- a/SightKeeper.Services/SightKeeper.Services.csproj
+++ b/SightKeeper.Services/SightKeeper.Services.csproj
@@ -15,8 +15,8 @@
-
-
+
+