Merge pull request #178 from iAmAsval/dev

4.0.0.1
This commit is contained in:
Valentin 2021-05-25 19:12:23 +02:00 committed by GitHub
commit e5d7315d41
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
30 changed files with 264 additions and 64 deletions

@ -1 +1 @@
Subproject commit adb0529c1770d41c84fa73f47ad918cd7d5ece4c
Subproject commit 70d417009d729260486d905eb5d10f45c78cfec7

View File

@ -52,7 +52,7 @@ namespace FModel
Directory.CreateDirectory(Path.Combine(UserSettings.Default.OutputDirectory, ".data"));
Log.Logger = new LoggerConfiguration().WriteTo.Console(theme: AnsiConsoleTheme.Literate).WriteTo.File(
path: Path.Combine(UserSettings.Default.OutputDirectory, "Logs", $"FModel-Log-{DateTime.Now:yyyy-MM-dd}.txt"),
Path.Combine(UserSettings.Default.OutputDirectory, "Logs", $"FModel-Log-{DateTime.Now:yyyy-MM-dd}.txt"),
outputTemplate: "{Timestamp:yyyy-MM-dd HH:mm:ss} [FModel] [{Level:u3}] {Message:lj}{NewLine}{Exception}").CreateLogger();
Log.Information("Version {Version}", Constants.APP_VERSION);
@ -80,6 +80,7 @@ namespace FModel
Icon = MessageBoxImage.Error,
Buttons = new[]
{
MessageBoxButtons.Custom("Reset Settings", EErrorKind.ResetSettings),
MessageBoxButtons.Custom("Restart", EErrorKind.Restart),
MessageBoxButtons.Custom("OK", EErrorKind.Ignore)
},
@ -89,6 +90,9 @@ namespace FModel
MessageBox.Show(messageBox);
if (messageBox.Result == MessageBoxResult.Custom && (EErrorKind) messageBox.ButtonPressed.Id != EErrorKind.Ignore)
{
if ((EErrorKind) messageBox.ButtonPressed.Id == EErrorKind.ResetSettings)
UserSettings.Delete();
ApplicationService.ApplicationView.Restart();
}

View File

@ -17,12 +17,12 @@ namespace FModel.Creator.Bases.BB
public override void ParseForInfo()
{
if (Object.TryGetValue(out FSoftObjectPath iconTextureAssetData, "IconTextureAssetData"))
if (Object.TryGetValue(out FSoftObjectPath iconTextureAssetData, "IconTextureAssetData", "UnlockPortraitGuideImage"))
Preview = Utils.GetBitmap(iconTextureAssetData);
if (Object.TryGetValue(out FText displayName, "DisplayName"))
if (Object.TryGetValue(out FText displayName, "DisplayName", "RegionDisplayName", "ZoneName"))
DisplayName = displayName.Text;
if (Object.TryGetValue(out FText description, "Description"))
if (Object.TryGetValue(out FText description, "Description", "RegionShortName", "ZoneDescription"))
Description = description.Text;
}

View File

