mirror of
https://github.com/gwdevhub/Daybreak.git
synced 2026-09-18 22:35:01 +00:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
d6623a8646 | ||
|
|
403ba51a7d | ||
|
|
b185a606e6 | ||
|
|
342a9a4826 | ||
|
|
2df2e8a65e | ||
|
|
2d5e9231a9 | ||
|
|
818e2bf1d0 | ||
|
|
f0a876f7cc | ||
|
|
3fae8f91cb | ||
|
|
8b08056ca7 | ||
|
|
39eaf53deb | ||
|
|
4674d1d7e5 | ||
|
|
b8b5cc8b1d | ||
|
|
dc987233a7 | ||
|
|
266b400c22 | ||
|
|
a4ac083fd0 | ||
|
|
320dd16838 | ||
|
|
5c05c636bc | ||
|
|
7103a8a83a | ||
|
|
ad749d801a | ||
|
|
747e9a0490 | ||
|
|
836402bd0f | ||
|
|
a3d5e1ce1f | ||
|
|
f2cc59a4ab | ||
|
|
6ea77f7e05 | ||
|
|
5ea8df7cb9 | ||
|
|
c70e8ec90d | ||
|
|
210e3a8cb1 | ||
|
|
a0c3bb094c | ||
|
|
b4d932692a | ||
|
|
667534a07a | ||
|
|
159928f24b | ||
|
|
8a91ded610 | ||
|
|
4226b7eb32 | ||
|
|
b61c99dd1c | ||
|
|
1ccb0d5334 | ||
|
|
7fa01353dd | ||
|
|
4f849d880b | ||
|
|
4b60c96aad | ||
|
|
a4dc0d65cf | ||
|
|
85e017423f |
+5
-2
@@ -6,8 +6,8 @@ csharp_indent_labels = one_less_than_current
|
||||
csharp_using_directive_placement = outside_namespace:error
|
||||
csharp_prefer_simple_using_statement = true:error
|
||||
csharp_prefer_braces = true:silent
|
||||
csharp_style_namespace_declarations = block_scoped:silent
|
||||
csharp_style_prefer_method_group_conversion = true:silent
|
||||
csharp_style_namespace_declarations = file_scoped:error
|
||||
csharp_style_prefer_method_group_conversion = true:suggestion
|
||||
csharp_style_expression_bodied_methods = false:silent
|
||||
csharp_style_expression_bodied_constructors = false:silent
|
||||
csharp_style_expression_bodied_operators = false:silent
|
||||
@@ -46,6 +46,9 @@ csharp_style_prefer_extended_property_pattern = true:suggestion
|
||||
csharp_style_var_for_built_in_types = false:silent
|
||||
csharp_style_var_when_type_is_apparent = false:silent
|
||||
csharp_style_var_elsewhere = false:silent
|
||||
csharp_style_prefer_top_level_statements = true:suggestion
|
||||
csharp_style_prefer_utf8_string_literals = true:suggestion
|
||||
csharp_style_prefer_readonly_struct = true:suggestion
|
||||
|
||||
[*.{cs,vb}]
|
||||
#### Naming styles ####
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
targetplatform: [x64]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
|
||||
@@ -19,7 +19,7 @@ jobs:
|
||||
|
||||
strategy:
|
||||
matrix:
|
||||
targetplatform: [x86]
|
||||
targetplatform: [x64]
|
||||
|
||||
runs-on: windows-latest
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
<Platforms>AnyCPU;x86;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
</Project>
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
<PropertyGroup>
|
||||
<TargetFramework>net6.0-windows</TargetFramework>
|
||||
<IsPackable>false</IsPackable>
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
<Platforms>AnyCPU;x86;x64</Platforms>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
|
||||
@@ -132,4 +132,55 @@ public class VersionTests
|
||||
action.Should().NotThrow<ArgumentException>();
|
||||
}
|
||||
}
|
||||
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0.1", true)]
|
||||
[DataRow("v0.1.0.0.1.0.0.0.0", "v0.1.0.0.1", true)]
|
||||
[DataRow("v0.1.0", "v0.1", true)]
|
||||
[DataRow("0.1.0", "0.1", true)]
|
||||
[DataRow("v0.1.0.0.0", "v0.1", true)]
|
||||
[DataRow("0.1.0.0.0", "0.1", true)]
|
||||
[DataRow("v0", "v0", true)]
|
||||
[DataRow("0", "0", true)]
|
||||
[DataRow("v0.1", "v0.1", true)]
|
||||
[DataRow("0.1-release", "0.1-release", true)]
|
||||
[DataRow("v0.1-release", "v0.1-release", true)]
|
||||
[DataRow("v0.1.0.0", "v0.1.0.0.1", false)]
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0", false)]
|
||||
[DataRow("v0.9.8.9", "v0.9.8.10", false)]
|
||||
[DataRow("0.1-release", "0.2-release", false)]
|
||||
[DataRow("v1.1-release", "v0.1-release", false)]
|
||||
[TestMethod]
|
||||
public void Equals(string version, string version2, bool result)
|
||||
{
|
||||
var parsedVersion1 = Version.Parse(version);
|
||||
var parsedVersion2 = Version.Parse(version2);
|
||||
|
||||
parsedVersion1.Equals(parsedVersion2).Should().Be(result);
|
||||
}
|
||||
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0.1", 0)]
|
||||
[DataRow("v0.1.0.0.1.0.0.0.0", "v0.1.0.0.1", 0)]
|
||||
[DataRow("v0.1.0", "v0.1", 0)]
|
||||
[DataRow("0.1.0", "0.1", 0)]
|
||||
[DataRow("v0.1.0.0.0", "v0.1", 0)]
|
||||
[DataRow("0.1.0.0.0", "0.1", 0)]
|
||||
[DataRow("v0", "v0", 0)]
|
||||
[DataRow("0", "0", 0)]
|
||||
[DataRow("v0.1", "v0.1", 0)]
|
||||
[DataRow("0.1-release", "0.1-release", 0)]
|
||||
[DataRow("v0.1-release", "v0.1-release", 0)]
|
||||
[DataRow("v0.1.0.0", "v0.1.0.0.1", -1)]
|
||||
[DataRow("v0.1.0.0.1", "v0.1.0.0", 1)]
|
||||
[DataRow("v0.9.8.9", "v0.9.8.10", -1)]
|
||||
[DataRow("v0.9.8.10", "v0.9.8.9", 1)]
|
||||
[DataRow("0.1-release", "0.2-release", -1)]
|
||||
[DataRow("v1.1-release", "v0.1-release", 1)]
|
||||
[TestMethod]
|
||||
public void CompareTo(string version, string version2, int comparisonResult)
|
||||
{
|
||||
var parsedVersion1 = Version.Parse(version);
|
||||
var parsedVersion2 = Version.Parse(version2);
|
||||
|
||||
parsedVersion1.CompareTo(parsedVersion2).Should().Be(comparisonResult);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,62 +0,0 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Options;
|
||||
using FluentAssertions;
|
||||
using Microsoft.VisualStudio.TestTools.UnitTesting;
|
||||
using Moq;
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Tests.Services;
|
||||
|
||||
[TestClass]
|
||||
public class ApplicationConfigurationOptionsManagerTests
|
||||
{
|
||||
private ApplicationConfigurationOptionsManager applicationConfigurationOptionsManager;
|
||||
|
||||
[TestInitialize]
|
||||
public void TestInitialize()
|
||||
{
|
||||
var configurationManagerMock = new Mock<IConfigurationManager>();
|
||||
configurationManagerMock
|
||||
.Setup(u => u.GetConfiguration())
|
||||
.Returns(new ApplicationConfiguration());
|
||||
|
||||
this.applicationConfigurationOptionsManager = new ApplicationConfigurationOptionsManager(configurationManagerMock.Object);
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetApplicationConfiguration_ReturnsObject()
|
||||
{
|
||||
var config = this.applicationConfigurationOptionsManager.GetOptions<ApplicationConfiguration>();
|
||||
|
||||
config.Should().NotBeNull();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void GetOtherOptions_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = new Action(() =>
|
||||
{
|
||||
this.applicationConfigurationOptionsManager.GetOptions<object>();
|
||||
});
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateOptions_OnApplicationConfiguration_Succeeds()
|
||||
{
|
||||
this.applicationConfigurationOptionsManager.UpdateOptions(new ApplicationConfiguration());
|
||||
}
|
||||
|
||||
[TestMethod]
|
||||
public void UpdateOptions_OnOthers_ThrowsInvalidOperationException()
|
||||
{
|
||||
var action = new Action(() =>
|
||||
{
|
||||
this.applicationConfigurationOptionsManager.UpdateOptions(new object());
|
||||
});
|
||||
|
||||
action.Should().Throw<InvalidOperationException>();
|
||||
}
|
||||
}
|
||||
@@ -28,14 +28,14 @@ public class BuildTemplateManagerTests
|
||||
build.Primary.Should().Be(Profession.Assassin);
|
||||
build.Secondary.Should().Be(Profession.None);
|
||||
build.Attributes.Count.Should().Be(4);
|
||||
build.Attributes[0].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
build.Attributes[1].Attribute.Should().Be(Attribute.DaggerMastery);
|
||||
build.Attributes[1].Points.Should().Be(11);
|
||||
build.Attributes[2].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
build.Attributes[2].Points.Should().Be(1);
|
||||
build.Attributes[3].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
build.Attributes[3].Points.Should().Be(5);
|
||||
build.Attributes[0].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
build.Attributes[0].Points.Should().Be(11);
|
||||
build.Attributes[1].Attribute.Should().Be(Attribute.DeadlyArts);
|
||||
build.Attributes[1].Points.Should().Be(1);
|
||||
build.Attributes[2].Attribute.Should().Be(Attribute.ShadowArts);
|
||||
build.Attributes[2].Points.Should().Be(5);
|
||||
build.Attributes[3].Attribute.Should().Be(Attribute.CriticalStrikes);
|
||||
build.Attributes[3].Points.Should().Be(11);
|
||||
build.Skills.Count.Should().Be(8);
|
||||
build.Skills[0].Should().Be(Skill.UnsuspectingStrike);
|
||||
build.Skills[1].Should().Be(Skill.WildStrike);
|
||||
|
||||
@@ -34,33 +34,47 @@ EndProject
|
||||
Global
|
||||
GlobalSection(SolutionConfigurationPlatforms) = preSolution
|
||||
Debug|Any CPU = Debug|Any CPU
|
||||
Debug|x64 = Debug|x64
|
||||
Debug|x86 = Debug|x86
|
||||
Release|Any CPU = Release|Any CPU
|
||||
Release|x64 = Release|x64
|
||||
Release|x86 = Release|x86
|
||||
EndGlobalSection
|
||||
GlobalSection(ProjectConfigurationPlatforms) = postSolution
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x64.Build.0 = Debug|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Debug|x86.Build.0 = Debug|x86
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.ActiveCfg = Release|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x64.Build.0 = Release|x64
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x86.ActiveCfg = Release|x86
|
||||
{AA45C2B1-8BD0-466C-9271-699F168905AF}.Release|x86.Build.0 = Release|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x64.Build.0 = Debug|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Debug|x86.Build.0 = Debug|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x64.ActiveCfg = Release|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x64.Build.0 = Release|x64
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x86.ActiveCfg = Release|x86
|
||||
{C911C1C2-6566-419C-89C7-F802EB3FE709}.Release|x86.Build.0 = Release|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|Any CPU.ActiveCfg = Debug|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|Any CPU.Build.0 = Debug|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.ActiveCfg = Debug|x64
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x64.Build.0 = Debug|x64
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x86.ActiveCfg = Debug|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Debug|x86.Build.0 = Debug|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|Any CPU.ActiveCfg = Release|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|Any CPU.Build.0 = Release|Any CPU
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x64.ActiveCfg = Release|x64
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x64.Build.0 = Release|x64
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x86.ActiveCfg = Release|x86
|
||||
{4E2BB805-135D-4F02-8C53-3D8B6876D323}.Release|x86.Build.0 = Release|x86
|
||||
EndGlobalSection
|
||||
|
||||
@@ -0,0 +1,9 @@
|
||||
using System;
|
||||
|
||||
namespace Daybreak.Attributes;
|
||||
|
||||
[AttributeUsage(AttributeTargets.Class)]
|
||||
public sealed class OptionsNameAttribute : Attribute
|
||||
{
|
||||
public string? Name { get; init; }
|
||||
}
|
||||
@@ -1,44 +0,0 @@
|
||||
using Daybreak.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
public sealed class ApplicationConfiguration
|
||||
{
|
||||
[JsonProperty("SetGuildwarsWindowSizeOnLaunch")]
|
||||
public bool SetGuildwarsWindowSizeOnLaunch { get; set; }
|
||||
[JsonProperty("DesiredGuildwarsScreen")]
|
||||
public int DesiredGuildwarsScreen { get; set; }
|
||||
[JsonProperty("BrowsersEnabled")]
|
||||
public bool BrowsersEnabled { get; set; } = true;
|
||||
[JsonProperty("ToolboxPath")]
|
||||
public string? ToolboxPath { get; set; }
|
||||
[JsonProperty("TexmodPath")]
|
||||
public string? TexmodPath { get; set; }
|
||||
[JsonProperty("ToolboxAutoLaunch")]
|
||||
public bool ToolboxAutoLaunch { get; set; }
|
||||
[JsonProperty("LeftBrowserDefault")]
|
||||
public string? LeftBrowserDefault { get; set; } = "https://gwpvx.fandom.com/wiki/PvX_wiki";
|
||||
[JsonProperty("RightBrowserDefault")]
|
||||
public string? RightBrowserDefault { get; set; } = "https://wiki.guildwars.com/wiki/Quick_access_links";
|
||||
[JsonProperty("GuildwarsPaths")]
|
||||
public List<GuildwarsPath> GuildwarsPaths { get; set; } = new();
|
||||
[JsonProperty("ProtectedLoginCredentials")]
|
||||
public List<ProtectedLoginCredentials> ProtectedLoginCredentials { get; set; } = new();
|
||||
[JsonProperty("AddressBarReadonly")]
|
||||
public bool AddressBarReadonly { get; set; } = true;
|
||||
[JsonProperty("ExperimentalFeatures")]
|
||||
public ExperimentalFeatures ExperimentalFeatures { get; set; } = new();
|
||||
[JsonProperty("ShortcutLocation")]
|
||||
public string? ShortcutLocation { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
[JsonProperty("PlaceShortcut")]
|
||||
public bool PlaceShortcut { get; set; }
|
||||
[JsonProperty("AutoCheckUpdate")]
|
||||
public bool AutoCheckUpdate { get; set; } = true;
|
||||
[JsonProperty("ProtectedGraphAccessToken")]
|
||||
public string? ProtectedGraphAccessToken { get; set; }
|
||||
[JsonProperty("ProtectedGraphRefreshToken")]
|
||||
public string? ProtectedGraphRefreshToken { get; set; }
|
||||
}
|
||||
@@ -1,25 +0,0 @@
|
||||
using Daybreak.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
public sealed class ExperimentalFeatures
|
||||
{
|
||||
[JsonProperty("MultiLaunchSupport")]
|
||||
public bool MultiLaunchSupport { get; set; }
|
||||
[JsonProperty("ToolboxAutoLaunchDelay")]
|
||||
public int ToolboxAutoLaunchDelay { get; set; } = 5000;
|
||||
[JsonProperty("DynamicBuildLoading")]
|
||||
public bool DynamicBuildLoading { get; set; } = true;
|
||||
[JsonProperty("LaunchGuildwarsAsCurrentUser")]
|
||||
public bool LaunchGuildwarsAsCurrentUser { get; set; } = true;
|
||||
[JsonProperty("CanInterceptKeys")]
|
||||
public bool CanInterceptKeys { get; set; }
|
||||
[JsonProperty("DownloadIcons")]
|
||||
public bool DownloadIcons { get; set; }
|
||||
[JsonProperty("FocusViewEnabled")]
|
||||
public bool FocusViewEnabled { get; set; }
|
||||
[JsonProperty("Macros")]
|
||||
public List<KeyMacro> Macros { get; set; } = new();
|
||||
}
|
||||
@@ -0,0 +1,9 @@
|
||||
namespace Daybreak.Configuration.FocusView;
|
||||
|
||||
public enum ExperienceDisplay
|
||||
{
|
||||
TotalCurretAndTotalMax,
|
||||
CurrentLevelCurrentAndCurrentLevelMax,
|
||||
RemainingUntilNextLevel,
|
||||
Percentage
|
||||
}
|
||||
@@ -0,0 +1,8 @@
|
||||
namespace Daybreak.Configuration.FocusView;
|
||||
|
||||
public enum PointsDisplay
|
||||
{
|
||||
CurrentAndMax,
|
||||
Remaining,
|
||||
Percentage
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Browser")]
|
||||
public sealed class BrowserOptions
|
||||
{
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
public bool Enabled { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(AddressBarReadonly))]
|
||||
public bool AddressBarReadonly { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(DynamicBuildLoading))]
|
||||
public bool DynamicBuildLoading { get; set; } = true;
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Build Synchronization")]
|
||||
public sealed class BuildSynchronizationOptions
|
||||
{
|
||||
[JsonProperty(nameof(ProtectedGraphAccessToken))]
|
||||
public string? ProtectedGraphAccessToken { get; set; }
|
||||
[JsonProperty(nameof(ProtectedGraphRefreshToken))]
|
||||
public string? ProtectedGraphRefreshToken { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,45 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Configuration.FocusView;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Focus View")]
|
||||
public sealed class FocusViewOptions
|
||||
{
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[JsonProperty(nameof(MemoryReaderFrequency))]
|
||||
public double MemoryReaderFrequency { get; set; } = 16;
|
||||
|
||||
[JsonProperty(nameof(EnablePathfinding))]
|
||||
public bool EnablePathfinding { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(ExperienceDisplay))]
|
||||
public ExperienceDisplay ExperienceDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(KurzickPointsDisplay))]
|
||||
public PointsDisplay KurzickPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(LuxonPointsDisplay))]
|
||||
public PointsDisplay LuxonPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(BalthazarPointsDisplay))]
|
||||
public PointsDisplay BalthazarPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(ImperialPointsDisplay))]
|
||||
public PointsDisplay ImperialPointsDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(VanquishingDisplay))]
|
||||
public PointsDisplay VanquishingDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(HealthDisplay))]
|
||||
public PointsDisplay HealthDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(EnergyDisplay))]
|
||||
public PointsDisplay EnergyDisplay { get; set; }
|
||||
|
||||
[JsonProperty(nameof(BrowserUrl))]
|
||||
public string? BrowserUrl { get; set; } = "https://wiki.guildwars.com/wiki/Main_Page";
|
||||
}
|
||||
@@ -0,0 +1,41 @@
|
||||
using Daybreak.Attributes;
|
||||
using Daybreak.Models;
|
||||
using Newtonsoft.Json;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Launcher")]
|
||||
public sealed class LauncherOptions
|
||||
{
|
||||
[JsonProperty(nameof(SetGuildwarsWindowSizeOnLaunch))]
|
||||
public bool SetGuildwarsWindowSizeOnLaunch { get; set; }
|
||||
|
||||
[JsonProperty(nameof(DesiredGuildwarsScreen))]
|
||||
public int DesiredGuildwarsScreen { get; set; }
|
||||
|
||||
[JsonProperty(nameof(LaunchGuildwarsAsCurrentUser))]
|
||||
public bool LaunchGuildwarsAsCurrentUser { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(GuildwarsPaths))]
|
||||
public List<GuildwarsPath> GuildwarsPaths { get; set; } = new();
|
||||
|
||||
[JsonProperty(nameof(ProtectedLoginCredentials))]
|
||||
public List<ProtectedLoginCredentials> ProtectedLoginCredentials { get; set; } = new();
|
||||
|
||||
[JsonProperty(nameof(ShortcutLocation))]
|
||||
public string? ShortcutLocation { get; set; } = Environment.GetFolderPath(Environment.SpecialFolder.Desktop);
|
||||
|
||||
[JsonProperty(nameof(PlaceShortcut))]
|
||||
public bool PlaceShortcut { get; set; }
|
||||
|
||||
[JsonProperty(nameof(AutoCheckUpdate))]
|
||||
public bool AutoCheckUpdate { get; set; } = true;
|
||||
|
||||
[JsonProperty(nameof(MultiLaunchSupport))]
|
||||
public bool MultiLaunchSupport { get; set; }
|
||||
|
||||
[JsonProperty(nameof(DownloadIcons))]
|
||||
public bool DownloadIcons { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Daybreak.Attributes;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Screen Manager")]
|
||||
public sealed class ScreenManagerOptions
|
||||
{
|
||||
public double X { get; set; }
|
||||
public double Y { get; set; }
|
||||
public double Width { get; set; }
|
||||
public double Height { get; set; }
|
||||
public double DpiX { get; set; }
|
||||
public double DpiY { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,14 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "Toolbox")]
|
||||
public sealed class ToolboxOptions
|
||||
{
|
||||
[JsonProperty(nameof(Path))]
|
||||
public string? Path { get; set; }
|
||||
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
public bool Enabled { get; set; }
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
using Daybreak.Attributes;
|
||||
using Newtonsoft.Json;
|
||||
|
||||
namespace Daybreak.Configuration.Options;
|
||||
|
||||
[OptionsName(Name = "uMod")]
|
||||
public sealed class UModOptions
|
||||
{
|
||||
[JsonProperty(nameof(Path))]
|
||||
public string? Path { get; set; }
|
||||
|
||||
[JsonProperty(nameof(Enabled))]
|
||||
public bool Enabled { get; set; }
|
||||
|
||||
[JsonProperty(nameof(AutoEnableMods))]
|
||||
public bool AutoEnableMods { get; set; }
|
||||
}
|
||||
@@ -1,7 +1,6 @@
|
||||
using Daybreak.Services.ApplicationLauncher;
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.Configuration;
|
||||
using Daybreak.Services.Credentials;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Logging;
|
||||
@@ -24,23 +23,44 @@ using Microsoft.CorrelationVector;
|
||||
using System.Logging;
|
||||
using Daybreak.Services.Updater.PostUpdate;
|
||||
using System.Core.Extensions;
|
||||
using Daybreak.Services.Updater.PostUpdate.Actions;
|
||||
using Daybreak.Services.Graph;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Onboarding;
|
||||
using Daybreak.Services.Menu;
|
||||
using Daybreak.Services.Scanner;
|
||||
using Daybreak.Services.Experience;
|
||||
using Daybreak.Services.Metrics;
|
||||
using Daybreak.Services.Monitoring;
|
||||
using System.Net.Http.Headers;
|
||||
using Daybreak.Services.Downloads;
|
||||
using Daybreak.Services.ExceptionHandling;
|
||||
using Daybreak.Services.Pathfinding;
|
||||
using Daybreak.Services.Startup;
|
||||
using Daybreak.Services.Startup.Actions;
|
||||
using Daybreak.Services.Drawing;
|
||||
using Daybreak.Services.Drawing.Modules.Entities;
|
||||
using Daybreak.Services.Drawing.Modules.MapIcons;
|
||||
using Daybreak.Services.Drawing.Modules;
|
||||
using Daybreak.Services.Guildwars;
|
||||
using Daybreak.Configuration.Options;
|
||||
using System.Configuration;
|
||||
using Daybreak.Services.UMod;
|
||||
using Daybreak.Services.Toolbox;
|
||||
using Daybreak.Views.Onboarding.UMod;
|
||||
using Daybreak.Views.Onboarding.Toolbox;
|
||||
|
||||
namespace Daybreak.Configuration;
|
||||
|
||||
public static class ProjectConfiguration
|
||||
{
|
||||
private const string DaybreakUserAgent = "Daybreak";
|
||||
|
||||
public static void RegisterResolvers(IServiceManager serviceManager)
|
||||
{
|
||||
serviceManager.ThrowIfNull();
|
||||
|
||||
serviceManager.RegisterOptionsManager<ApplicationConfigurationOptionsManager>();
|
||||
serviceManager.RegisterOptionsManager<OptionsManager>();
|
||||
serviceManager.RegisterResolver(new LoggerResolver());
|
||||
serviceManager
|
||||
.RegisterHttpClient<ApplicationUpdater>()
|
||||
@@ -49,6 +69,7 @@ public static class ProjectConfiguration
|
||||
var logger = sp.GetService<ILogger<ApplicationUpdater>>();
|
||||
return new LoggingHttpMessageHandler(logger!) { InnerHandler = new HttpClientHandler() };
|
||||
})
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<BloogumClient>()
|
||||
.WithMessageHandler(sp =>
|
||||
@@ -56,6 +77,7 @@ public static class ProjectConfiguration
|
||||
var logger = sp.GetService<ILogger<BloogumClient>>();
|
||||
return new LoggingHttpMessageHandler(logger!) { InnerHandler = new HttpClientHandler() };
|
||||
})
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<GraphClient>()
|
||||
.WithMessageHandler(sp =>
|
||||
@@ -63,6 +85,15 @@ public static class ProjectConfiguration
|
||||
var logger = sp.GetService<ILogger<GraphClient>>();
|
||||
return new LoggingHttpMessageHandler(logger!) { InnerHandler = new HttpClientHandler() };
|
||||
})
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.Build()
|
||||
.RegisterHttpClient<DownloadService>()
|
||||
.WithMessageHandler(sp =>
|
||||
{
|
||||
var logger = sp.GetService<ILogger<GraphClient>>();
|
||||
return new LoggingHttpMessageHandler(logger!) { InnerHandler = new HttpClientHandler() };
|
||||
})
|
||||
.WithDefaultRequestHeadersSetup(SetupDaybreakUserAgent)
|
||||
.Build();
|
||||
}
|
||||
|
||||
@@ -86,6 +117,8 @@ public static class ProjectConfiguration
|
||||
|
||||
services.AddScoped((sp) => new ScopeMetadata(new CorrelationVector()));
|
||||
services.AddSingleton<ViewManager>();
|
||||
services.AddSingleton<ProcessorUsageMonitor>();
|
||||
services.AddSingleton<MemoryUsageMonitor>();
|
||||
services.AddSingleton<IViewManager, ViewManager>(sp => sp.GetRequiredService<ViewManager>());
|
||||
services.AddSingleton<IViewProducer, ViewManager>(sp => sp.GetRequiredService<ViewManager>());
|
||||
services.AddSingleton<PostUpdateActionManager>();
|
||||
@@ -94,12 +127,15 @@ public static class ProjectConfiguration
|
||||
services.AddSingleton<IPostUpdateActionProvider>(sp => sp.GetRequiredService<PostUpdateActionManager>());
|
||||
services.AddSingleton<IMenuService, MenuService>();
|
||||
services.AddSingleton<IMenuServiceInitializer, MenuService>(sp => sp.GetRequiredService<IMenuService>().As<MenuService>());
|
||||
services.AddSingleton<IConfigurationManager, ConfigurationManager>();
|
||||
services.AddSingleton<ILiteDatabase, LiteDatabase>(sp => new LiteDatabase("Daybreak.db"));
|
||||
services.AddSingleton<IMutexHandler, MutexHandler>();
|
||||
services.AddSingleton<IShortcutManager, ShortcutManager>();
|
||||
services.AddSingleton<IIconBrowser, IconBrowser>();
|
||||
services.AddSingleton<IIconDownloader, IconDownloader>();
|
||||
services.AddSingleton<IMetricsService, MetricsService>();
|
||||
services.AddSingleton<IStartupActionProducer, StartupActionManager>();
|
||||
services.AddSingleton<IOptionsProducer, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().As<OptionsManager>());
|
||||
services.AddSingleton<IOptionsUpdateHook, OptionsManager>(sp => sp.GetRequiredService<IOptionsManager>().As<OptionsManager>());
|
||||
services.AddScoped<ICredentialManager, CredentialManager>();
|
||||
services.AddScoped<IApplicationLauncher, ApplicationLauncher>();
|
||||
services.AddScoped<IScreenshotProvider, ScreenshotProvider>();
|
||||
@@ -113,6 +149,17 @@ public static class ProjectConfiguration
|
||||
services.AddScoped<IOnboardingService, OnboardingService>();
|
||||
services.AddScoped<IGuildwarsMemoryReader, GuildwarsMemoryReader>();
|
||||
services.AddScoped<IMemoryScanner, MemoryScanner>();
|
||||
services.AddScoped<IExperienceCalculator, ExperienceCalculator>();
|
||||
services.AddScoped<IAttributePointCalculator, AttributePointCalculator>();
|
||||
services.AddScoped<IDownloadService, DownloadService>();
|
||||
services.AddScoped<IGuildwarsInstaller, GuildwarsInstaller>();
|
||||
services.AddScoped<IGuildwarsEntityDebouncer, GuildwarsEntityDebouncer>();
|
||||
services.AddScoped<IExceptionHandler, ExceptionHandler>();
|
||||
services.AddScoped<IPathfinder, StupidPathfinder>();
|
||||
services.AddScoped<IDrawingService, DrawingService>();
|
||||
services.AddScoped<IDrawingModuleProducer, DrawingService>(sp => sp.GetRequiredService<IDrawingService>().As<DrawingService>());
|
||||
services.AddScoped<IUModService, UModService>();
|
||||
services.AddScoped<IToolboxService, ToolboxService>();
|
||||
}
|
||||
|
||||
public static void RegisterViews(IViewProducer viewProducer)
|
||||
@@ -120,6 +167,7 @@ public static class ProjectConfiguration
|
||||
viewProducer.ThrowIfNull();
|
||||
|
||||
viewProducer.RegisterPermanentView<LauncherView>();
|
||||
viewProducer.RegisterPermanentView<Views.FocusView>();
|
||||
viewProducer.RegisterView<SettingsView>();
|
||||
viewProducer.RegisterView<AskUpdateView>();
|
||||
viewProducer.RegisterView<UpdateView>();
|
||||
@@ -135,14 +183,80 @@ public static class ProjectConfiguration
|
||||
viewProducer.RegisterView<IconDownloadView>();
|
||||
viewProducer.RegisterView<GraphAuthorizationView>();
|
||||
viewProducer.RegisterView<BuildsSynchronizationView>();
|
||||
viewProducer.RegisterView<OnboardingView>();
|
||||
viewProducer.RegisterView<FocusView>();
|
||||
viewProducer.RegisterView<LauncherOnboardingView>();
|
||||
viewProducer.RegisterView<MetricsView>();
|
||||
viewProducer.RegisterView<GuildwarsDownloadView>();
|
||||
viewProducer.RegisterView<UModInstallingView>();
|
||||
viewProducer.RegisterView<UModInstallationChoiceView>();
|
||||
viewProducer.RegisterView<UModOnboardingEntryView>();
|
||||
viewProducer.RegisterView<UModSwitchView>();
|
||||
viewProducer.RegisterView<UModBrowserView>();
|
||||
viewProducer.RegisterView<ToolboxInstallationView>();
|
||||
viewProducer.RegisterView<ToolboxInstallationChoiceView>();
|
||||
viewProducer.RegisterView<ToolboxOnboardingEntryView>();
|
||||
viewProducer.RegisterView<ToolboxSwitchView>();
|
||||
viewProducer.RegisterView<ToolboxHomepageView>();
|
||||
}
|
||||
|
||||
public static void RegisterStartupActions(IStartupActionProducer startupActionProducer)
|
||||
{
|
||||
startupActionProducer.ThrowIfNull();
|
||||
|
||||
startupActionProducer.RegisterAction<RenameInstallerAction>();
|
||||
}
|
||||
|
||||
public static void RegisterPostUpdateActions(IPostUpdateActionProducer postUpdateActionProducer)
|
||||
{
|
||||
postUpdateActionProducer.ThrowIfNull();
|
||||
}
|
||||
|
||||
postUpdateActionProducer.AddPostUpdateAction<RenameInstallerAction>();
|
||||
public static void RegisterDrawingModules(IDrawingModuleProducer drawingModuleProducer)
|
||||
{
|
||||
drawingModuleProducer.ThrowIfNull();
|
||||
|
||||
|
||||
drawingModuleProducer.RegisterDrawingModule<DeadEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<NeutralEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<AlliedCreatureEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<AllyEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<BossEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<EnemyEntityDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<NpcEntityDrawingModule>();
|
||||
|
||||
drawingModuleProducer.RegisterDrawingModule<ResurrectionShrineDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<CollectorDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<GateDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<StairsDownDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<StairsUpDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<CircledStarDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<AreaMapDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<DungeonBossDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<DungeonKeyDrawingModule>();
|
||||
|
||||
drawingModuleProducer.RegisterDrawingModule<PathfindingDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<PlayerPositionHistoryDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<QuestObjectiveDrawingModule>();
|
||||
|
||||
drawingModuleProducer.RegisterDrawingModule<MainPlayerDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<PartyMemberDrawingModule>();
|
||||
drawingModuleProducer.RegisterDrawingModule<WorldPlayerDrawingModule>();
|
||||
}
|
||||
|
||||
public static void RegisterOptions(IOptionsProducer optionsProducer)
|
||||
{
|
||||
optionsProducer.ThrowIfNull();
|
||||
|
||||
optionsProducer.RegisterOptions<BrowserOptions>();
|
||||
optionsProducer.RegisterOptions<BuildSynchronizationOptions>();
|
||||
optionsProducer.RegisterOptions<FocusViewOptions>();
|
||||
optionsProducer.RegisterOptions<LauncherOptions>();
|
||||
optionsProducer.RegisterOptions<ToolboxOptions>();
|
||||
optionsProducer.RegisterOptions<UModOptions>();
|
||||
optionsProducer.RegisterOptions<ScreenManagerOptions>();
|
||||
}
|
||||
|
||||
private static void SetupDaybreakUserAgent(HttpRequestHeaders httpRequestHeaders)
|
||||
{
|
||||
httpRequestHeaders.ThrowIfNull().TryAddWithoutValidation("User-Agent", DaybreakUserAgent);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Ellipse x:Name="BackgroundEllipse" Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Visibility="Visible" Opacity="0.1" />
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -4,8 +4,9 @@
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="50" d:DesignWidth="50">
|
||||
<Grid>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
xmlns:behaviors="clr-namespace:Daybreak.Behaviors"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
@@ -20,13 +21,12 @@
|
||||
FontStretch="{Binding ElementName=_this, Path=FontStretch, Mode=OneWay}"
|
||||
FontWeight="{Binding ElementName=_this, Path=FontWeight, Mode=OneWay}"
|
||||
FontStyle="{Binding ElementName=_this, Path=FontStyle, Mode=OneWay}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"></TextBlock>
|
||||
VerticalAlignment="{Binding ElementName=_this, Path=TextVerticalAlignment, Mode=OneWay}"
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=TextHorizontalAlignment, Mode=OneWay}"></TextBlock>
|
||||
<Rectangle Fill="{Binding ElementName=_this, Path=Highlight, Mode=OneWay}"
|
||||
Opacity="{Binding ElementName=_this, Path=HighlightOpacity, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=HighlightVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"></Rectangle>
|
||||
<Rectangle MouseEnter="Rectangle_MouseEnter" MouseLeave="Rectangle_MouseLeave"
|
||||
MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Fill="Transparent"
|
||||
Cursor="Hand"></Rectangle>
|
||||
MouseLeftButtonDown="Rectangle_MouseLeftButtonDown" Fill="Transparent"></Rectangle>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -26,6 +26,10 @@ public partial class OpaqueButton : UserControl
|
||||
public double highlightOpacity;
|
||||
[GenerateDependencyProperty]
|
||||
public bool highlightVisible;
|
||||
[GenerateDependencyProperty(InitialValue = VerticalAlignment.Center)]
|
||||
public VerticalAlignment textVerticalAlignment;
|
||||
[GenerateDependencyProperty(InitialValue = HorizontalAlignment.Center)]
|
||||
public HorizontalAlignment textHorizontalAlignment;
|
||||
|
||||
public OpaqueButton()
|
||||
{
|
||||
|
||||
@@ -5,6 +5,7 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
|
||||
@@ -6,6 +6,7 @@
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
|
||||
@@ -8,6 +8,7 @@
|
||||
xmlns:behaviors="clr-namespace:Daybreak.Behaviors"
|
||||
xmlns:converters="clr-namespace:Daybreak.Converters"
|
||||
x:Name="_this"
|
||||
Cursor="Hand"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
|
||||
@@ -9,6 +9,7 @@
|
||||
mc:Ignorable="d"
|
||||
Unloaded="UserControl_Unloaded"
|
||||
x:Name="_this"
|
||||
Initialized="UserControl_Initialized"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<converters:BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter" TriggerValue="True"></converters:BooleanToVisibilityConverter>
|
||||
@@ -19,7 +20,7 @@
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<StackPanel Margin="10">
|
||||
<local:OpaqueButton Text="Load build template" Foreground="White" Background="#F0202020" BackgroundOpacity="0.4"
|
||||
<local:OpaqueButton Text="Load build template" Foreground="White" Background="#F0212121" BackgroundOpacity="0.4"
|
||||
Clicked="LoadBuildTemplateButton_Click" FontSize="16" Height="40" Width="200"></local:OpaqueButton>
|
||||
</StackPanel>
|
||||
</ControlTemplate>
|
||||
@@ -33,7 +34,7 @@
|
||||
</Grid.RowDefinitions>
|
||||
<wv2:WebView2 x:Name="WebBrowser" Source="{Binding ElementName=_this, Path=Address, Mode=TwoWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"></wv2:WebView2>
|
||||
<Grid Grid.Row="1" Background="#80808080" IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
<Grid Grid.Row="1" Background="#F0212121" IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=ControlsEnabled, Mode=OneWay, Converter={StaticResource ReverseBooleanToVisibilityConverter}}">
|
||||
<Grid.ColumnDefinitions>
|
||||
<ColumnDefinition Width="auto"></ColumnDefinition>
|
||||
@@ -69,17 +70,19 @@
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"></TextBox>
|
||||
<StackPanel Grid.Column="2" Orientation="Horizontal">
|
||||
<local:HomeButton Width="30" Height="30" Margin="5"
|
||||
Visibility="{Binding ElementName=_this, Path=HomeButtonVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="HomeButton_Clicked"></local:HomeButton>
|
||||
<local:StarGlyph Height="30" Width="30" Margin="5"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="StarGlyph_Clicked" x:Name="FavoriteButton"></local:StarGlyph>
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Visibility="{Binding ElementName=_this, Path=HomeButtonVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="StarGlyph_Clicked" x:Name="FavoriteButton"></local:StarGlyph>
|
||||
<local:MaximizeButton Height="30" Width="30" Margin="5"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="MaximizeButton_Clicked"></local:MaximizeButton>
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
IsEnabled="{Binding ElementName=_this, Path=BrowserSupported, Mode=OneWay}"
|
||||
Clicked="MaximizeButton_Clicked"></local:MaximizeButton>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
<Grid Grid.RowSpan="2" Background="Gray"
|
||||
@@ -95,6 +98,5 @@
|
||||
<TextBlock Foreground="White" Text="Restart after the installation." FontSize="26" TextWrapping="Wrap" />
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Models.Browser;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
@@ -8,8 +8,12 @@ using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Web.WebView2.Core;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Diagnostics;
|
||||
using System.Extensions;
|
||||
using System.Globalization;
|
||||
using System.IO;
|
||||
using System.Text.RegularExpressions;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -26,23 +30,32 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
{
|
||||
public static readonly DependencyProperty AddressProperty =
|
||||
DependencyPropertyExtensions.Register<ChromiumBrowserWrapper, string>(nameof(Address));
|
||||
|
||||
|
||||
private const string BrowserSearchPlaceholder = "[PLACEHOLDER]";
|
||||
private const string BrowserSearchLink = $"https://www.google.com/search?q={BrowserSearchPlaceholder}";
|
||||
private const string BrowserDownloadLink = "https://developer.microsoft.com/en-us/microsoft-edge/webview2/";
|
||||
|
||||
private static readonly Regex WebAddressRegex = new("^((http|ftp|https)://)?([\\w_-]+(?:(?:\\.[\\w_-]+)+))([\\w.,@?^=%&:/~+#-]*[\\w@?^=%&/~+#-])?", RegexOptions.Compiled);
|
||||
|
||||
private static CoreWebView2Environment? coreWebView2Environment;
|
||||
|
||||
public event EventHandler<string>? FavoriteUriChanged;
|
||||
public event EventHandler? MaximizeClicked;
|
||||
public event EventHandler<Build>? BuildDecoded;
|
||||
public event EventHandler<DownloadPayload>? DownloadingFile;
|
||||
public event EventHandler<string>? DownloadedFile;
|
||||
|
||||
private ILiveOptions<ApplicationConfiguration>? liveOptions;
|
||||
private ILogger<ChromiumBrowserWrapper>? logger;
|
||||
private IBuildTemplateManager? buildTemplateManager;
|
||||
private readonly Task initializationTask;
|
||||
private readonly ILiveOptions<BrowserOptions>? liveOptions;
|
||||
private readonly ILogger<ChromiumBrowserWrapper>? logger;
|
||||
private readonly IBuildTemplateManager? buildTemplateManager;
|
||||
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool canDownloadBuild;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool canNavigate;
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool canDownloadFiles;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool controlsEnabled;
|
||||
[GenerateDependencyProperty(InitialValue = null)]
|
||||
@@ -57,6 +70,13 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
private string favoriteAddress = string.Empty;
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool preventDispose;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool homeButtonVisible = true;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool favoriteButtonVisible = true;
|
||||
[GenerateDependencyProperty]
|
||||
private string downloadsDirectory = string.Empty;
|
||||
|
||||
public string Address
|
||||
{
|
||||
get => this.GetTypedValue<string>(AddressProperty);
|
||||
@@ -70,9 +90,23 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
}
|
||||
|
||||
public ChromiumBrowserWrapper()
|
||||
: this(Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<BrowserOptions>>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBuildTemplateManager>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILogger<ChromiumBrowserWrapper>>())
|
||||
{
|
||||
}
|
||||
|
||||
public ChromiumBrowserWrapper(
|
||||
ILiveOptions<BrowserOptions> liveOptions,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> logger)
|
||||
{
|
||||
this.liveOptions = liveOptions.ThrowIfNull();
|
||||
this.buildTemplateManager = buildTemplateManager.ThrowIfNull();
|
||||
this.logger = logger.ThrowIfNull();
|
||||
this.initializationTask = this.InitializeBrowser();
|
||||
|
||||
this.InitializeComponent();
|
||||
this.WebBrowser.IsEnabled = false;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
@@ -84,35 +118,22 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
}
|
||||
}
|
||||
|
||||
public async Task InitializeDefaultBrowser()
|
||||
public async Task ReinitializeBrowser()
|
||||
{
|
||||
var options = Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<ApplicationConfiguration>>();
|
||||
var buildTemplateManager = Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IBuildTemplateManager>();
|
||||
var logger = Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILogger<ChromiumBrowserWrapper>>();
|
||||
|
||||
await this.InitializeDefaultBrowser(options, buildTemplateManager, logger);
|
||||
}
|
||||
|
||||
public async Task InitializeDefaultBrowser(
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> logger)
|
||||
{
|
||||
this.liveOptions = liveOptions;
|
||||
this.buildTemplateManager = buildTemplateManager;
|
||||
this.logger = logger;
|
||||
this.InitializeEnvironment();
|
||||
await this.InitializeBrowser();
|
||||
}
|
||||
|
||||
public async void ReinitializeBrowser()
|
||||
public Task InitializationTask() => this.initializationTask;
|
||||
|
||||
private async void UserControl_Initialized(object sender, EventArgs e)
|
||||
{
|
||||
this.InitializeEnvironment();
|
||||
await this.InitializeBrowser();
|
||||
}
|
||||
|
||||
private void InitializeEnvironment()
|
||||
{
|
||||
if (this.liveOptions!.Value.BrowsersEnabled is false)
|
||||
if (this.liveOptions!.Value.Enabled is false)
|
||||
{
|
||||
this.BrowserSupported = false;
|
||||
return;
|
||||
@@ -120,7 +141,11 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
|
||||
try
|
||||
{
|
||||
coreWebView2Environment ??= System.Extensions.TaskExtensions.RunSync(() => CoreWebView2Environment.CreateAsync(null, "BrowserData", null));
|
||||
coreWebView2Environment ??= System.Extensions.TaskExtensions.RunSync(() => CoreWebView2Environment.CreateAsync(null, "BrowserData", new CoreWebView2EnvironmentOptions
|
||||
{
|
||||
EnableTrackingPrevention = true,
|
||||
AllowSingleSignOnUsingOSPrimaryAccount = true
|
||||
}));
|
||||
|
||||
this.BrowserSupported = true;
|
||||
}
|
||||
@@ -139,7 +164,7 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
this.BrowserEnabled = true;
|
||||
await this.WebBrowser.EnsureCoreWebView2Async(coreWebView2Environment);
|
||||
this.AddressBarReadonly = this.liveOptions!.Value.AddressBarReadonly;
|
||||
this.CanDownloadBuild = this.liveOptions.Value.ExperimentalFeatures.DynamicBuildLoading;
|
||||
this.CanDownloadBuild = this.liveOptions.Value.DynamicBuildLoading;
|
||||
this.WebBrowser.CoreWebView2.NewWindowRequested += (browser, args) => args.Handled = true;
|
||||
this.WebBrowser.NavigationStarting += (browser, args) =>
|
||||
{
|
||||
@@ -152,6 +177,35 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
this.Navigating = true;
|
||||
}
|
||||
};
|
||||
this.WebBrowser.CoreWebView2.DownloadStarting += (browser, args) =>
|
||||
{
|
||||
if (this.CanDownloadFiles is false)
|
||||
{
|
||||
this.logger?.LogInformation("Downloads are disallowed. Cancelling download");
|
||||
args.Cancel = true;
|
||||
}
|
||||
|
||||
if (this.DownloadsDirectory.IsNullOrWhiteSpace())
|
||||
{
|
||||
this.logger?.LogInformation("No downloads directory specified. Downloading to default directory");
|
||||
return;
|
||||
}
|
||||
|
||||
var fileName = Path.GetFileName(args.ResultFilePath);
|
||||
var finalPath = Path.GetFullPath(Path.Combine(this.DownloadsDirectory, fileName));
|
||||
var downloadPayload = new DownloadPayload { ResultingFilePath = finalPath, CanDownload = true };
|
||||
this.DownloadingFile?.Invoke(this, downloadPayload);
|
||||
if (!downloadPayload.CanDownload)
|
||||
{
|
||||
args.Cancel = true;
|
||||
this.logger?.LogInformation("Download blocked by handler. Cancelling download");
|
||||
return;
|
||||
}
|
||||
|
||||
args.ResultFilePath = finalPath;
|
||||
|
||||
args.DownloadOperation.StateChanged += this.DownloadOperation_StateChanged;
|
||||
};
|
||||
this.WebBrowser.NavigationCompleted += (browser, args) => this.Navigating = false;
|
||||
this.WebBrowser.WebMessageReceived += this.CoreWebView2_WebMessageReceived!;
|
||||
this.WebBrowser.CoreWebView2.Settings.AreDevToolsEnabled = false;
|
||||
@@ -188,14 +242,19 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
{
|
||||
if (e.Key == System.Windows.Input.Key.Enter)
|
||||
{
|
||||
var newAddress = sender.As<TextBox>().Text;
|
||||
newAddress = SanitizeAddress(newAddress);
|
||||
if (newAddress.IsNullOrWhiteSpace())
|
||||
var input = sender.As<TextBox>().Text;
|
||||
var maybeAddress = SanitizeAddress(input);
|
||||
// If input is address, navigate to address. Otherwise search for the text input in Google
|
||||
if (Uri.TryCreate(maybeAddress, UriKind.Absolute, out _))
|
||||
{
|
||||
return;
|
||||
this.Address = maybeAddress;
|
||||
}
|
||||
else
|
||||
{
|
||||
var address = BrowserSearchLink.Replace(BrowserSearchPlaceholder, maybeAddress);
|
||||
this.Address = address;
|
||||
}
|
||||
|
||||
this.Address = newAddress;
|
||||
this.WebBrowser.CoreWebView2.Navigate(this.Address);
|
||||
e.Handled = true;
|
||||
}
|
||||
@@ -251,6 +310,24 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
}
|
||||
}
|
||||
|
||||
private void DownloadOperation_StateChanged(object? sender, object? e)
|
||||
{
|
||||
if (sender is not CoreWebView2DownloadOperation downloadOperation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (downloadOperation.State != CoreWebView2DownloadState.Completed &&
|
||||
downloadOperation.State != CoreWebView2DownloadState.Interrupted)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
downloadOperation.StateChanged -= this.DownloadOperation_StateChanged;
|
||||
var filePath = Path.GetFullPath(downloadOperation.ResultFilePath);
|
||||
this.DownloadedFile?.Invoke(this, filePath);
|
||||
}
|
||||
|
||||
private void LoadBuildTemplateButton_Click(object sender, EventArgs e)
|
||||
{
|
||||
var build = this.ContextMenu.DataContext.As<Build>();
|
||||
@@ -326,6 +403,11 @@ public partial class ChromiumBrowserWrapper : UserControl
|
||||
return default!;
|
||||
}
|
||||
|
||||
if (WebAddressRegex.IsMatch(address) is false)
|
||||
{
|
||||
return address;
|
||||
}
|
||||
|
||||
if (address.StartsWith("www") is false &&
|
||||
address.StartsWith("http") is false)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,38 @@
|
||||
<UserControl x:Class="Daybreak.Controls.ExpandableMenuSection"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<StackPanel Orientation="Vertical"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch">
|
||||
<buttons:MenuButton
|
||||
Cursor="Hand"
|
||||
HighlightColor="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Title="{Binding ElementName=_this, Path=SectionTitle, Mode=OneWay}"
|
||||
FontSize="{Binding ElementName=_this, Path=FontSize, Mode=OneWay}"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Clicked="MenuButton_Clicked"
|
||||
IsEnabled="{Binding ElementName=_this, Path=ExpanderButtonEnabled, Mode=OneWay}"
|
||||
Height="30"></buttons:MenuButton>
|
||||
<Rectangle Fill="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Height="1"
|
||||
HorizontalAlignment="Stretch"></Rectangle>
|
||||
<Grid MaxHeight="{Binding ElementName=_this, Path=ExpanderHeight, Mode=OneWay}"
|
||||
Margin="10, 0, 0, 0">
|
||||
<ItemsControl x:Name="ContentListView"
|
||||
ItemsSource="{Binding ElementName=_this, Path=Children, Mode=OneWay}"
|
||||
Background="Transparent"
|
||||
BorderThickness="0"></ItemsControl>
|
||||
</Grid>
|
||||
</StackPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,65 @@
|
||||
using System;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media.Animation;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
/// <summary>
|
||||
/// Interaction logic for ExpandableMenuSection.xaml
|
||||
/// </summary>
|
||||
public partial class ExpandableMenuSection : UserControl
|
||||
{
|
||||
[GenerateDependencyProperty]
|
||||
private string sectionTitle = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private double expanderHeight = 0;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool expanderButtonEnabled;
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool expanded = false;
|
||||
|
||||
public ObservableCollection<FrameworkElement> Children { get; } = new ObservableCollection<FrameworkElement>();
|
||||
|
||||
public ExpandableMenuSection()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void MenuButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.ExpanderButtonEnabled = false;
|
||||
var desiredHeight = 0d;
|
||||
foreach (var child in this.Children)
|
||||
{
|
||||
desiredHeight += child.DesiredSize.Height > 0 ?
|
||||
child.DesiredSize.Height :
|
||||
child.Height;
|
||||
}
|
||||
|
||||
var doubleAnimation = new DoubleAnimation();
|
||||
|
||||
if (this.expanded)
|
||||
{
|
||||
doubleAnimation.From = desiredHeight;
|
||||
doubleAnimation.To = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
doubleAnimation.From = 0;
|
||||
doubleAnimation.To = desiredHeight;
|
||||
}
|
||||
|
||||
doubleAnimation.AccelerationRatio = 0.3;
|
||||
doubleAnimation.DecelerationRatio = 0.3;
|
||||
doubleAnimation.Duration = TimeSpan.FromMilliseconds(100);
|
||||
doubleAnimation.Completed += (_, _) =>
|
||||
{
|
||||
this.Expanded = !this.Expanded;
|
||||
this.ExpanderButtonEnabled = true;
|
||||
};
|
||||
|
||||
this.BeginAnimation(ExpanderHeightProperty, doubleAnimation);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,18 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Glyphs.DownloadGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" StrokeThickness="3"
|
||||
Data="m32,30.454c0,0 8.312,0 9.098,0c4.365,0 7.902,-3.537 7.902,-7.901s-3.537,-7.902 -7.902,-7.902c-0.02,0 -0.038,0.003 -0.058,0.003c0.061,-0.494 0.103,-0.994 0.103,-1.504c0,-6.71 -5.439,-12.15 -12.15,-12.15c-5.229,0 -9.672,3.309 -11.386,7.941c-1.087,-1.089 -2.591,-1.764 -4.251,-1.764c-3.319,0 -6.009,2.69 -6.009,6.008c0,0.085 0.01,0.167 0.013,0.251c-3.665,1.013 -6.36,4.362 -6.36,8.349c0,4.788 3.881,8.669 8.67,8.669c0.827,0 8.33,0 8.33,0"></Path>
|
||||
<Polyline Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" Points="30,36 25,41 20,36" StrokeThickness="3"></Polyline>
|
||||
<Line X1="25" X2="25" Y1="21" Y2="41" Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}" StrokeThickness="3"></Line>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.Glyphs;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for DownloadGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class DownloadGlyph : UserControl
|
||||
{
|
||||
public DownloadGlyph()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
|
||||
@@ -1,17 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
|
||||
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Glyphs.GWToolboxGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<TextBlock Text="G" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></TextBlock>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls.Glyphs;
|
||||
/// <summary>
|
||||
/// Interaction logic for GWToolboxGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class GWToolboxGlyph : UserControl
|
||||
{
|
||||
public GWToolboxGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,20 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Glyphs.GaugeGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m13.5,13.5c1.44772,-1.44772 2.5,-3.29086 2.5,-5.5c0,-4.41828 -3.58172,-8 -8,-8s-8,3.58172 -8,8c0,2.20914 1.05228,4.05228 2.5,5.5"></Path>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m8,8l-4,-4"></Path>
|
||||
<Ellipse Margin="6, 7.5, 6, 6" Width="1.5" Height="1.5"
|
||||
Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.Glyphs;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for GaugeGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class GaugeGlyph : UserControl
|
||||
{
|
||||
public GaugeGlyph()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,4 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
|
||||
@@ -0,0 +1,28 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Glyphs.MapGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<Grid>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m18.53,14.53a9.37,9.37 0 0 1 -9.26,9.47l0,0a9.5,9.5 0 0 1 -3.26,-18.33a9.61,9.61 0 0 0 0.77,1.82a14.22,14.22 0 0 0 2.51,3.25a14.06,14.06 0 0 0 2.49,-3.24a9.2,9.2 0 0 0 0.75,-1.83a9.47,9.47 0 0 1 6,8.86z"></Path>
|
||||
<Polyline Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Points="9.270000457763672,24 9.270000457763672,23.989999771118164 9.270000457763672,10.739999771118164"></Polyline>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m9.27,24l0,0c-0.32,-0.22 -5.27,-3.85 -4.94,-10.1a11.36,11.36 0 0 1 2.44,-6.4"></Path>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m9.25,24a0,0 0 0 1 0,0l0,0c0.4,-0.29 5.25,-3.91 4.92,-10.1a11.35,11.35 0 0 0 -2.43,-6.39"></Path>
|
||||
<Line Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
X1="0" X2="18.53" Y1="14.53" Y2="14.53"></Line>
|
||||
<Path Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Data="m12.35,1.89a3.81,3.81 0 0 0 -3.08,-1.89a3.82,3.82 0 0 0 -3.09,1.89a4.75,4.75 0 0 0 -0.19,3.78a9.61,9.61 0 0 0 0.77,1.82a14.22,14.22 0 0 0 2.51,3.25a14.06,14.06 0 0 0 2.49,-3.24a9.2,9.2 0 0 0 0.77,-1.83a4.79,4.79 0 0 0 -0.18,-3.78z"></Path>
|
||||
<Ellipse Stroke="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Width="1.24" Height="1.26" Margin="8.6, 3" HorizontalAlignment="Left" VerticalAlignment="Top"></Ellipse>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls.Glyphs;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MapGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class MapGlyph : UserControl
|
||||
{
|
||||
public MapGlyph()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Glyphs.UModGlyph"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Viewbox>
|
||||
<TextBlock Text="U" Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"></TextBlock>
|
||||
</Viewbox>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,26 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Documents;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Navigation;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls.Glyphs;
|
||||
/// <summary>
|
||||
/// Interaction logic for UModGlyph.xaml
|
||||
/// </summary>
|
||||
public partial class UModGlyph : UserControl
|
||||
{
|
||||
public UModGlyph()
|
||||
{
|
||||
InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,87 @@
|
||||
<UserControl x:Class="Daybreak.Controls.GuildwarsMinimap"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
x:Name="_this"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800"
|
||||
MouseWheel="GuildwarsMinimap_MouseWheel"
|
||||
MouseLeftButtonDown="GuildwarsMinimap_MouseLeftButtonDown"
|
||||
MouseLeftButtonUp="GuildwarsMinimap_MouseLeftButtonUp"
|
||||
MouseRightButtonDown="GuildwarsMinimap_MouseRightButtonDown"
|
||||
MouseRightButtonUp="GuildwarsMinimap_MouseRightButtonUp"
|
||||
MouseMove="GuildwarsMinimap_MouseMove"
|
||||
Loaded="GuildwarsMinimap_Loaded"
|
||||
Unloaded="GuildwarsMinimap_Unloaded">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
<ContextMenu x:Key="WorldPlayerContextMenu">
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<local:WorldPlayerContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"></local:WorldPlayerContextMenu>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
<ContextMenu x:Key="MainPlayerContextMenu">
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<local:MainPlayerContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"></local:MainPlayerContextMenu>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
<ContextMenu x:Key="LivingEntityContextMenu">
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<local:LivingEntityContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
LivingEntityContextMenuClicked="LivingEntityContextMenu_LivingEntityContextMenuClicked"></local:LivingEntityContextMenu>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
<ContextMenu x:Key="PlayerContextMenu">
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<local:PlayerContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
PlayerContextMenuClicked="PlayerContextMenu_PlayerContextMenuClicked"></local:PlayerContextMenu>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
<ContextMenu x:Key="QuestContextMenu">
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<local:QuestContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
QuestContextMenuClicked="QuestContextMenu_QuestContextMenuClicked"></local:QuestContextMenu>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
<ContextMenu x:Key="MapIconContextMenu">
|
||||
<ContextMenu.Template>
|
||||
<ControlTemplate>
|
||||
<local:MapIconContextMenu DataContext="{Binding DataContext, RelativeSource={RelativeSource TemplatedParent}}"
|
||||
MapIconContextMenuClicked="MapIconContextMenu_MapIconContextMenuClicked"></local:MapIconContextMenu>
|
||||
</ControlTemplate>
|
||||
</ContextMenu.Template>
|
||||
</ContextMenu>
|
||||
</UserControl.Resources>
|
||||
<Grid>
|
||||
<Image x:Name="MapDrawingHost" VerticalAlignment="Top" HorizontalAlignment="Left" Stretch="Fill"/>
|
||||
<Image x:Name="EntitiesDrawingHost" VerticalAlignment="Stretch" HorizontalAlignment="Stretch" />
|
||||
<Grid Background="#F0212121"
|
||||
VerticalAlignment="Bottom"
|
||||
HorizontalAlignment="Right"
|
||||
Visibility="{Binding ElementName=_this, Path=ControlsVisible, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}">
|
||||
<local:MaximizeButton Height="30" Width="30" Margin="5"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
Clicked="MaximizeButton_Clicked"></local:MaximizeButton>
|
||||
</Grid>
|
||||
<WrapPanel Background="#F0212121" VerticalAlignment="Top" HorizontalAlignment="Right" >
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=TargetEntityId, Mode=OneWay}" Foreground="White"
|
||||
FontSize="16" Padding="5" ></TextBlock>
|
||||
<TextBlock Text=" - " Foreground="White"
|
||||
FontSize="16" Padding="5" ></TextBlock>
|
||||
<TextBlock Text="{Binding ElementName=_this, Path=TargetEntityModelId, Mode=OneWay}" Foreground="White"
|
||||
FontSize="16" Padding="5" ></TextBlock>
|
||||
</WrapPanel>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,699 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Models;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Media.Imaging;
|
||||
using System.Windows.Media;
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using Daybreak.Services.Scanner;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System.Core.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Daybreak.Services.Pathfinding;
|
||||
using Daybreak.Services.Pathfinding.Models;
|
||||
using System.Windows.Threading;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
using Daybreak.Services.Drawing;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Using source generators to auto-implement dependency properties")]
|
||||
/// <summary>
|
||||
/// Interaction logic for GuildwarsMinimap.xaml
|
||||
/// </summary>
|
||||
public partial class GuildwarsMinimap : UserControl
|
||||
{
|
||||
private const int MapDownscaleFactor = 10;
|
||||
private const int EntitySize = 100;
|
||||
private const float PositionRadius = 150;
|
||||
// Minimum amount of milliseconds to pass between calculating paths to objectives
|
||||
private const int MinPathCalculationFrequency = 500;
|
||||
|
||||
private readonly DispatcherTimer dispatcherTimer = new(DispatcherPriority.ApplicationIdle);
|
||||
private readonly List<Position> mainPlayerPositionHistory = new();
|
||||
private readonly IPathfinder pathfinder;
|
||||
private readonly IDrawingService drawingService;
|
||||
private readonly IGuildwarsEntityDebouncer guildwarsEntityDebouncer;
|
||||
private readonly Color outlineColor = Colors.Chocolate;
|
||||
private readonly TimeSpan offsetRevertDelay = TimeSpan.FromSeconds(3);
|
||||
|
||||
private bool calculatingPathToObjectives = false;
|
||||
private bool resizeEntities;
|
||||
private bool dragging;
|
||||
private double mapVirtualMinWidth;
|
||||
private double mapVirtualMinHeight;
|
||||
private double mapWidth;
|
||||
private double mapHeight;
|
||||
private DateTime offsetRevertTime = DateTime.Now;
|
||||
private double offsetRevert = 0;
|
||||
private Point originPoint = new(0, 0);
|
||||
private Vector originOffset = new(0, 0);
|
||||
private Point initialClickPoint = new(0, 0);
|
||||
private DebounceResponse? cachedDebounceResponse;
|
||||
private PathfindingCache? pathfindingCache;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private PathingData pathingData = new();
|
||||
[GenerateDependencyProperty]
|
||||
private GameData gameData = new();
|
||||
[GenerateDependencyProperty]
|
||||
private double zoom = 0.08;
|
||||
[GenerateDependencyProperty(InitialValue = true)]
|
||||
private bool drawPositionHistory = true;
|
||||
[GenerateDependencyProperty]
|
||||
private bool controlsVisible;
|
||||
[GenerateDependencyProperty]
|
||||
private int targetEntityId;
|
||||
[GenerateDependencyProperty]
|
||||
private int targetEntityModelId;
|
||||
|
||||
public event EventHandler? MaximizeClicked;
|
||||
public event EventHandler<QuestMetadata>? QuestMetadataClicked;
|
||||
public event EventHandler<LivingEntity>? LivingEntityClicked;
|
||||
public event EventHandler<PlayerInformation>? PlayerInformationClicked;
|
||||
public event EventHandler<MapIcon>? MapIconClicked;
|
||||
|
||||
public GuildwarsMinimap()
|
||||
:this(
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IPathfinder>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IDrawingService>(),
|
||||
Launch.Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IGuildwarsEntityDebouncer>())
|
||||
{
|
||||
}
|
||||
|
||||
public GuildwarsMinimap(
|
||||
IPathfinder pathfinder,
|
||||
IDrawingService drawingService,
|
||||
IGuildwarsEntityDebouncer guildwarsEntityDebouncer)
|
||||
{
|
||||
this.pathfinder = pathfinder.ThrowIfNull();
|
||||
this.drawingService = drawingService.ThrowIfNull();
|
||||
this.guildwarsEntityDebouncer = guildwarsEntityDebouncer.ThrowIfNull();
|
||||
|
||||
this.dispatcherTimer.Tick += (_, _) => this.ApplyOffsetRevert();
|
||||
this.dispatcherTimer.Interval = TimeSpan.FromMilliseconds(16);
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == ActualHeightProperty ||
|
||||
e.Property == ActualWidthProperty)
|
||||
{
|
||||
this.resizeEntities = true;
|
||||
}
|
||||
else if (e.Property == PathingDataProperty)
|
||||
{
|
||||
this.guildwarsEntityDebouncer.ClearCaches();
|
||||
this.mainPlayerPositionHistory.Clear();
|
||||
this.UpdateGameData();
|
||||
this.DrawMap();
|
||||
}
|
||||
else if (e.Property == ZoomProperty)
|
||||
{
|
||||
this.UpdateGameData();
|
||||
}
|
||||
else if (e.Property == GameDataProperty &&
|
||||
this.GameData.Valid)
|
||||
{
|
||||
this.UpdateGameData();
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateGameData()
|
||||
{
|
||||
if(this.GameData.Valid is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var debounceResponse = this.guildwarsEntityDebouncer.DebounceEntities(this.GameData);
|
||||
if (!double.IsFinite(this.mapWidth) ||
|
||||
!double.IsFinite(this.mapHeight) ||
|
||||
!double.IsFinite(this.mapVirtualMinWidth) ||
|
||||
!double.IsFinite(this.mapVirtualMinHeight) ||
|
||||
debounceResponse.MainPlayer.Position is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.TargetEntityId = this.GameData.Session?.CurrentTargetId ?? 0;
|
||||
this.TargetEntityModelId = (int?)this.GameData.LivingEntities?.FirstOrDefault(e => e.Id == this.TargetEntityId).ModelType ?? 0;
|
||||
var screenVirtualWidth = this.ActualWidth / this.Zoom;
|
||||
var screenVirtualHeight = this.ActualHeight / this.Zoom;
|
||||
var position = debounceResponse.MainPlayer.Position!.Value;
|
||||
this.originPoint = new Point(
|
||||
position.X - (screenVirtualWidth / 2) - (this.originOffset.X / this.Zoom),
|
||||
position.Y + (screenVirtualHeight / 2) + (this.originOffset.Y / this.Zoom));
|
||||
|
||||
var adjustedPosition = new Point((int)((position.X - this.mapVirtualMinWidth) * this.Zoom), (int)(this.mapHeight - position.Y + this.mapVirtualMinHeight) * this.Zoom);
|
||||
|
||||
this.MapDrawingHost.Margin = new Thickness(
|
||||
-adjustedPosition.X + (this.ActualWidth / 2) + this.originOffset.X,
|
||||
-adjustedPosition.Y + (this.ActualHeight / 2) + this.originOffset.Y,
|
||||
0,
|
||||
0);
|
||||
this.MapDrawingHost.Height = this.mapHeight * this.Zoom;
|
||||
this.MapDrawingHost.Width = this.mapWidth * this.Zoom;
|
||||
this.cachedDebounceResponse = debounceResponse;
|
||||
this.ManageMainPlayerPositionHistory();
|
||||
this.DrawEntities();
|
||||
}
|
||||
|
||||
private void ManageMainPlayerPositionHistory()
|
||||
{
|
||||
if (this.cachedDebounceResponse is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var currentPosition = this.cachedDebounceResponse.MainPlayer.Position ?? throw new InvalidOperationException("Unexpected main player null position");
|
||||
if (this.mainPlayerPositionHistory.Any(oldPosition => PositionsCollide(oldPosition, currentPosition)))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.mainPlayerPositionHistory.Add(currentPosition);
|
||||
}
|
||||
|
||||
private void DrawMap()
|
||||
{
|
||||
if (this.PathingData.Trapezoids is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var maxWidth = double.MinValue;
|
||||
var maxHeight = double.MinValue;
|
||||
var minWidth = double.MaxValue;
|
||||
var minHeight = double.MaxValue;
|
||||
foreach (var trapezoid in this.PathingData.Trapezoids!)
|
||||
{
|
||||
if (trapezoid.YT < minHeight)
|
||||
{
|
||||
minHeight = trapezoid.YT;
|
||||
}
|
||||
|
||||
if (trapezoid.YB > maxHeight)
|
||||
{
|
||||
maxHeight = trapezoid.YB;
|
||||
}
|
||||
|
||||
if (trapezoid.XTL < minWidth)
|
||||
{
|
||||
minWidth = trapezoid.XTL;
|
||||
}
|
||||
|
||||
if (trapezoid.XBL < minWidth)
|
||||
{
|
||||
minWidth = trapezoid.XBL;
|
||||
}
|
||||
|
||||
if (trapezoid.XTR > maxWidth)
|
||||
{
|
||||
maxWidth = trapezoid.XTR;
|
||||
}
|
||||
|
||||
if (trapezoid.XBR > maxWidth)
|
||||
{
|
||||
maxWidth = trapezoid.XBR;
|
||||
}
|
||||
}
|
||||
|
||||
var width = maxWidth - minWidth;
|
||||
var height = maxHeight - minHeight;
|
||||
this.mapVirtualMinHeight = minHeight;
|
||||
this.mapVirtualMinWidth = minWidth;
|
||||
this.mapWidth = width;
|
||||
this.mapHeight = height;
|
||||
|
||||
if (width <= 0 || height <= 0 ||
|
||||
!double.IsFinite(width) ||
|
||||
!double.IsFinite(height))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var bitmap = BitmapFactory.New((int)(width / MapDownscaleFactor), (int)(height / MapDownscaleFactor));
|
||||
this.MapDrawingHost.Source = bitmap;
|
||||
this.MapDrawingHost.Width = width / MapDownscaleFactor;
|
||||
this.MapDrawingHost.Height = height / MapDownscaleFactor;
|
||||
|
||||
using var bitmapContext = bitmap.GetBitmapContext();
|
||||
bitmap.Clear(Colors.Transparent);
|
||||
|
||||
foreach (var trapezoid in this.PathingData.Trapezoids)
|
||||
{
|
||||
var a = new Point((int)((trapezoid.XTL - minWidth) / MapDownscaleFactor), (int)((height - trapezoid.YT + minHeight) / MapDownscaleFactor));
|
||||
var b = new Point((int)((trapezoid.XTR - minWidth) / MapDownscaleFactor), (int)((height - trapezoid.YT + minHeight) / MapDownscaleFactor));
|
||||
var c = new Point((int)((trapezoid.XBR - minWidth) / MapDownscaleFactor), (int)((height - trapezoid.YB + minHeight) / MapDownscaleFactor));
|
||||
var d = new Point((int)((trapezoid.XBL - minWidth) / MapDownscaleFactor), (int)((height - trapezoid.YB + minHeight) / MapDownscaleFactor));
|
||||
|
||||
bitmap.FillPolygon(new int[] { (int)a.X, (int)a.Y, (int)b.X, (int)b.Y, (int)c.X, (int)c.Y, (int)d.X, (int)d.Y, (int)a.X, (int)a.Y }, Colors.White);
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawEntities()
|
||||
{
|
||||
if (this.ActualWidth == 0 || this.ActualHeight == 0)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.EntitiesDrawingHost.Source is not WriteableBitmap bitmap ||
|
||||
this.resizeEntities ||
|
||||
bitmap.PixelHeight != (int)this.ActualHeight ||
|
||||
bitmap.PixelWidth != (int)this.ActualWidth)
|
||||
{
|
||||
bitmap = BitmapFactory.New((int)this.ActualWidth, (int)this.ActualHeight);
|
||||
this.EntitiesDrawingHost.Source = bitmap;
|
||||
this.resizeEntities = false;
|
||||
}
|
||||
|
||||
this.CalculatePathsToObjectives();
|
||||
|
||||
bitmap.Clear(Colors.Transparent);
|
||||
using var context = bitmap.GetBitmapContext();
|
||||
|
||||
this.drawingService.UpdateDrawingParameters(
|
||||
(int)this.ActualWidth,
|
||||
(int)this.ActualHeight,
|
||||
this.originPoint,
|
||||
this.Zoom,
|
||||
PositionRadius,
|
||||
EntitySize);
|
||||
this.drawingService.DrawMainPlayerPositionHistory(bitmap, this.mainPlayerPositionHistory);
|
||||
this.drawingService.DrawPaths(bitmap, this.pathfindingCache);
|
||||
this.drawingService.DrawQuestObjectives(bitmap, this.GameData.MainPlayer?.QuestLog ?? new List<QuestMetadata>());
|
||||
this.drawingService.DrawMapIcons(bitmap, this.GameData.MapIcons ?? new List<MapIcon>());
|
||||
this.drawingService.DrawEntities(bitmap, this.cachedDebounceResponse ?? new DebounceResponse(), this.TargetEntityId);
|
||||
}
|
||||
|
||||
private bool MouseOverEntity(IPositionalEntity entity, Point mousePosition)
|
||||
{
|
||||
var x = (int)((entity.Position!.Value.X - this.originPoint.X) * this.Zoom);
|
||||
var y = 0 - (int)((entity.Position!.Value.Y - this.originPoint.Y) * this.Zoom);
|
||||
|
||||
return Math.Pow(mousePosition.X - x, 2) + Math.Pow(mousePosition.Y - y, 2) < Math.Pow(EntitySize * this.Zoom, 2);
|
||||
}
|
||||
|
||||
private void DragMinimap()
|
||||
{
|
||||
if (this.dragging is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
var mousePosition = Mouse.GetPosition(this);
|
||||
this.offsetRevert = 0;
|
||||
this.originOffset = mousePosition - this.initialClickPoint;
|
||||
this.offsetRevertTime = DateTime.Now + this.offsetRevertDelay;
|
||||
this.UpdateGameData();
|
||||
}
|
||||
|
||||
private void ApplyOffsetRevert()
|
||||
{
|
||||
if (DateTime.Now < this.offsetRevertTime)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.ContextMenu?.IsOpen is true)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.offsetRevert = 0.0001 + (this.offsetRevert * 1.0001);
|
||||
this.offsetRevert = Math.Min(99, this.offsetRevert);
|
||||
this.originOffset /= 1 + this.offsetRevert;
|
||||
this.UpdateGameData();
|
||||
}
|
||||
|
||||
private async void CalculatePathsToObjectives()
|
||||
{
|
||||
if (this.calculatingPathToObjectives)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.calculatingPathToObjectives = true;
|
||||
var currentMapQuests = this.GameData.MainPlayer?.QuestLog?.Where(q => IsValidPositionalEntity(q)).ToList();
|
||||
if (currentMapQuests is null)
|
||||
{
|
||||
this.calculatingPathToObjectives = false;
|
||||
return;
|
||||
}
|
||||
|
||||
var pathfindingTasks = currentMapQuests
|
||||
.Select(questMetaData =>
|
||||
{
|
||||
return this.pathfinder.CalculatePath(
|
||||
this.PathingData,
|
||||
new Point
|
||||
{
|
||||
X = this.cachedDebounceResponse?.MainPlayer.Position?.X ?? 0,
|
||||
Y = this.cachedDebounceResponse?.MainPlayer.Position?.Y ?? 0,
|
||||
},
|
||||
new Point
|
||||
{
|
||||
X = questMetaData.Position!.Value.X,
|
||||
Y = questMetaData.Position!.Value.Y
|
||||
},
|
||||
CancellationToken.None);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
await Task.WhenAll(pathfindingTasks.Append(Task.Delay(MinPathCalculationFrequency)));
|
||||
var paths = new List<PathfindingResponse>();
|
||||
var colors = new List<Color>();
|
||||
for(var i = 0; i < currentMapQuests.Count; i++)
|
||||
{
|
||||
var quest = currentMapQuests[i];
|
||||
var result = await pathfindingTasks[i];
|
||||
if (result.TryExtractSuccess(out var pathfindingResponse))
|
||||
{
|
||||
paths.Add(pathfindingResponse);
|
||||
var questColor = GetQuestColor(quest);
|
||||
var pathColor = Color.FromArgb(100, questColor.R, questColor.G, questColor.B);
|
||||
colors.Add(pathColor);
|
||||
}
|
||||
}
|
||||
|
||||
this.pathfindingCache = new PathfindingCache { PathfindingResponses = paths, Colors = colors };
|
||||
this.calculatingPathToObjectives = false;
|
||||
}
|
||||
|
||||
private IPositionalEntity? CheckMouseOverEntity(IEnumerable<IPositionalEntity>? maybeEntities)
|
||||
{
|
||||
if (maybeEntities is not IEnumerable<IPositionalEntity> entities)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
if (this.GameData.Valid is false)
|
||||
{
|
||||
return default;
|
||||
}
|
||||
|
||||
var mousePoint = Mouse.GetPosition(this);
|
||||
foreach(var entity in entities)
|
||||
{
|
||||
if (this.MouseOverEntity(entity, mousePoint))
|
||||
{
|
||||
this.Cursor = Cursors.Hand;
|
||||
return entity;
|
||||
}
|
||||
}
|
||||
|
||||
this.Cursor = default;
|
||||
return default;
|
||||
}
|
||||
|
||||
private Position ForceOnScreenPosition(Position entityPosition)
|
||||
{
|
||||
var screenVirtualWidth = this.ActualWidth / this.Zoom;
|
||||
var screenVirtualHeight = this.ActualHeight / this.Zoom;
|
||||
var finalEntitySize = EntitySize * this.Zoom;
|
||||
return new Position
|
||||
{
|
||||
X = (float)Math.Clamp(
|
||||
entityPosition.X,
|
||||
Math.Min(this.originPoint.X + finalEntitySize, this.originPoint.X + screenVirtualWidth - finalEntitySize),
|
||||
Math.Max(this.originPoint.X + finalEntitySize, this.originPoint.X + screenVirtualWidth - finalEntitySize)),
|
||||
Y = (float)Math.Clamp(
|
||||
entityPosition.Y,
|
||||
Math.Min(this.originPoint.Y - screenVirtualHeight + finalEntitySize, this.originPoint.Y - finalEntitySize),
|
||||
Math.Max(this.originPoint.Y - screenVirtualHeight + finalEntitySize, this.originPoint.Y - finalEntitySize)),
|
||||
};
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_MouseLeftButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
this.initialClickPoint = Mouse.GetPosition(this) - this.originOffset;
|
||||
this.offsetRevert = 0;
|
||||
this.offsetRevertTime = DateTime.Now + this.offsetRevertDelay;
|
||||
this.dragging = true;
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_MouseLeftButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
this.dragging = false;
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_MouseRightButtonDown(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
var maybeOffScreenQuestMetadata = this.CheckMouseOverEntity(
|
||||
this.GameData.MainPlayer?.QuestLog?
|
||||
.Where(q => IsValidPositionalEntity(q))
|
||||
.Where(entity => !this.drawingService.IsEntityOnScreen(entity.Position, out _, out _))
|
||||
.Select(oldQuestMetadata =>
|
||||
{
|
||||
var onScreenPosition = this.ForceOnScreenPosition(oldQuestMetadata.Position!.Value);
|
||||
return new QuestMetadata
|
||||
{
|
||||
From = oldQuestMetadata.From,
|
||||
To = oldQuestMetadata.To,
|
||||
Quest = oldQuestMetadata.Quest,
|
||||
Position = onScreenPosition
|
||||
};
|
||||
})
|
||||
.OfType<IPositionalEntity>());
|
||||
if (maybeOffScreenQuestMetadata is QuestMetadata offscreenQuestMetadata &&
|
||||
this.TryFindResource("QuestContextMenu") is ContextMenu offscreenQuestContextMenu)
|
||||
{
|
||||
this.ContextMenu = offscreenQuestContextMenu;
|
||||
this.ContextMenu.DataContext = offscreenQuestMetadata;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var maybeQuestMetadata = this.CheckMouseOverEntity(
|
||||
this.GameData.MainPlayer?.QuestLog?
|
||||
.OfType<IPositionalEntity>().Where(IsValidPositionalEntity)
|
||||
.Where(entity => this.drawingService.IsEntityOnScreen(entity.Position, out _, out _)));
|
||||
if (maybeQuestMetadata is QuestMetadata questMetadata &&
|
||||
this.TryFindResource("QuestContextMenu") is ContextMenu questContextMenu)
|
||||
{
|
||||
this.ContextMenu = questContextMenu;
|
||||
this.ContextMenu.DataContext = questMetadata;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(Enumerable.Repeat(this.GameData.MainPlayer.As<IEntity>(), 1)) is MainPlayerInformation &&
|
||||
this.TryFindResource("MainPlayerContextMenu") is ContextMenu mainPlayerContextMenu)
|
||||
{
|
||||
this.ContextMenu = mainPlayerContextMenu;
|
||||
this.ContextMenu.DataContext = this.GameData.MainPlayer;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var maybeWorldPlayer = this.CheckMouseOverEntity(this.GameData.WorldPlayers?.OfType<IEntity>().Where(IsValidPositionalEntity).OrderByDescending(p => p.Id == this.TargetEntityId));
|
||||
if (maybeWorldPlayer is WorldPlayerInformation worldPlayerInformation &&
|
||||
this.TryFindResource("WorldPlayerContextMenu") is ContextMenu worldPlayerContextMenu)
|
||||
{
|
||||
this.ContextMenu = worldPlayerContextMenu;
|
||||
this.ContextMenu.DataContext = worldPlayerInformation;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var maybePartyMember = this.CheckMouseOverEntity(this.GameData.Party?.OfType<IEntity>().Where(IsValidPositionalEntity).OrderByDescending(p => p.Id == this.TargetEntityId));
|
||||
if (maybePartyMember is PlayerInformation partyMember &&
|
||||
this.TryFindResource("PlayerContextMenu") is ContextMenu playerContextMenu)
|
||||
{
|
||||
this.ContextMenu = playerContextMenu;
|
||||
this.ContextMenu.DataContext = partyMember;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var maybeLivingEntity = this.CheckMouseOverEntity(this.GameData.LivingEntities?.OfType<IEntity>().Where(IsValidPositionalEntity).OrderByDescending(p => p.Id == this.TargetEntityId));
|
||||
if (maybeLivingEntity is LivingEntity livingEntity &&
|
||||
this.TryFindResource("LivingEntityContextMenu") is ContextMenu livingEntityContextMenu)
|
||||
{
|
||||
this.ContextMenu = livingEntityContextMenu;
|
||||
this.ContextMenu.DataContext = livingEntity;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
var maybeMapIcon = this.CheckMouseOverEntity(this.GameData.MapIcons?.OfType<IPositionalEntity>().Where(IsValidPositionalEntity));
|
||||
if (maybeMapIcon is MapIcon mapIcon &&
|
||||
this.TryFindResource("MapIconContextMenu") is ContextMenu mapIconContextMenu)
|
||||
{
|
||||
this.ContextMenu = mapIconContextMenu;
|
||||
this.ContextMenu.DataContext = mapIcon;
|
||||
this.ContextMenu.IsOpen = true;
|
||||
return;
|
||||
}
|
||||
|
||||
this.ContextMenu = default;
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_MouseRightButtonUp(object sender, MouseButtonEventArgs e)
|
||||
{
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_MouseMove(object sender, MouseEventArgs e)
|
||||
{
|
||||
if (this.GameData.Valid is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.DragMinimap();
|
||||
if (this.CheckMouseOverEntity(this.GameData.Party!.OfType<IEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.WorldPlayers!.OfType<IEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(Enumerable.Repeat(this.GameData.MainPlayer.As<IEntity>(), 1)) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.LivingEntities!.OfType<IEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.MapIcons!.OfType<IPositionalEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.MainPlayer!.Value.QuestLog!
|
||||
.Where(entity => this.drawingService.IsEntityOnScreen(entity.Position, out _, out _))
|
||||
.OfType<IPositionalEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (this.CheckMouseOverEntity(this.GameData.MainPlayer!.Value.QuestLog!
|
||||
.Where(entity => !this.drawingService.IsEntityOnScreen(entity.Position, out _, out _))
|
||||
.Select(oldQuestMetadata =>
|
||||
{
|
||||
var onScreenPosition = this.ForceOnScreenPosition(oldQuestMetadata.Position!.Value);
|
||||
return new QuestMetadata
|
||||
{
|
||||
From = oldQuestMetadata.From,
|
||||
To = oldQuestMetadata.To,
|
||||
Quest = oldQuestMetadata.Quest,
|
||||
Position = onScreenPosition
|
||||
};
|
||||
})
|
||||
.OfType<IPositionalEntity>()) is not null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_MouseWheel(object sender, MouseWheelEventArgs e)
|
||||
{
|
||||
var delta = e.Delta > 0 ? 0.1 : -0.1;
|
||||
var previousZoom = this.Zoom;
|
||||
var newZoom = this.Zoom + this.Zoom * delta;
|
||||
this.originOffset *= newZoom / previousZoom;
|
||||
this.initialClickPoint = new Point(
|
||||
this.initialClickPoint.X * newZoom / previousZoom,
|
||||
this.initialClickPoint.Y * newZoom / previousZoom);
|
||||
|
||||
this.Zoom = newZoom;
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.dispatcherTimer.Start();
|
||||
}
|
||||
|
||||
private void GuildwarsMinimap_Unloaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
this.dispatcherTimer.Stop();
|
||||
}
|
||||
|
||||
private void QuestContextMenu_QuestContextMenuClicked(object _, QuestMetadata? quest)
|
||||
{
|
||||
if (quest is not QuestMetadata)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.QuestMetadataClicked?.Invoke(this, quest.Value);
|
||||
}
|
||||
|
||||
private void PlayerContextMenu_PlayerContextMenuClicked(object _, PlayerInformation? playerInformation)
|
||||
{
|
||||
if (playerInformation is not PlayerInformation)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.PlayerInformationClicked?.Invoke(this, playerInformation.Value);
|
||||
}
|
||||
|
||||
private void LivingEntityContextMenu_LivingEntityContextMenuClicked(object _, LivingEntity? livingEntity)
|
||||
{
|
||||
if (livingEntity is not LivingEntity)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.LivingEntityClicked?.Invoke(this, livingEntity.Value);
|
||||
}
|
||||
|
||||
private void MapIconContextMenu_MapIconContextMenuClicked(object _, MapIcon? mapIcon)
|
||||
{
|
||||
if (mapIcon is not MapIcon)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.MapIconClicked?.Invoke(this, mapIcon.Value);
|
||||
}
|
||||
|
||||
private void MaximizeButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.MaximizeClicked?.Invoke(this, e);
|
||||
if (e is MouseButtonEventArgs mouseButtonEventArgs)
|
||||
{
|
||||
mouseButtonEventArgs.Handled = true;
|
||||
}
|
||||
}
|
||||
|
||||
private static bool PositionsCollide(Position position1, Position position2)
|
||||
{
|
||||
var a = PositionRadius + PositionRadius;
|
||||
var dx = position1.X - position2.X;
|
||||
var dy = position1.Y - position2.Y;
|
||||
return a * a > ((dx * dx) + (dy * dy));
|
||||
}
|
||||
|
||||
private static bool IsValidPositionalEntity(IPositionalEntity entity)
|
||||
{
|
||||
if (entity.Position?.X == 0 &&
|
||||
entity.Position?.Y == 0)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private static Color GetQuestColor(QuestMetadata questMetadata)
|
||||
{
|
||||
return QuestObjectiveColors.Colors[questMetadata.Quest?.Id % QuestObjectiveColors.Colors.Count ?? 0];
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,37 @@
|
||||
<UserControl x:Class="Daybreak.Controls.HorizontalResourceBar"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Viewbox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="Fill">
|
||||
<Grid Height="1">
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
Width="{Binding ElementName=_this, Path=MaxResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="#F0202020"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
Width="{Binding ElementName=_this, Path=CurrentResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
FontSize="{Binding ElementName=_this, Path=FontSize, Mode=OneWay}"
|
||||
FontFamily="{Binding ElementName=_this, Path=FontFamily, Mode=OneWay}"
|
||||
Text="{Binding ElementName=_this, Path=Text, Mode=OneWay}"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"></TextBlock>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,34 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for ResourceBar.xaml
|
||||
/// </summary>
|
||||
public partial class HorizontalResourceBar : UserControl
|
||||
{
|
||||
[GenerateDependencyProperty]
|
||||
private double currentResourceValue;
|
||||
[GenerateDependencyProperty]
|
||||
private double maxResourceValue;
|
||||
[GenerateDependencyProperty]
|
||||
private Brush barColor;
|
||||
[GenerateDependencyProperty]
|
||||
private string text;
|
||||
[GenerateDependencyProperty(InitialValue = HorizontalAlignment.Left)]
|
||||
private HorizontalAlignment fillAlignment;
|
||||
|
||||
public HorizontalResourceBar()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.MaxResourceValue = 1;
|
||||
this.CurrentResourceValue = 0;
|
||||
this.barColor = Brushes.Transparent;
|
||||
this.text = string.Empty;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="Daybreak.Controls.LivingEntityContextMenu"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:guildwars="clr-namespace:Daybreak.Models.Guildwars"
|
||||
mc:Ignorable="d"
|
||||
Background="#F0212121"
|
||||
d:DataContext="{d:DesignInstance Type=guildwars:LivingEntity, IsDesignTimeCreatable=True}"
|
||||
d:DesignHeight="300" d:DesignWidth="100">
|
||||
<StackPanel Margin="5, 0, 5, 0">
|
||||
<TextBlock
|
||||
Text="{Binding Allegiance, Mode=OneWay}" FontSize="16" Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding NpcDefinition.Name}" Foreground="LightBlue" Cursor="Hand"
|
||||
MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"></TextBlock>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="Id: " Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding ModelType, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="Lvl: " Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding Level, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,23 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
/// <summary>
|
||||
/// Interaction logic for LivingEntityContextMenu.xaml
|
||||
/// </summary>
|
||||
public partial class LivingEntityContextMenu : UserControl
|
||||
{
|
||||
public event EventHandler<LivingEntity?>? LivingEntityContextMenuClicked;
|
||||
|
||||
public LivingEntityContextMenu()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void TextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.LivingEntityContextMenuClicked?.Invoke(this, this.DataContext as LivingEntity? ?? default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
<UserControl x:Class="Daybreak.Controls.MainPlayerContextMenu"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:guildwars="clr-namespace:Daybreak.Models.Guildwars"
|
||||
mc:Ignorable="d"
|
||||
Background="#F0212121"
|
||||
d:DataContext="{d:DesignInstance Type=guildwars:MainPlayerInformation, IsDesignTimeCreatable=True}"
|
||||
d:DesignHeight="300" d:DesignWidth="100">
|
||||
<StackPanel Margin="5, 0, 5, 0">
|
||||
<TextBlock
|
||||
Text="{Binding Name, Mode=OneWay}" FontSize="16" Foreground="White"></TextBlock>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="Lvl: " Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding Level, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="{Binding PrimaryProfession.Alias, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
<TextBlock Text="/" Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding SecondaryProfession.Alias, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MainPlayerContextMenu.xaml
|
||||
/// </summary>
|
||||
public partial class MainPlayerContextMenu : UserControl
|
||||
{
|
||||
public MainPlayerContextMenu()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<UserControl x:Class="Daybreak.Controls.MapIconContextMenu"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:guildwars="clr-namespace:Daybreak.Models.Guildwars"
|
||||
mc:Ignorable="d"
|
||||
Background="#F0212121"
|
||||
d:DataContext="{d:DesignInstance Type=guildwars:MapIcon, IsDesignTimeCreatable=True}"
|
||||
d:DesignHeight="300" d:DesignWidth="100">
|
||||
<StackPanel Margin="5, 0, 5, 0">
|
||||
<TextBlock Text="Map Icon" Foreground="White" FontSize="16"></TextBlock>
|
||||
<TextBlock Text="{Binding Icon.Name}" Foreground="LightBlue" Cursor="Hand"
|
||||
MouseLeftButtonDown="TextBlock_MouseLeftButtonDown" Margin="0, 0, 0, 10"></TextBlock>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,24 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for MapIconContextMenu.xaml
|
||||
/// </summary>
|
||||
public partial class MapIconContextMenu : UserControl
|
||||
{
|
||||
public event EventHandler<MapIcon?>? MapIconContextMenuClicked;
|
||||
|
||||
public MapIconContextMenu()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void TextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.MapIconContextMenuClicked?.Invoke(this, this.DataContext as MapIcon? ?? default);
|
||||
}
|
||||
}
|
||||
+128
-48
@@ -5,89 +5,169 @@
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:buttons="clr-namespace:Daybreak.Controls.Buttons"
|
||||
xmlns:glyphs="clr-namespace:Daybreak.Controls.Glyphs"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel>
|
||||
<buttons:MenuButton Title="Game companion"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Clicked="GameCompanionButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:GoldenArrowGlyph Foreground="White"
|
||||
<local:ExpandableMenuSection
|
||||
SectionTitle="Guild Wars" Foreground="White"
|
||||
FontSize="16">
|
||||
<local:ExpandableMenuSection.Children>
|
||||
<buttons:MenuButton Title="Game companion"
|
||||
FontSize="12"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="GameCompanionButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:GoldenArrowGlyph Foreground="White"
|
||||
Width="40"></local:GoldenArrowGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Manage builds"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Clicked="ManageBuildsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FireballGlyph Foreground="White"
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Manage builds"
|
||||
FontSize="12"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="ManageBuildsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FireballGlyph Foreground="White"
|
||||
Width="40"></local:FireballGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Account settings"
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Download Guildwars"
|
||||
FontSize="12"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="DownloadGuildwarsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<glyphs:DownloadGlyph Foreground="White"
|
||||
Width="40"></glyphs:DownloadGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
</local:ExpandableMenuSection.Children>
|
||||
</local:ExpandableMenuSection>
|
||||
<local:ExpandableMenuSection
|
||||
SectionTitle="Mods" Foreground="White"
|
||||
FontSize="16">
|
||||
<local:ExpandableMenuSection.Children>
|
||||
<buttons:MenuButton Title="uMod"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="UModButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<glyphs:UModGlyph Foreground="White"
|
||||
Width="40"></glyphs:UModGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="GWToolboxpp"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="ToolboxButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<glyphs:GWToolboxGlyph Foreground="White"
|
||||
Width="40"></glyphs:GWToolboxGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
</local:ExpandableMenuSection.Children>
|
||||
</local:ExpandableMenuSection>
|
||||
<local:ExpandableMenuSection
|
||||
SectionTitle="Settings" Foreground="White"
|
||||
FontSize="16">
|
||||
<local:ExpandableMenuSection.Children>
|
||||
<buttons:MenuButton Title="Accounts"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="AccountSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:AvatarGlyph Foreground="White"
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:AvatarGlyph Foreground="White"
|
||||
Width="40"></local:AvatarGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Guildwars settings"
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Executables"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="GuildwarsSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FileGlyph Foreground="White"
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:FileGlyph Foreground="White"
|
||||
Width="40"></local:FileGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Launcher settings"
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Launcher"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="LauncherSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:CogGlyph Foreground="White"
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:CogGlyph Foreground="White"
|
||||
Width="40"
|
||||
Height="20"></local:CogGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Experimental settings"
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Experimental"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="ExperimentalSettingsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:ExperimentGlyph Foreground="White"
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:ExperimentGlyph Foreground="White"
|
||||
Width="40"></local:ExperimentGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Manage client version"
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
</local:ExpandableMenuSection.Children>
|
||||
</local:ExpandableMenuSection>
|
||||
<local:ExpandableMenuSection
|
||||
SectionTitle="Diagnostics" Foreground="White"
|
||||
FontSize="16">
|
||||
<local:ExpandableMenuSection.Children>
|
||||
<buttons:MenuButton Title="Manage client version"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="VersionManagementButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:StaticGlyph Foreground="White"
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:StaticGlyph Foreground="White"
|
||||
Width="40"></local:StaticGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Logs"
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Logs"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="LogsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:LogsGlyph Foreground="White"
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<local:LogsGlyph Foreground="White"
|
||||
Width="40"></local:LogsGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
<buttons:MenuButton Title="Metrics"
|
||||
Foreground="White"
|
||||
HighlightColor="White"
|
||||
Height="30"
|
||||
Cursor="Hand"
|
||||
Clicked="MetricsButton_Clicked">
|
||||
<buttons:MenuButton.InnerContent>
|
||||
<glyphs:GaugeGlyph Foreground="White"
|
||||
Width="40"></glyphs:GaugeGlyph>
|
||||
</buttons:MenuButton.InnerContent>
|
||||
</buttons:MenuButton>
|
||||
</local:ExpandableMenuSection.Children>
|
||||
</local:ExpandableMenuSection>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,10 +1,13 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Views;
|
||||
using Daybreak.Views.Onboarding.Toolbox;
|
||||
using Daybreak.Views.Onboarding.UMod;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Configuration;
|
||||
using System.Core.Extensions;
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
@@ -14,64 +17,89 @@ namespace Daybreak.Controls;
|
||||
/// </summary>
|
||||
public partial class MenuList : UserControl
|
||||
{
|
||||
private readonly IViewManager viewManager;
|
||||
private readonly ILiveOptions<LauncherOptions> liveOptions;
|
||||
|
||||
public MenuList()
|
||||
: this(
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>(),
|
||||
Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<LauncherOptions>>())
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private MenuList(
|
||||
IViewManager viewManager,
|
||||
ILiveOptions<LauncherOptions> liveOptions)
|
||||
{
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
this.liveOptions = liveOptions.ThrowIfNull();
|
||||
}
|
||||
|
||||
private void GameCompanionButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
viewManager.ShowView<LauncherView>();
|
||||
this.viewManager.ShowView<LauncherView>();
|
||||
}
|
||||
|
||||
private void AccountSettingsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
viewManager.ShowView<AccountsView>();
|
||||
this.viewManager.ShowView<AccountsView>();
|
||||
}
|
||||
|
||||
private void GuildwarsSettingsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
viewManager.ShowView<ExecutablesView>();
|
||||
this.viewManager.ShowView<ExecutablesView>();
|
||||
}
|
||||
|
||||
private void LauncherSettingsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
viewManager.ShowView<SettingsView>();
|
||||
this.viewManager.ShowView<SettingsView>();
|
||||
}
|
||||
|
||||
private void ExperimentalSettingsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
viewManager.ShowView<ExperimentalSettingsView>();
|
||||
this.viewManager.ShowView<ExperimentalSettingsView>();
|
||||
}
|
||||
|
||||
private void ManageBuildsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
var options = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<ILiveOptions<ApplicationConfiguration>>();
|
||||
if (options.Value.ExperimentalFeatures.DownloadIcons)
|
||||
if (this.liveOptions.Value.DownloadIcons)
|
||||
{
|
||||
viewManager.ShowView<IconDownloadView>();
|
||||
this.viewManager.ShowView<IconDownloadView>();
|
||||
}
|
||||
else
|
||||
{
|
||||
viewManager.ShowView<BuildsListView>();
|
||||
this.viewManager.ShowView<BuildsListView>();
|
||||
}
|
||||
}
|
||||
|
||||
private void VersionManagementButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
viewManager.ShowView<VersionManagementView>();
|
||||
this.viewManager.ShowView<VersionManagementView>();
|
||||
}
|
||||
|
||||
|
||||
private void LogsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
var viewManager = Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IViewManager>();
|
||||
viewManager.ShowView<LogsView>();
|
||||
this.viewManager.ShowView<LogsView>();
|
||||
}
|
||||
|
||||
private void MetricsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<MetricsView>();
|
||||
}
|
||||
|
||||
private void DownloadGuildwarsButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<GuildwarsDownloadView>();
|
||||
}
|
||||
|
||||
private void UModButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<UModOnboardingEntryView>();
|
||||
}
|
||||
|
||||
private void ToolboxButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
this.viewManager.ShowView<ToolboxOnboardingEntryView>();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,29 @@
|
||||
<UserControl x:Class="Daybreak.Controls.PlayerContextMenu"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:guildwars="clr-namespace:Daybreak.Models.Guildwars"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=guildwars:PlayerInformation, IsDesignTimeCreatable=True}"
|
||||
d:DesignHeight="300" d:DesignWidth="100"
|
||||
Margin="5, 0, 5, 0">
|
||||
<StackPanel Background="#F0212121">
|
||||
<TextBlock Text="Party Member" FontSize="16" Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding NpcDefinition.Name}" Foreground="LightBlue" Cursor="Hand"
|
||||
MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"></TextBlock>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="Id: " Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding ModelType, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="Lvl: " Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding Level, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
<WrapPanel>
|
||||
<TextBlock Text="{Binding PrimaryProfession.Alias, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
<TextBlock Text="/" Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding SecondaryProfession.Alias, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,23 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
/// <summary>
|
||||
/// Interaction logic for PlayerContextMenu.xaml
|
||||
/// </summary>
|
||||
public partial class PlayerContextMenu : UserControl
|
||||
{
|
||||
public event EventHandler<PlayerInformation?>? PlayerContextMenuClicked;
|
||||
|
||||
public PlayerContextMenu()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void TextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.PlayerContextMenuClicked?.Invoke(this, this.DataContext as PlayerInformation? ?? default);
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,17 @@
|
||||
<UserControl x:Class="Daybreak.Controls.QuestContextMenu"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:guildwars="clr-namespace:Daybreak.Models.Guildwars"
|
||||
mc:Ignorable="d"
|
||||
Background="#F0212121"
|
||||
d:DataContext="{d:DesignInstance Type=guildwars:QuestMetadata, IsDesignTimeCreatable=True}"
|
||||
d:DesignHeight="300" d:DesignWidth="100">
|
||||
<StackPanel Margin="5, 0, 5, 0">
|
||||
<TextBlock Text="{Binding Quest.Name}" FontSize="16" Foreground="White" TextWrapping="Wrap"></TextBlock>
|
||||
<TextBlock Text="{Binding Quest.WikiUrl}" TextWrapping="Wrap" Foreground="LightBlue" Cursor="Hand"
|
||||
MouseLeftButtonDown="TextBlock_MouseLeftButtonDown"></TextBlock>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,24 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Input;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for QuestContextMenu.xaml
|
||||
/// </summary>
|
||||
public partial class QuestContextMenu : UserControl
|
||||
{
|
||||
public event EventHandler<QuestMetadata?>? QuestContextMenuClicked;
|
||||
|
||||
public QuestContextMenu()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
private void TextBlock_MouseLeftButtonDown(object _, MouseButtonEventArgs e)
|
||||
{
|
||||
this.QuestContextMenuClicked?.Invoke(this, this.DataContext as QuestMetadata? ?? default);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,5 @@
|
||||
using System;
|
||||
using System.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
@@ -16,11 +18,15 @@ public partial class AttributeTemplate : UserControl
|
||||
{
|
||||
public event EventHandler<AttributeEntry>? HelpClicked;
|
||||
public event EventHandler<AttributeEntry>? AttributeChanged;
|
||||
|
||||
|
||||
private IAttributePointCalculator? attributePointCalculator;
|
||||
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool canAdd;
|
||||
[GenerateDependencyProperty(InitialValue = false)]
|
||||
private bool canSubtract;
|
||||
[GenerateDependencyProperty]
|
||||
private int attributePoints;
|
||||
|
||||
public AttributeTemplate()
|
||||
{
|
||||
@@ -28,6 +34,31 @@ public partial class AttributeTemplate : UserControl
|
||||
this.DataContextChanged += this.AttributeTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (e.Property == AttributePointsProperty &&
|
||||
this.DataContext is AttributeEntry attributeEntry)
|
||||
{
|
||||
var remainingPoints = this.AttributePoints;
|
||||
var requiredPointsForNextLevel = this.attributePointCalculator?.GetPointsRequiredToIncreaseRank(attributeEntry.Points) ?? 0;
|
||||
if (remainingPoints < requiredPointsForNextLevel)
|
||||
{
|
||||
this.CanAdd = false;
|
||||
}
|
||||
else if (this.DataContext.As<AttributeEntry>().Points < 12)
|
||||
{
|
||||
this.CanAdd = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
public void InitializeAttributeTemplate(
|
||||
IAttributePointCalculator attributePointCalculator)
|
||||
{
|
||||
this.attributePointCalculator = attributePointCalculator.ThrowIfNull();
|
||||
}
|
||||
|
||||
private void AttributeTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if (e.NewValue is AttributeEntry attributeEntry)
|
||||
|
||||
@@ -11,6 +11,9 @@
|
||||
x:Name="_this"
|
||||
Unloaded="BuildTemplate_Unloaded"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<UserControl.Resources>
|
||||
<BooleanToVisibilityConverter x:Key="BooleanToVisibilityConverter"></BooleanToVisibilityConverter>
|
||||
</UserControl.Resources>
|
||||
<Grid Background="Transparent" MouseLeftButtonDown="Grid_MouseLeftButtonDown">
|
||||
<Grid.RowDefinitions>
|
||||
<RowDefinition Height="auto"></RowDefinition>
|
||||
@@ -30,20 +33,15 @@
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Primary Profession: " FontSize="16" Foreground="White" Grid.Column="1"></TextBlock>
|
||||
<ListView FontSize="16" Foreground="White" Grid.Column="2" BorderThickness="0"
|
||||
Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
SelectedItem="{Binding ElementName=_this, Path=PrimaryProfession, Mode=TwoWay}" Height="30"
|
||||
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
PreviewMouseWheel="ListView_NavigateWithMouseWheel">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name, Mode=OneWay}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<behaviors:ScrollIntoView></behaviors:ScrollIntoView>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
<local:OpaqueButton Grid.Column="2"
|
||||
Text="{Binding ElementName=_this, Path=BuildEntry.Primary.Name, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Highlight="White"
|
||||
HighlightOpacity="0.4"
|
||||
FontSize="16"
|
||||
TextHorizontalAlignment="Left"
|
||||
Margin="0, 0, 10, 0"
|
||||
Clicked="PrimaryProfessionButton_Clicked"></local:OpaqueButton>
|
||||
<local:HelpButton Grid.Column="0" Foreground="White" Width="20" Height="20" Margin="3"
|
||||
Clicked="HelpButtonPrimary_Clicked" Cursor="Hand"></local:HelpButton>
|
||||
</Grid>
|
||||
@@ -54,29 +52,27 @@
|
||||
<ColumnDefinition Width="*"></ColumnDefinition>
|
||||
</Grid.ColumnDefinitions>
|
||||
<TextBlock Text="Secondary Profession: " FontSize="16" Foreground="White" Grid.Column="1"></TextBlock>
|
||||
<ListView FontSize="16" Foreground="White" Grid.Column="2" BorderThickness="0"
|
||||
Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
SelectedItem="{Binding ElementName=_this, Path=SecondaryProfession, Mode=TwoWay}" Height="30"
|
||||
SelectionMode="Single" ScrollViewer.VerticalScrollBarVisibility="Disabled"
|
||||
PreviewMouseWheel="ListView_NavigateWithMouseWheel">
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock Text="{Binding Name, Mode=OneWay}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
<interactivity:Interaction.Behaviors>
|
||||
<behaviors:ScrollIntoView></behaviors:ScrollIntoView>
|
||||
</interactivity:Interaction.Behaviors>
|
||||
</ListView>
|
||||
<local:OpaqueButton Grid.Column="2"
|
||||
Text="{Binding ElementName=_this, Path=BuildEntry.Secondary.Name, Mode=OneWay}"
|
||||
Foreground="White"
|
||||
Highlight="White"
|
||||
HighlightOpacity="0.4"
|
||||
FontSize="16"
|
||||
TextHorizontalAlignment="Left"
|
||||
Margin="0, 0, 10, 0"
|
||||
Clicked="SecondaryProfessionButton_Clicked"></local:OpaqueButton>
|
||||
<local:HelpButton Grid.Column="0" Foreground="White" Width="20" Height="20" Margin="3"
|
||||
Clicked="HelpButtonSecondary_Clicked" Cursor="Hand"></local:HelpButton>
|
||||
</Grid>
|
||||
<Grid Grid.Row="3">
|
||||
<ListBox Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=Attributes, Mode=OneWay}"
|
||||
<ListBox Background="Transparent" ItemsSource="{Binding ElementName=_this, Path=BuildEntry.Attributes, Mode=OneWay}"
|
||||
HorizontalContentAlignment="Stretch" BorderThickness="0">
|
||||
<ListBox.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<local:AttributeTemplate HelpClicked="AttributeTemplate_HelpClicked" AttributeChanged="AttributeTemplate_AttributeChanged"></local:AttributeTemplate>
|
||||
<local:AttributeTemplate HelpClicked="AttributeTemplate_HelpClicked"
|
||||
AttributeChanged="AttributeTemplate_AttributeChanged"
|
||||
Loaded="AttributeTemplate_Loaded"
|
||||
AttributePoints="{Binding Path=AttributePoints, Mode=OneWay, RelativeSource={RelativeSource AncestorType={x:Type UserControl}}}"></local:AttributeTemplate>
|
||||
</DataTemplate>
|
||||
</ListBox.ItemTemplate>
|
||||
</ListBox>
|
||||
@@ -98,60 +94,60 @@
|
||||
</Grid.RowDefinitions>
|
||||
<local:SkillTemplate Grid.Column="0" x:Name="SkillTemplate0"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill0, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.FirstSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="1" x:Name="SkillTemplate1"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill1, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.SecondSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="2" x:Name="SkillTemplate2"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill2, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.ThirdSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="3" x:Name="SkillTemplate3"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill3, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.FourthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="4" x:Name="SkillTemplate4"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill4, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.FifthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="5" x:Name="SkillTemplate5"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill5, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.SixthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="6" x:Name="SkillTemplate6"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill6, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.SeventhSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<local:SkillTemplate Grid.Column="7" x:Name="SkillTemplate7"
|
||||
Foreground="White" Cursor="Hand"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=Skill7, Mode=TwoWay}"
|
||||
FontSize="22" DataContext="{Binding ElementName=_this, Path=BuildEntry.EigthSkill, Mode=TwoWay}"
|
||||
VerticalAlignment="Stretch" Clicked="SkillTemplate_Clicked"
|
||||
RemoveClicked="SkillTemplate_RemoveClicked"></local:SkillTemplate>
|
||||
<TextBlock Grid.Column="0" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill0.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.FirstSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="1" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill1.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.SecondSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="2" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill2.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.ThirdSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="3" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill3.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.FourthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="4" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill4.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.FifthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="5" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill5.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.SixthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="6" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill6.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.SeventhSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
<TextBlock Grid.Column="7" Grid.Row="1" TextWrapping="Wrap" FontSize="16"
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=Skill7.Name, Mode=OneWay}"></TextBlock>
|
||||
Foreground="White" Text="{Binding ElementName=_this, Path=BuildEntry.EigthSkill.Name, Mode=OneWay}"></TextBlock>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<local:ChromiumBrowserWrapper x:Name="SkillBrowser" ControlsEnabled="False" Width="0" AddressBarReadonly="True" CanNavigate="True"></local:ChromiumBrowserWrapper>
|
||||
@@ -170,10 +166,11 @@
|
||||
<ListView x:Name="SkillsListView"
|
||||
Grid.Row="1"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Hidden"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Background="Transparent"
|
||||
ScrollViewer.CanContentScroll="False"
|
||||
ItemsSource="{Binding ElementName=_this, Path=AvailableSkills, Mode=OneWay}"
|
||||
MouseDoubleClick="ListView_MouseDoubleClick">
|
||||
MouseDoubleClick="SkillListView_MouseDoubleClick">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel>
|
||||
@@ -188,5 +185,28 @@
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
<Grid Grid.Column="1" Grid.RowSpan="6">
|
||||
<ListView x:Name="ProfessionListView"
|
||||
Width="0"
|
||||
HorizontalAlignment="Right"
|
||||
ScrollViewer.HorizontalScrollBarVisibility="Disabled"
|
||||
ScrollViewer.VerticalScrollBarVisibility="Auto"
|
||||
Background="Transparent"
|
||||
ScrollViewer.CanContentScroll="False"
|
||||
ItemsSource="{Binding ElementName=_this, Path=Professions, Mode=OneWay}"
|
||||
MouseDoubleClick="ProfessionListView_MouseDoubleClick">
|
||||
<ListView.ItemsPanel>
|
||||
<ItemsPanelTemplate>
|
||||
<VirtualizingStackPanel>
|
||||
</VirtualizingStackPanel>
|
||||
</ItemsPanelTemplate>
|
||||
</ListView.ItemsPanel>
|
||||
<ListView.ItemTemplate>
|
||||
<DataTemplate>
|
||||
<TextBlock FontSize="16" Foreground="White" TextWrapping="Wrap" Text="{Binding Name}"></TextBlock>
|
||||
</DataTemplate>
|
||||
</ListView.ItemTemplate>
|
||||
</ListView>
|
||||
</Grid>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
|
||||
@@ -1,14 +1,12 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Builds;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.BuildTemplates;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Utils;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Collections.ObjectModel;
|
||||
using System.Configuration;
|
||||
using System.ComponentModel;
|
||||
using System.Core.Extensions;
|
||||
using System.Extensions;
|
||||
using System.Linq;
|
||||
@@ -30,11 +28,12 @@ public partial class BuildTemplate : UserControl
|
||||
private const string InfoNamePlaceholder = "[NAME]";
|
||||
private const string BaseAddress = $"https://wiki.guildwars.com/wiki/{InfoNamePlaceholder}";
|
||||
|
||||
private bool suppressBuildChanged = false;
|
||||
private bool loadedProperties = false;
|
||||
private IIconBrowser? iconBrowser;
|
||||
private BuildEntry? loadedBuild;
|
||||
private bool showingSkillList = false;
|
||||
private bool replacingSecondaryProfession;
|
||||
private bool replacingPrimaryProfession;
|
||||
private IAttributePointCalculator? attributePointCalculator;
|
||||
private SkillTemplate? selectingSkillTemplate;
|
||||
private List<Skill>? skillListCache;
|
||||
private CancellationTokenSource? cancellationTokenSource = new();
|
||||
|
||||
public event EventHandler? BuildChanged;
|
||||
@@ -42,107 +41,31 @@ public partial class BuildTemplate : UserControl
|
||||
[GenerateDependencyProperty]
|
||||
private string skillSearchText = string.Empty;
|
||||
[GenerateDependencyProperty]
|
||||
private Profession primaryProfession = default!;
|
||||
private BuildEntry buildEntry;
|
||||
[GenerateDependencyProperty]
|
||||
private Profession secondaryProfession = default!;
|
||||
private int attributePoints;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill0 = default!;
|
||||
private List<Skill> availableSkills = new();
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill1 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill2 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill3 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill4 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill5 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill6 = default!;
|
||||
[GenerateDependencyProperty]
|
||||
private Skill skill7 = default!;
|
||||
public ObservableCollection<Skill> AvailableSkills { get; } = new ObservableCollection<Skill>();
|
||||
public ObservableCollection<AttributeEntry> Attributes { get; } = new ObservableCollection<AttributeEntry>();
|
||||
public ObservableCollection<Profession> Professions { get; } = new ObservableCollection<Profession>(Profession.Professions);
|
||||
private List<Profession> professions = new();
|
||||
|
||||
public BuildTemplate()
|
||||
: this(Launcher.Instance.ApplicationServiceProvider.GetService<IAttributePointCalculator>()!)
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.InitializeProperties();
|
||||
this.DataContextChanged += this.BuildTemplate_DataContextChanged;
|
||||
|
||||
}
|
||||
|
||||
public async void InitializeTemplate(
|
||||
IIconCache iconRetriever,
|
||||
IIconBrowser iconBrowser,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions,
|
||||
IBuildTemplateManager buildTemplateManager,
|
||||
ILogger<ChromiumBrowserWrapper> logger)
|
||||
|
||||
public BuildTemplate(
|
||||
IAttributePointCalculator attributePointCalculator)
|
||||
{
|
||||
this.iconBrowser = iconBrowser.ThrowIfNull();
|
||||
await this.SkillBrowser.InitializeDefaultBrowser(liveOptions, buildTemplateManager, logger);
|
||||
this.SkillTemplate0.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate1.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate2.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate3.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate4.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate5.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate6.InitializeSkillTemplate(iconRetriever);
|
||||
this.SkillTemplate7.InitializeSkillTemplate(iconRetriever);
|
||||
this.attributePointCalculator = attributePointCalculator.ThrowIfNull();
|
||||
|
||||
this.InitializeComponent();
|
||||
this.HideSkillListView();
|
||||
this.HideInfoBrowser();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (this.loadedProperties is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Property == PrimaryProfessionProperty || e.Property == SecondaryProfessionProperty)
|
||||
{
|
||||
if (e.Property == PrimaryProfessionProperty)
|
||||
{
|
||||
this.loadedBuild!.Build!.Primary = this.PrimaryProfession;
|
||||
}
|
||||
else
|
||||
{
|
||||
this.loadedBuild!.Build!.Secondary = this.SecondaryProfession;
|
||||
}
|
||||
|
||||
this.LoadSkills();
|
||||
this.LoadAttributes();
|
||||
if (this.suppressBuildChanged is false)
|
||||
{
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
|
||||
if (e.Property == Skill0Property ||
|
||||
e.Property == Skill1Property ||
|
||||
e.Property == Skill2Property ||
|
||||
e.Property == Skill3Property ||
|
||||
e.Property == Skill4Property ||
|
||||
e.Property == Skill5Property ||
|
||||
e.Property == Skill6Property ||
|
||||
e.Property == Skill7Property)
|
||||
{
|
||||
if (this.suppressBuildChanged is false)
|
||||
{
|
||||
this.loadedBuild!.Build!.Skills[0] = this.Skill0;
|
||||
this.loadedBuild!.Build!.Skills[1] = this.Skill1;
|
||||
this.loadedBuild!.Build!.Skills[2] = this.Skill2;
|
||||
this.loadedBuild!.Build!.Skills[3] = this.Skill3;
|
||||
this.loadedBuild!.Build!.Skills[4] = this.Skill4;
|
||||
this.loadedBuild!.Build!.Skills[5] = this.Skill5;
|
||||
this.loadedBuild!.Build!.Skills[6] = this.Skill6;
|
||||
this.loadedBuild!.Build!.Skills[7] = this.Skill7;
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
}
|
||||
}
|
||||
this.buildEntry = new BuildEntry();
|
||||
this.DataContextChanged += this.BuildTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
private void BuildTemplate_Unloaded(object sender, RoutedEventArgs e)
|
||||
@@ -150,144 +73,31 @@ public partial class BuildTemplate : UserControl
|
||||
this.cancellationTokenSource?.Cancel();
|
||||
}
|
||||
|
||||
private void InitializeProperties()
|
||||
{
|
||||
this.PrimaryProfession = Profession.None;
|
||||
this.SecondaryProfession = Profession.None;
|
||||
this.Skill0 = Skill.NoSkill;
|
||||
this.Skill1 = Skill.NoSkill;
|
||||
this.Skill2 = Skill.NoSkill;
|
||||
this.Skill3 = Skill.NoSkill;
|
||||
this.Skill4 = Skill.NoSkill;
|
||||
this.Skill5 = Skill.NoSkill;
|
||||
this.Skill6 = Skill.NoSkill;
|
||||
this.Skill7 = Skill.NoSkill;
|
||||
this.loadedProperties = true;
|
||||
}
|
||||
|
||||
private void BuildTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
if(e.NewValue is BuildEntry)
|
||||
if(e.NewValue is BuildEntry buildEntry)
|
||||
{
|
||||
this.LoadBuild();
|
||||
this.LoadSkills();
|
||||
this.LoadAttributes();
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.HideInfoBrowser();
|
||||
}
|
||||
|
||||
private void LoadAttributes()
|
||||
{
|
||||
var possibleAttributes = new List<AttributeEntry>();
|
||||
if (this.PrimaryProfession != Profession.None)
|
||||
{
|
||||
possibleAttributes.Add(new AttributeEntry { Attribute = this.PrimaryProfession.PrimaryAttribute });
|
||||
possibleAttributes.AddRange(this.PrimaryProfession.Attributes!.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
if (this.SecondaryProfession != Profession.None && this.SecondaryProfession != this.PrimaryProfession)
|
||||
{
|
||||
possibleAttributes.AddRange(this.SecondaryProfession.Attributes!.Select(a => new AttributeEntry { Attribute = a }));
|
||||
}
|
||||
|
||||
this.Attributes.ClearAnd().AddRange(possibleAttributes.Select(entry =>
|
||||
{
|
||||
var maybePresentAttribute = this.loadedBuild!.Build!.Attributes.Where(buildEntry => entry.Attribute == buildEntry.Attribute).FirstOrDefault();
|
||||
if (maybePresentAttribute is null)
|
||||
if (this.BuildEntry is not null)
|
||||
{
|
||||
return entry;
|
||||
this.BuildEntry.PropertyChanged -= this.BuildEntry_Changed;
|
||||
}
|
||||
|
||||
this.BuildEntry = buildEntry;
|
||||
this.BuildEntry.PropertyChanged += this.BuildEntry_Changed;
|
||||
this.AttributePoints = this.attributePointCalculator!.GetRemainingFreePoints(this.BuildEntry.Build!);
|
||||
this.LoadSkills();
|
||||
}
|
||||
}
|
||||
|
||||
entry.Points = maybePresentAttribute.Points;
|
||||
return entry;
|
||||
}));
|
||||
|
||||
this.loadedBuild!.Build!.Attributes = this.Attributes.ToList();
|
||||
private void BuildEntry_Changed(object? sender, PropertyChangedEventArgs propertyChangedEventArgs)
|
||||
{
|
||||
this.LoadSkills();
|
||||
}
|
||||
|
||||
private async void LoadSkills()
|
||||
{
|
||||
if (this.Skill0.Profession != this.PrimaryProfession &&
|
||||
this.Skill0.Profession != this.SecondaryProfession &&
|
||||
this.Skill0.Profession != Profession.None)
|
||||
{
|
||||
this.Skill0 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill1.Profession != this.PrimaryProfession &&
|
||||
this.Skill1.Profession != this.SecondaryProfession &&
|
||||
this.Skill1.Profession != Profession.None)
|
||||
{
|
||||
this.Skill1 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill2.Profession != this.PrimaryProfession &&
|
||||
this.Skill2.Profession != this.SecondaryProfession &&
|
||||
this.Skill2.Profession != Profession.None)
|
||||
{
|
||||
this.Skill2 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill3.Profession != this.PrimaryProfession &&
|
||||
this.Skill3.Profession != this.SecondaryProfession &&
|
||||
this.Skill3.Profession != Profession.None)
|
||||
{
|
||||
this.Skill3 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill4.Profession != this.PrimaryProfession &&
|
||||
this.Skill4.Profession != this.SecondaryProfession &&
|
||||
this.Skill4.Profession != Profession.None)
|
||||
{
|
||||
this.Skill4 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill5.Profession != this.PrimaryProfession &&
|
||||
this.Skill5.Profession != this.SecondaryProfession &&
|
||||
this.Skill5.Profession != Profession.None)
|
||||
{
|
||||
this.Skill5 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill6.Profession != this.PrimaryProfession &&
|
||||
this.Skill6.Profession != this.SecondaryProfession &&
|
||||
this.Skill6.Profession != Profession.None)
|
||||
{
|
||||
this.Skill6 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.Skill7.Profession != this.PrimaryProfession &&
|
||||
this.Skill7.Profession != this.SecondaryProfession &&
|
||||
this.Skill7.Profession != Profession.None)
|
||||
{
|
||||
this.Skill7 = Skill.NoSkill;
|
||||
}
|
||||
|
||||
var filteredSkills = await this.FilterSkills(this.SkillSearchText).ToListAsync().ConfigureAwait(true);
|
||||
this.AvailableSkills.ClearAnd().AddRange(filteredSkills);
|
||||
}
|
||||
|
||||
private void LoadBuild()
|
||||
{
|
||||
this.suppressBuildChanged = true;
|
||||
var build = this.DataContext.As<BuildEntry>();
|
||||
this.loadedBuild = build;
|
||||
this.PrimaryProfession = build.Build!.Primary;
|
||||
this.SecondaryProfession = build.Build.Secondary;
|
||||
this.Skill0 = build.Build.Skills[0];
|
||||
this.Skill1 = build.Build.Skills[1];
|
||||
this.Skill2 = build.Build.Skills[2];
|
||||
this.Skill3 = build.Build.Skills[3];
|
||||
this.Skill4 = build.Build.Skills[4];
|
||||
this.Skill5 = build.Build.Skills[5];
|
||||
this.Skill6 = build.Build.Skills[6];
|
||||
this.Skill7 = build.Build.Skills[7];
|
||||
this.suppressBuildChanged = false;
|
||||
this.PrepareSkillListCache(filteredSkills);
|
||||
}
|
||||
|
||||
private void BrowseToInfo(string infoName)
|
||||
@@ -301,8 +111,9 @@ public partial class BuildTemplate : UserControl
|
||||
{
|
||||
if (this.SkillBrowser.BrowserSupported is true)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.HideProfessionListView();
|
||||
this.SkillBrowser.Width = 400;
|
||||
this.SkillListContainer.Width = 0;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -316,23 +127,104 @@ public partial class BuildTemplate : UserControl
|
||||
|
||||
private void ShowSkillListView()
|
||||
{
|
||||
this.SkillBrowser.Width = 0;
|
||||
this.HideInfoBrowser();
|
||||
this.HideProfessionListView();
|
||||
this.SkillListContainer.Width = 400;
|
||||
}
|
||||
|
||||
private void HideSkillListView()
|
||||
{
|
||||
this.SkillListContainer.Width = 0;
|
||||
}
|
||||
|
||||
private void HelpButtonPrimary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.PrimaryProfession == Profession.None)
|
||||
this.SkillListContainer.Visibility = Visibility.Visible;
|
||||
this.showingSkillList = true;
|
||||
if (this.AvailableSkills is not null &&
|
||||
this.skillListCache?.Except(this.AvailableSkills).None() is true &&
|
||||
this.skillListCache.Count == this.AvailableSkills.Count)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(this.PrimaryProfession.Name!);
|
||||
this.AvailableSkills = this.skillListCache;
|
||||
}
|
||||
|
||||
private void HideSkillListView()
|
||||
{
|
||||
this.SkillListContainer.Visibility = Visibility.Hidden;
|
||||
this.SkillListContainer.Width = 0;
|
||||
this.showingSkillList = false;
|
||||
}
|
||||
|
||||
private void ShowProfessionListView()
|
||||
{
|
||||
this.HideInfoBrowser();
|
||||
this.HideSkillListView();
|
||||
this.ProfessionListView.Width = 400;
|
||||
this.ProfessionListView.Visibility = Visibility.Visible;
|
||||
}
|
||||
|
||||
private void HideProfessionListView()
|
||||
{
|
||||
this.ProfessionListView.Visibility = Visibility.Hidden;
|
||||
this.ProfessionListView.Width = 0;
|
||||
}
|
||||
|
||||
private void PrepareSkillListCache(List<Skill> skills)
|
||||
{
|
||||
/*
|
||||
* To improve application performance, only load the skill list when it is showing.
|
||||
* Otherwise, defer the loading to when the skill list will show.
|
||||
*/
|
||||
|
||||
this.skillListCache = skills;
|
||||
if (this.showingSkillList)
|
||||
{
|
||||
this.ShowSkillListView();
|
||||
}
|
||||
}
|
||||
|
||||
private async IAsyncEnumerable<Skill> FilterSkills(string searchTerm)
|
||||
{
|
||||
// Replace symbols to ease search
|
||||
searchTerm = searchTerm?.Replace("\"", "").Replace("!", "")!;
|
||||
|
||||
foreach (var skill in Skill.Skills)
|
||||
{
|
||||
if (skill == Skill.NoSkill)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (skill.Profession != this.BuildEntry!.Primary &&
|
||||
skill.Profession != this.BuildEntry!.Secondary &&
|
||||
skill.Profession != Profession.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (searchTerm.IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
|
||||
var matchesName = await Task.Run(() => StringUtils.MatchesSearchString(skill.Name!.Replace("\"", "").Replace("!", ""), searchTerm!));
|
||||
if (matchesName)
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
private void Grid_MouseLeftButtonDown(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
this.HideSkillListView();
|
||||
this.HideInfoBrowser();
|
||||
}
|
||||
|
||||
private void HelpButtonPrimary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.BuildEntry!.Primary == Profession.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(this.BuildEntry.Primary.Name!);
|
||||
if (e is RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
routedEventArgs.Handled = true;
|
||||
@@ -341,12 +233,12 @@ public partial class BuildTemplate : UserControl
|
||||
|
||||
private void HelpButtonSecondary_Clicked(object sender, System.EventArgs e)
|
||||
{
|
||||
if (this.SecondaryProfession == Profession.None)
|
||||
if (this.BuildEntry!.Secondary == Profession.None)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.BrowseToInfo(this.SecondaryProfession.Name!);
|
||||
this.BrowseToInfo(this.BuildEntry.Secondary.Name!);
|
||||
if (e is RoutedEventArgs routedEventArgs)
|
||||
{
|
||||
routedEventArgs.Handled = true;
|
||||
@@ -362,6 +254,7 @@ public partial class BuildTemplate : UserControl
|
||||
{
|
||||
e.ThrowIfNull();
|
||||
this.BuildChanged?.Invoke(this, new EventArgs());
|
||||
this.AttributePoints = this.attributePointCalculator!.GetRemainingFreePoints(this.BuildEntry.Build!);
|
||||
}
|
||||
|
||||
private void SkillTemplate_Clicked(object sender, RoutedEventArgs e)
|
||||
@@ -389,10 +282,41 @@ public partial class BuildTemplate : UserControl
|
||||
|
||||
private void SkillTemplate_RemoveClicked(object sender, System.EventArgs e)
|
||||
{
|
||||
sender.As<SkillTemplate>().DataContext = Skill.NoSkill;
|
||||
if (sender == this.SkillTemplate0)
|
||||
{
|
||||
this.BuildEntry.FirstSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate1)
|
||||
{
|
||||
this.BuildEntry.SecondSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate2)
|
||||
{
|
||||
this.BuildEntry.ThirdSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate3)
|
||||
{
|
||||
this.BuildEntry.FourthSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate4)
|
||||
{
|
||||
this.BuildEntry.FifthSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate5)
|
||||
{
|
||||
this.BuildEntry.SixthSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate6)
|
||||
{
|
||||
this.BuildEntry.SeventhSkill = Skill.NoSkill;
|
||||
}
|
||||
else if (sender == this.SkillTemplate7)
|
||||
{
|
||||
this.BuildEntry.EigthSkill = Skill.NoSkill;
|
||||
}
|
||||
}
|
||||
|
||||
private void ListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
private void SkillListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
if (this.selectingSkillTemplate is null)
|
||||
{
|
||||
@@ -400,77 +324,76 @@ public partial class BuildTemplate : UserControl
|
||||
return;
|
||||
}
|
||||
|
||||
this.selectingSkillTemplate.DataContext = sender.As<ListView>().SelectedItem;
|
||||
var selectedSkilll = sender.As<ListView>().SelectedItem.As<Skill>();
|
||||
if (this.selectingSkillTemplate == this.SkillTemplate0)
|
||||
{
|
||||
this.BuildEntry.FirstSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate1)
|
||||
{
|
||||
this.BuildEntry.SecondSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate2)
|
||||
{
|
||||
this.BuildEntry.ThirdSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate3)
|
||||
{
|
||||
this.BuildEntry.FourthSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate4)
|
||||
{
|
||||
this.BuildEntry.FifthSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate5)
|
||||
{
|
||||
this.BuildEntry.SixthSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate6)
|
||||
{
|
||||
this.BuildEntry.SeventhSkill = selectedSkilll;
|
||||
}
|
||||
else if (this.selectingSkillTemplate == this.SkillTemplate7)
|
||||
{
|
||||
this.BuildEntry.EigthSkill = selectedSkilll;
|
||||
}
|
||||
|
||||
this.HideSkillListView();
|
||||
this.loadedBuild!.Build!.Skills[0] = this.Skill0;
|
||||
this.loadedBuild!.Build!.Skills[1] = this.Skill1;
|
||||
this.loadedBuild!.Build!.Skills[2] = this.Skill2;
|
||||
this.loadedBuild!.Build!.Skills[3] = this.Skill3;
|
||||
this.loadedBuild!.Build!.Skills[4] = this.Skill4;
|
||||
this.loadedBuild!.Build!.Skills[5] = this.Skill5;
|
||||
this.loadedBuild!.Build!.Skills[6] = this.Skill6;
|
||||
this.loadedBuild!.Build!.Skills[7] = this.Skill7;
|
||||
}
|
||||
|
||||
private void ListView_NavigateWithMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
||||
private void ProfessionListView_MouseDoubleClick(object sender, System.Windows.Input.MouseButtonEventArgs e)
|
||||
{
|
||||
e.Handled = true;
|
||||
if (e.Delta > 0)
|
||||
var selected = sender.As<ListView>().SelectedItem.As<Profession>();
|
||||
if (this.replacingPrimaryProfession)
|
||||
{
|
||||
sender.As<ListView>().SelectedIndex = sender.As<ListView>().SelectedIndex > 0 ?
|
||||
sender.As<ListView>().SelectedIndex - 1 :
|
||||
0;
|
||||
this.BuildEntry!.Primary = selected;
|
||||
}
|
||||
else
|
||||
else if (this.replacingSecondaryProfession)
|
||||
{
|
||||
sender.As<ListView>().SelectedIndex = sender.As<ListView>().SelectedIndex < sender.As<ListView>().Items.Count - 1 ?
|
||||
sender.As<ListView>().SelectedIndex + 1 :
|
||||
sender.As<ListView>().Items.Count;
|
||||
this.BuildEntry!.Secondary = selected;
|
||||
}
|
||||
|
||||
this.HideProfessionListView();
|
||||
}
|
||||
|
||||
private void ScrollViewer_PreviewMouseWheel(object sender, System.Windows.Input.MouseWheelEventArgs e)
|
||||
private void SecondaryProfessionButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
if (sender is not ScrollViewer scrollViewer)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
e.Handled = true;
|
||||
scrollViewer.ScrollToVerticalOffset(scrollViewer.VerticalOffset - e.Delta);
|
||||
this.replacingPrimaryProfession = false;
|
||||
this.replacingSecondaryProfession = true;
|
||||
this.Professions = Profession.Professions.Where(p => p != this.BuildEntry?.Secondary).ToList();
|
||||
this.ShowProfessionListView();
|
||||
}
|
||||
|
||||
private async IAsyncEnumerable<Skill> FilterSkills(string searchTerm)
|
||||
private void PrimaryProfessionButton_Clicked(object sender, EventArgs e)
|
||||
{
|
||||
// Replace symbols to ease search
|
||||
searchTerm = searchTerm?.Replace("\"", "").Replace("!", "")!;
|
||||
|
||||
foreach (var skill in Skill.Skills)
|
||||
{
|
||||
if (skill == Skill.NoSkill)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
this.replacingPrimaryProfession = true;
|
||||
this.replacingSecondaryProfession = false;
|
||||
this.Professions.ClearAnd().AddRange(Profession.Professions.Where(p => p != this.BuildEntry?.Primary));
|
||||
this.ShowProfessionListView();
|
||||
}
|
||||
|
||||
if (skill.Profession != this.PrimaryProfession &&
|
||||
skill.Profession != this.SecondaryProfession &&
|
||||
skill.Profession != Profession.None)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (searchTerm.IsNullOrWhiteSpace())
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
|
||||
var matchesName = await Task.Run(() => StringUtils.MatchesSearchString(skill.Name!.Replace("\"", "").Replace("!", ""), searchTerm!));
|
||||
if (matchesName)
|
||||
{
|
||||
yield return skill;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
private void AttributeTemplate_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
sender.As<AttributeTemplate>().InitializeAttributeTemplate(this.attributePointCalculator!);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
<UserControl x:Class="Daybreak.Controls.Templates.QuestLogTemplate"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls.Templates"
|
||||
mc:Ignorable="d"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<StackPanel x:Name="ItemStackPanel">
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,170 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Data;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Media;
|
||||
using System.Windows.Shapes;
|
||||
|
||||
namespace Daybreak.Controls.Templates;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for QuestLogTemplate.xaml
|
||||
/// </summary>
|
||||
public partial class QuestLogTemplate : UserControl
|
||||
{
|
||||
private const string UncategorizedQuestsString = "Uncategorized Quests";
|
||||
private List<IGrouping<Map?, QuestMetadata>>? questLogCache;
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
private List<QuestMetadata> quests;
|
||||
|
||||
public event EventHandler<Map?>? MapClicked;
|
||||
public event EventHandler<Quest?>? QuestClicked;
|
||||
|
||||
public QuestLogTemplate()
|
||||
{
|
||||
this.quests = new List<QuestMetadata>();
|
||||
this.InitializeComponent();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
|
||||
if (e.Property == QuestsProperty)
|
||||
{
|
||||
this.DrawQuestLogLayout();
|
||||
}
|
||||
}
|
||||
|
||||
private void DrawQuestLogLayout()
|
||||
{
|
||||
var questLog = this.Quests?.GroupBy(q => q.From).OrderBy(g => g.Key?.Name).ToList();
|
||||
if (!this.DetectQuestLogChange(questLog))
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.questLogCache = questLog;
|
||||
if (this.questLogCache is null)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
this.ItemStackPanel.Children.Clear();
|
||||
|
||||
foreach(var grouping in this.questLogCache)
|
||||
{
|
||||
var location = grouping.Key;
|
||||
var locationTextBlock = new OpaqueButton
|
||||
{
|
||||
Text = grouping.Key?.Name ?? UncategorizedQuestsString,
|
||||
FontSize = 18,
|
||||
Cursor = grouping.Key is null ? Cursors.Arrow : Cursors.Hand,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
TextHorizontalAlignment = HorizontalAlignment.Left,
|
||||
Highlight = Brushes.White,
|
||||
HighlightOpacity = grouping.Key is null ? 0 : 0.6
|
||||
};
|
||||
|
||||
locationTextBlock.MouseLeftButtonDown += (_, _) => this.OnMapClicked(location);
|
||||
this.ItemStackPanel.Children.Add(locationTextBlock);
|
||||
var rectangle = new Rectangle
|
||||
{
|
||||
Height = 1,
|
||||
};
|
||||
|
||||
var rectangleForegroundBinding = new Binding("Foreground")
|
||||
{
|
||||
Source = this
|
||||
};
|
||||
|
||||
rectangle.SetBinding(Rectangle.FillProperty, rectangleForegroundBinding);
|
||||
this.ItemStackPanel.Children.Add(rectangle);
|
||||
foreach (var questMetadata in grouping)
|
||||
{
|
||||
var quest = questMetadata.Quest;
|
||||
var questTextBlock = new OpaqueButton
|
||||
{
|
||||
Text = quest?.Name,
|
||||
FontSize = 20,
|
||||
Cursor = Cursors.Hand,
|
||||
Highlight = Brushes.White,
|
||||
HighlightOpacity = 0.6,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch,
|
||||
TextHorizontalAlignment = HorizontalAlignment.Left
|
||||
};
|
||||
|
||||
questTextBlock.MouseLeftButtonDown += (_, _) => this.OnQuestClicked(quest);
|
||||
this.ItemStackPanel.Children.Add(questTextBlock);
|
||||
}
|
||||
|
||||
this.ItemStackPanel.Children.Add(new Rectangle
|
||||
{
|
||||
Fill = Brushes.Transparent,
|
||||
Height = 10,
|
||||
HorizontalAlignment = HorizontalAlignment.Stretch
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
private bool DetectQuestLogChange(List<IGrouping<Map?, QuestMetadata>>? newQuestLog)
|
||||
{
|
||||
if (this.questLogCache is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (newQuestLog is null)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (this.questLogCache.Count != newQuestLog.Count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var i = 0; i < this.questLogCache.Count; i++)
|
||||
{
|
||||
var grouping1 = this.questLogCache[i];
|
||||
var grouping2 = newQuestLog[i];
|
||||
if (grouping1.Key?.Id != grouping2.Key?.Id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
var cachedQuests = grouping1.ToList();
|
||||
var newQuests = grouping2.ToList();
|
||||
if (cachedQuests.Count != newQuests.Count)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
for (var j = 0; j < cachedQuests.Count; j++)
|
||||
{
|
||||
if (cachedQuests[j].Quest?.Id != newQuests[j].Quest?.Id)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void OnMapClicked(Map? map)
|
||||
{
|
||||
this.MapClicked?.Invoke(this, map);
|
||||
}
|
||||
|
||||
private void OnQuestClicked(Quest? quest)
|
||||
{
|
||||
this.QuestClicked?.Invoke(this, quest);
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,9 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Launch;
|
||||
using Daybreak.Models.Guildwars;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using System;
|
||||
using System.Core.Extensions;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
@@ -27,15 +30,16 @@ public partial class SkillTemplate : UserControl
|
||||
private double borderOpacity;
|
||||
|
||||
public SkillTemplate()
|
||||
: this(Launcher.Instance.ApplicationServiceProvider.GetRequiredService<IIconCache>())
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += this.SkillTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
public void InitializeSkillTemplate(IIconCache iconRetriever)
|
||||
public SkillTemplate(
|
||||
IIconCache iconCache)
|
||||
{
|
||||
this.iconRetriever = iconRetriever;
|
||||
this.SkillTemplate_DataContextChanged(this, new DependencyPropertyChangedEventArgs(UserControl.DataContextProperty, null, this.DataContext));
|
||||
this.iconRetriever = iconCache.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
this.DataContextChanged += this.SkillTemplate_DataContextChanged;
|
||||
}
|
||||
|
||||
private async void SkillTemplate_DataContextChanged(object sender, DependencyPropertyChangedEventArgs e)
|
||||
|
||||
@@ -0,0 +1,37 @@
|
||||
<UserControl x:Class="Daybreak.Controls.VerticalResourceBar"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
mc:Ignorable="d"
|
||||
x:Name="_this"
|
||||
d:DesignHeight="450" d:DesignWidth="800">
|
||||
<Grid>
|
||||
<Viewbox VerticalAlignment="Stretch" HorizontalAlignment="Stretch" Stretch="Fill">
|
||||
<Grid Width="1">
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Height="{Binding ElementName=_this, Path=MaxResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="#F0212121"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Stretch"></Rectangle>
|
||||
<Rectangle
|
||||
Fill="{Binding ElementName=_this, Path=BarColor, Mode=OneWay}"
|
||||
VerticalAlignment="{Binding ElementName=_this, Path=FillAlignment, Mode=OneWay}"
|
||||
HorizontalAlignment="Stretch"
|
||||
Height="{Binding ElementName=_this, Path=CurrentResourceValue, Mode=TwoWay}"></Rectangle>
|
||||
</Grid>
|
||||
</Viewbox>
|
||||
<TextBlock
|
||||
FontSize="{Binding ElementName=_this, Path=FontSize, Mode=OneWay}"
|
||||
FontFamily="{Binding ElementName=_this, Path=FontFamily, Mode=OneWay}"
|
||||
Text="{Binding ElementName=_this, Path=Text, Mode=OneWay}"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
VerticalAlignment="Center"
|
||||
HorizontalAlignment="Center"></TextBlock>
|
||||
</Grid>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,32 @@
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Media;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for ResourceBar.xaml
|
||||
/// </summary>
|
||||
public partial class VerticalResourceBar : UserControl
|
||||
{
|
||||
[GenerateDependencyProperty]
|
||||
private double currentResourceValue;
|
||||
[GenerateDependencyProperty]
|
||||
private double maxResourceValue;
|
||||
[GenerateDependencyProperty]
|
||||
private Brush barColor;
|
||||
[GenerateDependencyProperty]
|
||||
private string text;
|
||||
[GenerateDependencyProperty(InitialValue = VerticalAlignment.Bottom)]
|
||||
private VerticalAlignment fillAlignment;
|
||||
|
||||
public VerticalResourceBar()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
this.MaxResourceValue = 1;
|
||||
this.CurrentResourceValue = 0;
|
||||
this.barColor = Brushes.Transparent;
|
||||
this.text = string.Empty;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,21 @@
|
||||
<UserControl x:Class="Daybreak.Controls.WorldPlayerContextMenu"
|
||||
xmlns="http://schemas.microsoft.com/winfx/2006/xaml/presentation"
|
||||
xmlns:x="http://schemas.microsoft.com/winfx/2006/xaml"
|
||||
xmlns:mc="http://schemas.openxmlformats.org/markup-compatibility/2006"
|
||||
xmlns:d="http://schemas.microsoft.com/expression/blend/2008"
|
||||
xmlns:local="clr-namespace:Daybreak.Controls"
|
||||
xmlns:guildwars="clr-namespace:Daybreak.Models.Guildwars"
|
||||
mc:Ignorable="d"
|
||||
d:DataContext="{d:DesignInstance Type=guildwars:WorldPlayerInformation, IsDesignTimeCreatable=True}"
|
||||
d:DesignHeight="300" d:DesignWidth="100">
|
||||
<StackPanel Background="#F0212121">
|
||||
<TextBlock
|
||||
Margin="5, 0, 5, 0"
|
||||
Text="{Binding Name, Mode=OneWay}" FontSize="16" Foreground="White"></TextBlock>
|
||||
<WrapPanel
|
||||
Margin="5, 0, 5, 0">
|
||||
<TextBlock Text="Lvl: " Foreground="White"></TextBlock>
|
||||
<TextBlock Text="{Binding Level, Mode=OneWay}" Foreground="White"></TextBlock>
|
||||
</WrapPanel>
|
||||
</StackPanel>
|
||||
</UserControl>
|
||||
@@ -0,0 +1,14 @@
|
||||
using System.Windows.Controls;
|
||||
|
||||
namespace Daybreak.Controls;
|
||||
|
||||
/// <summary>
|
||||
/// Interaction logic for WorldPlayerContextMenu.xaml
|
||||
/// </summary>
|
||||
public partial class WorldPlayerContextMenu : UserControl
|
||||
{
|
||||
public WorldPlayerContextMenu()
|
||||
{
|
||||
this.InitializeComponent();
|
||||
}
|
||||
}
|
||||
+37
-57
@@ -8,16 +8,44 @@
|
||||
<UseWPF>true</UseWPF>
|
||||
<Nullable>enable</Nullable>
|
||||
<UseWindowsForms>true</UseWindowsForms>
|
||||
<Platforms>AnyCPU;x86</Platforms>
|
||||
<Platforms>AnyCPU;x86;x64</Platforms>
|
||||
<CopyLocalLockFileAssemblies>true</CopyLocalLockFileAssemblies>
|
||||
<LangVersion>preview</LangVersion>
|
||||
<ApplicationIcon>Daybreak.ico</ApplicationIcon>
|
||||
<IncludePackageReferencesDuringMarkupCompilation>true</IncludePackageReferencesDuringMarkupCompilation>
|
||||
<Version>0.9.8</Version>
|
||||
<Version>0.9.8.41</Version>
|
||||
<EnableWindowsTargeting>true</EnableWindowsTargeting>
|
||||
<UserSecretsId>cfb2a489-db80-448d-a969-80270f314c46</UserSecretsId>
|
||||
<AllowUnsafeBlocks>True</AllowUnsafeBlocks>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Services\Drawing\Resources\Bag.svg" />
|
||||
<None Remove="Services\Drawing\Resources\CircledStar.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Dungeon.svg" />
|
||||
<None Remove="Services\Drawing\Resources\DungeonBoss.svg" />
|
||||
<None Remove="Services\Drawing\Resources\DungeonKey.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Scroll.svg" />
|
||||
<None Remove="Services\Drawing\Resources\Skull.svg" />
|
||||
<None Remove="Services\Drawing\Resources\StairsDown.svg" />
|
||||
<None Remove="Services\Drawing\Resources\StairsUp.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Bag.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\CircledStar.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Dungeon.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\DungeonBoss.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Scroll.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\Skull.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\StairsDown.svg" />
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\StairsUp.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<EmbeddedResource Include="Services\Drawing\Resources\DungeonKey.svg" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Include="..\.editorconfig" Link=".editorconfig" />
|
||||
</ItemGroup>
|
||||
@@ -37,76 +65,28 @@
|
||||
</Target>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="LiteDB" Version="5.0.15" />
|
||||
<PackageReference Include="LiteDB" Version="5.0.16" />
|
||||
<PackageReference Include="Microsoft.CorrelationVector" Version="1.0.42" />
|
||||
<PackageReference Include="Microsoft.Extensions.Configuration.UserSecrets" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Http" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Logging.Abstractions" Version="7.0.0" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1587.40" />
|
||||
<PackageReference Include="Microsoft.Web.WebView2" Version="1.0.1661.34" />
|
||||
<PackageReference Include="Microsoft.Xaml.Behaviors.Wpf" Version="1.1.39" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.2" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.3" />
|
||||
<PackageReference Include="ScottPlot.WPF" Version="4.1.63" />
|
||||
<PackageReference Include="securifybv.ShellLink" Version="0.1.0" />
|
||||
<PackageReference Include="Slim" Version="1.9.2" />
|
||||
<PackageReference Include="Svg" Version="3.4.4" />
|
||||
<PackageReference Include="System.Linq.Async" Version="6.0.1" />
|
||||
<PackageReference Include="SystemExtensions.NetCore" Version="1.0.1" />
|
||||
<PackageReference Include="SystemExtensions.NetStandard" Version="1.5.0" />
|
||||
<PackageReference Include="WCL" Version="1.0.2" />
|
||||
<PackageReference Include="WpfExtended" Version="0.7.1" />
|
||||
<PackageReference Include="WpfExtended" Version="0.7.2" />
|
||||
<PackageReference Include="WpfExtended.SourceGeneration" Version="0.1.1" />
|
||||
<PackageReference Include="WpfScreenHelper" Version="2.1.0" />
|
||||
<PackageReference Include="WriteableBitmapEx" Version="1.6.8" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Compile Update="Controls\Buttons\SynchronizeButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\Buttons\HelpButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\Buttons\MinusButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\Glyphs\StarGlyph.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Controls\Buttons\CancelButton.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
<Compile Update="Views\IconDownloadView.xaml.cs">
|
||||
<SubType>Code</SubType>
|
||||
</Compile>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Page Update="Controls\Buttons\SynchronizeButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\Buttons\HelpButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\Buttons\MinusButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\Buttons\MaximizeButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\Glyphs\StarGlyph.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Controls\Buttons\CancelButton.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
<Page Update="Views\IconDownloadView.xaml">
|
||||
<XamlRuntime>$(DefaultXamlRuntime)</XamlRuntime>
|
||||
<SubType>Designer</SubType>
|
||||
</Page>
|
||||
</ItemGroup>
|
||||
|
||||
<Target Name="PostBuild" AfterTargets="PostBuildEvent" Condition="'$(Configuration)' == 'Release'">
|
||||
<Exec Command="echo.>$(Version).version" />
|
||||
|
||||
+17
-58
@@ -1,17 +1,15 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Exceptions;
|
||||
using Daybreak.Services.Drawing;
|
||||
using Daybreak.Services.ExceptionHandling;
|
||||
using Daybreak.Services.Navigation;
|
||||
using Daybreak.Services.Options;
|
||||
using Daybreak.Services.Startup;
|
||||
using Daybreak.Services.Updater.PostUpdate;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Logging;
|
||||
using Slim;
|
||||
using Slim.Integration.ServiceCollection;
|
||||
using System;
|
||||
using System.IO;
|
||||
using System.Linq;
|
||||
using System.Reflection;
|
||||
using System.Runtime.InteropServices;
|
||||
using System.Windows;
|
||||
using System.Windows.Extensions;
|
||||
|
||||
namespace Daybreak.Launch;
|
||||
@@ -21,6 +19,7 @@ public sealed class Launcher : ExtendedApplication<MainWindow>
|
||||
public readonly static Launcher Instance = new();
|
||||
|
||||
private ILogger? logger;
|
||||
private IExceptionHandler? exceptionHandler;
|
||||
|
||||
public System.IServiceProvider ApplicationServiceProvider => this.ServiceProvider;
|
||||
|
||||
@@ -36,71 +35,30 @@ public sealed class Launcher : ExtendedApplication<MainWindow>
|
||||
ProjectConfiguration.RegisterResolvers(serviceManager);
|
||||
return services.BuildSlimServiceProvider(serviceManager);
|
||||
}
|
||||
|
||||
protected override void RegisterServices(IServiceCollection services)
|
||||
{
|
||||
ProjectConfiguration.RegisterServices(services);
|
||||
}
|
||||
|
||||
protected override bool HandleException(Exception e)
|
||||
{
|
||||
if (e is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (this.logger is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if (e is FatalException fatalException)
|
||||
{
|
||||
this.logger.LogCritical(e, $"{nameof(FatalException)} encountered. Closing application");
|
||||
MessageBox.Show(fatalException.ToString());
|
||||
File.WriteAllText("crash.log", e.ToString());
|
||||
return false;
|
||||
}
|
||||
else if (e is TargetInvocationException targetInvocationException && e.InnerException is FatalException innerFatalException)
|
||||
{
|
||||
this.logger.LogCritical(e, $"{nameof(FatalException)} encountered. Closing application");
|
||||
MessageBox.Show(innerFatalException.ToString());
|
||||
File.WriteAllText("crash.log", e.ToString());
|
||||
return false;
|
||||
}
|
||||
else if (e is AggregateException aggregateException)
|
||||
{
|
||||
if (aggregateException.InnerExceptions.FirstOrDefault() is COMException comException &&
|
||||
comException.Message.Contains("Invalid window handle"))
|
||||
{
|
||||
/*
|
||||
* Ignore exception caused by browser failing to initialize due to missing window.
|
||||
* Likely caused by switching views before browser was initialized.
|
||||
*/
|
||||
this.logger.LogError(e, "Failed to initialize browser");
|
||||
return true;
|
||||
}
|
||||
}
|
||||
else if (e.Message.Contains("Invalid window handle.") && e.StackTrace?.Contains("CoreWebView2Environment.CreateCoreWebView2ControllerAsync") is true)
|
||||
{
|
||||
/*
|
||||
* Ignore exception caused by browser failing to initialize due to missing window.
|
||||
* Likely caused by switching views before the browser was initialized.
|
||||
*/
|
||||
this.logger.LogError(e, "Failed to initialize browser");
|
||||
return true;
|
||||
}
|
||||
|
||||
this.logger.LogError(e, $"Unhandled exception caught {e.GetType()}");
|
||||
MessageBox.Show(e.ToString());
|
||||
return true;
|
||||
return this.exceptionHandler?.HandleException(e) is true;
|
||||
}
|
||||
|
||||
protected override void ApplicationStarting()
|
||||
{
|
||||
ProjectConfiguration.RegisterViews(this.ServiceProvider.GetService<IViewManager>()!);
|
||||
ProjectConfiguration.RegisterPostUpdateActions(this.ServiceProvider.GetService<IPostUpdateActionProducer>()!);
|
||||
ProjectConfiguration.RegisterOptions(this.ServiceProvider.GetRequiredService<IOptionsProducer>()!);
|
||||
ProjectConfiguration.RegisterViews(this.ServiceProvider.GetRequiredService<IViewManager>()!);
|
||||
ProjectConfiguration.RegisterPostUpdateActions(this.ServiceProvider.GetRequiredService<IPostUpdateActionProducer>()!);
|
||||
ProjectConfiguration.RegisterStartupActions(this.ServiceProvider.GetRequiredService<IStartupActionProducer>()!);
|
||||
ProjectConfiguration.RegisterDrawingModules(this.ServiceProvider.GetRequiredService<IDrawingModuleProducer>()!);
|
||||
|
||||
this.logger = this.ServiceProvider.GetRequiredService<ILogger<Launcher>>();
|
||||
this.exceptionHandler = this.ServiceProvider.GetRequiredService<IExceptionHandler>();
|
||||
this.RegisterViewContainer();
|
||||
}
|
||||
|
||||
protected override void ApplicationClosing()
|
||||
{
|
||||
}
|
||||
@@ -111,6 +69,7 @@ public sealed class Launcher : ExtendedApplication<MainWindow>
|
||||
var mainWindow = this.ServiceProvider.GetRequiredService<MainWindow>();
|
||||
viewManager.RegisterContainer(mainWindow.Container);
|
||||
}
|
||||
|
||||
private static int LaunchMainWindow()
|
||||
{
|
||||
return Instance.Run();
|
||||
|
||||
@@ -23,7 +23,7 @@
|
||||
<Setter Property="Template">
|
||||
<Setter.Value>
|
||||
<ControlTemplate TargetType="{x:Type ToggleButton}">
|
||||
<Grid>
|
||||
<Grid Cursor="Hand">
|
||||
<Rectangle x:Name="OverlayRect" Fill="{TemplateBinding Background}" Opacity="0"></Rectangle>
|
||||
<controls:ThreeDotsGlyph Margin="13"></controls:ThreeDotsGlyph>
|
||||
</Grid>
|
||||
@@ -33,7 +33,7 @@
|
||||
<Condition Property="IsMouseOver" Value="True"></Condition>
|
||||
</MultiTrigger.Conditions>
|
||||
<MultiTrigger.Setters>
|
||||
<Setter Property="Opacity" TargetName="OverlayRect" Value="0.5"></Setter>
|
||||
<Setter Property="Opacity" TargetName="OverlayRect" Value="1"></Setter>
|
||||
</MultiTrigger.Setters>
|
||||
</MultiTrigger>
|
||||
<MultiTrigger>
|
||||
@@ -118,7 +118,7 @@
|
||||
Grid.RowSpan="2"
|
||||
VerticalAlignment="Stretch"
|
||||
HorizontalAlignment="Left"
|
||||
Background="#A0202020">
|
||||
Background="#F0212121">
|
||||
<controls:MenuList Margin="0, 30, 0, 0"/>
|
||||
</Grid>
|
||||
<ToggleButton x:Name="OpeningSettingsButton"
|
||||
@@ -126,6 +126,7 @@
|
||||
Width="50"
|
||||
Height="30"
|
||||
HorizontalAlignment="Left"
|
||||
Background="#F0212121"
|
||||
Margin="0, 0, 0, 0"
|
||||
Grid.ColumnSpan="2"
|
||||
Foreground="{Binding ElementName=_this, Path=Foreground, Mode=OneWay}"
|
||||
@@ -138,6 +139,7 @@
|
||||
Margin="0, 0, 0, 0"
|
||||
Grid.ColumnSpan="2"
|
||||
Foreground="White"
|
||||
Background="#F09E9E9E"
|
||||
Visibility="{Binding ElementName=_this, Path=IsShowingDropdown, Mode=OneWay, Converter={StaticResource BooleanToVisibilityConverter}}"
|
||||
Click="SettingsButton_Clicked"></ToggleButton>
|
||||
<wcl:Border OnResize="Border_OnResize" Grid.RowSpan="2" Grid.ColumnSpan="2" Active="True"></wcl:Border>
|
||||
@@ -146,8 +148,9 @@
|
||||
HorizontalAlignment="Center"
|
||||
Visibility="Visible"
|
||||
ControlsEnabled="False"
|
||||
CanNavigate="False"
|
||||
CanNavigate="True"
|
||||
CanDownloadBuild="False"
|
||||
Grid.Row="1"></controls:ChromiumBrowserWrapper>
|
||||
Grid.Row="1"
|
||||
Grid.Column="1"></controls:ChromiumBrowserWrapper>
|
||||
</Grid>
|
||||
</Window>
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
using Daybreak.Configuration;
|
||||
using Daybreak.Configuration.Options;
|
||||
using Daybreak.Services.Bloogum;
|
||||
using Daybreak.Services.IconRetrieve;
|
||||
using Daybreak.Services.Menu;
|
||||
@@ -16,7 +16,6 @@ using System.Extensions;
|
||||
using System.Threading;
|
||||
using System.Windows;
|
||||
using System.Windows.Controls;
|
||||
using System.Windows.Controls.Primitives;
|
||||
using System.Windows.Extensions;
|
||||
using System.Windows.Input;
|
||||
using System.Windows.Interop;
|
||||
@@ -29,7 +28,7 @@ namespace Daybreak.Launch;
|
||||
/// <summary>
|
||||
/// Interaction logic for MainWindow.xaml
|
||||
/// </summary>
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add readonly modifier", Justification = "Fields used by source generator for DependencyProperty")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("Style", "IDE0044:Add read-only modifier", Justification = "Fields used by source generator for DependencyProperty")]
|
||||
[System.Diagnostics.CodeAnalysis.SuppressMessage("CodeQuality", "IDE0052:Remove unread private members", Justification = "Used by source generators")]
|
||||
public partial class MainWindow : Window
|
||||
{
|
||||
@@ -40,7 +39,7 @@ public partial class MainWindow : Window
|
||||
private readonly IApplicationUpdater applicationUpdater;
|
||||
private readonly IPrivilegeManager privilegeManager;
|
||||
private readonly IIconDownloader iconDownloader;
|
||||
private readonly ILiveOptions<ApplicationConfiguration> liveOptions;
|
||||
private readonly ILiveOptions<LauncherOptions> launcherOptions;
|
||||
private readonly CancellationTokenSource cancellationToken = new();
|
||||
|
||||
[GenerateDependencyProperty]
|
||||
@@ -52,6 +51,8 @@ public partial class MainWindow : Window
|
||||
[GenerateDependencyProperty]
|
||||
private bool isShowingDropdown;
|
||||
|
||||
public event EventHandler<MainWindow>? WindowParametersChanged;
|
||||
|
||||
public MainWindow(
|
||||
IMenuServiceInitializer menuServiceInitializer,
|
||||
IViewManager viewManager,
|
||||
@@ -60,7 +61,7 @@ public partial class MainWindow : Window
|
||||
IApplicationUpdater applicationUpdater,
|
||||
IPrivilegeManager privilegeManager,
|
||||
IIconDownloader iconDownloader,
|
||||
ILiveOptions<ApplicationConfiguration> liveOptions)
|
||||
ILiveOptions<LauncherOptions> launcherOptions)
|
||||
{
|
||||
this.menuServiceInitializer = menuServiceInitializer.ThrowIfNull();
|
||||
this.viewManager = viewManager.ThrowIfNull();
|
||||
@@ -69,13 +70,29 @@ public partial class MainWindow : Window
|
||||
this.applicationUpdater = applicationUpdater.ThrowIfNull();
|
||||
this.privilegeManager = privilegeManager.ThrowIfNull();
|
||||
this.iconDownloader = iconDownloader.ThrowIfNull();
|
||||
this.liveOptions = liveOptions.ThrowIfNull();
|
||||
this.launcherOptions = launcherOptions.ThrowIfNull();
|
||||
this.InitializeComponent();
|
||||
this.CurrentVersionText = this.applicationUpdater.CurrentVersion.ToString();
|
||||
this.IsRunningAsAdmin = this.privilegeManager.AdminPrivileges;
|
||||
this.SetupMenuService();
|
||||
}
|
||||
|
||||
protected override void OnPropertyChanged(DependencyPropertyChangedEventArgs e)
|
||||
{
|
||||
base.OnPropertyChanged(e);
|
||||
if (this.IsLoaded is false)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
if (e.Property == LeftProperty ||
|
||||
e.Property == TopProperty ||
|
||||
e.Property == ActualWidthProperty ||
|
||||
e.Property == ActualHeightProperty)
|
||||
{
|
||||
this.WindowParametersChanged?.Invoke(this, this);
|
||||
}
|
||||
}
|
||||
|
||||
private void Window_Loaded(object sender, RoutedEventArgs e)
|
||||
{
|
||||
@@ -263,7 +280,7 @@ public partial class MainWindow : Window
|
||||
|
||||
private async void CheckForUpdates()
|
||||
{
|
||||
var updateAvailable = this.liveOptions.Value.AutoCheckUpdate is true && await this.applicationUpdater.UpdateAvailable().ConfigureAwait(true);
|
||||
var updateAvailable = this.launcherOptions.Value.AutoCheckUpdate is true && await this.applicationUpdater.UpdateAvailable().ConfigureAwait(true);
|
||||
if (updateAvailable)
|
||||
{
|
||||
this.viewManager.ShowView<AskUpdateView>();
|
||||
@@ -320,6 +337,6 @@ public partial class MainWindow : Window
|
||||
double R = color.ScR;
|
||||
double G = color.ScG;
|
||||
double B = color.ScB;
|
||||
return 0.299 * R + 0.587 * G + 0.114 * B;
|
||||
return (0.299 * R) + (0.587 * G) + (0.114 * B);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -12,12 +12,12 @@ public class BrowserPayload
|
||||
ContextMenu
|
||||
}
|
||||
|
||||
[JsonProperty("Key")]
|
||||
[JsonProperty(nameof(Key))]
|
||||
public PayloadKeys Key { get; set; }
|
||||
}
|
||||
|
||||
public sealed class BrowserPayload<T> : BrowserPayload
|
||||
{
|
||||
[JsonProperty("Value")]
|
||||
[JsonProperty(nameof(Value))]
|
||||
public T? Value { get; set; }
|
||||
}
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Daybreak.Models.Browser;
|
||||
|
||||
public sealed class DownloadPayload
|
||||
{
|
||||
public string? ResultingFilePath { get; init; }
|
||||
public bool CanDownload { get; set; }
|
||||
}
|
||||
@@ -4,10 +4,10 @@ namespace Daybreak.Models.Browser;
|
||||
|
||||
public sealed class OnContextMenuPayload
|
||||
{
|
||||
[JsonProperty("X")]
|
||||
[JsonProperty(nameof(X))]
|
||||
public double X { get; set; }
|
||||
[JsonProperty("Y")]
|
||||
[JsonProperty(nameof(Y))]
|
||||
public double Y { get; set; }
|
||||
[JsonProperty("Selection")]
|
||||
[JsonProperty(nameof(Selection))]
|
||||
public string? Selection { get; set; }
|
||||
}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System.Collections.Generic;
|
||||
using System.ComponentModel;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Models.Builds;
|
||||
|
||||
@@ -28,4 +30,186 @@ public sealed class BuildEntry : INotifyPropertyChanged
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Build)));
|
||||
}
|
||||
}
|
||||
public Profession Primary
|
||||
{
|
||||
get => this.Build!.Primary;
|
||||
set
|
||||
{
|
||||
this.Build!.Primary = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Primary)));
|
||||
this.UpdateAttributes();
|
||||
}
|
||||
}
|
||||
public Profession Secondary
|
||||
{
|
||||
get => this.Build!.Secondary;
|
||||
set
|
||||
{
|
||||
this.Build!.Secondary = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Secondary)));
|
||||
this.UpdateAttributes();
|
||||
}
|
||||
}
|
||||
public List<AttributeEntry> Attributes
|
||||
{
|
||||
get => this.Build!.Attributes;
|
||||
set
|
||||
{
|
||||
this.Build!.Attributes = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.Attributes)));
|
||||
this.UpdateSkills();
|
||||
}
|
||||
}
|
||||
public Skill FirstSkill
|
||||
{
|
||||
get => this.Build!.Skills[0];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[0] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.FirstSkill)));
|
||||
}
|
||||
}
|
||||
public Skill SecondSkill
|
||||
{
|
||||
get => this.Build!.Skills[1];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[1] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.SecondSkill)));
|
||||
}
|
||||
}
|
||||
public Skill ThirdSkill
|
||||
{
|
||||
get => this.Build!.Skills[2];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[2] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.ThirdSkill)));
|
||||
}
|
||||
}
|
||||
public Skill FourthSkill
|
||||
{
|
||||
get => this.Build!.Skills[3];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[3] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.FourthSkill)));
|
||||
}
|
||||
}
|
||||
public Skill FifthSkill
|
||||
{
|
||||
get => this.Build!.Skills[4];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[4] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.FifthSkill)));
|
||||
}
|
||||
}
|
||||
public Skill SixthSkill
|
||||
{
|
||||
get => this.Build!.Skills[5];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[5] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.SixthSkill)));
|
||||
}
|
||||
}
|
||||
public Skill SeventhSkill
|
||||
{
|
||||
get => this.Build!.Skills[6];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[6] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.SeventhSkill)));
|
||||
}
|
||||
}
|
||||
public Skill EigthSkill
|
||||
{
|
||||
get => this.Build!.Skills[7];
|
||||
set
|
||||
{
|
||||
this.Build!.Skills[7] = value;
|
||||
this.PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(nameof(this.EigthSkill)));
|
||||
}
|
||||
}
|
||||
|
||||
private void UpdateAttributes()
|
||||
{
|
||||
var attributesToAdd = new List<Attribute>();
|
||||
if (this.Primary.PrimaryAttribute is not null)
|
||||
{
|
||||
attributesToAdd.Add(this.Primary.PrimaryAttribute);
|
||||
}
|
||||
|
||||
attributesToAdd.AddRange(this.Primary.Attributes);
|
||||
attributesToAdd.AddRange(this.Secondary.Attributes);
|
||||
this.Attributes = attributesToAdd.Distinct().Select(attribute =>
|
||||
{
|
||||
if (this.Attributes.FirstOrDefault(attributeEntry => attributeEntry.Attribute == attribute) is AttributeEntry attributeEntry)
|
||||
{
|
||||
return attributeEntry;
|
||||
}
|
||||
|
||||
return new AttributeEntry { Attribute = attribute };
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
private void UpdateSkills()
|
||||
{
|
||||
if (this.FirstSkill.Profession != Profession.None &&
|
||||
this.FirstSkill.Profession != this.Primary &&
|
||||
this.FirstSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.FirstSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.SecondSkill.Profession != Profession.None &&
|
||||
this.SecondSkill.Profession != this.Primary &&
|
||||
this.SecondSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.SecondSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.ThirdSkill.Profession != Profession.None &&
|
||||
this.ThirdSkill.Profession != this.Primary &&
|
||||
this.ThirdSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.ThirdSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.FourthSkill.Profession != Profession.None &&
|
||||
this.FourthSkill.Profession != this.Primary &&
|
||||
this.FourthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.FourthSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.FifthSkill.Profession != Profession.None &&
|
||||
this.FifthSkill.Profession != this.Primary &&
|
||||
this.FifthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.FifthSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.SixthSkill.Profession != Profession.None &&
|
||||
this.SixthSkill.Profession != this.Primary &&
|
||||
this.SixthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.SixthSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.SeventhSkill.Profession != Profession.None &&
|
||||
this.SeventhSkill.Profession != this.Primary &&
|
||||
this.SeventhSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.SeventhSkill = Skill.NoSkill;
|
||||
}
|
||||
|
||||
if (this.EigthSkill.Profession != Profession.None &&
|
||||
this.EigthSkill.Profession != this.Primary &&
|
||||
this.EigthSkill.Profession != this.Secondary)
|
||||
{
|
||||
this.EigthSkill = Skill.NoSkill;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -0,0 +1,14 @@
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public enum Affiliation
|
||||
{
|
||||
Gray = 0b00000001,
|
||||
Blue = 0b00000010,
|
||||
Red = 0b00000100,
|
||||
Yellow = 0b00001000,
|
||||
Teal = 0b00010000,
|
||||
Purple = 0b00100000,
|
||||
Green = 0b01000000,
|
||||
GrayNeutral = 0b10000000,
|
||||
Any = 0b11111111
|
||||
}
|
||||
@@ -6,48 +6,48 @@ namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public sealed class Attribute
|
||||
{
|
||||
public static Attribute FastCasting { get; } = new() { Name = "Fast Casting", Id = 0 };
|
||||
public static Attribute IllusionMagic { get; } = new() { Name = "Illusion Magic", Id = 1 };
|
||||
public static Attribute DominationMagic { get; } = new() { Name = "Domination Magic", Id = 2 };
|
||||
public static Attribute InspirationMagic { get; } = new() { Name = "Inspiration Magic", Id = 3 };
|
||||
public static Attribute BloodMagic { get; } = new() { Name = "Blood Magic", Id = 4 };
|
||||
public static Attribute DeathMagic { get; } = new() { Name = "Death Magic", Id = 5 };
|
||||
public static Attribute SoulReaping { get; } = new() { Name = "Soul Reaping", Id = 6 };
|
||||
public static Attribute Curses { get; } = new() { Name = "Curses", Id = 7 };
|
||||
public static Attribute AirMagic { get; } = new() { Name = "Air Magic", Id = 8 };
|
||||
public static Attribute EarthMagic { get; } = new() { Name = "Earth Magic", Id = 9 };
|
||||
public static Attribute FireMagic { get; } = new() { Name = "Fire Magic", Id = 10 };
|
||||
public static Attribute WaterMagic { get; } = new() { Name = "Water Magic", Id = 11 };
|
||||
public static Attribute EnergyStorage { get; } = new() { Name = "Energy Storage", Id = 12 };
|
||||
public static Attribute HealingPrayers { get; } = new() { Name = "Healing Prayers", Id = 13 };
|
||||
public static Attribute SmitingPrayers { get; } = new() { Name = "Smiting Prayers", Id = 14 };
|
||||
public static Attribute ProtectionPrayers { get; } = new() { Name = "Protection Prayers", Id = 15 };
|
||||
public static Attribute DivineFavor { get; } = new() { Name = "Divine Favor", Id = 16 };
|
||||
public static Attribute Strength { get; } = new() { Name = "Strength", Id = 17 };
|
||||
public static Attribute AxeMastery { get; } = new() { Name = "Axe Mastery", Id = 18 };
|
||||
public static Attribute HammerMastery { get; } = new() { Name = "Hammer Mastery", Id = 19 };
|
||||
public static Attribute Swordsmanship { get; } = new() { Name = "Swordsmanship", Id = 20};
|
||||
public static Attribute Tactics { get; } = new() { Name = "Tactics", Id = 21 };
|
||||
public static Attribute BeastMastery { get; } = new() { Name = "Beast Mastery", Id = 22 };
|
||||
public static Attribute Expertise { get; } = new() { Name = "Expertise", Id = 23 };
|
||||
public static Attribute WildernessSurvival { get; } = new() { Name = "Wilderness Survival", Id = 24 };
|
||||
public static Attribute Marksmanship { get; } = new() { Name = "Marksmanship", Id = 25 };
|
||||
public static Attribute DaggerMastery { get; } = new() { Name = "Dagger Mastery", Id = 29 };
|
||||
public static Attribute DeadlyArts { get; } = new() { Name = "Deadly Arts", Id = 30 };
|
||||
public static Attribute ShadowArts { get; } = new() { Name = "Shadow Arts", Id = 31 };
|
||||
public static Attribute Communing { get; } = new() { Name = "Communing", Id = 32 };
|
||||
public static Attribute RestorationMagic { get; } = new() { Name = "Restoration Magic", Id = 33 };
|
||||
public static Attribute ChannelingMagic { get; } = new() { Name = "Channeling Magic", Id = 34 };
|
||||
public static Attribute CriticalStrikes { get; } = new() { Name = "Critical Strikes", Id = 35 };
|
||||
public static Attribute SpawningPower { get; } = new() { Name = "Spawning Power", Id = 36 };
|
||||
public static Attribute SpearMastery { get; } = new() { Name = "Spear Mastery", Id = 37 };
|
||||
public static Attribute Command { get; } = new() { Name = "Command", Id = 38 };
|
||||
public static Attribute Motivation { get; } = new() { Name = "Motivation", Id = 39 };
|
||||
public static Attribute Leadership { get; } = new() { Name = "Leadership", Id = 40 };
|
||||
public static Attribute ScytheMastery { get; } = new() { Name = "Scythe Mastery", Id = 41 };
|
||||
public static Attribute WindPrayers { get; } = new() { Name = "Wind Prayers", Id = 42 };
|
||||
public static Attribute EarthPrayers { get; } = new() { Name = "Earth Prayers", Id = 43 };
|
||||
public static Attribute Mysticism { get; } = new() { Name = "Mysticism", Id = 44 };
|
||||
public static Attribute FastCasting { get; } = new() { Name = "Fast Casting", Id = 0, Profession = Profession.Mesmer };
|
||||
public static Attribute IllusionMagic { get; } = new() { Name = "Illusion Magic", Id = 1, Profession = Profession.Mesmer };
|
||||
public static Attribute DominationMagic { get; } = new() { Name = "Domination Magic", Id = 2, Profession = Profession.Mesmer };
|
||||
public static Attribute InspirationMagic { get; } = new() { Name = "Inspiration Magic", Id = 3, Profession = Profession.Mesmer };
|
||||
public static Attribute BloodMagic { get; } = new() { Name = "Blood Magic", Id = 4, Profession = Profession.Necromancer };
|
||||
public static Attribute DeathMagic { get; } = new() { Name = "Death Magic", Id = 5, Profession = Profession.Necromancer };
|
||||
public static Attribute SoulReaping { get; } = new() { Name = "Soul Reaping", Id = 6, Profession = Profession.Necromancer };
|
||||
public static Attribute Curses { get; } = new() { Name = "Curses", Id = 7, Profession = Profession.Necromancer };
|
||||
public static Attribute AirMagic { get; } = new() { Name = "Air Magic", Id = 8, Profession = Profession.Elementalist };
|
||||
public static Attribute EarthMagic { get; } = new() { Name = "Earth Magic", Id = 9, Profession = Profession.Elementalist };
|
||||
public static Attribute FireMagic { get; } = new() { Name = "Fire Magic", Id = 10, Profession = Profession.Elementalist };
|
||||
public static Attribute WaterMagic { get; } = new() { Name = "Water Magic", Id = 11, Profession = Profession.Elementalist };
|
||||
public static Attribute EnergyStorage { get; } = new() { Name = "Energy Storage", Id = 12, Profession = Profession.Elementalist };
|
||||
public static Attribute HealingPrayers { get; } = new() { Name = "Healing Prayers", Id = 13, Profession = Profession.Monk };
|
||||
public static Attribute SmitingPrayers { get; } = new() { Name = "Smiting Prayers", Id = 14, Profession = Profession.Monk };
|
||||
public static Attribute ProtectionPrayers { get; } = new() { Name = "Protection Prayers", Id = 15, Profession = Profession.Monk };
|
||||
public static Attribute DivineFavor { get; } = new() { Name = "Divine Favor", Id = 16, Profession = Profession.Monk };
|
||||
public static Attribute Strength { get; } = new() { Name = "Strength", Id = 17, Profession = Profession.Warrior };
|
||||
public static Attribute AxeMastery { get; } = new() { Name = "Axe Mastery", Id = 18, Profession = Profession.Warrior };
|
||||
public static Attribute HammerMastery { get; } = new() { Name = "Hammer Mastery", Id = 19, Profession = Profession.Warrior };
|
||||
public static Attribute Swordsmanship { get; } = new() { Name = "Swordsmanship", Id = 20, Profession = Profession.Warrior };
|
||||
public static Attribute Tactics { get; } = new() { Name = "Tactics", Id = 21, Profession = Profession.Warrior };
|
||||
public static Attribute BeastMastery { get; } = new() { Name = "Beast Mastery", Id = 22, Profession = Profession.Ranger };
|
||||
public static Attribute Expertise { get; } = new() { Name = "Expertise", Id = 23, Profession = Profession.Ranger };
|
||||
public static Attribute WildernessSurvival { get; } = new() { Name = "Wilderness Survival", Id = 24, Profession = Profession.Ranger };
|
||||
public static Attribute Marksmanship { get; } = new() { Name = "Marksmanship", Id = 25, Profession = Profession.Ranger };
|
||||
public static Attribute DaggerMastery { get; } = new() { Name = "Dagger Mastery", Id = 29, Profession = Profession.Assassin };
|
||||
public static Attribute DeadlyArts { get; } = new() { Name = "Deadly Arts", Id = 30, Profession = Profession.Assassin };
|
||||
public static Attribute ShadowArts { get; } = new() { Name = "Shadow Arts", Id = 31, Profession = Profession.Assassin };
|
||||
public static Attribute Communing { get; } = new() { Name = "Communing", Id = 32, Profession = Profession.Ritualist };
|
||||
public static Attribute RestorationMagic { get; } = new() { Name = "Restoration Magic", Id = 33, Profession = Profession.Ritualist };
|
||||
public static Attribute ChannelingMagic { get; } = new() { Name = "Channeling Magic", Id = 34, Profession = Profession.Ritualist };
|
||||
public static Attribute CriticalStrikes { get; } = new() { Name = "Critical Strikes", Id = 35, Profession = Profession.Assassin };
|
||||
public static Attribute SpawningPower { get; } = new() { Name = "Spawning Power", Id = 36, Profession = Profession.Ritualist };
|
||||
public static Attribute SpearMastery { get; } = new() { Name = "Spear Mastery", Id = 37, Profession = Profession.Paragon };
|
||||
public static Attribute Command { get; } = new() { Name = "Command", Id = 38, Profession = Profession.Paragon };
|
||||
public static Attribute Motivation { get; } = new() { Name = "Motivation", Id = 39, Profession = Profession.Paragon };
|
||||
public static Attribute Leadership { get; } = new() { Name = "Leadership", Id = 40, Profession = Profession.Paragon };
|
||||
public static Attribute ScytheMastery { get; } = new() { Name = "Scythe Mastery", Id = 41, Profession = Profession.Dervish };
|
||||
public static Attribute WindPrayers { get; } = new() { Name = "Wind Prayers", Id = 42, Profession = Profession.Dervish };
|
||||
public static Attribute EarthPrayers { get; } = new() { Name = "Earth Prayers", Id = 43, Profession = Profession.Dervish };
|
||||
public static Attribute Mysticism { get; } = new() { Name = "Mysticism", Id = 44, Profession = Profession.Dervish };
|
||||
public static IEnumerable<Attribute> Attributes { get; } = new List<Attribute>
|
||||
{
|
||||
FastCasting,
|
||||
@@ -136,6 +136,7 @@ public sealed class Attribute
|
||||
|
||||
public int Id { get; private set; }
|
||||
public string? Name { get; private set; }
|
||||
public Profession? Profession { get; private set; }
|
||||
private Attribute()
|
||||
{
|
||||
}
|
||||
|
||||
@@ -1,20 +0,0 @@
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct CharContext
|
||||
{
|
||||
public const int BaseOffset = 0x0074;
|
||||
|
||||
[FieldOffset(0x0000)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x28)]
|
||||
public readonly byte[] PlayerNameBytes;
|
||||
|
||||
[FieldOffset(0x01B0)]
|
||||
public readonly int Language;
|
||||
|
||||
[FieldOffset(0x0344)]
|
||||
[MarshalAs(UnmanagedType.ByValArray, SizeConst = 0x80)]
|
||||
public readonly byte[] PlayerEmailBytes;
|
||||
}
|
||||
@@ -0,0 +1,11 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public sealed class DebounceResponse
|
||||
{
|
||||
public MainPlayerInformation MainPlayer { get; init; } = default;
|
||||
public IEnumerable<WorldPlayerInformation> WorldPlayers { get; init; } = default!;
|
||||
public IEnumerable<PlayerInformation> Party { get; init; } = default!;
|
||||
public IEnumerable<LivingEntity> LivingEntities { get; init; } = default!;
|
||||
}
|
||||
@@ -1,14 +0,0 @@
|
||||
using System;
|
||||
using System.Runtime.InteropServices;
|
||||
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
[StructLayout(LayoutKind.Explicit)]
|
||||
public readonly struct GameContext
|
||||
{
|
||||
[FieldOffset(0x002C)]
|
||||
public readonly IntPtr WorldContext;
|
||||
|
||||
[FieldOffset(0x0044)]
|
||||
public readonly IntPtr CharContext;
|
||||
}
|
||||
@@ -0,0 +1,16 @@
|
||||
using Daybreak.Models.Guildwars;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace Daybreak.Models;
|
||||
|
||||
public readonly struct GameData
|
||||
{
|
||||
public bool Valid { get; init; }
|
||||
public MainPlayerInformation? MainPlayer { get; init; }
|
||||
public List<PlayerInformation>? Party { get; init; }
|
||||
public UserInformation? User { get; init; }
|
||||
public SessionInformation? Session { get; init; }
|
||||
public List<WorldPlayerInformation>? WorldPlayers { get; init; }
|
||||
public List<LivingEntity>? LivingEntities { get; init; }
|
||||
public List<MapIcon>? MapIcons { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,82 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public sealed class GuildwarsIcon
|
||||
{
|
||||
public static GuildwarsIcon ResurrectionShrine { get; } = new GuildwarsIcon { Id = 191474, Name = "Resurrection Shrine", WikiUrl = "https://wiki.guildwars.com/wiki/Resurrection_Shrine" };
|
||||
public static GuildwarsIcon Collector { get; } = new GuildwarsIcon { Id = 191482, Name = "Collector", WikiUrl = "https://wiki.guildwars.com/wiki/Collector" };
|
||||
public static GuildwarsIcon AreaMap { get; } = new GuildwarsIcon { Id = 302781, Name = "Area Map" };
|
||||
public static GuildwarsIcon StairsUp { get; } = new GuildwarsIcon { Id = 302783, Name = "Stairs Up" };
|
||||
public static GuildwarsIcon StairsDown { get; } = new GuildwarsIcon { Id = 302784, Name = "Stairs Down" };
|
||||
public static GuildwarsIcon Gate { get; } = new GuildwarsIcon { Id = 191464, Name = "Gate", WikiUrl = "" };
|
||||
public static GuildwarsIcon Star { get; } = new GuildwarsIcon { Id = 191472, Name = "Star", WikiUrl = "" };
|
||||
public static GuildwarsIcon DungeonBoss { get; } = new GuildwarsIcon { Id = 302779, Name = "Dungeon Boss" };
|
||||
public static GuildwarsIcon DungeonKey { get; } = new GuildwarsIcon { Id = 302777, Name = "Dungeon Key" };
|
||||
|
||||
public static List<GuildwarsIcon> Icons { get; } = new()
|
||||
{
|
||||
ResurrectionShrine,
|
||||
Collector,
|
||||
AreaMap,
|
||||
StairsUp,
|
||||
StairsDown,
|
||||
Gate,
|
||||
Star,
|
||||
DungeonBoss,
|
||||
DungeonKey
|
||||
};
|
||||
|
||||
public static bool TryParse(int id, out GuildwarsIcon icon)
|
||||
{
|
||||
icon = Icons.Where(icon => icon.Id == id).FirstOrDefault()!;
|
||||
if (icon is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static bool TryParse(string name, out GuildwarsIcon icon)
|
||||
{
|
||||
icon = Icons.Where(map => map.Name == name).FirstOrDefault()!;
|
||||
if (icon is null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public static GuildwarsIcon Parse(int id)
|
||||
{
|
||||
if (TryParse(id, out var icon) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find an icon with id {id}");
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
public static GuildwarsIcon Parse(string name)
|
||||
{
|
||||
if (TryParse(name, out var icon) is false)
|
||||
{
|
||||
throw new InvalidOperationException($"Could not find an icon with name {name}");
|
||||
}
|
||||
|
||||
return icon;
|
||||
}
|
||||
|
||||
public int Id { get; init; }
|
||||
public Affiliation Affiliation { get; init; }
|
||||
public string? Name { get; init; }
|
||||
public string? WikiUrl { get; init; }
|
||||
|
||||
private GuildwarsIcon()
|
||||
{
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,7 @@
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public interface IEntity : IPositionalEntity
|
||||
{
|
||||
int Id { get; }
|
||||
uint Timer { get; }
|
||||
}
|
||||
@@ -0,0 +1,5 @@
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
public interface IPositionalEntity
|
||||
{
|
||||
Position? Position { get; }
|
||||
}
|
||||
@@ -0,0 +1,24 @@
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public readonly struct LivingEntity : IEntity
|
||||
{
|
||||
public int Id { get; init; }
|
||||
|
||||
public uint Timer { get; init; }
|
||||
|
||||
public uint? ModelType { get; init; }
|
||||
|
||||
public Npc? NpcDefinition { get; init; }
|
||||
|
||||
public Position? Position { get; init; }
|
||||
|
||||
public Profession? PrimaryProfession { get; init; }
|
||||
|
||||
public Profession? SecondaryProfession { get; init; }
|
||||
|
||||
public int Level { get; init; }
|
||||
|
||||
public LivingEntityState State { get; init; }
|
||||
|
||||
public LivingEntityAllegiance Allegiance { get; init; }
|
||||
}
|
||||
@@ -0,0 +1,12 @@
|
||||
namespace Daybreak.Models.Guildwars;
|
||||
|
||||
public enum LivingEntityAllegiance
|
||||
{
|
||||
Unknown,
|
||||
AllyNonAttackable,
|
||||
Neutral,
|
||||
Enemy,
|
||||
SpiritOrPet,
|
||||
Minion,
|
||||
NpcOrMinipet
|
||||
}
|
||||
Some files were not shown because too many files have changed in this diff Show More
Reference in New Issue
Block a user