@ -46,18 +46,32 @@ namespace FModel.Creator.Bases.FN
Preview = Utils.GetBitmap(s);
else if (Object.TryGetValue(out FPackageIndex otherPreview, "SmallPreviewImage", "ToastIcon", "access_item"))
Preview = Utils.GetBitmap(otherPreview);
else if (Object.TryGetValue(out UMaterialInstanceConstant materialInstancePreview, "EventCalloutImage"))
Preview = Utils.GetBitmap(materialInstancePreview);
else if (Object.TryGetValue(out FStructFallback brush, "IconBrush") && brush.TryGetValue(out UTexture2D res, "ResourceObject"))
Preview = Utils.GetBitmap(res);
// text
if (Object.TryGetValue(out FText displayName, "DisplayName", "DefaultHeaderText", "UIDisplayName", "EntryName"))
if (Object.TryGetValue(out FText displayName, "DisplayName", "DefaultHeaderText", "UIDisplayName", "EntryName", "EventCalloutTitle"))
DisplayName = displayName.Text;
if (Object.TryGetValue(out FText description, "Description", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription", "EntryDescription"))
if (Object.TryGetValue(out FText description, "Description", "GeneralDescription", "DefaultBodyText", "UIDescription", "UIDisplayDescription", "EntryDescription", "EventCalloutDescription"))
Description = description.Text;
else if (Object.TryGetValue(out FText[] descriptions, "Description"))
Description = string.Join('\n', descriptions.Select(x => x.Text));
if (Object.TryGetValue(out FText shortDescription, "ShortDescription", "UIDisplaySubName"))
ShortDescription = shortDescription.Text;
else if (Object.ExportType.Equals("AthenaItemWrapDefinition", StringComparison.OrdinalIgnoreCase))
ShortDescription = "Wrap";
ShortDescription = Utils.GetLocalizedResource("Fort.Cosmetics", "ItemWrapShortDescription", "Wrap");
// Only works on non-cataba designs
if (Object.TryGetValue(out FStructFallback eventArrowColor, "EventArrowColor") &&
eventArrowColor.TryGetValue(out FLinearColor specifiedArrowColor, "SpecifiedColor") &&
Object.TryGetValue(out FStructFallback eventArrowShadowColor, "EventArrowShadowColor") &&
eventArrowShadowColor.TryGetValue(out FLinearColor specifiedShadowColor, "SpecifiedColor"))
{
Background = new[] {SKColor.Parse(specifiedArrowColor.Hex), SKColor.Parse(specifiedShadowColor.Hex)};
Border = new[] {SKColor.Parse(specifiedShadowColor.Hex), SKColor.Parse(specifiedArrowColor.Hex)};
}
Description = Utils.RemoveHtmlTags(Description);
}

View File

@ -17,11 +17,11 @@ namespace FModel.Creator.Bases.FN
public override void ParseForInfo()
{
if (!(Object is UMaterialInstanceConstant material)) return;
if (Object is not UMaterialInstanceConstant material) return;
foreach (var textureParameter in material.TextureParameterValues) // get texture from base material
{
if (!(textureParameter.ParameterValue is UTexture2D texture) || Preview != null) continue;
if (textureParameter.ParameterValue is not UTexture2D texture || Preview != null) continue;
switch (textureParameter.ParameterInfo.Name.Text)
{
case "SeriesTexture":

View File

@ -0,0 +1,50 @@
using CUE4Parse.UE4.Assets.Exports;
using CUE4Parse.UE4.Assets.Exports.Material;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.UE4.Objects.Core.i18N;
using SkiaSharp;
namespace FModel.Creator.Bases.SB
{
public class BaseGameModeInfo : UCreator
{
private SKBitmap _icon;
public BaseGameModeInfo(UObject uObject, EIconStyle style) : base(uObject, style)
{
Width = 738;
Height = 1024;
}
public override void ParseForInfo()
{
if (Object.TryGetValue(out FText displayName, "DisplayName"))
DisplayName = displayName.Text;
if (Object.TryGetValue(out FText description, "Description"))
Description = description.Text;
if (Object.TryGetValue(out UMaterialInstanceConstant portrait, "Portrait"))
Preview = Utils.GetBitmap(portrait);
if (Object.TryGetValue(out UTexture2D icon, "Icon"))
_icon = Utils.GetBitmap(icon).Resize(25);
}
public override SKImage Draw()
{
using var ret = new SKBitmap(Width, Height, SKColorType.Rgba8888, SKAlphaType.Premul);
using var c = new SKCanvas(ret);
DrawPreview(c);
DrawTextBackground(c);
DrawDisplayName(c);
DrawIcon(c);
return SKImage.FromBitmap(ret);
}
private void DrawIcon(SKCanvas c)
{
if (_icon == null) return;
c.DrawBitmap(_icon, new SKPoint(5, 5), ImagePaint);
}
}
}

View File

@ -24,8 +24,8 @@ namespace FModel.Creator.Bases.SB
{
Background = new[] {SKColor.Parse("FFFFFF"), SKColor.Parse("636363")};
Border = new[] {SKColor.Parse("D0D0D0"), SKColor.Parse("FFFFFF")};
Width = Object.ExportType.StartsWith("BP_Cosmetic_Card") ? 1536 : 512;
Height = Object.ExportType.StartsWith("BP_Cosmetic_Card") ? 450 : 512;
Width = Object.ExportType.StartsWith("GCosmeticCard") ? 1536 : 512;
Height = Object.ExportType.StartsWith("GCosmeticCard") ? 450 : 512;
}
public override void ParseForInfo()
@ -33,12 +33,12 @@ namespace FModel.Creator.Bases.SB
if (Object.TryGetValue(out FName rarity, "Rarity"))
GetRarity(rarity);
if (Object.TryGetValue(out FSoftObjectPath preview, "IconTexture"))
if (Object.TryGetValue(out FSoftObjectPath preview, "IconTexture", "OfferTexture", "PortraitTexture"))
Preview = Utils.GetBitmap(preview);
else if (Object.TryGetValue(out FPackageIndex icon, "IconTexture"))
else if (Object.TryGetValue(out FPackageIndex icon, "IconTexture", "OfferTexture", "PortraitTexture"))
Preview = Utils.GetBitmap(icon);
if (Object.TryGetValue(out FText displayName, "DisplayName", "Title"))
if (Object.TryGetValue(out FText displayName, "DisplayName", "Title", "Name"))
DisplayName = displayName.Text;
if (Object.TryGetValue(out FText description, "Description"))
Description = description.Text;

View File

@ -227,4 +227,4 @@ namespace FModel.Creator.Bases
}
}
}
}
}

View File

@ -73,6 +73,7 @@ namespace FModel.Creator
case "FortCurrencyItemDefinition":
case "FortResourceItemDefinition":
case "FortBackpackItemDefinition":
case "FortEventQuestMapDataAsset":
case "FortCodeTokenItemDefinition":
case "FortSchematicItemDefinition":
case "FortWorldMultiItemDefinition":
@ -163,21 +164,59 @@ namespace FModel.Creator
return true;
// Battle Breakers
case "WExpGenericAccountItemDefinition":
case "WExpGearAccountItemDefinition":
case "WExpHQWorkerLodgesDefinition":
case "WExpPersonalEventDefinition":
case "WExpUpgradePotionDefinition":
case "WExpAccountRewardDefinition":
case "WExpHQBlacksmithDefinition":
case "WExpHQSecretShopDefinition":
case "WExpHQMonsterPitDefinition":
case "WExpHQHeroTowerDefinition":
case "WExpVoucherItemDefinition":
case "WExpTreasureMapDefinition":
case "WExpHammerChestDefinition":
case "WExpHQWorkshopDefinition":
case "WExpUnlockableDefinition":
case "WExpHQSmelterDefinition":
case "WExpContainerDefinition":
case "WExpCharacterDefinition":
case "WExpHQMarketDefinition":
case "WExpGiftboxDefinition":
case "WExpStandInDefinition":
case "WExpRegionDefinition":
case "WExpHQMineDefinition":
case "WExpXpBookDefinition":
case "WExpTokenDefinition":
case "WExpItemDefinition":
case "WExpZoneDefinition":
creator = new BaseBreakersIcon(_object, EIconStyle.Default);
return true;
// Spellbreak
case "GQuest":
case "GAccolade":
case "GCosmeticCard":
case "GCosmeticSkin":
case "GTargetedTeleportActiveSkill":
case "GChronomasterV2ActiveSkill":
case "GShadowstepActiveSkill":
case "GGatewayActiveSkill":
case "GStealthActiveSkill":
case "GFeatherActiveSkill":
case "GCosmeticDropTrail":
case "GFlightActiveSkill":
case "GCosmeticRunTrail":
case "GCosmeticArtifact":
case "GCosmeticTriumph":
case "GWolfsbloodSkill":
case "GDashActiveSkill":
case "GCharacterPerk":
case "GCosmeticTitle":
case "GCosmeticBadge":
case "GRMTStoreOffer":
case "GCosmeticEmote":
case "GCosmeticTriumph":
case "GCosmeticRunTrail":
case "GCosmeticArtifact":
case "GCosmeticDropTrail":
case "GCosmeticCard":
case "GCosmeticSkin":
case "GStoreOffer":
case "GAccolade":
case "GRuneItem":
case "GQuest":
creator = new BaseSpellIcon(_object, EIconStyle.Default);
return true;
case "GLeagueTier":
@ -186,6 +225,10 @@ namespace FModel.Creator
case "GLeagueDivision":
creator = new BaseDivision(_object, EIconStyle.Default);
return true;
// TODO: Draw this properly
// case "GGameModeInfo":
// creator = new BaseGameModeInfo(_object, EIconStyle.Default);
// return true;
default:
creator = null;
return false;

View File

@ -41,6 +41,14 @@ namespace FModel.Creator
private const string _BURBANK_SMALL_BLACK = "burbanksmall-black";
private const string _BURBANK_SMALL_BOLD = "burbanksmall-bold";
// Spellbreak
private const string _SPELLBREAK_BASE_PATH = "/Game/UI/Fonts/";
private const string _MONTSERRAT_SEMIBOLD = "Montserrat-Semibold";
private const string _MONTSERRAT_SEMIBOLD_ITALIC = "Montserrat-SemiBoldItalic";
private const string _NANUM_GOTHIC = "NanumGothic";
private const string _QUADRAT_BOLD = "Quadrat_Bold";
private const string _SEGOE_BOLD_ITALIC = "Segoe_Bold_Italic";
// WorldExplorers
private const string _BATTLE_BREAKERS_BASE_PATH = "/Game/UMG/Fonts/Faces/";
private const string _HEMIHEAD426 = "HemiHead426";
@ -198,7 +206,23 @@ namespace FModel.Creator
case FGame.Dungeons:
break;
case FGame.g3:
{
if (viewModel.Provider.TrySaveAsset(_SPELLBREAK_BASE_PATH + _QUADRAT_BOLD + _EXT, out data))
{
var m = new MemoryStream(data) {Position = 0};
DisplayName = SKTypeface.FromStream(m);
}
else DisplayName = Default;
if (viewModel.Provider.TrySaveAsset(_SPELLBREAK_BASE_PATH + _MONTSERRAT_SEMIBOLD + _EXT, out data))
{
var m = new MemoryStream(data) {Position = 0};
Description = SKTypeface.FromStream(m);
}
else Description = Default;
break;
}
case FGame.StateOfDecay2:
break;
case FGame.Prospect:

View File

@ -107,12 +107,14 @@ namespace FModel.Creator
if (material == null) return null;
foreach (var textureParameter in material.TextureParameterValues)
{
if (!(textureParameter.ParameterValue is UTexture2D texture)) continue;
if (textureParameter.ParameterValue is not UTexture2D texture) continue;
switch (textureParameter.ParameterInfo.Name.Text)
{
case "MainTex":
case "TextureA":
case "TextureB":
case "OfferImage":
case "KeyArtTexture":
{
return GetBitmap(texture);
}

View File

@ -11,9 +11,9 @@ namespace FModel
public enum EErrorKind
{
Close,
Ignore,
Restart
Restart,
ResetSettings
}
public enum SettingsOut

View File

@ -6,8 +6,8 @@
<UseWPF>true</UseWPF>
<ApplicationIcon>FModel.ico</ApplicationIcon>
<Version>4.0.0</Version>
<AssemblyVersion>4.0.0.0</AssemblyVersion>
<FileVersion>4.0.0.0</FileVersion>
<AssemblyVersion>4.0.0.1</AssemblyVersion>
<FileVersion>4.0.0.1</FileVersion>
<IsPackable>false</IsPackable>
<IsPublishable>true</IsPublishable>
<RuntimeIdentifier>win-x64</RuntimeIdentifier>

View File

@ -66,7 +66,7 @@ namespace FModel.Framework
private void ObserveAll()
{
foreach (T item in Items)
foreach (var item in Items)
item.PropertyChanged += ChildPropertyChanged;
}

View File

@ -29,6 +29,11 @@ namespace FModel.Settings
File.WriteAllText(FilePath, JsonConvert.SerializeObject(Default, Formatting.Indented));
}
public static void Delete()
{
if (File.Exists(FilePath)) File.Delete(FilePath);
}
private string _outputDirectory;
public string OutputDirectory
{

View File

@ -1,5 +1,4 @@
using System.Collections.Generic;
using System.IO;
using System.IO;
using System.Threading;
using System.Threading.Tasks;
using FModel.ViewModels.ApiEndpoints.Models;
@ -16,7 +15,7 @@ namespace FModel.ViewModels.ApiEndpoints
public async Task<AesResponse> GetAesKeysAsync(CancellationToken token)
{
var request = new RestRequest("https://benbotfn.tk/api/v2/aes", Method.GET)
var request = new RestRequest("https://benbot.app/api/v2/aes", Method.GET)
{
OnBeforeDeserialization = resp => { resp.ContentType = "application/json; charset=utf-8"; }
};
@ -32,7 +31,7 @@ namespace FModel.ViewModels.ApiEndpoints
public async Task<MappingsResponse[]> GetMappingsAsync(CancellationToken token)
{
var request = new RestRequest("https://benbotfn.tk/api/v1/mappings", Method.GET)
var request = new RestRequest("https://benbot.app/api/v1/mappings", Method.GET)
{
OnBeforeDeserialization = resp => { resp.ContentType = "application/json; charset=utf-8"; }
};

View File

@ -53,17 +53,17 @@ namespace FModel.ViewModels.ApiEndpoints
return _infos ?? GetInfosAsync(token, updateMode).GetAwaiter().GetResult();
}
public async Task<Backup[]> GetBackupsAsync(CancellationToken token, FGame game)
public async Task<Backup[]> GetBackupsAsync(CancellationToken token, string gameName)
{
var request = new RestRequest($"https://api.fmodel.app/v1/backups/{game}", Method.GET);
var request = new RestRequest($"https://api.fmodel.app/v1/backups/{gameName}", Method.GET);
var response = await _client.ExecuteAsync<Backup[]>(request, token).ConfigureAwait(false);
Log.Information("[{Method}] [{Status}({StatusCode})] '{Resource}'", request.Method, response.StatusDescription, (int) response.StatusCode, request.Resource);
return response.Data;
}
public Backup[] GetBackups(CancellationToken token, FGame game)
public Backup[] GetBackups(CancellationToken token, string gameName)
{
return _backups ??= GetBackupsAsync(token, game).GetAwaiter().GetResult();
return _backups ??= GetBackupsAsync(token, gameName).GetAwaiter().GetResult();
}
public async Task<CommunityDesign> GetDesignAsync(string designName)

View File

@ -23,7 +23,7 @@ namespace FModel.ViewModels
private ThreadWorkerViewModel _threadWorkerView => ApplicationService.ThreadWorkerView;
private ApiEndpointViewModel _apiEndpointView => ApplicationService.ApiEndpointView;
private ApplicationViewModel _applicationView => ApplicationService.ApplicationView;
private readonly FGame _game;
private readonly string _gameName;
private Backup _selectedBackup;
public Backup SelectedBackup
@ -35,9 +35,9 @@ namespace FModel.ViewModels
public ObservableCollection<Backup> Backups { get; }
public ICollectionView BackupsView { get; }
public BackupManagerViewModel(FGame game)
public BackupManagerViewModel(string gameName)
{
_game = game;
_gameName = gameName;
Backups = new ObservableCollection<Backup>();
BackupsView = new ListCollectionView(Backups) {SortDescriptions = {new SortDescription("FileName", ListSortDirection.Ascending)}};
}
@ -46,7 +46,7 @@ namespace FModel.ViewModels
{
await _threadWorkerView.Begin(cancellationToken =>
{
var backups = _apiEndpointView.FModelApi.GetBackups(cancellationToken, _game);
var backups = _apiEndpointView.FModelApi.GetBackups(cancellationToken, _gameName);
if (backups == null) return;
Application.Current.Dispatcher.Invoke(() =>
@ -62,7 +62,7 @@ namespace FModel.ViewModels
await _threadWorkerView.Begin(_ =>
{
var backupFolder = Path.Combine(UserSettings.Default.OutputDirectory, "Backups");
var fileName = $"{_game}_{DateTime.Now:MMddyyyy}.fbkp";
var fileName = $"{_gameName}_{DateTime.Now:MMddyyyy}.fbkp";
var fullPath = Path.Combine(backupFolder, fileName);
using var fileStream = new FileStream(fullPath, FileMode.Create);

View File

@ -19,6 +19,7 @@ using CUE4Parse.UE4.Assets.Exports.Sound;
using CUE4Parse.UE4.Assets.Exports.Texture;
using CUE4Parse.UE4.Assets.Exports.Wwise;
using CUE4Parse.UE4.Localization;
using CUE4Parse.UE4.Oodle.Objects;
using CUE4Parse.UE4.Wwise;
using CUE4Parse_Conversion.Materials;
using CUE4Parse_Conversion.Sounds;
@ -460,6 +461,17 @@ namespace FModel.ViewModels
break;
}
case "udic":
{
TabControl.SelectedTab.Image = null;
if (Provider.TryCreateReader(fullPath, out var archive))
{
var header = new FDictionaryHeader(archive);
TabControl.SelectedTab.SetDocumentText(JsonConvert.SerializeObject(header, Formatting.Indented), bulkSave);
}
break;
}
case "png":
case "jpg":
{
@ -475,7 +487,6 @@ namespace FModel.ViewModels
FLogger.AppendWarning();
FLogger.AppendText($"Export '{fullPath.SubstringAfterLast('/')}' and change its extension if you want it to be an installable font file", Constants.WHITE, true);
break;
case "udic":
case "ushaderbytecode":
TabControl.SelectedTab.Image = null;
break;

View File

@ -12,7 +12,8 @@ namespace FModel.ViewModels.Commands
public override void Execute(CustomDirectoriesViewModel contextViewModel, object parameter)
{
if (parameter is not CustomDirectory customDir) return;
if (parameter is not CustomDirectory customDir)
customDir = new CustomDirectory();
Helper.OpenWindow<AdonisWindow>("Custom Directory", () =>
{

View File

@ -24,7 +24,7 @@ namespace FModel.ViewModels.Commands
Helper.OpenWindow<AdonisWindow>("AES Manager", () => new AesManager().Show());
break;
case "Directory_Backup":
Helper.OpenWindow<AdonisWindow>("Backup Manager", () => new BackupManager(contextViewModel.CUE4Parse.Game).Show());
Helper.OpenWindow<AdonisWindow>("Backup Manager", () => new BackupManager(contextViewModel.CUE4Parse.Provider.GameName).Show());
break;
case "Views_AudioPlayer":
Helper.OpenWindow<AdonisWindow>("Audio Player", () => new AudioPlayer().Show());

View File

@ -105,8 +105,7 @@ namespace FModel.ViewModels
Icon = new Image {Source = new BitmapImage(new Uri("/FModel;component/Resources/add_directory.png", UriKind.Relative))},
HorizontalContentAlignment = HorizontalAlignment.Left,
VerticalContentAlignment = VerticalAlignment.Center,
Command = AddEditDirectoryCommand,
CommandParameter = new CustomDirectory()
Command = AddEditDirectoryCommand
};
yield return new Separator();

View File

@ -28,6 +28,13 @@ namespace FModel.ViewModels
get => _showCities;
set => SetProperty(ref _showCities, value, nameof(ShowCities));
}
private bool _showLandmarks;
public bool ShowLandmarks
{
get => _showLandmarks;
set => SetProperty(ref _showLandmarks, value, nameof(ShowLandmarks));
}
private bool _showPatrolPaths;
public bool ShowPatrolPaths
@ -49,6 +56,13 @@ namespace FModel.ViewModels
get => _citiesImage;
set => SetProperty(ref _citiesImage, value);
}
private BitmapImage _landmarksImage;
public BitmapImage LandmarksImage
{
get => _landmarksImage;
set => SetProperty(ref _landmarksImage, value);
}
private BitmapImage _patrolPathImage;
public BitmapImage PatrolPathImage
@ -81,6 +95,8 @@ namespace FModel.ViewModels
c.DrawBitmap(_mapBitmap, 0, 0);
if (ShowCities)
c.DrawBitmap(_citiesBitmap, 0, 0);
if (ShowLandmarks)
c.DrawBitmap(_landmarksBitmap, 0, 0);
if (ShowPatrolPaths)
c.DrawBitmap(_patrolPathBitmap, 0, 0);
@ -98,7 +114,12 @@ namespace FModel.ViewModels
{
switch (propertyName)
{
case nameof(ShowCities) when _citiesBitmap == null && _mapBitmap != null:
case nameof(ShowCities) when _citiesBitmap == null && _landmarksBitmap == null && _mapBitmap != null:
{
await LoadCities();
break;
}
case nameof(ShowLandmarks) when _landmarksBitmap == null && _citiesBitmap == null && _mapBitmap != null:
{
await LoadCities();
break;
@ -127,6 +148,7 @@ namespace FModel.ViewModels
private const int WorldRadius = 135000;
private SKBitmap _mapBitmap;
private SKBitmap _citiesBitmap;
private SKBitmap _landmarksBitmap;
private SKBitmap _patrolPathBitmap;
private readonly SKBitmap _pinBitmap =
SKBitmap.Decode(Application.GetResourceStream(new Uri("pack://application:,,,/Resources/pin.png"))?.Stream);
@ -141,7 +163,7 @@ namespace FModel.ViewModels
private readonly SKPaint _pathPaint = new()
{
IsAntialias = true, FilterQuality = SKFilterQuality.High, IsStroke = true,
Style = SKPaintStyle.Stroke, StrokeWidth = 5, Color = SKColors.Red,
Style = SKPaintStyle.Stroke, StrokeWidth = 10, Color = SKColors.Red,
ImageFilter = SKImageFilter.CreateDropShadow(4, 4, 8, 8, SKColors.Black)
};
@ -173,27 +195,38 @@ namespace FModel.ViewModels
await _threadWorkerView.Begin(_ =>
{
_citiesBitmap = new SKBitmap(_mapBitmap.Width, _mapBitmap.Height, SKColorType.Rgba8888, SKAlphaType.Premul);
using var c = new SKCanvas(_citiesBitmap);
_landmarksBitmap = new SKBitmap(_mapBitmap.Width, _mapBitmap.Height, SKColorType.Rgba8888, SKAlphaType.Premul);
using var cities = new SKCanvas(_citiesBitmap);
using var landmarks = new SKCanvas(_landmarksBitmap);
if (Utils.TryLoadObject("FortniteGame/Content/Quests/QuestIndicatorData", out UObject indicatorData) &&
indicatorData.TryGetValue(out FStructFallback[] challengeMapPoiData, "ChallengeMapPoiData"))
{
foreach (var poiData in challengeMapPoiData)
{
if (!poiData.TryGetValue(out FSoftObjectPath discoveryQuest, "DiscoveryQuest") ||
!poiData.TryGetValue(out FText text, "Text") ||
!poiData.TryGetValue(out FVector worldLocation, "WorldLocation") ||
discoveryQuest.AssetPathName.Text.Contains("Landmarks")) continue;
!poiData.TryGetValue(out FText text, "Text") || string.IsNullOrEmpty(text.Text) ||
!poiData.TryGetValue(out FVector worldLocation, "WorldLocation")) continue;
var shaper = new CustomSKShaper(_imagePaint.Typeface);
var shapedText = shaper.Shape(text.Text, _imagePaint);
var vector = GetMapPosition(worldLocation);
c.DrawPoint(vector.X, vector.Y, _pathPaint);
c.DrawBitmap(_cityPinBitmap, vector.X - 50, vector.Y - 90, _imagePaint);
c.DrawShapedText(shaper, text.Text, vector.X - shapedText.Points[^1].X / 2, vector.Y - 12.5F, _imagePaint);
if (discoveryQuest.AssetPathName.Text.Contains("landmarks", StringComparison.OrdinalIgnoreCase))
{
landmarks.DrawPoint(vector.X, vector.Y, _pathPaint);
landmarks.DrawShapedText(shaper, text.Text, vector.X - shapedText.Points[^1].X / 2, vector.Y - 12.5F, _imagePaint);
}
else
{
cities.DrawPoint(vector.X, vector.Y, _pathPaint);
cities.DrawBitmap(_cityPinBitmap, vector.X - 50, vector.Y - 90, _imagePaint);
cities.DrawShapedText(shaper, text.Text, vector.X - shapedText.Points[^1].X / 2, vector.Y - 12.5F, _imagePaint);
}
}
}
CitiesImage = GetImageSource(_citiesBitmap);
LandmarksImage = GetImageSource(_landmarksBitmap);
});
}

View File

@ -41,7 +41,7 @@
<TextBlock Text="&#09;&#09;&#09;&#09;" FontSize="25" FontWeight="700" Height="2" Foreground="Transparent" HorizontalAlignment="Center" />
</StackPanel>
<TextBlock FontSize="12" Foreground="#727272" TextWrapping="Wrap" Margin="0 0 0 30"
Text="Maiky &#x2665;, HYPEX &#x2665;, VenomLeaks &#x2665;, JayKey &#x2665;, Fevers &#x2665;, Netu &#x2665;, TheGameVlog &#x2665;, Quentin &#x2665;, Mikey, kyle, Yanteh, Shiina, SexyNutella, Alexander, Jinx, Tector, s0ll, imatrix, LamZykoss, Frenzy Leaks, LlamaLeaks, XTigerHyperX, FunGames, WeLoveFortnite." />
Text="Maiky &#x2665;, HYPEX &#x2665;, VenomLeaks &#x2665;, JayKey &#x2665;, Fevers &#x2665;, Netu &#x2665;, TheGameVlog &#x2665;, Quentin &#x2665;, Laggy &#x2665;, s0ll &#x2665;, RazTracker, Mikey, kyle, Yanteh, Shiina, SexyNutella, Alexander, Jinx, Tector, imatrix, LamZykoss, Frenzy Leaks, LlamaLeaks, XTigerHyperX, FunGames, WeLoveFortnite." />
<StackPanel HorizontalAlignment="Center">
<TextBlock Text="Powered by" FontSize="15" FontWeight="700" Foreground="#9DA3DD" FontStretch="Expanded" />

View File

@ -7,9 +7,9 @@ namespace FModel.Views
{
private readonly BackupManagerViewModel _viewModel;
public BackupManager(FGame game)
public BackupManager(string gameName)
{
DataContext = _viewModel = new BackupManagerViewModel(game);
DataContext = _viewModel = new BackupManagerViewModel(gameName);
InitializeComponent();
}

View File

@ -41,7 +41,7 @@
</Grid.ColumnDefinitions>
<TextBlock Grid.Row="0" Grid.Column="0" Text="Header" VerticalAlignment="Center" />
<TextBox Grid.Row="0" Grid.Column="2" Text="{Binding Header, Mode=TwoWay}" />
<TextBox x:Name="WpfSuckMyDick" Grid.Row="0" Grid.Column="2" Text="{Binding Header, Mode=TwoWay}" />
<TextBlock Grid.Row="2" Grid.Column="0" Text="Directory" VerticalAlignment="Center" />
<TextBox Grid.Row="2" Grid.Column="2" Text="{Binding DirectoryPath, Mode=TwoWay}" />
</Grid>

View File

@ -9,6 +9,10 @@ namespace FModel.Views
{
DataContext = customDir;
InitializeComponent();
Activate();
WpfSuckMyDick.Focus();
WpfSuckMyDick.SelectAll();
}
private void OnClick(object sender, RoutedEventArgs e)

View File

@ -54,11 +54,11 @@
<TextBlock Grid.Row="0" Grid.Column="0" Text="Images Per Row" VerticalAlignment="Center" Margin="0 0 10 0" />
<Slider x:Name="SizeSlider" Grid.Row="0" Grid.Column="1" TickPlacement="None" AutoToolTipPlacement="BottomRight"
IsMoveToPointEnabled="True" Minimum="2" Maximum="20" TickFrequency="1" Thumb.DragCompleted="DrawPreview"/>
IsMoveToPointEnabled="True" Minimum="2" Maximum="20" TickFrequency="1" MouseUp="Click_DrawPreview" Thumb.DragCompleted="DrawPreview"/>
<TextBlock Grid.Row="2" Grid.Column="0" Text="Margin Between Images" VerticalAlignment="Center" Margin="0 0 10 0" />
<Slider Grid.Row="2" Grid.Column="1" Value="{Binding ImageMergerMargin, Source={x:Static local:Settings.UserSettings.Default}, Mode=TwoWay}"
TickPlacement="None" AutoToolTipPlacement="BottomRight" IsMoveToPointEnabled="True" Minimum="0" Maximum="50" TickFrequency="1"
Thumb.DragCompleted="DrawPreview" />
MouseUp="Click_DrawPreview" Thumb.DragCompleted="DrawPreview" />
</Grid>
<StackPanel Grid.Row="3" Orientation="Horizontal" HorizontalAlignment="Center">
<Button x:Name="AddButton" Content="Add" MinWidth="80" Padding="1,3,1,3" Click="OnImageAdd"/>

View File

@ -7,6 +7,7 @@ using System.Threading.Tasks;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media.Imaging;
using AdonisUI.Controls;
using FModel.Extensions;
@ -30,6 +31,11 @@ namespace FModel.Views
if (ImagePreview.Source != null)
await DrawPreview().ConfigureAwait(false);
}
private async void Click_DrawPreview(object sender, MouseButtonEventArgs e)
{
if (ImagePreview.Source != null)
await DrawPreview().ConfigureAwait(false);
}
private async Task DrawPreview()
{
@ -267,5 +273,6 @@ namespace FModel.Views
}
private void OnCopyImage(object sender, RoutedEventArgs e) => Clipboard.SetImage((BitmapSource) ImagePreview.Source);
}
}

View File

@ -29,6 +29,8 @@
<StackPanel Grid.Column="0" VerticalAlignment="Center" Margin="50">
<CheckBox Content="Show Cities" IsEnabled="{Binding IsReady}" IsChecked="{Binding MapViewer.ShowCities, Mode=TwoWay}"
Margin="0 0 0 10" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
<CheckBox Content="Show Landmarks" IsEnabled="{Binding IsReady}" IsChecked="{Binding MapViewer.ShowLandmarks, Mode=TwoWay}"
Margin="0 0 0 10" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
<CheckBox Content="Show Patrol Paths" IsEnabled="{Binding IsReady}" IsChecked="{Binding MapViewer.ShowPatrolPaths, Mode=TwoWay}"
Margin="0 0 0 10" Style="{DynamicResource {x:Static adonisUi:Styles.ToggleSwitch}}" />
<Button Content="Save Image" IsEnabled="{Binding IsReady}" Click="OnClick" />
@ -43,6 +45,8 @@
Visibility="{Binding IsReady, Converter={StaticResource BoolToVisibilityConverter}}" />
<Image UseLayoutRounding="True" Source="{Binding MapViewer.CitiesImage}" HorizontalAlignment="Right" VerticalAlignment="Center"
Visibility="{Binding MapViewer.ShowCities, Converter={StaticResource BoolToVisibilityConverter}}" />
<Image UseLayoutRounding="True" Source="{Binding MapViewer.LandmarksImage}" HorizontalAlignment="Right" VerticalAlignment="Center"
Visibility="{Binding MapViewer.ShowLandmarks, Converter={StaticResource BoolToVisibilityConverter}}" />
<Image UseLayoutRounding="True" Source="{Binding MapViewer.PatrolPathImage}" HorizontalAlignment="Right" VerticalAlignment="Center"
Visibility="{Binding MapViewer.ShowPatrolPaths, Converter={StaticResource BoolToVisibilityConverter}}" />
</Grid>